Wednesday, July 21, 2010

New JAX-WS Lightweight API Allows Fast Access and Manipulation of SOAP Headers

Background:
SOAP Headers are typically used to pass additional context data to and from SOAP nodes.
JAX-WS provides a SAAJ API rendering of the message that can be queried and manipulated by JAX-WS application handlers.

Problem:
The SAAJ rendering of a message is heavyweight.
The JAX-WS runtime is optimized to stream inbound and outbound messages. Transforming the message into an intermediate SAAJ rendering is inefficient and increases the memory footprint.

Solution:
IBM has defined an alternative lightweight API that can be used to access and manipulate SOAP headers from within a JAX-WS handler.

This API is available in version 7.0.0.5 of the WebSphere Application Server:
PK96816

This API is available in version 6.1.0.27 of the Feature Pack for Web Services:
PK84170

We've documented the ability to set headers on outbound requests here:
instructions for setting SOAP Headers and retrieve SOAP headers here: instructions for accessing SOAP Headers

Example Usage
Here is an example usage.

Interested Parties:
This solution is applicable if your JAX-WS Web service uses large messages and requires high performance and/or low memory footprint.

This solution is also applicable for customers migrating existing JAX-RPC Web services to JAX-WS.

Sunday, March 28, 2010

How to set timeout for JAX-WS client invocations programmatically in WebSphere

A few of my teammates find it difficult to get this working properly. I hope this write-up and example code below would help you. It's actually not too hard.

What can I adjust?

There are three timeouts you can set:

1. CONNECTION_TIMEOUT: The amount of time WebSphere JAX-WS client would wait to establish a http/https connection (default is 180 seconds)
2. WRITE_TIMEOUT: The amount of time the client would wait to finish sending the request (default is 300 seconds)
3. RESPONSE_TIMEOUT: The amount of time the client would wait to finish receiving the response (default is 300 seconds)

How can I set them in my application code?

You can adjust them by setting properties on the requestContext. See code sample below.

HelloWorldSOAPProxy proxy = new HelloWorldSOAPProxy(); // generated proxy class

Map requestContext = ((BindingProvider)proxy._getDescriptor().getProxy()).getRequestContext();
requestContext.put(com.ibm.wsspi.webservices.Constants.CONNECTION_TIMEOUT_PROPERTY , "1");
requestContext.put(com.ibm.wsspi.webservices.Constants.WRITE_TIMEOUT_PROPERTY , "2");
requestContext.put(com.ibm.wsspi.webservices.Constants.RESPONSE_TIMEOUT_PROPERTY , "40");

proxy.sayHello("Billy");


Note: The property value in the Map must be a String; and in seconds.

My code does not work in my environment. How do I troubleshoot it?

Use the WebSphere AdminConsole to enable this trace specification (on the client side): "com.ibm.ws.websvcs.*=all=enabled:org.apache.axis2.*=all=enabled"

You should see something like this in the trace (if you set the response timeout).

[04/08/2009 19:28:37:937 EDT] 00000000 > ibm.ws.websvcs.transport.http.SOAPOverHTTPSender prepareHttpRequestHeaders(): com.ibm.ws.websvcs.transport.http.SOAPOverHTTPSender@33233323 Entry
[04/08/2009 19:28:37:953 EDT] 00000000 3 ibm.ws.websvcs.transport.common.ConfigFromJAX_WS ...ConfigFromJAX_WS.getReadTimeout() : 40
[04/08/2009 19:28:37:953 EDT] 00000000 3 ibm.ws.websvcs.transport.http.SOAPOverHTTPSender syncTimeoutValue 40000 ms for http


Additional tip:

If you are using a standalone Java client (outside of the J2EE container), you can set the WebSphere traceSpec using system properties.

System.setProperty("java.util.logging.manager","com.ibm.ws.bootstrap.WsLogManager");
System.setProperty("traceSettingsFile","MyTraceSettings.properties");
System.setProperty("java.util.logging.configureByServer","true");


and put your traceSpec in a file (e.g. MyTraceSettings.properties) on the working directory.

traceFileName=c:/temp/trace.log
com.ibm.ws.websvcs.*=all=enabled:org.apache.axis2.*=all=enabled


What if I can't or don't want to change the application code?

You can configure the HTTP Transport Policy to adjust these timeouts. See link in InfoCentre for details.

That's all for now.

Wednesday, March 24, 2010

JAX-RS support now exists in WebSphere Application Server!

I'm pleased to see that WebSphere released formal support for JAX-RS 1.0 (plus more) via an upgrade to the Web 2.0 Feature Pack today.  Support also includes JSON support and support for a client API.  Enjoy!

Friday, February 26, 2010

Web Services Caching using DynaCache

Recently, we've been working with customers on using DynaCache to cache web services responses on the server side (to improve throughput and load on a server for common requests). Our DynaCache expert published a blog entry documenting the details about how it works and example code for cache-id generation based on the request information while caching responses for SOAP 1.2.

Hope you find the blog entry is useful, and please provide us any feedback.

Wednesday, January 20, 2010

Two new developerWorks articles on WS-RM and WS-Addressing

There are two new interesting developerWorks articles by some of my IBM colleagues.

  1. The first one is about how to apply WS-ReliableMessaging (WS-RM) to a JAX-WS Web Services. WebSphere introduced WS-RM support in the Feature Pack for Web Services and support is rolled in WebSphere 7.0 and enhanced. Here is the short summary of the article:

    "Learn how to enable WS-Reliable Messaging by creating a Web service from the ground up and applying WS-RM to it, using Rational® Application Developer V7.5 and WebSphere® Application Server V7."

  2. The second article is an overview of JAX-WS 2.1 Support for WS-Addressing in WebSphere Application Server. Here is the short summary of the article:

    "IBM WebSphere Application Server V7 includes support for the Java API for XML-Based Web Services (JAX-WS) 2.1 specification. JAX-WS 2.1 is a maintenance release of Java Specification Request (JSR) 224 that extends the functionality provided by the JAX-WS 2.0 specification with new capabilities. The most significant new capability is support for Web Services Addressing (WS-Addressing) in the Application Programming Interface (API). In this article we learn how to use this new WS-Addressing support, and we see how it makes it easier for web service developers to write stateful web services."

Hope you find these articles useful.

Thursday, January 7, 2010

RAD 7.5.5 and Web Services support

Happy New Year!

Just before the holidays, RAD 7.5.5 was introduced which includes some additions for web services.  Details can be found here.  These additions enhance some of the capabilities that we've added to WebSphere or are actively working on.   Just a few high-level points include...

  • Support for JAX-RS runtimes.
There's now a preference that you can define a JAX-RS library to include the necessary runtime artifacts to pull in for JAX-RS support.  Therefore, the classes can be defined ones within this library, and a JAX-RS facet can then be utilized in order to pull in reference to those classes. 





Once this library has been defined, it's possible to define a JAX-RS facet pulling that in as part of the project.



 Additional configuration can then be done to specify some of the project-specific JAX-RS information.





This helps users not have to worry about including the libraries themselves (and can allow it to be separately managed).
  • Support for SAML
There's now a SAML Facet to ensure deployment to SAML-enabled WebSphere Application Servers  (see Facet diagram above),  support for SAML modifications in PolicySets and Bindings, as well as a SAML Sample that ships as part of RAD 7.5.5



  • Support for Policy Set and Binding Editors 
There is now XML editors for editing the Policy Sets and Bindings within RAD 7.5.5 for a number of different binding types.  An example is shown below for configuration of WS-Security for SAML.



I hope this helps bootstrap some folks to use some of the existing capabilities.

Monday, December 14, 2009

Handling JSON arrays and objects

Recently I was using the Apache Wink client-side capabilities to interface with the RESTful APIs of several popular social media sites like Twitter and bit.ly, and I ran into an interesting problem regarding handling the JSON data being returned from those services. Since I think quite a few people may hit this same issue, I thought it may be helpful to share one way of dealing with the problem.

What is the problem? Well, it turns out that in dealing with these services they were sending back JSON in two different forms. One of those forms was the object form of JSON, which looks like the following:

{"name":"Dustin", "userid":"WebSphereClouds"}

The other form that was getting sent back was the array form of JSON, which starts with a [ instead of a {:

[{"name":"Dustin", "userid":"WebSphereClouds"}]

That may not seem like a big deal, but it does in fact affect the way the data is parsed and the Java object type to which the data is converted.

For instance, consider my application which uses the IBM JSON4J library. If I were trying to convert a response input stream containing data in JSON object form, I would call JSONObject.parse(responseInputStream) and that would return a JSONObject. On the other hand, if I were converting a response input stream containing data in JSON array form I would call JSONArray.parse(responseInputStream) and that would return a JSONArray. Clearly, my application needed a way to determine what form of JSON data it was handling.

To do this, I created a simple class that encapsulates this data type determination. It contains two methods to parse a response input stream and return a JSONArtifact type which is an interface implemented by both JSONObject and JSONArray.

private enum JSONType {
ARRAY_TYPE,
REGULAR_TYPE
}
public JSONArtifact parse(InputStream is) throws IOException {
JSONArtifact parsedJSON = null;
FilterInputStream fis = new BufferedInputStream(is);
JSONType jsonType = getJSONType(fis);
if(jsonType == JSONType.ARRAY_TYPE) {
parsedJSON = JSONArray.parse(fis);
}
else {
parsedJSON = JSONObject.parse(fis);
}
return parsedJSON;
}
JSONType getJSONType(FilterInputStream fis) throws IOException {
JSONType type = null;
fis.mark(1);
byte[] bytes = new byte[1];
fis.read(bytes);
fis.reset();
String firstChar = new String(bytes);
if("[".equals(firstChar)) {
type = JSONType.ARRAY_TYPE;
}
else {
type = JSONType.REGULAR_TYPE;
}
return type;
}

The class simply reads the first byte of data from the stream, resets the stream, and then determines, based on whether the first byte is { or [, whether to parse using the JSONArray or JSONObject class.

I also want to point out what I would consider to be a best practice with respect to JSON data sent back from a RESTful service. When developing RESTful services on the server-side, I suggest sending back the object form of JSON. If necessary, you can encapsulate arrays in this object form:

{"userInfo":[{"name":"Dustin", "userid":"WebSphereClouds"}]}

This will make for simpler parsing by clients of your services, and you can easily add data to what you return by adding more entries in the JSON without regressing existing clients.