I'm using Spring JMS and ActiveMQ where I have a client that pushes messages to a Queue and I have multiple consumer threads that are listening and removing messages from the Queue. Some of the time the same messages gets dequeued from the Queue by two consumers. I don't want this behavior and want to ensure the only one messages is processed by only one consumer thread. Any ideas on where I've gone wrong?
Spring 3.2.2 Config:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util"
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
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<context:annotation-config />
<context:component-scan base-package="com.myapp" />
<!-- JMS ConnectionFactory config Starts -->
<bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL">
<value>${brokerURL}</value>
</property>
<property name="userName" value="${username}" />
<property name="password" value="${password}" />
</bean>
<bean id="pooledJmsConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory"
init-method="start" destroy-method="stop">
<property name="connectionFactory" ref="jmsConnectionFactory" />
</bean>
<!-- JMS ConnectionFactory config Ends -->
<!-- JMS Template config Starts -->
<bean id="myQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="${activemq.consumer.destinationName}" />
</bean>
<bean id="myQueueTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="pooledJmsConnectionFactory" />
</bean>
<!-- JMS Template config Ends -->
<!-- JMS Listener config starts -->
<bean id="simpleMessageConverter"
class="org.springframework.jms.support.converter.SimpleMessageConverter" />
<bean id="myContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="concurrentConsumers" value="${threadcount}" />
<property name="connectionFactory" ref="pooledJmsConnectionFactory" />
<property name="destination" ref="myQueue" />
<property name="messageListener" ref="myListener" />
<property name="messageSelector" value="JMSType = 'New'" />
</bean>
<bean id="myListener"
class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
<constructor-arg>
<bean class="myapp.MessageListener" />
</constructor-arg>
<property name="defaultListenerMethod" value="receive" />
<property name="messageConverter" ref="simpleMessageConverter" />
</bean>
<!-- JMS Listener config Ends -->
<!-- enable the configuration of transactional behavior based on annotations -->
<bean id="myJMSMessageSender" class="myapp.JMSMessageSender">
<property name="jmsTemplate" ref="myQueueTemplate" />
<property name="jmsQueue" ref="myQueue" />
<property name="messageConverter" ref="simpleMessageConverter" />
</bean>
<bean id="myQueueTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="pooledJmsConnectionFactory" />
</bean>
</beans>
ActiveMQ 5.9.1 config:
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="instance8161" dataDirectory="${activemq.data}" persistent="false">
<destinationPolicy>
<policyMap>
<policyEntries>
<policyEntry topic=">">
<!-- The constantPendingMessageLimitStrategy is used to prevent
slow topic consumers to block producers and affect other consumers
by limiting the number of messages that are retained
For more information, see:
http://activemq.apache.org/slow-consumer-handling.html
-->
<pendingMessageLimitStrategy>
<constantPendingMessageLimitStrategy limit="1000"/>
</pendingMessageLimitStrategy>
</policyEntry>
</policyEntries>
</policyMap>
</destinationPolicy>
... <!-- rest is default ActiveMQ Config -->
</broker>
Most likely, your myapp.MessageListener (or one of its dependencies) is not thread-safe and you are seeing cross-talk across the consumer threads.
Best practice is to craft your listener as stateless (no mutated fields in the class). If that's not possible, you need to protect shared variables with locks.
Related
I am trying to get the value of "value" attribute of second bean's property with name "jdbcUrl". I tried multiple xpath combinations, but the only one that works for me is (//#value)[4] which is not optimal at all because if someone changes order of properties, I will get the wrong value. Is there more safer way to do it using xPath?
<?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:mvc="http://www.springframework.org/schema/mvc"
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/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- Add support for component scanning -->
<context:component-scan base-package="xxx" />
<!-- Add support for conversion, formatting and validation support -->
<mvc:annotation-driven/>
<!-- Define Spring MVC view resolver -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- Step 1: Define Database DataSource / connection pool -->
<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="org.postgresql.Driver" />
<property name="jdbcUrl" value="afsafa" />
<property name="user" value="postgres" />
<property name="password" value="admin" />
<!-- these are connection pool properties for C3P0 -->
<property name="initialPoolSize" value="5"/>
<property name="minPoolSize" value="5" />
<property name="maxPoolSize" value="20" />
<property name="maxIdleTime" value="30000" />
</bean>
<!-- Step 2: Setup Hibernate session factory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="packagesToScan" value="ngsi" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<!-- Step 3: Setup Hibernate transaction manager -->
<bean id="myTransactionManager"
class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- Step 4: Enable configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="myTransactionManager" />
<!-- Add support for reading web resources: css, images, js, etc ... -->
<mvc:resources location="resources" mapping="/resources/**"/>
</beans>
get the value of "value" attribute of second bean's property with name "jdbcUrl"
That translates directly to
/*/*:bean[2]/*:property[#name="jdbcUrl"]/#value
That's XPath 2.0 syntax; if you're still using XPath 1.0 for some reason, then you can't use *:local; instead, either bind a prefix to the namespace http://www.springframework.org/schema/beans, or use *[local-name()="local"]
I have a situation with my spring integration with rabbitmq. The messages are sent to the queues but end up in the ready state and one as unacknowledged but the consumer doesn't gets them.
Thx xml configuration is like this:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-amqp="http://www.springframework.org/schema/integration/amqp"
xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/amqp
http://www.springframework.org/schema/integration/amqp/spring-integration-amqp.xsd
http://www.springframework.org/schema/rabbit
http://www.springframework.org/schema/rabbit/spring-rabbit.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:spring/prj-rabbitmq-context-thirdparty.properties" ignore-unresolvable="true" order="3"/>
<rabbit:connection-factory
id="prjRabbitmqConnectionFactory"
addresses="${rabbitmq.addresses}"
username="${rabbitmq.username}"
password="${rabbitmq.password}"
connection-timeout="5000" />
<bean id="rabbitTxManager"
class="org.springframework.amqp.rabbit.transaction.RabbitTransactionManager">
<property name="connectionFactory" ref="prjRabbitmqConnectionFactory"/>
</bean>
<rabbit:template
id="prjRabbitmqTemplate"
connection-factory="prjRabbitmqConnectionFactory"
message-converter="serializerMessageConverter"
retry-template="retryTemplate" />
<bean id="retryTemplate" class="org.springframework.retry.support.RetryTemplate">
<property name="backOffPolicy">
<bean class="org.springframework.retry.backoff.ExponentialBackOffPolicy">
<property name="initialInterval" value="1000" />
<property name="multiplier" value="3" />
<property name="maxInterval" value="10000" />
</bean>
</property>
</bean>
<rabbit:admin
id="prjRabbitmqAdmin"
auto-startup="true"
connection-factory="prjRabbitmqConnectionFactory" />
<rabbit:queue
id="prjSyncQueue"
name="${prj.sync.queue}"
durable="true">
<rabbit:queue-arguments>
<entry key="x-ha-policy" value="all" />
</rabbit:queue-arguments>
</rabbit:queue>
<rabbit:listener-container
connection-factory="prjRabbitmqConnectionFactory"
acknowledge="auto"
channel-transacted="true"
transaction-manager="rabbitTxManager"
task-executor="prjSyncExecutor"
concurrency="1"
max-concurrency="2"
requeue-rejected="true"
message-converter="serializerMessageConverter">
<rabbit:listener
ref="prjProcessorService"
queue-names="${prj.sync.queue}" method="processMessage" />
</rabbit:listener-container>
<task:executor id="prjSyncExecutor"
pool-size="${prj.sync.concurrency.min}-${prj.sync.concurrency.max}"
keep-alive="${prj.sync.concurrency.keep-alive}"
queue-capacity="${prj.sync.concurrency.queue}"
rejection-policy="CALLER_RUNS"/>
<int:channel
id="prjChannel" />
<int-amqp:outbound-channel-adapter
channel="prjChannel"
amqp-template="prjRabbitmqTemplate"
exchange-name="prjSyncExchange"
routing-key="prj-event"
default-delivery-mode="PERSISTENT" />
<rabbit:direct-exchange
name="prjSyncExchange">
<rabbit:bindings>
<rabbit:binding
queue="prjSyncQueue"
key="prj-event" />
</rabbit:bindings>
</rabbit:direct-exchange>
<int:gateway
id="prjGateway"
service-interface="ro.oss.niinoo.thirdparty.prj.gateway.prjEnrichmentGateway">
<int:method
name="send"
request-channel="prjChannel"/>
</int:gateway>
<bean id="prjProcessorService" class="ro.oss.niinoo.thirdparty.prj.processor.impl.prjEnrichmentProcessorImpl" />
<bean id="serializerMessageConverter" class="ro.oss.niinoo.thirdparty.prj.serializer.prjSerializer"/>
On the server restart the first one is picked up but on the next call the messages piles up in the queue. Do you have any idea why this might happen ?
Thanks
Daniel
EDIT:
The consumer code:
public class JsonEnrichmentService implements EnrichmentService {
#Resource
private UserQueryService userQueryService;
#Resource
private SecurityContextService securityContextService;
#Override
public void processMessage(POJO record) {
System.out.println(record);
}
This will call a new service that has a Transactional annotation to it.
In my experience, this is generally caused by the listener thread being "stuck" in user code someplace. Take a thread dump to see what the listener thread is doing.
I have started using Spring-integration for listening on JMS-queues, and it's working satisfactory, but I have somewhat of an issue with the amount of xml-configuration required in order to set up a listener. Most of this is boilerplate, what changes is really just the jms-instance and the name of the queue to listen to, and the class and method to invoke upon receiving a message. Here is an example:
<?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:int="http://www.springframework.org/schema/integration"
xmlns:jms="http://www.springframework.org/schema/integration/jms"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/jms http://www.springframework.org/schema/integration/jms/spring-integration-jms.xsd">
<bean id="jms.queue.myQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="${myApplication.jms.queue.myQueue}" />
</bean>
<bean id="jms.container.myJMSListender"
class="org.springframework.jms.listener.DefaultMessageListenerContainer"
destroy-method="destroy">
<property name="connectionFactory"
ref="jmsConnectionFactory" /> <!-- Defined elsewhere -->
<property name="destination"
ref="jms.queue.myQueue" />
<property name="sessionTransacted"
value="true" />
</bean>
<int:publish-subscribe-channel id="channel.myQueue" />
<jms:message-driven-channel-adapter id="channelAdapter.myQueue"
container="jms.container.myQueue"
channel="channel.myQueue"
acknowledge="transacted"/>
<int:service-activator id="serviceActivator.myQueue"
input-channel="channgel.myQueue"
ref="myQueueJMSListener"
method="handleMessage" />
</beans>
As you can see, a lot of config for something fairly simple, and with quite a lot of JMS-listeners this becomes tedious, both to read and write.
Is there a way to configure listening to a queue with Spring-integration that requires less boilerplate? I've looked into creating my own XML-tag, but I'm kinda hoping that there is a simpler solution.
You only need an external container if you need to configure properties that are not exposed on the namespace.
<jms:message-driven-channel-adapter id="channelAdapter.myQueue"
destination="jms.queue.myQueue"
connection-factory="jmsConnectionFactory"
channel="channel.myQueue"
acknowledge="transacted"/>
Found that Spring integration has annotation support.
Requires some setup, but this can be used for multiple listeners:
<amq:connectionFactory id="jmsConnectionFactory" brokerURL="${jms.host}">
<amq:redeliveryPolicy>
<amq:redeliveryPolicy maximumRedeliveries="0" />
</amq:redeliveryPolicy>
</amq:connectionFactory>
<bean id="cachingJmsConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="jmsConnectionFactory" />
</bean>
<jms:annotation-driven />
<bean id="jmsListenerContainerFactory" class="org.springframework.jms.config.DefaultJmsListenerContainerFactory">
<property name="connectionFactory" ref="cachingJmsConnectionFactory" />
</bean>
Then, listening to a certain queue is as simple as:
#JmsListener(destination = "${myQueueName}")
public void listen(#Payload final String payload) {
I have a simple Hello World example that passes a Map to Camel and displays the values to the console via Log4J. I want to expand this example to render this map in JSON by adding the Jackson library to my Camel applicationContext.xml
First I tried adding the following XML tags to my applicationContext.xml (as specified at
http://camel.apache.org/json.html under "Using JSON in Spring DSL")
<camel:dataFormats>
<camel:json id="jack" library="Jackson"/>
</camel:dataFormats>
But when I add this to my applicationContext.xml, and run my Java code I get the following XmlBeanDefinitionStoreException message:
cvc-complex-type.2.4.a: Invalid content was found starting with element 'dataFormats'. One of '{"http://camel.apache.org/schema/
spring":route}' is expected.
Moving these tags inside or outside of my camelContext yields the same error (just a longer list of URLs when inside the camelContext).
Is there something else I need to specify in my ApplicationContext.xml?
Here is my current applicationContext.xml:
UPDATED: The following xml now works. Had to move the location of the dataFormats XML tags.
<?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:camel="http://camel.apache.org/schema/spring"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean
class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />
<context:component-scan base-package="sample" />
<context:annotation-config />
<camel:camelContext id="HelloWorldContext">
<camel:dataFormats>
<camel:json id="jack" library="Jackson"/>
</camel:dataFormats>
<camel:route>
<camel:from
uri="timer://hello.world.request.timer?fixedRate=true&period=10000" />
<camel:to uri="log:hello.world.request?level=INFO?showAll=true" />
<camel:bean ref="helloWorld" />
<camel:to uri="log:hello.world.response?level=INFO?showAll=true" />
</camel:route>
</camel:camelContext>
<bean id="jms" class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="configuration" ref="jmsConfig" />
</bean>
<bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="jmsConnectionFactory" />
<property name="transacted" value="false" />
<property name="concurrentConsumers" value="1" />
</bean>
<bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="vm://localhost" />
<property name="redeliveryPolicy" ref="redeliveryPolicy" />
<property name="prefetchPolicy" ref="prefetchPolicy" />
</bean>
<bean id="prefetchPolicy" class="org.apache.activemq.ActiveMQPrefetchPolicy">
<property name="queuePrefetch" value="5" />
</bean>
<bean id="redeliveryPolicy" class="org.apache.activemq.RedeliveryPolicy">
<property name="maximumRedeliveries" value="1" />
<property name="backOffMultiplier" value="2" />
<property name="initialRedeliveryDelay" value="2000" />
<property name="useExponentialBackOff" value="true" />
</bean>
</beans>
The dateFormats and json elements are part of the camel namespace. You need to specify that
<camel:dataFormats>
<camel:json id="jack" library="Jackson"/>
</camel:dataFormats>
I have a Spring MVC application, and I was pretty confident I understand all the various configuration I have set up, however, in a recent exercise I have been switching over to use pure annotation based config (apart from the security configuration) and I have seen a change in the application's behavior which has made me think twice on a few points.
The main behavior change, is that it appears that my old app was running an OpenSessionInView type pattern - as several of my domain objects were lazy loading elements, but those elements could then still be accessed outside of the transactional/service layer classes (e.g. in my controllers) - having switched to annotations, this now fails as you would expect with lazy loading errors as the session is not open in my controller layer.
Below is the config I have been using - can any one explain which part of this is responsible for the OpenSessionInView type behavior my app was displaying previously?
App Context config file:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xmlns:cloud="http://schema.cloudfoundry.org/spring" xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
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/jee
http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://schema.cloudfoundry.org/spring
http://schema.cloudfoundry.org/spring/cloudfoundry-spring-0.7.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd">
<context:property-placeholder location="classpath*:META-INF/spring/*.properties" />
<context:spring-configured />
<context:annotation-config />
<mvc:annotation-driven />
<aop:aspectj-autoproxy proxy-target-class="true" />
<context:component-scan base-package="com.tmm.enterprise.adapter"></context:component-scan>
<context:component-scan base-package="com.tmm.enterprise.service"></context:component-scan>
<context:component-scan base-package="com.tmm.enterprise.helper"></context:component-scan>
<context:component-scan base-package="com.tmm.enterprise.util"></context:component-scan>
<context:component-scan base-package="com.tmm.enterprise.repository"></context:component-scan>
<context:component-scan base-package="com.tmm.enterprise.core.dao"></context:component-scan>
<context:component-scan base-package="com.tmm.enterprise.security.dao"></context:component-scan>
<!--Http client -->
<bean id="httpClient" class="org.apache.commons.httpclient.HttpClient">
<property name="state" ref="httpState" />
</bean>
<!--Http state -->
<bean id="httpState" factory-bean="httpStateFactory" factory-method="buildState"/>
<!--Http client -->
<bean id="httpClientFactory"
class="org.springframework.http.client.CommonsClientHttpRequestFactory">
<constructor-arg ref="httpClient" />
</bean>
<!--RestTemplate -->
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<constructor-arg ref="httpClientFactory" />
</bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
lazy-init="default" autowire="default">
<property name="driverClass" value="${database.driverClassName}" />
<property name="jdbcUrl" value="${database.url}" />
<property name="user" value="${database.username}" />
<property name="password" value="${database.password}" />
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager"
id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="applicationController" class="com.tmm.enterprise.service.ApplicationService"></bean>
<bean id="socialConfig"
class="com.tmm.enterprise.configuration.SocialConfiguration"></bean>
<bean id="cachingConfig"
class="com.tmm.enterprise.configuration.CachingConfiguration"></bean>
<tx:annotation-driven mode="aspectj"
transaction-manager="transactionManager" proxy-target-class="true" />
<bean
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
id="entityManagerFactory">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="persistenceUnit" />
</bean>
<bean id="geocoder" class="com.google.code.geocoder.Geocoder" />
<bean id="validatorFactory" class="javax.validation.Validation"
factory-method="buildDefaultValidatorFactory" />
<bean id="validator" factory-bean="validatorFactory"
factory-method="getValidator" />
</beans>
MVC Config:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<!-- The controllers are autodetected POJOs labeled with the #Controller annotation. -->
<context:component-scan base-package="com.tmm.enterprise.controller" use-default-filters="false">
<context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>
<!-- Turns on support for mapping requests to Spring MVC #Controller methods
Also registers default Formatters and Validators for use across all #Controllers -->
<mvc:annotation-driven/>
<mvc:resources mapping="/resouces/**" location="/styles, /images, /javascript, /libs" />
<!-- a higher value meaning greater in terms of sorting. -->
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" p:order="3">
<property name="alwaysUseFullPath" value="true" />
</bean>
<!-- register "global" interceptor beans to apply to all registered HandlerMappings -->
<mvc:interceptors>
<bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor"/>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" p:paramName="lang"/>
</mvc:interceptors>
<!-- selects a static view for rendering without the need for an explicit controller -->
<mvc:view-controller path="/login"/>
<!--mvc:view-controller path="/index"/-->
<mvc:view-controller path="/uncaughtException"/>
<mvc:view-controller path="/resourceNotFound"/>
<mvc:view-controller path="/dataAccessFailure"/>
<mvc:view-controller path="/jobs" view-name="jobsPage"/>
<mvc:view-controller path="/applications" view-name="jobsPage"/>
<mvc:view-controller path="/users" view-name="usersPage"/>
<mvc:view-controller path="/companies" view-name="companiesPage"/>
<mvc:view-controller path="/tos" view-name="tos"/>
<mvc:view-controller path="/about" view-name="about"/>
<mvc:view-controller path="/privacypolicy" view-name="privacyPolicy"/>
<mvc:view-controller path="/sitemap.xml" view-name="sitemap"/>
<!-- Resolves logical view names returned by Controllers to Tiles; a view
name to resolve is treated as the name of a tiles definition -->
<bean class="org.springframework.js.ajax.AjaxUrlBasedViewResolver" id="tilesViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
</bean>
<!-- Configures the Tiles layout system -->
<bean class="org.springframework.web.servlet.view.tiles2.TilesConfigurer" id="tilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/layouts/layouts.xml</value>
<!-- Scan views directory for Tiles configurations -->
<value>/WEB-INF/views/**/views.xml</value>
</list>
</property>
</bean>
<!-- Resolves localized messages*.properties and application.properties files in the application to allow for internationalization.
The messages*.properties files translate Roo generated messages which are part of the admin interface, the application.properties
resource bundle localizes all application specific messages such as entity names and menu items. -->
<bean class="org.springframework.context.support.ReloadableResourceBundleMessageSource" id="messageSource" p:basenames="WEB-INF/i18n/application" p:fallbackToSystemLocale="false"/>
<!-- store preferred language configuration in a cookie -->
<bean class="org.springframework.web.servlet.i18n.CookieLocaleResolver" id="localeResolver" p:cookieName="locale"/>
<!-- resolves localized <theme_name>.properties files in the classpath to allow for theme support -->
<bean class="org.springframework.ui.context.support.ResourceBundleThemeSource" id="themeSource"/>
<!-- store preferred theme configuration in a cookie -->
<bean class="org.springframework.web.servlet.theme.CookieThemeResolver" id="themeResolver" p:cookieName="theme" p:defaultThemeName="standard"/>
<!-- This bean resolves specific types of exceptions to corresponding logical - view names for error views.
The default behaviour of DispatcherServlet - is to propagate all exceptions to the servlet container:
this will happen - here with all other types of exceptions. -->
<bean class="com.tmm.enterprise.controller.exception.NerdExceptionHandler" p:defaultErrorView="uncaughtException">
<property name="exceptionMappings">
<props>
<prop key=".DataAccessException">dataAccessFailure</prop>
<prop key=".NoSuchRequestHandlingMethodException">resourceNotFound</prop>
<prop key=".TypeMismatchException">resourceNotFound</prop>
<prop key=".MissingServletRequestParameterException">resourceNotFound</prop>
</props>
</property>
</bean>
<!-- Controllers -->
<bean id="connectController" class="com.tmm.enterprise.controller.ConnectController"></bean>
<!-- allows for integration of file upload functionality -->
<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver"/>
<bean id="ajaxViewResolver"
class="com.tmm.enterprise.views.AjaxViewResolver">
<property name="ajaxView">
<bean class="com.tmm.enterprise.views.AjaxView" />
</property>
<property name="ajaxPrefix" value="ajax_"></property>
</bean>
<bean id="editableViewResolver"
class="com.tmm.enterprise.views.EditableViewResolver">
<property name="editableView">
<bean class="com.tmm.enterprise.views.EditableView" />
</property>
<property name="editablePrefix" value="editable_"></property>
</bean>
</beans>
The OpenSessionInView(Hibernate)/OpenEntityManagerInView(JPA) behaviour is often part of a filter defined in web.xml, but can also be done using an interceptor, as described in this answer. You can use the OpenEntityManagerInViewInterceptor for JPA.
<mvc:interceptors>
<bean class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
</mvc:interceptors>