March 27, 2016

How to run standalone Java EE MVC application

This project demonstrates how to create standalone Java EE MVC application.

MVC is newly developed Java EE JSR 371: Model-View-Controller (MVC 1.0) Specification.
The MVC API defines an action-oriented Web framework as an alternative to the component-oriented JSF. In an action-oriented framework, developers are responsible for all the controller logic and are given full control of the URI space for their application. 
The MVC API is layered on top of JAX-RS over Servlets and integrates with existing EE technologies like CDI and Bean Validation.
MVC spec is going to be part of next Java EE 8. MVC reference implementation named Ozark is hosted on java.net. MVC depends on Servlets, JAX-RS and CDI. I've chosen to use UndertowJersey and Weld. And DeltaSpike as CDI extension library. Finally, Gradle to build and run the project.

ext {
    undertowVersion = '1.3.18.Final'
    weldVersion = '2.3.3.Final'
    deltaspikeVersion = '1.5.4'
    jerseyVersion = '2.22.2'
    ozarkVersion = '1.0.0-m02'
}
task wrapper(type: Wrapper) {
    gradleVersion = '2.12'
}

Standalone CDI container

Weld contains module to support Java SE applications. Together with Apache DeltaSpike Java SE & Weld module:

dependencies {
    compile "org.jboss.weld.se:weld-se:$weldVersion"
    compile "org.apache.deltaspike.cdictrl:deltaspike-cdictrl-weld:$deltaspikeVersion"

it is easy to bootstrap and shutdown CDI container:

import javax.enterprise.context.ApplicationScoped;
import org.apache.deltaspike.cdise.api.CdiContainer;
import org.apache.deltaspike.cdise.api.CdiContainerLoader;
import org.jboss.weld.servlet.WeldInitialListener;
import org.jboss.weld.servlet.WeldTerminalListener;

public class Main {

    static CdiContainer init() throws ServletException, NoSuchMethodException {
        CdiContainer cdiContainer = CdiContainerLoader.getCdiContainer();

        cdiContainer.boot();
        cdiContainer.getContextControl().startContext(ApplicationScoped.class);

        initServlet();

        return cdiContainer;
    }

    static void destroy(CdiContainer cdiContainer) {
        cdiContainer.getContextControl().stopContext(ApplicationScoped.class);
        cdiContainer.shutdown();
    }

...

You can see we also start and stop CDI ApplicationScoped scope.

Initialize Servlet

Next we need to register Jersey ServletContainer as Undertow servlet:

dependencies {
    compile "io.undertow:undertow-core:$undertowVersion"
    compile "io.undertow:undertow-servlet:$undertowVersion"

    compile "org.glassfish.jersey.core:jersey-server:$jerseyVersion"
    compile "org.glassfish.jersey.containers:jersey-container-servlet-core:$jerseyVersion"
    compile "org.glassfish.jersey.ext.cdi:jersey-cdi1x-servlet:$jerseyVersion"

import javax.servlet.Servlet;
import javax.servlet.ServletException;

import io.undertow.Undertow;
import io.undertow.servlet.Servlets;
import io.undertow.servlet.api.DeploymentInfo;
import io.undertow.servlet.api.DeploymentManager;
import io.undertow.servlet.api.ServletContainer;
import io.undertow.servlet.api.ServletInfo;

import org.jboss.weld.servlet.WeldInitialListener;
import org.jboss.weld.servlet.WeldTerminalListener;

public class Main {

    ...

    private static void initServlet() throws ServletException, NoSuchMethodException {
        DeploymentInfo deploymentInfo = new DeploymentInfo()
                .addListener(Servlets.listener(WeldInitialListener.class))
                .addListener(Servlets.listener(WeldTerminalListener.class))
                .setContextPath("/")
                .setDeploymentName("standalone-javax-mvc-app")
                .addServlets(
                        createServletInfo("/resources/*", "JAX-RS Resources", org.glassfish.jersey.servlet.ServletContainer.class)
                )
                .setClassIntrospecter(CdiClassIntrospecter.INSTANCE)
                .setAllowNonStandardWrappers(true)
                .setClassLoader(ClassLoader.getSystemClassLoader());

        ServletContainer servletContainer = Servlets.defaultContainer();
        DeploymentManager deploymentManager = servletContainer.addDeployment(deploymentInfo);
        deploymentManager.deploy();

        Undertow server = Undertow.builder()
                .addHttpListener(8080, "0.0.0.0")
                .setHandler(deploymentManager.start())
                .build();
        server.start();
    }

    private static ServletInfo createServletInfo(String mapping, String servletName, Class<? extends Servlet> servlet)
            throws NoSuchMethodException {
        ServletInfo servletInfo = Servlets
                .servlet(servletName, servlet)
                .setAsyncSupported(true)
                .setLoadOnStartup(1)
                .addMapping(mapping);
        servletInfo.setInstanceFactory(CdiClassIntrospecter.INSTANCE.createInstanceFactory(servlet));

        return servletInfo;
    }
}

Important part is registering of Weld Servlet listeners: WeldInitialListener and WeldTerminalListener.

The instance of Jersey ServletContainer is provided as ApplicationScoped bean by custom CdiProducer using CdiClassIntrospecter.

import javax.enterprise.inject.Produces;

import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;

@ApplicationScoped
public class CdiProducer {

    private long helloCounter;

    @Produces
    @ApplicationScoped
    public ServletContainer createServletContainer() {
        final ResourceConfig resourceConfig = new ResourceConfig();
        resourceConfig.register(HelloController.class);
        resourceConfig.property("javax.mvc.engine.ViewEngine.viewFolder", "WEB-INF/views/");

        return new ServletContainer(resourceConfig);
    }

    ...

You can see we need to customize "javax.mvc.engine.ViewEngine.viewFolder" property to support standalone application class-path behaviour.

CdiClassIntrospecter implements Undertow ClassIntrospecter interface and just delegates to CDI.

MVC

Now you can provide MVC @Controller methods:

dependencies {
    compile "org.glassfish.ozark:ozark:$ozarkVersion"
    compile "org.glassfish.ozark.ext:ozark-mustache:$ozarkVersion"

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.mvc.Models;
import javax.mvc.annotation.Controller;
import javax.mvc.annotation.View;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;

@Path("hello")
@ApplicationScoped
public class HelloController {

    @Inject
    private Models models;

    @GET
    @Controller
    @Produces("text/html")
    @View("hello.mustache")
    public void hello(@QueryParam("user") @DefaultValue("World") String user) {
        models.put("user", user);
    }

}

You can see I've chosen to use Mustache template engine, see hello.mustache:

<html>
    <head>
        <title>Hello</title>
    </head>
    <body>
        <h1>Hello {{user}}!</h1>
    </body>
</html>

Sources

Complete project sources are available on GitHub, https://github.com/shamoh/standalone-javax-mvc.

The easiest way how to run the project is:


gradlew run

The application is then available on: http://localhost:8080/resources/hello?user=Libor.


April 24, 2015

JAX-RS Kryo Message Body providers are placed to Jersey incubator

I have good news, mine JAX-RS Kryo support has been moved to Jersey incubator.

You can just add dependency on the module and your application can produce and consume application/x-kryo entities:


<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-kryo</artifactId>
    <version>${jersey.version}</version>
</dependency>

Original GitHub repository has been updated to use Jersey module. And as a bonus I've added two ways how to try it.

This is true since Jersey 2.18. The version was not released yet in time of writing this blog post. So you need to use 2.18-SNAPSHOT version and add Maven snapshot repository to your project:


<repositories>
    <repository>
        <id>java.net.snapshot</id>
        <url>https://maven.java.net/content/repositories/snapshots/</url>
    </repository>
</repositories>

Grizzly it

Maven packaging of this demo application is war. But it is possible to run the application using Grizzly HTTP container:

mvn exec:java

You can enable FINEST logging using logging.properties:

mvn exec:java -Djava.util.logging.config.file=target/test-classes/logging.properties

Jetty it

Or you can run it as common webapp using Jetty container:

mvn jetty:run-war

Again, you can enable FINEST logging using logging.properties:

mvn jetty:run-war -Djava.util.logging.config.file=target/test-classes/logging.properties

Check it

GET method is available at URL http://localhost:8080/, check it using curl:


curl -v http://localhost:8080/

Response should look like:


> GET / HTTP/1.1
> User-Agent: curl/7.40.0
> Host: localhost:8080
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Length: 20
< Content-Type: application/x-kryo
< Server: Jetty(8.1.16.v20140903)
<
Salzbur�*Wolfgan�

Origin

The Jersey Kryo support started as a "friday project". Evolution of the Kryo support shows list of previous blog posts:
  1. JAX-RS Kryo support introduced
  2. Performance report of JAX-RS Kryo support

April 10, 2015

JAX-RS Kryo Message Body Writer & Reader performance

In this blog post I'm going to return to one of my previous post about JAX-RS Message Body Providers using Kryo serialization framework. Today I'll show you performance statistics and compare it with some of Jersey build-in providers.

Comparing to ...

I have chosen to compare my Kryo provider with:
  • JAXB RI providers to read from and write to XML format.
  • Jackson providers to read from and write to JSON format.
  • Custom provider that reads and writes test entity (Person class) by itself. (Note: Used format is really simple and implementation is Person specific, uses artificial MIKME type application/person.)
  • Just plain text provider to read and write String only. It uses Jersey build-in provider.
Test applications are very similar to mine Jersey Kryo module and are part of Jersey source code:
The Kryo provider has been introduced in previous blog post. I have done one change since then. Performance of Kryo provider was several times improved using KryoPool:


@Consumes("application/x-kryo")
@Produces("application/x-kryo")
public class KryoMessageBodyProvider implements MessageBodyWriter<Object>,
                MessageBodyReader<Object> {

    private final KryoPool kryoPool;

    public KryoMessageBodyProvider() {
        final KryoFactory kryoFactory = new KryoFactory() {
            public Kryo create() {
                final Kryo kryo = new Kryo();
                // configure kryo instance, customize settings
                return kryo;
            }
        };
        kryoPool = new KryoPool.Builder(kryoFactory).softReferences().build();
    }

    //
    // MessageBodyWriter
    //

    @Override
    public long getSize(final Object object, final Class<?> type, final Type genericType,
                        final Annotation[] annotations, final MediaType mediaType) {
        return -1;
    }

    @Override
    public boolean isWriteable(final Class<?> type, final Type genericType,
                               final Annotation[] annotations, final MediaType mediaType) {
        return true;
    }

    @Override
    public void writeTo(final Object object, final Class<?> type, final Type genericType,
                        final Annotation[] annotations, final MediaType mediaType,
                        final MultivaluedMap<String, Object> httpHeaders, 
                        final OutputStream entityStream)
            throws IOException, WebApplicationException {
        final ByteArrayOutputStream baos = new ByteArrayOutputStream();

        final Output output = new Output(baos);
        kryoPool.run(new KryoCallback() {
            public Object execute(Kryo kryo) {
                kryo.writeObject(output, object);
                return null;
            }
        });
        output.close();

        entityStream.write(baos.toByteArray());
    }

    //
    // MessageBodyReader
    //

    @Override
    public boolean isReadable(final Class<?> type, final Type genericType,
                              final Annotation[] annotations, final MediaType mediaType) {
        return true;
    }

    @Override
    public Object readFrom(final Class<Object> type, final Type genericType,
                           final Annotation[] annotations, final MediaType mediaType,
                           final MultivaluedMap<String, String> httpHeaders,
                           final InputStream entityStream) 
                throws IOException, WebApplicationException {
        try {
            final Input input = new Input(entityStream);
            final Object object = kryoPool.run(new KryoCallback() {
                public Object execute(Kryo kryo) {
                    return kryo.readObject(input, type);
                }
            });
            input.close();

            return object;
        } catch (Exception e) {
            throw new WebApplicationException(e);
        }
    }

}

Test environment

Each test application was executed using Grizzly HTTP Server, no servlet container, on 4 core VM. And load has been produced from another 2 client VMs using wrk - a HTTP benchmarking tool. GET, POST and PUT HTTP methods was measured. It is necessary to say each test works just with one instance of Person entity. It means data load is small. Test's focus is on throughput measurement. 

Test results

Following table shows number of requests per second for each tested provider and mentioned HTTP method:

GETPOSTPUT
XML (JAXB RI)217051131612080
JSON (Jackson)220971859020116
Kryo215331837121304
Custom215431888420442
TEXT (String)218161769519882


Conclusion

Please note the Kryo provider is not in production quality. It just demonstrates how simple it is to enhance JAX-RS runtime to support new entity media type. However it is naive implementation of message body provider it provides very good performance. Kryo also support class registration and compression features that can also affect performance.

And finally, test applications work just with one instance of entity (Person). I guess Kryo could show it's power while working with more complex objects or with collection of them. And Kryo compression feature would be very strong in such case. Maybe I could prepare such test in couple of next months. ;-)

March 11, 2015

JAX-RS Client API Groovy DSL, prototype

Groovy language is DSL friendly language.  See http://groovy-lang.org/dsls.html or http://groovy.codehaus.org/Writing+Domain-Specific+Languages.

Let me share with you my JAX-RS Client API Groovy DSL prototype, code is available in GitHub https://github.com/shamoh/jersey-groovy repo. It just supports GET and POST methods. This is really just concept prototype. But it shows power of Groovy and way how simplified JAX-RS Client API could look like.

The GitHub repository contains couple of unit tests to show the DSL. And also uses Spock Framework what is another Groovy DSL example, in this case as testing framework/API.

Examples

GET plain text, no parameters

JAX-RS Client API:
WebTarget target = ClientBuilder.newClient().target(RESOURCE_URL)
def response = target.request(TEXT_PLAIN_TYPE).get(String)
response == "Hello World!"
Jersey Groovy DSL:
def response = GET[RESOURCE_URL].text
response == "Hello World!"


GET plain text, path parameter

JAX-RS Client API:
WebTarget target = ClientBuilder.newClient().target(RESOURCE_URL)
def response = target.path("Jersey").request(TEXT_PLAIN_TYPE).get(String)
response == "Hello Jersey!"
Jersey Groovy DSL:
def response = GET[RESOURCE_URL/"Jersey"].text
response == "Hello Jersey!"


GET XML, path parameter

JAX-RS Client API:
WebTarget target = ClientBuilder.newClient().target(RESOURCE_URL)
def response = target.path("Jersey").request(APPLICATION_XML_TYPE).get(Message)
response instanceof Message
response.greeting == "Hello Jersey!"
Jersey Groovy DSL:
def response = (GET[RESOURCE_URL/"Jersey"] & APPLICATION_XML_TYPE) as Message
response instanceof Message
response.greeting == "Hello Jersey!"


POST plain text, response text

JAX-RS Client API:
WebTarget target = ClientBuilder.newClient().target(RESOURCE_URL)
def Entity entity = Entity.entity("Jersey", TEXT_PLAIN_TYPE);
def response = target.request().post(entity, String)
response == "Hello Jersey!"
Jersey Groovy DSL:
def response = POST[RESOURCE_URL] << "Jersey" as String
response == "Hello Jersey!"

POST object as JSON, response text

JAX-RS Client API:
WebTarget target = ClientBuilder.newClient().target(RESOURCE_URL)
def Entity entity = Entity.entity(new Message("Jersey", new Date()), APPLICATION_JSON_TYPE)
def response = target.request().post(entity, String)
response == "Hello Jersey!"
Jersey Groovy DSL:
def response = (POST[RESOURCE_URL] | APPLICATION_JSON_TYPE) \
                   << new Message("Jersey", new Date()) as String
response == "Hello Jersey!"

(And finally there is simple slide deck to introduce the DSL API, same examples.)

Enjoy.

JAX-RS Message Body Writer & Reader using Kryo serialization framework


In this post I'm gonna show you how simple it is to enhance JAX-RS application by a new body format. In this example I use Kryo serialization framework.

Kryo serialization framework


Kryo is a fast and efficient object graph serialization framework for Java. The goals of the project are speed, efficiency, and an easy to use API. The project is useful any time objects need to be persisted, whether to a file, database, or over the network.
Kryo can also perform automatic deep and shallow copying/cloning. This is direct copying from object to object, not object->bytes->object.

JAX-RS Message Body providers

JAX-RS allows you to enhance JAX-RS engine to support another body type. There is MessageBodyReader and MessageBodyWriter SPI to be implemented. I have chosen to use application/x-kryo media type for Kryo (de)serialized message bodies.


package cz.kramolis.jersey.kryo;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.MessageBodyWriter;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;

@Consumes("application/x-kryo")
@Produces("application/x-kryo")
public class KryoMessageBodyProvider implements
                        MessageBodyWriter<Object>,
                        MessageBodyReader<Object> {

    //
    // MessageBodyWriter
    //

    @Override
    public long getSize(Object object, Class<?> type, Type genericType,
                        Annotation[] annotations, MediaType mediaType) {
        return -1;
    }

    @Override
    public boolean isWriteable(Class<?> type, Type genericType,
                        Annotation[] annotations, MediaType mediaType) {
        return true;
    }

    @Override
    public void writeTo(Object object, Class<?> type, Type genericType,
                        Annotation[] annotations, MediaType mediaType,
                        MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
            throws IOException, WebApplicationException {
        final ByteArrayOutputStream baos = new ByteArrayOutputStream();

        final Kryo kryo = new Kryo();
        final Output output = new Output(baos);

        kryo.writeObject(output, object);
        output.close();

        entityStream.write(baos.toByteArray());
    }

    //
    // MessageBodyReader
    //

    @Override
    public boolean isReadable(Class<?> type, Type genericType,
                        Annotation[] annotations, MediaType mediaType) {
        return true;
    }

    @Override
    public Object readFrom(Class<Object> type, Type genericType,
                           Annotation[] annotations, MediaType mediaType,
                           MultivaluedMap<String, String> httpHeaders,
                           InputStream entityStream) throws IOException, WebApplicationException {
        try {
            Kryo kryo = new Kryo();
            Input input = new Input(entityStream);
            Object object = kryo.readObject(input, type);
            input.close();

            return object;
        } catch (Exception e) {
            throw new WebApplicationException(e);
        }
    }

}

You can see it is really simple Message Body provider. But I hope it shows you the way...

Than you need to register provider class into JAX-RS Application, e.g.


package cz.kramolis.jersey.kryo;

import java.util.HashSet;
import java.util.Set;

import javax.ws.rs.core.Application;

public class JaxRsApplication extends Application {

    static final Set<Class<?>> APP_CLASSES = new HashSet<Class<?>>() {{
        add(KryoMessageBodyProvider.class);
        add(PersonResource.class);
    }};

    @Override
    public Set<Class<?>> getClasses() {
        return APP_CLASSES;
    }

}


And finally usage of the new body type is very easy:


package cz.kramolis.jersey.kryo;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

@Path("/")
@Consumes("application/x-kryo")
@Produces("application/x-kryo")
public class PersonResource {

    @POST
    public Person echo(final Person person) {
        return person;
    }

    @PUT
    public void put(final Person person) {
    }

    @GET
    public Person get() {
        return new Person("Wolfgang", 21, "Salzburg");
    }

}


Conclusion

Whole sources are available in dedicated GitHub repository. Use it as you need. JAX-RS provides really simple way how to extend it's support. And Kryo is really powerful framework. Give it a try. Look at deeper JVM serializers comparision.

In one of the next blog posts I will provider some performance data comparing Kryo with JSON, XML and others message body providers.

Links