I'm setting the body of a Camel route using a Bean. That works on a Camel standalone project. When deployed on JBoss Fuse the Spring bean is not found. Here is a snippet of the blueprint:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cxf="http://camel.apache.org/schema/blueprint/cxf"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://camel.apache.org/schema/blueprint/cxf http://camel.apache.org/schema/blueprint/cxf/camel-cxf.xsd
http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">
<bean id="personFactory" class="sample.PersonFactory" />
<bean id="myBean" class="sample.Person" />
<camelContext id="cbr-example-context" xmlns="http://camel.apache.org/schema/blueprint" xmlns:order="http://fusesource.com/examples/order/v7">
<route id="myroute">
<from uri="timer:foo?repeatCount=1"/>
<setProperty propertyName="name">
<constant>John</constant>
</setProperty>
<setProperty propertyName="surname">
<constant>Doe</constant>
</setProperty>
<setBody>
<spel>#{#personFactory.createPerson(properties['name'],properties['surname'])}
</spel>
</setBody>
. . . .
</route>
</camelContext>
</blueprint>
When deployed on Fuse, the following exception is raised:
org.apache.camel.ExpressionEvaluationException: org.springframework.expression.spel.SpelEvaluationException:
EL1057E:(pos 1): No bean resolver registered in the context to resolve access to bean 'personFactory'
Any help ?
I had same problem recently. Unfortunately, did not managed to resolve this using spel and have switched to simple. This should help in your case:
<simple>${bean:personFactory?method=createPerson(property.name, property.surname)}</simple>
Related
I have a requirement that to configure the database connector using my custom-defined Datasource(Spring based). When configuring my data-source to DB Connector with my custom bean, I am getting an error that cannot set javax.sql.Datasource to org.mule.extension.db.internal.domain.data source.DataSourceConnetionSettings.dataSourceRef. When I didn't configure my DB connector and referred to the data source using java invoke, able to get the Datasource object. How can I pass this Datasource this my database connector in runtime?
Referred to the below but didn't help.
https://help.mulesoft.com/s/article/Spring-based-datasources
Can someone help me with the last point in the below knowledgebase?
https://help.mulesoft.com/s/article/How-to-configure-connector-with-dynamic-parameters
<db:config name="Database_Config">
<db:data-source-connection dataSourceRef="myDbConnetor" />
</db:config>
My beans.xml as like below:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd">
<context:annotation-config />
<context:component-scan base-package="com.test.datasource.*" />
<bean id="myDbConnetor" class="com.test.datasource.MyCustomDataSource"/>
</beans>
Is it possible to reference my own properties inside the <broker> configuration portion of the activemq.xml file?
I'm setting my property values by altering the ACTIVEMQ_OPTS in the "env" script, e.g. adding something like:
ACTIVEMQ_OPTS="${ACTIVEMQ_OPTS} -Dmy.property=MyValue"
And I have the following at the start of my activemq.xml file:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
<!-- Allows us to use system properties as variables in this configuration file -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<value>file:${activemq.conf}/credentials.properties</value>
</property>
</bean>
Configuring <beans> in the activemq.xml file works fine with my own properties in the "value", e.g. this works fine:
<bean id="myBean" class="MyClass">
<property name="someProperty" value="${my.property}"/>
</bean>
and ${my.property} is resolved perfectly ... but I just can't figure out how to get my properties to resolve when inside the <broker> element or one of it's children (like the persistenceAdapter).
For example, in the following case ...
<persistenceAdapter>
<replicatedLevelDB directory="${activemq.data}/leveldb" zkAddress="${my.zk.address}" zkPath="/activemq" bind="tcp://0.0.0.0:0" weight="${my.weight}"/>
</persistenceAdapter>
... the ${activemq.data} property is resolved ... but I can't seem to figure out how to get any of my own properties to resolve within the <broker> element of the activemq.xml configuration file ... I just keep getting an error that '${my.weight}' isn't a valid number (which is kind of insulting, if you think about it ;-)
I am stuck with the same problem
Got it to work but not sure if that is the right way.
You have to add it to the startup scripts.
If you are using active.bat
"%_JAVACMD%" %ACTIVEMQ_SUNJMX_START% %ACTIVEMQ_DEBUG_OPTS% %ACTIVEMQ_OPTS% %ACTIVEMQ_SSL_OPTS%
-Dactivemq.classpath="%ACTIVEMQ_CLASSPATH%"
-Dactivemq.home="%ACTIVEMQ_HOME%"
-Dactivemq.base="%ACTIVEMQ_BASE%"
-Dactivemq.conf="%ACTIVEMQ_CONF%"
-Dactivemq.data="%ACTIVEMQ_DATA%"
-Djava.io.tmpdir="%ACTIVEMQ_TMP%"
-D**remote.host.ip=1.2.3.4**
-jar "%ACTIVEMQ_HOME%/bin/activemq.jar" %*
If you are using wrapper, add it to wrapper.conf
wrapper.java.additional.**13**=-Dremote.host.ip="1.2.3.4"
Make sure to increment bolded number.
Yes, you can use property placeholders to load a properties file or use environment variables. It looks like you are using Spring, so you'd need to use the Spring-specific property placeholder mechanism.
Property file:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties">
...
Environment variables:
<context:property-placeholder />
Also see:
Spring property placeholders
In mule I have many applications running on the same container that access a jdbc connector with the same connection string/user/password set.
Of course any app has configured the same global connector in its xml configuration file, so there is code duplication.
Is there a way to define only once per container the connection and access it from any app?
I would try this: have one app create the datasource and store it in JNDI and have the other apps pick it up from JNDI.
Since there is no strong guarantee of app start ordering, it's possible that one app that needs the JNDI datasource would start too soon. You would need to configure Spring to be able to perform the JNDI lookup again in case of failure and configure a threaded retry policy on the Mule JDBC connector.
Also you will need to install the datasource and database JARs in lib/user so all apps could use them.
Just create a spring bean for your JDBC connector in xml some where in your system and have all your applications load it in your apps:
<spring:import resource="JDBC-beans.xml" />
and the xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd ">
<!-- Initialization for data source -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/TEST"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</bean>
</beans>
I have solved this kind of problem using a Domain project, where I inserted all database configurations that have been used by other projects.
I have written a simple authentication/authorization plugin that I want to inject into ActiveMQ. I want it to be called onConnect and onSubscribe. I have followed these steps at the ActiveMQ website but a couple of things happen.
1) If I put in my bean declaration in the default activemq.xml file in //beans/broker/plugins I get a validation error saying that the node "bean" is not allowed there.
2) If I put the plugin declaration outside of the broker element it will inject the element, but it will not call installPlugin() nor the hooks, presumably because that is for the broker to do.
3) If I change the XML namespace declaration in the default activemq.xml (http://activemq.apache.org/schema/core) to that which is stated in the docs listed above (http://activemq.org/config/1.0) along with the proper URLs, I get the error that it cannot find the schema document.
The only thing I can come up with is that either there were changes in 5.6 that were not reflected in the documentation, I'm doing something very wrong, or I'm just crazy. Here is the relevant portion of the xml doc (minus several nodes not directly related to the problem).
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:amq="http://activemq.org/config/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="${activemq.data}">
<plugins>
<bean id="tokenLoginPlugin" class="auth.TokenLoginPlugin">
<property name="host" value="localhost" />
</bean>
</plugins>
</broker>
This generates the following exception.
The matching wildcard is strict, but no declaration can be found for element 'broker'.
If I use the xmlns declarations from the default activemq.xml file, I get the following.
Invalid content was found starting with element 'bean'
I can see that it's a validation error, but none of the docs seem to be pointing me in the right direction.
Figured it out, though I had tried it before and it hadn't worked. Perhaps I had messed up my namespaces the last time. I changed my plugin definition and added the Spring namespace to my bean declaration.
<plugins>
<bean id="tokenLoginPlugin" class="auth.TokenLoginPlugin" xmlns="http://www.springframework.org/schema/beans">
<property name="host" value="localhost" />
</bean>
</plugins>
My configuration is :
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
<plugins>
<bean xmlns="http://www.springframework.org/schema/beans" id="probePlugin" class="com.ProbePlugin"/>
</plugins>
</beans>
Hello has anyone ever used Camel with IBM's MQ. We are looking at possibly using the two products together but have no example of the two products working together.
I have extensive use of IBM MQ's with camel. There is no issue using both together. I will paste a sample configuration from one of my spring context files leveraging a camel Jms Endpoint, A spring connection factory, and an IBM MQ definition.
Camel Route
from("someplace")
.to("cpaibmmq:queue:myQueueName");
Spring Context
<bean name="cpaibmmq" class="org.apache.camel.component.jms.JmsComponent" destroy-method="doStop">
<property name="transacted" value="${jms.transacted}" />
<property name="concurrentConsumers" value="${cpa.concurrentConsumers}" />
<property name="maxConcurrentConsumers" value="${cpa.concurrentConsumers}" />
<property name="acceptMessagesWhileStopping" value="${jms.acceptMessagesWhileStopping}" />
<property name="acknowledgementModeName" value="${jms.acknowledgementModeName}" />
<property name="cacheLevelName" value="${jms.cacheLevelName}" />
<property name="connectionFactory" ref="ibmFac1" />
<property name="exceptionListener" ref="ibmFac1" />
</bean>
<bean id="ibmFac1" class="org.springframework.jms.connection.SingleConnectionFactory" destroy-method="destroy">
<constructor-arg>
<bean class="com.ibm.mq.jms.MQQueueConnectionFactory">
<property name="transportType" value="1" />
<property name="channel" value="${cpa.wmq.channel}" />
<property name="hostName" value="${cpa.wmq.hostname}" />
<property name="port" value="${cpa.wmq.port}" />
<property name="queueManager" value="${cpa.wmq.mqmanager}" />
</bean>
</constructor-arg>
</bean>
The best I have been able to get is documented below, illustrated as a Spring XML application context that itself hosts the CAMEL context and routes. This sample works with the IBM native MQ JCA-compliant resource adapter v7.5, CAMEL 2.16, Spring core 4.2. I have deployed it in Glassfish, Weblogic, and JBoss EAP7 servers.
The complexity is bound to handling the flow of MQ reports whose philosophy conflicts with that of a plain JMS reply-to message. For a detailed explanation, please refer to Implementing native websphere MQ with CoD over Camel JMS component
This example based on the CAMEL XML DSL is self-contained and easy to test.
We start with Spring & CAMEL declarations:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:camel="http://camel.apache.org/schema/spring"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">
The CAMEL context follows with 2 routes: MQ to JMS and JMS to MQ, here chained to form a bridge to ease testing.
<camel:camelContext id="mqBridgeCtxt">
<camel:route id="mq2jms" autoStartup="true">
Weird: on Weblogic, the only way to get (e.g.) 3 listeners is to enforce 3 connections (with 3 Camel:from statements in sequence) with max 1 session each, otherwise an MQ error ensues: MQJCA1018: Only one session per connection is allowed. On JBoss, you can simply adjust concurrentConsumers=...
<camel:from uri="wmq:queue:TEST.Q1?concurrentConsumers=1&disableReplyTo=true&
acknowledgementModeName=SESSION_TRANSACTED"/>
The disable disableReplyTo option above ensures that CAMEL will not produce a reply before we can test the MQ message type to be 1=Request(-reply) or 8=datagram (one way!). That test and reply construction is not illustrated here.
Then we enforce the EIP to InOnly on the next posting to plain JMS to be consistent with the Inbound MQ mode.
<camel:setExchangePattern pattern="InOnly"/>
<!-- camel:process ref="reference to your MQ message processing bean fits here" / -->
<camel:to uri="ref:innerQueue" />
</camel:route>
This ends the MQ-to-jms route; next comes the jms-to-MQ route still in the same CAMEL context:
<camel:route id="jms2mq" autoStartup="true">
<camel:from uri="ref:innerQueue" />
<!-- remove inner message headers and properties to test without inbound side effects! -->
<camel:removeHeaders pattern="*"/>
<camel:removeProperties pattern="*" />
<!-- camel:process ref="reference to your MQ message preparation bean fits here" / -->
Now comes the request flag for the MQ CoD report to be returned by remote destination. We also enforce the MQ message to be of Datagram type (value 8).
<camel:setHeader headerName="JMS_IBM_Report_COD"><camel:simple resultType="java.lang.Integer">2048</camel:simple></camel:setHeader>
<camel:setHeader headerName="JMS_IBM_Report_Pass_Correl_ID"><camel:simple resultType="java.lang.Integer">64</camel:simple></camel:setHeader>
<camel:setHeader headerName="JMS_IBM_MsgType"><camel:simple resultType="java.lang.Integer">8</camel:simple></camel:setHeader>
The ReplyTo queue can be specified either via the ReplyTo uri option, else as a header as below.
Next we do use CamelJmsDestinationName header to enforce suppressing of the JMS MQ message header MQRFH2 (using targetClient MQ URL option value 1). In other words, we want to send a plain vanilla MQ binary message (i.e. Only the MQMD message descriptor followed by the payload).
<camel:setHeader headerName="JMSReplyTo"><camel:constant>TEST.REPLYTOQ</camel:constant></camel:setHeader>
<camel:setHeader headerName="CamelJmsDestinationName"> <camel:constant>queue://MYQMGR/TEST.Q2?targetClient=1</camel:constant></camel:setHeader>
More MQMD fields may be controlled through reserved JMS properties as illustrated below. See restrictions in IBM doc.
<camel:setHeader headerName="JMS_IBM_Format"><camel:constant>MQSTR </camel:constant></camel:setHeader>
<camel:setHeader headerName="JMSCorrelationID"><camel:constant>_PLACEHOLDER_24_CHARS_ID_</camel:constant></camel:setHeader>
The destination queue in the URI is overwritten by the CamelJmsDestinationName above, hence the queue name in the URI becomes a placeholder.
The URI option preserveMessageQos is the one that - as observed - allows sending a message with the ReplyTo data being set (to get the MQ CoD Report), yet prevent CAMEL to instantiate a Reply message listener by enforcing the InOnly MEP.
<camel:to uri="wmq:queue:PLACEHOLDER.Q.NAME?concurrentConsumers=1&
exchangePattern=InOnly&preserveMessageQos=true&
includeSentJMSMessageID=true" />
</camel:route>
</camel:camelContext>
We have not finished, we have still to declare our queue factories for both a native JMS provider and Websphere MQ (via the native IBM WMQ JCA Resource Adapter), to be adjusted to your context.
We use here JNDI lookups on administrative objects.
<camel:endpoint id="innerQueue" uri="jmsloc:queue:transitQueue">
</camel:endpoint>
<jee:jndi-lookup id="mqQCFBean" jndi-name="jms/MYQMGR_QCF"/>
<jee:jndi-lookup id="jmsraQCFBean" jndi-name="jms/jmsra_QCF"/>
<bean id="jmsloc" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory" ref="jmsraQCFBean" />
</bean>
<bean id="wmq" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory" ref="mqQCFBean" />
</bean>
</beans>
An alternative to fetching the factories (and JCA adapters) from JNDI is to declare the JMS client as Spring beans. In Weblogic and Glassfish, you'll be better inspired by deploying the native IBM JCA resource adapter and creating JNDI resources then referenced in the Spring Context as above, in JBoss a direct MQ client bean declaration suits best as below)
<bean id="mqCFBean" class="com.ibm.mq.jms.MQXAConnectionFactory">
<property name="hostName" value="${mqHost}"/>
<property name="port" value="${mqPort}"/>
<property name="queueManager" value="${mqQueueManager}"/>
<property name="channel" value="${mqChannel}"/>
<property name="transportType" value="1"/> <!-- This parameter is fixed and compulsory to work with pure MQI java libraries -->
<property name="appName" value="${connectionName}"/>
</bean>
<bean id="wmq" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory" ref="mqCFBean"/>
<property name="transacted" value="true"/>
<property name="acknowledgementModeName" value="AUTO_ACKNOWLEDGE"/>
</bean>
Comments and improvements welcome.
A quick google revealed following,
http://lowry-techie.blogspot.de/2010/11/camel-integration-with-websphere-mq.html
HTH