aspose file tools*
The moose likes Web Services and the fly likes How to bind JAXB persistant objects to WS parameters? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of EJB 3 in Action this week in the EJB and other Java EE Technologies forum!
JavaRanch » Java Forums » Java » Web Services
Bookmark "How to bind JAXB persistant objects to WS parameters?" Watch "How to bind JAXB persistant objects to WS parameters?" New topic
Author

How to bind JAXB persistant objects to WS parameters?

Philippe Desrosiers
Ranch Hand

Joined: Mar 29, 2006
Posts: 138
Alrighty.

Step 1) Generate Web service client code with JAX-WS. Check. Done. Awesome.
Step 2) Generate xsd-compliant java source with JAXB. Yessir. Checkaroonie. Sweet.
Step 3) For specific web service methods that require an XML Document as a parameter, bind the Marshalled JAXB document to the parameter. For Service methods that return an XML document, bind a JAXB-compliant bean to the returned value. Preferably through Spring IOC, if that makes any sense.

Uh...

Can anyone help me out here?
Peer Reynders
Bartender

Joined: Aug 19, 2005
Posts: 2906
Philippe Desrosiers wrote:Step 2) Generate xsd-compliant java source with JAXB. Yessir. Checkaroonie. Sweet.


This is were you lose me. Step 1) with wsimport would have already done that behind the scenes. The resulting generated Java classes would already be used as parameters for the consumer service proxy. So you only ever deal with the wsimport generated classes (most of which are JAXB-compliant beans). The code inside the consumer service proxy deals with JAXB - you don't.

See these examples
GeoIP
Xslt2Xml
StockQuote


"Don't succumb to the false authority of a tool or model. There is no substitute for thinking."
Andy Hunt, Pragmatic Thinking & Learning: Refactor Your Wetware p.41
Philippe Desrosiers
Ranch Hand

Joined: Mar 29, 2006
Posts: 138
Wow. Verrry interesting. I used JAXB because the specific web service that I'm trying to call expects an XML document as a parameter, but doesn't specify a schema. As a result, JAX-WS generates a proxy that takes a String, but doesn't provide any validation.

Since I have no control over the web services I'm trying to call, but a schema does exist (usually) for the expected XML document, I basically had to generate those classes separately, and write some glue code.

It's basically down to the idiosyncrasies of the specific web service I'm trying to call...
Peer Reynders
Bartender

Joined: Aug 19, 2005
Posts: 2906
Philippe Desrosiers wrote:web service that I'm trying to call expects an XML document as a parameter


If that is true the WSDL should have used {http://www.w3.org/2001/XMLSchema}anyType for that "document". The JAX-WS proxy would then accept a java.lang.Object that you provide with an org.w3c.dom.Element that holds the document root element. That is what the Xslt2Xml example is all about. What is the XSD schema type that the WSDL uses for the "XML document"?
Philippe Desrosiers
Ranch Hand

Joined: Mar 29, 2006
Posts: 138
As I understand it, that's exactly what's happening, but if I want to pass a "Customer" object to the service, I'll have to serialize it to an org.w3c.dom.Element before passing it through the WS Client proxy, no? In case I'm totally missing the boat, here is some WSDL:

As you can see, it doesn't tell me much about the structure of the XML Document I'm supposed to give as a parameter to, say, the SetUser service. It just says "any". But I'm told it expects an XML document, formatted according to this schema:

To be honest, the only part I've tried so far is to convert a returned XML Document (from the GetUserHeirarchy service) into a local object via JAXB. As far as I can tell, this is not automatic (or else I'm doing it wrong. Example:

Anyway, I can't even test that code now, because of this other problem I'm having right now.

BUT: If you can suggest a way for me to "fix" the WSDL so that JAX-ws detectes that the service expects an XML document in that parameter, or, better yet, supply the schema for that XML document directly in the WSDL, you will have made me a very happy man. I don't control these WSDLs or Schemas myself (as I hope you can tell from all the proprietary microsoft crap inside them), but I'd love to be able to supply some suggestions to our M$ consultant on how to improve our interoperability...

Thanks for you genius, as always, Peer!

[PR: added line breaks to schema to minimize page width]
Peer Reynders
Bartender

Joined: Aug 19, 2005
Posts: 2906
According to the JavaDoc of javax.xml.bind.Unmarshaller

should be sufficient provided the JAXB context has been properly initialized.

However you need to be careful about assuming that your document root is at index 0 (otherwise why bother with the List<Object> and not simply return an Object). An org.w3c.dom.Document can contain other nodes besides the document root (the one that you get with getDocumentElement()). A document node can contain things like:
  • Processing instruction nodes
  • Comment nodes
  • Document type Node
  • one single document element node

  • However processing instructions, and document type nodes aren't permitted inside the XML body. This explains why you can't use org.w3c.dom.Document with Java web services but must use an org.w3c.dom.Element instead. However comment nodes are legal. That is why an "XML Document" is represented as a List<Object> rather than an Object and that first Object could simply be a comment node. So you should verify at least that you are dealing with a org.w3c.dom.Node.ELEMENT_NODE nodeType and possibly check the nodeName before blindly unmarshalling it.

    According to the JavaDoc of javax.xml.bind.Marshaller you can marshal your JAXB objects to a DOM node:


    You are probably best advised to stick all the List<Object> <=> JAXB objects conversion code in some helper/utility class.

    Philippe Desrosiers wrote:BUT: If you can suggest a way for me to "fix" the WSDL so that JAX-ws detectes that the service expects an XML document in that parameter, or, better yet, supply the schema for that XML document directly in the WSDL, you will have made me a very happy man.


    While it is possible to supply JAX-WS with and alternate, doctored WSDL, I don't think it is worth it in this case. The any/anyType is a tactic to minimize versioning of the web services contract. From what I can tell they are using XSD typed DataSets that generate and consume these document elements and they don't want to have to change the contract when they modify one of those XSD typed DataSets even though the change will most likely break the client(s). When they change the DataSet you should just have to update the JAXB binding and any code that breaks with it - but you should be able to leave the web service proxy alone.

    However if you want some fuel for a rant:
    Tip: xsd:any: A cautionary tale.
    Realizing Strategies for Document-Based Web Services With JAX-WS 2.0: Part 3 in a Series
     
    I agree. Here's the link: http://aspose.com/file-tools
     
    subject: How to bind JAXB persistant objects to WS parameters?
     
    Similar Threads
    What to do, if we have 130 to 150 attributes/fields/parameters for a web service..???
    Sample Questions for 288 - Need answers
    JAXB Vs JAX-WS
    Calling Web Service Method using SAAJ
    Need to create a web service in Java that reads data and results in XML.