How do I use Apache Camel's ActiveMQ component to connect to a remote instance of ActiveMQ?
You can define an endpoint for each of your ActiveMQ instances:
<bean id="instance1"
class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="brokerURL" value="tcp://server1:61616"/>
</bean>
...
<bean id="instance2"
class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="brokerURL" value="tcp://server2:61616"/>
</bean>
and then use it in routes as
<from uri="instanceX:myQueue"/> or <to uri="instanceX:myQueue"/>
Related
My Spring application was using JPA transaction manager but for some situations I would like to use JTA transaction manager. Therefore I updated Spring config to something like that:
<beans>
<!-- Old config -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<!-- ...-->
<property name="jpaPropertyMap" ref="jpaPropertyMap"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven proxy-target-class="true"/>
<!-- ...-->
<!-- Updated config-->
<util:map id="jpaPropertyMap" key-type="java.lang.String">
<!-- ... ->
<entry key="javax.persistence.transactionType" value="jta"/>
<entry key="hibernate.transaction.jta.platform" value="Atomikos"/>
</util:map>
<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close">
<property name="forceShutdown" value="false"/>
</bean>
<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"/>
<bean id="jtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="atomikosTransactionManager"/>
<property name="userTransaction" ref="atomikosUserTransaction"/>
</bean>
<!-- ...-->
</beans>
Now in Java code when I need several JPA transactions (to different databases) to act as one transaction I annotate the starting service method with #Transactional("jtaTransactionManager"), while for situation when I need a single transaction I use standard #Transactional annotation.
But I have observed that, because of the properties
<entry key="javax.persistence.transactionType" value="jta"/>
<entry key="hibernate.transaction.jta.platform" value="Atomikos"/>
even if I start a sigle JPA transaction, Hibernate internally is also using Atomikos transaction manager. Is it possible to have Hibernate use Atomikos for JTA transaction and to not use it for single JPA transactions?
I am new to camel and I am attempting to write an app that bridges Websphere MQ and Active MQ on JBoss EAP 7. The app deploys successfully works, I can drop messages on the Websphere queue, and it gets picked up by Active MQ. However I see error messages in the log showing it is attempting to use a connection after it is open.
15:48:57,814 ERROR [org.jboss.jca.core.connectionmanager.listener.TxConnectionListener] (Camel (camel) thread #1 - JmsConsumer[I0_TEST]) IJ000315: Pool IbmMQQueueFactory has 1 active handles
15:48:57,819 INFO [org.jboss.as.connector.deployers.RaXmlDeployer] (Camel (camel) thread #1 - JmsConsumer[I0_TEST]) wmq.jmsra.rar: MQJCA4016:Unregistered connection handle being closed: 'com.ibm.mq.connector.outbound.ConnectionWrapper#214da401'.
15:49:02,819 WARN [org.apache.camel.component.jms.DefaultJmsMessageListenerContainer] (Camel (camel) thread #1 - JmsConsumer[I0_TEST]) Setup of JMS message listener invoker failed for destination 'I0_TEST' - trying to recover. Cause: Local JMS transaction failed to commit; nested exception is com.ibm.msg.client.jms.DetailedIllegalStateException: MQJCA1020: The session is closed.
The application attempted to use a JMS session after it had closed the session.
Modify the application so that it closes the JMS session only after it has finished using the session.
Here is my applicationContext.xml
<bean id="jmsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:/ConnectionFactory" />
<property name="lookupOnStartup" value="false" />
<property name="cache" value="true" />
<property name="proxyInterface" value="javax.jms.ConnectionFactory" />
</bean>
<bean id="jmsTransactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManagerName" value="java:/TransactionManager" />
</bean>
<bean id="jms" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory" ref="jmsConnectionFactory" />
<property name="transacted" value="true" />
<property name="transactionManager" ref="jmsTransactionManager" />
</bean>
<bean id="wmqConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:/jms/IbmMQMsgQCF" />
<property name="lookupOnStartup" value="false" />
<property name="cache" value="true" />
<property name="proxyInterface" value="javax.jms.ConnectionFactory" />
</bean>
<bean id="wmqTransactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManagerName" value="java:/TransactionManager" />
</bean>
<bean id="wmq" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory" ref="wmqConnectionFactory" />
<property name="transacted" value="true" />
<property name="transactionManager" ref="wmqTransactionManager" />
</bean>
<bean id="routerlogger" class="org.jboss.as.quickstarts.mdb.RoutLogger" />
<camelContext trace="true" id="camel"
xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="wmq:websphereQueue"/>
<setExchangePattern pattern="InOnly"/>
<to uri="jms:activeQueue" pattern="InOnly" />
</route>
</camelContext>
Its a simple app, trying to determine what I'm missing.
I found this JBossDeveloper bug "JBEAP-2344: UserTransaction commit(), rollback() closes connection in Websphere MQ 7.5" which looks like it describes your issue and has comments pointing to documentation update "JBEAP-3535: Documentation: Add note about connection close on commit() and rollback() to Deploy the WebSphere MQ Resource Adapter subchapter".
Could you please add a note, that setting tracking="false", solves
problem with WebSphere MQ 7.5 and 8, where method commit() or
rollback() on UserTransaction closes any JMS connections which was
part of this transaction. This part is related to documenting known
limitation of WebSphere MQ in
JBEAP-3142.
I'm working on an existing Spring application that uses JDBC (DAO's extend NamedParameterJdbcDaoSupport). There were four datasources configured, each with it's own DataSourceTransactionManager. (though only one was registered with tx:annotation-driven for some reason)
I've recently added JPA (Spring-data-JPA) into the application and configured two entityManagerFactories (for now I don't need the other two datasources). I also configured two JpaTransactionManagers and removed the corresponding DataSourceTransactionManagers for these dataSources, since the JpaTransactionManagers can also be used for JDBC transactions. (correct me if I'm wrong)
It appears I need to be able to have distributed transactions, since the two datasources (to two different databases) need to be accessed (through JPA) in one service method. Since I did not have all I need to set up JTA (missing XA-driver for one of the databases) I've decided to give the Spring ChainedTransactionManager a try. Sadly this didn't work out as expected. All works fine if I just call a service method that only uses JPA.
Though when I call an existing service method that uses a JDBC find that has a class level #transactional annotation with it's propagation set to NOT_SUPPORTED and call another service method after that with a JPA call and a #transactional, I get an exception:
Caused by: java.lang.IllegalStateException: Already value [org.springframework.jdbc.datasource.ConnectionHolder#462cf9d9] for key [org.jboss.jca.adapters.jdbc.WrapperDataSource#3fbb4c32] bound to thread [http-/127.0.0.1:8080-5]
at org.springframework.transaction.support.TransactionSynchronizationManager.bindResource(TransactionSynchronizationManager.java:189) [spring-tx-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:403) [spring-orm-3.2.5.RELEASE.jar:3.2.5.RELEASE]
After some debugging, I found out that the transactions in Spring get added to a map on a ThreadLocal in the "TransactionSynchronizationManager.bindResource" method. The problem is that when using a JDBC call with #transactional and propogation NOT_SUPPORTED, a transaction is made anyway and registered through that method. When the JpaTransactionManager tries to bind it's resource, it is already on the map (and not marked as void) which causes the error to occur.
Changing the propagation to the default "REQUIRED" for the service call that encapsulates the JDBC call fixes the problem.
I have no idea why Spring is still creating that transaction when the transactional annotation is NOT_SUPPORTED. And if it creates that transaction, it should not bypass the JpaTransactionManager.
So what I'd like to know is if there is some way to tell Spring to use the JpaTransactionManager also when it creates a transaction itself inside the NamedParameterJdbcDaoSupport. (Well actually the JdbcDaoSupport... Well actually the DataSourceUtils)
We're using Spring 3.2.5, spring-data-jpa 1.6.0 and I've used Hibernate 4.2.0 as JpaVendor.
This problem doesn't occur without the ChainedTransactionManager.
Datasources:
<bean id="dataSourceCompta" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:jboss/datasources/comptaDS"/>
</bean>
<bean id="dataSourceUnisys" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:jboss/datasources/insoverDS"/>
</bean>
<bean id="dataSourceInsoverwebMysql" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:jboss/datasources/insoverWebDS"/>
</bean>
<bean id="dataSourceBatch" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:jboss/datasources/batchDS"/>
</bean>
Single remaining JDBC transaction manager (no JPA counterpart):
<bean id="transactionManagerBatch" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSourceBatch"/>
</bean>
JPA Transaction Managers:
<bean id="jpaUnisysTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactoryUnisys"/>
<qualifier value="unisys" />
</bean>
<bean id="jpaMysqlTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactoryMysql"/>
<qualifier value="mysql" />
</bean>
My ChainedTransactionManager:
<bean id="chainedTransactionManager" class="org.springframework.data.transaction.ChainedTransactionManager">
<constructor-arg>
<list>
<ref bean="jpaUnisysTransactionManager" />
<ref bean="jpaMysqlTransactionManager" />
</list>
</constructor-arg>
</bean>
JPA Entity manager factories:
<bean name="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
<bean id="entityManagerFactoryUnisys" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath:META-INF/some-persistence.xml"/>
<property name="dataSource" ref="dataSourceUnisys"/>
<property name="persistenceUnitName" value="unisysPU"/>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
<property name="jpaProperties">
<!-- properties -->
</property>
</bean>
<bean id="entityManagerFactoryMysql" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath:META-INF/some-persistence.xml"/>
<property name="dataSource" ref="dataSourceCompta"/>
<property name="persistenceUnitName" value="mysqlPU"/>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
<property name="jpaProperties">
<!-- properties -->
</property>
</bean>
For now I've "fixed" this, by changing all the class-level transactional annotations to have propagation.REQUIRED (default) instead of NOT_SUPPORTED. Though I do not really like this solutions, since it might be somebody set those propagations to NOT_SUPPORTED with a good reason. I've also tried SUPPORTED, but using that had the same issue as NOT_SUPPORTED: a transaction was being made anyway by the Spring DataSourceUtils when the query was being executed by the NamedParameterJdbcDaoSupport DAO.
When no transactional annotation is set on the service, all works well too.
Is it possible (if yes, with what configuration?) to have a Spring application running on one JBoss instance connect to a JMS queue defined on a different JBoss instance? I read a few pages about how to do it programmatically, but is it possible to have the queue injected in the Spring app so the application is not aware of the remote location of the queue and not required to do an explicit lookup?
Ideally, to have the JNDI name of the queue being resolved to a remote queue by the "client JBoss". An acceptable option would be to have the client application define the queue as remote in the <jms:listener> configuration.
Software: JBoss EAP 6.2, Spring 3.x
Yes you can use remoting NettyConnectionFactory
<bean name="liveTransportConfiguration" class="org.hornetq.api.core.TransportConfiguration">
<constructor-arg value="org.hornetq.core.remoting.impl.netty.NettyConnectorFactory" />
<constructor-arg>
<map key-type="java.lang.String" value-type="java.lang.Object">
<entry key="port" value="5445"></entry>
<entry key="host" value="ip of server"></entry>
</map>
</constructor-arg>
</bean>
<bean name="connectionFactory" class="com.kp.KPHornetQJMSConnectionFactory"
destroy-method="close">
<constructor-arg name="ha" type="boolean" value="false" />
<constructor-arg>
<array>
<ref bean="liveTransportConfiguration"></ref>
</array>
</constructor-arg>
<property name="clientFailureCheckPeriod" value="5000" />
<property name="retryInterval" value="1000" />
<property name="retryIntervalMultiplier" value="1.0" />
<property name="reconnectAttempts" value="-1" />
<property name="confirmationWindowSize" value="-1" />
</bean>
<bean name="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory"></property>
</bean>
<bean name="kpListener" class="Your jms MessageListener">
<property name="jmsTemplate" ref="jmsTemplate"></property>
</bean>
<jms:listener-container connection-factory="connectionFactory" concurrency="1">
<jms:listener destination="myqueue" ref="kpListener" method="onMessage" />
</jms:listener-container>
KPHornetQJMSConnectionFactory.java class
public class KPHornetQJMSConnectionFactory extends HornetQJMSConnectionFactory {
private static final long serialVersionUID = -712113311282964108L;
public KPHornetQJMSConnectionFactory(final boolean ha,
org.hornetq.api.core.TransportConfiguration transportConfiguration) {
super(ha, transportConfiguration);
super.setUseGlobalPools(false);
}
}
I created a RESTful web service, and I want to send binary files to this service without SOAP.
There are some information on CXF website:
XOP
But I can't find a way to get the CXF JAX-RS endpoints, and set an mtom-enabled property.
My Spring config is:
<jaxrs:server id="fis" address="http://172.20.41.40:8080/fis">
<jaxrs:serviceBeans>
<ref bean="FaultInfoResource" />
<ref bean="ExplorationResultResource" />
</jaxrs:serviceBeans>
</jaxrs:server>
<bean id="FaultInfoService" parent="baseService" class="com.dfe.demo.FaultInfoService">
</bean>
<bean id="FaultInfoResource" class="com.dfe.demo.FaultInfoResource">
<property name="faultInfoService" ref="FaultInfoService"/>
</bean>
<bean id="ExplorationResultService" parent="baseService" class="com.dfe.demo.ExplorationResultService">
</bean>
<bean id="ExplorationResultResource" class="com.dfe.demo.ExplorationResultResource">
<property name="explorationResultService" ref="ExplorationResultService"/>
</bean>
And my server class is:
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"com/dfe/iss/config/applicationContext.xml","com/dfe/demo/yearlyplan/cxf-servlet.xml"});
JAXRSServerFactoryBean fib = (JAXRSServerFactoryBean) ctx.getBean("fis");
fib.create();
Try this:
<beans>
<jaxrs:server id="bookstore1">
<jaxrs:properties>
<entry key="mtom-enabled" value="true"/>
</jaxrs:properties>
</jaxrs:server>
</beans>