LazyInitializationException for some of requests - spring

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).

Related

Mapping Controllers

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.

406 Not Acceptable Spring Rest WS

I am writing a spring rest WS to return response as XML. Below are my classes and pom file.
I am getting Http 406 Error on executing the service as below:
http://localhost:8080/SpringRestExample/rest/emp/dummy.xml
However, I am getting the JSON response back when executing
http://localhost:8080/SpringRestExample/rest/emp/dummy.json
Please advise
pom.xml
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>${jackson.version}</version>
</dependency>
EmployeeController:
#RequestMapping(value = "/rest/emp/dummy", method = RequestMethod.GET,produces={"application/xml"})
public #ResponseBody Employee getDummyEmployeeXML() {
logger.info("Start getDummyEmployee");
Employee emp = new Employee();
emp.setId(9999);
emp.setName("Dummy");
emp.setCreatedDate(new Date());
empData.put(9999, emp);
return emp;
}
app-context.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:mvc="http://www.springframework.org/schema/mvc"
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/mvc http://www.springframework.org/schema/mvc/spring-mvc.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/" />
<context:component-scan base-package="com.skanda.spring.controller" />
<beans:bean id="contentNegotiationManager"
class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<beans:property name="favorPathExtension" value="true" />
<beans:property name="favorParameter" value="true" />
<beans:property name="parameterName" value="mediaType" />
<beans:property name="ignoreAcceptHeader" value="true"/>
<beans:property name="useJaf" value="false"/>
<beans:property name="defaultContentType" value="application/json" />
<beans:property name="mediaTypes">
<beans:map>
<beans:entry key="json" value="application/json" />
<beans:entry key="xml" value="application/xml" />
</beans:map>
</beans:property>
</beans:bean>
Employee:
public class Employee implements Serializable{
private static final long serialVersionUID = -7788619177798333712L;
private int id;
private String name;
private Date createdDate;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#JsonSerialize(using=DateSerializer.class)
public Date getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Date createdDate) {
this.createdDate = createdDate;
}
}
406 means that the server is not able to produce a response in the content type asked by the client. Check the Accept header of your HTTP request, and make sure it contains application/xml.
Maybe it contains text/xml, and that's what you should use in the producesattribute of your #RequestMappingannotation. BTW, you should use the constants in org.springframework.http.MediaType instead of hard-coding the string as you're doing.
for any type of xml conversion you need to add #XmlRootElement annotation on top of Model class. i have done the changes and run the above program and got the result.Just add #XmlRootElement above Employee class and you are done.

I can persist data through the test but not through the app. aop problems

I've been spending two days in trying to resolve a weird problem. I'm working in a MVC Spring App and when I run the following test....
#ContextConfiguration(locations = "/persistence-beans.xml")
public class UserDaoTest extends AbstractJUnit4SpringContextTests{
#Autowired
private UserDao userDao;
#Test
public void testAdd() {
int size = userDao.list().size();
User user = new User();
user.setName("omar");
userDao.add(user);
List<User> users = userDao.list();
System.out.println("users size: " + users.size());
// list should have one more employee now
assertTrue (size < users.size());
}
}
I see the result in the data base and all it's ok. But, when I call a controller and use the same Dao (userDao) to create an user, the app does not persist the user and do not throw any error. The only thing that comes to my mind is that there is a problem with the transaction annotation from Spring in the part of the servlet-context.xml. I can believe that in the test case work but not in app flow!
Please, I need to get out from this problem!!!!
------ Interface Dao --------
public interface GenericDao<E, K> {
void add(E entity);
void update(E entity);
void remove(E entity);
E find(K key);
List<E> list();
}
public interface UserDao extends GenericDao<User, Long>{
}
package com.tutorial.dao.impl;
import java.io.Serializable;
import java.util.List;
import com.tutorial.dao.GenericDao;
import java.lang.reflect.ParameterizedType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
#Transactional(propagation = Propagation.REQUIRED, readOnly = false)
public class GenericDaoJPAImpl<E, K extends Serializable> implements GenericDao<E, K>{
#PersistenceContext
private EntityManager entityManager;
protected Class<E> daoType;
#SuppressWarnings("unchecked")
public GenericDaoJPAImpl() {
daoType = (Class<E>) ((ParameterizedType) getClass().getGenericSuperclass())
.getActualTypeArguments()[0];
}
public void add(E entity) {
em().persist(entity);
}
public EntityManager em() {
return entityManager;
}
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
#Override
public void update(E entity) {
em().merge(entity);
}
#Override
public void remove(E entity) {
em().remove(em().merge(entity));
}
#Override
public E find(K key) {
return (E) em().find(daoType, key);
}
#Override
public List<E> list() {
List<E> list = null;
TypedQuery<E> query = em().createQuery("select o from "
+ daoType.getSimpleName() + " o",
daoType);
list = query.getResultList();
return list;
}
}
#Repository("UserDao")
public class UserDaoImpl extends GenericDaoJPAImpl<User, Long> implements UserDao{
}
-------- Service Layer -----------
#Service("calculatorService")
#Transactional(propagation= Propagation.REQUIRED, readOnly=false)
public class CalculatorServiceImpl implements CalculatorService{
#Autowired
private UserDao userDao;
#Override
public void createUser(User user) {
userDao.add(user);
}
}
---------- Controller --------------
#Controller
#RequestMapping("/calculate")
public class CalculatorController {
#Autowired
private CalculatorService calculatorService;
#RequestMapping(method = RequestMethod.POST)
public String addUser(User user){
calculatorService.createUser(user);
return "session";
}
}
------- Persistence Beans ---------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
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-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<!-- we can use annotations -->
<context:annotation-config />
<!-- we will manage transactions with annotations -->
<tx:annotation-driven />
<context:component-scan base-package="com.tutorial.dao.impl" />
<context:property-placeholder location="classpath*:properties/database.properties"/>
<!-- data source for our database -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${database.driverClassName}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<!-- EntityManagerFactoryBean -->
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="persistenceUnitName" value="persistenceUnit"/>
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
---------------------- Servlet Context -----------------------------
<?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">
<!-- 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>
<!--All beans are scanned here, except the Repository because they are scanned in persistence-beans.xml-->
<context:component-scan base-package="com.tutorial.*" >
<context:exclude-filter expression="org.springframework.stereotype.Repository" type="annotation"/>
</context:component-scan>
</beans:beans>
----------------------- 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">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/root-context.xml
classpath:persistence-beans.xml
</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>calculator</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</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>calculator</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
The link of this project is the next: https://github.com/igiagante/calculator
Feel free to download to prove what's going on :) Thanks you!!!
It seems that you missed for your CalculatorServiceImpl. While your dispatcher-servlet.xml does.
Have a try that adding
<context:component-scan base-package="where your service is"/>
in your root application context and remove unnecessary component-scan in your dispatcher-servlet.

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();
}

Resources