Thursday, February 26, 2009

CXF JAXRS Client API updates

We've been working on improving the initial Client API prototype we had added to CXF. Particularly, the goal was to tap a bit into a powerful CXF core runtime which gives us interceptor chains and a highly optimized HTTPConduit.

I was overwhelmed with how many options CXF JAXWS client runtime had for all sorts of invocations, asynchronous ones, one ways, synchronous ones with retries, automatic processing of cases where a destination has been moved to a new address, secure HTTPS invocations, etc. So CXF JAXRS client runtime will eventually end up being as flexible and configurable as its JAXWS 'brother' (hopefully, if you're completely into REST then this analogy does not shock you too much :-)).

With CXF 2.2 coming out soon I didn't have time to update the CXF JAXRS client code to do all the things CXF JAXWS can do - this will gradually be done later on. But few key things have been done, mainly it's now possible for both proxy and http-centric CXF JAXRS clients to transparently pick up the CXF Bus configuration, rely on the HTTPConduit which deals with all the complicated HTTP stuff (chunking, http proxies, timeouts, etc), as well as custom outbound and inbound CXF interceptors.
One interesting thing about it is that you can now basically reuse in certain cases, say, secure JAXWS and JAXRS proxies (with the HTTPS-related configuration being picked up from Spring) and you can always find out what type of proxy you're dealing with :



BookService jaxwsService = ...
BookService jaxrsService = ...
useBookService(jaxwsService);
useBookService(jaxrsService);

if (WebClient.client(jaxwsService) == null) {
// it's a jaxws client
}



For example, see this JAXRS HTTPS test which does a secure invocation with both proxy and http-centric clients. Note how straightforward it is. Actually that needs to be simplified, with a CXF Bus creation code to be pushed into a JAXRSClientFactoryBean - but you can do it right now by simply passing a command line CXF property pointing to a configuration code with the bus creation code becoming redundant.

The actual simple configuration is here, it configures both client and server sides.

Another interesting thing is that we can now inject JAXRS proxies into the server service code, be it JAXWS or JAXRS one. For example, have a look at this test resource class which can serve both JAXRS and JAXWS invocations. JAXRS proxy is injected like this :


public class BookStoteSoapRestImpl {
@Resource(name="rectClient")
private BookStoreJaxrsJaxws webClient;
}


and then it's used inside a getBook() method, irrespectively of whether it's a jaxws or jaxrs invocation which is inderway, by invoking the same method :


public class BookStoteSoapRestImpl {
public Book getBook(Long id) {
// if it's not a recursive invocation then
webClient.getBook();
}
}


Now the invocation goes over HTTP in this case but we'll add the support for local transport invocations too.

Please check this configuration sample on how a jaxrs:client is configured. Among other things you can setup all the headers which need to flow, plus input/output interceptors and whether subresource proxies if any need to inherit the headers. I'll also add a support for a basic autorization here as opposed to doing it at the Client level, as one really needs to do it in combination with HTTPS.

You can also inject jaxws:clients into your JAXRS endpoints if you wish. REST and SOAP united indeed.

So that's what happening with CXF JAXRS Client API. More enhancements will be done to it, to its proxy, http- and xml-centric parts and the way it integrates with the core runtime.

Stay tuned.

CXF JAXRS in Camel

My colleague William Tam has spent some of his time on Camel providing the support for CXF JAXRS consumers, which is much appreciated.

The way William did it is very nice in that JAXWS will eventually be supported too, using the same high-level route definition. What is also good is that no strange queries like ?httpverb=POST will have to specified in routes, as in case of other Camel components consuming HTTP requests.

Here's a basic example (courtesy of William) :

from("jetty:http://localhost:9000?matchOnUriPrefix")
.to("cxfbean:serviceBean")

where 'serviceBean' is an identifier for a resource class bean under which it's also been registered in a Camel service registry.

With CXF 2.0 being released soon we have a client api support coming out too, which will make it possible to add cxf jaxrs producers calling out to external services, we'll make sure it goes into a Camel 2.0 final release.

I'd encourage someone from a Mule community to add support for CXF JAXRS routes too, perhaps by combining it somehow with the existing Mule CXF JAXWS routes.

Thursday, February 19, 2009

FAQ : Why CXF implements JAXRS

A number of people have asked us why, or why, do we spend the time on implementing JAXRS in CXF, despite the brilliance of existing third-party implementations, with all the resources and big names support behind them.

The answer is quite simple actually. We're not hell-bent on trying to emulate what others have done, nor are we into some kind of JAXRS 'battle' - not yet anyway. We aim for a 'simpler' goal which is to make sure CXF is seen as the best of breeds platform for developers writing web services. We won't tell them they have to write REST services - we'll trust their choice and ensure CXF will handle most demanding requirements, whether it SOAP, REST or both.

CXF is being recognized now as a top platform for writing SOAP services - highly optimized, tried and tested. There were times it was beginning its life with writing JAXWS from scratch and people, myself including were asking why. It was quite a bit of time ago though, and no one asks such questions any more. CXF JAXWS is just going to get stronger, it' s happening every day. IONA trusted in those few involved in the early CXF work to pull it off and that trust payed off.

So here we're, tinkering with the CXF JAXRS implementation. Odds are not that terrific for now but we'll persevere and see what happens. We continue trust in our experience and we'll get to the final destination eventually. And when we do we won't mind if a fledgling CXF JAXRS will get off the ground on its own...

The bottom line is that we do see JAXRS as a very important technology for CXF. CXF is not a pure SOAP stack anymore. It's a progressive framework where all sorts of services will coexist.

Have fun

Friday, February 13, 2009

CXF JAXRS Client API Preview

We've worked very hard recently on prototyping the client API for CXF JAXRS. We've tried our best to come up with something which will offer at least something new. It has not been easy but hopefully you'll acknowledge some differences. So without further ado here's the first overview of the CXF JAXRS Client API.


The proxies : design your resource classes and use them everywhere.

Proxy-based API is very familiar to CXF JAXWS users. As I've mentioned a number of times before it's our top priority to ensure JAXWS users can start playing with RESTful services similarly to how they do it with SOAP services. I can already hear people saying - sure, that RPC stuff is here again - but hold one please, proxy-based API can be made quite robust and I will dedicate a separate post to the comparison of different forms of client API that CXF JAXRS supports and talk about their pros and cons. And you know what, CXF JAXRS proxies are http-centric too. So here are some examples for a start.


ProviderFactory.getInstance().register(
new ResponseToBookNotFoundMapper());
String base = "http://localhost";
BookInterface bp = JAXRSClientFactory.create(base,
BookInterface.class);
try {
Book b = bp.getBook(123);
} catch (BookNotFound ex) {}
BookSubresource bs = b.getSubresource(1, 2);
bs.getBooks();



BookInterface and BookSubresource are proxies created by JAXRSClientFactory. You've already spent some time designing your service resource classes - no need to do it again for a client side. Proxies 'navigate' with the help of JAXRS annotations and do the remote invocations. The power of UriBuilder makes the replacement of URI template variables along the way quite straightforward really. All the JAXRS parameter annotations are handled such that the receiving end will work as expected : path, query and matrix parameters will find its way into a resulting URI while HttpHeader and Cookie will go to request headers.

The values will be encoded by default unless Encoded annotation is available - if you do plan to decode yourself then it's reasonable to expect you encode yourself in such cases.

FormParams and MultivaluedMap parameters are handled like any other parameters representing a request body - they're serialized with the help of JAXRS MessageBodyWriters. Likewise, return values are handled by JAXRS MessageBodyReaders.
Registered ResponseExceptionMappers will be given a chance to handle exceptional JAXRS Responses, othewise JAXRS WebApplicationException containing the Response will be thrown.

Consumes and Produces values control Content-Type and Accept headers.

Note that in the above example the root proxy is created on an interface. It might not always be possible to refactor your resource class to get the JAXRS annotations inherited from an interface. No worries, CGLIB proxies will be created in such cases, for root and sub-resource classes - you'll just need to be a little bit careful and avoid doing some initialization with side effects in default constructors.

With proxies you can't have Context parameters in your method signatures - but may be it's a good thing indeed. You can't also have Objects returned as sub-resource instances - I know JAXRS lets you do it and indeed it's a great way to test how well the dynamic resolution on sub-resources works :-), but it's Java afterall :-), not a big deal I think.

Proxies are HTTP clients

Every proxy is Client which represents the common capabilities for both proxy and http-centric clients. JAXRSClientFactory has few methods for common cases when headers need to be customized but here's how you can control what the proxy sends and receives :


BookProxy ps = JAXRSClientFactory.create(uri);
WebClient.client(ps).type("text/xml").accept(text/xml)
.modified(date, false);
Book b = ps.getBook();
if (b == null) {
Response r = WebClient.client(ps).getResponse();
if (r.getStatus() == 204) {
// check what the story is with
// the http-centric client
WebClient wc =
new WebClient(WebClient.client(ps), true);
Response r2 = wc.get();
// create a new proxy now
BookProxy ps2 =
JAXRSClientProxy.fromClient(wc, true);
assertEquals(
WebClient.client(ps).getCurrentURI(),
WebClient.client(ps2).getCurrentURI())
}
}


The headers set explicitly will be chosen instead of those derived from Consumes and Provides (for Content-Type and Accept). If no information is available then most likely application/xml will be set - after all, it's all mostly about XML services.
The code above also shows few more details. If Book instance is null then most likely the conditional GET has worked but we'd like to do more checks just in case, first by checking the actual Response and then using a WebClient http centric client which is initialized with our proxy's current URI and existing headers. Then we create a new proxy from a WebClient instance by inheriting its headers too.

HTTP-centric clients

WebClient represents HTTP-centric clients. I do think it's unfortunate we have no standard client API. We tried to apply the same builder pattern used by JAXRS ResponseBuilder. All the header-related methods have been done after checking the section 14 of HTTP 1.1, plus JAXRS JAXRS HttpHeaders and ResponseBuilder. Here are some examples.


WebClient wc = new WebClient("http://foo");
WebClient wc2 = new WebClient(wc.getBaseURI());
Response r = wc2.accept("text/plain").get();
Response r = wc2.post(new Book());
Book b = wc2.get(Book.class);
Book b2 = wc2.invoke("myhttpmethod",
body, Book.class);
//etc


You can get a Response or a typed object, you choose. WebClient is a Client, but the builder pattern works thanks to the covariance support.


WebClient acts like a browser




WebClient wc = new WebClient("http://foo");
// submit form to http://foo/bar/foo/baz
wc.path("bar").path("foo/baz").
form(new Form().set("a", "b")
.set("c", "d"));
wc.back();
assert(wc.getCurrentURI(),
"http://foo/bar/foo");
// get back to base URI
wc.back(fast);

assert(wc.getCurrentURI(),
"http://foo");

wc.to("http://newhost");


The power of XPath and XSLT

Sometimes you just need to look into a resulting XML, either when dealing with unexpected changes or when retrieving a subnode. So we've gone ahead and created a utility class XMLSource, to be optimized and enhanced later. You'll be able to easily get to a required XML piece in a number of ways, initial example :


XMLSource xs = new XMLSource(
(InputStream)client.get().getEntity());
Book b = xs.getNode("/books/book[1]", Book.class);


There are quite a few more things to say about what we have but I guess it's enough for now.
It's not yet finished at all - stay tuned for more updates. And we'd welcome a lot any constructive feedback - please send the comments to CXF lists or comment here or contact me directly.

And yes - thanks to JAXRS and RI (Jersey) for being innovative and inspiring.

Enjoy.

Thursday, February 5, 2009

JAXRS Spring Security Demo in Fuse

We've recently added a Spring Security JAXRS demo to our Fuse Service Framework distributions covering both 2.1 and 2.2 lines.

Spring Security is powerful indeed. The demo shows how easily one can secure JAXRS resource classes, those derived from interfaces and those which are plain classes and are wrapped by CGLIB proxies, with or without applying dedicated security annotations to individual resource methods.

You need to create an account in order to see the source of the demo. I hope you can appreciate why we added the demo to Fuse : we intend to continue raising the awareness of Fuse. This demo will be regularly tested by our CPI process which is based on Xharness.

You can also get the idea of what the demo does by checking the system tests in CXF trunks on Apache. In fact the system tests evolved a bit since the demo was created, they show how subresource methods can be controlled too, with subresource instances being injected Spring proxies themselves.

Hopefully though the perceived initial inconvenience to do with the account activation :-) will be compensated by the fact that you're likely to find some information of interest on everything which is happening in the Fuse world and may decide to get back again :-)

Wednesday, February 4, 2009

New CXF SubProject : Distributed OSGI RI

Apache CXF has recently had a new subproject created which hosts a Distributed OSGI Reference Implementation.

David Bosschaert and Eric Newcomer have already posted about it.

I'd like to add few comments.

I think in the todays software world it's not easy to innovate and it's a great achievement indeed for Eric, David, Tim Diekman, Eoghan Glynn and all the folks from various companies who worked very hard and have contributed to the DOSGI-related efforts.

Don't get discouraged by the RPC-ishness of DOSGI - if you do then I recommend you to read this very convincing post.

I do hope to plugin the CXF JAXRS implementation into a DOSGI RI. It's a topic for a separate post, but one can write a perfectly restful yet capable of surviving the changes client code which relies on proxies.

While DOSGI will be perfect for OSGI developers, it will also attract those who are primarily after the promise of OSGI containers to replace modules on the fly in a predictable way - this is one of the reasons people might want to play with DOSGI even though today they may do fine without it.

When a given DOSGI server module will get replaced it would be ideal for the active incoming client requests not to be lost or for clients to get helpful error messages. OSGI can help here. Hopefully future versions of DOSGI will address this fundamental issue. Perhaps we can expect a dedicated (OSGI) service be introduced which will process the pending messages as needed, by either replying properly or saving them to some storage while a given service implementation or a DOSGI bundle itself get replaced.

You can expect a lot of features from DOSGI RI which sits on top of WS-Policy aware CXF runtime.

Please give it a try, contribute and provide some feedback and enjoy playing with this new and cool technology.

Monday, February 2, 2009

Multiparts in CXF JAXRS

We've just had CXF JAXRS updated to deal with multiparts. Multipart/related, multipart/alternative, multipart/mixed and multipart/form-data are supported at the moment.

The reason I've decided to blog about it is that I was fascinated how little work I had actually to do to make it all happen. CXF JAXRS sits on top of the robust CXF runtime core component, which, among other things, has a great support for (de)serializing multipart requests, with the ability for attachments exceeding a given configurable memory threshold be saved into a configurable directory.

A number of options is available for developers wishing to handle multipart requests. First we tried to make sure that JAXWS users trying JAXRS can reuse the same code they use when dealing with attachments in JAXWS. Particularly, one can get a root attachment bound to a method parameter, while the subordinate ones can later be retrieved for further processing :


public class Resource {
@Context
private MessageContext cxfJaxrsContext;

@POST
@Path("/")
public void handle(StreamSource root) {
// check the root one...
// get to the rest of them
Map<String, DataHandler> parts =
AttachmentUtils.getChildAttachmentsAsMap(mc);
handleParts(parts);
}
}


The root attachment can be bound to any type which can be supported by registered providers :


public class Resource {
@Context
private MessageContext cxfJaxrsContext;

@POST
@Path("/")
public void handle(JaxbBook book) {
// book represents the root one
List<Attachment> parts = AttachmentUtils.getChildAttachments(mc);
}

@POST
@Path("/")
public void handle2(JSONBook book) {
// book represents the root one
List<Attachment> parts = AttachmentUtils.getChildAttachments(mc);
}

@POST
@Path("/")
public void handle3(MultipartBody body) {
Attachment a = body.getRootAttachment();
List<Attachment> parts = body.getChildAttachments();
}

@POST
@Path("/")
public void handle4(List<InputStream> all) {
}

@POST
@Path("/")
public void handle5() {
Attachment a = AttachmentUtils.getRootAttachment(mc);
List<Attachment> parts = AttachmentUtils.getChildAttachments(mc);
AttachmentUtils.getAllAttachments(mc);
}
}


One can address individual parts like this :


public class Resource {
@Context
private MessageContext cxfJaxrsContext;

@POST
@Path("/")
public void handle(@Multipart(value="id1",
type="application/json") JSONBook book,
@Multipart(value="id2") JaxbBook book) {

}
}


For multipart/form-data, FormParams can be used to bind to individual parts representing form fields. MultipartMap is supported. One limitation at the moment is that with multipart/form-data, parts can only be bound to Strings (which can further be processed as per the JAXRS parameter handling rules if FormParam is used, with CXF JAXRS ParameterHandler being of likely help here). Thus if one wants to upload files then at the moment one needs to use MultipartBody and do some custom processing :


public class Resource {

@POST
@Path("/")
@Consumes("multipart/form-data")
public void handle(MultipartBody body) {
// presumes the part has a content id
Attachment a = body.getAttachmentById("file");
ContentDisposition cd = a.getContentDisposition();
InputStream is = a.getDataHandler().getInputStream();
// proceed
}
}


Configuring the attachments directories and memory thresholds can be done on a per jaxrs:endpoint from Spring, setting corresponding bean properties on a CXF JAXRS provider dealing with multiparts. Or you can do it from your code if you wish :


public class Resource {

@POST
@Path("/")
public void handle() {
List<Attachment> all =
AttachmentUtils.getAllAttachments(mc,
"/tmp", "589678")
}
}


Outbound attachments will also be supported. Give it a go and let us know what you think.