Using the JCache API with CDI on Payara Server

Photo of Steve Millidge by Steve Millidge
The latest release of Payara Server 4.1.151 includes Hazelcast as a builtin JSR107 JCache implementation this means with Payara Server you can start building applications that uses a robust data grid as a caching tier with a standard api.


Payara is a supported and enhanced version of GlassFish Open Source edition 4.1 and uses GlassFish to provide support for CDI and Java EE7.Hazelcast is an in-memory Data Grid that provides resilient, elastically scalable, distributed storage of POJOs. Hazelcast provides a JSR107 compatible api.JCache JSR107 specifies an api for caching of Java POJOs in Java SE and therefore works with Java EE. JCache provides a map like Key Value store for caching objects similar to other caches like memcached or EHCache.JSR107 also specifies a set of annotations for caching objects which can be used via CDI and this is what we will walkthrough in this blog.

First Enable Hazelcast in Payara

We will assume you have Payara installed (see blog for details of how to do this).
As Payara provides a drop-in replacement for GlassFish 4.1 open source edition Hazelcast is disabled by default. It can be enabled via as-admin or via the administration console.

./asadmin set-hazelcast-configuration --enabled=true –target=server
We can check that Hazelcast is enabled using asadmin;
./asadmin list-hazelcast-members –target=server
This will printout the Payara servers that are part of the Hazelcast cluster.
{ server-/192.168.79.135:55555-this }In this case just our Payara server as we don't have any further Payara servers running.

 

Payara Server Hazelcast Configuration

 

Adding Caching to a CDI Bean

Now we have Hazelcast enabled within Payara we can use the new JCache apis in Java EE applications.So imagine we have a CDI Bean with a method that takes a long time;

 

@RequestScoped

public class SlowOperationBean {

    public String doSlowOperation(String input1, String input2) {

        try {

            Thread.currentThread().sleep(20000);

        } catch (InterruptedException ex) {

            Logger.getLogger(SlowOperationBean.class.getName()).log(Level.SEVERE, null, ex);

        }

        String randomHex = Double.toHexString(Math.random());

        return randomHex;

    }

}

In the real world this operation could be doing anything that could take a long time and could be cached for performance e.g.;
  • Running a time consuming database query
  • Obtaining a JSON result from a remote REST service
  • Computing some HTML based on user preferences

Lets add Caching to speed it up

 

To Cache the result of the method using JSR107, in Payara Server, we just need to add the @CacheResult annotation to the method;

 

    @CacheResult

    public String doSlowOperation(String input1, String input2) {

        try {

            Thread.currentThread().sleep(20000);

        } catch (InterruptedException ex) {

            Logger.getLogger(SlowOperationBean.class.getName()).log(Level.SEVERE, null, ex);

        }

        String randomHex = Double.toHexString(Math.random());

        return randomHex;

    }

 

 

That's all you need to do!

 

Driving the Bean

So I created a servlet, that injects the CDI bean, and runs in Payara to test drive caching for this blog.You just need to package up your bean and your servlet in a standard web application and deploy to Payara. Nothing else needs to be done to use JSR107 on Payara. Nothing needs to be added to beans.xml, no CDI extensions need to be written. Just deploy the bean and the servlet.

@WebServlet(name = "CallSlowMethod", urlPatterns = {"/CallSlowMethod"})

public class TestServlet2 extends HttpServlet {

    @Inject

    SlowOperationBean bean;

    @Override

    protected void doGet(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        response.setContentType("text/html;charset=UTF-8");

        try (PrintWriter out = response.getWriter()) {

            out.println("<!DOCTYPE html>");

            out.println("<html>");

            out.println("<head>");

            out.println("<title>Servlet Call Slow Method</title>");

            out.println("</head>");

            out.println("<body>");

            long startTime = System.currentTimeMillis();

            String result = bean.doSlowOperation("hello", "world");

            long endTime = System.currentTimeMillis();

            out.println("Calling Slow Bean took " + (endTime - startTime) + " ms and we got result " + result);

            out.println("</body>");

            out.println("</html>");

        }

    }

}

 

Running the Servlet

 

Servlet Call

 

 

The first time I run the servlet we can see the call takes 20s and we get a random hex result.The second time I run the Servlet you can see the method call takes 1ms and we get the same  result back. This is because the @CacheResult annotation tells Payara to take the result of the method call and Cache it into Hazelcast using a key derived from the value of the two method parameters.As simple as that! We have cached the result and sped up the method call 10,000 times. How’s that for spurecharging your application with 12 characters!

 

 

Servlet Call

 

Exploring More

The JCache JSR107 specification is fully supported in Payara 4.1.151 onwards and this blog shows just a very simple use case. Further blogs will show using other features of JCache from within Payara.If you want to find out more about JSR107 take a look at these slides, click here to view a slide show with further instructions. Click here to download Payara and try this for yourself! 

 

Comments