How to pass Mule expression to spring property - spring

I'm looking for a way to assign an exception message to spring property at runtime in mule flow (Mule 3.3.0)
This is how my code-snippet looks like:
<catch-exception-strategy>
<logger message="----->Exception is #[exception.causeException]"
level="INFO" />
<custom-transformer
class="com.company.transformer.VelocityMessageTransformer">
<spring:property name="velocityEngine" ref="velocityEngine" />
<spring:property name="templateName" value="soap11Fault.vm" />
<spring:property name="beanClass">
<spring:bean parent="abstractSoap11ClientFault">
<spring:property name="faultString" value="Invalid Request" />
<spring:property name="detail" value="${exception.causeException}" />
</spring:bean>
</spring:property>
</custom-transformer>
</catch-exception-strategy>
I want to assign exception cause to detail property here:
<spring:property name="detail" value="${exception.causeException}" />
but spring is looking for this property in properties file. I tried doing this also
<spring:property name="detail" value="${#[exception.causeException]}" /> but doesn't work.
Is there a way to pass Mule expression at run-time to Spring property?

Properties are set during the application initialization: the value you want to pass is evaluated at runtime, so that can't work.
What you need to do is make com.company.transformer.VelocityMessageTransformer extend org.mule.transformer.AbstractMessageTransformer. You will then have to override transformMessage(MuleMessage message, String outputEncoding), which will give you access to the current message and its associated exception payload. The exception payload is what you get with the #[exception] expression.

Related

How to fix java.lang.IllegalArgumentException: null source?

In mule flow, I have configured XA datasource for XA transaction as following and also jboss transaction management
<jbossts:transaction-manager doc:name="Transaction Manager">
<property key="com.arjuna.ats.arjuna.coordinator.defaultTimeout"
value="3000" />
<property key="com.arjuna.ats.arjuna.coordinator.txReaperTimeout"
value="300000" />
</jbossts:transaction-manager>
<spring:beans>
<spring:bean id="mySqlXADataSource" name="MySqlXADataSource"
class="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource">
<spring:property name="user" value="${ftp.db.user}" />
<spring:property name="password" value="${ftp.db.password}" />
<spring:property name="url"
value="${ftp.db.url}" />
</spring:bean>
</spring:beans>
<jdbc-ee:connector name="FTPDatabase" dataSource-ref="mySqlXADataSource"
validateConnections="true" queryTimeout="-1" pollingFrequency="0"
doc:name="Database">
<reconnect blocking="false" frequency="10000" count="3" />
</jdbc-ee:connector>
But i am facing following exception at runtime
Exception stack is:
1. null source (java.lang.IllegalArgumentException)
java.util.EventObject:56 (null)
2. Failed to route event via endpoint: DefaultOutboundEndpoint{endpointUri=jdbc://FetchFTPConfig, connector=EEJdbcConnector
{
name=FTPDatabase
lifecycle=start
this=3dbe005a
numberOfConcurrentTransactedReceivers=4
createMultipleTransactedReceivers=false
connected=true
supportedProtocols=[jdbc]
serviceOverrides=<none>
}
, name='endpoint.jdbc.FetchFTPConfig', mep=REQUEST_RESPONSE, properties={queryTimeout=-1, queries=merged: {FetchFTPConfig=SELECT SRC.C_BSF_ACKNWLDGMNT AS C_BSF_ACKNWLDGMNT, FTP.C_BFA_IPADDR AS C_BFA_IPADDR, FTP.C_BFA_PORT AS C_BFA_PORT, FTP.C_BFA_OWNR AS C_BFA_OWNR, FTP.C_BFA_PATH AS C_BFA_PATH, FTP.C_BFA_PSSWRD AS C_BFA_PSSWRD, FTP.C_BFA_USRNM AS C_BFA_USRNM,SRC.C_BSF_FILE_TYPE_ID AS C_BSF_FILE_TYPE_ID from T_BMRS_SRC_FILES AS SRC,T_BMRS_FILETYPE AS FTYPE,T_BMRS_FTP_ACCNTS FTP where SRC.C_BSF_FILE_TYPE_ID=FTYPE.C_BFT_ID and FTYPE.C_BFT_BFA_KEY=FTP.C_BFA_KEY and SRC.C_BSF_FILE_UNIQUEID=#[flowVars.FileId];}}, transactionConfig=Transaction{factory=org.mule.transaction.XaTransactionFactory#3726423c, action=BEGIN_OR_JOIN, timeout=30000}, deleteUnacceptedMessages=false, initialState=started, responseTimeout=10000, endpointEncoding=UTF-8, disableTransportTransformer=false}. Message payload is of type: NotifyESBRequest (org.mule.api.transport.DispatchException)
org.mule.transport.AbstractMessageDispatcher:105 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/transport/DispatchException.html)
--------------------------------------------------------------------------------
Root Exception stack trace:
java.lang.IllegalArgumentException: null source
at java.util.EventObject.<init>(EventObject.java:56)
at javax.sql.StatementEvent.<init>(StatementEvent.java:64)
at com.mysql.jdbc.jdbc2.optional.JDBC4PreparedStatementWrapper.close(JDBC4PreparedStatementWrapper.java:70)
+ 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
Mysql connector i am using is mysql-connector-java-5.1.36 jar.

Dynamic URL for Custom Http-Client - Spring-XD

We have written a custom Http-client for spring XD and planning to use this custom processor for invoking different APIs. However, We have a situation where we need to invoke two different API based on the payload. Apart from using dynamic-router (which writes to a named channel) is there a way we can set the URL dynamically for the http-client to invoke? Here is the current configuration.
<header-filter input-channel="input" output-channel="inputX"
header-names="x-death" />
<service-activator input-channel="inputX" ref="gw" />
<gateway id="gw" default-request-channel="toHttp"
default-reply-timeout="0" error-channel="errors" />
<beans:bean id="inputfields"
class="com.batch.httpclient.HTTPInputProperties">
<beans:property name="nonRetryErrorCodes" value="${nonRetryErrorCodes}" />
</beans:bean>
<beans:bean id="responseInterceptor"
class="com.batch.httpclient.ResponseInterceptor">
<beans:property name="inputProperties" ref="inputfields" />
</beans:bean>
<chain input-channel="errors" output-channel="output">
<transformer ref="responseInterceptor" />
</chain>
<int-http:outbound-gateway id='batch-http'
header-mapper="headerMapper" request-channel='toHttp' url-expression="${url}"
http-method="${httpMethod}" expected-response-type='java.lang.String'
charset='${charset}' reply-timeout='${replyTimeout}' reply-channel='output'>
</int-http:outbound-gateway>
<beans:bean id="headerMapper"
class="org.springframework.integration.http.support.DefaultHttpHeaderMapper"
factory-method="outboundMapper">
<beans:property name="outboundHeaderNames" value="*" />
<beans:property name="userDefinedHeaderPrefix" value="" />
</beans:bean>
<channel id="output" />
<channel id="input" />
<channel id="inputX" />
<channel id="toHttp" />
If it's based on the payload type, something like this should work...
url-expression="payload.getClass().getSimpleName().equals("Bar") ? 'http://foo/bar' : 'http://foo/baz'"
If it's a property on the payload, then
url-expression="payload.foo.equals("bar") ? 'http://foo/bar' : 'http://foo/baz'"
EDIT
or
url-expression="payload.foo.equals("bar") ? '${url1}' : '${url2}'"
This would need changing the property metadata class to rename url and add url2.

how to design a fallback for a spring integration service activator with circuit breaker?

when a circuit breaker advice is triggered, this takes care not to overload the failing integration service.
How do i fallback to a different service activator when the circuit is open? and when the circuit becomes closed need to fallback to primary activator
Is there a way to implement this with the framework? or some custom code has to be written
You can use an inline gateway to catch the exceptions and send them to an error channel; you can then use a router on the error flow to decide how to proceed further. Hopefully the following is reasonably easy to follow...
<int:service-activator input-channel="inbound" ref="gw" />
<int:gateway id="gw" default-request-channel="toPrimary"
error-channel="failures"
default-reply-timeout="0" />
<int:service-activator input-channel="toPrimary" expression=" 1 / 0 ">
<int:request-handler-advice-chain>
<bean class="org.springframework.integration.handler.advice.RequestHandlerCircuitBreakerAdvice">
<property name="threshold" value="2" />
<property name="halfOpenAfter" value="10000" />
</bean>
</int:request-handler-advice-chain>
</int:service-activator>
<!-- Error flow -->
<int:publish-subscribe-channel id="failures" />
<int:logging-channel-adapter id="failing" channel="failures" />
<int:recipient-list-router input-channel="failures" default-output-channel="nullChannel" >
<int:recipient channel="circuitFailures" selector-expression="payload.message.contains('Expression evaluation failed: 1 / 0') || payload.cause.message.contains('Circuit Breaker is Open')" />
</int:recipient-list-router>
<int:chain input-channel="circuitFailures" output-channel="loggingChannel">
<int:transformer expression="payload.failedMessage" />
<int:service-activator expression="payload + ' failed'" />
</int:chain>
<int:logging-channel-adapter id="loggingChannel" log-full-message="false" logger-name="tapInbound"
level="INFO" />

Transforming HL7 v2 to XML using apache camel routes

I am new to HL7 .I have to convert the HL7v2 to XML using apache camel routes.I am extracting the HL7 message from file.
Can any one help me how to convert HL7 to XML
There is an HL7 component for unmarshalling the file into a HAPI message. The HAPI api also includes an XMLParser that will convert the message into xml. So you should be able to combine the two into a simple camel route like the following:
<bean id="hl7XmlConverter" class="example.Hl7XmlConverter" />
<bean id="hl7FileFilter"
class="org.apache.camel.component.file.AntPathMatcherGenericFileFilter">
<property name="includes" value="*.hl7" />
</bean>
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route id="hl7FileRoute">
<from
uri="file:///tmp/test/?delete=true&moveFailed=.error&filter=#hl7FileFilter" />
<convertBodyTo type="java.lang.String" />
<log message="HL7 Request: ${body}" />
<unmarshal>
<hl7 validate="true" />
</unmarshal>
<bean ref="hl7XmlConverter"/>
<log message="HL7 Response: ${body}" />
</route>
</camelContext>
Where the bean is just a simple method:
public String convertMessage(Message message) throws HL7Exception{
XMLParser parser = new DefaultXMLParser();
return parser.encode(message);
}
Depending on your desired xml format, you could also add an xslt after the bean.

One of '{"http://www.mulesoft.org/schema/mule/jdbc":abstract-query}' is expected

I am trying implement XA Transaction with oracle database connector in Mule Studio. When I try to deploy this mule application on MuleStudio server I am getting below exception.
Exception:
"Caused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'url' of bean class [oracle.jdbc.xa.client.OracleXADataSource]: Bean property 'url' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?"
Mule Configuration xml file:
<jdbc-ee:oracle-data-source name="Oracle_Data_Source" user="system" password="manager" url="jdbc:oracle:thin:#//localhost:1521/xe" transactionIsolation="UNSPECIFIED" doc:name="Oracle Data Source"/>
<jdbc-ee:connector name="Database" dataSource-ref="oracleJdbcBean" validateConnections="true" queryTimeout="-1" pollingFrequency="0" doc:name="Database"/>
<jbossts:transaction-manager doc:name="Transaction Manager"/>
<spring:beans>
<spring:bean id="oracleJdbcBean" name="oracleJdbcBean" class="oracle.jdbc.xa.client.OracleXADataSource">
<spring:property name="user" value="system"/>
<spring:property name="password" value="manager"/>
<spring:property name="url" value="jdbc:oracle:thin:#localhost:1521:xe"/>
</spring:bean>
</spring:beans>
<flow name="oraclexatransactionFlow1" doc:name="oraclexatransactionFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8082" path="testTable" doc:name="HTTP"/>
<ee:xa-transactional action="ALWAYS_BEGIN" doc:name="Transactional">
<jdbc-ee:outbound-endpoint exchange-pattern="request-response" queryKey="testQuery" queryTimeout="-1" connector-ref="Database" doc:name="Database">
<xa-transaction action="ALWAYS_JOIN"/>
<jdbc-ee:query key="testQuery" value="select * from test"/>
</jdbc-ee:outbound-endpoint>
</ee:xa-transactional>
</flow>
I have followed the above configuration for other application to make xa transaction work with oracle database but I am getting different exception as below:
Caused by: org.xml.sax.SAXParseException; lineNumber: 195; columnNumber: 55; cvc-complex-type.2.4.a: Invalid content was found starting with element 'xa-transaction'. One of '{"http://www.mulesoft.org/schema/mule/jdbc":abstract-query}' is expected.
Please correct me if I configured anything wrong.
Url property should probably be
<spring:property name="url" value="jdbc:oracle:thin:#//localhost:1521/XE"/>
Uppercase of "URL" worked for me to resolve the first problem i.e.,
<spring:property name="URL" value="jdbc:oracle:thin:#localhost:1521:xe" />
And the second problem was resolved by placing the "xa-transaction" element before the query as below.
<jdbc-ee:outbound-endpoint exchange-pattern="request-response" queryKey="testQuery" queryTimeout="-1" connector-ref="Database" doc:name="Database">
<xa-transaction action="NONE" />
<jdbc-ee:query key="testQuery" value="select * from test" />

Resources