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.

Wednesday, December 17, 2008

Managing contexts in CXF JAXRS

In JAXRS, a number of classes representing various features of a given request exist, as opposed to a composite WebServiceContext in JAXWS which lets get to individual contexts and message properties.

Imagine this JAXRS resource class which needs to know where the request came from, how secure it is, what the structure of the request URI is, what servlet context parameters corresponding to a given request are, what HTTP headers are involved and if certain request preconditions are met. And if you're writing a composite message body provider then, in addition to the above requirements, you also want to query other available providers as well as to check if a certain context resolver is available.

How unreatistic these requirements are ? It's likely they won't arise in many cases at the same time but likewise it's likely they'll will have to be met in some cases.

So here's a portable JAXRS code showing how you can get an access to all the contexts :


public class CompositeMessageReader
implements MessageBodyReader<Composite> {

@Context UriInfo u;
@Context SecurityContext sc;
@Context HttpHeaders h;
@Context Request r;
@Context ServletContext sc;
@Context HttpServletRequest httpR;
@Context ContextResolver contextR;

// use the injected contexts

}



And here's a CXF JAXRS specific code on how you can get an access to all the contexts plus the properties of the underlying message.


public class CompositeMessageReader
implements MessageBodyReader<Composite> {

@Context org.apache.cxf.jaxrs.ext.MessageContext mc;
// use the injected contexts
mc.getSecurityContext();
mc.getHttpHeaders();
mc.getUriInfo();
mc.getContextResolver(JAXBContext.class)
mc.getRequest();
mc.getServletContext();
mc.getServletConfig();
mc.getHttpServletRequest();
mc.getHttpServletResponse();

FutureJAXRSContext newContext =
mc.getContext(FutureJAXRSContext.class);

mc.get(PROPERTY_KEY);

}

I'm contradicting here to my previous post where I'm whining :-) about the JAXRS portability.
But you know how long would it take you to get back to a portable JAXRS code.

JAXRS Wish List

I think I won't say anything new by repeating that a JAXRS specification has been a success.

It brings so many new annotations into a Java code but the main goal behind it, at least as far I see was to popularize the REST paradigm among java developers and surely, the goal has been achieved.

Marc Hadley, Paul Sandoz and indeed all the experts who contributed to the JAXRS specification have done a fantastic job. And no doubts more is to come from newer versions of JAXRS.

So here's my wish list. It's not a long one. May be it's a bit early given that JAXRS 1.0 was only released last September but here it goes :

Please focus on the Portability.
There's no uniform way to express that a given service class is a singleton. There's no portable client api - why is that ? In JAXWS one can do a portable code which creates and consumes services. There's no uniform way to query for a document describing a service.

That's it really - not a long list indeed :-)

Tuesday, December 9, 2008

CXF JAXRS Keeps Getting Better

I could not resist it, even though I'm not a Christina Aguilera's fan :-)

CXF JAXRS is catching up. Jersey is an extremely strong player, and I have little doubt about the top quality of other JAXRS implementations - but their CXF competitor has something to say on its own - right now.

CXF is there to offer a number of approaches toward building serious web services. The fusion of JAXWS and JAXRS is likely to appeal to many developers and this is just one of the areas where CXF JAXRS can play its part.

Stay tuned.

Monday, December 1, 2008

Continuations in CXF

It's a classic problem really, how a service can help a client to submit a request and obtain a response asynchronously. A number of approaches exist :

* Client does an invocation on a web service and provides an address to reply to - this requires a client to have a web service of its own for the callback to eventually arrive while on the server side, for the (HTTP) transport thread be released, a typical HTTP 201 may be sent back as an initial acknowledgement, depending on if it's a typical two-way or so-called one way operation.

* Service responds with a resource address a client needs to poll for the results be eventually obtained which requires a client to structure the code accordingly.

There's another approach emerging - using suspended invocations or continuations. Actually, it's not a new approach but with Jetty supporting and Servlet 3 embracing them the suspended invocations are bound to enter the mainstream.

Please read a Jetty Continuations page on when using continuations can make sense.

Without further ado, here's a sample code fragment showing how one can do continuations in CXF in a transport neutral way. CXF Continuations API is currently supported for SOAP-HTTP services based on Jetty 6 and SOAP-JMS services. CXF JAXRS runtime supports them too :



import org.apache.cxf.jaxrs.ext.MessageContext;

@Path("/")
public class WebResource {

private @Context MessageContext context;
private Executor executor = ...;

@GET @PATH("/quote/{id}")
public Quote getQuote(@PathParam("id") String policyId) {

String key =
"org.apache.cxf.continuations.ContinuationProvider";
ContinuationProvider provider = context.get(key);

Continuation c = provider.getContinuation();
synchronized (c) {
if (c.isNew()) {
FutureTask f = new FutureTask(
new CallablePolicyHandler(policyId, c));
c.setUserObject(f);
executor.execute(f);
c.suspend(timeout);
} else {
FutureTask f = (FutureTask)c.getUserObject();
if (f.done()) {
return f.get();
}
c.suspend(decreaseTimeout());
}
}
}
}


What happens is that when continuation.suspend(timeout) is called, the current transport thread gets immediately released and a pending request is put back in the requests queue. Once an asynchronous activity gets completed, it will call continuation.resume() - in this example it's done somewhere inside a CallablePolicyHandler, which results in a suspended request be returned to this method. The code now checks if the FutureTask is done and if not then it means an initial timeout was not enough for the asynchronous activity to complete - in this specific case we decide to suspend a request yet again but with a smaller timeout.

Note that in case of JAXWS the code will be absolutely identical for this specific sample, except that a ContinuationProvider instance will have to be obtained from a JAXWS WebServiceContext.getMessageContext().

Both CXF JAXRS MessageContext and JAXWS MessageContext will have to be used when combining JAXWS and JAXRS. I think we may need to come up with a common MessageContext interface for such cases.

Finally, this CXF Continuations API won't change when Jetty 7 (and indeed Tomcat) implementing Servlet 3 specification will ship.

For another example see this CXF-based demo in a Jetty 7 trunk. It shows the use of JAXWS asynchronous handlers among other things. Note in this demo a new ServletRequest.suspend() call is used as opposed to ContinuationsSupport.getContinuation() and Continuation.suspend() pair of calls in Jetty 6. Nothing to worry about though if you're a CXF Continuations API user - it all will be handled internally without you noticing it.

Thursday, November 6, 2008

Portugal

Here are some photos from our trip to Portugal, it was a great trip.