Spring mvc + hibernate/jpa -> entity manager is not injected despite #PersistenceContext - java

I have a problem with EntityManager. When I try to use EntityManager in a dao class, I got null pointer exception. So EntityManager is not injected despite #PersistenceContext annotation.
My dao:
package com.fido.pia.dao;
import com.fido.pia.model.User;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
#Repository
public class UserDao {
#PersistenceContext
protected EntityManager entityManager;
public User save(User row) {
if(row.isNew()) {
entityManager.persist(row);
return row;
} else {
return entityManager.merge(row);
}
}
}
Servlet Config:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
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.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--
Adds some default beans (HandlerAdapter, HandlerMapping, Binding Initializer...). It also turn on some annotations.
Explanation in http://stackoverflow.com/questions/28851306/spring-framework-what-is-the-purpose-of-mvcannotation-driven
WITHOUT THIS, #RequestMapping ANNOTATIONS ARE LOADED, BUT MAPPING DO NOT WORK!!
-->
<mvc:annotation-driven />
<!-- Set loading annotations from classes
<context:component-scan base-package="com.fido.pia"/>-->
<!--manual homepage-->
<mvc:view-controller path="/" view-name="home"/>
<!--view resolver-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/" />
<property name="suffix" value=".jsp" />
</bean>
<!--static resources - request will be handeled by ResourceHttpRequestHandler-->
<mvc:resources mapping="/resources/**" location="/resources/" />
<!--database config-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/pia" />
<property name="username" value="root" />
<property name="password" value="" />
</bean>
<!--entity manager factory-->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="packagesToScan" value="com.fido.pia" />
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<!--<property name="generateDdl" value="true" />-->
<property name="showSql" value="true" />
</bean>
</property>
</bean>
<!-- Transactions -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<!-- enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!--Set loading annotations from classes-->
<context:component-scan base-package="com.fido.pia"/>
</beans>
Any ideas what is wrong here?

In entityManagerFactory bean definition, try this :
<property name="packagesToScan" value="com.fido.pia.*" />
This should work

I finally solve it. The problem was that I use common dependency injection to inject my dao class in controller. When I change it to DI with autowired (added #autowired to controller constructor), entity manager in dao is initialized.
So now it works, but I'm still curious about why is that change so important. I've asked new question about it.

You need to enable persistence annotations:
<context:annotation-config/>
or
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

Related

Dispacter Servelt xml file

I am working on project with Spring mvc and i want to use jpa features as well.
I have an 3 entity classes, their corresponding repository interfaces. I have their autowired objects in common service class. However I am facing issues while creating bean for this service class object which is used in controller.
The 3 model class are User, Appointment and Notification.
The repository interface extends CRUDRepository interface.
Service class :
#Service
public class EHealthService
{
#Autowired
UserRepository uRepo;
#Autowired
AppointmentRepository aRepo;
#Autowired
NotificationRepository nRepo;
public void registerUser(User u)
{
uRepo.save(u);
}
public boolean login(User u)
{
if(uRepo.findByemail(u.getEmail())!=null)
return true;
else
return false;
}
public List<User> getDoctorList()
{
return uRepo.findByisdoctor(true);
}
// some more functions
}
Controller class:
#Controller
public class EHealthController
{
#Autowired
EHealthService eservice;
//Some code
}
ehealth-dispacter-servlet.xml file:
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<context:component-scan base-package="com.cl3.controller" />
<context:component-scan base-package="com.cl3.model" />
<context:component-scan base-package="com.cl3.service" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"/>
<property name="generateDdl" value="true"/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
<property name="packagesToScan" value="com.cl3.model"/>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
<jpa:repositories base-package="com.cl3.model"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="url" value="jdbc:postgresql://localhost:5432/cl3" />
<property name="username" value="ucan" />
<property name="password" value="ucan" />
</bean>
<bean id="eservice" class="com.cl3.service.EHealthService">
<property name="uRepo" ref="uRepo"></property>
<property name="nRepo" ref="nRepo"></property>
<property name="aRepo" ref="aRepo"></property>
</bean>
<bean id="uRepo" class="com.cl3.model.UserRepository">
</bean>
<bean id="nRepo" class="com.cl3.model.NotificationRepository">
</bean>
<bean id="aRepo" class="com.cl3.model.AppointmentRepository">
</bean>
It says the class is an interface.
What will be the bean for eservice object and to enable jpa in dispacter servel xml file?
Thank you.
If you are using spring xml based configuration then add below bean's to configuration file :
<bean id="entityManagerFactoryBean" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- This makes /META-INF/persistence.xml is no longer necessary -->
<property name="packagesToScan" value="com.howtodoinjava.demo.model" />
<!-- JpaVendorAdapter implementation for Hibernate EntityManager.
Exposes Hibernate's persistence provider and EntityManager extension interface -->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">validate</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
</props>
</property>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<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="password" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactoryBean" />
Register component scanning by adding this binding annotation in xml file :
<context:component-scan base-package="com.mycompany.projectname.demo" />
If your project is spring mvc the add below binding annotation to xl file
<!-- This allow for dispatching requests to Controllers -->
<mvc:annotation-driven />
For declarative transaction management add below piece in xml file.
<tx:annotation-driven />
Basically you no need to add service bean in xml configuration file if you are enabled component scanning feature in spring.
Add required dependencies to integrate jpa with spring.
Refer this link will help you more :
https://howtodoinjava.com/jpa/spring-hibernate-jpa-configuration-example/

Spring MVC Test setup fails on loading ApplicationContext.xml

Currently I'm trying to setup Spring MVC Controller testing for a school project I'm working on next to my job. Normally I program in php and frameworks like Laravel so this is pretty new for me. The problem is that I can't figure out how to solve the problem that keeps popping up on loading the ApplicationContext. Any help is appreciated.
Update:
I'm now told that test cases don't use a jndi ref in my app server. So this reference would fail on a test case, it runs fine on starting the application. Now I made a second file called servlet-test.xml (listed below) that uses a reference to the database on port 3306. I only use this file on tests not when starting up the application. But when I use this method I get Following error: Error creating bean with name 'productController': Injection of autowired dependencies failed. Any help is welcome as I'm struggling to setup MVC Controller tests for my school project. Other students I've been working with also are stuck with the same problem I am so I could help them out too.
I suspect the problem is the following, but I'm not sure how to solve this.
Error creating bean with name 'myDataSource' defined in URL
[file:web/WEB-INF/servlet.xml]: Invocation of init method failed;
nested exception is javax.naming.NamingException: Lookup failed for
'java:app/fotoproducent' ...
The Error Stack Trace
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in URL [file:web/WEB-INF/servlet.xml]: Cannot resolve reference to bean 'myDataSource' while setting bean property 'dataSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myDataSource' defined in URL [file:web/WEB-INF/servlet.xml]: Invocation of init method failed; nested exception is javax.naming.NamingException: Lookup failed for 'java:app/fotoproducent' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.url.pkgs=com.sun.enterprise.naming, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl} [Root exception is javax.naming.NamingException: Invocation exception: Got null ComponentInvocation ]
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:107)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1456)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1197)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:973)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:750)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:121)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:100)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:250)
at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContextInternal(CacheAwareContextLoaderDelegate.java:64)
at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:91)
The Controller test i'm trying to run:
ProductController Test
package controller.tests.config;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration({"file:web/WEB-INF/servlet-test.xml", "file:web/WEB-INF/dispatcher-servlet.xml"})
public class ProductControllerTest {
#Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
#Before
public void setup() {
DefaultMockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(this.wac);
this.mockMvc = builder.build();
}
#Test
public void testProductAction() throws Exception {
ResultMatcher ok = MockMvcResultMatchers.status().isOk();
ResultMatcher msg = MockMvcResultMatchers.model()
.attribute("msg", "Spring quick start!!");
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/product");
this.mockMvc.perform(builder)
.andExpect(ok)
.andExpect(msg);
}
}
servlet.xml / applicationContext.xml file
<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-4.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- module/package declarations -->
<context:component-scan base-package="Application" />
<context:component-scan base-package="Authentication" />
<context:component-scan base-package="Photo" />
<context:component-scan base-package="Product" />
<context:component-scan base-package="Organisation" />
<context:component-scan base-package="Login" />
<context:component-scan base-package="UI" />
<context:component-scan base-package="I18n" />
<context:component-scan base-package="Internationalization" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<bean id="myDataSource" class="org.springframework.jndi.JndiObjectFactoryBean" scope="singleton">
<property name="jndiName" value="java:app/fotoproducent" />
<property name="resourceRef" value="true" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />
<property name="packagesToScan" value="*" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
</bean>
</property>
</bean>
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
<mvc:resources mapping="/static/**" location="/static/"/>
<mvc:resources mapping="/resources/**" location="/resources/" />
<mvc:default-servlet-handler/>
<mvc:annotation-driven />
</beans>
Dispatcher-servlet.xml
<?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:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMap ping"/>
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="index.html">indexController</prop>
<prop key="test.html">testController</prop>
</props>
</property>
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/views/"
p:suffix=".jsp" />
<!--
The index controller.
-->
<bean name="indexController"
class="org.springframework.web.servlet.mvc.ParameterizableViewController"
p:viewName="index" />
<!--
The test controller.
-->
<bean name="testController"
class="org.springframework.web.servlet.mvc.ParameterizableViewController"
p:viewName="test" />
</beans>
Update 1: "DataSource Configuration"
This shows how the datasource is configured.
glassfish-resources.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions//EN" "http://glassfish.org/dtds/glassfish-resources_1_5.dtd">
<resources>
<jdbc-connection-pool allow-non-component-callers="false" associate-with-thread="false" connection-creation-retry-attempts="0" connection-creation-retry-interval-in-seconds="10" connection-leak-reclaim="false" connection-leak-timeout-in-seconds="0" connection-validation-method="auto-commit" datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" fail-all-connections="false" idle-timeout-in-seconds="300" is-connection-validation-required="false" is-isolation-level-guaranteed="true" lazy-connection-association="false" lazy-connection-enlistment="false" match-connections="false" max-connection-usage-count="0" max-pool-size="32" max-wait-time-in-millis="60000" name="mysql_fotoproducent_rootPool" non-transactional-connections="false" pool-resize-quantity="2" res-type="javax.sql.DataSource" statement-timeout-in-seconds="-1" steady-pool-size="8" validate-atmost-once-period-in-seconds="0" wrap-jdbc-objects="false">
<property name="serverName" value="localhost"/>
<property name="portNumber" value="3306"/>
<property name="databaseName" value="fotoproducent"/>
<property name="User" value="root"/>
<property name="Password" value="password"/>
<property name="URL" value="jdbc:mysql://localhost:3306/fotoproducent?zeroDateTimeBehavior=convertToNull"/>
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
</jdbc-connection-pool>
<jdbc-resource enabled="true" jndi-name="app/fotoproducent" object-type="user" pool-name="mysql_fotoproducent_rootPool"/>
</resources>
Update 2: Additional Bean Config file (servlet-test.xml)
This results in beans not being loaded. Following error: Error creating bean with name 'productController': Injection of autowired dependencies failed
<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-4.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:annotation-config/>
<mvc:annotation-driven />
<!-- module/package declarations -->
<context:component-scan base-package="Application" />
<context:component-scan base-package="Authentication" />
<context:component-scan base-package="Photo" />
<context:component-scan base-package="Product" />
<context:component-scan base-package="Organisation" />
<context:component-scan base-package="Login" />
<context:component-scan base-package="UI" />
<context:component-scan base-package="I18n" />
<context:component-scan base-package="Internationalization" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/fotoproducent?zeroDateTimeBehavior=convertToNull" />
<property name="username" value="root" />
<property name="password" value="password" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />
<property name="packagesToScan" value="*" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
</bean>
</property>
</bean>
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
<mvc:resources mapping="/static/**" location="/static/"/>
<mvc:resources mapping="/resources/**" location="/resources/" />
</beans>
Update 3: Additional Code for problem resolving
Product Controller
package Product.Controller;
import Product.Sevice.ProductService;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
#Controller
#RequestMapping("/product")
public class ProductController {
#Autowired
protected ProductService service;
#RequestMapping(value = "", method = RequestMethod.GET)
public String productAction(ModelMap model)
{
model.put("productList", this.service.findAll());
return "product/overview";
}
}
Product Service
package Product.Sevice;
import Product.Entity.Product;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.transaction.Transactional;
import org.springframework.stereotype.Service;
#Service
public class ProductService {
#PersistenceContext
private EntityManager em;
#Transactional
public void insert(Product product)
{
// insert into database
// persist function is for NEW entities in database
this.em.persist(product);
}
#Transactional
public Product get(Integer id)
{
// this gets the entity from the database and returns it
return this.em.find(Product.class, (long) id);
}
#Transactional
public Product update(Product product)
{
// this updates the ExampleEntity in within the database
return this.em.merge(product);
}
#Transactional
public void remove(Integer id)
{
Product product = this.em.find(Product.class, (long) id);
product.delete();
// this updates the product in within the database
this.update(product);
}
#Transactional
public List<Product> findAll()
{
Query q = this.em.createNamedQuery("product.namedquery", Product.class);
return q.getResultList();
}
}
According to your stack trace when application context is initializing it still try to load wrong configuration files (servlet.xml), but should load servlet-test.xml. Please try to change your config locations with using path from root (src) folder, such as:
#ContextConfiguration({"file:src/main/web/WEB-INF/servlet-test.xml", "file:src/main/web/WEB-INF/dispatcher-servlet.xml"})
P.S Also you can try to move your config for tests (servlet-test.xml) to src/test/resources and load it from classpath: "classpath:servlet-test.xml". Also you can check this thread on stackoverflow: Spring #ContextConfiguration how to put the right location for the xml for extended discussion of similar problem.
You get an error which says that Spring IOC container fails to create and instantiate entityManagerFactory bean. Why?
That's another thing that your error exception mention. It fails to do so because it can't instantiate the myDataSource bean. Why?
According to your error message:
Lookup failed for 'java:app/fotoproducent'
It means that when IOC Spring container tried to create myDataSource bean, it failed to do so because it failed to set the jndiName with value of java:app/fotoproducent
Instead of using this:
<bean id="myDataSource" class="org.springframework.jndi.JndiObjectFactoryBean" scope="singleton">
<property name="jndiName" value="java:app/fotoproducent" />
<property name="resourceRef" value="true" />
</bean>
Replace it with:
<bean id="myDataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="your_driver_class_name" />
<property name="url" value="url_to_your_db" />
<property name="username" value="user_name_to_db" />
<property name="password" value="password_to_db" />
</bean>
My suggestion is to create a standard dataSource like mentioned on Spring docs above.
Now don't forget to replace the values for driver class name, url, user name, and password.
Here is an example from Spring docs, of how to define a data source for use of Hibernate ORM: http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#orm-hibernate

Cannot inject sessionFactory

While trying to get sessionFactory.getCurrentSession() debugger shows that sessionFactory is null. I assume Spring 3 fails to inject sessionFactory into this class although all configuration seems to be in place. How to fix it?
ServiceOrderDAO:
#Transactional
public class ServiceOrderDAO{
#Autowired
static
SessionFactory sessionFactory;
public static List<ServiceOrderEntity> search(params...){
Session localSession = sessionFactory.getCurrentSession();
...
}
}
applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<context:annotation-config />
<mvc:annotation-driven/>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="" />
<property name="suffix" value=".jsp" />
</bean>
<context:component-scan base-package="controller" />
<context:component-scan base-package="dao" />
<context:component-scan base-package="service" />
<context:property-placeholder location="classpath:dbConnection.properties" />
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="model" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!--<bean id="persistenceExceptionTranslationPostProcessor" class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.user}" />
<property name="password" value="${jdbc.pass}" />
</bean>
<bean id="jdbcTemplateBean" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
There are a few things I think you'll want to touch up:
SessionFactory shouldn't be static, nor should your search method be static if you're trying to treat that class as a Spring bean.
Add a #Component or #Repository annotation to the class. I don't think Spring will autowire classes that are missing a stereotype annotation on the class.
You should consider moving your #Transactional annotation to the method so you can provide more fine-grained propagation. For example, your search method may not require a transaction so you may want to use #Transactional(propagation = Propagation.SUPPORTS). Check out the Spring documentation for additional info that explains the various annotations and where/how to annotate transactions.
sessionFactory being static definitely is the cause of the problem. You can't inject static fields with spring.
Going under the covers, the static fields gets initialized by classloader, before the constructor gets called, and therefore before spring gets chance to inject anything.
And your service class should be transactional, not your dao. And yes you need to annotate with #Component or #Service or similar.

Setting FlushMode.COMMIT in Spring

I would like set my Hibernate/JPA FlushMode to COMMIT, but in configuration file (applicationContenxt.xml is one of my files), i have a entityManager in my DAO, but i don't know how to set this in configuration file.
So, this is my applicationContext.xml
<?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-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">
<!-- Seta anotaƧoes para serem usadas pelo Spring -->
<context:annotation-config />
<!-- Define o pacote onde o Spring vai procurar por beans anotados -->
<context:component-scan
base-package="br.com.sender" />
<!-- define que as transaƧoes irao ser anotadas -->
<tx:annotation-driven proxy-target-class="true" />
<!-- Configuracao do Banco de Dados -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="url" value="jdbc:postgresql://localhost/sender" />
<property name="username" value="postgres" />
<property name="password" value="pgadmin" />
</bean>
<!-- Configuracao do Hibernate -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="senderPU" />
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="org.hibernate.dialect.PostgreSQLDialect" />
<property name="showSql" value="true" />
</bean>
</property>
</bean>
<!-- Configuracao do gerente de transacoes do Spring -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
</beans>
EDIT 1:
I tried the following in applicationContext.xml
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect">
<property name="flushMode" value="COMMIT"/>
</bean>
</property>
Tomcat error:
aused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'flushMode' of bean class [org.springframework.orm.jpa.vendor.HibernateJpaDialect]: Bean property 'flushMode' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:1052)
at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:921)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:76)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:58)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1358)
... 53 more
SOLUTION:
After a lot of research, i found a solution. I setted the FlushMode in #PersistenceContext in my BasicDAO class. Look:
#PersistenceContext(type = javax.persistence.PersistenceContextType.EXTENDED,
properties = #PersistenceProperty(name="org.hibernate.flushMode", value="COMMIT"))
protected EntityManager entityManager;
This works fine. I removed all #Transactional annotation from my "find" functions, because with #Transactional the "COMMIT" are fired and flush too.

Insert into two tables in two different database

My Java web application on spring framework is using two database say database-1 and database-2. Both database have User table. What I am trying to do is to insert record into both tables at same time.
There are two persistence-unit in the persistence.xml that is pointing out to database.
Here is my persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="p1-jpa" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:jboss/datasources/MySqlDS2</jta-data-source>
<class>com.xyz.entity.User</class>
<exclude-unlisted-classes />
<properties>
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.HashtableCacheProvider" />
</properties>
</persistence-unit>
<persistence-unit name="p2-jpa" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:jboss/datasources/MySqlDS2</jta-data-source>
<class>com.mmxhealthcare.entity.MMASCUser</class>
<exclude-unlisted-classes />
<properties>
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.HashtableCacheProvider" />
</properties>
</persistence-unit>
</persistence>
Now Whenever I am trying to add user, it is inserted only in Database-1. I am not getting any exception.
Here is my spring-servlet.xml file:-
<?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:jaxrs="http://cxf.apache.org/jaxrs"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util" xmlns:security="http://www.springframework.org/schema/security"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.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-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.1.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<bean id="viewResolver" 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="0"/>
</bean>
<!-- <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean> -->
<context:property-placeholder location="classpath:config.properties" />
<context:annotation-config />
<context:component-scan base-package="com.xyz.controller" />
<context:component-scan base-package="com.xyz.service" />
<context:component-scan base-package="com.xyz.dao" />
<context:component-scan base-package="com.xyz.security" />
<context:component-scan base-package="com.xyz.dto" />
<context:component-scan base-package="com.xyz.util" />
<context:component-scan base-package="com.xyz.entity" />
<tx:annotation-driven />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="transactionManager1" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="aaentityManagerFactory" />
</bean>
<bean id="transactionManager2" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="mmascentityManagerFactory" />
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="d1SourceLocal" />
<property name="persistenceUnitName" value="p1-jpa" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
</bean>
<bean id="mmascentityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="d2DataSourceLocal" />
<property name="persistenceUnitName" value="p2-jpa" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
</bean>
<!-- <bean id="dataSourceLocal" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:jboss/datasources/MySqlDS2"/>
</bean> -->
<!-- Local -->
<bean id="d1SourceLocal"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${database.driver}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.username}" />
<property name="password" value="${database.password}" />
</bean>
<bean id="d2DataSourceLocal"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${d2-database.driver}" />
<property name="url" value="${d2-database.url}" />
<property name="username" value="${d2-database.username}" />
<property name="password" value="${d2-database.password}" />
</bean>
</beans>
Here it is my service class:
public class Userservice{
#Autowired
Database2IUserDAO immDao;
#Autowired
Database1IUserDAO iaaDao;
public User saveUser(fname,address){
User u = new User(); // This points Database-1 User table.
u.setFname(fname);
u.setAddress(address);
iaaDao.save(u);
User2 u2 = new User2(); // This points Database-2 User table.
u2.setFname(fname);
u2.setAddress(address);
immDao.save(u2);
}
}
Here is my Database1IUserDAO //This is an Interface
package com.xyz.dao;
public interface Database1IUserDAO {
public Object save(Object ob);
}
Here is my Database2IUserDAO //This is an another Interface for database2
package com.xyz.dao;
public interface Database2IUserDAO {
public Object save(Object ob);
}
** And this is finally DAO class for Database-1 and Database 2**
My both DAO class extends BaseDao class, that have Save() method that we are using to insert or save.
BaseDao.java
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.transaction.annotation.Transactional;
public class BaseDAO {
protected EntityManager entityManager;
#PersistenceContext
public void setEntityManager(EntityManager entityManager) {
this. entityManager = entityManager;
}
#Transactional
public Object save(Object ob) {
Object object = entityManager.merge(ob);
return object;
}
#Transactional
public void remove(Object ob) {
Object object = entityManager.merge(ob);
entityManager.remove(object);
}
#Transactional
public int update(String query) {
return entityManager.createQuery(query).executeUpdate();
}
}
Please help.
You have to use database specific Transaction Manager as you mentioned in your spring-context.xml file as below.
<bean id="transactionManager2" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="mmascentityManagerFactory" />
</bean>
You should create a save function in your DAO Class with database specific Transaction Manager as follows:
#Transactional(value="transactionManager2")
public Object save(Object ob) {
Object object = entityManager.merge(ob);
return object;
}
I hope it will work for you.
You seem to be using the same EntityManager (EM) from the BaseDAO for all your DAOs. Since you don't specify which TransactionManager the EM is using, it will default to this one:
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
... as noted in the documentation http://docs.spring.io/spring/docs/2.0.8/reference/transaction.html (find table 9.2)
If you want to write to another database, you will need to explicity tell Spring which one you want to use. See this answer as an example:
Spring multiple #Transactional datasources
It looks you are using the same datasource for both the persistence unit.
ie java:jboss/datasources/MySqlDS2
so it is inserting into only one DB which is corresponding to above data source mstly Mysql DB.
so add different datasource in both the persistence-unit , and that should help you to insert to both the databases.
it wont give any exception because one datasource that you are using might be valid datasource(i cant guarantee as we dont have data source information in your post).
let me know for any thing else.

Categories