Mapping Controllers - spring

What is wrong?
I was wrote two controllers but don't understand what is wrong.
Don't know how to make correct for working both controller correct.
Type Exception Report
Message Servlet.init() for servlet [mvc-dispatcher] threw exception
Description The server encountered an unexpected condition that prevented it from fulfilling the request.
Exception
javax.servlet.ServletException: Servlet.init() for servlet [mvc-dispatcher] threw exception
rg.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#0': Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'bookController' bean method
public java.lang.String com.jackson.BookController.editBook(int,org.springframework.ui.Model)
to {[/edit/{id}],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}: There is already 'authorController' bean method
public java.lang.String com.jackson.AuthorController.editAuthor(int,org.springframework.ui.Model) mapped.
package com.jackson;
#Controller
public class AuthorController {
private AuthorService authorService;
#Autowired(required = true)
#Qualifier(value = "authorService")
public void setBookService(AuthorService authorService) {
this.authorService = authorService;
}
#RequestMapping
(value = "authors", method = RequestMethod.GET)
public String listAuthors(Model model){
model.addAttribute("author", new Author());
model.addAttribute("listAuthors", this.authorService.list());
return "authors";
}
#RequestMapping
(value = "authors/add", method = RequestMethod.POST)
public String addAuthor(#ModelAttribute("author") Author author){
if(author.getId() == 0){
this.authorService.addAuthor(author);
}else {
this.authorService.updateAuthor(author);
}
return "redirect:/authors";
}
#RequestMapping("/remove/{id}")
public String removeAuthor(#PathVariable("id") int id){
this.authorService.removeAuthor(id);
return "redirect:/authors";
}
#RequestMapping("/edit/{id}")
public String editAuthor(#PathVariable("id") int id, Model model){
model.addAttribute("author", this.authorService.getAuthorById(id));
model.addAttribute("listBooks", this.authorService.list());
return "authors";
}
#RequestMapping("authordata/{id}")
public String authorData(#PathVariable("id") int id, Model model){
model.addAttribute("author", this.authorService.getAuthorById(id));
return "authordata";
}
}
In my opinion all code working right but still understand whats wrong
package com.jackson;
#RestController
public class BookController {
private BookService bookService;
#Autowired(required = true)
#Qualifier(value = "bookService")
public void setBookService(BookService bookService) {
this.bookService = bookService;
}
#RequestMapping(value = "books", method = RequestMethod.GET)
public String listBooks(Model model){
model.addAttribute("book", new Book());
model.addAttribute("listBooks", this.bookService.listBooks());
return "books";
}
#RequestMapping(value = "/books/add", method = RequestMethod.POST)
public String addBook(#ModelAttribute("book") Book book){
if(book.getId() == 0){
this.bookService.addBook(book);
}else {
this.bookService.updateBook(book);
}
return "redirect:/books";
}
#RequestMapping("/remove/{id}")
public String removeBook(#PathVariable("id") int id){
this.bookService.removeBook(id);
return "redirect:/books";
}
#RequestMapping("edit/{id}")
public String editBook(#PathVariable("id") int id, Model model){
model.addAttribute("book", this.bookService.getBookById(id));
model.addAttribute("listBooks", this.bookService.listBooks());
return "books";
}
#RequestMapping("bookdata/{id}")
public String bookData(#PathVariable("id") int id, Model model){
model.addAttribute("book", this.bookService.getBookById(id));
return "bookdata";
}
}
In my opinion all code working right but still understand whats wrong
mvc-dispacther-servlet.xml
<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/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.jackson"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>
// database config
<!-- Hibernate 4 SessionFactory Bean definition -->
<bean id="hibernate4AnnotatedSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="annotatedClasses">
<list>
<value>com.jackson.Book</value>
<value>com.jackson.Author</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect
</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<!--BookDao and BookService beans-->
<bean id="bookDao" class="com.jackson.BookDao">
<property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory"/>
</bean>
<bean id="bookService" class="com.jackson.BookService">
<property name="bookDao" ref="bookDao"/>
</bean>
<bean id="authorDao" class="com.jackson.AuthorDao">
<property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory"/>
</bean>
<bean id="authorService" class="com.jackson.AuthorService">
<property name="authorDao" ref="authorDao"/>
</bean>
<context:component-scan base-package="com.jackson"/>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory"/>
</bean>
<mvc:default-servlet-handler/>
<mvc:annotation-driven/>
</beans>
web.xml
<web-app version="2.4"
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">
<display-name>com.jackson.Book Manager</display-name>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>

Your controllers have conflict mapping methods. Don't declare same request mapping method on different controllers.

BookController needs to have #Controller instead of #RestController.

Related

LazyInitializationException for some of requests

This is probably a duplicate, but I am struggling with this problem for few days now. After dozens of tutorials, books, stack answers etc I am in the dead end.
This is RESTfull Spring hibernate app
How to eliminate lazyinitializationexception and problems with Session? I tried to set eager fetch in model class, but it didn't work for me, I have Transaction annotations but its still the same. I bet that it must be set somehow in Spring xml config, but have no clue how to do that.
Why ... /getAllCountries works perfectly fine, and /getCountry/id throw Session error? I see no difference between them.
Please give me a code based answer.
Controller:
#RestController
public class CountryController {
#Autowired
CountryService countryService;
#RequestMapping(value = "/getAllCountries", method = RequestMethod.GET, headers = "Accept=application/json")
public List<Country> getCountries() {
List<Country> listOfCountries = countryService.getAllCountries();
return listOfCountries;
}
#RequestMapping(value = "/getCountry/{id}", method = RequestMethod.GET, headers = "Accept=application/json")
public Country getCountryById(#PathVariable int id) {
return countryService.getCountry(id);
}
// .....
}
DAO:
#Repository
public class CountryDAO {
#Autowired
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sf) {
this.sessionFactory = sf;
}
public List<Country> getAllCountries() {
Session session = this.sessionFactory.getCurrentSession();
List<Country> countryList = session.createQuery("from Country").list();
return countryList;
}
public Country getCountry(int id) {
Session session = this.sessionFactory.getCurrentSession();
Country country = (Country) session.load(Country.class, new Integer(id));
return country;
}
// ......
}
Service:
#Service("countryService")
public class CountryService {
#Autowired
CountryDAO countryDao;
#Transactional
public List<Country> getAllCountries() {
return countryDao.getAllCountries();
}
#Transactional
public Country getCountry(int id) {
return countryDao.getCountry(id);
}
}
Entity:
#Entity
#Table(name="COUNTRY")
public class Country{
#Id
#Column(name="id")
#GeneratedValue(strategy=GenerationType.IDENTITY)
int id;
#Column(name="countryName")
String countryName;
#Column(name="population")
long population;
public Country() {
super();
}
public Country(int i, String countryName,long population) {
super();
this.id = i;
this.countryName = countryName;
this.population=population;
}
// getters and setters...
}
Spring config xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.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/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<annotation-driven />
<resources mapping="/resources/**" location="/resources/" />
<beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<beans:property name="driverClassName" value="org.postgresql.Driver" />
<beans:property name="url"
value="..." />
<beans:property name="username" value="postgres" />
<beans:property name="password" value="..." />
</beans:bean>
<!-- Hibernate 4 SessionFactory Bean definition -->
<beans:bean id="hibernate4AnnotatedSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<beans:property name="dataSource" ref="dataSource" />
<beans:property name="annotatedClasses">
<beans:list>
<beans:value>org.arpit.java2blog.model.Country</beans:value>
</beans:list>
</beans:property>
<beans:property name="hibernateProperties">
<beans:props>
<beans:prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect
</beans:prop>
<beans:prop key="hibernate.show_sql">true</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
<context:component-scan base-package="org.arpit.java2blog" />
<tx:annotation-driven transaction-manager="transactionManager"/>
<beans:bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" />
</beans:bean>
</beans:beans>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Your problem comes from the Session.load() method that doesn't return an object but a proxy of the object which is initialized at the first access of an non-identifier property.
Hibernate Documentation:
T load(Class theClass,
Serializable id)
Return the persistent instance of the given entity class with the given identifier, assuming that the
instance exists. This method might return a proxied instance that is
initialized on-demand, when a non-identifier method is accessed.
And for you it means it's initialized when Spring will try to marshall the object, which is when the Session is close.
To fix it you can either add #org.hibernate.annotations.Proxy(lazy = false) on the class level, use Session.get() instead of Session.load() in the dao to get a fully loaded object (depending on the lazy strategy on members).
Or manually trigger the lazy loading when the Session is still like by calling any member of the object (like calling List.size() on a collection to force the loading).

in memory db hibernate spring

I have been trying to integrate between spring and memorydb in junit tests but i keep getting the exception.
org.hibernate.exception.SQLGrammarException: user lacks privilege or object not found: ORDERTABLE
testcontext.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:tx="http://www.springframework.org/schema/tx" 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/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<jdbc:embedded-database id="testDataSource" type="HSQL">
</jdbc:embedded-database>
<context:annotation-config />
<tx:annotation-driven transaction-manager="transactionManager" />
<context:component-scan base-package="com.bidblaze.service.test"/>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
</bean>
<!-- Hibernate session factory -->
<bean id="SessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" >
<property name="dataSource">
<ref bean="testDataSource" />
</property>
<property name="packagesToScan" value= MYPACKAGE />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.hbm2ddl.auto">create-drop</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.connection.url">jdbc:hsqldb:mem:projectdb</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="SessionFactory" ref="SessionFactory" />
</bean>
with defining the other beans
My service class:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "/testContext.xml" })
#Transactional
public class TestService {
//ApplicationContext context = new ClassPathXmlApplicationContext(
//"spring-config.xml");
#Autowired
PaypalPaymentsService PaypalService;
#Autowired
private OrderDAO orderDAO ;
#Autowired
private SessionFactory sessionFactory;
private Session extSession;
#Before
#Transactional
public void openSessionExternal() {
extSession = sessionFactory.getCurrentSession();
}
#Test
#Transactional
public void shouldHaveASessionFactory() {
assertNotNull(sessionFactory);
}
#Test
#Transactional
public void shouldHaveASession() {
assertNotNull(extSession);
}
#Test
public void saveOrder(){
Order order = new Order();
order.setOrderId("1");
order.setRecieverEmail("enduser_biz#gmail.com");
order.setAmount((double)2.00);
extSession.save(order);
Order testOrder = (Order) extSession.createQuery("from OrderTable where orderId = ?").setParameter(0, "1").list().get(0);
assertNotNull(testOrder);
}
the Order class :
#Entity
#Table(name="OrderTable")
public class Order {
#Id
#GeneratedValue
#Column(name="orderId")
String orderId;
PS: my Order class has other properties that refer to other classes but i didnt map them neither they are entities as well.
any suggestions
Following this answer, and knowing your XML mapping, I'd suggest the following annotation changes to orderId:
#Id
#GeneratedValue
#Column(name="orderId", columnDefintion="BIGINT")
String orderId;
That's assuming that #GeneratedValue equates to a "native" generator as in your XML. You might need to use an #GenericGenerator instead with a strategy=native instead more like this:
#Id
#GeneratedValue(generator="my-native-generator")
#GenericGenerator(name="my-native-generator", strategy = "native")
#Column(name="orderId", columnDefintion="BIGINT")
String orderId;

Initialization of collection throws LazyInitializationException

I have a problem with the access to a collection from JSP file. Application is based on MVC Spring framework. I put OpenSessionInViewFilter filter to my web.xml. When I want to access to URL with mentioned file, it throws me
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.app.cloud.hibernate.Product.availabilities, no session or session was closed
I use domain driven design in my app. When I changed fetch type in class Product from FetchType.LAZY to FetchType.EAGER, it worked.
stacktrace
SEVERE: Servlet.service() for servlet [spring] in context with path [] threw exception [org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.app.cloud.hibernate.Product.availabilities, no session or session was closed] with root cause
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.app.cloud.hibernate.Product.availabilities, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:119)
at org.hibernate.collection.PersistentSet.isEmpty(PersistentSet.java:169)
at org.apache.el.parser.AstEmpty.getValue(AstEmpty.java:55)
at org.apache.el.parser.AstNot.getValue(AstNot.java:44)
at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:185)
at org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate(PageContextImpl.java:1026)
at org.apache.jsp.WEB_002dINF.jsp.product.products_jsp._jspx_meth_c_005fwhen_005f0(products_jsp.java:321)
at org.apache.jsp.WEB_002dINF.jsp.product.products_jsp._jspx_meth_c_005fchoose_005f0(products_jsp.java:290)
at org.apache.jsp.WEB_002dINF.jsp.product.products_jsp._jspx_meth_c_005fforEach_005f0(products_jsp.java:233)
at org.apache.jsp.WEB_002dINF.jsp.product.products_jsp._jspx_meth_c_005fif_005f0(products_jsp.java:185)
at org.apache.jsp.WEB_002dINF.jsp.product.products_jsp._jspService(products_jsp.java:141)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
at org.apache.jasper.servlet.JspServlet._serviceJspFile(JspServlet.java:390)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:749)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:487)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:412)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:339)
at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:238)
at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:264)
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1208)
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:992)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:939)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:915)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:811)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:796)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.__invoke(StandardContextValve.java:123)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:581)
at org.apache.catalina.core.StandardHostValve.__invoke(StandardHostValve.java:171)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:947)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1009)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1686)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
web.xml
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>sessionFactoryBeanName</param-name>
<param-value>sessionFactory</param-value>
</init-param>
<init-param>
<param-name>singleSession</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Context parameters -->
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>WEB-INF/log4j.properties</param-value>
</context-param>
<context-param>
<param-name>log4jExposeWebAppRoot</param-name>
<param-value>false</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
</web-app>
spring-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:p="http://www.springframework.org/schema/p" 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.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.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/lang http://www.springframework.org/schema/lang/spring-lang.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<mvc:annotation-driven />
<tx:annotation-driven />
<context:component-scan base-package="com.app.cloud" />
<bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
<property name="basename" value="spring-views" />
<property name="order" value="1" />
</bean>
<bean id="jspViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
<property name="order" value="2" />
</bean>
<!-- JDBC -->
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="/WEB-INF/jdbc.properties" />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close" p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.databaseurl}" p:username="${jdbc.username}" p:password="${jdbc.password}" />
<!-- Hibernate -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
<property name="configurationClass">
<value>org.hibernate.cfg.AnnotationConfiguration</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${jdbc.dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
ProductService.java
#Transactional
public interface ProductService {
#Transactional
public void add(Product product);
#Transactional
public List<Product> getAll();
#Transactional
public Product get(Integer idProduct);
#Transactional
public void remove(Integer id);
#Transactional
public void edit(Product product);
}
ProductServiceImpl.java
#Service
#Transactional
public class ProductServiceImpl implements ProductService {
#Autowired
private ProductDAO productDAO;
#Transactional
public void add(Product product) {
productDAO.add(product);
}
#Transactional
public List<Product> getAll() {
return productDAO.getAll();
}
#Transactional
public void remove(Integer id) {
productDAO.remove(id);
}
#Transactional
public Product get(Integer idProduct) {
return productDAO.get(idProduct);
}
#Transactional
public void edit(Product product) {
productDAO.edit(product);
}
}
ProductDAO.java
public interface ProductDAO {
public void add(Product product);
public void edit(Product product);
public List<Product> getAll();
public Product get(Integer idProduct);
public void remove(Integer id);
}
ProductDAOImpl.java
#Repository
public class ProductDAOImpl implements ProductDAO {
#Autowired
private SessionFactory sessionFactory;
public void add(Product product) {
sessionFactory.getCurrentSession().save(product);
}
public List<Product> getAll() {
return sessionFactory.getCurrentSession().createQuery("from Product")
.list();
}
public void remove(Integer id) {
Product product = (Product) sessionFactory.getCurrentSession().load(
Product.class, id);
if (null != product) {
sessionFactory.getCurrentSession().delete(product);
}
}
public Product get(Integer idProduct) {
Product product = (Product) sessionFactory.openSession().get(
Product.class, idProduct);
return product;
}
#Override
public void edit(Product product) {
sessionFactory.getCurrentSession().update(product);
}
}
Product.java
#Entity
#Table(name = "product", catalog = "app")
public class Product implements java.io.Serializable {
private Integer idProduct;
#NotEmpty
#Length (min=1,max=70)
private String name;
private Set<Availability> availabilities = new HashSet<Availability>(0);
public Product() {
}
public Product(String name) {
this.category = category;
this.name = name;
this.lastUpdate = lastUpdate;
this.actionFlag = actionFlag;
}
public Product(String name,
Set<Availability> availabilities,
) {
this.name = name;
this.availabilities = availabilities;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id_product", unique = true, nullable = false)
public Integer getIdProduct() {
return this.idProduct;
}
public void setIdProduct(Integer idProduct) {
this.idProduct = idProduct;
}
#Column(name = "name", nullable = false, length = 70)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "product")
public Set<Availability> getAvailabilities() {
return this.availabilities;
}
public void setAvailabilities(Set<Availability> availabilities) {
this.availabilities = availabilities;
}
}
It's very classical error when working with Hibernate.
If you have any lazy-loading proxies your should replace them either with nulls or with real objects before returning from #Transactional context.
The Set or List that is lazy loaded is replaced by the Hibernate with the proxy. The proxy would load the collection first time it is accessed. But what if it is first accessed if you are outside the transactional context? The hibernate session that is referenced by the proxy doesn't exist so you have the error.
If you won't need the collection, set it to null or empty HashSet/ArrayList. If you would need it, call the size() or iterate through the element within transactional context. If you are not sure, provide the API for loading the connection. But don't return objects with uninitialized proxies.
Annotate your Controller as #Transactional. You wont see that error again, You bet!!
Note
Experts say that #Transactional is not to be used on Controller, But I didn't get an answer why?
You can try
#Proxy (lazy = false)
On top of both entity class. It works in my case.

Hibernate Spring Integration, Tables Are Being Created, But SessionFactory is not Autowired

I have integrated Spring and Hibernate, when i run my application using jetty plugin for maven, Hibernate creates tables but i my sessionFactory object is null,
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
</welcome-file-list>
<!-- The definition of the Root Spring Container shared by all Servlets
and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml,
/WEB-INF/spring/security-context.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
servlet-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.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">
<!-- DispatcherServlet Context: defines this servlet's request-processing
infrastructure -->
<!-- Enables the Spring MVC #Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving
up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by #Controllers to .jsp resources
in the /WEB-INF/views directory -->
<beans:bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.fyp.ptma" />
<beans:bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="/WEB-INF/jdbc.properties" />
<beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close" p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.databaseurl}" p:username="${jdbc.username}" p:password="${jdbc.password}" />
<beans:bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<beans:property name="dataSource" ref="dataSource"></beans:property>
<beans:qualifier value="sessionFactory"></beans:qualifier>
<beans:property name="annotatedClasses">
<beans:list>
<beans:value>com.fyp.ptma.model.Application</beans:value>
<beans:value>com.fyp.ptma.model.ApplicationVersion</beans:value>
<beans:value>com.fyp.ptma.model.Defect</beans:value>
<beans:value>com.fyp.ptma.model.DefectDetail</beans:value>
<beans:value>com.fyp.ptma.model.Group</beans:value>
<beans:value>com.fyp.ptma.model.Downloader</beans:value>
<beans:value>com.fyp.ptma.model.Notification</beans:value>
<beans:value>com.fyp.ptma.model.RegisterStatus</beans:value>
<beans:value>com.fyp.ptma.model.User</beans:value>
<beans:value>com.fyp.ptma.model.Invitation</beans:value>
<beans:value>com.fyp.ptma.model.Installation</beans:value>
</beans:list>
</beans:property>
<beans:property name="hibernateProperties">
<beans:props>
<beans:prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect
</beans:prop>
<beans:prop key="hibernate.show_sql">true</beans:prop>
<beans:prop key="hibernate.hbm2ddl.auto">create</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
<beans:bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<beans:property name="sessionFactory" ref="sessionFactory" />
</beans:bean>
UserDao.java
#Repository
public class UserDao implements IUserDao {
#Autowired
#Qualifier(value="sessionFactory")
private SessionFactory sessionFactory;
public Session openSession() {
return sessionFactory.getCurrentSession();
}
public Long save(Object objToSave) throws PersistenceException,
ConstraintViolationException {
Session session = null;
try {
session = this.openSession();
session.beginTransaction();
session.save(objToSave);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally {
// session.close();
}
return null;
}
public Long update(Object objToUpdate) throws PersistenceException {
// TODO Auto-generated method stub
return null;
}
public boolean delete(Object objToDelete) throws PersistenceException,
ConstraintViolationException {
// TODO Auto-generated method stub
return false;
}
public List<Application> getAllApplications(User user)
throws HibernateException {
// TODO Auto-generated method stub
return null;
}
public Application getApplication(User user) throws HibernateException {
// TODO Auto-generated method stub
return null;
}
public boolean authenticateLogin(User user) throws AuthenticationException,
HibernateException {
Session session = this.openSession();
session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.eq("email", user.getEmail()));
User userDB = (User) criteria.uniqueResult();
return userDB.getPassword().equals(user.getPassword());
}
public User getUserByEmail(String email) throws HibernateException {
Session session = this.openSession();
session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.eq("email", email));
User userDB = (User) criteria.uniqueResult();
// session.close();
return userDB;
}
}
My Controller
#ResponseBody
#RequestMapping(value = "/processRegistration.html", method = RequestMethod.POST)
public String processRegistration(#ModelAttribute("user") User user,
Model model, BindingResult result) {
UserDao uDao = DaoFactory.getUserDao();
uDao.save(user);
return "ok";
}
when i call uDao.save in my controller , sessionFactory object of UserDao is null, but during initialisation i dont get any wiring error when i try my controller with below line,
ApplicationContext context = new
AnnotationConfigApplicationContext("com.fyp.ptma.dao");
it throw exception while submitting form:
: No matching bean of type [org.hibernate.SessionFactory] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
It is stupid but what i was doing i was AutoWired my SessionFactory, and Dao Class but when i was getting Dao from Dao Factory i was returning as return new Dao(); this was causing to create whole new object, because SessionFactory was instance variable in Dao, it get default value of Object which was null here, below is my bug snipped
public class UserDao{
#AutoWired
private SessionFactory sessionFactory;
...
//more code
}
public static Dao getUserDao() {
return new UserDao();
}

Injection of the sessionFactory not working

I'm new with Spring and I want to inject the sessionFactory and its not working at all. I'm starting a web server Jetty and then I load the context. After i start a GWT web application, I make a call on the server side and I try to get some info but I get a null pointer. There is no error at all so it make it difficult to know where the problem is. I know its suppose to work because I saw it working on a project I worked on some times ago. Any help will be appreciate. (Sorry for my possibly bad english)
Here is the context.xml :
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:security="http://www.springframework.org/schema/security"
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/tx http://www.springframework.org/schema
/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema
/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema
/security/spring-security-3.0.xsd">
<!-- Standard spring initialization -->
<context:component-scan base-package="com.test">
</context:component-scan>
<tx:annotation-driven transaction-manager="txManager"/>
<!-- Connection to the database-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-
method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/test" />
<property name="username" value="root" />
<property name="password" value="123456789" />
</bean>
<!-- Hibernate session factory-->
<bean id="jpaSessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.domain"/>
<property name="namingStrategy" >
<bean class="org.hibernate.cfg.ImprovedNamingStrategy" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<!-- Hibernate session factory -->
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="jpaSessionFactory" />
</bean>
</beans>
Here is the main :
public static void main(String[] args) {
ContextHandlerCollection contexts = new ContextHandlerCollection();
contexts.setHandlers(new Handler[]
{ new AppContextBuilder().buildWebAppContext()});
final JettyServer jettyServer = new JettyServer();
jettyServer.setHandler(contexts);
Runnable runner = new Runnable() {
#Override
public void run() {
new ServerRunner(jettyServer);
}
};
EventQueue.invokeLater(runner);
new ClassPathXmlApplicationContext("context.xml");
}
Here is the class Test where I want the injection :
#Component("test")
public class TEST{
#Resource(name="jpaSessionFactory")
private SessionFactory sessionFactory;
#SuppressWarnings("unchecked")
#Transactional(readOnly = true)
public List<Personne> getPersonnes() {
Session s = sessionFactory.getCurrentSession();
Query query = s.createQuery("from Person");
return query.list();
}
}
Here is the server side from the application (not shown completely)
/*** The server side implementation of the RPC service.
*/
#SuppressWarnings("serial")
public class GreetingServiceImpl extends RemoteServiceServlet implements
GreetingService {
#Resource
private TEST t;
public String greetServer(String input) throws IllegalArgumentException {
// Verify that the input is valid.
if (!FieldVerifier.isValidName(input)) {
// If the input is not valid, throw an IllegalArgumentException
back to
// the client.
throw new IllegalArgumentException(
"Name must be at least 4 characters long");
}
t.getPersons(); // NULL pointer here
.........................
The MySQL tables are created like it should, so all the scanning seems to work.
Thanks
Bob
This is because the GreetingServiceImpl class is not created by spring - it is servlet that is initialized by the container directly. Follow the instructions in this article to fix the issue. I have copied the relevant code from the article.
#Override
public void init() throws ServletException {
super.init();
final WebApplicationContext ctx =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
if (ctx == null) {
throw new IllegalStateException("No Spring web application context found");
}
ctx.getAutowireCapableBeanFactory().autowireBeanProperties(this,
AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
}

Resources