• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

How to bind JAXB persistant objects to WS parameters?

 
Ranch Hand
Posts: 138
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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?
 
Bartender
Posts: 2968
6
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
 
Philippe Desrosiers
Ranch Hand
Posts: 138
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 2968
6
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 138
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 2968
6
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
    reply
      Bookmark Topic Watch Topic
    • New Topic