0
votes

I have a 2 Mule flows :- ...The first flow expose a SOAP Web service which perform a DB CRUD operation ... My first flow is :-

<flow name="ServiceFlow" doc:name="ServiceFlow">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8082" path="mainData" doc:name="HTTP"/>
<cxf:jaxws-service  serviceClass="com.test.services.schema.maindata.v1.MainData"  doc:name="SOAP"/>
<component class="com.test.services.schema.maindata.v1.Impl.MainDataImpl" doc:name="JavaMain_ServiceImpl"/>
</flow>

The SOAP request of the web service :-

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://services.test.com/schema/MainData/V1">
   <soapenv:Header/>
   <soapenv:Body>
      <v1:insertDataRequest>
         <v1:Id>477</v1:Id>
         <v1:Name>ttttt</v1:Name>
         <v1:Age>56</v1:Age>
         <v1:Designation>aaaaaa </v1:Designation>
      </v1:insertDataRequest>
   </soapenv:Body>
</soapenv:Envelope>

and the SOAP response is :-

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <insertDataResponse xmlns="http://services.test.com/schema/MainData/V1">
         <Response>Data inserted Successfully</Response>
         <Id>0</Id>
         <Age>0</Age>
      </insertDataResponse>
   </soap:Body>
</soap:Envelope> 

Now I have another flow which is a client flow to this web service.... The Client flow is :-

    <flow name="ClientFlow" doc:name="ClientFlow">
            <http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8888" path="clientpath" doc:name="HTTP"/>

    <set-payload doc:name="Set Payload" value="#[import com.test.services.schema.maindata.v1.*; dRequest = new DataRequest();dRequest.id = 7;dRequest.age = 55;dRequest.name = 'aValue';dRequest.designation = 'hhhhh'; dRequest]"/>

     <async doc:name="Async">
    <mulexml:object-to-xml-transformer doc:name="Object to XML"/>
    <logger message="payload :- #[message.payload]" level="INFO" doc:name="Logger"/>
    </async>

    <cxf:jaxws-client doc:name="SOAP" serviceClass="com.test.services.schema.maindata.v1.MainData" operation="insertDataOperation" port="MainDataPort" />  

 <http:outbound-endpoint exchange-pattern="request-response" host="localhost" port="8082" path="mainData" doc:name="HTTP" method="POST"/>

</flow>

Now the issue is .. in this client flow I am setting the request from Mule <set-payload ... the service is working fine and the request from Client is posted to main service using Http outbound ... but I am getting exception from the response .. I don't know how to set the response here ... do I need to use set Payload again after http outbound ?? if yes .. then how could I set it ?? Please help .. Following is the exception I am getting :-

Exception stack is:
1. unable to marshal type "com.test.services.schema.maindata.v1.DataResponse" as an element because it is missing an @XmlRootElement annotation (com.sun.istack.SAXException2)
  com.sun.xml.bind.v2.runtime.XMLSerializer:244 (null)
2. null (javax.xml.bind.MarshalException)
  com.sun.xml.bind.v2.runtime.MarshallerImpl:328 (http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/xml/bind/MarshalException.html)
3. failed to mashal objec tto XML (java.io.IOException)
  org.mule.module.xml.transformer.jaxb.JAXBMarshallerTransformer$1:110 (null)
4. failed to mashal objec tto XML (java.io.IOException). Message payload is of type: HttpResponse (org.mule.execution.ResponseDispatchException)
  org.mule.transport.http.HttpMessageProcessTemplate:141 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/execution/ResponseDispatchException.html)
--------------------------------------------------------------------------------
Root Exception stack trace:
com.sun.istack.SAXException2: unable to marshal type "com.test.services.schema.maindata.v1.DataResponse" as an element because it is missing an @XmlRootElement annotation
    at com.sun.xml.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:244)
    at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:303)
    at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:490)
    + 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)

UPDATED FLOW :- I have use Java component to set Response for Client flow and it's working fine without any issue ...:-

<flow name="ClientFlow" doc:name="ClientFlow">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8888" path="aa" doc:name="HTTP"/>

<set-payload doc:name="Set Payload" value="#[import com.test.services.schema.maindata.v1.*; dRequest = new DataRequest();dRequest.id = 7;dRequest.age = 55;dRequest.name = 'aValue';dRequest.designation = 'hhhhh'; dRequest]"/>

<http:outbound-endpoint exchange-pattern="request-response" host="localhost" port="8082" path="mainData" doc:name="HTTP">
<cxf:jaxws-client doc:name="SOAP" serviceClass="com.test.services.schema.maindata.v1.MainData" operation="insertDataOperation" port="MainDataPort" />
</http:outbound-endpoint>
<custom-transformer class="com.test.request.ResponseTransformer" doc:name="JavaTransformerForResponse"/> <!-- Response Java Class -->
<mulexml:object-to-xml-transformer doc:name="Object to XML"/>
<logger message="#[message.payload]" level="INFO" doc:name="JSON Logging"/>
</flow>

Now It's working fine and response in Log is :-

Now Entering Method:: com.test.services.schema.maindata.v1.Impl.MainDataImpl.insertDataOperation() *****
Data inserted Successfully
[2014-07-31 13:06:23,150] [INFO ] [[SOAPHeaderInterceptor].connector.http.mule.default.receiver.04] <com.test.services.schema.maindata.v1.DataResponse>
  <response>Data inserted Successfully</response>
  <id>0</id>
  <age>0</age>
</com.test.services.schema.maindata.v1.DataResponse>

But I don't want to use Java component for response .. Please suggest how to set it using setpayload or Expression in Mule ... Please help ..

2
It's a JAXB marshalling issue so I reckon it's on the server side, right? Does the service work when you test it with SOAPui?David Dossot
yes .. The service is working fine David ... The issue is only from the client flow .. even when I trigger the client flow .the data are successfully posted to the main service (ServiceFlow) and data are inserted into Database but the exception are thrown at the end .. I guess it is the client flow that is unable to generate the response back .. Pls see the SOAP response .. there is the root object insertDataResponse .. and in the exception it is unable to marshal the root object ... I guess I need to set the payload in the same way for the response after outbound endpoint ..Anirban Sen Chowdhary
But I dont know how to do it ... is there any way I can display the response message in the client from the main service ?? do I need to set DataResponse object after outbound endpoint in Client ??Anirban Sen Chowdhary
Have you tried commenting out the async block to see if that's causing issues? Also another issue can come from when Mule builds the response of the ClientFlow: how do you want Mule to serialize the response object so it can be served over HTTP?David Dossot
I don't get it: the custom-transformer doesn't do anything to the payload (it gets it and sets it back, so it's a noop) but it sets the response content-type to "text/html", though the response is XML. Are you really sure this custom-transformer is necessary? What happens if you remove it?David Dossot

2 Answers

1
votes

You can remove the custom-transformer because it really doesn't do anything useful for you.

I believe the original:

unable to marshal type "com.test.services.schema.maindata.v1.DataResponse as an element because it is missing an @XmlRootElement annotation

issue was due to the fact that Mule needed a way to marshal the DataResponse object from the cxf:jaxws-client to a form that it could serve back over HTTP to the caller.

The addition of the mulexml:object-to-xml-transformer solved the issue by hinting Mule in how to marshal it (i.e. don't use JAXB because it just can't work, instead use XStream).

0
votes

So as per David's suggestion the final solution is using a object-to-json-transformer or object-to-xml-transformer or object-to-string-transformer any one can be used here to marshal the Response Object