The HTML/Java API is an alternative to Swing and JavaFX for creating
applications with a graphical user interface. It's major strengths is the
intelligent combination of existing technologies.
With HTML/Java, the proven model used on servers for many years, has been ported to the client.
Java is used for developing business and view logic, while
HTML5, CSS and JavaScript are used to render the UI.
Get the best of both worlds by combining the industry stability of
Java and richness of JavaScript ecosystem when it comes
to UI and rendering frameworks.
The motivation for this project is the inability of Swing and JavaFX to keep up with the rapid development of browser based technologies, and the uncertain future of Swing and JavaFX. The logical solution is to simply use these technologies from Java instead of trying to build a whole own alternative stack. With Java/HTML we created a better and more powerful alternative, which is still small and easy to maintain.
For this Java/HTML makes use of the Model View ViewModel (MVVM) pattern to separate the view from the logic of the application. This approach is different from Swing or JavaFX, as the Java code doesn't require any references to the widgets that are displayed in the view. The Java code instead exposes {@link net.java.html.json.Property properties} for the View to bind to, and {@link net.java.html.json.Function functions} that can be called in response to user interactions. This keeps the {@link net.java.html.json.Model Java API} small and simple to learn.
This architecture also makes it easy to port the technology to different platforms. Porting of HTML/Java is as easy as implementing {@link org.netbeans.html.boot.spi.Fn.Presenter} interface and successfully passing the {@link org.netbeans.html.json.tck test compatibility kit}. Various ports of this rendering pipeline were built including support for pure "webkit desktop rendring Android WebView and iOS WebView developed by DukeScript project.
This technology has also been adopted by some Java bytecode to JavaScript transpilers - for example TeaVM or Bck2Brwsr VM - as such you can also run the same Java application in a pluginless browser.
$ mvn archetype:generate \ -DarchetypeGroupId=com.dukescript.archetype \ -DarchetypeArtifactId=knockout4j-archetype \ -DgroupId=your.company -DartifactId=test -Dversion=1.0-SNAPSHOT -DarchetypeVersion=0.30 \ # or newer version, if availableand then you can:
$ cd test $ mvn install $ mvn -f client/pom.xml process-classes exec:exec
We tried to make our API Docs as useful as possible, so they contain lots of valuable information. So this should be your first stop when looking for information: Current development version
The DukeScript project contains a lot of information for Java/HTML developers. There's a Blog with the latest news and tips and tricks how to get the most out of these APIs and also an extensive getting started guide explaining all the concepts and walking you through code examples. For advanced users there's an in depth tutorial on the Knockout For Java API with many examples and tipps and tricks.
And finally, if you want to see this API in action, look no further, here's an example application running with the Bck2Brwsr VM directly in your browser.
This is a bugfix release focused on improving {@link org.netbeans.html.presenters.spi.ProtoPresenter} when running in {@linkplain org.netbeans.html.presenters.spi.ProtoPresenterBuilder#loadJavaScript(org.netbeans.html.presenters.spi.ProtoPresenterBuilder.Evaluator, boolean) asynchronous mode}. PR #48 changes the Knockout For Java binding to use JavaScript {@code Promise} to properly order initialization of many {@link net.java.html.json.Model} classes in a highly asynchronous environment. As a result the underlying JavaScript engine has to (since version 1.8.1) provide support for {@code Promise} or emulate it somehow.
Asynchronous calls to Java - since PR #44 the {@link net.java.html.js.JavaScriptBody} annotation supports new {@link net.java.html.js.JavaScriptBody#wait4java wait4java=false} attribute. That allows one make an asynchronous call to Java. More information in the updated {@link net.java.html.js Java/JavaScript interactions} page. Support for reactive programming simplified with {@link net.java.html.json.Models#react} as provided by PR-43.
Giving proper OSGi name to
org.netbeans.html.presenters.spi
,
org.netbeans.html.presenters.render
,
org.netbeans.html.presenters.browser
and
org.netbeans.html.presenters.webkit
modules -
PR #40.
Configure {@link org.netbeans.html.presenters.browser.Browser.Config#browser(java.util.function.Consumer) browser presenter}
to handle opening of a {@code URI} programmatically -
PR #42.
Code completions for callbacks from JavaScript to Java - PR #36. Support for ecj - PR #37. Robustness of {@link org.netbeans.html.presenters.spi.ProtoPresenter} improved - PR #38.
Bugfix release to address robustness and security issues.
New modules are provided since PR #23:
Click the link to view even more historic changes...
One model instance can be used in two views (PR #14). GC related behavior has been improved (PR #19). Safe and {@link net.java.html.boot.script.Scripts sanitized builder} to create {@link javax.script.ScriptEngine}-based execution environment (PR #15). Switching to knockout.js version 3.5.0 (PR #20).
Compiles on JDK11 while using
Open JavaFX 11
when necessary.
{@link net.java.html.json.ComputedProperty Computed properties} can
depend on other computed properties -
PR #3.
{@link net.java.html.js.JavaScriptResource} annotation has been
made repeatable -
PR #4.
@Model
annotation processor bugfix
#621.
The project has been donated to Apache Foundation and the code is now hosted in the repository along other Apache incubating projects. Contribute to the project by forking its GitHub repository.
Using Android JSON parsing library as it is Apache licensed - bug #89. It is acceptable to read properties of a model when {@link net.java.html.json.ComputedProperty computing a property}. Regular subclassing of {@link org.netbeans.html.json.spi.Proto.Type} is possible. Bugfix #99 - better garbage collector related behavior of ko4j instances thanks to introduction of {@link org.netbeans.html.json.spi.Technology.ToJavaScript}. Mentioning knockout.js license in the ko4j artifact - bug #98. Simplifying dependencies of {@link org.netbeans.html.json.tck} - bug #111
Bug fix for multiple observers on a single model object. Better GC behavior specified in TCK and used in Knockout for Java implementation. Removing dependency on Java collection classes implementations. Adding {@link net.java.html.json.Models#asList} factory method to a create simple list implementation. Simplifying {@link org.netbeans.html.json.tck.KnockoutTCK} to avoid usage of {@link java.net.URI}, etc.
null
and undefined
are
treated as null.
Better behavior under
multi-threaded load.
Workaround for garbage collector behavior of modern JavaFX WebView
implementations (JDK8 u112 and newer).
JavaFX Presenter can
show popup window.
Development has switched to
Git repository thanks to
conversion by Emilian Bold.
Better support for obfuscation of knockout module
(bug
270013).
false
to define a non-mutable (almost constant) property. That
in case of Knockout bindings means: the property is
represented by a plain value rather than an observable in the JavaScript
object. The JavaFX presenter can be executed in headless mode -
just specify -Dfxpresenter.headless=true
when launching
its virtual machine and no window will be shown. This is particularly
useful for testing. Configure your surefire or failsafe
plugins like: <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.13</version> <configuration> <systemPropertyVariables> <fxpresenter.headless>true</fxpresenter.headless> </systemPropertyVariables> </configuration> </plugin>OSGi headers are now enterprise OSGi ready. Switched to minified version 3.4.0 of knockout.js. Better support for recursive @Model definitions. New module
org.netbeans.html:xhr4j
provides implementation
of {@link org.netbeans.html.json.spi.Transfer} with
{@link org.netbeans.html.context.spi.Contexts.Id technology identifier}
xhr4j - this module can be used to
workaround limitations
of CORS by handling the {@link net.java.html.json.OnReceive}
connections in Java.
One can control {@link net.java.html.json.OnReceive#headers() HTTP request headers}
when connecting to server using the {@link net.java.html.json.OnReceive}
annotation. It is possible to have
{@link net.java.html.json.ComputedProperty#write() writable computed properties}.
There is an easy way to enable Firebug in
the JavaFX based Web View -
just run with -Dfirebug.lite=true
as
this video
demonstrates.
Bugfix of issues 250503,
252987.
The content of a {@link net.java.html.BrwsrCtx context}
can be selected by registering implementations under specific
{@link org.netbeans.html.context.spi.Contexts.Id technology identifiers}
and requesting them during
{@link org.netbeans.html.context.spi.Contexts#newBuilder(java.lang.Object...) construction}
of the context. org.netbeans.html:ko4j
module's implementation
offers ko4j, xhr and websocket identifiers
for its registered services
(e.g. {@link org.netbeans.html.json.spi.Technology},
{@link org.netbeans.html.json.spi.Transfer} and
{@link org.netbeans.html.json.spi.WSTransfer}).
org.netbeans.html:ko-ws-tyrus
module registers its
{@link org.netbeans.html.json.spi.Transfer Java based JSON} and
{@link org.netbeans.html.json.spi.WSTransfer WebSocket} implementations
under the name tyrus.
A particular DOM subtree
that a knockout.js model gets
applied to can be selected by using
{@link net.java.html.json.Models#applyBindings(java.lang.Object,java.lang.String)
Models.applyBindings(m, id)} with an id of an HTML element.
There is new {@link net.java.html.json.Model#targetId()} attribute
which controls behavior of the generated applyBindings
method.
If specified and non-empty, then the generated method
will call {@link net.java.html.json.Models#applyBindings(java.lang.Object,java.lang.String)}
with this
and the provided {@link net.java.html.json.Model#targetId() target id}.
If specified, but left empty, then the generated method
calls {@link net.java.html.json.Models#applyBindings(java.lang.Object)}.
If unspecified, the method will not be generated at all
(a change with respect to older versions). However one can
still use {@link net.java.html.json.Models#applyBindings(java.lang.Object)}
or {@link net.java.html.json.Models#applyBindings(java.lang.Object,java.lang.String)}
to perform the association of any model with the page element.
Memory model when using Knockout bindings has been improved (required additions of two new methods: {@link org.netbeans.html.json.spi.PropertyBinding#weak()} and {@link org.netbeans.html.json.spi.FunctionBinding#weak()}) and now the Java {@link net.java.html.json.Model models} can garbage collect, when no longer used. Library writers that use {@link net.java.html.js.JavaScriptBody} annotation can also control garbage collection behavior of method arguments by setting {@link net.java.html.js.JavaScriptBody#keepAlive() keepAlive=false} attribute.
{@link net.java.html.json.Property#array() Array properties} are now mutable from the knockout.js point of view (required {@link org.netbeans.html.json.spi.Proto.Type#replaceValue one SPI change}). The page lookup mechanism can use {@link net.java.html.boot.BrowserBuilder#locale(java.util.Locale) locale} to load localized a page with appropriate suffix. All SPI were moved under the NetBeans namespace - e.g. {@link org.netbeans.html.boot.spi}, {@link org.netbeans.html.context.spi}, {@link org.netbeans.html.json.spi}, {@link org.netbeans.html.sound.spi}, and also {@link org.netbeans.html.json.tck}. Methods annotated with {@link net.java.html.js.JavaScriptBody} annotation and without fallback Java code now throw {@link java.lang.IllegalStateException} with a message suggesting to switch to proper {@link net.java.html.BrwsrCtx#execute browser context} to prevent endless debugging when one forgets to do so.
System can run in {@link net.java.html.boot.BrowserBuilder#classloader(java.lang.ClassLoader) Felix OSGi container} (originally only Equinox). {@link net.java.html.json.ComputedProperty Derived properties} now deeply check changes in other {@link net.java.html.json.Model model classes} they depend on and recompute their values accordingly. Knockout.js library has been updated to version 3.2.0.
Setters or array properties on classes generated by {@link net.java.html.json.Model}
annotation can be accessed from any thread. {@link org.netbeans.html.sound.spi.AudioEnvironment}
can be registered into {@link net.java.html.BrwsrCtx}. There is
a {@link net.java.html.json.Models#parse(net.java.html.BrwsrCtx, java.lang.Class, java.io.InputStream, java.util.Collection) method}
to parse a JSON array and convert it into
{@link net.java.html.json.Model model classes}.
Improved behavior of enum
values in
{@link net.java.html.json.Model knockout bindings}.
Few bugfixes for better portability. New API for {@link net.java.html.boot.script.Scripts headless execution} on top of Nashorn - does not run knockout for Java fully yet (reported as JDK-8046013), however even in current state it is quite {@link net.java.html.boot.script.Scripts useful for testing} of {@link net.java.html.js Java/JavaScript interactions}.
{@link net.java.html.boot.fx.FXBrowsers} has been extended with new helper methods to make it easier to use HTML+Java API in existing JavaFX applications. The annotation processor is made more robust with respect to errors in callback syntax of {@link net.java.html.js.JavaScriptBody} body parameter. Javadoc of {@link net.java.html.BrwsrCtx#execute} method has been improved based on a failure of its usability study. There can be additional parameters to methods annotated by {@link net.java.html.json.OnReceive} that allows one to pass state when a JSON call is made and use it when it finishes. The mechanism of discovery of sibling HTML page has been extended to work on systems that don't support {@link java.lang.Class#getProtectionDomain}.
The first argument of method annotated by {@link net.java.html.json.OnReceive} annotation has to be the associated {@link net.java.html.json.Model model class}.
{@link net.java.html.json.OnReceive} annotation now accepts {@link java.util.List} of data values as second argument (previously required an array).
{@link net.java.html.js.JavaScriptBody} annotation has new attribute {@link net.java.html.js.JavaScriptBody#wait4js()} which allows asynchronous execution. Libraries using {@link net.java.html.js.JavaScriptBody} are urged to use this new attribute as much as possible, as it can speed up execution in certain environments.
Use {@link net.java.html.BrwsrCtx#execute(java.lang.Runnable)} in multi-threaded environment to execute your code on the browser thread. See example {@link net.java.html.BrwsrCtx#execute(java.lang.Runnable) using Java timer}.