Tag Archives: java

JAX-RS resources in JAR files: how to use CDI to register it with the JAX-RS runtime

Imagine you are creating a JAX-RS resource called Resource, and bundling it into a JAR called resource.jar, as a reusable service.  A developer creating a WAR would use your JAR in WEB-INF/lib, ensure that the JAX-RS runtime is started, and the resource would be detected and exposed, right?

No, sadly, the JAX-RS runtime will not automatically be able to find resources from within JARs without some help. CDI to the rescue!

If we annotate our JAX-RS class with a CDI annotation, such as @ApplicationScoped or @RequestScoped, and include a beans.xml in our JAR, then CDI will inspect our JAR, register our resource as a CDI managed bean, and — as a side effect — also register our resource with the JAX-RS runtime.

If you don’t use this method, then the developer of the WAR has to do a little bit more work. He/she will have to write a javax.ws.rs.core.Application subclass and implement either the getSIngletons() or getClasses() method and mention our resource class explicity in there, in order to let JAX-RS runtime know about the Resource class.

By using CDI, we can make the life of a resource user—the developer of the WAR—easier.

 

Advertisements

Java EE 6 and modular JAX-RS services

Problem Statement

I often create custom web applications to support mobile products that have a few functions in common. For e.g., many web applications need to let users authenticate themselves from a mobile application. These functions are exposed to the mobile applications using a RESTful API. I’d like to create re-usable bundles of these services and add as many or as few of them as needed to my custom web application and write as little integration logic as possible, focusing all my time on the custom business logic of the product being developed.

Here is a “note-to-self” primer on how to go about bundling JAX-RS services in a jar and then using them from a war.

I assume that the projects are built using Maven and that they are being deployed to a Java EE 6 app container.

The REST API and the jar

Let’s create a jar project called resource (I assume you know how to create a jar using Maven).

The JAX-RS API dependency

First let’s get our dependencies lined up. Our code will refer to the JAX-RS APIs at least. The APIs are provided by the app container, so our dependency will be in the provided scope. The only question is, what GAV (groupId-artifactId-version triplet that uniquely identifies a dependency in Maven) vector to use?

Typical web applications have this in their pom.xml:

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

but I prefer dependencies from apache geronimo project instead (because the above dependency cannot be used in unit tests and does not allow me to download javadocs):

        <dependency>
            <groupId>org.apache.geronimo.specs</groupId>
            <artifactId>geronimo-jaxrs_1.1_spec</artifactId>
            <version>1.0</version>
            <scope>provided</scope>
        </dependency>

For illustration, we shall create a JAX-RS based REST API to manage a simple entity. For simplicity we shall not bother about where this entity is stored, retrieved from etc.

Here is my entity class:

// file src/main/java/net/nihilanth/demo/resource/GenericEntity.java
package net.nihilanth.demo.resource;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class GenericEntity {

    private long id;
    private String name;

    // getter, setters and constructors omitted
}

Note the @XmlRootElement annotation. This is needed so that I can marshal my entity to/from XML. It also automatically allows me to marshal it to/from JSON. If I were not using XML but only JSON, I’d still keep this annotation just because it easily lets me marshal my entity to/from JSON.

And I expose this as a REST resource:

// file src/main/java/net/nihilanth/demo/resources/GenericResource.java
package net.nihilanth.demo.resource;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.ws.rs.*;

@Path("/generic")
public class GenericResource {
    private long nextId = 1;

    // in lieu of a database, we shall retrieve entities from a list
    List<GenericEntity> list = new ArrayList<GenericEntity>();

    // we create a few instances so that we can see something in our tests
    // in real life you'd have code to retrieve entities from a database etc.
    public GenericResource() {
        createEntity(new GenericEntity("alpha"));
        createEntity(new GenericEntity("beta"));
        createEntity(new GenericEntity("gamma"));
    }

    @POST
    @Consumes("application/json")
    public String createEntity(GenericEntity entity) {
        entity.setId(nextId);
        nextId++;
        list.add(entity);
        return "" + entity.getId();
    }

    @GET
    @Produces("application/json")
    public List<GenericEntity> list() {
        return Collections.unmodifiableList(list);
    }
}

And that’s all that is needed. I now compile and “install” the jar in my local repository (or eventually, publish to our corporate maven repository). I can’t see my REST API in action yet: I have to create a web application that uses my JAR first.

The web application

Let’s create a war project called, simply, webapp.

The JAX-RS API dependency and the JAR dependency

I replace the default javaee-web-api dependency put there by Maven with our geronimo based dependency, and also add a dependency to the jar we just created:

<!-- this the pom.xml depedencies section for my war -->
    <dependencies>
        <dependency>
            <groupId>org.apache.geronimo.specs</groupId>
            <artifactId>geronimo-jaxrs_1.1_spec</artifactId>
            <version>1.0</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>net.nihilanth.demo</groupId>
            <artifactId>resource</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

Using our REST API

The JAR we created above is included in our WAR as a dependency. We have to figure out a way to tell the app container to locate our GenericResource from the JAR and publish it. We also have to decide the URL under which the resource will be available. We decide that all our REST resources will be made available under the URL /resources under our context path. To coax the app container to search our JARs and instantiate any REST resources found in them, we create this class:

// file src/main/java/net/nihilanth/demo/webapp/JaxRsApplication.java
package net.nihilanth.demo.webapp;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("/resources")
public class JaxRsApplication extends Application {
}

The exact name and package of the class is not important. It just has to exist in our WAR, and the important thing is that:

  • It extends javax.ws.rs.core.Application, which tell the app container that our WAR contains one or more JAX-RS resources
  • It is annotated with @ApplicationPath annotation, which tells the app container the relative path under which our JAX-RS resources will be available (“resources”, in this case).

And that’s it. We don’t even need a web.xml in this example. Just build and deploy the war to an app container (e.g., glassfish v3). Note:

  • My instance of glassfish is listening on port 8080 (the default). I can thus access my web applications from the URL http://localhost:8080/
  • I have specified nothing special regarding the context path of my web application. By default, therefore, the web application’s context name is the same as my war file name, that is, webapp. Thus I can access my web app at the URL http://localhost:8080/webapp/
  • In the @ApplicationPath annotation I specified that the JAX-RS resources be made available under “resources” URI; thus all my JAX-RS resources are available at the URL http://localhost:8080/webapp/resources/
  • Finally, in my GenericResource class, the annotation @Path specified that this resource in named generic. So the individual methods of the GenericResource will be available under the URL http://localhost:8080/webapp/resources/generic

So let’s give it a spin. Here is here how I list the existing GenericEntity instances from the command line:

$ curl -H 'Accept: application/json' 'http://localhost:8080/webapp/resources/generic'
{"genericEntity":[{"id":"1","name":"alpha"},{"id":"2","name":"beta"},{"id":"3","name":"gamma"}]}

We got the three entities we had pre-prepared. Let’s add a new one:

$ curl -X POST -A 'Accept: application/json' -H 'Content-type: application/json' -d '{"name": "foo"}' 'http://localhost:8080/webapp/resources/generic'
4

There we go! The new entity was added and its new ID, 4, was returned.

Issues

You might have noticed that the return type of the GenericResource.createEntity method is String, even though the underlying data type (the ID of the created entity) is long. Why? Because out of the box, JAX-RS implementations cannot convert long or java.lang.Long to an external media type. If we want to keep the method return type as a primitive type, we shall have to provide our own entity mapper. But that is fodder for another post.

Another issue you might notice is that after creating a new entity, if we try to list all the entities, we get the same three entities back. Our fourth entity is not listed. This is because a new instance of GenericResource is created for every new request. We will fix this issue in a subsequent article.

JAX-WS clients and embedded WSDL files

Search stackoverflow.com for JAX-WS and WSDL and you will see a lot of people asking questions like this:

The problem is i need to build a web service client from a file i’m been provided. I’ve stored this file on the local file system and , while i keep the wsdl file in the correct file system folder, everithing is fine. When i deploy it to a server or remove the wsdl from the file system folder the proxy can’t find the wsdl and rises an error.

The common suggestion to use the “wsdlLocation” command line option or the equivalent maven plugin configuration directive does not work. This suggestion does work though.

Here is a portable way to create a web service client. Say the WSDL file is in the directory “src/main/resources/wsdl/CardValidator.wsdl” (assuming a maven project) inside the project, then the following code can be used to create the web service client and this code will work from inside a war, a jar or even from the exploded classes directory as well:


public class App {

    public void someMethod() {
        URL wsdlURL = App.class.getClassLoader().getResource("wsdl/CardValidator.wsdl");
        QName qname =
            new QName("http://ws.creditcard.jaxws.demo.nihilanth.net/", "CardValidatorService");
        CardValidatorService cardValidatorService =
            new CardValidatorService(wsdlURL, qname);
        CardValidator cardValidator = cardValidatorService.getCardValidatorPort();
    }

Spring Java Config and ProxyFactoryBean

I really like spring remoting. I really like spring java config. Recently I had to marry the two. Here is how.

I have a value-object:

public class Datum
        implements Serializable
    {
    private int id;
    private String name;

    public Datum(int id, String name)
        {
        this.id = id;
        this.name = name;
        }

    public int getId()
        {
        return id;
        }

    public String getName()
        {
        return name;
        }

    @Override
    public String toString()
        {
        return "Datum{" + "id=" + id + "name=" + name + '}';
        }

    }

I have a service that produces Datum objects. The service interface is:

public interface IDatumProducer
    {
    public Datum produce();
    }

and a sample implementation might be:

public class RandomDatumProducerImpl
        implements IDatumProducer
    {
    private static final Logger log =
            LoggerFactory.getLogger(RandomDatumProducerImpl.class);

    private Random rnd = new Random(System.currentTimeMillis());

    @Override
    public Datum produce()
        {
        int i = rnd.nextInt();
        Datum datum = new Datum(i, String.valueOf(i));
        log.info("Produced {}", datum);
        return datum;
        }

    }

Here is a client for the service:

public class DatumProducerClient
    {
    private static final Logger log =
            LoggerFactory.getLogger(DatumProducerClient.class);

    private final IDatumProducer producer;

    public DatumProducerClient(IDatumProducer producer)
        {
        this.producer = producer;
        }

    @PostConstruct
    public void init()
        {
        while (true)
            {
            try
                {
                Datum datum = producer.produce();
                log.info("Got {}", datum);
                Thread.sleep(1000L);
                }
            catch (InterruptedException ex)
                {
                log.error("Interrupted", ex);
                }
            }
        }
    }

Now I want to run the DatumProducerClient and the IDatumProducer on different machines. The client should connect remotely to the producer, invoke the produce method, and do its stuff.

We can expose the service easily using Spring. The spring remoting (JMS) manual section gives the spring configuration XML to do this, but no example for doing this in Java Config. Turns out there is one small detail to take care of when using Java config.

Producer (Server)

Here is the application config for the producer side:

@Configuration
public class ProducerConfig
    {

    @Bean
    public AbstractMessageListenerContainer messageListenerContainer()
        {
        SimpleMessageListenerContainer container =
                new SimpleMessageListenerContainer();
        container.setConnectionFactory(jmsConnectionFactory());
        container.setDestination(jmsQueue());
        container.setMessageListener(jmsInvokerServiceExporter());
        container.setConcurrentConsumers(3);
        return container;
        }

    @Bean
    public JmsInvokerServiceExporter jmsInvokerServiceExporter()
        {
        JmsInvokerServiceExporter serviceExporter =
                new JmsInvokerServiceExporter();
        serviceExporter.setService(datumProducer());
        serviceExporter.setServiceInterface(IDatumProducer.class);
        return serviceExporter;
        }

    @Bean
    public ConnectionFactory jmsConnectionFactory()
        {
        ActiveMQConnectionFactory baseConnectionFactory =
                new ActiveMQConnectionFactory();
        baseConnectionFactory.setBrokerURL("tcp://localhost:61616");
        return baseConnectionFactory;
        }

    @Bean
    public Queue jmsQueue()
        {
        ActiveMQQueue queue = new ActiveMQQueue("dataChannel");
        return queue;
        }

    @Bean
    public IDatumProducer datumProducer()
        {
        return new RandomDatumProducerImpl();
        }

    }

And here is a main method that kicks off our application.

public class PublisherMain
    {
    public static void main(String[] args)
        {
        AnnotationConfigApplicationContext ctx =
                new AnnotationConfigApplicationContext(ProducerConfig.class);
        }
    }

Consumer (Client)

Here is how the consumer is wired up.

@Configuration
public class ConsumerConfig
    {

    @Bean
    public DatumProducerClient datumProducerClient()
        {
        return new DatumProducerClient(datumProducer());
        }

    @Bean
    public IDatumProducer datumProducer()
        {
        // producerFactory.getObject() will return null if we don't define
        // it as a separate bean; if we copy over the code from
        // jmsInvokerProxyFactoryBean here, it won't work: the proxy won't
        // get "enhanced" by spring, and its getObject() method will always
        // return null.
        JmsInvokerProxyFactoryBean producerProxy = jmsInvokerProxyFactoryBean();
        return (IDatumProducer) producerProxy.getObject();
        }

    // We can't fold this code into datumProducer above
    // The proxy bean must be defined separately, otherwise spring won't get
    // a chance to enhance it.
    @Bean
    public JmsInvokerProxyFactoryBean jmsInvokerProxyFactoryBean()
        {
        JmsInvokerProxyFactoryBean producerProxy = new JmsInvokerProxyFactoryBean();
        producerProxy.setServiceInterface(IDatumProducer.class);
        producerProxy.setConnectionFactory(jmsConnectionFactory());
        producerProxy.setQueue(jmsQueue());
        return producerProxy;
        }

    @Bean
    public ConnectionFactory jmsConnectionFactory()
        {
        ActiveMQConnectionFactory baseConnectionFactory =
            new ActiveMQConnectionFactory();
        baseConnectionFactory.setBrokerURL("tcp://localhost:61616");
        return baseConnectionFactory;
        }

    @Bean
    public Queue jmsQueue()
        {
        ActiveMQQueue queue = new ActiveMQQueue("dataChannel");
        return queue;
        }
    }

and here is how the main method on the client side looks like:

public class ConsumerMain
    {
    public static void main(String[] args)
        {
        AnnotationConfigApplicationContext ctx =
                new AnnotationConfigApplicationContext(ConsumerConfig.class);
        }
    }

The important bit to note here is that the JmsInvokerProxyFactoryBean is configured as a bean in its own right. This allows spring to “enhance” it at runtime to do all the proxying for us. If this were not a separate bean, things would not work. For e.g., the following code won’t work:

// Wrong way to use a ProxyFactoryBean
    @Bean
    public IDatumProducer datumProducer()
        {
        JmsInvokerProxyFactoryBean producerProxy = new JmsInvokerProxyFactoryBean();
        producerProxy.setServiceInterface(IDatumProducer.class);
        producerProxy.setConnectionFactory(jmsConnectionFactory());
        producerProxy.setQueue(jmsQueue());
        return (IDatumProducer) producerProxy.getObject(); // Wrong: getObject always returns null
        }

That’s all!

CPU consumption by idle JVM and how to reduce it

http://blogs.sun.com/nickstephen/entry/java_why_does_my_jvm

Concurrency: Erlang vs Java

Its fashionable to extol the high-performance of Erlang concurrency these days. Programming Erlang, Section 8.11, has this problem:

Write a ring benchmark. Create N processes in a ring. Send a message
round the ring M times so that a total of N * M messages get
sent. Time how long this takes for different values of N and M.

Well, I copied off the Java program from here: http://www.sics.se/~joe/ericsson/du98024.html

And then I wrote this Erlang program:

-module(threadperftest).
-compile(export_all).

timeit() ->
register(mainproc, self()),
io:format(" Procs, Mesgs, SpawnTotal, SpawnProc, RunTotal, RunMesg~n", []),
timeit_aux(1000, 1000, 10000),
init:stop().

timeit_aux(NProcs, NMsgs, NProcsMax) ->
if NProcs =
main([NProcs, NMsgs]),
timeit_aux(NProcs+1000, NMsgs, NProcsMax);
true -> void
end.

main([N, M]) ->
{_, _W0} = statistics(wall_clock),
FirstPid = spawn(fun loop0/0),
% io:format("First: ~p~n", [FirstPid]),
LastPid = setup(N-1, FirstPid),
FirstPid ! LastPid,
{_, W1} = statistics(wall_clock),
LastPid ! M,
receive
stop ->
void
end,
{_, W2} = statistics(wall_clock),
io:format("~6B, ~6B, ~10g, ~10g, ~10g, ~10g~n", [N, M, W1*1.0, 1.0*W1/N, W2*1.0, W2*1000.0/(M*N+N)]).

setup(0, PrevPid) ->
PrevPid;
setup(HowMany, PrevPid) ->
Pid = spawn(fun() -> loop(PrevPid) end),
% io:format("~p: Linking to: ~p~n", [Pid, PrevPid]),
setup(HowMany - 1, Pid).

loop0() ->
receive
LinkedPid when is_pid(LinkedPid) ->
% io:format("First: ~p: Linking to ~p~n", [self(), LinkedPid]),
loop1(LinkedPid);
X ->
erlang:error({unknownMessageError, X, self()})
end.

loop1(LinkedPid) ->
receive
M when is_integer(M), M > 0 ->
% io:format("~p: Received: ~p~n", [self(), M]),
LinkedPid ! (M-1),
loop1(LinkedPid);
M when is_integer(M), M =:= 0 ->
% io:format("~p: Received: ~p, Terminating~n", [self(), M]),
mainproc ! stop,
done;
X ->
erlang:error({unknownMessageError, X, self()})
end.

loop(LinkedPid) ->
receive
M when is_integer(M), M > 0 ->
% io:format("~p: Received: ~p~n", [self(), M]),
LinkedPid ! M,
loop(LinkedPid);
M when is_integer(M), M =:= 0 ->
% io:format("~p: Received: ~p, Terminating~n", [self(), M]),
LinkedPid ! M,
done;
X ->
erlang:error({unknownMessageError, X, self()})
end.

The performance is something like this (all times are in milliseconds, except the last one, which is in microseconds):

 Procs,  Mesgs, SpawnTotal,  SpawnProc,   RunTotal,    RunMesg
1000, 1000, 0.00000e+0, 0.00000e+0, 266.000, 0.265734
2000, 1000, 16.0000, 8.00000e-3, 562.000, 0.280719
3000, 1000, 0.00000e+0, 0.00000e+0, 969.000, 0.322677
4000, 1000, 0.00000e+0, 0.00000e+0, 1672.00, 0.417582
5000, 1000, 15.0000, 3.00000e-3, 2469.00, 0.493307
6000, 1000, 16.0000, 2.66667e-3, 3234.00, 0.538462
7000, 1000, 16.0000, 2.28571e-3, 4015.00, 0.572998
8000, 1000, 16.0000, 2.00000e-3, 4750.00, 0.593157
9000, 1000, 31.0000, 3.44444e-3, 5469.00, 0.607060
10000, 1000, 31.0000, 3.10000e-3, 6375.00, 0.636863

The numbers in the RunMesg column are the time it takes to send one message from one process to another. Why is it increasing? Does the runtime have to do more work to find the target process?

Here is the Java output (program below):

 Procs,  Mesgs, SpawnTotal, SpawnProcs,   RunTotal,   RunMesg
100, 1000, 16.000, 0.160, 15531.000, 15.531
200, 1000, 62.000, 0.310, 27047.000, 27.047
300, 1000, 94.000, 0.313, 37828.000, 37.828
400, 1000, 125.000, 0.313, 46859.000, 46.859
500, 1000, 141.000, 0.282, 54578.000, 54.578
600, 1000, 203.000, 0.338, 60594.000, 60.594
700, 1000, 234.000, 0.334, 65282.000, 65.282
800, 1000, 406.000, 0.508, 68156.000, 68.156
900, 1000, 484.000, 0.538, 69782.000, 69.782
1000, 1000, 735.000, 0.735, 70015.000, 70.015

The last column is in milliseconds whereas for Erlang it was in microseconds, AND the number of procs is 100-1000, whereas for Erlang they were 1000-10,000.