Matt RaibleMatt Raible is a Web Architecture Consultant specializing in open source frameworks.

10+ YEARS


Over 10 years ago, I wrote my first blog post. Since then, I've authored books, had kids, traveled the world, found Trish and blogged about it all.

My Experience with Java REST Frameworks (specifically Jersey and CXF)

Recently I was tasked with developing a server-side REST strategy for a client. When I started working with them, they were using GWT RPC for exposing services. They wanted to move to RESTful services to allow for a more open platform, that multiple types of clients could talk to. There were interested in supporting SOAP and GWT RPC as well, but it wasn't required. They are using Spring, a custom namespace (for easily creating remote services) and an HTML documentation generator to expose their API in human readable form.

When I first starting developing, I chose to try Enunciate. From Enunciate's homepage:

Enunciate is an engine for creating, maintaining, and deploying your rich Web service API on the Java platform. If that sounds complicated, it's not. All you have to do is define your service interfaces in Java source code. ... Then invoke Enunciate.

Sounds pretty sweet, eh? At first glance, the things I liked about Enunciate were:

  1. The ability to generate multiple endpoints (and clients).
  2. Generates nice-looking documentation.
  3. Allows selecting different frameworks (for example, CXF instead of JAX-WS RI).

Initially, the hardest part of using Enunciate was integrating it into my project. This was somewhat related to having a multi-module project, but moreso related to getting the settings right in my enunciate.xml file. After getting everything working, I encountered a few Spring wiring issues with the GWT Endpoints and with Jersey's Spring support.

The good news is I believe most of these issues were related to my project and how it proxies Spring beans that Jersey couldn't find. Jersey's Spring support only supports annotations at this time, so I was unable to tell it the proxied bean names via XML (or even its own annotations). I'm sure this problem is solvable, but after struggling with it for a day or two, I decided to give up on Enunciate. I had to get something working, and fast.

At this point, I was back to the drawing board. I knew there were plenty of good Java REST frameworks available, but Spring and CXF (for SOAP) were already available dependencies in my project, so I chose that route. I was able to get something up and running fairly quickly with this tutorial and CXF's JAX-RS documentation. I ran into an Invalid JSON Namespace issue, but was able to solve it by adding a custom namespace.

It's not all rosy though, there are still a couple CXF issues I haven't solved:

While CXF does take a bit of XML for each service, it's kinda slick in that it only requires you to annotate your service interfaces. It also generates documentation for your services (WSDL and WADL), but it's not as pretty as Enunciate's. To solve this, I added Enunciate for documentation only. To make Enunciate work, I did have to add some annotations to my service implementation classes and parse the generated HTML to fix some links to CXF's services, but ultimately it works pretty well.

In the end, I recommended my client not use Enunciate for generating endpoints. This was primarily related to their unique Spring configuration, but also because I was able to easily use the same classes for REST, SOAP and GWT Endpoints. However, I will continue to keep my eye on Enunciate. It could be very useful for the upcoming appfuse-ws archetype. I'm also eager to see better GWT support and the ability to generate Overlay types in future releases.

Posted in Java at Aug 27 2009, 02:20:51 PM MDT 15 Comments
Comments:

I also played around with exposing RESTful Web Services - although - in my case project design is completely up to me and I don't have any existing dependencies - as it's a new project.

The server side with jersey was quite straightforward and I liked it. On the client side my first obstacle is using query parameters - here is a sample:

        ClientConfig config = new DefaultClientConfig();
        Client wsClient = Client.create(config);
        MultivaluedMapImpl queryParams = new MultivaluedMapImpl();
        queryParams.add("view", "detail");
        WebResource req = wsClient.resource("http://localhost:8080/TestWebService/resources/generic");
        ClientResponse response = req.path(item).accept("application/json").get(ClientResponse.class);
        return response.getEntity(String.class);

I couldn't get the queryParams added to the request and further I really dislike the approach

req.path(item).accept("application/json").blablabla().blablal().get(ClientResponse.class);

Why not something like

req.setPath(item);
req.setAccept("application/json");
req.setQueryParams(queryParams);
ClientResponse response = req.get(ClientResponse.class);

Posted by Martin Wildam on August 28, 2009 at 01:55 AM MDT #

Many Thanks, Matt, for sharing your Spring+CXF journey, very helpful!

I was wondering what your expierences are regarding exposing domain objects as JSON/XML structure. When you are in control of the client code you can of course couple it a bit more tightly, but otherwise (and allowing to evolve the services long-term) wouldn't a "DTO" make sense? Do you have any recommendations on expressing this with CXF? Using versioning schemes for your services?

Cheers, Niko

PS: I very much like your approach in contributing back to the community and projects while on the journey exploring new technologies.

Posted by Niko Schmuck on August 28, 2009 at 02:45 AM MDT #

I've finished a RESTful project using Glassfish(Jersey) , Apache HttpClient, XStream for domain object to/from XML and Swing based client.

It was a quite interesting experience.

Posted by Kenneth on August 28, 2009 at 04:40 AM MDT #

Hey, thanks for mentioning the XStream - didn't know that and it looks awesome easy - I like such libraries.

Posted by Martin Wildam on August 28, 2009 at 04:56 AM MDT #

Hi. I decided to give Resteasy a try. Being a JBoss subproject that offers a straight forward spring integration and it's quite well documented.

I am not sure, whether endpoints can be declared as xml. The web service endpoints are annotated:

   @GET
    @Produces({"application/xml", "application/json"})
    @Path("{id}")
    public Response getAd(@PathParam("id") Long id,
            @QueryParam("fields") String aliasCSVs) { ... }

So far I came across two major issues with this framework.

  • Resteasy does not honor the the requested encoding.
  • I stumbled across a json namespace issue, too.

Posted by Lars Behnke on September 07, 2009 at 02:27 AM MDT #

I have a current project where I need to provide a web service - or better: I need to implement a service oriented architecture for converting a file. One of the challenges is that I need to post some header data and then the file.

After "playing around" with some of the libraries I could use when using a full application server stack I wonder if is not the fastest way (which is either "K.I.S.S. compliant") to just implement it on my own.

I decided to (for this particular project) throw the application server and all the frameworks and libraries to the fishes. I started to implement it the plain old net way. Simple TCP protocol definition a little similar to the very well spreaded SMTP protocol. And I have full control. - And no long waiting for a startup process of the application server.

I think that if I decide to use frameworks and so on, I would have more problems in overcoming the bugs and limitations than implementing it on my own.

I know there are some nice-to-haves using Jersey (or RESTeasy or whatever) and I am sure there are plenty of projects where it makes sense, but somehow I find it a little like the XML hype years ago - it was used in plenty of cases where it was not adequate.

Posted by Martin Wildam on September 07, 2009 at 03:17 AM MDT #

I looked at CXF, Jersey and RESTEasy and chose RESTEasy for 1) small footprint 2) concise documentation with examples. I did not need SOAP endpoint. The largest issue I've encountered had to with serializing/deserializing objects to/from JSON. JAXB wasn't doing it for me so I used json-lib for expicit control over Java <-> JSON flow so RESTEasy was only involved in dealing with REST issues.

Posted by Ken Brown on November 12, 2009 at 10:04 AM MST #

The best solution I have found to the horrible JSON produced by JAXB in JAX-RS is the Provider from the Jackson JSON library. Here's a post about it: http://www.cowtowncoder.com/blog/archives/2009/03/entry_229.html

Posted by Tom McGee on November 12, 2009 at 10:34 AM MST #

@Tom - I agree. We've switched from CXF's default JSON Provider (Jettison) to Jackson and are very happy with the results so far.

Posted by Matt Raible on November 12, 2009 at 10:41 AM MST #

Have you considered any options of restful client libraries with GWT?

Posted by Tom McGee on November 12, 2009 at 10:46 AM MST #

Matt, any reason you didn't include RESTEasy in your analysis? We have a pretty strong community and a bunch of people and well known companies using it.

Posted by Bill Burke on November 12, 2009 at 11:09 AM MST #

@Lars I think we've fixed the encoding issues. @Lars and @Ken: As far as the json namespace issues, this is more a problem with Jettison than anything else. I suggest using the Jackson plugin. I may even deprecate Jettison support as I believe Jackson supports JAXB annotations now.

Posted by Bill Burke on November 12, 2009 at 11:24 AM MST #

Matt, any reason you didn't include RESTEasy in your analysis?

No reason in particular, except that I was originally trying to use Enunciate and it didn't have RESTEasy support.

Posted by Matt Raible on November 12, 2009 at 11:33 AM MST #

There is this small, clean and simple REST-compatible web framework called Taimen that I am designing:

http://code.google.com/p/bitumenframework/

Your feedback is most welcome.

Posted by Shantanu Kumar on November 13, 2009 at 02:54 AM MST #

Could you please let me know if you know any good architecture that support

EXTJS front-end

and a

SOAP-based WS in the backend ?

I'm required to write a brand-new UI using Ext JS that would calls an existing SOAP WS .

I have tried EXT JS with REST before, and it's easily done. But given an existing SOAP layer to plug into EXT JS , I don't have a good architecture in hands.

Please let me know .
Thank you

Posted by tho dinh on November 13, 2009 at 12:45 PM MST #

Post a Comment:
  • HTML Syntax: Allowed