Bean property 'persistenceManagerFactory' is not writable or has an invalid setter method - spring

I am running maven jdo project. And i want to use annotational transactions so i have set my dispatcher according to this but i am getting this error following error.
org.springframework.beans.factory.BeanCreationException: Error creating
bean with name 'myController': Injection of autowired dependencies
failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire field: private com.titas.dao.UserDAO
com.titas.controller.MyController.userDAO; nested exception is
org.springframework.beans.factory.BeanCreationException: Error creating
bean with name 'userDAO' defined in ServletContext resource [/WEB-
INF/dispatcher-servlet.xml]: Error setting property values; nested
exception is org.springframework.beans.NotWritablePropertyException:
Invalid property 'persistenceManagerFactory' of bean class
[com.titas.dao.UserDAOImpl]: Bean property 'persistenceManagerFactory'
is not writable or has an invalid setter method. Does the parameter type
of the setter match the return type of the getter?
My dispatcher.xml is:
<!-- declare mvc to be annotation driven -->
<mvc:annotation-driven/>
<!-- provide Your Base package to scan annotations for components -->
<context:component-scan base-package="com.titas.controller"></context:component-scan>
<mvc:resources location="/resources/" mapping="/resources/**"/>
<!-- enable the configuration of transactional behavior based on annotations-->
<tx:annotation-driven transaction-manager="txManager"/>
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>
<!--
Most controllers will use the ControllerClassNameHandlerMapping above, but
for the index controller we are using ParameterizableViewController, so we must
define an explicit mapping for it.
-->
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="index">indexController</prop>
</props>
</property>
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/"
p:suffix=".jsp" />
<!--The index controller.-->
<bean name="indexController"
class="org.springframework.web.servlet.mvc.ParameterizableViewController"
p:viewName="index" />
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://localhost:3306/login"
p:username="root"
p:password="" />
<!-- PMF Bean -->
<bean id="myPmf" class="org.springframework.orm.jdo.LocalPersistenceManagerFactoryBean">
<property name="jdoPropertyMap">
<props>
<prop key="javax.jdo.PersistenceManagerFactoryClass">org.datanucleus.api.jdo.JDOPersistenceManagerFactory</prop>
<prop key="javax.jdo.option.ConnectionDriverName">com.mysql.jdbc.Driver</prop>
<prop key="javax.jdo.option.ConnectionURL">jdbc:mysql://localhost:3306/login</prop>
<prop key="javax.jdo.option.ConnectionUserName">root</prop>
<prop key="javax.jdo.option.NontransactionalRead">true</prop>
<prop key="javax.jdo.option.RetainValues">false</prop>
<prop key="javax.jdo.option.DetachAllOnCommit">true</prop>
<prop key="javax.jdo.option.Multithreaded">true</prop>
<prop key="datanucleus.appengine.ignorableMetaDataBehavior">NONE</prop>
</props>
</property>
</bean>
<bean id="pmfProxy" class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy">
<property name="targetPersistenceManagerFactory" ref="myPmf"/>
<property name="allowCreate" value="false"/>
</bean>
<bean id="txManager" class="org.springframework.orm.jdo.JdoTransactionManager">
<property name="dataSource" ref="dataSource"/>
<property name="persistenceManagerFactory" ref="pmfProxy"/>
</bean>
<bean id="userDAO" class="com.titas.dao.UserDAOImpl" >
<property name="persistenceManagerFactory" ref="pmfProxy"/>
</bean>
UserDAOImpl.java
#Repository
public class UserDAOImpl implements UserDAO{
static Logger log = Logger.getLogger(UserDAOImpl.class.getName());
#Autowired
#Qualifier("dataSource")
private DataSource dataSource;
#Autowired
#Qualifier("myPmf")
private PersistenceManagerFactory persistenceManagerFactory;
HttpServletRequest request;
#Override
#Transactional
public User getUser(String user_name, String user_password) {
PersistenceManager pm = this.persistenceManagerFactory.getPersistenceManager();
try {
User user=new User();
pm.makePersistent(user);
Query query = pm.newQuery(User.class, "this.userName == userNameParam && this.userPassword==userPasswordParam");
query.setFilter("this.userName == userNameParam && this.userPassword==userPasswordParam");
query.declareParameters("String lastNameParam, String userPasswordParam");
log.info("hereeee 5");
log.info("hereeee again 5");
user = (User)query.execute(user_name,user_password);
log.info("hereeee 6");
log.info("hereeee again 6");
log.info(user.getUserEmail()+"..........."+user.getUserProfileName());
return user;
}
finally {
pm.close();
}
}
MyController.java
#Controller
//#RequestMapping(value = "/test")
public class MyController{
static Logger log = Logger.getLogger(MyController.class.getName());
#Autowired
private UserDAO userDAO;
List<User> allUser = new ArrayList<User>();
May i know where i need to change.
Thanks in advance.

Your bean definition is:
<bean id="userDAO" class="com.titas.dao.UserDAOImpl" >
<property name="persistenceManagerFactory" ref="pmfProxy"/>
</bean>
In your UserDaoImpl you havent defined a method called setPersistenceManagerFactory which Spring is complaining about.
By above bean definition, Spring is going to inject factory object within user dao via setter method which is not present and hence you see exception.
So instead of:
#Qualifier("myPmf")
You should use bean name for proxy factory object (although i don't see problem using myPmf, it's just what you tries to inject property using <property name="persistenceManagerFactory" ref="pmfProxy"/> in userDao bean and hence this suggestion and you could ignore this) like:
#Qualifier("pmfProxy")
And remove the line which tries to inject property when you say autowired:
<bean id="userDAO" class="com.titas.dao.UserDAOImpl" />
from your bean definition for userDAO as Spring is going to inject it for you.
If you want to manually specify the dependency and inject it via setter then you would need to define setter method like:
.. setPersistenceManagerFactory(..) {
....
}

Related

Spring Bean is not writable or has an invalid setter method

I'm experimenting with Spring, I'm following the book: Spring: A developer's notebook. I'm getting this error:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'validateFile' defined in class path resource [batch-config.xml]: Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'customersDAO' of bean class [com.emp.ValidateCustomer]: Bean property 'customersDAO' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
Below is my batch-config.xml:-
<bean id="validateFile" class="com.emp.ValidateCustomer" >
<property name="customersDAO">
<bean class="com.emp.dao.CustomerDao">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
</property>
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="customerdb"/>
<property name="packagesToScan" value="com.emp" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.cglib.use_reflection_optimizer">false</prop>
<prop key="hibernate.jdbc.batch_size">50</prop>
<prop key="hibernate.default_batch_fetch_size">50</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.use_sql_comments">false</prop>
<prop key="hibernate.generate_statistics">false</prop>
<prop key="hibernate.format_sql">false</prop>
<prop key="hibernate.hbm2ddl.auto">false</prop>
<prop key="hibernate.enable_lazy_load_no_trans">true</prop>
</props>
</property>
</bean>
</bean>
Below is CustomersDao.java:-
#Repository
public class CustomersDao {
#SuppressWarnings("deprecation")
private HibernateTemplate hibernateTemplate=null;
#Autowired
#Qualifier("sessionFactory")
public void setSessionFactory(SessionFactory sessionFactory) {
hibernateTemplate = new HibernateTemplate(sessionFactory);
}
}
And in ValidateCustomer.java:-
#Autowired
private CustomersDao customersDAO;
Please help.
As #MarcosBarbero says, without seeing more of ValidateCustomer.java, it's impossible to be definitive about the problem.
What annotations are on the ValidateCustomer class? I have no problem with Autowired for a private property when the enclosing class is a component or service. If it's not, then do you have a public setter? The property is not public, if the setter is not public, Spring won't be able to set it.

Spring Hibernate "No Current Transaction" for getCurrentSession method

I am using the Spring configuration to test Spring-Hibernate Transactions.
<beans ...>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- hibernate 4 onwards annotationsessionfactorybean is replaced with localsessionfactory bean -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.fg.arch.test.transaction.Foo</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
<!-- <prop key="hibernate.current_session_context_class">org.hibernate.context.internal.ThreadLocalSessionContext</prop> -->
</props>
</property>
</bean>
</beans>
My service layer is annotated with #Transactional.
This is my DAO:
public class FooHibernateDaoImpl implements FooDao {
private SessionFactory sessionFactory;
public void testFoo(Foo foo) throws Throwable {
System.out.println(" --- ");
sessionFactory.openSession().save(foo);
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
}
Explicitly opening the session using the openSession() method does not cause a problem however when I change to getCurrentSession() I am getting an exception.
I have two questions.
Is it good practice to call openSession() in every DAO method.
How can I make getCurrentSession() work so that it will not give me an exception like no active transaction present ?
Thanks.
To answer your questions:
No, its not. The #Transactional annotation that should be on your service class method calling testFoo() is opening the session for you. You should use getCurrentSession() in the DAO to get this session.
You can, but you shouldn't. That's the entire point of using the Hibernate SessionFactory with annotation based transaction management. As long as you are marking your service methods transactional, you shouldn't have a problem.
As a side note, why are you not Autowiring your SessionFactory? Don't use setters to set something that should be Autowired. Otherwise you may as well not use Spring.

Spring + #Transactional: can't rollback in case of error

I am trying to implement the following: I need to add two different entities in same same transaction to database.
I have different DAO classes and Service classes for each entity.
public class InvoicesDAO {
#Autowired
protected SessionFactory sessionFactory;
public void save(Invoice object) {
Session session = SessionFactoryUtils.getSession(sessionFactory, false);
session.persist(object);
}
}
public class RequestsDAO {
#Autowired
protected SessionFactory sessionFactory;
public void save(Request object) {
Session session = SessionFactoryUtils.getSession(sessionFactory, false);
session.persist(object);
}
}
public class InvoicesService {
#Autowired
private InvoicesDAO invoicesDAO;
#Autowired
private RequestsDAO requestsDAO;
#Transactional
public void add(Invoice object) throws HibernateException {
invoicesDAO.save(object);
}
#Transactional
public void updateAndGenerate(Invoice object1, Request object2) throws HibernateException {
invoicesDAO.save(object1);
requestsDAO.save(object2);
}
}
The config:
<tx:annotation-driven transaction-manager="transactionManager" />
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:/hibernate.properties" />
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${hibernate.connection.driver_class}" />
<property name="url" value="${hibernate.connection.url}" />
<property name="username" value="${hibernate.connection.username}" />
<property name="password" value="${hibernate.connection.password}" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.ejl.butler.object.data" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
<prop key="hibernate.cache.region.factory_class">${hibernate.cache.region.factory_class}</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<context:annotation-config />
<context:component-scan base-package="com.service" />
<bean id="invoicesDao" class="com.dao.InvoicesDAO" />
<bean id="requestsDao" class="com.dao.RequestsDAO" />
Controller:
//***
/**
* Invoices access service
*/
#Autowired
private InvoicesService invoicesService;
// objects creation
invoicesService.updateAndGenerate(invoice, request);
//***
So when I am trying to call updateAndGenerate method and pass there invalid values for object2 - it fails without rolling back the object1. How can I fix it? Thank you
I dont think it is got to do with Proxies. You dont need a proxy object here. Generally you need a proxy object for instances such for a login service etc where you need a proxy object for the singleton bean definition. But, the only way it can not rollback is if your propogation level on the Transaction isnt correct.
If you use a Trasaction.REQUIRES_NEW then the dao.save wouldnt rollback and it wouldnt tie back to the outer transaction and hence wouldnt rollback.
Finally I figured out where the problem was so I will answer my own question...
According to Declarative transactions (#Transactional) doesn't work with #Repository in Spring and https://stackoverflow.com/a/3250959/705869 the order of the base-package items inside context:component-scan directive is very important. In additional, you should put only really necessary packages.
I had some duplicates inside this directive so the application context was initialized before database context. And that's why transactions were disabled inside services!
So check twice for base-package packages inside context:component-scan and remove unnecessary ones.

Is it possible to read a combination of a System Property and a Customized Property in Spring config file?

I need to know if its possible in Spring to derive a value for a Property by combination of a System-Property and a Customized-Property defined over a PropertyFile.
What I've done:
1) Configured a -D argument in server as : -Dapp.Env="dev"
2) In my spring-config.xml, defined datasource details as below:
<!-- DataSource configurations -->
<bean id="myDataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean"
init-method="init" destroy-method="close">
<property name="uniqueResourceName" value="myDataSource" />
<property name="xaDataSourceClassName" value="${my.database.xaDriver.class}" />
<property name="xaProperties">
<props>
<prop key="URL">#{systemProperties['appEnv']}.${my.database.jdbcUrl}</prop>
<prop key="user">#{systemProperties['appEnv']}.${my.database.user}</prop>
<prop key="password">#{systemProperties['appEnv']}.${my.database.password}</prop>
</props>
</property>
<property name="maxPoolSize" value="${my.database.maxPoolSize}" />
<property name="minPoolSize" value="${my.database.minPoolSize}" />
<property name="borrowConnectionTimeout" value="60" />
<property name="maintenanceInterval" value="120" />
</bean>
3) Defined the following properties in my .properties file:
my.database.xaDriver.class=oracle.jdbc.xa.client.OracleXADataSource
my.database.initialPoolSize=2
my.database.maxPoolSize=10
my.database.minPoolSize=2
dev.my.database.jdbcUrl=jdbc:oracle:thin:#test.com:1535:myDb
dev.my.database.user=myuserid
dev.my.database.password=mypwd
4) Defined .properties file location in the spring-config.xml as :
<context:property-placeholder location="/WEB-INF/spring/spring-config.properties" />
What I get on start of server :
Throwable occurred: org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'myDataSource' defined in ServletContext resource [/WEB-INF/spring/spring-config.xml]: Could not resolve placeholder 'my.database.jdbcUrl' in string value "#{systemProperties['appEnv']}.${my.database.jdbcUrl}"
What I also tried :
5) Defined a property in .properties file as below:
app.Env=dev
6) Modified the datasource bean configuration as below:
<prop key="URL">${app.Env}.${my.database.jdbcUrl}</prop>
<prop key="user">${app.Env}.${my.database.user}</prop>
<prop key="password">${app.Env}.${my.database.password}</prop>
However on start of server, I get same exception message :
Throwable occurred: org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'myDataSource' defined in ServletContext resource [/WEB-INF/spring/spring-config.xml]: Could not resolve placeholder 'my.database.jdbcUrl' in string value "${app.Env}.${my.database.jdbcUrl}"
Can someone help me out in pointing out what mistake I might be doing and what is/are the possible fix for this issue ?
1) You can read system properties into Spring bean:
<bean id="systemProperties" class="java.lang.System" factory-method="getProperties"/>
and then use multiple property resolvers
2) You can use flag systemPropertiesMode of PropertyPlaceholderConfigurer
3) You can write your custom bean factory that would produce single java.util.Properties object from system properties and file properties.
That bean would have method
public Properties merge() {
Properties merged = new Properties();
for (Properties p : properties) {
if (p != null) {
merged.putAll(p);
}
}
return merged;
}
Invoked in spring like that:
<bean id="factory" class="my.Factory">
<property name="properties">
<util:list>
<bean class="java.lang.System" factory-method="getProperties"/>
<bean ref="otherProperties">
</util:list>
</property>
</bean>

java.lang.IllegalArgumentException: 'sessionFactory' or 'hibernateTemplate' is required in spring+hibernate

I am doing spring + hibernate apllication. When I run the application on tomcat server I am getting some exception. Below is my code.
This is my bean config 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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>WEB-INF/database/db.properties</value>
</property>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value>Employee.hbm.xml</value>
</list>
</property>
</bean>
<bean id="employeeBo" class="com.saggezza.employee.bo.impl.EmployeeBoImpl">
<property name="employeeDao" ref="employeeDao" />
</bean>
<bean id="employeeDao" class="com.saggezza.employee.dao.impl.EmployeeDaoImpl">
<constructor-arg ref="sessionFactory"></constructor-arg>
</bean>
this is my dao class.
public class EmployeeDaoImpl extends HibernateDaoSupport implements EmployeeDao {
private SessionFactory sessionFactory;
public EmployeeDaoImpl(SessionFactory sessionfactory){
this.sessionFactory=sessionfactory;
}
#Override
public List<Employee> getEmployeeDetails() {
return getHibernateTemplate().find("from Employee");
}
}
Here another class employeeBo is calling the employeeDaoImpl.
when I run thisI am getting the below exception.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'employeeBo' defined in ServletContext resource [/WEB-INF/spring/EmployeeBean.xml]: Cannot resolve reference to bean 'employeeDao' while setting bean property 'employeeDao'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'employeeDao' defined in ServletContext resource [/WEB-INF/spring/EmployeeBean.xml]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: 'sessionFactory' or 'hibernateTemplate' is required
Can anybody help to resolve this. I have tried a lot and google it as well.But did get the solution.
If you have two configuration files, you duplicates 'sessionFactory' definition. Remove one of the 'sessionFactory' definitions . You would have got duplicate bean definition exception before the IllegalArgumentException.
Edit: After your comment,
public class EmployeeDaoImpl extends HibernateDaoSupport implements EmployeeDao {
public EmployeeDaoImpl(SessionFactory sessionfactory){
setSessionFactory(sessionfactory);
}
#Override
public List<Employee> getEmployeeDetails() {
return getHibernateTemplate().find("from Employee");
}
}
or get rid of constructor in above code and inject 'sessionFactory' using setter injection.See org.springframework.orm.hibernate3.support.HibernateDaoSupport.setSessionFactory(SessionFactory). I prefer later approach.
I think the problem is the type of SessionFactory you are injecting in EmployeeDaoImpl does not match with the type of the SessionFactory you used in the class.
Can you check it?
This is an old question so must be solved now but still if someone comes across this problem. Following is solution.
You can use Hibernate DAO Support by extending HibernateDAOSupport class and overriding its afterPropertiesSet() method.
This method is called in HibernateDAO support and at that time since sessionFactory is null it is throwing this error. In your custom class you can set this property explicitly and then call the same method of Parent Class (i.e. HibernateDAOSupport's addProperties() method)
package com.techcielo.spring4.hibernate.template;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.stereotype.Component;
#Component("hibernateTemplate")
public class Hibernate4CustomTemplate extends HibernateTemplate{
#Autowired(required=true)
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
System.out.println("Setting SessionFactory");
this.sessionFactory = sessionFactory;
super.setSessionFactory(sessionFactory);
}
#Override
public void afterPropertiesSet() {
System.out.println("Checking if properties set..."+this.sessionFactory);
setSessionFactory(sessionFactory);
super.afterPropertiesSet();
}
}
Following can be used for sample!
I had the same problem and fix it by using Autowired constructor with EntityManagerFactory. Keyur answer is correct
#Service
class EmployeeDaoImpl #Autowired constructor(
factory: EntityManagerFactory
) : HibernateDaoSupport(), EmployeeDao {
init {
if (factory.unwrap(SessionFactory::class.java) == null) {
throw NullPointerException("factory is not a hibernate factory")
}
setSessionFactory(factory.unwrap(SessionFactory::class.java))
}
...
}

Resources