Database Configuration In Spring As Well As Hibernate config files - database

I am a newbie to Spring and Hibernate.And while browsing through projects, I found database details like connection-url, username, password in both hibernate and spring xml config files.
I need to understand why we do so ?

Yes. If you using both Hibernate and Spring then you can also try like that.
You need both hibernate.cfg.xml for hibernate and ApplicationContext.xml for spring.
do like this, at first create your hibernate.cfg.xml.
i.e
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/country</property>
<property name="connection.username">root</property>
<property name="connection.password">password</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">false</property>
<property name="hibernate.current_session_context_class">thread</property>
<mapping class="com.hibernate.test" />
</session-factory>
</hibernate-configuration>
now create your ApplictionContext.xml,and add your hibernate.cfg.xml as properties in sessionFactory bean.
i.e
<?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
//package to scan for Annotated classes
<context:component-scan base-package="com.hibernate.spring" />
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
//add and locate the hibernate.cfg.xml here
<property name="configLocation" value="classpath:hibernate.cfg.xml" />
</bean>
</beans>
by this you only need to call Application.xml,the hibernate.cfg.xml will automatically loaded.

You have two options.
You can have hibernate to manage your database connections or you can have Spring managing your connections.
When you have Hibernate managing your connections, you only need to tell Spring where hibernate configuration is. Sorry, I couldn't find very easily an example where Hibernate manages the connections and Spring only "using" hibernate.
The other option is to use Spring to manage your connections and hbm files/annotated entities.
Here is a snippet from Spring docs
<beans>
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:hsql://localhost:9001"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<bean id="mySessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource"/>
<property name="mappingResources">
<list>
<value>product.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.HSQLDialect
</value>
</property>
</bean>
</beans>
and here the full documentation
http://docs.spring.io/spring/docs/4.0.5.RELEASE/spring-framework-reference/htmlsingle/#orm-hibernate
Besides very specific problems, I can't a lot of differences on using either way but I would prefer to let Spring to manage my database connections and I can let Spring to deal transactions for example and have everything centralized in the same configuration file.

Related

Steps to setup distributed transaction management in JBoss

I am trying to implement a distributed transaction (XA) in JBoss EAP 6.2 application server so that multiple datastores can be accessed in a single coordinated atomic transaction. To be more precise, I'd like my transactional service method to write to a database table and to a message queue in such a way that these two operations are either both committed or both rolled back consistently (all or nothing).
My approach is based on the following:
Use Spring JTA Transaction Manager
Configure the entity manager to use an XA JDBC datasource, defined in JBoss application server and accessed via a JNDI name
Use ActiveMQ XA Connection Factory for messaging
The problem I am facing is that only the database operation is rolled back. The message written to ActiveMQ queue is always commited regardless of the transaction being rolled back or not.
Key elements of my configuration:
<tx:jta-transaction-manager/>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jtaDataSource" ref="xaDataSource" />
...
<property name="jpaProperties">
<props>
...
<prop key="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</prop>
</props>
</property>
</bean>
<jee:jndi-lookup id="xaDataSource" jndi-name="xaDataSource"/>
<bean id="xaConnectionFactory" class="org.apache.activemq.ActiveMQXAConnectionFactory">
<property name="brokerURL">
<value>tcp://localhost:61616</value>
</property>
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="xaConnectionFactory" />
<property name="defaultDestinationName" value="TEST_QUEUE" />
<property name="sessionTransacted" value="true"/>
</bean>
I finally got this working. The key was to configure the JMS connection factory within a JBoss Resource Adapter. Detailed steps below:
1. Install Apache ActiveMQ
Version used: 5.11.3
Detailed install instructions can be found here.
Once ActiveMQ installed, Create a queue named TEST_QUEUE (use admin console: http://127.0.0.1:8161/admin/index.jsp)
2. Set up Spring application context
Key elements:
Use Spring JTA Transaction Manager tag: this will prompt the use of
the app server transaction manager;
Configure the datasource bean to use the XA datasource defined in the app server (see XA JDBC datasource setup);
Wire the jtaDataSource attribute of the Entity Manager Factory to the XA datasource;
Set Hibernate property manager_lookup_class to JBossTransactionManagerLookup;
Configure the connection factory bean to use the XA connection factory bean defined in the app server (see XA Connection Factory setup);
Set property transactedSession of connection factory bean to false.
e
<?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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:jms="http://www.springframework.org/schema/jms" 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/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd">
<jpa:repositories base-package="com.company.app.repository" />
<context:component-scan base-package="com.company.app" />
<tx:annotation-driven transaction-manager="transactionManager"/>
<tx:jta-transaction-manager/>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jtaDataSource" ref="xaDataSource" />
<property name="packagesToScan" value="com.company.app.domain" />
<property name="persistenceProviderClass" value="org.hibernate.ejb.HibernatePersistence" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect" />
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</prop>
</props>
</property>
</bean>
<jee:jndi-lookup id="xaDataSource" jndi-name="jdbc/xaDataSource"/>
<bean id="xaConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="activemq/ConnectionFactory" />
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="xaConnectionFactory" />
<property name="defaultDestinationName" value="TEST_QUEUE" />
<property name="sessionTransacted" value="false"/>
</bean>
3. Set up application server (JBoss)
For a distributed transaction to work, all the datasources involved must be of type XA. JBoss supports JDBC XA datasource (xa-datasource tag) out of the box. The XA configuration for JMS datasource is achieved by defining appropriate Resource Adapter.
3.1. XA JDBC datasource
In standalone.xml under <subsystem xmlns="urn:jboss:domain:datasources:1.1"> <datasources> add an XA JDBC datasource:
<xa-datasource jndi-name="java:/jdbc/xaDataSource" pool-name="jdbc/xaDataSource" enabled="true">
<xa-datasource-property name="URL">
jdbc:oracle:thin:#<hostname>:<port_number>/<SID>
</xa-datasource-property>
<xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>
<driver>ojdbc6-11.2.0.3.jar</driver>
<security>
<user-name>db_user</user-name>
<password>password</password>
</security>
</xa-datasource>
3.2. XA Conncection Factory
Resource adapters are a concept from the J2EE Connector Architecture (JCA) and are used to interface with Enterprise Information Systems, i.e. systems external to the application server (e.g., relational databases, mainframes, Message-Oriented Middleware, accounting systems, etc.).
First you need to install ActiveMQ RAR (Resource adapter ARchive) in JBoss, by dropping the appropriate RAR file from maven central under \standalone\deployments. Then, in standalone.xml, under <subsystem xmlns="urn:jboss:domain:resource-adapters:1.1"> add the following:
<resource-adapters>
<resource-adapter id="activemq-rar.rar">
<archive>
activemq-rar-5.11.3.rar
</archive>
<transaction-support>XATransaction</transaction-support>
<config-property name="Password">
admin
</config-property>
<config-property name="UserName">
admin
</config-property>
<config-property name="ServerUrl">
tcp://localhost:61616?jms.rmIdFromConnectionId=true
</config-property>
<connection-definitions>
<connection-definition class-name="org.apache.activemq.ra.ActiveMQManagedConnectionFactory" jndi-name="java:/activemq/ConnectionFactory" enabled="true" pool-name="ConnectionFactory">
<xa-pool>
<min-pool-size>1</min-pool-size>
<max-pool-size>20</max-pool-size>
<prefill>false</prefill>
<is-same-rm-override>false</is-same-rm-override>
</xa-pool>
</connection-definition>
</connection-definitions>
</resource-adapter>
</resource-adapters>
For further details about installing ActiveMQ RAR in JBoss, refer to RedHat documentation.
4. Make your Service method Transactional
#Service
public class TwoPhaseCommitService {
#Autowired
private EmployeeRepository employeeRepository;
#Autowired
private JmsTemplate jmsTemplate;
#Transactional
public void writeToDbAndQueue() {
final Employee employee = new Employee();
employee.setFirstName("John");
employee.setLastName("Smith");
// persist entity to database
employeeRepository.save(employee);
// write message to TEST_QUEUE
jmsTemplate.send(new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage(employee.getFirstName());
}
});
// To test rollback uncomment code below:
// throw new RuntimeException("something went wrong. Transaction must be rolled back!!!");
}
}

Camel route on Wildfly Swarm trying to load h2 database when it shouldn't

I have a Camel route running on Wildfly Swarm (2017.8.1) that connects to a SQL Server database using JTDS driver. However when I try and run it, it tries to load the h2 database module. I'm not using h2.
<?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://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>app.properties</value>
</property>
</bean>
<bean id="coreDS" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="net.sourceforge.jtds.jdbc.Driver"/>
<property name="url" value="${db.core.uri}"/>
<property name="username" value="${db.core.user}"/>
<property name="password" value="${db.core.password}"/>
</bean>
<bean id="sql" class="org.apache.camel.component.sql.SqlComponent">
<property name="dataSource" ref="coreDS"/>
</bean>
<camelContext xmlns="http://camel.apache.org/schema/spring">
<propertyPlaceholder id="placeholder" location="classpath:app.properties"/>
<route id="retrieveZipFile">
<from uri="{{ftp.silica.uri}}"/>
<log message="checking for files"/>
<to uri="file://Data/temp/zip"/>
<to uri="sql:insert into dbo.Source_In(date, sourceInSystemId, filename) values (getdate(), 1, 'test');dataSource=coreDS"/>
</route>
</camelContext>
</beans>
Error:
Caused by: org.jboss.modules.ModuleLoadError: com.h2database.h2:main
at org.jboss.modules.ModuleLoadException.toError(ModuleLoadException.java:74)
at org.jboss.modules.Module.getPathsUnchecked(Module.java:1435)
at org.jboss.modules.Module.loadModuleClass(Module.java:601)
at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:190)
Why is the h2 module required? I've tried adding it to my POM bt it still fails.

Using xa transactions in Karaf

I'm trying to create a xa transaction between postgres (using pax-jdbc to set up xa datasource) and activemq in karaf, using blueprint and camel.
The setup is the following: I have a camel route which receives a jms message, does some database updates, and then sends a jms message to another queue. This other queue then reads the updated records.
The problem is that the second queue is reading the old data instead of getting the updated data.
I believe the cause is that JMS transaction is being "released" first, and the database has not commited the changes yet.
If I put a Thread.sleep(1000) on the second queue, I always read the correct data. Also, I believe the transaction is working fine, if I throw an exception in the camel route, I see no changes in the database, and the jms message does not get sent, proving they are working together.
Here's my blueprint with the jta configs and camel route:
<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"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
xmlns:tx="http://aries.apache.org/xmlns/transactions/v2.0.0"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://aries.apache.org/xmlns/transactions/v2.0.0 http://aries.apache.org/schemas/transaction/transactionv20.xsd">
<tx:enable/>
<bean id="resourceManager" class="org.apache.activemq.pool.ActiveMQResourceManager" init-method="recoverResource">
<property name="transactionManager" ref="jtaTxManager" />
<property name="connectionFactory" ref="jmsConnectionFactory" />
<property name="resourceName" value="activemq.localhost" />
</bean>
<bean id="redeliveryPolicy" class="org.apache.activemq.RedeliveryPolicy">
<property name="maximumRedeliveries" value="0"/>
</bean>
<bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQXAConnectionFactory">
<property name="brokerURL" value="$ext{brokerUrl}"/>
<property name="userName" value="karaf"/>
<property name="password" value="karaf"/>
<property name="redeliveryPolicy" ref="redeliveryPolicy"/>
</bean>
<bean id="jmsXaPoolConnectionFactory" class="org.apache.activemq.pool.JcaPooledConnectionFactory">
<property name="name" value="activemq.default"/>
<property name="maxConnections" value="4"/>
<property name="transactionManager" ref="jtaTxManager"/>
<property name="connectionFactory" ref="jmsConnectionFactory"/>
</bean>
<!-- define the activemq Camel component so we can integrate with the AMQ broker -->
<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent">
<!-- due to a bug in activemq-camel we must configure using a nested configuration bean -->
<property name="configuration">
<bean class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="jmsXaPoolConnectionFactory"/>
<!-- JTA transaction manager (Spring interface to Aries-TM) -->
<property name="transactionManager" ref="springJtaTxManager"/>
<!-- IMPORTANT: We set local transactions to false, because the JtaTransactionManager
will take care of enrolling the XA JMS Connection when needed. -->
<property name="transacted" value="false"/>
<!-- IMPORTANT: and disable cache level as the JtaTransactionManager needs to control the consumers
from its JcaPooledConnectionFactory -->
<property name="cacheLevelName" value="CACHE_NONE"/>
</bean>
</property>
</bean>
<reference id="jtaTxManager" interface="org.apache.geronimo.transaction.manager.RecoverableTransactionManager"/>
<reference id="springJtaTxManager" interface="org.springframework.transaction.PlatformTransactionManager"/>
<bean id="required" class="org.apache.camel.spring.spi.SpringTransactionPolicy">
<property name="transactionManager" ref="springJtaTxManager"/>
<property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"/>
</bean>
<camelContext xmlns="http://camel.apache.org/schema/blueprint" id="om-bstask-context" useMDCLogging="true">
<route id="notificationConsumer">
<from uri="activemq:queue:incomingNotification"/>
<transacted ref="required"/>
<doTry>
<!-- execute some bd updates -->
<to uri="activemq:anotherQueue"/>
<doCatch>
<exception>java.lang.Exception</exception>
<handled>
<constant>false</constant>
</handled>
<bean beanType="xxxx.MessagingUtil"
method="logErrorMessage(${headers.JMSXDeliveryCount}, ${headers.om_txid}, 'incomingNotification', ${exception})"/>
</doCatch>
<doFinally>
</doFinally>
</doTry>
</route>
</camelContext>
</blueprint>
Do I have something wrong with my setup? Or what could explain this behavior?
PS I got the config from https://github.com/camelinaction/camelinaction2/blob/master/chapter12/xa-karaf/src/main/resources/OSGI-INF/blueprint/camel-context.xml

Problems With Activiti OSGI and Blueprint

i try to use Activiti in KARAF OSGI with camel.
I copied some parts out of the service mix configuration.
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:camel="http://camel.apache.org/schema/blueprint"
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 http://camel.apache.org/schema/blueprint/camel-blueprint.xsd"
xmlns:jpa="http://aries.apache.org/xmlns/jpa/v1.0.0"
xmlns:tx="http://aries.apache.org/xmlns/transactions/v1.0.0"
xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0">
<ext:property-placeholder />
<!--
Setting up the process engine configuration, using an embedded H2 database together with our default Aries
transaction manager.
-->
<bean id="dataSource" class="org.h2.jdbcx.JdbcDataSource">
<property name="URL" value="jdbc:h2:~/activiti"/>
<property name="user" value="sa"/>
<property name="password" value=""/>
</bean>
<reference id="transactionManager" interface="javax.transaction.TransactionManager"/>
<bean id="configuration" class="org.activiti.engine.impl.cfg.JtaProcessEngineConfiguration" ext:field-injection="true">
<property name="databaseType" value="h2"/>
<property name="dataSource" ref="dataSource"/>
<property name="transactionManager" ref="transactionManager"/>
<property name="databaseSchemaUpdate" value="true"/>
<property name="transactionsExternallyManaged" value="true" />
<property name="defaultCamelContext" value="defaultContext"/>
</bean>
<!--
Set up the custom resolver implementation to ease integration with Camel routes
-->
<bean id="resolver" class="de.myproject.CamelAwareELResolver"/>
<reference-list availability="optional" interface="org.activiti.camel.ContextProvider">
<reference-listener ref="resolver" bind-method="addContextProvider" unbind-method="removeContextProvider" />
</reference-list>
<reference-list availability="optional" interface="org.activiti.engine.delegate.JavaDelegate">
<reference-listener ref="resolver" bind-method="bindService" unbind-method="unbindService" />
</reference-list>
<!--
Set up the Activiti process engine itself
-->
<bean id="processEngineFactory" class="org.activiti.osgi.blueprint.ProcessEngineFactoryWithELResolver" init-method="init" destroy-method="destroy">
<property name="processEngineConfiguration" ref="configuration"/>
<property name="bundle" ref="blueprintBundle"/>
<property name="blueprintELResolver" ref="resolver" />
</bean>
<bean id="processEngine" factory-ref="processEngineFactory" factory-method="getObject"/>
<bean id="runtimeService" factory-ref="processEngine" factory-method="getRuntimeService" />
<!--
Register the ProcessEngine and RuntimeService as OSGi services to allow other bundles to use them
-->
<service ref="processEngine" interface="org.activiti.engine.ProcessEngine"/>
<service ref="runtimeService" interface="org.activiti.engine.RuntimeService"/>
<bean id="routeBuilder" class="de.myproject.bpmn.BpmnRestRouteBuilder"/>
<camelContext id="clientContext" trace="false" xmlns="http://camel.apache.org/schema/blueprint">
<routeBuilder ref="routeBuilder" />
<route id="entryPointClient">
<from uri="vm:client_queue"/>
<to uri="jobsbpmn://bpmn"/>
</route>
</camelContext>
I can deploy the bundle without problems in the container. When i trigger a workflow with a camel module i get those exception:
2016-11-08 11:56:43,569 | ERROR | m://client_queue | JobsBpmnProducer
| 45 - jobs-logging - 1.0.0 | No Processdefinition found with this
Identifier ActivitiException: Expecting a
SpringProcessEngineConfiguration for the Activiti Camel module.
ClassCastException:
org.activiti.engine.impl.cfg.JtaProcessEngineConfiguration cannot be
cast to org.activiti.spring.SpringProcessEngineConfiguration**
How can i deploy a OSGI conform Processengine using spring to get Camel to work?
This problem might be fixed in the Activity code already.
See https://github.com/Activiti/Activiti/pull/519
Can you try with the newest Activitiy version?

Starting ActiveMQ message listener in Tomcat?

I've created an ActiveMQ MessageListener and configured it using Spring. I'm hosting the listener in Tomcat. When I start up the web application (that features only the listener), should the listener automatically start? Or do I need additional configuration?
Here's what I have. First, updated the web.xml to allow spring to configure itself on startup,
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/spring/applicationContext.xml</param-value>
</context-param>
</web-app>
Then I created the applicationContext.xml to configure the ActiveMQ listener,
<?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:context="http://www.springframework.org/schema/context"
xmlns:amq="http://activemq.apache.org/schema/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config />
<context:component-scan base-package="com.somepackage"/>
<context:property-placeholder location="classpath:env.properties"/>
<bean id="jmsFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616" />
</bean>
<bean id="documentListener" class="com.somepackage.SomeListener" />
<bean id="container"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="cachingConnectionFactory"/>
<property name="messageListener" ref="documentListener"/>
<property name="destinationName" value="STOCKS.MSFT" />
</bean>
<bean id="cachingConnectionFactory"
class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="jmsFactory" />
<property name="sessionCacheSize" value="1" />
</bean>
</beans>
And that's it. Based on what I've seen around the web, I can't tell if that's all I need? Maybe I need some other configuration in Tomcat to kick off the listener?
This was actually working. I was debugging this using Eclipse and I had to do a couple refreshes, cleans and restarts before it suddenly decided to work.
To answer my own question, yes, this is all that is required in order to run a listener in a web application from within Tomcat. It can be totally configured with XML only.

Resources