X

Geertjan's Blog

  • April 24, 2014

Meaningful HTML/Java DukeScript Framework Applications (Part 2)

Geertjan Wielenga
Product Manager

OK, so now the application I started working on is even more meaningful.

Firstly, what is it all about? Well, with the DukeScript Framework, you use Java to write application logic, with HTML5 to render the UI. No Swing. No JavaFX. HTML takes the place of those toolkits. Then you can manipulate the HTML page from Java, use REST or WebSockets, and do anything else with Java that you might want to do.

So here's the state of my CRUD app right now, i.e., still only R, but with improved code (thanks Jarda), and now the selected customer is displayed when a row is selected. 

Let's start by looking at the HTML file that defines the above.

<html>
<body>
<h1>Sample Database</h1>
<table border="1">
<thead>
<tr>
<th>Name</th>
<th>City</th>
<th>State</th>
<th>Mail</th>
</tr>
</thead>
<tbody data-bind="foreach: customers">
<tr data-bind="click: $root.selectCustomer" style="cursor: pointer">
<td data-bind="text: name"></td>
<td data-bind="text: city"></td>
<td data-bind="text: state"></td>
<td data-bind="text: email"></td>
</tr>
</tbody>
</table>
<br/>
<b>Current Selection</b>
<p data-bind="with: selectedCustomer">
<font color="red">Name</font>: <span data-bind="text: name"> </span>
<br/>
<font color="red">City</font>: <span data-bind="text: city"> </span>
</p>
</body>
</html>

What you see here is plain HTML together with Knockout bindings. The rows in the table are bound to properties in the model. When a row is selected, a method in the model is called that changes a property, which is bound with the Knockout "with" binding so that the currently selected name and city are shown.

Here's the definition of the Main class, which is annotated with the @Model annotation, and can be understood as a singleton:

@Model(className = "CrudApp", properties = {
@Property(name = "selectedCustomer", type = CustomerData.class),
})
public final class Main {
@ComputedProperty
static java.util.List<CustomerData> customers() {
EntityManager entityManager
= Persistence.createEntityManagerFactory("myPU").
createEntityManager();
Query query = entityManager.createNamedQuery("Customer.findAll");
List<CustomerData> arr = new ArrayList<>();
for (Object object : query.getResultList()) {
arr.add(((Customer) object).getData());
}
return arr;
}
@Function
static void selectCustomer(CrudApp myModel, CustomerData data) {
myModel.setSelectedCustomer(data);
}
private Main() {
}
/**
* Launches the browser
*/
public static void main(String... args) throws Exception {
BrowserBuilder.newBrowser().
loadPage("pages/index.html").
loadClass(Main.class).
invoke("onPageLoad", args).
showAndWait();
System.exit(0);
}
/**
* Called when page is ready
*/
public static void onPageLoad(String... args) throws Exception {
new CrudApp().applyBindings();
}
}

There's also a Customer POJO, i.e., a JPA entity, which in addition to the JPA annotations is annotated as follows:

@Model(className = "CustomerData", properties = {
@Property(name = "name", type = String.class),
@Property(name = "addressline1", type = String.class),
@Property(name = "addressline2", type = String.class),
@Property(name = "city", type = String.class),
@Property(name = "state", type = String.class),
@Property(name = "phone", type = String.class),
@Property(name = "fax", type = String.class),
@Property(name = "email", type = String.class),
@Property(name = "creditLimit", type = int.class)
})

Plus, there's a getter that returns the CustomerData, so that the "customers()" method in the Main class can build up the list of customers.

The next step is to persist the data back into the database. Weird to be manipulating the DOM from Java but, obviously, great. 

Join the discussion

Comments ( 4 )
  • Christoph Nahr Friday, April 25, 2014

    Thanks for this enlightening series. A general-purpose, multi-device way to use Java with a HTML UI would be extremely useful. As you pointed out earlier, the project does need better communication. When I first heard about "DukeScript" I assumed it was probably some way to script NetBeans applications...


  • guest Friday, April 25, 2014

    Next step is to replace

    <span data-bind="text: name"> </span>

    with

    <input data-bind="value: name"> </input>

    possibly also clone the current user data (to not influence the data in primary table before submitting):

    myModel.setSelectedCustomer(data.clone());


  • Jaroslav Tulach Tuesday, September 16, 2014

    Now there is a CRUD wizard: http://wiki.apidesign.org/wiki/CRUD


  • Emanuele Ziglioli Sunday, June 7, 2015

    Very good blog post,

    I find interesting the mapping of the "ComputedProperty" concept from knockout to DukeScript. Also some magic happens when we pass a parameter into a "@computedPorperty" method.

    Now, it seems to me a bit of an overload having two annotations "@Function" and "@ComputedProperty", couldn't DukeScript just allow a @Function method to optionally return a value and be done with it?


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.