Эта история не о Java Applet или Java WebStart, это история на чистом JavaScript, представленная г-жой. Гвитани и Др. Jackl, широко известный как GWT и J2CL.

В мире веб-браузеров JavaScript является королем, поэтому все веб-API основаны на JavaScript. Сеть разработчиков Mozilla (MDN) является источником истины для веб-API. Выглядит потрясающе и прекрасно все объясняет на примерах. Поэтому, если вы хотите создавать веб-приложения, вам обязательно понадобится документация MDN.

Урок 1: считайте Сеть разработчиков Mozilla (MDN) и Веб-API своими лучшими друзьями.

В этой истории я покажу вам, как мы можем использовать веб-API из транспилятора GWT / J2CL. Для этого я выбрал IndexedDB API. В документации по MDN приведено определение IndexedDB API:

IndexedDB - это низкоуровневый API для хранения на стороне клиента значительных объемов структурированных данных, включая файлы / большие двоичные объекты. Этот API использует индексы для обеспечения высокопроизводительного поиска этих данных. Хотя веб-хранилище полезно для хранения меньших объемов данных, оно менее полезно для хранения больших объемов структурированных данных. IndexedDB предлагает решение.

В IndexedDB следует реализовать следующую простую логику:

  1. Веб-приложение создаст базу данных IndexedDB, когда пользователь впервые откроет веб-приложение. Если база данных / хранилище данных недоступны, он создаст новую базу данных и вставит некоторые значения.
  2. Если мы откроем веб-приложение в следующий раз, а база данных уже существует, веб-приложение просто вставит некоторые значения. Это все.

Как мы узнали из статьи « Научитесь использовать везде: использование JavaScript API в Java для веб-браузера », нам нужны классы JsInterop, которые соединяют доступ с Java к IndexedDB API (вариант использования 2). Конечно, мы можем сами создавать классы JsInterop вручную, но в этом нет необходимости. Библиотека Elemental2 от Google здесь, чтобы помочь. Библиотека Elemental2 - это тонкий мост, который содержит коллекцию классов JsInterop для доступа к доступным веб-API. Мы можем использовать эти классы непосредственно в нашем веб-приложении Java. Итак, каковы шаги по использованию библиотеки Elemental2? Держи…

Первый шаг: вам нужно добавить необходимые зависимости Maven, в данном случае библиотеку IndexedDB Elemental2, в ваш pom.xml.

<dependency>
    <groupId>com.google.elemental2</groupId>
    <artifactId>elemental2-indexeddb</artifactId
    <version>1.1.0</version>
</dependency>

Урок 2: прежде чем создавать классы JsInterop вручную, взгляните на библиотеку Elemental2, для большинства веб-API уже созданы классы JsInterop.

Второй шаг: Документация библиотеки Elemental2 для IndexedDB очень редка, поэтому вам необходимо использовать документацию MDN для IndexedDB. Документация отличная, и в ней есть несколько примеров. По теме IndexDB также есть несколько хороших документов и статей:

С приведенными выше документами и статьями вы готовы реализовать функции IndexedDB с помощью Elemental2.

Урок 3. Сначала найдите статьи и документацию по этой теме. Большинство статей посвящено JavaScript, но не паникуйте, вы поймете, что вам нужно делать на Java, поскольку он очень похож. Помните: модель программирования в JavaScript в основном основана на событиях, обещаниях, асинхронной модели программирования. API-интерфейсы Elemental2 будут очень похожи на API-интерфейсы JavaScript.

Третий шаг. Первая проблема, с которой я столкнулся, заключалась в том, чтобы проверить, доступна ли IndexedDB в веб-браузере с помощью следующего кода JavaScript:

if ('indexedDB' in window) {
    console.log('This browser doesn\'t support IndexedDB');
    return;
}

После запроса в GWT Gitter Chat (это определенно место, где можно попросить темы GWT / J2CL / Elemental2) я получил следующие решения на Java:

// General solution with JsInterop
Window window = DomGlobal.window;
if (Js.asPropertyMap(window).has("indexedDB") {
    logger.info("IndexedDB found");
}
... or ...
// Use Elemental2 specific global variable
IDBFactory indexedDB = IndexedDbGlobal.indexedDB;
if (indexedDB != null) {
    logger.info("IndexedDB found");
}

После получения решения для первого препятствия остальное легко, поскольку все работает так же, как и в решении JavaScript. Очень интересна модель асинхронного программирования в JavaScript, которая необычна для разработчиков Java. Вот код для проверки базы данных / хранилища данных, когда его еще нет, поэтому вам нужно сначала создать его.

JavaScript:

openDBRequest.onupgradeneeded = function(event) {
    // Create object store from db or event.target.result
};

Java с Lambda:

openDBRequest.onupgradeneeded = event -> {
    // Create object store from db or event.target.result
    return null;
};

Как видите, код очень похож. Возвращение null в Java нехорошо, но необходимо, потому что библиотеки Elemental2 генерируются из Closure libraries (подробнее о генерации позже).

С помощью этих трех шагов вы сможете завершить реализацию простой логики для IndexedDB, описанной выше. Полный класс Java реализован в файле IndexedDbElemental2.java. Теперь мы можем запустить веб-приложение. Просто перейдите в каталог проекта Maven indexeddb-element2-example и выполните следующую команду:

mvn gwt:generate-module gwt:devmode

Мы можем отладить код Java, изменить его и перезагрузить. Все будет автоматически перенесено и перезагружено. Отладка работает очень хорошо, добавляя точку останова на исходных файлах в Google Chrome.

Чтобы увидеть результат, вам просто нужно перейти на панель Приложение в Chrome и найти слева область Хранилище. В меню IndexedDB вы найдете нашу сгенерированную базу данных и хранилище данных. Нажав кнопку Обновить в таблице, вы можете увидеть содержимое хранилища данных. В этом примере мы сохраняем объект Продукт при каждой перезагрузке index.html. При каждой перезагрузке мы создаем объект IndexedDbElemental2 и открываем базу данных. Вот класс EntryPoint AppEntryPoint:

package com.github.lofi.client; 
... 
public class AppEntryPoint implements EntryPoint {  
    @Override 
    public void onModuleLoad() {  
        new IndexedDbElemental2().openDb(); 
    } 
}

Вот и все! Вы можете проверить весь файл IndexedDbElemental2, и вы увидите, что форма очень похожа на пример JavaScript, что позволяет нам очень легко реализовать, если мы можем найти несколько хороших статей по JavaScript или примеров по этой теме.

В заключение этой истории я хочу показать вам предысторию создания библиотек Elemental2. Библиотеки Elemental2 в основном генерируются с помощью JsInterop Generator. Вот описание проекта JsInterop Generator:

Генератор jsinterop - это программа Java, которая принимает закрывающие внешние файлы в качестве входных данных и генерирует классы Java, аннотированные аннотациями JsInterop. Этот проект используется для сборки Elemental2 [библиотека]. Любое другое использование является экспериментальным. Вы можете использовать его для создания API-интерфейсов Java для других библиотек JavaScript, но мы не предоставляем официальной поддержки. Тем не менее, не стесняйтесь открывать проблемы с помощью трекера проблем GitHub.

Важно знать, что мы действительно можем получить файлы JsInterop с помощью автоматической генерации, поскольку они являются всего лишь контрактами между миром Java и JavaScript.

Между тем существует еще один генератор Webtack Generator, который генерирует файлы JsInterop с большей ориентацией на Java и более приятными документами Javadoc. Вы помните return null выше? Здесь, на этой странице, вы можете увидеть различия файлов, сгенерированных JsInterop Generator (Elemental2) и Webtack Generator (также известный как Элементаль3). Для сравнения я создал тот же проект, но с использованием Webtack JsInterop для IndexedDB: indexeddb-element3-example. Проверьте это и взгляните на API IndexedDB (IndexedDbElemental3), он выглядит более чистым и более ориентированным на Java.

Урок 4: попробуйте сгенерировать нужные вам файлы JsInterop, проверьте, работает ли кто-нибудь на миссис Гвитани, а доктор Джекл уже сделал это, или используйте JsInterop Generator / Webtack Generator для их автоматической генерации. Помните: файлы JsInterop - это только договор между миром Java и JavaScript.

Миссис Гвитани и доктор Джекл не одни со своими транспиляторными инструментами. Транспилятор TypeScript и Транспилятор Kotlin в JavaScript очень похожи. Основное отличие заключается в том, что если вы используете Spring Boot (Java) на стороне сервера, у вас тот же язык, инструменты и пуленепробиваемый механизм также на стороне клиента в браузере, так что вы можете научиться один раз использовать везде!

На приведенной ниже схеме показан способ доступа к API веб-браузера из Java.

Послесловие: Привет от г-жи Гвитани и Др. Джекл и Надеюсь, вам понравятся четыре урока, упомянутые в этой истории. В следующий раз они покажут нам, как сделать этот пример IndexedDB более поддерживаемым и тестируемым с помощью внедрения зависимостей, Service / Шаблон репозитория и Mock-объект -, которые представляют собой пуленепробиваемый механизм при разработке приложений Java для разработчиков Java и от них.

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

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