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


February 14, 2015

Jersey 2.16 has been released

Jersey team is happy to announce availability of Jersey 2.16.

For an overview of changes, bug fixes, new features and 7 merged GitHub pull requests, please consult Jersey 2.16 Release Notes.

Highlights

JAX-B providers separated from the core

From version 2.16 onwards, all JAX-B providers are being bundled in a separate module.

The main motivation behind that is t allow using Jersey Client on Android. Current status of Android support has been described by Jakub Podlešák in his Jersey 2.x Client on Android blog post.

Performance gain when using Sub-Resource Locators

We improved the performance for using sub-resource locators in an Jersey application. The performance gains are available for cases when the sub-resource locator method returns either a resource class (return value is e.g. Class<?> or Class<MySubResource>) or a (non-proxied) resource instance (when return value is an instance of MySubResource class).

This is described by Michal Gajdoš in more detail in his Performance Improvements of Sub-Resource Locators in Jersey blog post.

Another blog post about is again by Jakub about general Jersey 2 performance improvements.

More unified connector configuration options

Jetty connector and Apache connector have been previously using their own custom properties to set SSL context on a connector. These properties have been deprecated and the code has been updated to read the SSL context information from the JAX-RS client configuration. This means that all Jersey connectors now properly accept SSL configuration as configured via standard JAX-RS ClientBuilder methods.

Previously, all Jersey connectors have been using their own default chunk size when HTTP chunked coding was used. Since Jersey 2.16, there is a new default chunk size value used by all connectors, if a custom chunk size is not set. The new default value is stored under ClientProperties.DEFAULT_CHUNK_SIZE client property.

Links

To download Jersey 2.16, please check our download page.

You can also check out the refreshed Jersey 2.16 documentation:

Other blog posts

Feedback

For feedback send an email to: users@jersey.java.net (archived here)
or log bugs/features here.


January 17, 2015

Reactive Jersey Client using Java 8, RxJava and Netflix Hystrix

In this post I will show you how to use Jersey Client Reactive API, it's RxJava Observable support together with Netflix Hystrix, latency and fault tolerance library. All sources are placed in GitHub jersey--examples--rx-client-java8-webapp project.

Jersey framework contains Reactive Client API. Reactive Jersey Client API is a generic API allowing end users to utilize the popular reactive programming model when using Jersey Client. Reactive programming is very popular these days. It helps you to implement asynchronous code with solved callback hell issue.


Jersey

Jersey supports RxJava ObservableJava 8 CompletionStage and CompletableFutureGuava ListenableFuture and FuturesJSR-166e CompletableFuture. It also provides SPI to be extended by custom reactive libraries.

There is excellent 3 part blog post series written by Michal Gajdoš about Reactive Jersey Client:
  1. Reactive Jersey Client – Motivation
  2. Reactive Jersey Client – Usage and Supported Reactive Libraries
  3. Reactive Jersey Client – Customization (SPI)

Jersey source code contains also examples for supported reactive libraries, see modules:


Hystrix

Hystrix is a latency and fault tolerance library designed to isolate points of access to remote systems, services and 3rd party libraries, stop cascading failure and enable resilience in complex distributed systems where failure is inevitable.

You usually use Hystrix to isolate dependent system call into HystrixCommand class. It allows to be executed synchronously, asynchronously (returns java.util.concurrent.Future) and also asynchronously via RxJava Observable.

Code

In case dependent system already supports RxJava Observable API you can use specific HystrixObservableCommand class. And thanks to Jersey Reactive Client API and its RxJava support it allows us to write resilient JAX-RS client code.

private class ForecastCommand extends HystrixObservableCommand<Forecast> {
    private final Destination destination;
    ...
    @Override
    protected Observable<Forecast> run() {
        return RxObservable.from(forecastWebTarget)
                .resolveTemplate("destination", destination.getDestination())
                .request().rx()
                .get(Forecast.class);
    }
    @Override
    protected Observable<Forecast> getFallback() {
        return Observable.just(new Forecast(destination.getDestination(), "N/A"));
    }
}

The code above creates new Hystrix RxJava Observable ready Command that invokes remote REST API using Jersey Reactive Client API. Whenever API call fails or times out a getFallback() method is invoked. And in this case we return Forecast instance with N/A forecast value.

Whole example web application enhanced by code using Hystrix is placed into my GitHub jersey--examples--rx-client-java8-webapp repository. Shown and little but simplified code snipped is from HystrixObservableAgentResource class. The example module is clone of rx-client-java8-webapp.

To run the example:
    mvn clean package jetty:run

At beginning of HystrixObservableAgentResource class there are TIMEOUT_* constants. You can play with values and you will see that sometimes you don't get all domain objects' values and sometimes you see default values (N/A for Forecast and -1 for Calculation). You can also play with Thread.sleep intervals but because of Hystrix timeout support the overall JAX-RS resource method processing time is never (too much) longer than TIMEOUT_OVERALL (currently 900 ms).

You can also check unit test RxClientsTest. Processing time is expected between 850 and 950 ms!


Links





November 18, 2013

How to configure JDK logging for Jersey 2 tests

Jersey uses JDK Logging API to log messages.

One way how to configure JDK Logging is a properties file. In such case you have to set JVM system property java.util.logging.config.file to reference the properties file.

Initially the logging configuration file logging.properties can look:

#All attributes details
handlers=java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.level=FINEST
java.util.logging.SimpleFormatter.format=%4$-7s [%3$s] %5$s%6$s%n

#All log level details
.level=INFO
org.glassfish.jersey.level=CONFIG
org.glassfish.jersey.tracing.level=FINEST

The configuration explained:

  • handlers=java.util.logging.ConsoleHandler - log messages are written to System.err
  • java.util.logging.ConsoleHandler.level=FINEST - allow to log FINEST message;
    default is INFO so more detailed messages are suppressed by default
  • java.util.logging.SimpleFormatter.format - example of simple and single line format - just level, logger name and message;
    Note: It just works with Java 7.
  • org.glassfish.jersey.level=CONFIG - example of per-package level configuration;
    log all SEVERE, WARNING, INFO and CONFIG level Jersey messages
  • org.glassfish.jersey.tracing.level=FINEST - example of detailed level configuration of specified package
And as mentioned it is necessary to set system property java.util.logging.config.file. Do you want to see log messages during unit testing (e.g. using maven)? There are two options:

  • run tests in new JVM instance (fork option) and configure the system property in such maven plugin
  • enhance maven command line parameter and add the
    -Djava.util.logging.config.file=... property

For example, run test application using Jetty server for test module tracing-support:

~/jersey2/tests/integration/tracing-support$ mvn compile jetty:run -Djava.util.logging.config.file=src/test/resources/logging.properties

-that's all folks