Wednesday Jan 30, 2013

GlassFish 4 Latest Builds, Zip, API, and Javadocs (TOTD #200)


Do you want a handy link to the latest GlassFish builds, zip bundles, Java EE 7 API jar or javadocs ?

Now they are available at download.java.net/glassfish/4.0/promoted!



The pattern is: download.java.net/glassfish/4.0/promoted/latest-*.

So download.java.net/glassfish/4.0/promoted/latest-glassfish.zip gives you the latest GlassFish zip bundle. Similarly download.java.net/glassfish/4.0/promoted/latest-javaee-api-javadoc.jar gives you the latest Java EE 7 javadocs and download.java.net/glassfish/4.0/promoted/latest-web-unix.sh gives you the latest Unix installer for Java EE 7 Web profile. These are all in turn link to the latest promoted build.

The complete set of promoted builds are available as usual at download.java.net/glassfish/4.0/promoted. And the nightly builds at download.java.net/glassfish/4.0/nightly.

What is your favorite location to download GlassFish builds ?

Tuesday Jan 29, 2013

Java EE 7 and NetBeans IDE - Early Support Available (TOTD #199)


NetBeans IDE provides the best out-of-the-box experience for Java EE development, deployment, and debugging. Early builds of NetBeans have already started providing support for Java EE 7 features such as
  • Registering GlassFish 4
  • Creating Java EE 7 application
  • Wizard for JAX-RS 2 Filters/Interceptors
  • Initial support for Faces Flow
  • Loading templates from a resource library
  • Non-persistent EJB timers in Web profile
  • Wizard for WebSocket endpoints
wiki.netbeans.org/JavaEE7 provide a complete list of features slated for the release and the builds can be downloaded from bertram2.netbeans.org:8080/job/web-main-javaee7. Here are some snapshots of the work completed so far.

Creating a Java EE 7 Web application and using GlassFish 4 server


Creating a WebSocket endpoint



Wizard for creating WebSocket endpoint


The generated code looks like:

@WebSocketEndpoint("/endpoint")
public class NewWSEndpoint {

@WebSocketMessage
public String onMessage(String message) {
return null;
}

}

Creating a JAX-RS 2 Filter


Wizard for creating a JAX-RS 2 Filter


By default it is a server-side filter but can be made client-side filter too.

Wizard for creating a JAX-RS 2 Interceptor



Creating a RESTful Java Client using JAX-RS 2 Client APIs



Wizard for creating a JAX-RS 2 Client


This is a very early work-in-progress so any feedback is welcome.

Download GlassFish 4.0 promoted build, register it with NetBeans IDE and take it for a test drive!

Monday Jan 28, 2013

JSF 2.2 Faces Flow - @FlowScoped, #{flowScope}, @FlowDefinition (TOTD #198)


JavaServer Faces 2.2 is more evolutionary than it is revolutionary. This is by design as JSF 2.0 added a whole bunch of new features as part of the Java EE 6 platform. The Preface 1 from the JSF 2.2 Public Review specification provides a list of changes between JSF 2.1 and 2.2. There are several changes coming in JSF 2.2 but the big ticket items are:
  • Faces Flow
  • Resource Library Contract
  • HTML5 Friendly Markup
This Tip Of The Day (TOTD) will explain Faces Flow. Section 7.5 and 11.4.3 in the specification introduce the feature.

Faces Flow provides an encapsulation of related views/pages with an application defined entry and exit points. For example, a check out cart can consist of cart page, credit card details page, shipping address page, and confirmation page. All these pages, along with required resources and beans, can be packaged together as a module which can then be reused in other applications.

Each flow has a well-defined entry and exit point that have been assigned some application specific meaning by the developer. Usually the objects in a faces flow are designed to allow the user to accomplish a task that requires input over a number of different views. In our case, the navigation between pages for selecting items, entering shipping address, credit card details, and confirmation page would make a flow. All the pages and objects that deal with the checking out process can be composed as modules. An application thus become a collection of flows instead of just views.

It takes the best part of other flow-based technologies such as ADF Task Flow, Spring Web Flow, and Apace MyFaces CODI and standardizes in JSF 2.2.

What is the need ?

Imagine a multi-page shopping cart with one page for selecting the items, a second page for shipping options, a third page for entering credit card details, and a fourth page for final confirmation. Managed Beans can be used to capture the data, session scope variables pass information between pages, button clicks can be used to invoke the business logic in backing EJBs, and (conditional) navigation rules can be defined to go from one page to another. There are a few issues with this approach:
  • This flow of sequence will typically be part of a bigger application. However an application, typically with several pages, is one large flow and everything is visible with no logical partitioning.
  • The flow of pages or views cannot be encapsulated as a logical unit and thus cannot be reused, e.g. incorporated into another bigger flow easily.
  • The lowest logical granularity is a page. The only way to invoke application logic is to tie it to a UI component activated by the user in a page. Business logic cannot be invoked without any user initiated action.
  • Same flow cannot be opened in multiple windows because session scoped variables are used to pass information between pages. CDI defines @ConversationScoped but that is only part of the solution.
  • There is no scope defined that can span multiple pages but less than a session.
Faces Flow provide a solution to the issues mentioned above.

What's new in JSF 2.2 for flows ?

The flow of application is no longer restricted to flow between pages but instead defined as flow between "nodes". There are five different types of nodes:
  • View: Any JSF page in the application
  • Method Call: Invoke application logic from flow graph via an EL
  • Switch: Navigation decisions in the flow graph based on boolean EL
  • Flow Call: Call another flow with parameters and receive return values
  • Flow Return: Return to the calling flow
The nodes define the entry and exit points of a flow.

Two new annotations are introduced:
  • @FlowScoped is a CDI scope that defines the scope of bean in the specified flow. This enables automatic activation/passivation of the bean when the scope is entered/exited.
  • @FlowDefinition is a class level annotation that allows the flow definition to be defined using the fluent FlowBuilder API.
A new EL object, #{flowScope}, for flow local storage is also introduced. This maps to facesContext.getApplication().getFlowHandler().getCurrentFlowScope().

How are flows packaged ?

Flows can be packaged in JAR files or in directories.

JAR packaging requires flows to be explicitly declared in META-INF/faces-config.xml in the JAR file. Flow nodes are packaged in META-INF/flows/<flowname> where <flowname> is a JAR directory entry whose name is identical to that of a flow id in the corresponding faces-config.xml. @FlowScoped and @FlowDefinition beans must be packaged in the JAR file and accompanied by META-INF/beans.xml.

A sample JAR file looks like:

META-INF/faces-config.xml
META-INF/flows/flow1/entry.xhtml
META-INF/flows/flow1/next.xhtml
META-INF/flows/flow1/end.xhtml
META-INF/flows/flow2/start.xhtml
META-INF/flows/flow2/next.xhtml
META-INF/flows/flow2/end.xhtml
META-INF/beans.xml
org/glassfish/sample/MyFlow1Bean.class
org/glassfish/sample/MyFlow2Bean.class
org/glassfish/sample/MyFlowDefintion.class
Flows packaged in directories use convention-over-configuration. The conventions are:
  • Every View Declaration Language file in that directory is a view node of that flow.
  • The start node of the flow is the view whose name is the same as the name of the flow.
  • Navigation among any of the views in the directory is considered to be within the flow.
  • Navigation to a view outside of that directory is considered to be an exit of the flow.
  • Optional <flowname>-flow.xml that represents the flow definition. The rules in this file overrides the conventions described above.

A sample directory looks like:

flow1/flow1.xhtml
flow1/flow1a.xhtml
flow1/flow1b.xhtml
flow2/flow2-flow.xml
flow2/flow2.xhtml
flow2/flow2a.xhtml
flow2/flow2b.xhtml
WEB-INF/...
Show me the code!

Lets try a sample now!

The source code for the two samples explained below can be downloaded here. A complete explanation of the sample including the code walk-through is shown in the video:



This will run on GlassFish 4.0 b72. For now, you'll need to replace glassfish/modules/javax.faces.jar with javax.faces-2.2.0-SNAPSHOT.jar and replacing glassfish/modules/javax.el.jar with javax-el-3.0-b03.jar. This JARs will soon be integrated in the GlassFish build. Ah, the joys of bleeding edge development!

Saturday Jan 26, 2013

Java EE 7 Maven Application (TOTD #197)

Did you know that Java EE 7 APIs are now published in maven ?

The complete set of coordinates are described here. So how do you build a simple Java EE 7 maven application ?

  1. Generate the ususal Java EE 6 maven application as:

    mvn -DarchetypeGroupId=org.codehaus.mojo.archetypes -DarchetypeArtifactId=webapp-javaee6 -DarchetypeVersion=1.5 -DarchetypeRepository=http://repo.maven.apache.org/maven2 -DgroupId=org.glassfish -DartifactId=hello-javaee7 -Dversion=1.0-SNAPSHOT -Dpackage=org.glassfish.hellojavaee7 -Darchetype.interactive=false --batch-mode archetype:generate
  2. In the generated pom.xml, replace
    <dependencies>
    <dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-web-api</artifactId>
    <version>6.0</version>
    <scope>provided</scope>
    </dependency>
    </dependencies>

    with

    <repositories>
    <repository>
    <id>Java EE 7</id>
    <url>https://maven.java.net/content/groups/promoted/</url>
    </repository>
    </repositories>

    <dependencies>
    <dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-api</artifactId>
    <version>7.0-b72</version>
    </dependency>
    </dependencies>

    Notice, there is a new <version> of dependency for each GlassFish 4 promoted build. This may be simplified in the coming builds.

    The <artifactId> can be changed to javaee-web-api if your application requires Java EE 7 Web Profile API only.

And now all Java EE 7 APIs so far integrated in GlassFish are available in your application.

You can also include specific API JAR files explicitly in your project directly. The latest APIs are available in the format:

In general, you can replace "b72" in the URL with the latest promoted build number to get the latest artifacts. A simplified URL for the latest set of these artifacts is in the works!

What next ? Maven archetype and support in NetBeans coming soon!

Tuesday Jan 22, 2013

Default DataSource in Java EE 7: Lesser XML and More Defaults (TOTD #196)


Section E.5.5.20 in the Java EE 7 Platform specification defines a new Default Data Source that must be provided by a Java EE 7-compliant runtime. This pre-configured data source can be used by application for accessing the associated database. It is accessible to the application under the JNDI name:
java:comp/DefaultDataSource

This can be accessed in the application as:
@Resource(name="myDataSource", lookup="java:comp/DefaultDataSource")
DataSource myDS;

If the binding is not specified, the mapping of the reference will default to this default data source. So the above fragment is equivalent to:
@Resource(name="myDataSource")
DataSource myDS;

Section 8.2.1.5 in the JPA 2.1 specification says

If neither jta-data-source and non-jta-data-source elements are specified, the deployer must specify a JTA data source at deployment or a JTA data source must be provided by the container, and a JTA EntityManagerFactory will be created to correspond to it.

Per.book
This means a Java EE 7 application can have the following persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="myPU" transaction-type="JTA">
<jta-data-source>java:comp/DefaultDataSource</jta-data-source>
</persistence-unit>
</persistence>

This is semantically equivalent to:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="movieplex7PU" transaction-type="JTA"/>
</persistence>

Notice, no jta-data-source.

In both cases, the default data source will be provisioned and available to the application. In GlassFish 4, this is bound to the JDBC resource jdbc/__default.

And this can be verified by giving the command:
./bin/asadmin list-jdbc-resources
jdbc/sample
jdbc/__TimerPool
jdbc/__default
Command list-jdbc-resources executed successfully.

Lesser XML and more defaults makes Java EE 7 more lightweight and user friendly!

Download GlassFish 4.0 promoted build and try it today!

Friday Jan 18, 2013

JPA 2.1 Implementation - EclipseLink M6 integrated in GlassFish 4 (TOTD #195)

As TOTD #187 explained, one of the new features in JPA 2.1 is Schema Generation. It refers to generation of database artifacts like tables, indexes, and constraints in a database schema. Read TOTD #187 for more details. This Tip Of The Day (TOTD) will explain how to use this feature in GlassFish 4.

JPA 2.1 is implemented in EclipseLink and the status shows that a decent progress is made. EclipseLink Milestone builds shows the dates when milestones are released. It typically takes a few days for the milestone to be integrated in GlassFish 4 after the release.

How do you know which milestone is integrated in GlassFish 4 ?

Issue the following commmand in glassfish/modules directory:
unzip -p org.eclipse.persistence.core.jar META-INF/MANIFEST.MF | grep Bundle-Version
to see an output as:
Bundle-Version: 2.5.0.v20130110-d839ca4
If we break the version string then it shows this is version 2.5.0 and dated 20130110 in the format YYYYMMDD, that would be Jan 10, 2013. Based upon the milestone release dates, this indicates M6 is integrated.

I tried this with the latest nightly build (dated Jan 18). By the time you read this blog, a newer version may be integrated and so the version string may look different.

Now lets see this in action!

The sample code explained below can be downloaded here and run on GlassFish 4 1/17 nightly. A promoted build after this nightly should work too.

Create an Entity class as:
@Entity
@Table
@NamedQueries({
@NamedQuery(name = "Employee.findAll", query = "SELECT e FROM Employee e")
})
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;

@Column(length=40)
private String name;
This is a simple Employee entity that has two fields id and name. A trivial @NamedQuery is defined to retrieve the list of employees.

The associated persistence.xml looks like:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="MyPU" transaction-type="JTA">
<jta-data-source>jdbc/sample</jta-data-source>
<properties>
<property name="javax.persistence.schema-generation-action" value="drop-and-create"/>
<property name="javax.persistence.schema-generation-target" value="database"/>
<property name="eclipselink.deploy-on-startup" value="true"/>
</properties>
</persistence-unit>
</persistence>

Other than the usual elements like <persistence-unit> and <jta-data-source>, the newly introduced properties - javax.persistence.schema-generation-action and javax.persistence.schema-generation-target define the action and target for the schema generation. The action is to drop and create the tables. The target defines to perform the action in the database. These properties control the behavior of schema generation and their meaning is defined in TOTD #187. Notice, the third property is EclipseLink specific and is specified to eagerly initialize the Persistence Unit. This will ensure that the schema is generated during the application deployment itself. Otherwise it is generated when the PU is first accessed.

This will generate the table in the database defined by jdbc/sample JDBC resource. This resource is pre-defined for JavaDB that is already bundled with GlassFish 4.

After this, you can write a simple EJB as:

@Stateless
public class EmployeeBean {

@PersistenceContext
EntityManager em;

public void persist(Employee e) {
em.persist(e);
}

public List<Employee> get() {
return em.createNamedQuery("Employee.findAll", Employee.class).getResultList();
}
}

And invoke it from a Servlet as:

for (int i=0; i<5; i++) {
bean.persist(new Employee("Name" + i));
}
for (Employee e : bean.get()) {
out.println(e.getName() + "<br>");
}

A different set of properties may be specified as:

<properties>
<property name="javax.persistence.schema-generation-action" value="drop-and-create"/>
<property name="javax.persistence.schema-generation-target" value="scripts"/>
<property name="javax.persistence.ddl-create-script-target" value="createfoo.sql"/>
<property name="javax.persistence.ddl-drop-script-target" value="dropfoo.sql"/>
<property name="eclipselink.deploy-on-startup" value="true"/>
<property name="eclipselink.application-location" value="/tmp"/>
</properties>
These properties specify the action as "drop-and-create", i.e. drop and create the tables. The target specifies the the action to be performed in a script. The *.script-target property specifies the name of the files for create and drop DDL. The following scripts are generated:

more /tmp/createfoo.sql 
CREATE TABLE EMPLOYEE (ID INTEGER NOT NULL, NAME VARCHAR(40), PRIMARY KEY (ID))
CREATE TABLE SEQUENCE (SEQ_NAME VARCHAR(50) NOT NULL, SEQ_COUNT DECIMAL(15), PRIMARY KEY (SEQ_NAME))
INSERT INTO SEQUENCE(SEQ_NAME, SEQ_COUNT) values ('SEQ_GEN', 0)
CREATE TABLE SEQUENCE (SEQ_NAME VARCHAR(50) NOT NULL, SEQ_COUNT DECIMAL(15), PRIMARY KEY (SEQ_NAME))
INSERT INTO SEQUENCE(SEQ_NAME, SEQ_COUNT) values ('SEQ_GEN', 0)

more /tmp/dropfoo.sql
DROP TABLE EMPLOYEE
DELETE FROM SEQUENCE WHERE SEQ_NAME = 'SEQ_GEN'

By default, the scripts are generated in glassfish/domains/domain1 directory. In this case, an EclipseLink-specific property to identify the base location of the generated files is specified.

As TOTD #187 explains, you can bundle DDL and DML scripts to generate and populate the database. Are you ready to test drive JPA 2.1 implemented using EclipseLink 2.5 in GlassFish 4 ?

JPA 2.1 Public Review specification has been available for a few days now. The Appendix A in the specification provide revision history in case you want to focus on the newly added features only.  If you are a JUG member, you may consider adopting this JSR and provide feedback!

Friday Jan 11, 2013

JAX-RS Client API and GlassFish 4 - Logging HTTP messages (TOTD #194)


One of the main features added in JAX-RS 2 is Client API. This API is used to access Web resources and provides integration with JAX-RS Providers. Without this API, the users need to use a low-level HttpUrlConnection to access the REST endpoint.

If the resource looks like:

@Path("/fruit")
public class MyResource {

@GET
public String get() {

then, before this API, the endpoint can be accessed as:

URL url = new URL("http://. . ./webresources/fruit");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.setDoOutput(false);
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
    //. . .
}
With this newly introduced API, the endpoint can be accessed as:

Client client = ClientFactory.newClient();
WebTarget target = client.target("http://. . ./webresources/fruit");
String response = target.request().get(String.class);
Client is the entry point to the Client API and is used to build and execute client requests and consume responses returned. The default instance of Client can be obtained by calling ClientFactory.newClient. Using this we can create a WebTarget by specifying URI of the web resource. These targets are then used to prepare client request invocation by specifying additional query or matrix parameters and resolving the URI template for different names. Finally, one of the HTTP methods is invoked on the prepared client.

The fluency of the API hides the complexity but a better understanding of the flow allows to write better code.

All the classes introduced in the specification are available in javax.ws.rs.client package.

Lets take a look at a complete sample. The complete source code can be downloaded here.

For a resource defined as:

@Path("/fruit")
public class MyResource {

@GET
public String get() {
return Database.getAll();
}

@GET
@Path("{name}")
public String get(@PathParam("name")String payload) {
return Database.get(payload);
}

@POST
public void post(String payload) {
Database.add(payload);
}

@PUT
public void put(String payload) {
Database.add(payload);
}

@DELETE
public void delete(String payload) {
Database.delete(payload);
}
}

A Client invoking all the HTTP methods look like:

Client client = ClientFactory.newClient();
WebTarget target = client.target("http://"
+ request.getServerName()
+ ":"
+ request.getServerPort()
+ request.getContextPath()
+ "/webresources/fruit");

// POST
target.request().post(Entity.text("apple"));

// PUT
target.request().put(Entity.text("banana"));

// GET (all)
String r = target.request().get(String.class);

// GET (one)
r = target.path("apple").request().get(String.class);

// DELETE
target.path("banana").request().delete();

// GET (all)
r = target.request().get(String.class);

And here are the message dumps:

INFO: 1 * LoggingFilter - Request received on thread http-listener-1(5)
1 > POST http://localhost:8080/endpoint/webresources/fruit
1 > Content-Type: text/plain
apple

INFO: 2 * LoggingFilter - Response received on thread http-listener-1(5)
2 < 204
2 < Date: Fri, 11 Jan 2013 22:21:23 GMT
2 < Server: GlassFish Server Open Source Edition 4.0
2 < X-Powered-By: Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 4.0 Java/Oracle Corporation/1.7)

INFO: 3 * LoggingFilter - Request received on thread http-listener-1(5)
3 > PUT http://localhost:8080/endpoint/webresources/fruit
3 > Content-Type: text/plain
banana

INFO: 4 * LoggingFilter - Response received on thread http-listener-1(5)
4 < 204
4 < Date: Fri, 11 Jan 2013 22:21:23 GMT
4 < Server: GlassFish Server Open Source Edition 4.0
4 < X-Powered-By: Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 4.0 Java/Oracle Corporation/1.7)

INFO: 5 * LoggingFilter - Request received on thread http-listener-1(5)
5 > GET http://localhost:8080/endpoint/webresources/fruit

INFO: 6 * LoggingFilter - Response received on thread http-listener-1(5)
6 < 200
6 < Date: Fri, 11 Jan 2013 22:21:23 GMT
6 < Content-Length: 15
6 < Content-Type: text/html
6 < Server: GlassFish Server Open Source Edition 4.0
6 < X-Powered-By: Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 4.0 Java/Oracle Corporation/1.7)
[apple, banana]

INFO: 7 * LoggingFilter - Request received on thread http-listener-1(5)
7 > GET http://localhost:8080/endpoint/webresources/fruit/apple

INFO: 8 * LoggingFilter - Response received on thread http-listener-1(5)
8 < 200
8 < Date: Fri, 11 Jan 2013 22:21:23 GMT
8 < Content-Length: 5
8 < Content-Type: text/html
8 < Server: GlassFish Server Open Source Edition 4.0
8 < X-Powered-By: Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 4.0 Java/Oracle Corporation/1.7)
apple

INFO: 9 * LoggingFilter - Request received on thread http-listener-1(5)
9 > DELETE http://localhost:8080/endpoint/webresources/fruit/banana

INFO: 10 * LoggingFilter - Response received on thread http-listener-1(5)
10 < 204
10 < Date: Fri, 11 Jan 2013 22:21:23 GMT
10 < Server: GlassFish Server Open Source Edition 4.0
10 < X-Powered-By: Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 4.0 Java/Oracle Corporation/1.7)

INFO: 11 * LoggingFilter - Request received on thread http-listener-1(5)
11 > GET http://localhost:8080/endpoint/webresources/fruit

INFO: 12 * LoggingFilter - Response received on thread http-listener-1(5)
12 < 200
12 < Date: Fri, 11 Jan 2013 22:21:23 GMT
12 < Content-Length: 7
12 < Content-Type: text/html
12 < Server: GlassFish Server Open Source Edition 4.0
12 < X-Powered-By: Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 4.0 Java/Oracle Corporation/1.7)
[apple]

This has been tested on GlassFish 4 build 70 with the following dependencies:

<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0-m10</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-common</artifactId>
<version>2.0-m10</version>
<type>jar</type>
</dependency>

Here are some more pointers to follow:

Provide feedback on Jersey 2 to users@jersey.java.net and JAX-RS specification to users@jax-rs-spec.java.net.


Monday Jan 07, 2013

JAX-RS Custom Entity Providers (TOTD #193)


JAX-RS defines Entity Providers that supply mapping services between on-the-wire representations and their associated Java types. The entities, also known as "message payload" or "payload" represent the main part of an HTTP message. These are specified as method parameters and return types of resource methods. Several standard Java types such as String, byte[], javax.xml.bind.JAXBElement, java.io.InputStream, java.io.File, and others have a pre-defined mapping and is required by the specification. Applications may provide their own mapping to custom types using MessageBodyReader and MessageBodyWriter interfaces. This allows to extend the JAX-RS runtime easily to support your own custom entity providers.

The MessageBodyReader interface defines the contract for a provider that supports the conversion of a stream to a Java type. The MessageBodyWriter interface defines the contract for a provider that supports the conversion of a Java type to a stream. This Tip Of The Day (TOTD) will explain how to write these custom entity providers.

Note, this functionality was defined in JAX-RS 1.0 as opposed to Client API, Client- and Server-side async, Hypermedia, and many other features. The complete source code for this sample application can be downloaded here and will work on GlassFish 4.0 b70.

Here is a simple resource that returns name of the fruit based upon the index passed as parameter:

@Path("fruits")
public class MyResource {
private String[] response = { "apple", "banana", "mango" };

@POST
public String getFruit(int index) {
return response[index % 3];
}
}
This resource can be invoked using the newly introduced Client API as:

Client client = ClientFactory.newClient();
WebTarget target = client.target("http://"
+ request.getServerName()
+ ":"
+ request.getServerPort()
+ request.getContextPath()
+ "/webresources/fruits");
String fruit = target
.request()
.post(Entity.text("1"), String.class);

If we update the resource such that the index parameter is passed as the following object:

public class MyObject implements Serializable {
public static final String MIME_TYPE = "application/myType";

private int index;

public MyObject() {
}

public MyObject(int index) {
this.index = index;
}

public int getIndex() {
return index;
}

public void setIndex(int index) {
this.index = index;
}
}

Then the resource method would look like:

@POST
@Consumes(value=MyObject.MIME_TYPE)
public String getFruit(MyObject mo) {
return response[Integer.valueOf(mo.getIndex()) % 3];
}

The additional @Consumes annotation defines the media type that the method can accept. The following custom entity providers are defined to support this custom type. The first one, MyReader, defines the conversion of on-the-wire representation to MyObject Java type.

@Provider
@Consumes(MyObject.MIME_TYPE)
public class MyReader implements MessageBodyReader<MyObject> {

@Override
public boolean isReadable(Class<?> type, Type type1, Annotation[] antns, MediaType mt) {
return MyObject.class.isAssignableFrom(type);
}

@Override
public MyObject readFrom(Class<MyObject> type,
Type type1,
Annotation[] antns,
MediaType mt, MultivaluedMap<String, String> mm,
InputStream in) throws IOException, WebApplicationException {
try {
ObjectInputStream ois = new ObjectInputStream(in);
return (MyObject)ois.readObject();
} catch (ClassNotFoundException ex) {
Logger.getLogger(MyReader.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
}

The interface require two methods, isReadable and readFrom, to be implemented. The implementation has @Consumes annotation restricting the media type supported by this entity provider.

The second one, MyWriter, defines the conversion from MyObject Java type to on-the-wire representation.

@Provider
@Produces(MyObject.MIME_TYPE)
public class MyWriter implements MessageBodyWriter<MyObject> {

@Override
public boolean isWriteable(Class<?> type, Type type1, Annotation[] antns, MediaType mt) {
return MyObject.class.isAssignableFrom(type);
}

@Override
public long getSize(MyObject t, Class<?> type, Type type1, Annotation[] antns, MediaType mt) {
// As of JAX-RS 2.0, the method has been deprecated and the
// value returned by the method is ignored by a JAX-RS runtime.
// All MessageBodyWriter implementations are advised to return -1 from
// the method.

return -1;
}

@Override
public void writeTo(MyObject t,
Class<?> type,
Type type1,
Annotation[] antns,
MediaType mt,
MultivaluedMap<String, Object> mm,
OutputStream out) throws IOException, WebApplicationException {
ObjectOutputStream oos = new ObjectOutputStream(out);
oos.writeObject(t);
}
}
The interface require three methods isWriteable, getSize, writeTo to be implemented. The implementation of getSize method is recommended to return -1 as JAX-RS runtime is required to compute the actual Content-Length header value. The implementation has @Produces annotation restricting the media type supported by this entity provider.

The reader and writer entity providers are marked with @Provider and are thus automatically discovered at runtime on the server-side. But until JERSEY-1634 is fixed, they need to be explicitly specified in the Application class as:

@ApplicationPath("webresources")
public class MyApplication extends Application {
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new java.util.HashSet<>();
resources.add(MyResource.class);
resources.add(MyReader.class);
resources.add(MyWriter.class);
return resources;
}
}

On the client-side, the providers need to be explicitly registered as shown:

Client client = ClientFactory.newClient();
client
.configuration()
.register(MyReader.class)
.register(MyWriter.class);
String fruit = target
.request()
.post(Entity.entity(new MyObject(1), MyObject.MIME_TYPE), String.class);

Notice, how invoking the endpoint requires to specify the media type as part of post method invocation.

The complete source code for this sample application can be downloaded here and will work on GlassFish 4.0 b70.

Here are some more pointers to follow

Provide feedback on Jersey 2 to users@jersey.java.net and JAX-RS specification to users@jax-rs-spec.java.net.


Wednesday Jan 02, 2013

Batch Applications in Java EE 7 - Undertanding JSR 352 Concepts: TOTD #192


Batch processing is execution of series of "jobs" that is suitable for non-interactive, bulk-oriented and long-running tasks. Typical examples are end-of-month bank statement generation, end-of-day jobs such as interest calculation, and ETL (extract-transform-load) in a data warehouse. These tasks are typically data or computationally intensive, execute sequentially or in parallel, and may be initiated through various invocation models, including ad-hoc, scheduled, and on-demand.

JSR 352 will define a programming model for batch applications and a runtime for scheduling and executing jobs. This blog will explain the main concepts in JSR 352.

The diagram below highlight the key concepts of a batch processing architecture.



  • A Job is an instance that encapsulates an entire batch process. A job is typically put together using a Job Specification Language and consists of multiple steps. The Job Specification Language for JSR 352 is implemented with XML and is referred as "Job XML".
  • A Step is a domain object that encapsulates an independent, sequential phase of a job. A step contains all of the information necessary to define and control the actual batch processing.
  • JobOperator provides an interface to manage all aspects of job processing, including operational commands, such as start, restart, and stop, as well as job repository commands, such as retrieval of job and step executions.
  • JobRepository holds information about jobs current running and jobs that run in the past. JobOperator provides access to this repository.
  • Reader-Processor-Writer pattern is the primary pattern and is called as Chunk-oriented processing. In this, ItemReader reads one item at a time, ItemProcessor processes the item based upon the business logic, such as calculate account balance and hands it to ItemWriter for aggregation. Once the 'chunk' number of items are aggregated, they are written out, and the transaction is committed.

    JSR 352 also defines roll-your-own batch pattern, called as Batchlet. This batch pattern is invoked once, runs to completion, and returns an exit status. This pattern must implement and honor a "cancel" callback to enable operational termination of the Batchlet.
A Job XML for a chunk-oriented processing may look like:

<job id="myJob" xmlns="http://batch.jsr352/jsl">
<step id="myStep" >
<chunk reader="MyItemReader"
writer="MyItemWriter"
processor="MyItemProcessor"
buffer-size="5"
checkpoint-policy="item"
commit-interval="10" />
</step>
</job>

  • The <job> has an "id" attribute that defines the logical name of the job and is used for identification purposes.
  • Each <job> can multiple <step>s where each <step> identifies a job step and it's characteristics. Each <step> has an "id" attribute that defines the logical name of the job and is used for identification purposes.
  • A <step> may have <chunk> or <batchlet> element, this <step> has a <chunk>. A <chunk> identifies a chunk type step and implements the reader-processor-writer pattern of batch.
  • The "reader", "processor", and "writer" attributes specify the class names of an item reader, processor, and writer respectively.
  • "buffer-size" specifies number of items to read and buffer before writing. When enough items have been read to fill the buffer, the buffer is emptied to a list and the configured ItemWriter is invoked with the list of items.
  • "checkpoint-policy" attribute specifies the checkpoint policy that governs commit behavior for this chunk. Valid values are "item", "time" and "custom". The "item" policy means chunk is checkpointed after a specified number of items are processed. The "time" policy means the chunk is committed after a specified amount of time. The "custom" policy means the chunk is checkpointed according to a checkpoint algorithm implementation. The default policy is "item".
  • "commit-interval" specifies the commit interval for the specified checkpointed policy. The unit meaning of the commit-interval specifies depends on the specified checkpoint policy. For "item" policy, commit-interval specifies a number of items. For "time" policy, commit- interval specifies a number of seconds. The commit-interval attribute is ignored for "custom" policy.

    When the configured checkpoint policy directs it is time to checkpoint, all the items read and processed so far are passed to the "writer".

Here is a simple reader:

@ItemReader
public class MyItemReader {
private static int id;
MyCheckPoint checkpoint = null;

@Open
void open(MyCheckPoint checkpoint) {
this.checkpoint = checkpoint;
System.out.println(getClass().getName() + ".open: " + checkpoint.getItemCount());
}

@ReadItem
MyBatchRecord read() {
checkpoint.incrementByOne();
return new MyBatchRecord(++id);
}

@CheckpointInfo
MyCheckPoint getCheckPoint() {
return checkpoint;
}
}

Methods marked with @Open, @ReadItem, and @CheckpointInfo are required.

Here is a simple processor that rejects every other item:

@ItemProcessor
public class MyItemProcessor {
@ProcessItem
MyBatchRecord process(MyBatchRecord record) {
return (record.getId() % 2 == 0) ? record : null;
}
}

And here is a simple writer:

@ItemWriter
public class MyItemWriter {
MyCheckPoint checkpoint = null;

@Open
void open(MyCheckPoint checkpoint) {
this.checkpoint = checkpoint;
System.out.println(getClass().getName() + ".open: " + checkpoint.getItemCount());
}

@WriteItems
void write(List<MyBatchRecord> list) {
System.out.println("Writing the chunk...");
for (MyBatchRecord record : list) {
System.out.println(record.getId());
}
checkpoint.increment(list.size());
System.out.println("... done.");
}

@CheckpointInfo
MyCheckPoint getCheckPoint() {
return checkpoint;
}
}

Finally a simple implementation of MyCheckpoint:

public class MyCheckPoint {
int itemCount;

public int getItemCount() {
return itemCount;
}

public void setItemCount(int itemCount) {
this.itemCount = itemCount;
}

void incrementByOne() {
itemCount++;
}

void increment(int size) {
itemCount += size;
}
}

Together, MyItemReader, MyItemWriter, MyItemProcessor, MyCheckPoint, and batch.xml, will read/process/write 5 items and commit when 10 such items have been processed.

JSR 352 specification defines several other concepts such as how Job XML can define sequencing of jobs, listeners to interpose on job execution, transaction management, and running jobs in partitioned and concurrent modes. Subsequent blog will explain some of those concepts.

A complete replay of Java Batch for Cost-Optimized Business Efficiency from JavaOne 2012 can be seen here (click on CON4105_mp4_4105_001 in Media).

Each feature will be added to the JSR subject to EG approval. You can share your feedback to public@jbatch.java.net.

The APIs and implementation of JSR 352 are not integrated in GlassFish 4 promoted builds yet.

Here are some more references for you:

Here are some other Java EE 7 primers published so far:


And of course, more on their way! Do you want to see any particular one first ?

About

profile image
Arun Gupta is a technology enthusiast, a passionate runner, author, and a community guy who works for Oracle Corp.


Java EE 7 Samples

Stay Connected

Search

Archives
« January 2013 »
SunMonTueWedThuFriSat
  
1
3
4
5
6
8
9
10
12
13
14
15
16
17
19
20
21
23
24
25
27
31
  
       
Today