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...
Related
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.
Excuse me if I use incorrect terminology, I'm a bit new to this. I've created a web service using Sun's JAX-WS RI "Provider" implementation. We send this service plain XML, and it responds in plain XML. I've tried to move this into Spring so the services are accessible via Spring context, but now it's looking for a SOAP envelope, which we are not using. How do I tell it I am not using SOAP?
My web.xml looks like this:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<display-name>MyServiceImpl</display-name>
<servlet-name>MyServiceImpl</servlet-name>
<servlet-class>com.sun.xml.ws.transport.http.servlet.WSSpringServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>MyServiceImpl</servlet-name>
<url-pattern>/myServiceUrl</url-pattern>
</servlet-mapping>
And here's my applicationContext.xml:
<!-- this bean implements web service methods -->
<bean id="myService" class="com.acme.MyServiceImpl" />
<bean class="com.sun.xml.ws.transport.http.servlet.SpringBinding">
<property name="url" value="/myServiceUrl" />
<property name="service">
<bean class="org.jvnet.jax_ws_commons.spring.SpringService">
<property name="bean">
<ref local="myService" />
</property>
<property name="impl" value="com.acme.MyServiceImpl" />
</bean>
</property>
</bean>
My service class looks something like this:
#javax.xml.ws.WebServiceProvider
#javax.xml.ws.ServiceMode(value=javax.xml.ws.Service.Mode.MESSAGE)
public class MyServiceImpl implements Provider<Source> {
#Override
public Source invoke(Source source) {
... // unmarshal the source object using JAXB, do work, marshall a response back
}
The error message I receive upon sending the service my basic XML is:
<?xml version="1.0" encoding="UTF-8"?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><S:Fault xmlns:ns4="http://www.w3.org/2003/05/soap-envelope"><faultcode>S:Client</faultcode><faultstring>Couldn't create SOAP message due to exception: unexpected XML tag. expected: {http://schemas.xmlsoap.org/soap/envelope/}Envelope but found: {}Request</faultstring></S:Fault></S:Body></S:Envelope>
How do I rid the SOAP?
Found it; need to specify the bindingId (which was defined in the sun-jaxws.xml previously) on the web service bean:
<property name="service">
<bean class="org.jvnet.jax_ws_commons.spring.SpringService">
<property name="bean">
<ref local="myService" />
</property>
<property name="impl" value="com.acme.MyServiceImpl" />
<property name="bindingID" value="http://www.w3.org/2004/08/wsdl/http" />
</bean>
</property>
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.
I am using spring framework in my project,
Here is part of my web.xml:
<servlet>
<servlet-name>SpringMvcServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/servlet-context.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringMvcServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>httpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>httpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<error-page>
<error-code>404</error-code>
<location>/system/404.html</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/system/500.html</location>
</error-page>
And configure:
<mvc:resources mapping="/system/**" location="/WEB-INF/pages/system/" />
But I find so many error in my log, some request like this:
POST /index.php
POST /notexists.html
They were not exists in my server, so will call "/system/404.html", but the mvc:resources don't accept POST method, so it will return 500 Error.
How to fix that? or work around?
Thanks
First of all: I think you abuse the ResourceHttpRequestHandler when you try to use it for POST requests. -- And I am not sure that every thing works correct if you made this handler to handle POST requests.
<mvc:resources /> configure an instance of class org.springframework.web.servlet.resource.ResourceHttpRequestHandler. This has the super class WebContentGenerator and this super class has a property Set<String> supportedMethods.
So all what you need to do is:
<property name="supportedMethods">
<list>
<value>GET</value>
<value>HEAD</value>
<value>POST</value>
</list>
</property>
Unfortunately this requires that you configure the ResourceHttpRequestHandler by hand instead of using <mvc:resources />
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="urlMap">
<map>
<entry key="/system/**" value="myResourceHandler" />
</map>
</property>
<property name="order" value="100000" />
</bean>
<bean id="myResourceHandler" name="myResourceHandler"
class="org.springframework.web.servlet.resource.ResourceHttpRequestHandler">
<property name="locations" value="/WEB-INF/pages/system/" />
<property name="supportedMethods">
<list>
<value>GET</value>
<value>HEAD</value>
<value>POST</value>
</list>
</property>
<!-- cacheSeconds: maybe you should set it to zero because of the posts-->
</bean>
I have not proved this configuration, I have just written it down from what the ResourceBeanDefintionParser does.
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).