Request scoped bean inside a Singleton bean - spring

I have a web app where i define 2 bean
1 with a singleton scope and one with a request scope.
I need the request scoped bean inside the singleton bean.
So i ended up with this
<bean id="routingDataSource" class="org.ai2l.ifsr.service.multiTenants.RoutingDataSource" scope="request">
<aop:scoped-proxy/>
<property name="targetDataSources" value="#{tenantSpecificDependencyFactory.tenantIdToDataSource}"/>
<!-- <property name="defaultTargetDataSource" ref="parentDataSource"/> -->
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="ifsrPU"/>
<property name="dataSource" ref="routingDataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="${hibernate.dialect}"/>
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.ejb.naming_strategy">
org.hibernate.cfg.ImprovedNamingStrategy
</prop>
</props>
</property>
</bean>
As you will notice i've use the <aop:scoped-proxy/>but it isn't working.
I've also tryed the
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
inside my web.xml. But none of this is working.
I still get this error
Caused by: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
Does any one know why this happens??

Related

Hibernate Envers not Finding JPA Transaction:

I've been trying to wrap my head around this issue all day.
Currently our project has setup JPATransactionManager through a Spring Application Context to take care of our various session transactions with the use of #Transactional on all services that take care of persistence and deletions (DAO usage).
Changing over from Hibernate 3 to 5, we wanted to remove our use of a custom audit interceptor and move onto using Hibernate Envers. I have annotated all my classes properly and have the tables being created, but once it actually gets to a point of insertion, the listener throws an error in which it can't find the current transaction given by JPA:
org.hibernate.envers.exception.AuditException: Unable to create revision because of non-active transaction
at org.hibernate.envers.event.spi.BaseEnversEventListener.checkIfTransactionInProgress(BaseEnversEventListener.java:132)
at org.hibernate.envers.event.spi.EnversPostInsertEventListenerImpl.onPostInsert(EnversPostInsertEventListenerImpl.java:34)
at org.hibernate.action.internal.EntityIdentityInsertAction.postInsert(EntityIdentityInsertAction.java:156)
at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:102)
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:597)
at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:232)
at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:213)
at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:256)
at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:318)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:275)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:182)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:113)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:192)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:177)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:97)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:651)
at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:643)
at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:638)
Looking inside the code, it seems that it's basing the transaction status off it's default value of INACTIVE meaning that it's not hooking into the transaction properly. I know that Hibernate Envers also automatically pushes the listeners into hibernate with recent versions so I don't know if this may also be a source of the issue.
I know that its been documented to work with HibernateTransactionManager but we wish to step away from using that in favor of hooking up our transactions and sessions solely via Spring making things easier so it may also be the need of finding an alternative to envers. Does anyone have any advice or solutions to this problem? Or also hit this issue?
ApplicationContext.xml
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="dataSource" ref=“dataSource" />
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="net.sourceforge.jtds.jdbcx.JtdsDataSource" />
<property name="url" value="jdbc:jtds:sqlserver://.." />
<property name="username" value=“..." />
<property name="password" value=“..." />
</bean>
<bean id="hibernateProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location">
<value>classpath:hibernate.properties</value>
</property>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
<property name="hibernateProperties">
<ref bean="hibernateProperties" />
</property>
</bean>
<bean id="txProxyTemplate" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<property name="transactionAttributes">
<props>
<prop key="find*">PROPAGATION_SUPPORTS,readOnly
</prop>
<prop key="load*">PROPAGATION_SUPPORTS,readOnly
</prop>
<prop key="make*">PROPAGATION_REQUIRED</prop>
<prop key="add*">PROPAGATION_REQUIRED</prop>
<prop key="refresh">PROPAGATION_SUPPORTS</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_SUPPORTS,readOnly
</prop>
</props>
</property>
</bean>
<bean id="PROPAGATION_REQUIRED" class="org.apache.camel.spring.spi.SpringTransactionPolicy">
<property name="transactionManager" ref="transactionManager" />
</bean>
hibernate.properties
#hibernate.hbm2ddl.auto=update
hibernate.show_sql=true
hibernate.connection.datasource=java\:comp/env/datasource
#hibernate.connection.provider_class=org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl
hibernate.connection.provider_class=org.hibernate.connection.DatasourceConnectionProvider
hibernate.cache.use_second_level_cache=true
hibernate.cache.use_query_cache=true
#hibernate.generate_statistics=true
hibernate.cache.use_structured_entries=true
hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider
hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory
hibernate.id.new_generator_mappings=false
hibernate.dialect=org.hibernate.dialect.SQLServer2008Dialect
hibernate.listeners.envers.autoRegister=false
org.hibernate.envers.track_entities_changed_in_revision=false
org.hibernate.envers.audit_table_prefix=AUD_
org.hibernate.envers.audit_table_suffix=
My DAOs are hooked up using the txProxyTemplate like so
<bean id="objectDAO" parent="txProxyTemplate">
<property name="target">
<bean
class="path.to.objectDAOImpl">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
</property>
</bean>
All my services that use the various DAOs are simply hooked up using the #Transactional annotation where we want to have transactions. I've been able to see through trace that my transactions are succeeding in completing and rolling back as well when there are errors. Once I added envers into the mix, the auditing can't find the transaction to join. There must be something I'm missing but I'm not sure what it is.
I don't believe you need to define a txProxyTemplate bean nor a SpringTransactionPolicy from my experience. This functionality has since been superseded with the <tx:/> tags and the use of the #Transactional annotation.
You just need to make sure a JpaTransactionManager has been created and associated as the transactionManager associated with the <tx:annotation-driven/> tag.

Why is MultiActionController deprecated in Spring 4.3?

In most cases, I'm able to replace MultiActionController with an annotated controller just fine. But I have a use-case where I need to map different URLs to DIFFERENT instances of the same controller class, each wired with a different implementation of the same interface. (It's for various find-as-you-type APIs.) I've been using SimpleUrlHandlerMapping for this. Is there any way to do this with an annotated controller? Or do I now have to make separate controller classes for each API? Here's my config with only two MultiActionControllers shown, although I have more:
<bean name="regionAutocompleteController" class="...ajax.autocomplete.AutocompleteController" autowire="byName">
<property name="finder" ref="regionFinder"/>
</bean>
<bean name="blockAutocompleteController" class="...ajax.autocomplete.AutocompleteController" autowire="byName">
<property name="finder" ref="blockFinder"/>
</bean>
<bean id="atlasAjaxControllerMappings"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="order" value="4" />
<property name="mappings">
<props>
<prop key="/findBlock/*">blockAutocompleteController</prop>
<prop key="/findRegion/*">regionAutocompleteController</prop>
</props>
</property>
</bean>

Spring IntTest is getting "Failed to grow the connection pool" from Atomikos

I have a Spring application that normally runs fine in WebLogic.
I have a set of integration tests that use the Atomikos "Transaction Essentials" framework to provide the standalone transaction manager. I had this working, but I'm now seeing a new problem, but I don't know what I might have changed that would make this happen.
I'm seeing a stack trace beginning like this:
org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is com.atomikos.jdbc.AtomikosSQLException: Failed to grow the connection pool
at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:80)
Here are the relevant bean definitions:
<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close">
<!-- when close is called, should we force transactions to terminate or not? -->
<property name="forceShutdown">
<value>true</value>
</property>
</bean>
<!-- Also use Atomikos UserTransactionImp, needed to configure Spring -->
<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout">
<value>300</value>
</property>
</bean>
<!-- Configure the Spring framework to use JTA transactions from Atomikos -->
<bean id="catalogTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager">
<ref bean="atomikosTransactionManager" />
</property>
<property name="userTransaction">
<ref bean="atomikosUserTransaction" />
</property>
</bean>
I also have several like this:
<bean id="appConfigDataSource"
class="com.atomikos.jdbc.AtomikosDataSourceBean"
p:uniqueResourceName="appConfigDataSource"
p:xaDataSourceClassName="oracle.jdbc.xa.client.OracleXADataSource"
p:poolSize="5">
<property name="xaProperties">
<props>
<prop key="user">${ds.appconfig.userName}</prop>
<prop key="password">${ds.appconfig.password}</prop>
<prop key="URL">${ds.appconfig.url}</prop>
</props>
</property>
</bean>
I tried changing the "5" to "50". This makes it run longer, but it still fails with the same error. There's no way that it would even need 5 or even 50 connections. I have a strong feeling that if I changed it to a larger number, it would run even longer, and still fail with the same error.
What might I be missing?
Never mind. It was a simple problem. I forgot that the hostname of my test database changed a while ago, and I forgot to change the property value.

NoSuchMethodException thrown by AnnotationValidationInterceptor when executing an action

Details of jars used:
Struts2 2.2.1
Spring 3.0.5.RELEASE
Hibernate 3.6.0.FINAL
I am experiencing a strange issue when trying to execute an action mapped as follows:
<action name="supplierSearch" class="supplierSearchAction">
<result>/pages/suppliersearch.jsp</result>
</action>
<action name="searchForSupplier" class="supplierSearchAction" method="doSearch">
<result>/pages/suppliersearch.jsp</result>
</action>
the first action sends the user to a search page, they enter a search string and then the second action is invoked when the post the form.
The action in spring config is as follows:
<bean id="supplierSearchAction"
class="com.blah.SupplierSearchAction"
scope="prototype">
<property name="searchService" ref="supplierSearchService"></property>
</bean>
the search service uses hibernate search and is defined as follows:
<bean id="supplierSearchService"
class="com.devcentre.yubi.application.service.SupplierSearchServiceImpl">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
I am using spring aop to configure my transaction boundaries and the persistence config is as follows:
<tx:annotation-driven transaction-manager="txManager" />
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
// annotated classes here
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect"> org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">upgrade</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.provider_class">
net.sf.ehcache.hibernate.SingletonEhCacheProvider</prop>
<prop key="hibernate.search.default.directory_provider">org.hibernate.search.store.FSDirectoryProvider
</prop>
<prop key="hibernate.search.default.indexBase">/lucene/indexes</prop>
<prop key="hibernate.search.default.batch.merge_factor">10</prop>
<prop key="hibernate.search.default.batch.max_buffered_docs">10</prop>
</props>
</property>
</bean>
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
Spring is configured as follows in my web.xml:
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/src/spring-config.xml
/WEB-INF/src/persistence-config.xml
</param-value>
</context-param>
On the search JSP page I have a form which submits the search string to the action which should invoke the doSearch method. However, when I submit the search I get an exception as follows (because devmode is enabled):
Struts has detected an unhandled exception:
Messages: $Proxy28.doSearch()
File: java/lang/Class.java Line
number: 1,605
and then the stack trace:
java.lang.NoSuchMethodException: $Proxy28.addComponent()
java.lang.Class.getMethod(Class.java:1605)
org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.getActionMethod(AnnotationValidationInterceptor.java:75)
org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:47)
com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
This is very odd because there is a method on the action class with the signature:
public String doSearch()
Can anyone help shed light on why the ActionProxy doesn't have the expected method?
Thanks,
Alex
java.lang.NoSuchMethodException: $Proxy25.doSearch()
Notice that the name of your action class is $Proxy25. It appears that something is creating a dynamic proxy to your action class. This is usually seen when using Aspect Oriented Programming (AOP) method interceptors on methods of a class — e.g., for things like transactions.
For example, I use Google Guice from time-to-time and when using AOP method interceptors on methods of a class, an action called LoginAction would have a dynamic proxy created called LoginAction$$EnhancerByGuice$$someAdditionalCharacters. While this dynamic proxy subclasses the methods of the class, it does not inherit annotations. My guess is that the same thing is happening here.
I don't use Spring, so I am not familiar with what libraries it uses to create dynamic proxies.
Update
If you remove the AOP annotations from your action class, then it should work as expected. Your action class can delegate to a service-layer class to handle persisting to the database (you can put the #Transactional annotation on that class's method(s)).
The struts2 spring & annotation integration seems to have its catches still...
the first call to getMethod from the AnnotationValidationInterceptor can be avoided using exclude parameters.
<interceptor-ref name="validation">
<param name="excludeMethods">YOURMETHODHERE</param>
</interceptor-ref>
however, this simply postpones the problem until the actual method is called by the DefaultActionInvocation ending up at the same code location (getMethod Class#1597) which fails with the given method name on the proxy.
WORKAROUND
The only functional workaround I found was to use the standard execute() method for the action and split the actions up into different classes.
Hope that helps.

Spring SimpleUrlHandlerMapping not allowing routing for any html page

I'm trying to implement a file upload in my Spring application based on the Spring documentation. However, when I add the SimpleUrlHandlerMapping reference, I can't even route to my login page.
In my web.xml, I have all .htm files mapped to my servlet:
<servlet-mapping>
<servlet-name>myapp</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
then, in myapp-servlet.xml, I have this:
<bean name="/login.htm" class="com.example.web.LoginFormController">
<property name="sessionForm" value="true" />
<property name="commandName" value="loginCommand" />
<property name="commandClass" value="com.example.command.LoginCommand" />
<property name="authenticationService" ref="authenticationService" />
<property name="loginDataAccess" ref="loginDAO" />
<property name="validator" ref="loginValidator" />
<property name="formView" value="login" />
<property name="successView" value="hello.htm" />
</bean>
This allows me to go to the login page and login. However, when I add the following based on the documentation, I get this error: No mapping found for HTTP request with URI [/myapp/login.htm] in DispatcherServlet with name 'myapp'
These are the lines I added to the myapp-servlet.xml file:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<value>/upload.form=fileUploadController</value>
</property>
</bean>
<bean id="fileUploadController" class="com.example.web.FileUploadController">
<property name="commandClass" value="com.example.domain.FileUploadBean" />
<property name="formView" value="fileuploadform" />
<property name="successView" value="hello.htm" />
</bean>
If I take out the urlMapping section, I can navigate to the upload page, but then I get an IllegalStateException. How do I have Spring route the htm files normally and allow me to upload a file? Shouldn't the urlMapping only matter when the upload.form is called?
Update
Per SKaffman's answer, I updated the myapp-servlet.xml to look like this:
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<value>
/upload.form=fileUploadController
/upload.htm=fileUploadController
/login.htm=loginController
</value>
</property>
</bean>
This allows me to navigate to the upload page, but when I click on the submit button, I get a 404 for upload.form saying "(/myapp/upload.form) is not available." If I take the upload.htm out of the mapping, I can't navigate to that page. I don't know what mapping to use for both the page and the upload. The upload page has this action defined:
<form method="post" action="upload.form" enctype="multipart/form-data">
By default, Spring registers multiple HandlerMapping beans automatically, including a BeanNameUrlHandlerMapping. This handler allows you to use things like <bean name="/login.htm"> without any additional configuration.
However, as soon as you add an explicit handler mapping bean, like your SimpleUrlHandlerMapping, then the default ones are no longer registered, and your login controller will not longer be mapped.
The simplest solution for you is probably to add your login controller to the SimpleUrlMappingHandler:
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<value>/login.htm=loginController</value>
<value>/upload.form=fileUploadController</value>
</property>
</bean>
<bean id=loginController" class="com.example.web.LoginFormController">
...
</bean>

Resources