Search code examples
javaweb-servicesjaxbjax-ws

Java-WS: is it possible to use raw XML for one argument and still use JAXB objects for the rest?


I'm writing a Java webservice client that will be running on WebSphere. I created a new "Web Service Client" project in RAD Developer, gave it my WSDL, specified "Top down Java Bean", and it autogenerated a bunch of files.

One of the operations is "GetAddressData". RAD Developer auto-generated "GetAddressData.java" and "GetAddressDataResonse.java", both annotated with "XmlRootElement".

One of the arguments in "GetAddressData" is "RequestData", a simple object consisting of four strings: worfklow, module, username, and id. RAD Developer generated a "RequestData.java" for me too.

Is there any way that I can substitute raw XML for the JAXB "RequestData" object, instead of packing and unpacking the record a field at a time?

I tried something like this:

private static String theXml =   
    "<requestOptions>\n" +  
    "  <WorkflowName>unmarshalTestWorkflow</WorkflowName>\n" +  
    "  <ModuleName>unmarshalTestModule</ModuleName>\n" +  
    "  <UserName>unmarshalTestName</UserName>\n" +  
    "  <TransactionId>0099</TransactionId>\n" +  
    "</requestOptions>\n";  

private RequestOptions mkRequestOptions () throws Exception {  
    JAXBContext context = JAXBContext.newInstance(RequestOptions.class);  
    Unmarshaller unmarshaller = context.createUnmarshaller();  
    Object obj = unmarshaller.unmarshal(new StringReader (theXml));  
    RequestOptions requestOptions = (RequestOptions)obj;
    ...

But I keep getting:

error: Unexpected element "requestOptions". Expected elements are "".

Solution

  • You'll need to do 2 things.

    1. xmlns in your root: <requestOptions xmlns=\"http://www.company.com/ns\">. This reaches back to your XSD.
    2. Since it sounds like RequestData is not a @XmlRootElement you will have to unmarshall it wrapping it in a JAXBElement

    Illustrated here:

    public class Test
    {
      static String randomXml =
          "<divisionRequestHeader xmlns=\"http://www.company.com/ns/\">"
            + "<id>fake id</id>"
            + "<CoName>My Co Name</CoName>" + "<User>"
            + "<Type>EXTERNAL</Type>" + "<Value>me</Value>" + "</User>"
            + "<Count>100</Count>"
            + "<Requestor>My App Requesting</Requestor>"
            + "</divisionRequestHeader>";
    
      public static void main(String[] args) throws Exception
      {
        JAXBContext context = JAXBContext.newInstance(DivisionRequestHeader.class);
        Unmarshaller unmarshaller = context.createUnmarshaller();
        Source source = new StreamSource(new StringReader(randomXml));
    
        JAXBElement<DivisionRequestHeader> jaxbElement = unmarshaller.unmarshal(source,
                DivisionRequestHeader.class);
        DivisionRequestHeader header = jaxbElement.getValue();
    
        System.out.println(header.toString());
      }
    }
    

    Output with jaxb toString plugin:

    com.company.ns.DivisionRequestHeader@620c620c[id=fake id, coName=My Co Name,
        user=com.company.ns.User@79e479e4[type=EXTERNAL, value=me], count=100,
        requestor=My App Requesting]