В статье Использование IndexedDB в веб-браузере - все на Java г-жа Гвитани и доктор Джекл рассказали нам, как мы можем использовать Java с Elemental2 для создания простого прототип на основе WebAPI для IndexedDB. На этот раз они покажут нам, как создать уже показанный код, чтобы его можно было тестировать и поддерживать со всеми шаблонами дизайна, которые мы уже знаем из наших серверный опыт работы с Java.

В мире серверной Java мы все время используем следующие шаблоны, поэтому мы хотим использовать их и в приложениях веб-браузера:

  • Внедрение зависимостей: мы внедряем зависимый объект в основной объект, чтобы мы могли легко смоделировать внедренный объект, чтобы иметь возможность протестировать основной объект в простом модульном тесте. Это очень полезно, особенно если зависимый объект использует, например, база данных, которая не может быть загружена очень быстро.
  • Шаблон службы и репозитория: мы создаем службы, и эти службы обращаются к репозиториям данных, чтобы иметь возможность вызывать операции с базой данных.
  • Расширенная модель домена: мы не хотим строить анемичную модель предметной области, содержащую только данные, вместо этого мы также хотим иметь некоторую логику в ней, которая называется моделью богатой предметной области.
  • Шаблон Строителя: мы строим наш объект шаг за шагом, используя правильную последовательность действий, чтобы иметь возможность управлять созданием этого объекта.
  • Мок-тест: как упоминалось ранее, очень важно иметь возможность имитировать поведение зависимых объектов, чтобы вам не нужно было использовать настоящую базу данных для своего модульного теста.

Урок 1: чтобы создать поддерживаемое и расширяемое приложение веб-браузера, вам необходимо использовать известные шаблоны проектирования, которые вы уже узнали из серверной Java.

Чтобы показать, как мы можем использовать шаблоны, миссис Гвитани создала небольшой пример indexeddb-element2-dagger2-example на основе IndexedDB, который мы видели в прошлой статье. . В примере используются следующие библиотеки и фреймворки:

  • Внедрение зависимостей: Dagger2 разработан, чтобы быть гибким и использует полностью статический генератор времени компиляции для Java, Kotlin и Android.
  • Шаблон службы и репозитория: нет специальной структуры для службы, а для шаблона репозитория мы используем общий шаблон репозитория, который разработан на основе этого класса: Repository.java
  • Модель Rich Domain: никакой специальной структуры, у нас просто есть вычисляемое свойство getCalculatedPriceWithAmount в нашем классе Product.java
  • Builder Pattern: некоторые возможности используются с использованием фреймворков Project Lombok, AutoValue и Immutables. На этот раз мы просто создаем шаблон Builder вручную, но в следующий раз мы попробуем использовать неизменяемые элементы для этого шаблона.
  • Mock Test: для этого мы используем JUnit 5 и Mockito (см. pom.xml)

Итак, давайте углубимся в пример проекта!

Структура проекта Maven

Прежде чем мы подробно рассмотрим проект, давайте посмотрим на структуру проекта Maven на Eclipse STS 4 ниже.

В проекте, основанном на Maven и Mrs. Gwitany, используется GWT Boot для упрощения pom.xml. Зависимости GWT Boot Starter - это, по сути, простая коллекция зависимостей Starter для GWT, как и зависимости Spring Boot Starter. Идея взята из Spring Boot Starters. Вот важная часть pom.xml, которая основана на зависимостях GWT Boot Starter:

Миссис Гвитани использует две зависимости Starter:

  • gwt-boot-starter-dagger2: зависимости от Dagger2. Все зависимости GWT включены как транзитивные зависимости.
  • gwt-boot-starter-elemento-core: зависимости от Elemento. Эта библиотека значительно упрощает работу с Elemental2.

Другие зависимости, такие как element2-indexeddb, могут быть добавлены независимо. Также не забудьте добавить необходимые модули в определение модуля GWT: module.gwt.xml.

GWT Boot использует GWT Maven Plugin, и его нужно настроить, как показано ниже:

С этим pom.xml вы готовы к работе. Дополнительную информацию о том, как настроить проект Maven с загрузкой GWT, см. В разделе Примеры загрузки GWT.

Урок 2: используйте модули GWT Boot Starter, чтобы упростить управление вашим pom.xml. Нет необходимости копировать и вставлять зависимости с соответствующими версиями.

Основной метод == Точка входа

В GWT ваше приложение начинается с загрузки кода в Entry Point. Таким образом, это сопоставимо с основным методом Java. В этой точке входа мы просто инициализируем структуру Dagger2 с помощью корневого представления / компонента пользовательского интерфейса ProductComposite.

Какая точка входа должна быть вызвана, должна быть определена в файле определения модуля GWT: module.gwt.xml.

DI: Dagger2

Если вы знаете Spring Boot с его аннотациями Dependency Injection (DI), то использовать Dagger2 несложно. В приведенной ниже таблице показано сходство между аннотациями Spring Boot и Dagger2 DI.

Следующие модули и компоненты должны быть реализованы пользователем Dagger2:

  • AppModule: в этом модуле мы не определяем создание каких-либо объектов, потому что мы используем @Singleton для каждого класса, которым управляет Dagger2.
  • AppComponent: в этом компоненте мы определяем точку входа для класса ProductComposite. Класс ProductComposite является представлением корневого компонента / пользовательским интерфейсом домена Product.

После запуска mvn compile Dagger2 сгенерирует несколько файлов Java для управления внедрением зависимостей за вас. Dagger2 использует генератор кода для создания фабрик, и это также большая разница с Spring Boot, который в основном использует динамические прокси и отражения. В мире JavaScript у нас нет Reflection API, поэтому генератор кода - вот решение.

Как мы могли бы потом использовать структуру DI? Так же просто, как этот пример ниже. Класс ProductService использует внедрение конструктора для внедрения двух других классов ProductIdbRepository и ProductRandomCreator, которые могут будет использоваться позже в методе createProduct.

Шаблон службы и репозитория

Для шаблона репозитория мы могли бы определить общий интерфейс, например Репозиторий.

ProductIdbRepository реализует интерфейс для операций IndexedDB, который состоит из сущности Product. Реализация IndexedDB довольно проста. В этом примере миссис Гвитани реализовала только метод persist. Остальное вы можете реализовать. ProductRandomCreator - это класс, в котором мы создаем некоторые продукты, поскольку у нас нет возможности создавать продукты из пользовательского интерфейса.

Оба класса будут внедрены в ProductService в его конструкторе, как мы видели выше.

На следующей диаграмме классов показана структура модели предметной области.

  • ProductService ‹‹Service››: служит для создания продуктов и будет использоваться непосредственно из пользовательского интерфейса ProductComposite.
  • ProductRandomCreator ‹‹Service››: создает некоторые продукты случайным образом.
  • ProductIdbRepository ‹‹Repository››: предлагает операции CRUD (создание, чтение, обновление, удаление) для базы данных веб-браузера IndexedDB.
  • Продукт ‹‹Entity››: это объект, который должен создаваться и управляться репозиторием.

Сущность: богатая и анемичная модель домена и шаблон построителя

Как мы видели выше, Продукт - это сущность в модели предметной области. Миссис Гвитани сделала сущность Product многофункциональной, поскольку она также вычисляет цену с заданной суммой в методе под названием getCalculatedPriceWithAmount . Она также создает Builder Pattern, чтобы иметь возможность красиво создать экземпляр продукта. Итак, вот как мы могли бы создать сущность Product с помощью паттерна Builder:

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

Ниже приведен код сущности Продукт, в которой также реализован шаблон Builder.

Урок 3: Внедрение зависимостей, Сервис, Репозиторий, Сущность и Строитель можно также использовать в веб-браузере с Java и GWT / J2CL. Помните, что у нас есть шаблоны дизайна, потому что мы узнали, что они помогают нам структурировать наше приложение, чтобы его было легче поддерживать и расширять.

Пользовательский интерфейс Composite

После того, как у нас есть модель предметной области, нам просто понадобится представление / пользовательский интерфейс. Для этого миссис Гвитани создала класс ProductComposite. Ему требуется ProductService, поэтому он вводится в ProductComposite. Метод renderView строит дерево HTML DOM с помощью библиотеки Elemento. Пользовательский интерфейс очень прост, поэтому мы можем сосредоточиться на основах. Обработчик события onProductCreated будет вызываться каждый раз, когда пользователь нажимает кнопку. У него есть некоторая логика представления, которая управляет созданием поля ввода или простым входом в консоль.

Миссис Гвитани и доктор Джекл подробно займутся разработкой пользовательского интерфейса позже в другой статье, потому что GWT / J2CL предлагает множество инфраструктур пользовательского интерфейса, по количеству почти сопоставимых с JavaScript и старым миром Java.

Пробный тест

И последнее, но не менее важное: на самом деле это очень важная часть, о которой мне рассказали миссис Гвитани и доктор Джекл. В Java вы можете использовать свои хорошо известные тестовые среды, такие как JUnit и Mockito. В этих двух классах модульных тестов вы можете найти несколько интересных тестов:

Результат

Как выглядит веб-приложение? Просто перейдите в каталог проекта Maven indexeddb-element2-dagger2-example и выполните следующую команду:

mvn gwt:generate-module gwt:devmode

Вы увидите следующее приложение Swing, и вы можете скопировать и вставить адрес веб-браузера или просто нажать кнопку, чтобы запустить браузер по умолчанию в вашей системе.

Следующее веб-приложение может быть протестировано впоследствии. Вы также можете взглянуть на средство просмотра IndexDB на вкладке Приложение в Google Chrome.

Примечание 1. приложение для веб-браузера протестировано только с Chrome и Firefox. В Firefox вы не могли использовать частный режим для запуска IndexedDB.
Примечание 2: приложение работает с Java 8 или Java 11, поскольку GWT 2.9 поддерживает Java 11, но не забывайте, что результатом вашего приложения всегда будет JavaScript приложение.

Эпилог

В этой статье миссис Гвитани и доктор Джекл показали нам, как создать тестируемое и поддерживаемое приложение веб-браузера на основе Java . Вы можете использовать все шаблоны проектирования, которые вы узнали из серверной Java, в своем клиентском веб-браузере в Java-приложении. В эпоху облачных вычислений это того стоит проявить смелость, чтобы перенести логику вашего бизнеса с серверной на клиентскую. Благодаря загрузке на стороне клиента вы сэкономите на вычислительных затратах вашего поставщика облачных вычислений. PWA (прогрессивные веб-приложения) и приложения для веб-браузера с Java просты и благодаря GWT и J2CL (транспилятору Java2JavaScript) управляемы и расширяемы, как и их аналог на стороне сервера. Сегодня они готовы к производству.

В следующей статье миссис Гвитани и доктор Джекл покажут нам, как использовать некоторые красивые фреймворки пользовательского интерфейса со всеми этими причудливыми дизайнами, такими как Material Design и Bootstrap . Также как получить доступ к API REST Spring Boot на стороне сервера, чтобы показать, как повторно использовать коды для клиента и сервера. А пока наслаждайтесь чтением и не забудьте поиграть с GWT и J2CL!

Все примеры можно найти по адресу:
https://github.com/lofidewanto/jsinterop-simple-jsframework-example/tree/master/indexeddb-elemental2-dagger2-example

Padlet для современного программирования GWT / J2CL:
https://bit.ly/GWTIntroPadlet