My problem
I recently had the pleasure of working with Mule. In my use case I wanted to lookup a JMS queue, post to that queue and receive a reply – a synchronous JMS bridge pattern. This would be packaged into a web application that uses Spring, and deployed on JBoss 4.2.3. With such a “simple” solution I can’t see why I ran into problems…
I recently had the pleasure of working with Mule. In my use case I wanted to lookup a JMS queue, post to that queue and receive a reply – a synchronous JMS bridge pattern. This would be packaged into a web application that uses Spring, and deployed on JBoss 4.2.3. With such a “simple” solution I can’t see why I ran into problems…
My error in the JBoss console was as follows:
Caused
by: org.mule.retry.RetryPolicyExhaustedException: Unsupported ConnectionFactory
type: $Proxy286
at
org.mule.retry.policies.AbstractPolicyTemplate.execute(AbstractPolicyTemplate.java:105)
at org.mule.transport.AbstractConnector.connect(AbstractConnector.java:1616)
at org.mule.transport.jms.JmsConnector.connect(JmsConnector.java:460)
at org.mule.transport.AbstractConnector.start(AbstractConnector.java:428)
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:601)
at
org.mule.lifecycle.phases.DefaultLifecyclePhase.applyLifecycle(DefaultLifecyclePhase.java:225)
at org.mule.lifecycle.RegistryLifecycleManager$RegistryLifecycleCallback.onTransition(RegistryLifecycleManager.java:276)
at
org.mule.lifecycle.RegistryLifecycleManager.invokePhase(RegistryLifecycleManager.java:155)
at org.mule.lifecycle.RegistryLifecycleManager.fireLifecycle(RegistryLifecycleManager.java:126)
at
org.mule.registry.AbstractRegistryBroker.fireLifecycle(AbstractRegistryBroker.java:80)
at
org.mule.registry.MuleRegistryHelper.fireLifecycle(MuleRegistryHelper.java:120)
at
org.mule.lifecycle.MuleContextLifecycleManager$MuleContextLifecycleCallback.onTransitio
Searching for a solution (ask Google approach)
As usual I ended up trawling through loads of forums, Stackoverflow, MuleSoft,
etc and of course the Mule documentation.
The main stumbling block seemed to be my desire to use the local JNDI
lookup. Mule is predominantly used for
integration and as such will usually need to run standalone. However, my use case called for it to run
embedded in my web application and I didn’t want to specify the JNDI
configuration of each Web container I choose to deploy on.
Mule docs:
http://www.mulesoft.org/documentation-3.2/display/MULEUSER/Jndi+Container
http://www.mulesoft.org/documentation-3.2/display/MULEUSER/Configuring+Jms
http://www.mulesoft.org/documentation/display/current/JMS+Transport+Reference
http://www.jarvana.com/jarvana/view/mule/mule/1.3/mule-1.3-website-docs.distribution-zip!/MULE/Configuring%20Jms.html
http://www.mulesoft.org/documentation-3.2/display/MULEUSER/Configuring+Jms
http://www.mulesoft.org/documentation/display/current/JMS+Transport+Reference
http://www.jarvana.com/jarvana/view/mule/mule/1.3/mule-1.3-website-docs.distribution-zip!/MULE/Configuring%20Jms.html
Possible issues:
My configuration
My configuration was pretty straight forward.
web.xml
<!-- Mule Bridge Settings -->
<resource-ref
id="ResourceRef_jmsConnectionFactory">
<description>Used
to get connections to JMS queue, using JMS as a bridge to
Mule</description>
<res-ref-name>jms/jmsConnectionFactory</res-ref-name>
<res-type>javax.jms.ConnectionFactory</res-type>
<res-auth>Container</res-auth>
</resource-ref>
jboss-web.xml
<resource-ref>
<res-ref-name>jms/jmsConnectionFactory</res-ref-name>
<res-type>javax.jms.ConnectionFactory</res-type>
<jndi-name>java:/ConnectionFactory</jndi-name>
</resource-ref>
uil2-service.xml
<mbean
code="org.jboss.naming.LinkRefPairService"
name="jboss.jms:alias=QueueConnectionFactory">
<attribute
name="JndiName">QueueConnectionFactory</attribute>
<attribute
name="RemoteJndiName">ConnectionFactory</attribute>
<attribute
name="LocalJndiName">java:/JmsXA</attribute>
<depends>jboss:service=Naming</depends>
</mbean>
Debugging the problem
Debugging the problem was a little tedious as I mostly received
exceptions in the JBoss log and not much else.
In hindsight, perhaps attaching a debugger and stepping through the Mule
source might have been quicker. The main points were to confirm that I could
connect to the queue, I could lookup the queue in my web application, and I
could
Now for the solution
This helpful post was the solution to my
problem. http://stackoverflow.com/questions/12461714/mule-embedded-use-the-containers-own-jndiinitialfactory
Unfortunately we need one new class in our web application to help
lookup the queue and this class depends on Spring.
package my.package;
import javax.naming.NamingException;
import org.mule.transport.jms.jndi.AbstractJndiNameResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jndi.JndiTemplate;
public class SpringJndiNameResolver extends AbstractJndiNameResolver
implements InitializingBean {
private static Logger logger =
LoggerFactory.getLogger(SpringJndiNameResolver.class);
private JndiTemplate
jndiTemplate;
@Override
public void
afterPropertiesSet() throws Exception {
if (jndiTemplate == null)
{
jndiTemplate = new
JndiTemplate();
}
}
@Override
public Object lookup(String
name) throws NamingException {
Object object = null;
if (name != null) {
logger.debug("Looking up name "+name);
object =
jndiTemplate.lookup(name);
logger.debug("Object "+object+" found for name
"+name);
}
return object;
}
public JndiTemplate
getJndiTemplate() {
return jndiTemplate;
}
public void
setJndiTemplate(JndiTemplate jndiTemplate) {
this.jndiTemplate =
jndiTemplate;
}
}
mule-config.xml (client or local side)
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:jms="http://www.mulesoft.org/schema/mule/jms"
xmlns:file="http://www.mulesoft.org/schema/mule/file"
xmlns:vm="http://www.mulesoft.org/schema/mule/vm"
xmlns="http://www.mulesoft.org/schema/mule/core"
xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans"
version="EE-3.3.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.mulesoft.org/schema/mule/vm
http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd
http://www.mulesoft.org/schema/mule/file
http://www.mulesoft.org/schema/mule/file/current/mule-file.xsd
http://www.mulesoft.org/schema/mule/jms
http://www.mulesoft.org/schema/mule/jms/current/mule-jms.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core
http://www.mulesoft.org/schema/mule/core/current/mule.xsd ">
<spring:beans>
<spring:bean
id="jndiTemplate" class="org.springframework.jndi.JndiTemplate"/>
</spring:beans>
<!--
The following suggestion
works:
http://stackoverflow.com/questions/12461714/mule-embedded-use-the-containers-own-jndiinitialfactory
-->
<jms:connector
name="local-jms-connector"
connectionFactoryJndiName="java:comp/env/jms/jmsConnectionFactory"
jndiDestinations="true"
forceJndiDestinations="true"
specification="1.1" doc:name="JMS">
<jms:custom-jndi-name-resolver
class="com.temenos.hothouse.mule.SpringJndiNameResolver">
<spring:property name="jndiTemplate"
ref="jndiTemplate"/>
</jms:custom-jndi-name-resolver>
</jms:connector>
<!--
throws exception with "Unsupported ConnectionFactory type:
$Proxy338"
<spring:bean
id="jmsConnectionFactory"
class="org.springframework.jndi.JndiObjectFactoryBean">
<spring:property name="jndiName"
value="java:env/comp/jms/jmsConnectionFactory"/>
<spring:property name="lookupOnStartup"
value="false"/>
<spring:property name="cache"
value="true"/>
<spring:property name="proxyInterface"
value="javax.jms.ConnectionFactory"/>
</spring:bean>
<jms:connector
name="local-jms-connector"
connectionFactory-ref="jmsConnectionFactory"
jndiDestinations="true"
forceJndiDestinations="true"
disableTemporaryReplyToDestinations="true" doc:name="JMS
Local">
</jms:connector>
-->
<!-- TODO Can't seem to get
the local jms connection factory lookup to work
(even this remote way barfs
with the same exception as above) -->
<!--
<jms:connector
name="remote-jms-connector"
jndiInitialFactory="org.jnp.interfaces.NamingContextFactory"
jndiProviderUrl="jnp://127.0.0.1:1099"
maxRedelivery="1"
connectionFactoryJndiName="QueueConnectionFactory"
jndiDestinations="true"
forceJndiDestinations="true"
disableTemporaryReplyToDestinations="true"
doc:name="JMS">
</jms:connector>
-->
<flow
name="vm://Forecast-view-command" doc:name="vm://Forecast-view-command">
<vm:inbound-endpoint
exchange-pattern="request-response"
path="Forecast-view-command" doc:name="VM"/>
<logger
message="VM Request:
#[payload]" level="INFO" doc:name="Logger"/>
<set-payload
value="#[mule:message.payload(java.lang.String)]" doc:name="Set
Payload"/>
<file:outbound-endpoint
path="c:\logs\"
outputPattern="forecast-request-#[function:datestamp].xml"
responseTimeout="10000" doc:name="File"/>
<jms:outbound-endpoint
exchange-pattern="request-response"
queue="queue/MuleRequest" doc:name="MuleRequest"
connector-ref="local-jms-connector" />
<file:outbound-endpoint
path="c:\logs\"
outputPattern="forecast-response-#[function:datestamp].xml"
responseTimeout="10000" doc:name="File"/>
<jms:jmsmessage-to-object-transformer doc:name="JmsMessage to
Object"/>
<object-to-string-transformer doc:name="Object to
String"/>
<logger
message="Response: #[payload]"
level="INFO" doc:name="Logger"/>
</flow>
</mule>
mule-config.xml (server or remote side)
<?xml version="1.0" encoding="UTF-8"?>
<mule
xmlns:mulexml="http://www.mulesoft.org/schema/mule/xml"
xmlns:stdio="http://www.mulesoft.org/schema/mule/stdio"
xmlns:jms="http://www.mulesoft.org/schema/mule/jms"
xmlns:data-mapper="http://www.mulesoft.org/schema/mule/ee/data-mapper"
xmlns:file="http://www.mulesoft.org/schema/mule/file"
xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking"
xmlns:vm="http://www.mulesoft.org/schema/mule/vm"
xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans"
version="EE-3.3.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.mulesoft.org/schema/mule/xml http://www.mulesoft.org/schema/mule/xml/current/mule-xml.xsd
http://www.mulesoft.org/schema/mule/file
http://www.mulesoft.org/schema/mule/file/current/mule-file.xsd
http://www.mulesoft.org/schema/mule/stdio
http://www.mulesoft.org/schema/mule/stdio/current/mule-stdio.xsd
http://www.mulesoft.org/schema/mule/jms
http://www.mulesoft.org/schema/mule/jms/current/mule-jms.xsd
http://www.mulesoft.org/schema/mule/ee/data-mapper
http://www.mulesoft.org/schema/mule/ee/data-mapper/current/mule-data-mapper.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core
http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/ee/tracking
http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd
http://www.mulesoft.org/schema/mule/vm
http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd ">
<custom-transformer
class="org.mule.transformer.codec.XmlEntityDecoder"
name="XmlEntityDecoder" doc:name="Java"/>
<jms:connector
name="remote-jms-connector"
jndiInitialFactory="org.jnp.interfaces.NamingContextFactory"
jndiProviderUrl="jnp://127.0.0.1:1099"
maxRedelivery="1"
connectionFactoryJndiName="java:/QueueConnectionFactory"
jndiDestinations="true"
forceJndiDestinations="true"
disableTemporaryReplyToDestinations="true"
doc:name="JMS">
<!--retry:forever-policy frequency="2000"/-->
</jms:connector>
<data-mapper:config
name="wsdlresponsetoentityresponse"
transformationGraphPath="wsdlresponsetoentityresponse.grf"
doc:name="DataMapper"/>
<data-mapper:config
name="reqtores" transformationGraphPath="reqtores.grf"
doc:name="reqtores"/>
<flow
name="ProcessFromQueue" doc:name="ProcessFromQueue">
<jms:inbound-endpoint
queue="queue/MuleRequest"
connector-ref="remote-jms-connector" doc:name="Request"
/>
<set-payload
value="#[mule:message.payload(java.lang.String)]" doc:name="Set
Payload"/>
<logger message="Before
WSDL #[payload]" level="INFO" doc:name="Logger"/>
<set-payload
value="#[xpath('//viewcommand/pathparameters/postcode').text]"
doc:name="Extract PostCode"/>
<set-variable
variableName="Requested_PostCode" value="#[payload]" doc:name="Set
Requested_PostCode"/>
<logger
message="Requested_PostCode:
#[Requested_PostCode]" level="INFO"
doc:name="Logger"/>
<flow-ref
name="ForecastWSDL" doc:name="ForecastWSDL"/>
<logger
message="Latest Forecast:
#[xpath('//forecastResult/forecasts/com.cdyne.ws.weatherws.Forecast[1]/desciption').text]"
level="INFO" doc:name="Logger"/>
<data-mapper:transform
config-ref="wsdlresponsetoentityresponse"
doc:name="DataMapper">
<data-mapper:input-arguments>
<data-mapper:input-argument
key="Requested_PostCode">#[Requested_PostCode]</data-mapper:input-argument>
</data-mapper:input-arguments>
</data-mapper:transform>
<object-to-string-transformer doc:name="Object to
String"/>
<jms:outbound-endpoint
queue="queue/MuleResponse"
connector-ref="remote-jms-connector"
doc:name="Response"/>
</flow>
<sub-flow
name="ForecastWSDL" doc:name="ForecastWSDL">
<outbound-endpoint
exchange-pattern="request-response"
address="wsdl-cxf:http://wsf.cdyne.com/WeatherWS/weather.asmx?WSDL&method=GetCityForecastByZIP"
doc:name="WSDL"/>
<mulexml:object-to-xml-transformer doc:name="Object to
XML"/>
<stdio:outbound-endpoint
system="OUT" doc:name="STDIO"/>
<file:outbound-endpoint
path="c:\logs\"
outputPattern="wsdl-response-#[function:datestamp].xml"
responseTimeout="10000" doc:name="File"/>
<!--
<file:outbound-endpoint path="c:\logs"
outputPattern="jms-response-#[function:datestamp].xml"
responseTimeout="10000" doc:name="File"/>
-->
</sub-flow>
<flow
name="mule-configFlow1" doc:name="mule-configFlow1">
<data-mapper:transform
config-ref="reqtores" doc:name="DataMapper">
<data-mapper:input-arguments>
<data-mapper:input-argument
key="Requested_PostCode">#[Requested_PostCode]</data-mapper:input-argument>
</data-mapper:input-arguments>
</data-mapper:transform>
</flow>
</mule>
Iam very impressive your site gives the best and the most interesting information. This is just the kind of information that i had been looking for, i'm already your rss reader now and i would regularly watch out for the new posts, once again hats off to you..
ReplyDeleteMulesoft online training hyderabad
I'm very happy to search out this information processing system. I would like to thank you for this fantastic read!!
ReplyDeleteMuleSoft Online Training
MuleSoft Training in Hyderabad
Im very happy to share this post
ReplyDeleteFull Stack Training in Chennai | Certification | Online Training Course | Full Stack Training in Bangalore | Certification | Online Training Course | Full Stack Training in Hyderabad | Certification | Online Training Course | Full Stack Training in Pune | Certification | Online Training Course | Full Stack Training | Certification | Full Stack Online Training Course
Thanks for sharing valuable information and very well explained.keep posting.
ReplyDeletemulesoft online training
mulesoft course