I am trying to get the OS name available in my flow so I can adjust variable depending on the operating system running.
I am new to spring beans, but so far the below will call the set function ( I see it in the log) but I need to be able to access the osName from inside my flow.
java class:
public class CustomVariables {
public CustomVariables(){}
public String osName;
public String getOsName(){
System.out.println("got value: "+ osName);
return osName;
}
public void setOsName(String name){
osName = System.getProperty("os.name").toLowerCase();
System.out.println("set value: "+ osName); //this prints in console on startup
}
}
mule.xml:
<spring:beans>
<spring:bean class="netstockconnector.CustomVariables">
<spring:property name="osName" value="{os.name}"> </spring:property>
</spring:bean>
</spring:beans>
in flow:
<logger message="${osName}" level="INFO" doc:name="Logger"></logger>
This just prints to the console "${osName}" rather than "mac os x" for instance.
Any ideas?
There is a much simpler solution...
<logger message='#[System.getProperty("os.name")]' level="INFO" doc:name="Logger"></logger>
To trigger the Mule Expression Language, the expression to evaluate should be between #[expression to evaluate]. By default MEL imports a set of java classes which includes java.lang.System, hence the direct utilization in the expression.
Related
Trying to use the Mule XML streaming feature as have to process very large xml files. Followed the documentation, the document does not have concrete examples.
When I inspected the payload I get the XMLUtils class and not the XMLStreamReader class as stated in the documentation.
The flow is as follows have a file connector which passes payload to a custom transformer, the transformer passes the data to a spring bean which is going to have event based processing.
In the spring bean. At run time the spring bean gets the XMLUtils class and not the XMLStreamReader class.
Mule - Config:
<spring:beans>
<spring:bean id="OracleCDMMapper" class="oraclecdmstream.OracleCDMMapper">
</spring:bean>
<spring:bean id = "OraclePaySlip" class="com.nect.transform.OracleCDMPaySlip" ></spring:bean>
</spring:beans>
<flow name="mulefileconnectorexampleFlow1" >
<file:inbound-endpoint path="C:/c-OracleCloud/src/main/resources" pollingFrequency="600000" moveToDirectory="C:/c-OracleCloud/src/main/resources/back" doc:name="File Input" >
<!-- <file:filename-regex-filter pattern="(^*.xml$)" caseSensitive="false"/>
--> <file:filename-wildcard-filter pattern="*.xml"></file:filename-wildcard-filter>
</file:inbound-endpoint>
<logger message="Transferring file : #[message.inboundProperties['originalFilename']]" level="INFO" doc:name="Logger"/>
<logger message ="Logger 1 " level="INFO" doc:name ="Logger1" />
<!-- Call the XMLSTREAMER -->
**<custom-transformer name="XmlToXSR" class="org.mule.module.xml.transformer.XmlToXMLStreamReader" doc:name="XMLTOORACLE">**
</custom-transformer>
<component doc:name="Java">
<spring-object bean="OracleCDMMapper"/>
</component>
-->
<logger message ="I am Complete " level="INFO" doc:name ="LoggerMurali" />
</flow>
</mule>
Here is the Javacode:
Spring Bean
public class OracleCDMMapper implements Callable {
private final Logger logger = LoggerFactory.getLogger(OracleCDMMapper.class);
#Override
public Object onCall(MuleEventContext eventContext) throws Exception {
// TODO Auto-generated method stub
MuleMessage muleMessage = eventContext.getMessage();
logger.info("In the Spring Component");
logger.info(muleMessage.getPayload().getClass().toString());
**javax.xml.stream.XMLStreamReader xsr = (XMLStreamReader) muleMessage.getPayload(javax.xml.stream.XMLStreamReader.class);**
Any help will be much appreciated
I've verified and you are right, in the code the supposed returning class should be a DelegateXMLStreamReader class that implements XMLStreamReader, but the returned class is an anonymous inner class of XMLUtils that at runtime cannot be casted to any Stream like class. It seems to be a defect.
If you really need the control of the xml stream, you could use a custom java component:
<component class="com.foo.CustomJavaComponent" doc:name="Java"/>
.
public class CustomJavaComponent implements Callable{
#Override
public Object onCall(MuleEventContext eventContext) throws Exception {
MuleMessage muleMessage = eventContext.getMessage();
FileInputStream fis = (FileInputStream)muleMessage.getPayload();
//Do something with this stream
return "Hello world";
}
}
And get the input stream to do whatever you want.
In a soap based web service i want to access the Mule message properties. Is there a way of doing this i know one way of using RequestContext.getEvent().getMessage() but this i guess is deprecated. An other way of accessing the MuleMessage properties in the web service. Can someone please provide any pointers on this.
Code Snippet
<flow name="MyWebService" doc:name="MyWebService">
<http:inbound-endpoint exchange-pattern="request-response" address="${WEB_SERVICE_PROTOCOL}://${WEB_SERVICE_HOST}:${WEB_SERVICE_PORT}/MyWebService?wsdl" tracking:enable-default-events="true">
<cxf:jaxws-service serviceClass="com.XXX.XXX.service.MyWebService" doc:name="SOAP"/>
</http:inbound-endpoint>
<component doc:name="My Web Service">
<spring-object bean="WebServiceImpl"/>
</component>
</flow>
Depending on what is your purpose for obtaining the message properties, one option is to use a cxf interceptor to access the message. See the following example.
adding the interceptor:
<cxf:jaxws-service serviceClass="org.example.HelloWorld">
<cxf:inInterceptors>
<spring:bean class="org.example.MyInterceptor"/>
</cxf:inInterceptors>
</cxf:jaxws-service>
interceptor class:
package org.example;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.Phase;
import org.mule.api.MuleEvent;
import org.mule.api.MuleMessage;
public class MyInterceptor extends AbstractSoapInterceptor {
public MyInterceptor() {
super(Phase.USER_PROTOCOL);
}
#Override
public void handleMessage(SoapMessage message) throws Fault {
MuleEvent muleEvent = (MuleEvent)message.getContextualProperty("mule.event");
MuleMessage muleMessage = muleEvent.getMessage();
System.out.println(muleMessage.toString());
}
}
You can achieve this by not implementing the service interface at all and deal with the SOAP requests as Mule messages (where properties are accessible) instead of dealing with deserialized objects in service classes.
Here is an example fragment, assuming you've generated the necessary classes and interfaces from the WSDL with wsdl2java:
<flow name="WebServiceFlow">
<http:inbound-endpoint exchange-pattern="request-response"
address="http://localhost:8080/services/some" />
<cxf:jaxws-service
serviceClass="com.amce.SomePortType" />
<choice>
<when
expression="#[cxf_operation.localPart == 'SomeOperation']">
<flow-ref name="HandleSomeOperation" />
</when>
If you have access to MuleMessage then you get the required properties by using the method
Set<String> getPropertyNames(PropertyScope scope);
available in MuleMessage class. To get the MuleMessage you would need access to MuleClient; have you got access to MuleClient? if yes, then use:
muleClient = muleContext.getClient();
MuleMessage result = muleClient.send(webaddress, "", props);
Is this what you are trying to acheive?
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.
I have a main flow which begins with a http endpoint then a soap component which implements the interface and after a java component 1 that implements this interface. Now, I want to add a flow ref and after it a java component 2 that implements the same interface. I get the problem of "could not find entry point"
I am now following this tutorial blogs.mulesoft.org/mule-school-invoking-component-methods-using-entry-point-resolvers/
Given below is my flow.
<flow name="CreateAccountFlow1" doc:name="CreateAccountFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081"
doc:name="HTTP" path="bank"/>
<cxf:jaxws-service doc:name="SOAP" serviceClass="com.essai2.AccountService"/>
<component class="com.essai2.AccountRequest" doc:name="Java"/>
<logger level="INFO" doc:name="Logger"/>
<flow-ref name="Projet2Flow1" doc:name="Flow Reference"/>
<component class="com.essai2.AccountResponse" doc:name="Java"/>
<logger level="INFO" doc:name="Logger"/>
</flow>
Can anyone help me?
In mule there are many ways to invoke a Java component.
1. Entry point resolver
2. Implemnt mule Life Cycle API i.e callable
3. Invoke component.
when ever Mule finds Java component as message processors in a flow, tries to execute above three methods .
In the java component if you have created any methods with param same as mule message payload , Entry Point resolver is used.
eg : class XYZ{
method1(String s1){
}
method2(List<String> S2){
}
}
If Mule Message Payload has type String then method1 is invoked, if message payload has List of String , method2 is invoked during run time.
2. If you can invoke the Java component in the flow irrespective of type of the payload, should implement Callable interface which overrides onCall() method.
for eg : class XYS implements Callable{
#override
onCall(MuleEventConext muleEventConext){
}
using MuleEvent Conext you can extract the payload and process it.
3. Using Invoke component, you can create the object of the Class and invoke explicitly the method with appropriate Parameters passed.
I use mule to process the files from sftp, but I need to process the file in order(the sequence is order by name of file).
For example:
there are 3 files in sftp:
1.txt,2.txt,3.txt
I need to process these three files one by one and have to in the order of file's name.(first to process 1.txt then 2.txt at last 3.txt)
I use service-overrides in connector and extend the SftpMessageReceiver and override the poll() method ,in the method I make these files's name by order. But it doesn't work.Who can tell me where is wrong.
the class I write
public class NewSftpMessageReceiver extends SftpMessageReceiver {
private SftpReceiverRequesterUtil sftpRRUtil = null;
public NewSftpMessageReceiver(SftpConnector connector,
FlowConstruct flow,
InboundEndpoint endpoint,
long frequency) throws
CreateException {
super(connector, flow, endpoint);
this.setFrequency(frequency);
sftpRRUtil = new SftpReceiverRequesterUtil(endpoint);
}
public NewSftpMessageReceiver(SftpConnector connector, FlowConstruct flow, InboundEndpoint endpoint)
throws
CreateException {
super(connector, flow, endpoint);
sftpRRUtil = new SftpReceiverRequesterUtil(endpoint);
}
#Override
public void poll() throws
Exception {
try {
String[] files = sftpRRUtil.getAvailableFiles(false);
//do something here.....
for (String file : files) {
if (getLifecycleState().isStopping()) {
break;
}
routeFile(file);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
the config file like below
<sftp:connector name="incoming-mandate-connector"
archiveDir="${esb.archive.path}/mandate/incoming"
useTempFileTimestampSuffix="true"
autoDelete="true"
identityFile="${esb.incoming.sftp.identityFile}"
passphrase="${esb.incoming.sftp.passphrase}"
sizeCheckWaitTime="${esb.incoming.sftp.sizeCheckWaitTime}">
<service-overrides messageReceiver="com.xxy.NewSftpMessageReceiver"/>
</sftp:connector>
<sftp:endpoint name="incoming-mandate-ep"
address="${esb.incoming.connector}"
connector-ref="incoming-mandate-connector"
keepFileOnError="true" encoding="${esb.encoding}">
<file:filename-wildcard-filter pattern="${esb.incoming.filePattern}"/>
</sftp:endpoint>
the flow like blew
<flow name="process">
<quartz:inbound-endpoint name="quartz-endpoint" cronExpression="${esb.cronExpression}" jobName="incoming-mandate-job">
<quartz:endpoint-polling-job>
<quartz:job-endpoint ref="incoming-mandate-ep"/>
</quartz:endpoint-polling-job>
</quartz:inbound-endpoint>
<processor ref="mandate-processor"/>
<transformer ref="mandate-transformer"/>
<mulexml:jaxb-object-to-xml-transformer jaxbContext-ref="jaxb" name="mandate-jaxb-transformer"/>
<byte-array-to-string-transformer mimeType="application/xml"/>
<message-properties-transformer scope="outbound">
<add-message-property key="${esb.username}" value="${esb.password}"/>
</message-properties-transformer>
<outbound-endpoint ref= "mandate-service-ep"/>
</flow>
The reason why your message receiver is not being called is because you have a Quartz endpoint that calls the SFTP transport, so in fact you are using a message requester, not a receiver.
You would need to create a custom message requester instead of a receiver and also a custom requester factory (that creates instances of the requester)
You can configure it as follows:
<sftp:connector name="sftpConnector">
<spring:property name="serviceOverrides">
<spring:map>
<spring:entry key="requester.factory" value="your.package.YourCustomSftpRequesterFactory"/>
</spring:map>
</spring:property>
</ftp:connector>