How to invoke a webservice with dataFormat as PAYLOAD - apache

I'm using camel 2.16.0
Created a camel route to invoke a web service, dataFormat as MESSAGE and i get the response normally.
and this route is invoked using ProducerTemlate
//payloadXml is a string which contains SOAP Request Message.
Object response = producerTemplate.requestBody("direct:invokeWS", payloadXml);
<route id="my_Sample_Camel_Route_with_CXF">
<from uri="direct:invokeWS" />
<to uri="cxf://http://localhost:8111/camel_MQ/TestService?wsdlURL=http://localhost:8111/camel_MQ/TestService?wsdl&serviceName={http://www.test.org/interface/test/ws}camel_MQ-ws&portName={http://www.test.org/interface/test}TestEndpoint&dataFormat=MESSAGE" />
<log message="------------->> ${body}" />
</route>
But once i change the dataFormat to "PAYLOAD"
I get exception.
Caused by: java.lang.IllegalArgumentException: The PayLoad elements cannot fit with the message parts of the BindingOperation. Please check the BindingOperation and PayLoadMessage.
at org.apache.camel.component.cxf.CxfEndpoint$CamelCxfClientImpl.setParameters(CxfEndpoint.java:1171)
Tried creating CxfPayload and then sent that to producerTeamplate while invoking the WS, but still the same Exception,

Finally I'm able to invoke WS using dataFormat as payload.
created CxfPayload object and added SOAP Headers and Body to it.
But still i was getting the same exception "The PayLoad elements cannot fit with the message parts of the BindingOperation"
Then I added defaultOperationName & defaultOperationNamespace headers while invoking the webservice as shown below.
<to uri="cxf:bean:camel_MQ_MQ-ws?dataFormat=PAYLOAD&defaultOperationName=TestService&defaultOperationNamespace=http://www.camel_MQ.org/interface&loggingFeatureEnabled=true" />
hope this helps ;-)

Related

Set Inbound Properties for MUnit Flow Reference in Mulesoft for APIKit

I'm trying to test APIKit in MUnit. Originally I was using an http request within MUnit to call my flow and then APIKit would route the request to the proper subflow where my logic lives. Now I want to mock one of the elements of the subflow, so I'm trying to replace the http request with a reference to the APIKit flow. This works, but the APIKit router throws an error:
Cannot resolve request base path
Because none of the inbound properties are set. And this is my problem, how do I mimic the inbound properties that I send to a flow reference so that the request looks like it came from an HTTP request? Alternatively, is there another way I can structure the code so that I can mock an element of my logic?
Thanks
You can add properties on your mock http response. See sample below:
<mock:when messageProcessor=".*:.*" doc:name="Queue Message">
<mock:with-attributes>
<mock:with-attribute name="doc:name" whereValue="#['Queue Message']"/>
</mock:with-attributes>
<mock:then-return payload="#['Sample response']">
<mock:inbound-properties>
<mock:inbound-property key="prop1" value="val1"/>
<mock:inbound-property key="prop2" value="val2"/>
</mock:inbound-properties>
</mock:then-return>
</mock:when>
Hope this helps
You can use set message processor before the flow reference to set payload and properties. Please refer to the following code
<munit:before-suite name="twitter_munit_testBefore_Suite" description="MUnit Test">
<scripting:component doc:name="Script">
<scripting:script name="groovyScriptPayloadGenerator" engine="Groovy"><![CDATA[
import groovy.json.JsonSlurper
def jsonSlurper = new JsonSlurper()
def object = jsonSlurper.parseText '''
{ "positive": 15,
"negative": 5,
"neutral": 0
}''']]></scripting:script>
</scripting:component>
</munit:before-suite>
<munit:test name="new-test-suite-tetsFlowTest" description="Test">
<munit:set payload="#[resultOfScript('groovyScriptPayloadGenerator')]" doc:name="Set Message">
<munit:inbound-properties>
<munit:inbound-property key="http.query.params" value="#[['query':'value']]"/>
</munit:inbound-properties>
</munit:set>
<flow-ref name="tetsFlow" doc:name="Flow-ref to tetsFlow"/>
</munit:test>
Also check this for more details.
Same way you can configure mock also.
Hope this helps..

Error sending HTTP request. Message payload is of type: LinkedHashMap [MULE ESB]

I'm new in MULE ESB, I have this code and i'm trying sending a http request using http:request with the following format:
"http: //www.host.com/api/commentThreads?key=val&part=val2&..."
<file:inbound-endpoint connector-ref="fileConnector" path="C:/tmp/input"
doc:name="Reader File Configuration" responseTimeout="10000"
encoding="UTF-8" mimeType="text/plain"
pollingFrequency="20000">
<file:filename-wildcard-filter pattern="*.json"/>
</file:inbound-endpoint>
<json:json-to-object-transformer returnClass="java.util.Map" doc:name="JSON to Object"/>
<logger level="INFO" message="#[payload]" doc:name="Logger" />
<http:request config-ref="HTTP_Request_Configuration" path="/commentThreads" method="GET" port="443" doc:name="HTTP Request">
<http:request-builder>
<http:query-param paramName="key" value="#[message.payload.key]"/>
<http:query-param paramName="allThreadsRelatedToChannelId" value="#[message.payload.allThreadsRelatedToChannelId]"/>
<http:query-param paramName="part" value="#[message.payload.part]"/>
</http:request-builder>
</http:request>
But I'm having this error:
Message : Error sendinbut g HTTP request. Message payload is of type: LinkedHashMap
Code : MULE_ERROR--2
Exception stack is:
null (java.util.concurrent.TimeoutException) org.glassfish.grizzly.impl.SafeFutureImpl$Sync:357 (null)
Error sending HTTP request. Message payload is of type: LinkedHashMap (org.mule.api.MessagingException)
org.mule.module.http.internal.request.DefaultHttpRequester:190
(http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/MessagingException.html)
The question is how can I do to make a http request with that format using the map?
According to documents
https://www.mulesoft.org/documentation/display/current/HTTP+Request+Connector#HTTPRequestConnector-HTTPRequestBody
The Mule Message payload is converted into a byte array and sent as
the HTTP Request's body. This behavior is carried out always, except
in the following scenarios:
The Mule Message's Payload is a Map of keys and values
Generate the Request Body with
Content-Type:application/x-form-urlencoded
Whenever the message payload is a Map, the connector automatically
generates an HTTP request with the header
Content-Type:application/x-www-form-urlencoded. The keys and values of
the map in the payload are converted into form parameter keys and
values in the body of the HTTP request.
I suppose the map is converter automatically for the request. Correct me if I'm wrong
It was necessary to make a transformation before the
<json: json-to-object-transformer returnClass = "java.util.Map" doc: name = "JSON to Object" />
It is corrected by putting
<byte-array-to-string-transformer doc: name = "Byte Array to String" />
The error you're getting actually is not because your request has something wrong (or at least is not failing at that stage) but that your app is not being able to connect to the http server you're trying to send the request to. You can infer this by the exception you're getting java.util.concurrent.TimeoutException.
In order to troubleshoot please verify the host name and port are typed correctly.

Removing the "Host" and "org.apache.cxf.request.uri" headers from the camel exchange

I have a problem with removing the "Host" and "org.apache.cxf.request.uri" headers from the In Message in camel exchange. I'm using a cxfrs client to call a rest end point. But before calling that I used removeHeaders tag and removed some unnecessary headers from the exchange. Some of the headers are removed. But I was unable to remove "Host" and "org.apache.cxf.request.uri" headers. They are temporarily removed from the flow just after the removeHeaders call. But they appear in the request call headers when calling using the cxf rs client. Following is a sample from my scenario.
...............................
..............................
${property.asd} == true && ${property.afd} == true
**<to uri="direct:removeUnnecessaryHeaders" />**
<setHeader headerName="CamelCxfRsUsingHttpAPI">
<constant>true</constant>
</setHeader>
<setHeader headerName="CamelHttpMethod">
<constant>PUT</constant>
</setHeader>
<setHeader headerName="CamelHttpPath">
<constant>/partner/managepartnerprofile</constant>
</setHeader>
<to uri="cxfrs:bean:aclient"/>
</when>
..................................
.................................
**<route>
<from uri="direct:removeUnnecessaryHeaders" />
<removeHeaders pattern="CamelCxfRsResponseGenericType|org.apache.cxf.request.uri|CamelCxfMessage|CamelHttpResponseCode|Host" />
</route>**
I just did some test and found out these headers was suppose to tell CXF how to build the request with WebClient and them should not be treated as the HTTP protocol headers.
You can use camel-http or camel-http4 endpoint if you don't want to send the those headers to the server.

Null exception thrown when running mule, when a devkit 3.0.0 method that takes a #InboundAttachments param

I'm trying to make use of #attachment http properties
I have a devkit method called validate in a flow that is called like so
<http:connector name="httpConnector" doc:name="HTTP\HTTPS">
<service-overrides
messageFactory="org.mule.transport.http.HttpMultipartMuleMessageFactory" />
</http:connector>
<flow name="AttachmentTestFlow1" doc:name="AttachmentTestFlow1">
<http:inbound-endpoint connector-ref="httpConnector" doc:name="HTTP" exchange-pattern="request-response" host="localhost" port="8100"/>
<Foo:validate config-ref="TestMessageSizeHappy" />
</flow>
In Devkit:
#Processor
public Object validate(#Payload InputStream in
,#InboundAttachments("*") Map<String, DataHandler> inboundAttachments
,#OutboundAttachments Map<String, DataHandler> outboundAttachments
) {
however when running my mule application this is thrown:
ERROR 2013-07-30 09:06:39,225 [main]
org.mule.module.launcher.application.DefaultMuleApplication: null
org.xml.sax.SAXParseException: cvc-complex-type.2.4.b: The content of
element 'xmlthreatprotection:validate' is not complete. One of
'{"http://www.mulesoft.org/schema/mule/core":annotations,
"http://www.mulesoft.org/schema/mule/xmlthreatprotection":inbound-attachments}'
is expected. at
org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown
Source)
It seems to me that mule expects the attachments to be put in as an attribute some how !
When I remove the #attachment stuff I get no errors at runtime.
Are you sure this is supported by DevKit? I can not find a single integration test in the source code that exercises #InboundAttachments and #OutboundAttachments annotations, while #InboundHeaders and #OutboundHeaders are both test covered.
Alternatively you can receive the MuleEvent and access the attachments through it:
#Processor
#Inject
public Object validate(#Payload InputStream in, MuleEvent muleEvent) {

XMLStreamReader parser affects MuleEventContext

I'm using Mule Studio (Mule 3.2.1CE) to configure a proxy service which simply calls a remote web service. Everything works fine with calling and getting the proper response (using soapUI). I want to log SOAP message received within the ESB. I'm getting a DepthXMLStreamReader message as expected by the CXF component but I'm facing an odd behavior when I use XMLStreamReader object's next() method. Here is the code I use:
public Object onCall(MuleEventContext context) throws Exception {
MuleMessage message = context.getMessage();
DepthXMLStreamReader streamReader = new DepthXMLStreamReader((XMLStreamReader) message.getPayload());
while(streamReader.hasNext()){
streamReader.next();
if(streamReader.getEventType() == XMLStreamReader.START_ELEMENT)
{
System.out.println(streamReader.getLocalName());
}
}
return context.getMessageAsString();
The above code works and prints XML elements but I get the following error afterwards:
org.apache.cxf.interceptor.Fault: Failed to route event via endpoint: DefaultOutboundEndpoint{endpointUri=..., connector=HttpConnector
...
Caused by: org.mule.transport.http.HttpResponseException: Internal Server Error, code: 500
I tried using StaxUtils.nextEvent and StaxUtils.toNextElement, but no difference in result. I wonder why parsing XML by next() method affects mule context. If I use System.out.println(context.getMessageAsString()); before the return statement it prints "[Messaage could not be converted to string]" but it works before while statement in the above code.
Here is my mule config:
<flow name="wsFlow1" doc:name="wsFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8090" contentType="text/xml" doc:name="HTTP"/>
<cxf:proxy-service bindingId="..." namespace="http://..." service="..." payload="body" wsdlLocation="..." enableMuleSoapHeaders="false" doc:name="SOAP"/>
<component class="mule.ws.SoapLogging" doc:name="Java"/>
<http:outbound-endpoint exchange-pattern="request-response" address="http://..." contentType="text/xml" doc:name="HTTP"/>
</flow>
Thanks
I don't think this is related to MuleEventContext.
The in-flight payload is a XMLStreamReader. You consume this XMLStreamReader in your component then try to return a String representation of it, which is not possible anymore because you've consumed it.
Try the following in your component:
Serialize the XMLStreamReader to a String
Log this String or part thereof
Return this String from the component.