I'm trying to integrate Mybatis with spring. Here you can see my application context of Spring
<context:annotation-config />
<context:component-scan base-package="com" />
<tx:annotation-driven />
<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/DB" />
<property name="username" value="root" />
<property name="password" value="" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:/com/mybatis/mybatis-config.xml" />
<!--<property name="transactionFactory" ref="springManagedTransactionFactory" />-->
</bean>
<!--
<bean id="springManagedTransactionFactory" class="org.mybatis.spring.transaction.SpringManagedTransactionFactory">
<constructor-arg index="0" ref="dataSource" />
</bean> -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="registroClimaMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.mybatis.dao.RegistroClimaMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
First of all I have commented springManagedTransactionFactory in XML because it's giving me an exception
Error creating bean with name 'springManagedTransactionFactory' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Could not resolve matching constructor (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)
Here is my interface RegistroClimaMapper. I do not have any annotation here because I have defined the context:component scan.
public interface RegistroClimaMapper {
void insertarRegistroClima(RegistroClima registro) throws SQLException;
List<RegistroClima> getRegistrosClima() throws SQLException;
List<RegistroClima> getRegistrosClima(#Param("Validado") boolean Validado) throws SQLException;
}
I try to use this interface in a ManagedBean and when I'm going to use registroClimaPersistence inside a method of TablaRegistroClimaBean I get a NullPointerException
#ManagedBean(name = "tablaRegClimaBean")
#ViewScoped
public class TablaRegistroClimaBean implements Serializable {
#Autowired
private RegistroClimaMapper registroClimaPersistence;
public void setRegistroClimaPersistence(RegistroClimaMapper registroClimaPersistence) {
this.registroClimaPersistence = registroClimaPersistence;
}
}
As seen here: http://javadox.com/org.mybatis/mybatis-spring/1.1.1/org/mybatis/spring/transaction/SpringManagedTransactionFactory.html#SpringManagedTransactionFactory%28%29, SpringManagedTransactionFactory has a default constructor, but none that takes a datasource. You need to pass the datasource to the newTransaction() method, but not to the constructor: http://javadox.com/org.mybatis/mybatis-spring/1.1.1/org/mybatis/spring/transaction/SpringManagedTransactionFactory.html#newTransaction(javax.sql.DataSource,%20org.apache.ibatis.session.TransactionIsolationLevel,%20boolean)
Change the piece of code to
<bean id="springManagedTransactionFactory" class="org.mybatis.spring.transaction.SpringManagedTransactionFactory">
<!--<constructor-arg index="0" ref="dataSource" />-->
</bean>
or completely remove the constructor-arg.
What NullPointerException do you get? It might come from you just defining the RegistroClimaMapper interface, but not implementing this interface in any bean. Please add a Bean that implements this interface and the Autowired annotation should work.
Related
I am running a spring application with xml configuration. I have defined two beans in the application-configuration.xml followed as
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="myDataSource"></property>
</bean>
<bean id="myDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="url" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
</bean>
and I am trying to get the bean simply as
public class SQLDbService {
#Autowired
JdbcTemplate jdbcTemplate;
public void someMethod()
{
jdbcTemplate.execute();
}
}
but the jdbcTemplate field is always null.
The application starts from another class
public static void main(String[] args) throws InterruptedException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application-configuration.xml");
}
I tried adding
<context:annotation-config/>
to application configuration.
I would like to know if an annotation-based autowiring is possible at this point, if so, what I am missing?
<bean id="sQLDbService" class="path.to.your.package.SQLDbService">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
Closed 7 years ago.
I am unable to inject my DAO class in Spring MVC:
This is my DAO class:
package com.pankaj.bookslibrary.dao;
#Component
public class BooksLibraryDAO
{
#PersistenceContext
private EntityManager em;
public void saveBook(Book book)
{
em.persist(book);
}
}
This is my BO class which calls DAO:
package com.pankaj.bookslibrary.controller;
#Service
public class BooksLibraryBO
{
#Autowired
private BooksLibraryDAO booksLibraryDAO;
public void saveBook(Book book)
{
booksLibraryDAO.saveBook(book);
}
The above line gives NullPointerException as booksLibraryDAO is null.
Here are the relevant lines from my dispatcherServlet config file:
<beans xmlns=...3.0.xsd">
<context:component-scan base-package="com.pankaj.bookslibrary" />
<context:annotation-config/>
<bean id="dataSource"....</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />
<property name="persistenceUnitName" value="BooksLibrary_PersistenceUnit" />
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
<property name="showSql" value="false" />
<property name="generateDdl" value="true" />
</bean>
</property>
</bean>
<bean id="transactionManagerNonJTA" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="defaultTimeout" value="1800"></property>
</bean>
<tx:annotation-driven transaction-manager="transactionManagerNonJTA" />
I am not sure what I have missed.
This is how I am making a call from the controller:
BooksLibraryBO bo = new BooksLibraryBO();
bo.saveBook(book);
The packages the classes are in differs from the package you scan for annotations. Add the packages to the list of base-packages to scan for!
As M.Deinum explained, you are creating the BooksLibraryBO yourself, spring do not know that instances and will not process the annotations.
I am looking using #Transactional on one of the Service methods. However when an exception occurs, the transaction is not getting rolled back. I tried the same with #Transactional(rollbackFor=Exception.class). My code as follows:-
#Override
#Transactional(rollbackFor=Throwable.class)
public boolean addUser(User user) throws Exception{
boolean userAdded = userDao.addUser(user);
boolean userRegistrationRecorded = userDao.recordUserRegistraionDetails(user);
return true;
}
I read lot of posts and every one says that Spring handles only RuntimeExceptions and not checked Exceptions other than RmiException. I need a solution that works for any kind of Exception. Some one suggested me to write own annotation, where as others suggested of having a TransactionManager as part of applicationContext.xml file. A detailed solution will definitely help me.
By the way I am using Spring JdbcTemplate. The strange thing I observe is though the Exceptions raised by Spring are RuntimeExceptions the transaction is not getting rolled back. I am trying to raise an Exception by adding the same User in the above scenario.
My applicationContext.xml is as follows:-
<context:component-scan base-package="org.chaperone.services.security.*" />
<context:annotation-config />
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="propertyPlaceholderConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="searchSystemEnvironment" value="true" />
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="${DATABASE_URL}" />
<property name="username" value="${DATABASE_USER_NAME}" />
<property name="password" value="${DATABASE_PASSWORD}" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
The ease-of-use afforded by the use of the #Transactional annotation is best illustrated in this link
you have to add :
<tx:annotation-driven transaction-manager="transactionManager" />
I am facing a weird issue when I'm trying to inject beans,
I'm always getting this stack trace:
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'transactionManager' defined in class
path resource [applicationContext.xml]: Error setting property values;
nested exception is
org.springframework.beans.NotWritablePropertyException: Invalid
property 'entityInterceptor' of bean class
[org.springframework.orm.hibernate4.HibernateTransactionManager]: Bean
property 'entityInterceptor' is not writable or has an invalid setter
method. Does the parameter type of the setter match the return type of
the getter?
When I try to do this :
<bean id="transactionManager"class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
<property name="entityInterceptor" ref="auditInterceptor" />
</bean>
I did check org.springframework.orm.hibernate4.HibernateTransactionManager and it sure does has the setter for entityInterceptor and my auditInterceptor extends EmptyInterceptor which implements the methods.
I am not able to get what I am doing wrong in here?
I googled for various ways to create an interceptor for spring+hibernate 4 configuration, I don't want to use envers and I don't want to do this programmatically.
Please make sure you have added right version of Spring jar file it should be greater than version 3.2.1
Note the configuration below:
applicationContext.xml
<bean name="auditInterceptor" class="com.mypackage.AuditInterceptor" />
<bean id="myDatasource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.mydbDriverClassName}"/>
<property name="jdbcUrl" value="${jdbc.mydbUrl}"/>
<property name="user" value="${jdbc.mydbUsername}"/>
<property name="password" value="${jdbc.mydbPassword}"/>
<!-- Common properties for all DS -->
<property name="initialPoolSize" value="${jdbc.initialPoolSize}"/>
<property name="maxPoolSize" value="${jdbc.maxPoolSize}"/>
<property name="minPoolSize" value="${jdbc.minPoolSize}"/>
<property name="acquireIncrement" value="${jdbc.acquireIncrement}"/>
<property name="acquireRetryAttempts" value="${jdbc.acquireRetryAttempts}"/>
<property name="preferredTestQuery" value="${jdbc.preferredTestQuery}"/>
<property name="idleConnectionTestPeriod" value="${jdbc.idleConnectionTestPeriod}"/>
</bean>
<bean id="mySessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="myDatasource"/>
<property name="configurationClass">
<value>org.hibernate.cfg.AnnotationConfiguration</value>
</property>
<property name="packagesToScan" value="com.mypackage" />
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="mySessionFactory"/>
<property name="entityInterceptor" ref="auditInterceptor" />
</bean>
Interceptor Class
package com.mypackage;
public class AuditInterceptor extends EmptyInterceptor {
#Override
public boolean onFlushDirty(Object entity, Serializable id,
Object[] currentState, Object[] previousState,
String[] propertyNames, Type[] types) {
//method body
}
#Override
public boolean onSave(Object entity, Serializable id, Object[] state,
String[] propertyNames, Type[] types) {
//method body
}
}
hope this will solve your problem
i have a simple question. Its possible to add dependency injection via #Ressource or #Autowired to the Hibernate Eventlistener?
I will show you my entitymanagerfactory configuration:
<bean id="entityManagerFactory" class="org.hibernate.ejb.EntityManagerFactoryImpl">
<qualifier value="entityManagerFactory" />
<constructor-arg>
<bean
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitManager">
<bean
class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManagerr">
<property name="defaultDataSource" ref="dataSource" />
</bean>
</property>
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="mis" />
<property name="persistenceProviderClass" value="org.hibernate.ejb.HibernatePersistence" />
<property name="jpaProperties" ref="jpa.properties" />
<property name="jpaDialect" ref="jpaDialect" />
<property name="jpaVendorAdapter">
<bean
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="true" />
<property name="database">
<util:constant
static-field="org.springframework.orm.jpa.vendor.Database.POSTGRESQL" />
</property>
<property name="showSql" value="true" />
</bean>
</property>
</bean>
</constructor-arg>
</bean>
At the moment i register my listener via jpa.properties,
hibernate.ejb.event.load=com.example.hibernate.events.LoadEvent
but in this case i have no spring injection in my listener. I found a solution, but this use the sessionFactory and not the entitymanager oder can i modifiy the sessionfactory in my context? Hopefully someone have a nice idea or solutionhow to deal with this problematic!
Big thanks!
If you used SessionFactory, this would be the configuration:
<bean id="mySessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<!-- Stripped other stuff -->
<property name="eventListeners">
<map>
<entry key="pre-load">
<bean class="com.mycompany.MyCustomHibernateEventListener1" />
</entry>
<entry key="pre-persist">
<bean class="com.mycompany.MyCustomHibernateEventListener2" />
</entry>
</map>
</property>
</bean>
But since you are using JPA, I'm afraid you need to use AOP as outlined in this thread
Or you can
store the ApplicationContext in a ThreadLocal or a custom holder class and expose it through a static method
have a base class for your listeners something like this:
Base class:
public abstract class ListenerBase{
protected void wireMe(){
ApplicationContext ctx = ContextHelper.getCurrentApplicationContext();
ctx.getAutowireCapableBeanFactory().autowireBean(this);
}
}
Now in your lifycycle methods call wireMe() first.
Update:
Here is a sample implementation of ContextHelper:
public final class ContextHelper implements ApplicationContextAware{
private static final ContextHelper INSTANCE = new ContextHelper();
private ApplicationContext applicationContext;
#Override
public void setApplicationContext(final ApplicationContext applicationContext){
this.applicationContext = applicationContext;
}
public static ApplicationContext getCurrentApplicationContext(){
return INSTANCE.applicationContext;
};
public static ContextHelper getInstance(){
return INSTANCE;
}
private ContextHelper(){
}
}
Wire it in your Spring Bean configuration like this:
<bean class="com.mycompany.ContextHelper" factory-method="getInstance" />