Simple Example for Accessing JavaScript Frameworks from Java GWT with Elemental2 and very early version of Akasha
This example uses GWT Boot as Starter Parent: https://github.com/gwtboot/gwt-boot-samples
Following articles are available as guidance:
- Take a look at this article to see the whole story: http://bit.ly/GWTJ2CLIndexedDB
- Also this article for the Design Patterns in Java: https://bit.ly/GwtIndexedDBDesignPatterns
We have three examples to use IndexedDB APIs on the web browser:
1. indexeddb-elemental2-example: this example uses Elemental2 lib.
2. indexeddb-elemental3-example: this example uses the Akasha lib.
3. indexeddb-elemental2-dagger2-example: this example shows how to use well known Design Patterns in GWT applications with IndexedDB.
To build the example:
mvn clean package
To run the example:
-
First: go to the project you want to run: indexeddb-elemental2-example or indexeddb-elemental3-example or indexeddb-elemental2-dagger2-example
-
In the directory run the GWT Dev Mode:
mvn gwt:generate-module gwt:devmode
- Second: open your browser and go to following address:
http://127.0.0.1:8888/calculator/
- GWT Dev Mode supports automatic transpiling. You just need to update your Java code in your IDE and reload your web browser. Your Java code will be automatically transpiled and your webapp stays uptodate without restarting the web server. If you change the index.html you need to push the restart button on the Swing GUI.
-
Comparison of IndexedDB API and IndexedDB Promised library: https://developers.google.com/web/ilt/pwa/working-with-indexeddb#comparison_of_indexeddb_api_and_indexeddb_promised_library
-
We use IndexedDB API with Elemental2
-
Google IndexedDB: https://developers.google.com/web/ilt/pwa/working-with-indexeddb#opening_a_database
-
Mozilla IndexedDB: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
-
Medium article IndexedDB for JavaScript: https://medium.com/jspoint/indexeddb-your-second-step-towards-progressive-web-apps-pwa-dcbcd6cc2076
-
Example IndexedDB in JavaScript: https://github.com/mdn/to-do-notifications/blob/gh-pages/scripts/todo.js
-
IndexedDB Elemental2JavaDoc: https://javadoc.io/doc/com.google.elemental2/elemental2-indexeddb/latest/index.html
-
Elemental2 examples: https://github.com/google/elemental2/tree/master/samples
-
Example Elemental2 IndexedDB in GWT Group: https://groups.google.com/g/google-web-toolkit/c/hUmBkKI_6ow/m/m6ppyUDGFwAJ
openDBRequest.onsuccess = event -> {
addProducts(event);
return null;
};
openDBRequest.onsuccess = event -> {
addProducts(event);
return Js.undefined();
};
- The generator for generating the JsInterops files is JsInterop Generator (https://github.com/google/jsinterop-generator).
- JsInterop Generator generates Java JsInterops files from Closure Externs. Closure Externs are mostly hand written. Example: Someone decided to map Any to a Template value. The Extern Def file is at https://github.com/google/closure-compiler/blob/master/externs/browser/w3c_indexeddb.js#L166 but really they could map it in a few different ways.
- Akasha (https://github.com/akasha/akasha) reads the WebIDL and generates Java JsInterop files from that.
A similar but slightly different set of conventions from Elemental2. Example:
In the case above Akasha would map it to Any but in some cases it maps it to @DoNotAutobox object.
@JsType(isNative = true, namespace = JsPackage.GLOBAL)
public class IDBRequest<T> implements EventTarget {
@JsType(isNative = true, name = "?", namespace = JsPackage.GLOBAL)
public interface ErrorUnionType {
@JsOverlay
static IDBRequest.ErrorUnionType of(Object o) {
return Js.cast(o);
}
@JsOverlay
default DOMError asDOMError() {
return Js.cast(this);
}
@JsOverlay
default DOMException asDOMException() {
return Js.cast(this);
}
@JsOverlay
default boolean isDOMError() {
return (Object) this instanceof DOMError;
}
@JsOverlay
default boolean isDOMException() {
return (Object) this instanceof DOMException;
}
}
@JsFunction
public interface OnerrorFn {
Object onInvoke(Event p0);
}
@JsFunction
public interface OnsuccessFn {
Object onInvoke(Event p0);
}
@JsType(isNative = true, name = "?", namespace = JsPackage.GLOBAL)
public interface SourceUnionType {
@JsOverlay
static IDBRequest.SourceUnionType of(Object o) {
return Js.cast(o);
}
@JsOverlay
default IDBCursor asIDBCursor() {
return Js.cast(this);
}
@JsOverlay
default IDBIndex asIDBIndex() {
return Js.cast(this);
}
@JsOverlay
default IDBObjectStore asIDBObjectStore() {
return Js.cast(this);
}
@JsOverlay
default boolean isIDBCursor() {
return (Object) this instanceof IDBCursor;
}
@JsOverlay
default boolean isIDBIndex() {
return (Object) this instanceof IDBIndex;
}
@JsOverlay
default boolean isIDBObjectStore() {
return (Object) this instanceof IDBObjectStore;
}
}
public IDBRequest.ErrorUnionType error;
@Deprecated public double errorCode;
public IDBRequest.OnerrorFn onerror;
public IDBRequest.OnsuccessFn onsuccess;
public String readyState;
public T result;
public IDBRequest.SourceUnionType source;
public IDBTransaction transaction;
public native void addEventListener(
String type, EventListener listener, EventTarget.AddEventListenerOptionsUnionType options);
public native void addEventListener(String type, EventListener listener);
public native boolean dispatchEvent(Event evt);
public native void removeEventListener(
String type, EventListener listener, EventTarget.RemoveEventListenerOptionsUnionType options);
public native void removeEventListener(String type, EventListener listener);
}
/**
* The IDBRequest interface of the IndexedDB API provides access to results of asynchronous requests to databases and database objects using event handler attributes. Each reading and writing operation on a database is done using a request.
*
* @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/IDBRequest">IDBRequest - MDN</a>
* @see <a href="https://www.w3.org/TR/IndexedDB/#idbrequest">IDBRequest - Indexed Database API 2.0</a>
* @see <a href="https://www.w3.org/TR/IndexedDB/#request-api">IDBRequest - Indexed Database API 2.0</a>
*/
@Generated("org.realityforge.webtack")
@JsType(
isNative = true,
namespace = JsPackage.GLOBAL,
name = "IDBRequest"
)
public class IDBRequest extends EventTarget {
/**
* The following example requests a given record title, onsuccess gets the associated record from the IDBObjectStore (made available as objectStoreTitleRequest.result), updates one property of the record, and then puts the updated record back into the object store. Also included at the bottom is an onerror function that reports what the error was if the request fails. For a full working example, see our To-do Notifications app (view example live.)
*
* @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/IDBRequest/onerror">IDBRequest.onerror - MDN</a>
* @see <a href="https://www.w3.org/TR/IndexedDB/#dom-idbrequest-onerror">onerror - Indexed Database API 2.0</a>
* @see <a href="https://w3c.github.io/IndexedDB/#dom-idbrequest-onerror">onerror - Indexed Database API Draft</a>
*/
@Nullable
public EventHandler onerror;
/**
* The following example requests a given record title, onsuccess gets the associated record from the IDBObjectStore (made available as objectStoreTitleRequest.result), updates one property of the record, and then puts the updated record back into the object store. For a full working example, see our To-do Notifications app (view example live.)
*
* @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/IDBRequest/onsuccess">IDBRequest.onsuccess - MDN</a>
* @see <a href="https://www.w3.org/TR/IndexedDB/#dom-idbrequest-onsuccess">onsuccess - Indexed Database API 2.0</a>
* @see <a href="https://w3c.github.io/IndexedDB/#dom-idbrequest-onsuccess">onsuccess - Indexed Database API Draft</a>
*/
@Nullable
public EventHandler onsuccess;
protected IDBRequest() {
}
/**
* A DOMError containing the relevant error. In Chrome 48+/Firefox 58+ this property returns a DOMException because DOMError has been removed from the DOM standard. The following error codes are returned under certain conditions:
*
* @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/IDBRequest/error">IDBRequest.error - MDN</a>
* @see <a href="https://www.w3.org/TR/IndexedDB/#dom-idbrequest-error">error - Indexed Database API 2.0</a>
* @see <a href="https://w3c.github.io/IndexedDB/#dom-idbrequest-error">error - Indexed Database API Draft</a>
*/
@JsProperty(
name = "error"
)
@Nullable
public native DOMException error();
/**
* The IDBRequestReadyState of the request, which takes one of the following two values:
*
* @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/IDBRequest/readyState">IDBRequest.readyState - MDN</a>
* @see <a href="https://www.w3.org/TR/IndexedDB/#dom-idbrequest-readystate">readyState - Indexed Database API 2.0</a>
* @see <a href="https://w3c.github.io/IndexedDB/#dom-idbrequest-readystate">readyState - Indexed Database API Draft</a>
*/
@JsProperty(
name = "readyState"
)
@Nonnull
@IDBRequestReadyState
public native String readyState();
/**
* any
*
* @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/IDBRequest/result">IDBRequest.result - MDN</a>
* @see <a href="https://www.w3.org/TR/IndexedDB/#dom-idbrequest-result">result - Indexed Database API 2.0</a>
* @see <a href="https://w3c.github.io/IndexedDB/#dom-idbrequest-result">result - Indexed Database API Draft</a>
*/
@JsProperty(
name = "result"
)
@Nullable
public native Any result();
/**
* An object representing the source of the request, such as an IDBIndex, IDBObjectStore or IDBCursor.
*
* @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/IDBRequest/source">IDBRequest.source - MDN</a>
* @see <a href="https://www.w3.org/TR/IndexedDB/#dom-idbrequest-source">source - Indexed Database API 2.0</a>
* @see <a href="https://w3c.github.io/IndexedDB/#dom-idbrequest-source">source - Indexed Database API Draft</a>
*/
@JsProperty(
name = "source"
)
@Nullable
public native IDBObjectStoreOrIDBIndexOrIDBCursorUnion source();
/**
* An IDBTransaction.
*
* @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/IDBRequest/transaction">IDBRequest.transaction - MDN</a>
* @see <a href="https://www.w3.org/TR/IndexedDB/#dom-idbrequest-transaction">transaction - Indexed Database API 2.0</a>
* @see <a href="https://w3c.github.io/IndexedDB/#dom-idbrequest-transaction">transaction - Indexed Database API Draft</a>
*/
@JsProperty(
name = "transaction"
)
@Nullable
public native IDBTransaction transaction();
@JsOverlay
public final void addErrorListener(@Nonnull final EventListener callback,
@Nonnull final AddEventListenerOptions options) {
addEventListener( "error", Js.cast( callback ), options );
}
@JsOverlay
public final void addErrorListener(@Nonnull final EventListener callback,
final boolean useCapture) {
addEventListener( "error", Js.cast( callback ), useCapture );
}
@JsOverlay
public final void addErrorListener(@Nonnull final EventListener callback) {
addEventListener( "error", Js.cast( callback ) );
}
@JsOverlay
public final void removeErrorListener(@Nonnull final EventListener callback,
@Nonnull final EventListenerOptions options) {
removeEventListener( "error", Js.cast( callback ), options );
}
@JsOverlay
public final void removeErrorListener(@Nonnull final EventListener callback,
final boolean useCapture) {
removeEventListener( "error", Js.cast( callback ), useCapture );
}
@JsOverlay
public final void removeErrorListener(@Nonnull final EventListener callback) {
removeEventListener( "error", Js.cast( callback ) );
}
@JsOverlay
public final void addSuccessListener(@Nonnull final EventListener callback,
@Nonnull final AddEventListenerOptions options) {
addEventListener( "success", Js.cast( callback ), options );
}
@JsOverlay
public final void addSuccessListener(@Nonnull final EventListener callback,
final boolean useCapture) {
addEventListener( "success", Js.cast( callback ), useCapture );
}
@JsOverlay
public final void addSuccessListener(@Nonnull final EventListener callback) {
addEventListener( "success", Js.cast( callback ) );
}
@JsOverlay
public final void removeSuccessListener(@Nonnull final EventListener callback,
@Nonnull final EventListenerOptions options) {
removeEventListener( "success", Js.cast( callback ), options );
}
@JsOverlay
public final void removeSuccessListener(@Nonnull final EventListener callback,
final boolean useCapture) {
removeEventListener( "success", Js.cast( callback ), useCapture );
}
@JsOverlay
public final void removeSuccessListener(@Nonnull final EventListener callback) {
removeEventListener( "success", Js.cast( callback ) );
}
}
- Elemental2 which is generated from JsInterop Generator is actually more JavaScript oriented since the source is from hand written Closure Externs.
- Akasha is more Java oriented.