DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
11 Monitoring and Observability Tools for 2023
Learn more
  1. DZone
  2. Data Engineering
  3. Data
  4. JAX-WS Payload Validation, and Websphere 7 Problems

JAX-WS Payload Validation, and Websphere 7 Problems

Ant Kutschera user avatar by
Ant Kutschera
·
Sep. 13, 10 · Interview
Like (0)
Save
Tweet
Share
19.77K Views

Join the DZone community and get the full member experience.

Join For Free

A WSDL file contains a reference to an XSD document which defines the data structures which can be sent to the service over SOAP. In an XSD, you can define a Type for an element, or things like the elements cardinality, whether its optional or required, etc.

When the web server hosting a web service is called, it receives a SOAP envelope which tells it which web service is being called. It could (and you might expect it does) validate the body of the SOAP message against the XSD in the WSDL... but it doesn't.

Is this bad? Well, most clients will be generated from the WSDL, so you can assume that the type safety is respected. Saying that, it's not something the server can guarantee, so it needs to check that say a field that is supposed to contain a date, really does contain a date, and not some garbled text that is meant to be a date. But more importantly, something which a client does not guarantee, is whether all required fields in the data structure are actually present. To check this, you can validate incoming SOAP bodies against the XSD.

The way to do this, is by using "Handlers". The JAX-WS specification defines two kinds, namely, SOAP Handlers and Logical Handlers. The SOAP kind is useful for accessing the raw SOAP envelope, for example to log the actual SOAP message. The logical kind is useful for accessing the payload as an XML document. To configure a handler, you add the HandlerChain annotation to your web service, passing it the name of the handler configuration file:

@WebService
@HandlerChain(file="handler.xml")
public class GislerService {

  private static final String FORMAT_DD_MMM_YYYY_HH_MM_SS = "dd. MMM yyyy HH:mm:ss";

  @WebMethod
  public String formatDate(ObjectModel om){
    SimpleDateFormat sdf = new SimpleDateFormat(FORMAT_DD_MMM_YYYY_HH_MM_SS);
    return "Formatted, its " + sdf.format(om.date);
  }
}


So, in order to validate a body against an XSD (i.e. to ensure that the "ObjectModel" instance in the above method is valid, before your method gets called by the WS framework), you use a logical handler to grab the payload as a javax.xml.transform.Source and pass it to a javax.xml.validation.Validator which you create using a javax.xml.validation.SchemaFactory and javax.xml.validation.Schema, based on the XSD from the WSDL. If the validation is successful, you let your handler return "true", otherwise you throw a javax.xml.ws.WebServiceException passing it the validation exception's text, so that any client making an invalid call can work out why it's invalid. It's something like this:

public class MyLogicalHandler implements LogicalHandler {

  private Validator validator;

  public MyLogicalHandler(){
    try{
      long start = System.nanoTime();					
      SchemaFactory schemaFac = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
      Schema schema = schemaFac.newSchema(new URL("http://localhost:8084/Gisler/GislerServiceService?xsd=1"));
      validator = schema.newValidator();
      System.out.println("created validator in " + ((System.nanoTime()-start)/1000000.0) + "ms");
    } catch (IOException e) {
      e.printStackTrace();
      throw new WebServiceException(e.getMessage());  //cant validate/initialise
    } catch (SAXException e) {
      e.printStackTrace();
      throw new WebServiceException(e.getMessage());  //cant validate/initialise
    }
  }
.
.
.
  public boolean handleMessage(LogicalMessageContext context) {

    if (((Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY)).booleanValue()) {
      return true; // only validate incoming messages
    }

    try{
      LogicalMessage lm = context.getMessage();
      Source payload = lm.getPayload();
      validator.validate(payload);
      System.out.println("validated ok");
    }catch(SAXParseException e){
      System.out.println("validated failed: " + e.getMessage());
      throw new WebServiceException(e.getMessage());  //invalid, so tell the caller!
    } catch (SAXException e) {
      e.printStackTrace();
      throw new WebServiceException(e.getMessage());  //cant validate/initialise
    } catch (IOException e) {
      e.printStackTrace();
      throw new WebServiceException(e.getMessage());  //cant validate/initialise
    }
		
    return true;
  }
}
The attached Eclipse Projects were tested using GlassFish v3 (Glassfish Tools Bundle for Eclipse 1.2), and they worked well. To test required but missing elements, I wrote a JUnit test, which is in the client project. To test badly formed dates, I captured the SOAP HTTP Requests from the JUnit using the Eclipse TCP/IP Monitor, and modified them before resending them, with an invalid date string. Note that to make this work, you also need to modify the HTTP header's "content-length" using the monitor, otherwise you get some very strange errors, because the stream terminates early! An alternative is to use a tool like SoapUI.

Compared to Glassfish, Websphere didn't do so well - it has a nasty bit of functionality built in. Validating using a handler works fine, until your first invalid request comes in. Then, it still works, until another valid request is processed. After that, it completely ignores invalid elements like dates, if they are marked as optional (which is the default!). How come? Well, that took a while to work out, but basically, it's optimising the incoming message by arguing that if an element is optional, and happens to be present but invalid, the invalid data can be thrown away, because it's... well, optional... OK, I couldn't believe it either, but that's what it does, the SOAP handler that logs to System.out simply had the invalid element missing. So a little searching around on the internet, and a little luck, and hey presto this link which is a bug fix for Websphere 7 fix pack 9. By setting the system property "jaxws.payload.highFidelity=true", Websphere guarantees that the message passed to the handlers is exactly that which came over the wire. Tests showed that it indeed did fix the problem.

So what does all this mean, in the grand scheme of SOAP things? Well, when designing a service, you need to consider how important it is to have valid data. If you allow optional fields which are strongly typed, such as dates or complex types, then you could have a problem. Without adding a validating handler, it is possible that the caller could pass you optional but invalid data, and you wouldn't receive it in your web service, which is given a null reference, instead of invalid data! If you don't work with optional data, then you could skip validation, and just let null pointer exceptions fly around, in cases where a caller has passed invalid required data. By logging the incoming and outgoing communications, it makes it easier to debug such problems, but it is a little impolite to build a public interface which handles invalid requests like this.

The last consideration is performance. Creating a validator for a simple schema like in this demo only took around 20ms on my laptop. The actual validation took less than a millisecond for a valid request, and just over a millisecond for an invalid response. The reader is left to draw their own conclusions :-)

From http://blog.maxant.co.uk/pebble/2010/09/09/1284065640000.html

Payload (computing) Web Service SOAP Web Protocols Data (computing)

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • When to Choose Redpanda Instead of Apache Kafka
  • 10 Best Ways to Level Up as a Developer
  • Secure APIs: Best Practices and Measures
  • Is DevOps Dead?

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: