JNDI access with Tomcat 7 and embedded HornetQ - spring

I set up a new project with Tomcat 7.0 and an embedded HornetQ JMS server.
I used these 2 tutorials to help me:
http://www.javacodegeeks.com/2010/06/spring-3-hornetq-21-integration.html
http://wash-inside-out.blogspot.com/2010/08/hornetq-jms-integration-with-tomcat.html
But as it is mentioned in the tutos, the Tomcat JNDI repository is readonly (cannot find a way to write) and I configured a "separated" JNDI used by HornetQ, the messaging works, but Tomcat cannot access it.
Normally, in my other projects using Tomcat, I defined the datasource as a global resource in the server.xml and I map it in the context.xml. doing this, the definition of the datasource (jdbc url, credentials, etc...) are outside the application and can be managed by environment (dev, test, prod, ...) but I cannot find a way to do it with the other JNDI.
Currently, the datasource is defined in my application with an external property file for the parameters but I am not really satisfied with this solution.
Here is my Spring configuration:
<!-- enable autowire -->
<context:annotation-config />
<!-- enable transaction demarcation with annotations -->
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource">
<property name="driverClassName" value="com.informix.jdbc.IfxDriver" />
<property name="url" value="${URL}" />
<property name="username" value="${user}" />
<property name="password" value="${password}" />
<property name="maxActive" value="50" />
<property name="maxIdle" value="10" />
<property name="maxWait" value="1000" />
<property name="removeAbandoned" value="true" />
<property name="removeAbandonedTimeout" value="300" />
<property name="logAbandoned" value="true" />
</bean>
<!-- HornetQ config -->
<bean name="namingServerImpl" class="org.jnp.server.NamingBeanImpl" init-method= "start" destroy-method="stop" >
<!-- configure HornetQ JNDI server not to use an existing JNDI service if available -->
<property name="useGlobalService" value="false" />
</bean>
<bean name="namingServer" class="org.jnp.server.Main" init-method="start" destroy-method="stop">
<property name="namingInfo" ref="namingServerImpl" />
<property name="port" value="1099" />
<property name="bindAddress" value="localhost" />
<property name="rmiPort" value="1098" />
<property name="rmiBindAddress" value="localhost" />
</bean>
<bean name="mbeanServer" class="java.lang.management.ManagementFactory" factory-method="getPlatformMBeanServer" />
<bean name="fileConfiguration" class="org.hornetq.core.config.impl.FileConfiguration"
init-method="start" destroy-method="stop" />
<bean name="hornetQSecurityManagerImpl" class="org.hornetq.spi.core.security.HornetQSecurityManagerImpl" />
<!-- The core server -->
<bean name="hornetQServerImpl" class="org.hornetq.core.server.impl.HornetQServerImpl">
<constructor-arg index="0" ref="fileConfiguration" />
<constructor-arg index="1" ref="mbeanServer" />
<constructor-arg index="2" ref="hornetQSecurityManagerImpl" />
</bean>
<!-- The JMS server -->
<bean name="jmsServerManagerImpl" class="org.hornetq.jms.server.impl.JMSServerManagerImpl"
init-method="start" destroy-method="stop" depends-on="namingServer">
<constructor-arg ref="hornetQServerImpl" />
</bean>
<!-- to use HornetQ messaging service through Spring we can either create a connection factory, or lookup one from JNDI -->
<bean name="connectionFactory" class="org.hornetq.jms.client.HornetQConnectionFactory">
<constructor-arg index="0" type="boolean" value="false"/>
<constructor-arg index="1">
<bean class="org.hornetq.api.core.TransportConfiguration">
<constructor-arg index="0" type="java.lang.String" value="org.hornetq.integration.transports.netty.NettyConnectorFactory" />
<constructor-arg index="1">
<map key-type="java.lang.String" value-type="java.lang.Object">
<entry key="port" value="5445"></entry>
</map>
</constructor-arg>
</bean>
</constructor-arg>
</bean>
<bean id="notificationsQueue" class="org.springframework.jndi.JndiObjectFactoryBean" depends-on="jmsServerManagerImpl">
<property name="jndiName">
<value>/queue/Notifications</value>
</property>
</bean>
<bean id="inVMConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean" depends-on="jmsServerManagerImpl">
<property name="jndiName">
<value>/ConnectionFactory</value>
</property>
</bean>
How can I managed it in a better way, I mean, define the datasource on the server side as usual? Is there a configuration to tell Tomcat to use the external JNDI I defined or create a read/write repo?

Related

JMS Message Redelivery not working for Topic in Spring + ActiveMQ + Atomikos + JTA + Tomcat

I have following configuration in the application that works perfectly fine with queues and redelivers the messages when a RuntimeException occurs with transaction rollback as expected.
But the same configuration fails to redeliver message with topics and emits following warning message:
WARN DefaultMessageListenerContainer - Setup of JMS message listener invoker failed for destination 'XXX_TOPIC' - trying to recover. Cause: JTA transaction unexpectedly rolled back (maybe due to a timeout); nested exception is javax.transaction.RollbackException: One or more resources refused to commit (possibly because of a timeout in the resource - see the log for details). This transaction has been rolled back instead.
Configuration:
<bean id="amqConnectionFactory" class="org.apache.activemq.ActiveMQXAConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616"/>
<!-- <property name="sendTimeout" value="1000"/> -->
<property name="redeliveryPolicy" ref="redeliveryPolicy"/>
</bean>
<!-- Atomikos Connection Factory Wrapper For Gobal Tx -->
<bean id="queueConnectionFactoryBean" class="com.atomikos.jms.AtomikosConnectionFactoryBean">
<property name="uniqueResourceName" value="amq1" />
<property name="xaConnectionFactory" ref="amqConnectionFactory" />
</bean>
<bean id="jmsConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory">
<ref bean="queueConnectionFactoryBean"/>
</property>
<property name="sessionCacheSize" value="20"/>
<property name="cacheConsumers" value="false"/>
</bean>
<bean id="jtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager">
<bean class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init"
destroy-method="close">
<property name="forceShutdown" value="false" />
</bean>
</property>
<property name="userTransaction">
<bean class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout" value="300" />
</bean>
</property>
</bean>
<!-- Topic configuration -->
<bean id="messageListener1" class="com.x.y.impl.JmsMessageListener"></bean>
<bean id="container1" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsConnectionFactory"/>
<property name="destinationName" value="XXX_TOPIC"/>
<property name="messageListener" ref="messageListener1" />
<property name="pubSubDomain" value="true" />
<property name="transactionManager" ref="jtaTransactionManager" />
<property name="concurrency" value="1" />
<property name="receiveTimeout" value="3000" />
<!-- For local session and Atomikos-->
<property name="sessionTransacted" value="true"/>
</bean>
<!-- Bean configuration -->
<bean id="messageListener2" class="com.x.y.impl.JmsMessageListener"></bean>
<bean id="container2" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsConnectionFactory"/>
<property name="destinationName" value="XXX_QUEUE"/>
<property name="messageListener" ref="messageListener2" />
<property name="pubSubDomain" value="false" />
<property name="transactionManager" ref="jtaTransactionManager" />
<property name="concurrency" value="1" />
<!-- For local session and Atomikos-->
<property name="sessionTransacted" value="true"/>
</bean>
The Spring version used is 3.1, ActiveMQ 5.14, Atomikos 4.0.6.
Please let me know if i missed any configuration for topic DMLC.

how to configure jms queue inside blueprint.xml

how to configure jms queue(using activemq inside karaf) inside blueprint.xml which present inside karaf deploy folder..
below is my code which shows config for jms connection inside blueprint.xml..
<bean id="activemqConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616" />
<property name="userName" value="karaf" />
<property name="password" value="karaf" />
</bean>
<bean id="pooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory">
<property name="maxConnections" value="8" />
<property name="connectionFactory" ref="activemqConnectionFactory" />
</bean>
<bean id="resourceManager" class="org.apache.activemq.pool.ActiveMQResourceManager" init-method="recoverResource">
<property name="transactionManager" ref="transactionManager" />
<property name="connectionFactory" ref="activemqConnectionFactory" />
<property name="resourceName" value="activemq.localhost" />
</bean>
<reference id="transactionManager" interface="javax.transaction.TransactionManager" />
<service ref="activemqConnectionFactory" interface="javax.jms.ConnectionFactory">
<service-properties>
<entry key="name" value="connectionFactory" />
<entry key="osgi.jndi.service.name" value="jms/connectionFactory" />
</service-properties>
</service>
You don't configure a queue in OSGi, like you did in J2EE. You just use the connection factory in your plain Java or to configure the camel-jms component.

Spring WebServiceTemplate Interceptor for adding security header

I am trying to add a SOAP:Header with wss4j authentication for my outbound SOAP service.
Below is my WebServiceTemplate and interceptor configuration
<bean id="securityHeader"
class="org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor">
<property name="securementActions" value="UsernameToken" />
<property name="securementUsername" value="uname" />
<property name="securementPassword" value="password#123" />
<property name="securementPasswordType" value="PasswordText" />
<property name="securementUsernameTokenElements" value="Nonce Created" />
</bean>`
<bean id="webService" class="org.springframework.ws.client.core.WebServiceTemplate">
<constructor-arg ref="messageFactory" />
<property name="messageSender">
<bean
class="org.springframework.ws.transport.http.CommonsHttpMessageSender">
<!-- <property name="credentials" ref="credentials" /> -->
</bean>
</property>
<property name="interceptors">
<list>
<ref bean="securityHeader" />
</list>
</property>
<property name="defaultUri"
value="https://test.test.com/ws/service/test" />
<property name="marshaller" ref="fmarshaller" />
<property name="unmarshaller" ref="forwardunmarshaller" />
</bean>
But when the outbound call happens, its not adding the SOAP security header.webService.marshalSendAndReceive("http://localhost:8088/mockBinding",request);
Below changes did the trick for me.
Changing the SOAP version to 1.1
Defining the bean declaration inside interceptor instead of referencing it.
Use a web service message callback.

How to create apache camel XA connection using JNDI in Atomikos

Hi i am trying to create a XA transaction for camel and jdbc using atomikos but i have JNDI to set up a XA jdbc transaction i am having issues configuring it.
Below is my code and i am getting cannot write to the class exception
<!-- Atomikos and Spring transaction configuration -->
<!-- JMS config; with XAConnectionFactory -->
<bean id="xa.amqConnectionFactory" class="org.apache.activemq.spring.ActiveMQXAConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616"/>
</bean>
<!-- nothing transactional here, this connection factory will be used from the test harness -->
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616"/>
</bean>
<!-- Atomikos JTA configuration, nothing specific to Spring here -->
<bean id="atomikos.connectionFactory" class="com.atomikos.jms.AtomikosConnectionFactoryBean"
init-method="init" destroy-method="close">
<property name="uniqueResourceName" value="My_MQSeries_XA_RMI"/>
<property name="xaConnectionFactory" ref="xa.amqConnectionFactory"/>
<!-- XAConnectionFactory -->
<property name="maxPoolSize" value="10"/>
<property name="ignoreSessionTransactedFlag" value="false"/>
</bean>
<!-- database config; the XADataSource bean is both a DataSource and an XADataSource-->
<!-- <import resource="xa-embedded-db-context.xml"/> -->
<bean id="db2jndi" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value = "jndi NAMe"/>
</bean>
<!-- <bean id="XADataSource" class="MyDAOclass">
<property name="MyDAOmethod" ref="db2jndi"/>
</bean> -->
<bean id="atomikos.dataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean">
<property name="xaDataSource" ref="XADataSource"/>
<!-- XADataSource -->
</bean>
<!-- javax.transaction.TransactionManager -->
<bean id="atomikos.transactionManager"
class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init"
destroy-method="close"
depends-on="atomikos.connectionFactory,atomikos.dataSource">
<property name="forceShutdown" value="false"/>
</bean>
<!-- javax.transaction.UserTransaction -->
<bean id="atomikos.userTransaction"
class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout" value="300"/>
</bean>
<!-- This is the Spring wrapper over the JTA configuration -->
<!-- org.springframework.transaction.PlatformTransactionManager -->
<bean id="jta.transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="atomikos.transactionManager"/>
<property name="userTransaction" ref="atomikos.userTransaction"/>
</bean>
<!-- Camel components -->
<bean id="jms" class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="connectionFactory" ref="atomikos.connectionFactory"/>
<property name="transactionManager" ref="jta.transactionManager"/>
</bean>
<!-- this component is used only from the test harness -->
<bean id="nonTxJms" class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="connectionFactory" ref="connectionFactory"/>
</bean>
<bean id="sql" class="org.apache.camel.component.sql.SqlComponent">
<property name="dataSource" ref="atomikos.dataSource"/>
</bean>
<!-- Policy -->
<bean id="PROPAGATION_REQUIRED" class="org.apache.camel.spring.spi.SpringTransactionPolicy">
<property name="transactionManager" ref="jta.transactionManager"/>
<!-- Atomikos TX Manager -->
<property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"/>
</bean>
If anyone has worked on apache camel using XA transactions can you guys provide me your sample config file so that i can use and modify it.
This works for me. It looks like you've missed the ActiveMQResourceManager. Also ensure you use a XAPooledConnectionFactory otherwise your MDBs will disconnect after every bind to check for a message (and CPU on the broker will go through the roof).
<?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.2.xsd">
<bean id="env" class="java.lang.String">
<constructor-arg value="test-junit"/>
</bean>
<!-- JMS configuration -->
<bean id="resourceManager" class="org.apache.activemq.pool.ActiveMQResourceManager"
init-method="recoverResource">
<property name="transactionManager" ref="atomikosTransactionManager" />
<property name="connectionFactory" ref="pooledJmsXaConnectionFactory" />
<property name="resourceName" value="activemq.default" />
</bean>
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="atomikosTransactionManager" />
<property name="userTransaction" ref="userTransaction" />
</bean>
<bean id="pooledJmsXaConnectionFactory" class="org.apache.activemq.pool.XaPooledConnectionFactory"
init-method="start" destroy-method="stop">
<property name="maxConnections" value="8" />
<property name="connectionFactory" ref="jmsXaConnectionFactory" />
<property name="transactionManager" ref="atomikosTransactionManager" />
</bean>
<!-- <bean id="pooledJmsXaConnectionFactory" class="com.atomikos.jms.AtomikosConnectionFactoryBean"
init-method="init" destroy-method="close"> <property name="poolSize" value="8"
/> <property name="uniqueResourceName" value="activemq" /> <property name="xaConnectionFactory"
ref="jmsXaConnectionFactory" /> </bean> -->
<bean id="jmsXaConnectionFactory" class="org.apache.activemq.ActiveMQXAConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616" />
<property name="redeliveryPolicy">
<bean class="org.apache.activemq.RedeliveryPolicy">
<property name="maximumRedeliveries" value="0" />
</bean>
</property>
</bean>
<bean id="jms" class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="connectionFactory" ref="pooledJmsXaConnectionFactory" />
<property name="transacted" value="false" />
<property name="transactionManager" ref="transactionManager" />
</bean>
<!-- JMS configuration for test enqueue/dequeue without transactions -->
<bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616" />
</bean>
<bean id="myEmf"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="persistenceXmlLocation" value="classpath:META-INF/test-persistence.xml"/>
</bean>
<!-- JDBC configuration -->
<bean id="dataSource" class="org.apache.commons.dbcp2.managed.BasicManagedDataSource">
<property name="transactionManager" ref="atomikosTransactionManager" />
<!-- <property name="driverClassName" value="org.apache.derby.jdbc.EmbeddedXADataSource40" /> -->
<property name="driverClassName" value="org.apache.derby.jdbc.EmbeddedDriver" />
<property name="url" value="jdbc:derby:target/testdb;create=true" />
<property name="defaultAutoCommit" value="false" />
</bean>
<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close">
<property name="forceShutdown" value="false" />
</bean>
<bean id="userTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout" value="120" />
</bean>
<!-- -->
<bean id="springContext" class="org.example.testutils.SpringContext"/>
</beans>

Spring resource

Problem: I want to make the below bean definitions (specified in aaplicationContext.xml) optional for "org.springframework.web.context.ContextLoaderListener". If i am not providing the "emsPropLocation" context parameter correctly, tomcat web container is not able to initialized properly and it is obvious reason. Is there any way to make it optional?
appicationContext.xml:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound" value="false"/>
<property name="location" value="file:/#{contextParameters.emsPropLocation}" />
</bean>
<!-- TIBCO Connection Factory Bean -->
<bean id="tibcoConnectionFactory" class="com.tibco.tibjms.TibjmsConnectionFactory">
<constructor-arg value="${emsServerURL}"/>
<property name="userName" value="${emsUserName}"/>
<property name="userPassword" value="${emsPassword}"/>
<property name="connAttemptCount" value="${connAttemptCount}"/>
<property name="connAttemptDelay" value="${connAttemptDelay}"/>
<property name="connAttemptTimeout" value="${connAttemptTimeout}"/>
<property name="reconnAttemptCount" value="${reconnAttemptCount}"/>
<property name="reconnAttemptDelay" value="${reconnAttemptDelay}"/>
<property name="reconnAttemptTimeout" value="${reconnAttemptTimeout}"/>
</bean>
<!-- bean id="tibcoUtil" class="com.nr.ns.upload.TibcoUtil" scope="singleton">
<constructor-arg value="true"/>
</bean-->
<bean id="jmsExceptionListener" class="com.nr.ns.upload.LogMsgExceptionListener"/>
<!-- Spring CachingConnectionFactory Bean -->
<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<constructor-arg ref="tibcoConnectionFactory"/>
<property name="reconnectOnException" value="${reconnectOnException}"/>
<property name="sessionCacheSize" value="${sessionCacheSize}"/>
<property name="exceptionListener" ref="jmsExceptionListener"/>
</bean>
<!-- JMSTemplate Bean -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<constructor-arg ref="connectionFactory"/>
<property name="receiveTimeout" value="${receiveTimeout}"/>
<property name="deliveryMode" value="${deliveryMode}"/>
</bean>
We are keeping WAR file outside tomcat and to make it happen we have "app.xml" file inside TOMCAT_HOME/conf/Catalina/localhost.
app.xml:
<Context path="/app"
docBase="/abc/ccp/app.war"
reloadable="true"
unpackWAR="false">
<Parameter name="emsPropLocation"
value="/xyz/config/EMSServerConf.properties"
override="false"/>
</Context>
have a try to change the ignoreResourceNotFound property of your propertyConfigurer to true.
If contextParameters.emsPropLocation is not set, this will default to what is afer the colon.
<property name="location" value="file:/#{contextParameters.emsPropLocation:/xyz/config/EMSServerConf.properties}" />

Resources