Facing issue in mule testing - mule

I am facing problem with mule testing. I just tries out simple functional testing example.
following is my flow
<flow name="muletestFlow1" doc:name="muletestFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="test" doc:name="HTTP"/>
<response>
<object-to-string-transformer />
</response>
<component class="com.org.Square" doc:name="Square"/>
<component class="com.org.Neg doc:name="Neg"/>
</flow>
and following is my testing class
#Test
public void testSquareAddInverse() throws Exception {
MuleClient client = muleContext.getClient();
MuleMessage reply = client.send ("http://localhost:8081/test", "3", null, 5000);
assertNotNull(reply);
assertNotNull(reply.getPayload());
assertTrue(reply.getPayload() instanceof String);
String result = (String)reply.getPayload();
assertEquals("-9", result);
If i run above class as junit test then got following error.
java.lang.AssertionError
at org.junit.Assert.fail(Assert.java:92)
at org.junit.Assert.assertTrue(Assert.java:43)
at org.junit.Assert.assertTrue(Assert.java:54)
at com.test.TestEx.testSquareAddInverse(TestEx.java:25)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:622)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:46)
at org.junit.internal.runners.statements.FailOnTimeout$1.run(FailOnTimeout.java:28)
What is the solution please help me.
If i comment this line
assertTrue(reply.getPayload() instanceof String);
then got following error.
java.lang.ClassCastException: org.mule.transport.http.ReleasingInputStream cannot be cast to java.lang.String
What is the wrong in this code? How can i solve this problem. please help me
Thanks in advance

Since you call the flow through http protocol, which implicitly transforms the payload type. So the reply in the unit test will not contain a String but a InputStream. This is expected so you should test for a InputStream instead of a String. To get the value as a String you can use the method MuleMessage#getPayload(java.lang.Class) that will transform the payload to a String using the registered transformers.
#Test
public void testGetNegaiveNine() throws Exception {
MuleClient client = muleContext.getClient();
MuleMessage reply = client.send ("http://localhost:8081/test", "3", null, 5000);
assertNotNull(reply);
assertNotNull(reply.getPayload());
assertTrue(reply.getPayload() instanceof InputStream);
String result = reply.getPayload(String.class);
assertEquals("-9", result);
}
The exception you get in the flow
after that.
"DefaultJavaComponent{muletestFlow1.component.3418143}. Message payload is of type: ContentLengthInputStream"
is because the components can not handle the payload that the message inside your flow has. Since you are sending a HTTP POST into the flow the payload of the incoming message is a ContenLengthInputStream and you components expects a String.
So you will have to transform the payload into a String by adding a object-to-string transformer before the components. The complete flow would then be something like this.
<flow name="muletestFlow1" doc:name="muletestFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="test" doc:name="HTTP"/>
<response>
<!-- Ensure that the response is a String -->
<object-to-string-transformer />
</response>
<!-- Ensure that the incoming request is a String -->
<object-to-string-transformer />
<component class="com.org.Square" doc:name="Square"/>
<component class="com.org.Neg doc:name="Neg"/>
</flow>

Related

How to read an XML file in Mule Anypoint Studio after invoking an HTTP endpoint?

I am new to Anypoint Studio and I am trying to create a flow that will have an HTTP connector and an endpoint and when a user invokes the http endpoint then the application will load the contents of an XML file, will convert then to JSON and will return the JSON back in the HTTP Response.
My flow configuration looks like this
<flow name="test-flow">
<http:listener config-ref="HttpListenerConfiguration" path="/read" allowedMethods="POST" doc:name="HTTP">
<http:response-builder statusCode="200">
<http:header headerName="Content-Type" value="application/json"/>
</http:response-builder>
</http:listener>
<file:inbound-endpoint path="xml/test.xml" responseTimeout="10000" doc:name="File"/>
<mulexml:xml-to-object-transformer returnClass="org.mule.examples.Catalog" doc:name="XML to Object"/>
<json:object-to-json-transformer sourceClass="org.mule.examples.Catalog" doc:name="Object to JSON"/>
</flow>
Of course it doesn't work. I get a
SAXParseException: cvc-complex-type.2.4.a: Invalid content was found starting with element 'file:inbound-endpoint'. One of '{"http://www.mulesoft.org/schema/mule/core":abstract-message-processor, "http://www.mulesoft.org/schema/mule/core":abstract-outbound-endpoint, "http://www.mulesoft.org/schema/mule/core":abstract-mixed-content-message-processor, "http://www.mulesoft.org/schema/mule/core":response}' is expected.
which I assume is coming from the fact that <file:inbound-endpoint...> needs to be as a source in the flow.
Any suggestions on how can I read a file after an HTTP endpoint is invoked?
Thanks
As you correctly assumed, file:inbound-endpoint can only act as a message source. Thus to achieve what you want you can use the mule module requester. HTH.
Try the requester module. It will allow you to load the file at any point in the flow. You can read more about it in this blogpost.
Also you can use XML to Json inbuilt transformer in to convert it to a Json object.
<http:listener-config name="HTTP_Listener_Configuration" host="localhost" port="8081" doc:name="HTTP Listener Configuration"/>
<flow name="test-flow1">
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
<json:xml-to-json-transformer doc:name="XML to JSON"/>
<logger message="#[message.payload]" level="INFO" doc:name="Logger"/>
</flow>
If the XML file is on the classpath, you might try <parse-template location="xml/test.xml"> instead of your <file:inbound-endpoint />
The parse-template processor comes in handy surprisingly often. The User's Guide also has a nice reference for it.
You can also write a java component to read the content of the file and use that component in the flow.
Example:
public class FileReaderComponent implements Callable, Initialisable {
private String filePath;
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
#Override
public void initialise() throws InitialisationException {
if (filePath == null || filePath.equals("")) {
throw new InitialisationException(MessageFactory.createStaticMessage("FilePath property has to be set"), this);
}
}
#Override
public Object onCall(MuleEventContext eventContext) throws Exception {
BufferedReader in = null;
try {
in = new BufferedReader(new FileReader(new File(filePath)));
} catch (Exception e) {
//Handle Exception
}
StringBuilder content = new StringBuilder();
try {
String line;
while ((line = in.readLine()) != null) {
content.append(line);
}
}catch (Exception e) {
//Handle Exception
} finally {
in.close();
}
return content.toString();
}
}
As many suggested in above, you can use java component or some kind of parse template.
We also had same kind of requirement , we used the expression component to read the file from particular location

Mule: How Access Field in Pojo From JSON To Object

I building Mule project who receive JSON by HTTPComponent and convet to object.
My problem is can't acess field in object converted.
My flux's XML is:
<flow name="RestJsonHelloWorldFlow1" doc:name="RestJsonHelloWorldFlow1"><http:inbound-endpointexchange-pattern="request-response"
host="localhost" port="8081"
path="credit/new" doc:name="HTTP"
mimeType="application/json"/> <response>
<logger message=" #[message.payload.transactionCode]" level="INFO" doc:name="Logger"/>
</response>
<json:json-to-object-transformer doc:name="JSON to Object" returnClass="com.creditmobile.domain.Request" name="request"/></flow>
My pojo is:
#JsonAutoDetect
public class Request {
private Integer transactionCode;
public Request() {
super();
}
public Integer getTransactionCode() {
return transactionCode;
}
My JSON is:
{
"transactionCode": 1
}
I got following exception:
org.mule.api.transformer.TransformerMessagingException: The object transformed is of type: "SimpleDataType{type=java.lang.String, mimeType='*/*'}", but the expected return type is "SimpleDataType{type=org.mule.api.transport.OutputHandler, mimeType='application/json'}". The current MuleMessage is null! Please report this to dev#mule.codehaus.org
at org.mule.transformer.AbstractMessageTransformer.checkReturnClass(AbstractMessageTransformer.java:183)
at org.mule.transformer.AbstractMessageTransformer.transform(AbstractMessageTransformer.java:162)
at org.mule.transformer.AbstractMessageTransformer.transform(AbstractMessageTransformer.java:73)
+ 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
I saw anothers topics with same problem, but they don't have resolution and yours suggesttion doesn't work for me.
I access field with:[message.payload.transactionCode]
Thanks.
I think your problem is in the http response phase, not in accessing the field. Mule gets confused when you try to return your Java object as an http response. Depending on your requirements, try setting the return payload to something more understandable in the response phase. For example
<set-payload value="#[payload.transactionCode.toString()]"/>
or
<json:object-to-json-transformer/>
What do you actually want to return to the user once the application exits RestJsonHelloWorldFlow1 flow?
I think as Anton Kupias said your problem is the tag. I managed to solve the exception by removing the tag, and convert the payload into an object exactly after the HTTP inbound endpoint.
Config XML
<flow name="RestJsonHelloWorldFlow1" doc:name="RestJsonHelloWorldFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="credit/new"
doc:name="HTTP" mimeType="application/json" />
<json:json-to-object-transformer
doc:name="JSON to Object" returnClass="com.creditmobile.domain.Request" />
<component class="com.creditmobile.domain.TransactionResponse" doc:name="Java"/>
<object-to-string-transformer doc:name="Object to String"/>
</flow>
basically you have
1) An HTTP inbound endpoint which is set to request-response
2) immediately convert the JSON to Object
3) Then I have created a java component to perform the required processing; by creating a class which implements org.mule.api.lifecycle.Callable. Got the transaction code from the payload and set the overridden method to return an object of type string
public class TransactionResponse implements Callable {
#Override
public Object onCall(MuleEventContext eventContext) throws Exception {
// Type casts payload to object Request
Request requestObject = (Request) eventContext.getMessage().getPayload();
int code = Integer.valueOf(requestObject.getTransactionCode());
String reply = "";
switch (code) {
case 1:
reply = "New";
break;
case 2:
reply = "Delete";
break;
}
return reply;
}
}
4) Then i terminated the flow by adding the Object to String component, Or place the Object to JSON component if you wish to return a JSON object to the user.

Mule: No Receiver registered error during Functional Test case run

I was trying to develop a Functional Test case for my mule configuration. Here is the code:
protected String getConfigResources() {
// TODO Auto-generated method stub
return "src/test/resources/employee-get-functionalTestCase-config.xml";
}
#Test
public void testMessage() throws Exception {
MuleClient client = muleContext.getClient();
client.dispatch("vm://in", "70009", null);
MuleMessage result = client.request("vm://out", 60000);
Assert.assertNotNull("Response payload was null", result);
Assert.assertNull(result.getExceptionPayload());
Assert.assertFalse(result.getPayload() instanceof NullPayload);
& here is the context of my XMl file:
<spring:beans>
<context:property-placeholder location="classpath:mule-app.properties"/>
</spring:beans>
<flow name="testFlow">
<vm:inbound-endpoint path="in"/>
<logger message="in functional-test-config.xml (v4)" level="INFO" doc:name="Logger"/>
<set-payload value="70010" doc:name="Use fixed employeeId 70010"/>
<vm:outbound-endpoint exchange-pattern="request-response" path="employee-profile-get" doc:name="VM"/>
<logger message="after employee-profile-get; payload: #[payload]" level="INFO" doc:name="Logger"/>
<vm:outbound-endpoint path="out"/>
</flow>
However when I execute this code, I get the following error:
org.mule.api.transport.NoReceiverForEndpointException: There is no receiver registered on connector "connector.VM.mule.default" for endpointUri vm://employee-profile-get
Where do I register the vm endpoint?
You must have an inbound endpoint for every exchange-pattern="request-response" vm endpoint .
When the application is run in your mule studio you may not get any error(at compile time ) but when the message is passed through the flow you will get an error of the above mentioned sort .
This is because VM is an in-memory queue ,where once you put a message, there should be a receiver to pick the message thus when not there this error pops and it is only for the exchange-pattern="request-response" because the flow from where you put the message(outbound endpoint with request-response) will wait for a response from the vm endpoint "employee-profile-get" .
To depict the same error replace the with a localhost http endpoint and try invoking the http endpoint .
To avoid this create another flow with inbound endpoint as vm with path="employee-profile-get" and return a string using set payload component .Then your test case would work.
Regards,
Naveen Raj

Mule: process expression evaluator

I'm trying to use the expression #[process:processName:valueToProcess] in my flow.
This is my flow config:
<flow name="exampleFlow">
<quartz:inbound-endpoint jobName="job1" cronExpression="0/5 * * * * ?" connector-ref="quartzConnector">
<quartz:event-generator-job>
<quartz:payload>foo</quartz:payload>
</quartz:event-generator-job>
</quartz:inbound-endpoint>
<logger message="#[process:test:#[payload]]" level="INFO"/>
</flow>
<sub-flow name="test" doc:name="test">
<component class="com.myComp.ComponentTest" doc:name="Java"/>
</sub-flow>
And this is my Java Component:
package com.myComp;
public class ComponentTest
{
public String test(String s)
{
return s + "bar";
}
}
The problem comes when the expression #[process:test:#[payload]] is evaluated. It throws this exception:
java.lang.NullPointerException
at org.mule.component.AbstractComponent.invokeInternal(AbstractComponent.java:112)
at org.mule.component.AbstractComponent.process(AbstractComponent.java:156)
at org.mule.processor.chain.DefaultMessageProcessorChain.doProcess(DefaultMessageProcessorChain.java:99)
at org.mule.processor.chain.AbstractMessageProcessorChain.process(AbstractMessageProcessorChain.java:66)
at org.mule.processor.chain.InterceptingChainLifecycleWrapper.doProcess(InterceptingChainLifecycleWrapper.java:56)
at org.mule.processor.chain.AbstractMessageProcessorChain.process(AbstractMessageProcessorChain.java:66)
at org.mule.processor.chain.InterceptingChainLifecycleWrapper.process(InterceptingChainLifecycleWrapper.java:87)
at org.mule.api.processor.MessageProcessors$LifecyleAwareMessageProcessorWrapper.process(MessageProcessors.java:114)
at org.mule.expression.MessageProcessorExpressionEvaluator.evaluate(MessageProcessorExpressionEvaluator.java:87)
at org.mule.expression.DefaultExpressionManager.evaluate(DefaultExpressionManager.java:273)
at org.mule.expression.DefaultExpressionManager.evaluate(DefaultExpressionManager.java:209)
at org.mule.expression.DefaultExpressionManager$1.match(DefaultExpressionManager.java:399)
at org.mule.util.TemplateParser.parse(TemplateParser.java:156)
at org.mule.util.TemplateParser.parse(TemplateParser.java:133)
at org.mule.expression.DefaultExpressionManager.parse(DefaultExpressionManager.java:395)
at org.mule.expression.DefaultExpressionManager.parse(DefaultExpressionManager.java:379)
at org.mule.api.processor.LoggerMessageProcessor.log(LoggerMessageProcessor.java:89)
at org.mule.api.processor.LoggerMessageProcessor.process(LoggerMessageProcessor.java:71)
at org.mule.processor.chain.DefaultMessageProcessorChain.doProcess(DefaultMessageProcessorChain.java:99)
at org.mule.processor.chain.AbstractMessageProcessorChain.process(AbstractMessageProcessorChain.java:66)
at org.mule.processor.AbstractInterceptingMessageProcessorBase.processNext(AbstractInterceptingMessageProcessorBase.java:105)
at org.mule.interceptor.AbstractEnvelopeInterceptor.process(AbstractEnvelopeInterceptor.java:55)
at org.mule.processor.AsyncInterceptingMessageProcessor.processNextTimed(AsyncInterceptingMessageProcessor.java:111)
at org.mule.processor.AsyncInterceptingMessageProcessor$AsyncMessageProcessorWorker.doRun(AsyncInterceptingMessageProcessor.java:158)
at org.mule.work.AbstractMuleEventWork.run(AbstractMuleEventWork.java:43)
at org.mule.work.WorkerContext.run(WorkerContext.java:310)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
The same happens with any other scripting component.
I'm guessing it has something to do with my component lifecycle, but I couldn't find a way to make it work.
If I replace my component with any other Mule processor (e.g. logger, stringAppend) it works fine.
Any help will be appreciated!
You're right when you say it's an initialization issue: for any reason, components in a sub-flow are not initialized the same way they are in a flow, ie. this works:
<flow name="test" doc:name="test">
<component class="com.myComp.ComponentTest" doc:name="Java"/>
</flow>
I believe this is a bug hence I reported it. Please upvote the issue.
To make this work with an asynchronous event, like the ones the Quartz inbound endpoint generates, you will need to add processingStrategy="synchronous" to the called flow in order to invoke in synchronously, otherwise by default it will be invoke asynchronously (even if process:test:#[payload] expects a synchronous response). That's a known quirk in Mule 3.
So the end solution is:
<flow name="test" processingStrategy="synchronous" doc:name="test">
<component class="com.myComp.ComponentTest" doc:name="Java"/>
</flow>

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.