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.

 

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.

HTML5 and Mobile: any real applications

HTML5 is getting pretty capable, especially with extensions on mobile that give it the ability to access mobile device functionality. The question is: is this all academic/niche or are there some real apps out there using it? How do HTML5 apps stack up against native apps?

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();
    }

1-year-old thinks a magazine is a broken iPad

MySQL and Index Woes

I have often noticed that altering indexes on large tables in MySQL is a very time consuming process. I’d chalked it up to “just how things are” and account for that when doing database migrations. Possibly because I’d usually *add* an index on the table not drop it.

But apparently there there is a design flaw in MySQL 5.0 and before with respect to how it handles indexes that caused dropping indexes on tables very slow, and also adding a new index on the table slower than it needed to be. Gory details here: http://bugs.mysql.com/bug.php?id=2364

But in 5.1, at least dropping table ought to be near instantaneous. Adding an index? Umm… it seemed the old behaviour was:

Given the same MyISAM table T having four indexes (ndx1,ndx2,ndx3,ndx4)
and you want to ‘alter table T add index ndx5 (…);’ here is exactly
what happens (from: http://lists.mysql.com/mysql/202489)

1) MySQL copies T.MYD to a temp table, i.e., S.MYD and a zero byte S.MYI.
2) MySQL does ‘alter table S add index ndx1 (…);
3) MySQL does ‘alter table S add index ndx2 (…);
4) MySQL does ‘alter table S add index ndx3 (…);
5) MySQL does ‘alter table S add index ndx4 (…);
6) MySQL does ‘alter table S add index ndx5 (…);
7) MySQL deletes T.MYD and deletes T.MYI
8) MySQL renames S.MYD to T.MYD, and renames S.MYI to T.MYI

Note that each of the “alter table” step involves copying the table to a temp table with no indexes, applying all existing indexes one by one, and then applying the new index…. so in the above case:

In fact, for table T with no indexes and you want to add N indexes
MySQL will copy the MYD N times
MySQL will copy the MYI N times
MySQL will run ‘alter table add index’ N(N+1)/2 times if adding an index
MySQL will run ‘alter table drop index’ N(N-1)/2 times if dropping an index

So here is a better way to add indexes to a table:

1) create table T1 like T;
This creates an empty table T1 with indexes ndx1,ndx2,ndx3 and ndx4.
2) alter table T1 drop index ndx3;
This drops index ndx3 on the empty T1, which should be instantaneous.
3) insert into T1 select * from T;
This will populate table T and load all three(3) indexes for T1 in one pass.
4) drop table table T;
5) alter table T1 rename to T;

Starhub MaxOnline and speedtest.net

I have a Starhub MaxOnline Premium connection. Ostensible it provides a download speed of upto 30Mbps. I am happy to pay the extra price for the increased bandwidth. But am I getting more bandwidth for muy money? How much more?

Continue reading

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!

Buttons that don’t look like buttons: a rant on usability

As part of work, I recently was installing and configuring an open source
software. I was in a big hurry to get something done. This software was
a helper program; it did something awfully nice and useful and which
would make “disciplined” programmers jump with joy. But I was not
jumping with joy. I had something to get done. I needed this software,
but I was not prepared to delve deeply into it. I did not want to learn
too much about it. I just needed it to work, bare minimum, no fancy
stuff, so that I could get on with writing my code.

I suppose I was mentally prepared to fight the software. If it actually
was performing such a nice and useful function, it ought to be
complicated and self-important. “Read my README”, I imagined it
saying. “Then read the INSTALL.txt, and Getting Started, and then
Adminstrator’s Guide…”. I was hoping to wing it. I’d try to start
it, see what broke, try to configure that, see what else broke, try to
fix that, and so on until I won and the software lost the game of
Yet-Another-Installation-Nightmare.

My fears turned out to be grounless.
Installing it was a breeze. One just unpacked the
software and ran a start script. All dependencies were already included
so I did not have to hunt down any. It just started up, presenting a
web-based management UI. It was already configured with sensible
defaults to get a new user up to speed quickly. Wow!

My next step was to create a user account. I brought up the web
management console in firefox. I clicked on the “Users” link, and was
presented with a list of existing user accounts. I could not see how
to create a new user
. I could see how to attach users to roles, I
could see how to search for users using their name, role, email etc.
But for the life of me I could not figure out how to create a new
user account.

When I was just about to admit defeat and turn to the “User Manual”, the
answer jumped out of the page and smacked me in the forehead. There it
was, clear as day, a button labeled “Create New User”. I had been
staring at various links and trying everything on that page, expecting
that this step would be as easy as the install part was, and getting
slightly annoyed that it wasn’t. I had been clicking at everything but
this button. In fact, I had given this button a good long stare and
looked around it to find a link that I could click.

Had my brain suddenly turned into putty? What is so hard about clicking
a dar***d button?

There is nothing hard about clicking a button. Except that the button
in question did not look like a button. The button looked like a
flat, light gray box. When I hovered the mouse over the box, the cursor
did not change into something that indicated “click me”. Basically,
someone had gone out of their way to create a CSS style that made
the button obscure.

Why?

Because it looked “better”? Because it was there to be styled? Just
because? Beats me. The point is that this beautifully useful and easy
to setup software had a GUI blooper right there in the management
console on one of the most commonly used functions. In other words,
this very useful software, which was insanely great in so many other
ways, had a usability issue.

Same day. Another web page. This was a commercial web site that served
up search results arranged alphabetically. There was a nice, helpful
row of navigation links at the top, labeled “A”, “B”, and so one all the
way to “Z”, to allow the user to see results starting with that lette.
The letters were surrounded in a nice, colored box that became highlighted
when your mouse hovered over the box.

So I moused over to the box containing “P” and when it was highlighted,
I clicked.

Nothing happened.

So I double-checked and found that while the box gets highlighted when
your mouse hovered over it, only the letter itself was clickable, not
the box. The “target area” presented by the letter is significantly
smalled than the box, forcing you to be precise about where you click.
There might as well not have been any box. In fact, the box was
downright misleading. It looked good. But it lulled my busy brain into
trying to click something that was not clickable. Another usability
issue
.

Usability has been on my mind recently. (Gee, can you tell?). It is
amazing that there is so much software and so many websites out there
with small, niggly usability issues that are sucking away seconds,
minutes or hours of their users life as they grumpily are trying to get
their jobs done. It is sad, really. The code is there. It works. But
the path to executing that code is strewn with brambles and thickets of
usability issues.

Programmers need to pay attention to the usability of their UIs. Most
books, tutorials and manuals focus on making the UI look good, but few
point out how to make the UI more usable. Most people don’t read the UI
design guidelines of the platform they are working on. And there are
probably no standard guidelines for designing for the web. Web
technologies are changing too fast anyway for any technology focused
guidelines to remain relevant for long. The core principles are taught
in the discipline of Interaction Design. But I don’t think many people
know what Interaction Designers do. I myself didn’t until very
recently.

There really ought to be more interaction designers out there and they
ought to have more work. Programmers and managers should be paying
attention to the usability of their software and its interface.

But for now, I am too busy slapping together functionality to pay
due attention to how it will end up getting used. Oh, I think about
this issue and try to do something about it, for sure. I try to design
the software, imagining the end user and his/her goals in mind.

But that is not enough. User interviews, mock-ups, usability testing
are some of the tools that are involved in producing usable software. I
did not budget for it; I did not set up any time for it. And I wonder
if anyone would understand me if I told them I wanted to take a flight
to meet our users (internal business folks) and do a usability testing.

Or maybe they would. One of these days, I am going to try.

CPU consumption by idle JVM and how to reduce it

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