Spring autowire by constructor not working without setter method - spring

Here is my Spring xml config:
<beans profile="test">
<context:annotation-config />
<!-- hsqldbDataSource bean for testing purposes -->
<bean id="hsqldbDataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="shutdown">
<constructor-arg>
<bean class="com.zaxxer.hikari.HikariConfig">
<constructor-arg>
<props>
<prop key="dataSource.url">${hsqldb.url}</prop>
<prop key="dataSource.user">${user}</prop>
<prop key="dataSource.password">${password}</prop>
</props>
</constructor-arg>
<property name="dataSourceClassName" value="org.hsqldb.jdbc.JDBCDataSource" />
<property name="connectionTestQuery" value="SELECT 1" />
<property name="maximumPoolSize" value="5" />
<property name="minimumPoolSize" value="1" />
</bean>
</constructor-arg>
</bean>
<!-- execute a script to create tables after creation of bean for in-memory HSQLDB -->
<jdbc:embedded-database id="hsqldbDataSource" type="HSQL">
<jdbc:script location="classpath:schema.sql" />
<jdbc:script location="classpath:test-data.sql"/>
</jdbc:embedded-database>
<bean id="daoManager" class="com.d.DAOManager" autowire="constructor">
<property name="dataSource" ref="hsqldbDataSource"/>
</bean>
</beans>
And my DAOManager class:
public class DAOManager {
private DataSource dataSource;
private Connection connection;
#Autowired
public DAOManager(DataSource dataSource) {
this.dataSource = dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
And here I call get my daoManager bean.
public static DAOManager createHSQLDBDAOManager() {
LOG.info("Setting up datasource to in-memory HSQLDB");
ConfigurableEnvironment env = (ConfigurableEnvironment)applicationContext.getEnvironment();
env.setActiveProfiles("test");
applicationContext.load("classpath:/applicationContext.xml");
applicationContext.refresh();
DAOManager daoManager = applicationContext.getBean("daoManager", DAOManager.class);
return daoManager;
}
Why is it complaining if I remove the setter method? I don't need it. If I remove the #Autowired before the constructor (it also works) it's just useless and not using the by constructor autowire function.

Needed to remove the property value of the daoManager bean
<bean id="daoManager" class="com.d.DAOManager" autowire="constructor"/>

Related

Spring 4 + Hibernate 5: No bean named 'transactionManager' is defined

I have a problem with my project when I call a URL.
This is my applicationContext
<context:component-scan base-package="com.prova" />
<mvc:annotation-driven />
<mvc:resources mapping="/resources/**" location="/resources/" />
<bean id="dataSource"
<!-- connection to datasource -->
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.prova.model"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.id.new_generator_mappings">false</prop>
<prop key="hibernate.cache.use_second_level_cache">false</prop>
<prop key="hibernate.cache.use_query_cache">false</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate5.HibernateTransactionManager"
name ="transactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
This is my Controller
package com.prova.controller;
<!-- import -->
#Controller
public class EmployeeController {
private static final Logger logger = Logger
.getLogger(EmployeeController.class);
public EmployeeController() {
System.out.println("EmployeeController()");
}
#Autowired
private EmployeeService employeeService;
#RequestMapping(value = "/all")
public ModelAndView listEmployee(ModelAndView model) throws IOException {
List<Employee> listEmployee = employeeService.getAllEmployees();
model.addObject("listEmployee", listEmployee);
model.setViewName("home");
return model;
}
...
...
...
When I call in postman the url http://localhost:8082/prova/all I receive this error:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'transactionManager' is defined: No matching PlatformTransactionManager bean found for qualifier 'transactionManager' - neither qualifier match nor bean name match!
Please help me because I try all solutions.
Thanks!

Spring transaction does not start

Environment: Eclipse Keppler, jetty 7.5.1,
Spring 3.2.1, Hibernate 4.2.5, Oracle 11
Problem: hibernate entity saves does not apply to database physically
Cause of problem may be: no active transaction
Question: Why does not transaction start?
Note: if I change openSession() to getCurrentSession(), everything works. Transaction starts & entity saves to DB physically.
GenericDaoImpl:
#Transactional(propagation = Propagation.REQUIRED, readOnly = false,
value = "transactionManager")
public abstract class GenericDaoImpl<T, ID extends Serializable> implements GenericDao<T, ID> {
private Class<T> persistentClass;
protected SessionFactory sessionFactory;
#Override
public T addEntity(T entity) {
Session session = null;
try {
session = sessionFactory.openSession();
session.save(entity);
} catch (Exception e) {
e.printStackTrace();
} finally {
if(session != null){
Transaction t = session.getTransaction();
System.out.println("Transaction().isActive()......." + session.getTransaction().isActive());
System.out.println("before: session.isOpen() " + session.isOpen() + " trx wasCommitted " + t.wasCommitted());
session.close();
System.out.println("after: session.isOpen() " + session.isOpen() + " trx wasCommitted" + t.wasCommitted());
}
}
return entity;
}
UserDaoImpl extending GenericDaoImpl:
#Component
#Scope("prototype")
#Transactional(propagation = Propagation.REQUIRED, readOnly = false, value = "transactionManager")
public class UserDaoImpl extends GenericDaoImpl<User, Long> implements UserDao {
.
.
}
After following code executed called:
userDao.addEntity(user);
logs printed below:
Transaction().isActive().......false
before: session.isOpen() true trx wasCommitted false
after: session.isOpen() false trx wasCommittedfalse
transaction logs:
[2016-07-15 10:42:04,567][DEBUG] Adding transactional method 'addEntity' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; 'transactionManager'
databaseContext.xml:
<bean class="com.blabla.dao.local.implementations.UserDaoImpl"
scope="prototype" name="userDao">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven />
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan"
value="com.blabla.model.local,com.blabla.model.authorization, com.blabla.model.authentication" />
<property name="entityInterceptor">
<bean class="com.blabla.listeners.EntityInterceptor" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.transaction.flush_before_completion">true</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</prop>
<prop key="hibernate.connection.driver_class">${jdbc.driver}</prop>
<prop key="hibernate.connection.url">${jdbc.url}</prop>
<prop key="hibernate.connection.username">${jdbc.user}</prop>
<prop key="hibernate.connection.password">${jdbc.password}</prop>
</props>
</property>
</bean>
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
<property name="initialSize" value="5" />
<property name="maxActive" value="10" />
</bean>
In your example it's pretty much obvious that spring handles hibernate session and transaction:
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
So you cannot use this:
session = sessionFactory.openSession();
Because you are opening new hibernate session and spring does not know nothing about this.
Using: sessionFactory.getCurrentSession() means that spring will handle everything behind the scene with your proper configuration.

From TransactionProxyFactoryBean to a Declarative transaction management?

I want to migrate from old style of transaction management with TransactionProxyFactoryBean to a Declarative transaction management recommended by spring.
So that will be possible to avoid exceptions with transactions that appear from time to time.
This is my configuration xml file:
<beans xmlns=...>
<context:annotation-config/>
<context:component-scan base-package="prof" />
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation">
<value>WEB-INF/classes/hibernate.cfg.xml</value>
</property>
</bean>
<import resource="prof-dao-spring.xml" />
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
...
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
<bean id="ProfileService" parent="baseTransactionProxy">
<property name="target">
<bean class="tv.clever.hibernate.service.ProfileService"></bean>
</property>
</bean>
</beans>
ProfileService looks like:
#Component
public class ProfileService {
#Autowired
#Qualifier("baseDAO")
protected BaseDAO baseDAO;
private static ProfileService profileService;
public ProfileService() {
setProfileService(this);
}
public void setProfileService(ProfileService ps) {
profileService = ps;
}
public void save(final Collection transientObjects) {
baseDAO.save(transientObjects);
}
...
}
From where do I need to start?
Assuming you want to use annotations slap a #Transactional on your service class, add <tx:annotation-driven /> to your configuration and remove the TransactionalProxyFactoryBean declaration and all beans using that as a parent.
Additional pro-tips:
Use #Service for service classes and #Repository for daos
<context:annotation-config /> is implied by <context:component-scan />
Your service
#Service
#Transactional
public class ProfileService { ... }
Configuration
<beans xmlns=...>
<context:component-scan base-package="prof" />
<import resource="prof-dao-spring.xml" />
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation">
<value>WEB-INF/classes/hibernate.cfg.xml</value>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<tx:annotation-driven />
</beans>
Restart application.

EntityManager not injected from factory

I'm using JPA/Hibernate to build a web app. I'm using a LocalContainerEntityManagerFactoryBean with <property name="packagesToScan" value="<pkg>" /> to build my entities from a java package, and a jdbc.datasource.DriverManagerDataSource configured for PostgreSQL, so I don't have a defined persistence context.
Can I build an EntityManager with these constraints, using either Spring annotations or xml?
EDIT:
I'm using a code of the following form to get a user data for login. In the Spring Security context the EntityManager is always null.
#Repository
public class UserDao implements UserDetailsService {
#PersistenceContext
private EntityManager entityManager; // With getter and setter
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
// Used by spring-security, here entityManager is null
}
}
EDIT2: Added context configuration
<context:spring-configured />
<context:annotation-config />
<context:component-scan base-package="<BasePackage>" />
EDIT3: Added entity manager factory config:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="default_unit" />
<property name="dataSource" ref="dataSource" />
<property name="persistenceProviderClass" value="org.hibernate.ejb.HibernatePersistence"></property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="databasePlatform" value="org.hibernate.dialect.PostgreSQLDialect" />
</bean>
</property>
<property name="packagesToScan" value="<package>" />
<property name="jpaProperties">
<value>
hibernate.show_sql=true
hibernate.format_sql=true
hibernate.hbm2ddl.auto=create-drop
hibernate.hbm2ddl.import_files=/loaded-on-startup/import.sql
<!-- ALSO CHECK IMPORT.SQL -->
</value>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
/// CONNECTION CONFIG ///
</bean>
I also have added default-autowire="byType" to my beans tag and autowire="byType" to the security authentication bean definition.
Yes. Take a look here . You need to provide a datasource and use LocalContainerEntityManagerFactoryBean bean
Edit
It may be because of no transaction available.Read here

how to get transaction supporting proxy from spring application context?

i need to use bean from spring application context not in a spring managed bean, so i do next: annotate bean with #Service annotation, so instance of bean created during spring loading.
<bean id="customRevisionListener" class="ru.csbi.registry.services.impl.envers.CustomRevisionListener" />
This instance is ApplicationContextAware, so application context is injected in this bean instance and i save it to static variable:
#Service
public class CustomRevisionListener implements EntityTrackingRevisionListener, ApplicationContextAware {
private static ApplicationContext applicationContext;
private ModelInformationService modelInformationService;
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
CustomRevisionListener.applicationContext = applicationContext;
}
private ModelInformationService getModelInformationService() {
if (modelInformationService == null) {
modelInformationService = applicationContext.getBean(ModelInformationService.class);
}
// TransactionProxyFactoryBean
return modelInformationService;
}
After that another instance of CustomRevisionListener created in not spring context(hibernate envers context). Here i use static variable to receive spring applicationContext
after that i'm getting beans from application context:
private ModelInformationService getModelInformationService() {
if (modelInformationService == null) {
modelInformationService = applicationContext.getBean(ModelInformationService.class);
}
the problem is that this bean has all #Autowired properties injected correctly:
#Service
public class ModelInformationServiceImpl implements ModelInformationService {
#Autowired
private EntityChangeService entityChangeService; // injected correctly
#Autowired
private PropertyService propertyService; // injected correctly
#Autowired
private ru.csbi.registry.services.reflection.HibernateDomainService hibernateService; // injected correctly
, but they are simple instances of java classes not Proxies supporting #Transactional annotation, which they are for my regular spring code:
getModelInformationService().getClass().getName() is "ru.csbi.registry.services.impl.envers.ModelInformationServiceImpl"
and must be something like
$Proxy71
How to get transaction supporting proxies, which spring genereates for example when injecting beans in #Controller, in bean not managed by spring?
i'm using next spring config:
<bean id="dataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
<constructor-arg ref="lazyConnectionDataSourceProxy"/>
</bean>
<bean id="lazyConnectionDataSourceProxy" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
<property name="targetDataSource">
<ref local="dataSourceTarget" />
</property>
</bean>
<bean id="dataSourceTarget" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${ds.driver}" />
<property name="url" value="${ds.url}" />
<property name="username" value="${ds.user}" />
<property name="password" value="${ds.password}" />
<property name="initialSize" value="${ds.initialSize}" />
<property name="maxActive" value="${ds.maxActive}" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<!--property name="entityInterceptor">
<bean class="ru.csbi.registry.utils.audit.AuditLogInterceptor">
<property name="sessionFactory" ref="auditSessionFactory" />
</bean>
</property-->
<property name="dataSource" ref="dataSource" />
<property name="lobHandler" ref="oracleLobHandler" />
<property name="packagesToScan" value="ru.csbi.registry.domain" />
<property name="hibernateProperties">
<bean id="hibernatePropertiesFactoryBean" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>file:${realtyregistry.settings.path}/hibernate-config.properties</value>
</list>
</property>
</bean>
</property>
<property name="eventListeners">
<map>
<entry key="post-insert" value-ref="auditEventListener" />
<entry key="post-update" value-ref="auditEventListener" />
<entry key="post-delete" value-ref="auditEventListener" />
<entry key="pre-collection-update" value-ref="auditEventListener" />
<entry key="pre-collection-remove" value-ref="auditEventListener" />
<entry key="post-collection-recreate" value-ref="auditEventListener" />
</map>
</property>
</bean>
<bean id="auditEventListener" class="org.hibernate.envers.event.AuditEventListener" />
<bean id="persistenceManagerHibernate" class="ru.csbi.registry.utils.PersistenceManagerHibernate">
<property name="sessionFactory" ref="sessionFactory" />
</bean>

Resources