Using IndexedDB on Web Browser with Well Known Design Patterns — Only with Java by Mrs. Gwitany and Dr. Jackl

Dr. Lofi Dewanto
Oct 28, 2020 · 8 min read

In the article “Using IndexedDB in Web Browser — All in Java” Mrs. Gwitany and Dr. Jackl told us how we could use Java with Elemental2 to build a simple prototype based on WebAPIs for IndexedDB. This time they’ll show us how to build the already shown code to be testable and maintainable with all the Design Patterns we already know from our server-side experiences with Java.

In the server-side Java world we use following patterns all the time, so we want to use them in the Web browser apps as well:

  • Dependency Injection: we inject dependent object into a main object so that we could easily mock the injected object to be able to test the main object in a simple unit test. This is very useful especially if the dependent object uses e.g. database which can’t be booted very quickly.
  • Service and Repository Pattern: we build services and those services access data repositories to be able to call the database operations.
  • Rich Domain Model: we don’t want to build anemic domain model which contents only data, instead we also want to have some logics in it which is called rich domain model.
  • Builder Pattern: we build our object step-by-step using correct sequence of actions to be able to manage the creation of that object.
  • Mock Test: as mentioned before it is very important to be able to mock the behavior of dependent objects so that you don’t need to use real database for your unit test.

Lesson 1: to build maintainable and extensible Web browser app you need to use the known design patterns you already learned from the server-side Java.

To show how we could use the patterns Mrs. Gwitany has created a small example indexeddb-elemental2-dagger2-example based on IndexedDB which we have seen in the last article. Following libraries and frameworks are used in the example:

  • Dependency Injection: Dagger2 is designed to be flexible and uses fully static, compile-time generator for Java, Kotlin and Android.
  • Service and Repository Pattern: no special framework for Service and for Repository Pattern we use a generic Repository Pattern which is designed from this class: Repository.java
  • Rich Domain Model: no special framework, we just have a calculated property getCalculatedPriceWithAmount on our Product.java class
  • Builder Pattern: some possibilities are using Project Lombok, AutoValue and Immutables framework. This time we just build the Builder Pattern manually, but next time we would try to use Immutables for this pattern.
  • Mock Test: for this purpose we use JUnit 5 and Mockito (see pom.xml)

So, let’s deep dive into the example project!

Maven Project Structure

Before we are looking into the project in detail let’s see the structure of the Maven project on Eclipse STS 4 below.

The structure of the Maven project indexeddb-elemental2-dagger2-example

The project based on Maven and Mrs. Gwitany uses GWT Boot to simplify the pom.xml. GWT Boot Starter dependencies is basically a simple Starter dependencies collection for GWT just like Spring Boot Starter dependencies. The idea is taken from Spring Boot Starters. Here is the important part of the pom.xml which is based on GWT Boot Starter dependencies:

GWT Boot — pom.xml

Mrs. Gwitany uses two Starter dependencies:

  • gwt-boot-starter-dagger2: dependencies to Dagger2. All GWT dependencies are included as transitive dependencies.
  • gwt-boot-starter-elemento-core: dependencies to Elemento. This library makes working with Elemental2 a lot more easier.

Other dependencies like elemental2-indexeddb can be added independently. Also don’t forget to add the needed modules to the GWT Module Definition: module.gwt.xml.

GWT Boot uses GWT Maven Plugin and it should be configured like below:

GWT Boot — pom.xml Maven plugin

With this pom.xml you are ready to go. More information how to setup a Maven project with GWT Boot please see GWT Boot Samples.

Lesson 2: use GWT Boot Starter modules to make your pom.xml easier to manage. No need to copy&paste the dependencies with the matching versions.

Main Method == Entry Point

In GWT your app starts with the loading the code in Entry Point. So this is comparable with the Java Main Method. In this Entry Point we just simply initialize the Dagger2 framework with the root view / UI component ProductComposite.

Entry Point — Main Method

Which Entry Point should be called, has to be defined in the GWT Module Definition file: module.gwt.xml.

DI: Dagger2

If you know Spring Boot with its Dependency Injection (DI) annotations then it is easy to use Dagger2. This table below shows the similarity between Spring Boot and Dagger2 DI annotations.

Annotation Comparison Spring Framework / Boot vs. Dagger2

Following Modules and Components should be implemented by the user of Dagger2:

  • AppModule: in this module we don’t define any object creations because we use @Singleton on each class to be managed by Dagger2.
  • AppComponent: in this component we define the entry point for the class ProductComposite. The class ProductComposite is the root component view / UI of the Product domain.

After running mvn compile Dagger2 will generate some Java files to manage the dependency injection for you. Dagger2 uses code generator to create the factories and this is also the big difference with Spring Boot which mostly uses dynamic proxies and reflections. In the world of JavaScript we don’t have Reflection APIs, therefore code generator is here the solution.

Generated Files from Dagger2 in target/generated-sources

How could we use the DI framework afterwards? Just as simple as this example below. The class ProductService uses constructor injection to inject two other classes ProductIdbRepository and ProductRandomCreator which can be used later in the method createProduct.

Using Dagger2 to Inject Dependencies for ProductService

Service and Repository Pattern

For the Repository Pattern we could define a general interface like Repository.

Repository.java — General Interface for Repository

ProductIdbRepository implements the interface for the IndexedDB operations which consists the Product entity. The implementation of IndexedDB is quite straight forward. In the example Mrs. Gwitany only implemented the persist method. The rest is open for you to implement. ProductRandomCreator is the class where we create some products since we don’t have any possibility to create products from the user interface.

Both classes will be injected into ProductService in its constructor like we have seen above.

Following class diagram shows us the structure of the Product domain model.

Product Service, Repository, RandomCreator and Product Entity
  • ProductService <<Service>>: serves to create products and will be used directly from the user interface ProductComposite.
  • ProductRandomCreator <<Service>>: creates some products randomly.
  • ProductIdbRepository <<Repository>>: offers CRUD (Create Read Update Delete) operations for IndexedDB Web browser database.
  • Product <<Entity>>: is the entity which should be created and managed by the repository.

Entity: Rich vs. Anemic Domain Model and Builder Pattern

As we have seen above the Product is the entity in the domain model. Mrs. Gwitany made the the Product entity a rich one since it also calculates the price with the given amount in the method called getCalculatedPriceWithAmount. She also creates a Builder Pattern to be able to instantiate the product nicely. So here is how we could create the Product entity with the Builder Pattern:

Product product = new Product.Builder(key, 
"Lofi " + key).setType(type).setAmount(10)
.setPrice(price)
.build();

Following is the code of the Product entity in which the Builder pattern is also implemented.

Product Entity as Rich Domain Model

Lesson 3: Dependency Injection, Service, Repository, Entity and Builder can be used also on Web browser with Java and GWT / J2CL. Please remember, we have Design Patterns because we’ve learned that they help us to structure our app so that it will be better maintainable and extensible.

User Interface Composite

After we have the domain model we just need the view / UI. For this purpose Mrs. Gwitany created the class ProductComposite. It needs the the ProductService, so it is injected into the ProductComposite. The renderView method build the HTML DOM tree with the help of Elemento library. The UI is very simple so that we can concentrate on the basics. The event handler onProductCreated will be call every time when the user clicks the button. It has some “presentation logic” which controls the creation of input field or just a simple logging on console.

ProductComposite as a Simple UI

Mrs. Gwitany and Dr. Jackl will handle the UI development in detail later in another article, because GWT / J2CL offers a lot of UI frameworks, in amount almost comparable with the JavaScript and old Java world.

Mock Test

Last but not least, actually this a very important part which Mrs. Gwitany and Dr. Jackl told me, within Java you can use your well known test frameworks like JUnit and Mockito. In these two unit test classes you can find some interesting tests:

ProductCompositeTest — Unit Test for ProductComposite View / UI

The Result

How does the Web app look like? Just go to the directory of the Maven project indexeddb-elemental2-dagger2-example and run following command:

mvn gwt:generate-module gwt:devmode

You’ll see following Swing app and you can copy&paste the Web browser address or just push the button to launch the default browser on your system.

GWT Development Mode with Jetty Web Server

Following Web app can be tested afterwards. You can also take a look at the IndexDB viewer on the Application tab of Google Chrome.

IndexedDB Example — Logging
IndexedDB Example — IndexedDB Content

Note 1: the Web browser app tested only with Chrome and Firefox. In Firefox you could not use private mode to run IndexedDB.
Note 2: the app works with Java 8 or Java 11 since GWT 2.9 supports Java 11 but don’t forget that the result of your app is always a JavaScript app.

Epilog

In this article Mrs. Gwitany and Dr. Jackl have shown us how to build a testable and maintainable Web browser app based on Java. You can use all the design patterns you have learned from the server-side Java in your client-side Web browser Java app. In the era of Cloud Computing it is worth it to be brave to move your business logics from server-side to client-side. With the load on the client-side you will save computing costs from your cloud vendor. PWA (Progressive Web Apps) and Web browser apps with Java are simple and thanks to GWT and J2CL (Java2JavaScript transpiler) manageable and extensible just like their counterpart on the server-side. They are ready for production today.

In the next article Mrs. Gwitany and Dr. Jackl will show us how to use some pretty UI frameworks with all those fancy design like Material Design and Bootstrap. Also how to access the server-side Spring Boot REST APIs to be able to show how to reuse codes for client and server. Until then enjoy reading and don’t forget to play with GWT and J2CL!

Star Gazers

“If you want to master something, teach it.”

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store