Sunday 29 December 2013

How to use @Asynchronous in JEE

Since Java Enterprise Edition (JEE) 6 and EJB 3.1 (JSR 318) we can use the @Asynchronous annotation to call a method asynchronously.

The following example contains a Stateless Session Bean with three asynchronous methods, each one of them running for a different amount of time (1, 3 and 5 seconds) and returning a simple String value.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ejb.AsyncResult;
import javax.ejb.Asynchronous;
import javax.ejb.Stateless;
import java.util.concurrent.Future;

@Stateless
public class AsynchronousBean {

    private static final Logger LOG = LoggerFactory.getLogger(AsynchronousBean.class);

    @Asynchronous
    public Future<String> workFor5Seconds() throws Exception {
        LOG.info("==> workFor5Seconds");
        Thread.sleep(5000);
        LOG.info("<== workFor5Seconds");
        return new AsyncResult<String>("test1");
    }

    @Asynchronous
    public Future<String> workFor3Seconds() throws Exception {
        LOG.info("==> workFor3Seconds");
        Thread.sleep(3000);
        LOG.info("<== workFor3Seconds");
        return new AsyncResult<String>("test2");
    }

    @Asynchronous
    public Future<String> workFor1Second() throws Exception {
        LOG.info("==> workFor1Second");
        Thread.sleep(1000);
        LOG.info("<== workFor1Second");
        return new AsyncResult<String>("test3");
    }
}

We can test the AsynchronousBean with a small unit test using an EJBContainer to set up the environment. We call all three asynchronous methods in a row and use the Future type for the return result.

import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

public class AsynchronousTest {

    private static final Logger LOG = LoggerFactory.getLogger(AsynchronousTest.class);

    public static EJBContainer container;

    AsynchronousBean asynchronousBean;

    @Before
    public void setUp() throws Exception {
        container = EJBContainer.createEJBContainer();
        container.getContext().bind("inject", this); 
        asynchronousBean = (AsynchronousBean) container.getContext().lookup("java:global/[module-name]/" + AsynchronousBean.class.getSimpleName());
    }

    @Test
    public void asynchronousTest() throws Exception {

        final Future<String> future1 = asynchronousBean.workFor5Seconds();
        final Future<String> future2 = asynchronousBean.workFor3Seconds();
        final Future<String> future3 = asynchronousBean.workFor1Second();

        LOG.info("Do something else..");
        Thread.sleep(1000);

        final String result1 = future1.get();
        final String result2 = future2.get();
        final String result3 = future3.get();

        LOG.info("Result from workFor5Seconds is: {}", result1);
        LOG.info("Result from workFor3Seconds is: {}", result2);
        LOG.info("Result from workFor1Second is: {}", result3);
    }

    @AfterClass
    public static void destroy() throws Exception {
        if(container != null) {
            container.close();
        }
    }
}

If we analyze the output of the logging we see characteristics of @Asynchronous. In a sequential processing we would be stuck in the first method waiting for 5 seconds to return and then call the next one. Using asynchronous calls we can enter all methods concurrently and get the final result if it is ready.

[INFO ] Do something else..
[INFO ] ==> workFor5Second
[INFO ] ==> workFor3Seconds
[INFO ] ==> workFor1Seconds
[INFO ] <== workFor1Second
[INFO ] <== workFor3Seconds
[INFO ] <== workFor5Seconds
[INFO ] Result from workFor5Seconds is: test1
[INFO ] Result from workFor3Seconds is: test2
[INFO ] Result from workFor1Second is: test3

See also

Tuesday 22 October 2013

Hibernate Caching with Hazelcast

Probably you already know Hazelcast, the open source clustering and highly scalable platform for Java. If you do not know Hazelcast then visit their website and watch the nice intro video to get an idea of it.

As in-memory data-grid Hazelcast is well suited for a distributed cache. In this post I will show you how to setup Hazelcast as a second level cache for Hibernate.  For further information you can check the documentation or download my sample project from Github.

The important dependencies for the Hazelcast part are hazelcast and hazelcast-hibernate4. As the current Hazelcast version does not support Hibernate 4 you need an additional implementation for that.

<dependency>
    <groupid>com.hazelcast</groupid>
    <artifactid>hazelcast</artifactid>
    <version>3.0.2</version>
</dependency>
<dependency>
    <groupid>com.hazelcast</groupid>
    <artifactid>hazelcast-hibernate4</artifactid>
    <version>3.0.2</version>
</dependency>

In your persistence.xml you add the following lines to activate the second level cache and configure Hibernate to use Hazelcast for it.

<property name="hibernate.cache.use_second_level_cache" value="true" />
<property name="hibernate.cache.use_minimal_puts" value="true" />
<property name="hibernate.cache.hazelcast.use_lite_member" value="true" />
<property name="hibernate.cache.region.factory_class" value="com.hazelcast.hibernate.HazelcastCacheRegionFactory" />

In Hibernate 4 you now can annotate your entity with

@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)

to enable caching for that particular class. There are some configuration you can do using the hazelcast.xml. Check the sample project to see the complete setup with some tests to run.

See also:


Friday 20 September 2013

JAX-RS 2.0 using JSON and Persistence with JEE7

This post is about building a basic RESTful application with Maven using the JAX-RS 2.0 API (JSR339: JAX-RS 2.0). The data is exchanged using the JSON format. You will also see how JEE7 can simplify persistence for you. As server we will use Glassfish4 which contains the reference implementation of JEE7. At the end we will test our service with curl and with a unit test.

You can checkout this project from Github or download the archive here.

POM

So let's start. The only dependency we need in our pom.xml is the following:

<dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-api</artifactId>
    <version>7.0</version>
    <scope>provided</scope>
</dependency>

Persistence

To be able to persist the data we first create a basic entity class, nothing special about that.

@Entity
public class Customer {

    @Id
    private long id;
    private String name;
    
    // getters, setters and others
    ...
}

Using JEE7 we now have the possibility of using a default datasource for persistence. The persistence.xml file looks a bit shorter though.

<persistence-unit name="mypu" transaction-type="JTA">
    <properties>
        <property name="javax.persistence.schema-generation.database.action" value="drop-and-create">
    </property></properties>
</persistence-unit>

That's all about your persistence configuration. Featured by JEE7 we will use a default datasource under java:comp/DefaultDataSource. This is defined in Glassfish4 and connects to an integrated Derby database instance.

CRUD

To work with the Customer object we first need a service that handles the persistence. The following stateless bean offers the common CRUD functionality.

@Stateless
public class CustomerService {

    @PersistenceContext
    EntityManager em;

    public void create(Customer entity) {
        em.persist(entity);
    }

    public void update(Customer entity) {
        em.merge(entity);
    }

    public void remove(long id) {
        Customer customer = find(id);
        em.remove(customer);
    }

    public Customer find(long id) {
        return em.find(Customer.class, id);
    }
}

To make sure that Glassfish find our bean we also need the beans.xml in the WEB-INF directory.

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
xsi:schemalocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" 
bean-discovery-mode="all"></beans>

Make sure you use the bean-discovery-mode attribute because otherwise the container will not find your bean. At this point we are done with persistence so far.

RESTful

So let's step further to the RESTful part of our project. What we need is another stateless session bean with a method for each CRUD operation we want to support. The only thing we have to do for getting RESTful functionality is to use some annotations. On class level we annotate @Path("customers") as path to our service. Then we use @POST, @GET, @PUT and @DELETE to denote the different RESTful operations. As we want to communicate through JSON we use the MediaType.APPLICATION_JSON.

@Stateless
@Path("customers")
public class CustomerResource {

    @Inject
    CustomerService service;

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public void create(Customer customer) {
        service.create(customer);
    }

    @GET
    @Path("{id}")
    @Produces(MediaType.APPLICATION_JSON)
    public Customer find(@PathParam("id") long id) {
        return service.find(id);
    }

    @PUT
    @Consumes(MediaType.APPLICATION_JSON)
    public void update(Customer customer) {
        service.update(customer);
    }

    @DELETE
    @Path("{id}")
    public void delete(@PathParam("id") long id) {
        service.remove(id);
    }
}

There is one last thing we need to do to complete our REST configuration. @ApplicationPath("api") defines the global path to our application and this class has to extend javax.ws.rs.core.Application.

@ApplicationPath("api")
public class RESTConfig extends Application {
}

That's all the magic. Start the integrated Derby database with asadmin start-database and fire up your Glassfish server to try your new RESTful service.

curl

You can do a quick functionality check using curl. To send a POST request to your server and thereby create and persist the data do something like this:

curl -i -X POST -d '{"id":1,"name":"Annabelle"}' http://localhost:8080/jee7-rest-crud/api/customers -H 'Content-Type: application/json'

Basically that means, send a POST request containing that string to this address using the JSON format. Doing it right, your server will return something like that:

HTTP/1.1 204 No Content
X-Powered-By: Servlet/3.1 JSP/2.3 (GlassFish Server Open Source Edition  4.0  Java/Oracle Corporation/1.7)
Server: GlassFish Server Open Source Edition  4.0
Date: Fri, 20 Sep 2013 05:11:11 GMT

Status code 204 No Content is perfect here because we defined our RESTful service not to send any data back on a POST request. If you want to read the data you saved before you can send a GET request:

curl -i -X GET http://localhost:8080/jee7-rest-crud/api/customers/1 -H 'Content-Type: application/json'

Your server should return a result like this:

HTTP/1.1 200 OK
X-Powered-By: Servlet/3.1 JSP/2.3 (GlassFish Server Open Source Edition  4.0  Java/Oracle Corporation/1.7)
Server: GlassFish Server Open Source Edition  4.0
Content-Type: application/json
Date: Fri, 20 Sep 2013 05:10:16 GMT
Content-Length: 27

{"id":1,"name":"Annabelle"}

The PUT (update) and DELETE (remove) operations can be tested in the same way.

Unit Test

If you want to unit test your RESTful service you can now use the new ClientBuilder from the JAX-RS 2.0 API coming with JEE7. But you will need some extra dependencies for the JSON data binding because Java do not yet provide that (likely to come with Java 8).

<dependency>
    <groupId>org.glassfish.jersey.core</groupId>
    <artifactId>jersey-client</artifactId>
    <version>2.2</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.6.3</version>
    <scope>test</scope>
</dependency>

To do the data binding for JSON we need to implement the MessageBodyReader<T> and MessageBodyWriter<T> from the javax.ws.rs.ext package. These classes need to be annotated with @Provider and @Consumes respectively @Produces. Check the CustomerMessageBodyReader and CustomerMessageBodyWriter classes of the project for implementation details.

Now we can write a unit test to check the CRUD functionality of our RESTful service.

public class CustomerClientTest {

    private static final String SERVER = "http://localhost:8080/jee7-rest-crud/api/customers";

    private WebTarget target;

    @Before
    public void setUp() {
        Client client = ClientBuilder.newClient();
        client.register(CustomerMessageBodyReader.class);
        client.register(CustomerMessageBodyWriter.class);
        this.target = client.target(SERVER);
    }

    @Test
    public void crud() {

        Customer origin = new Customer(1, "Mathilda");
        Entity entity = Entity.entity(origin, MediaType.APPLICATION_JSON);

        // create
        Response response = target.request(MediaType.APPLICATION_JSON).post(entity, Response.class);
        assertThat(response.getStatus(), equalTo(204));

        // read
        Customer result = target.path(String.valueOf(origin.getId())).request(MediaType.APPLICATION_JSON).get(Customer.class);
        assertThat(result, equalTo(origin));

        // update
        entity.getEntity().setName("Annabelle");
        target.request().put(entity);

        // delete
        target.path(String.valueOf(origin.getId())).request(MediaType.APPLICATION_JSON).delete();
    }
}

First we build the client and register the custom reader and writer classes. Then we set the target to the address of our service. The rest is straight forward testing of the various functionality we have built.

See also