File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Web Services and the fly likes Passing Set<java.lang.Object> and List<java.lang.Object> in Axis 2.0 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 "Passing Set<java.lang.Object> and List<java.lang.Object> in Axis 2.0 " Watch "Passing Set<java.lang.Object> and List<java.lang.Object> in Axis 2.0 " New topic
Author

Passing Set<java.lang.Object> and List<java.lang.Object> in Axis 2.0

vinoth subramaniam
Ranch Hand

Joined: Jul 05, 2008
Posts: 47
Is there [size=18]DIRECT or INDIRECT any way to pass java.util.Set<java.lang.Object> and java.util.List<java.lang.Object> in Axis 2.0 ? I have read that it is possible by converting it into Object[]. But it will affect our entire project.

and i have read that Axis 2.0 will support JAXB 2.0 and in JAXB 2.0 , java.util.List<java.lang.Object> can be mapped as xsd:IDREFS . How it can be implemented in WSDL file?

Kindly someone help me.

I am using jboss-5.0.0.GA and runtime is JDK 1.6.

Thanks in advance [/size]
Peer Reynders
Bartender

Joined: Aug 19, 2005
Posts: 2906
vinoth subramaniam wrote:I have read that Axis 2.0 will support JAXB 2.0

That intention has existed for a long time - so I wouldn't hold my breath. The XML object model used by the Axis2 engine is Apache Axiom.

in JAXB 2.0 , java.util.List<java.lang.Object> can be mapped as xsd:IDREFS.

Incorrect. xsd:IDREFS are mapped to java.util.List<java.lang.Object> but not the other way around.

{http://www.w3.org/2001/XMLSchema}IDREF is simply a reference to an XML element that is somewhere else in the XML document. {http://www.w3.org/2001/XMLSchema}IDREFS is simply an enumeration of multiple {http://www.w3.org/2001/XMLSchema}IDREF. The point is that the "thing" they refer to still has to exist somewhere else in the document where most likely the document context defines the "type" of the "thing" with reference to the originating schema.


If I understand your situation correctly you seem to have a distributed system that uses Set<Object> and List<Object> as "generic" Data Transfer Objects.

In XML the equivalent would be an XML document that could have any number of child elements, each containing the root element of a separate "document".

In Axis2 the Set<Object>/List<Object> would be replaced with an org.apache.axiom.om.OMElement as for example in axis2/samples/userguide/src/userguide/example1/MyService.java.

Given that Axis2 gives you org.apache.axis2.util.XMLUtils.toOM(org.w3c.dom.Element) and org.apache.axis2.util.XMLUtils.toDOM(org.apache.axiom.om.OMElement), you have an integration point or seam with JAXB.

  • Get all your objects that may appear in your Set<Object>/List<Object> together and bind them with JAXB using your preferred method, with one single ObjectFactory

  • When you need to send a Set<Object>/List<Object>:
  • create an OMElement to act as the root container (The name of this element could easily imply whether it is a Set or a List).
  • Iterate through the Objects in the Set<Object>/List<Object>
  • For each object use JAXB to marshal it as a W3C DOM representation and then retrieve the root org.w3c.dom.Document.Element with org.w3c.dom.Document.getDocumentElement()
  • Convert the root org.w3c.dom.Document.Element to a org.apache.axiom.om.OMElement with XMLUtils.html.toOM()
  • Add the resulting org.apache.axiom.om.OMElement to the root container element with org.apache.axiom.om.OMElement.addChild(org.apache.axiom.om.OMNode)
  • Once all the objects have been added, your Set<Object>/List<Object> as a org.apache.axiom.om.OMElement is ready

  • When you need to reconstitute a Set<Object>/List<Object>:
  • Check the name (getQName() or getLocalName()) of the org.apache.axiom.om.OMElement to determine whether you are creating a Set<Object> or List<Object> and create it.
  • Iterate over the children (getChildren()) of the org.apache.axiom.om.OMElement
  • Convert each of them with XMLUtils.html.toDOM() to an org.w3c.dom.Document.Element
  • Use JAXB to unmarshal the org.w3c.dom.Document.Element back to its object form
  • Add the resulting object to the Set<Object>/List<Object>.
  • Once you iterated through all the children you should have your Set<Object>/List<Object> back.


  • "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
    vinoth subramaniam
    Ranch Hand

    Joined: Jul 05, 2008
    Posts: 47
    Thank you very much for your valuable ideas..

    Let me try to explain my context

    i need to make webservices for BookSearchWebServices.java.. and it contains


    Book.java is (which is having an object of Author.java as one of its attributes)

    Author.java is (which is having Set<books> as one of its attributes)






    How can i pass them ?
    Peer Reynders
    Bartender

    Joined: Aug 19, 2005
    Posts: 2906
    vinoth subramaniam wrote:How can i pass them ?


    You've got bigger problems. Not only are you trying to return "A list of books" - you are trying to return an entire object graph and to make things worse, an object graph with cycles. XML is notoriously bad at representing graphs (and the cycles don't help either) because XML is hierarchical in nature - so it is necessary to restructure the information to make it more XML-friendly. In most cases the "listed" object is simply stripped down to its bare essentials so that no object-graph remains.

    If it is necessary to retain all the information in the object-graph then a different approach is required. The XML document has to represent all the instances of any type that appears in the entire graph and any relationships are realized through {http://www.w3.org/2001/XMLSchema}IDREF and {http://www.w3.org/2001/XMLSchema}ID types. So in the case of the Book/Author example the document needs three sub-sequences:
  • a books sequence. This sequence contains all the books in the graph - not just the ones that belong to the List<Book>. Each book can reference multiple authors.
  • an authors sequence. This sequence contains all the authors in the graph. Each author can reference multiple books.
  • a list sequence. This sequence simply contains references to the books that are actually in the List<Book>.

  • The {http://idref.jaxws.coderanch.com/}bookList in the following schema realizes this structure

  • The {http://idref.jaxws.coderanch.com/}BookRef uses an {http://www.w3.org/2001/XMLSchema}IDREF to refer to the isbn13 of a {http://idref.jaxws.coderanch.com/}Book. It is used by the list to identify the books in "the list" and by {http://idref.jaxws.coderanch.com/}Author to identify the author's books.
  • The {http://idref.jaxws.coderanch.com/}AuthorRef uses an {http://www.w3.org/2001/XMLSchema}IDREF to refer to the id of an {http://idref.jaxws.coderanch.com/}Author. It is used by {http://idref.jaxws.coderanch.com/}Book to identify a book's authors.

  • This schema can now be used in a web service contract

    To keep things simple I'm going to proceed with JDK 6 tools only (i.e. JAX-WS & JAXB - which I believe are supported by JBoss 5).

    A JAX-WS binding file
    which maps the Java web service artifacts to the com.coderanch.jaxws.idref.ws package.

    A JAXB external binding customization file
    which maps the JAXB artifacts to the com.coderanch.jaxws.idref.dto package. The main reason for using the customization is to force strong typing on the IDREF links and to suppress the use of JAXBElement wrappers. Of course many of the names for the Java classes are customized as well.
    wsimport BookSearch.wsdl -b BookSearch.xml -b BookSearch.xjb -s src
    is then used to generate the Java artifacts:
  • com.coderanch.jaxws.idref.ws.BookSearch - the endpoint interface
  • com.coderanch.jaxws.idref.ws.BookSearch_Service - the web service client proxy
  • com.coderanch.jaxws.idref.dto.AuthorDto class to represent {http://idref.jaxws.coderanch.com/}Author.
  • com.coderanch.jaxws.idref.dto.AuthorHolder class to represent {http://idref.jaxws.coderanch.com/}AuthorRef.
  • com.coderanch.jaxws.idref.dto.BookDto class to represent {http://idref.jaxws.coderanch.com/}Book.
  • com.coderanch.jaxws.idref.dto.BookHolder class to represent {http://idref.jaxws.coderanch.com/}BookRef.
  • com.coderanch.jaxws.idref.dto.BookList class to represent {http://idref.jaxws.coderanch.com/}BookList.
  • com.coderanch.jaxws.idref.dto.BookSearchRequest class to represent {http://idref.jaxws.coderanch.com/}BookSearchRequest.
  • com.coderanch.jaxws.idref.dto.ObjectFactory - the JAXB ObjectFactory.
  • package-info.java containing the JAXB package level annotations.


  • At this point the building blocks for the web service are in place. Of course some domain objects are necessary. The Book, Author, and the Repository class that returns them.



    As you may notice the Repository returns a List<Book> while the generated service endpoint interface returns a com.coderanch.jaxws.idref.dto.BookList, so for the conversion we need an adapter:

    Finally we can put together the web service implementation.

    And the code to host the endpoint

    To compile everything:
    javac -d . src\com\coderanch\jaxws\idref\domain\*.java
    javac -d . src\com\coderanch\jaxws\idref\util\BookListAdapter.java
    javac -d . src\com\coderanch\jaxws\idref\provider\*.java
    wsgen -cp . com.coderanch.jaxws.idref.provider.BookSearchImpl


    Start the web service with:
    java com.coderanch.jaxws.idref.provider.Main

    If you point a browser to http://localhost:8080/wsdemo/booksearch?wsdl you should see the JAX-WS generated WSDL.

    Open a separate console window to work on the web service consumer.

    And compile it with
    javac -d . src\com\coderanch\jaxws\idref\consumer\BookSearchClient.java
    and run it with
    java com.coderanch.jaxws.idref.consumer.BookSearchClient
    The SOAP request for the {http://idref.jaxws.coderanch.com/}bookList would look like this:

    Notice how there is no "search" method in the request. That is a characteristic of the document/literal messaging mode. An operation can only receive one parameter, the "input document". The type of the "input document" determines which method is executed. In this case the payload is of the {http://idref.jaxws.coderanch.com/}BookSearchRequest type, so the payload is processed by the "search" WebMethod.

    The response carries all the result information. The "list" holds the references to the books that are part of the result set; "books" holds all the books that are in the object graph, each book having one or more author references; "authors" holds all the authors that are in the object graph, each author having one or more book references.

    (linebreaks and whitespace added, chunking lengths removed for readability)

    An example of an empty {http://idref.jaxws.coderanch.com/}bookList:

    The "list", "books", and "authors" elements are simply "nil" elements.

    So all this is basically an example of how a List<Book> is converted to a BookList on the provider side and then reconstituted to a List<Book> on the consumer side.
    Balaji Loganathan
    author and deputy
    Bartender

    Joined: Jul 13, 2001
    Posts: 3150
    Cool answer.
    Very nice of Peer.


    Spritle Software Blogs
     
    Consider Paul's rocket mass heater.
     
    subject: Passing Set<java.lang.Object> and List<java.lang.Object> in Axis 2.0
     
    Similar Threads
    EXAMLAB QUESTION - Can't understand the Answer
    Could not parse mapping document from resource PojoTestTable.hbm.xml
    setting value for ID attribute dynamically for rich:modalpanel (for templating overlay)
    How to resolve Axis Fault Error?
    ESAPI for localization