#Transaction at Service layer not working on DAO layer in spring - spring

I am using #Transactional (org.springframework.transaction.annotation) at the service method from where I call the DAO layer to fetch data from DB.
However, I am getting following error
org.hibernate.HibernateException: No Session found for current thread
on
sessionFactory.getCurrentSession()
I have added package scanning to different files as suggested by other posts.Still unable to get the error.
Please help.Thanks a million in advance.
Following are the files I have used.
applicationContext.xml
<mvc:annotation-driven />
<context:annotation-config/>
<context:component-scan base-package="com.BASE_PCKG"></context:component-scan>
spring-servlet.xml
<mvc:annotation-driven />
<context:component-scan base-package="com.BASE_PCKG.SUB_PCKG.web"></context:component-scan>
Web.xml
...
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/applicationContext.xml</param-value>
</context-param>
....
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/spring-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Also I have configured the transaction manager in applicationContext file as :
<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager" primary="true">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<tx:annotation-driven transaction-manager="txManager"/>

Add #Transactional on daoImpl class and Add transaction manager in configuration file:
<tx:annotation-driven/>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>

Calling the method via proxy would help and fix the issue.
Calling the same method from same class would not help transaction work.

Related

Java config in Spring with AOP

This question is about Java config in Spring. Is it possible to replace the following declaration in Java code.
<servlet>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/secure-app-context.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Where secure-app-context.xml
<beans xmlns="http://www.springframework.org/schema/beans"
...
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
<aop:aspectj-autoproxy />
<mvc:annotation-driven>
<mvc:message-converters register-defaults="false">
<bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter" />
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
</mvc:message-converters>
</mvc:annotation-driven>
<context:component-scan base-package="com.abc.secure.service" />
<bean id="securityAspect" class="com.abc.secure.service.Secure" />
</beans>
You can very well do it by using WebApplicationInitializer(you dont need web.xml in this case)
Please see the post below:
How to configure Spring MVC with pure Java-based configuration?

Not Rolling Back Spring Transaction From ZK

I am facing a problem while calling the service method written in Spring Sevice that is injected in MVVM in that method I am saving one object and after that doing some other value fatching method call that throw exception and I want that while throwing that exception my Transaction rollback my service method part are as under CeilingServiceIMPL:
CeilingSheet ceilingSheet = new CeilingSheet();
ceilingSheet.setFiscalYear(fiscalYear);
ceilingSheet.setStatus(ECeilingSheetStatus.NEW);
ceilingSheet = saveCeilingSheet(ceilingSheet).getResult();
CeilingCategory ceilingCategory1 = null;
try {
ceilingCategory1 = categoryQueryService.findCeilingCategoryByCode(
"01").getResult();
} catch (ObjectNotFoundException ex) {
throw new RequestException(1234, ceilingCategory1);
}
if RequestException throws , I am expecting that my record that I saved before also rollback. I have making the service Transaction by annotating as
#Transactional(rollbackFor = RequestException.class)
The bean is injected with
#WireVariable(ICeilingSheetService.NAME) private ICeilingSheetService ceilingSheetService;
When I tried this method to call from junit test case it rolling back fine , but when I integrate it with ZK zul page and View Model by autowired services it stop rolling back and even if my code throws RequestException my CeilingSheet are persisting.
My ZK web.xml is
<!-- Spring can be easily integrated into any Java-based web framework.
All you need to do is to declare the ContextLoaderListener in your web.xml
and use a contextConfigLocation <context-param> to set which context files
to load. If you don't specify the contextConfigLocation context parameter,
the ContextLoaderListener will look for a /WEB-INF/applicationContext.xml
file to load. Once the context files are loaded, Spring creates a WebApplicationContext
object based on the bean definitions and puts it into the ServletContext. -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/application-context.xml
</param-value>
</context-param>
<!-- LOGGER -->
<context-param>
<param-name>log4j-config-location</param-name>
<param-value>WEB-INF/log4j.properties</param-value>
</context-param>
<!-- Loads the Spring web application context -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- end of spring configuration -->
<description><![CDATA[My ZK Application]]></description>
<display-name>IFMIS User Interface</display-name>
<!-- //// -->
<!-- ZK -->
<listener>
<description>ZK listener for session cleanup</description>
<listener-class>org.zkoss.zk.ui.http.HttpSessionListener</listener-class>
</listener>
<servlet>
<description>ZK loader for ZUML pages</description>
<servlet-name>zkLoader</servlet-name>
<servlet-class>org.zkoss.zk.ui.http.DHtmlLayoutServlet</servlet-class>
<!-- Must. Specifies URI of the update engine (DHtmlUpdateServlet). It
must be the same as <url-pattern> for the update engine. -->
<init-param>
<param-name>update-uri</param-name>
<param-value>/zkau</param-value>
</init-param>
<!-- Optional. Specifies whether to compress the output of the ZK loader.
It speeds up the transmission over slow Internet. However, if you configure
a filter to post-processing the output, you might have to disable it. Default:
true <init-param> <param-name>compress</param-name> <param-value>true</param-value>
</init-param> -->
<!-- [Optional] Specifies the default log level: OFF, ERROR, WARNING, INFO,
DEBUG and FINER. If not specified, the system default is used. <init-param>
<param-name>log-level</param-name> <param-value>OFF</param-value> </init-param> -->
<load-on-startup>1</load-on-startup><!-- Must -->
</servlet>
<servlet-mapping>
<servlet-name>zkLoader</servlet-name>
<url-pattern>*.zul</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>zkLoader</servlet-name>
<url-pattern>*.zhtml</url-pattern>
</servlet-mapping>
<!-- [Optional] Uncomment it if you want to use richlets. <servlet-mapping>
<servlet-name>zkLoader</servlet-name> <url-pattern>/zk/*</url-pattern> </servlet-mapping> -->
<servlet>
<description>The asynchronous update engine for ZK</description>
<servlet-name>auEngine</servlet-name>
<servlet-class>org.zkoss.zk.au.http.DHtmlUpdateServlet</servlet-class>
<!-- [Optional] Specifies whether to compress the output of the ZK loader.
It speeds up the transmission over slow Internet. However, if your server
will do the compression, you might have to disable it. Default: true <init-param>
<param-name>compress</param-name> <param-value>true</param-value> </init-param> -->
<!-- [Optional] Specifies the AU extension for particular prefix. <init-param>
<param-name>extension0</param-name> <param-value>/upload=com.my.MyUploader</param-value>
</init-param> -->
</servlet>
<servlet-mapping>
<servlet-name>auEngine</servlet-name>
<url-pattern>/zkau/*</url-pattern>
</servlet-mapping>
My application-context.xml
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>/WEB-INF/database.properties</value>
<value>/WEB-INF/msg-database.properties</value>
</list>
</property>
</bean>
<tx:annotation-driven />
<context:annotation-config />
<context:component-scan base-package="my.service" />
<import resource="hibernate-context.xml" />
My hibernat-context.xml
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass">
<value>${jdbc.driverClassName}</value>
</property>
<property name="jdbcUrl">
<value>${jdbc.url}</value>
</property>
<property name="user">
<value>${jdbc.username}</value>
</property>
<property name="password">
<value>${jdbc.password}</value>
</property>
<property name="maxPoolSize" value="${jdbc.maxPoolSize}" />
<property name="minPoolSize" value="${jdbc.minPoolSize}" />
<property name="maxStatements" value="${jdbc.maxStatements}" />
<property name="testConnectionOnCheckout" value="${jdbc.testConnection}" />
</bean>
<!-- bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"> <value>${driverClassName}</value> </property>
<property name="url"> <value>${url}</value> </property> <property name="username">
<value>${username}</value> </property> <property name="password"> <value>${password}</value>
</property> </bean -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan">
<list>
<value>my.domain.class</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
<prop key="jadira.usertype.autoRegisterUserTypes">${jadira.usertype}</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="persistenceExceptionTranslationPostProcessor"
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
Please advice ...
The first step in such cases is always to enable logging at level DEBUG for org.springframework.orm.hibernate4.HibernateTransactionManager. That will show you what Spring is doing and why.
For example, it will show you when it detects an exception and when it does a rollback or a commit. You can also set breakpoints in this code to see what is going on. It's pretty straightforward.
Knowing a bit about ZK, my guess is that you have new CeilingServiceIMPL() somewhere in the ZK code because you couldn't figure out how to inject Spring beans into a controller. This effectively renders all #Transactional useless.
You must get the bean from spring. Check out http://www.zkoss.org/product/zkspring and the documentation at Using Spring Variable Resolver how to wire beans with ZK.
I found the solution :
Reason : In My application we have the requirement to show the User messages based on the number thrown by the exception , for this we have a separate message-hibernate-context.xml file with seperate
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="messageSessionFactory" />
</bean>
and one is already with hibernate-context.xml
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
and the above both xml file called from my application-context.xml as
<import resource="hibernate-context.xml" />
<import resource="message-hibernate-context.xml" />
So after code thrown exception based on key thrown , my user-message bean trying to load separate Transaction Manager and old transaction committed and new Hibernate session starts that was going to rollback and since this is new Transaction so It does not found anything to rollback.
Once I removed other Transaction Manager it start working .
Thanks All for support...

Bean Context in Spring

The application works perfectly with the following config files:
My Web.XML is as follows
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/spring/mvc-dispatcher-servlet.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/classes/spring/spring-context.xml,
/WEB-INF/classes/spring/spring-security.xml
</param-value>
</context-param>
<!-- Spring Security -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
My mvc-dispatcher-servlet
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<context:component-scan base-package="biz.canisrigel.slapMe" />
<!-- enable autowire -->
<context:annotation-config />
My spring-context.xml is
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<context:component-scan base-package="biz.canisrigel.slapMe" />
<!-- enable autowire -->
<context:annotation-config />
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/slapMe" />
<property name="username" value="root" />
<property name="password" value="adminadmin" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="typeAliasesPackage" value="biz.canisrigel.slapMe.bean" />
</bean>
<!-- scan for mappers and let them be autowired -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="biz.canisrigel.slapMe.mapper" />
</bean>
I couldn't run spring security properly cause earlier spring-context.xml was the xml config file for dispatcher servlet for MVC. So I moved spring-context to contextConfigLocation. But then I had to provide something to dispatcher servlet.
My problem is that mvc-dispatcher-servlet.xml and spring-context is having same data. If I remove mvc-dispatcher its an error. If I don't place the contents of mvc-dispatcher in spring context then also error occurs.
Where am I going wrong in my understanding of concepts.
A few things:
Your web.xml looks correct
The InternalResourceViewResolver should only exist in your mvc-dispatcher-servlet.xml since it is directly related to MVC -- remove it from your spring-context.xml
You can have context:component-scan in both configuration files, but they should be scanning different packages. The one in your servlet xml will generally be component scanning your controller packages (and anything else directly related to MVC), and the one in your parent spring context xml will generally be scanning your services, DAOs, etc. In general, your component scan packages should be very specific; you should never point it towards the base package of your entire application!
You can remove context:annotation-config -- it is redundant if you have context:component-scan
Your MVC context should have only configuration related to MVC which generally includes ViewResolvers, FileUpload, PropertyFiles, Message/Theme Resolvers etc. Your applicationContext will have beans related to DAO, Service and other utils. The security file should have security configuration. To understand better and to know good/recommended practices, check out the spring greehouse code.

configure BasicDataSource as bean in web.xml

I'm trying to configure org.apache.commons.dbcp.BasicDataSource as bean in web.xml under a tomcat project using tomcat 6. (it's red5 with tomcat, we can ignore that the main server is actually red5 because i actually run jsp files under port 5080 and don't connect to the red5 directly using RTMP protocol)
my web.xml:
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/ j2ee/web-app_2_4.xsd"
version="2.4">
<display-name>gamesisland-login-red5</display-name>
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>/[myapp]</param-value>
</context-param>
<listener>
<listener-class>org.red5.logging.ContextLoggingListener</listener-class>
</listener>
<filter>
<filter-name>LoggerContextFilter</filter-name>
<filter-class>org.red5.logging.LoggerContextFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LoggerContextFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>rtmpt</servlet-name>
<servlet-class>org.red5.server.net.rtmpt.RTMPTServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>rtmpt</servlet-name>
<url-pattern>/fcs/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>rtmpt</servlet-name>
<url-pattern>/open/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>rtmpt</servlet-name>
<url-pattern>/close/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>rtmpt</servlet-name>
<url-pattern>/send/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>rtmpt</servlet-name>
<url-pattern>/idle/*</url-pattern>
</servlet-mapping>
<security-constraint>
<web-resource-collection>
<web-resource-name>Forbidden</web-resource-name>
<url-pattern>/streams/*</url-pattern>
</web-resource-collection>
<auth-constraint/>
</security-constraint>
<bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/red5-web.properties" />
</bean>
<bean id="idDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName"><value>${db.driver}</value></property>
<property name="url"><value>${db.url}</value></property>
<property name="username"><value>${db.username}</value></property>
<property name="password"><value>${db.password}</value></property>
<property name="poolPreparedStatements"><value>true</value></property>
<property name="maxActive"><value>10</value></property>
<property name="maxIdle"><value>10</value></property>
</bean>
</web-app>
my red5-web.properties:
webapp.contextPath=/myapp
webapp.virtualHosts=*
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://127.0.0.1:3306/dbname
db.username=user
db.password=pass
does tomcat automatically searches for WEB-INF/web.xml for configuration?
why don't I get any relevant errors to the creation of idDataSource ?
I really don't have any clue how to pinpoint or debug the problem.
any assistance would be greatly appreciated.
thank you!
kfir
I don't know nothing about Red5, but it seems like you trying to put Spring beans directly inside web.xml, which is wrong. You are suppose to create a separate Spring configuration file that will be picked up by Springs' ContextLoaderListener. First, add this to your web.xml:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Than create applicationContext.xml file under /WEB-INF:
<?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">
<bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/red5-web.properties" />
</bean>
<bean id="idDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName"><value>${db.driver}</value></property>
<property name="url"><value>${db.url}</value></property>
<property name="username"><value>${db.username}</value></property>
<property name="password"><value>${db.password}</value></property>
<property name="poolPreparedStatements"><value>true</value></property>
<property name="maxActive"><value>10</value></property>
<property name="maxIdle"><value>10</value></property>
</bean>
</beans>
Of course all the <bean/> declarations should go away from web.xml.
Second thought: looking at this document it seems like Red5 uses a file named red5-web.xml, please go through this documentation carefully.

Spring, Need to use a a bean declared in a ApplicationContextFactory servlet, in a DispatcherServlet

i have a web.xml with these 2 servlet:
<servlet>
<servlet-name>ApplicationContextFactory</servlet-name>
<servlet-class>com.bamboo.common.factory.ApplicationContextFactory</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
AND
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
I need to use these bean declared on the ApplicationContextFactory:
<bean id="**catalogFacadeTarget**" class="com.bamboo.catW3.business.impl.CatalogFacadeImpl">
<property name="categoryDAO"><ref local="categoryDAOTarget"/></property>
<property name="containerDAO"><ref local="containerDAOTarget"/></property>
<property name="productDAO"><ref local="productDAOTarget"/></property>
<property name="productOptionDAO"><ref local="productOptionDAOTarget"/></property>
<property name="productStatusDAO"><ref local="productStatusDAOTarget"/></property>
<property name="userDAO"><ref local="userDAOTarget"/></property>
</bean>
in the dispatcher-servlet like this:
<bean name="welcome"
class="com.bamboo.catW3.business.impl.Welcome">
<property name="successView">
<value>welcome</value>
</property>
<property name="catalogFacadeImpl"><ref local="**categoryDAOTarget**"/> </property>
</bean>
Is it posible some how? Thank you!
You can't share contexts between servlets.
If you need to share beans, then you need to move the shared beans out of the ApplicationContextFactory servlet's context and into the root webapp context, using a ContextLoaderListener declared in web.xml. Both servlets will then be able to use the beans defined in that root context.
(I'd give you a link, but springsource.org seems be down at the moment).

Resources