I'm trying to get Javer setup with my project. I am using Hibernate JPA and I believe I have everything configured correctly.
Here is my Spring config:
<bean id="auditDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.audit.url}"/>
<property name="username" value="${jdbc.audit.username}"/>
<property name="password" value="${jdbc.audit.password}"/>
<property name="maxActive" value="100"/>
<property name="maxWait" value="1000"/>
<property name="poolPreparedStatements" value="true"/>
<property name="defaultAutoCommit" value="true"/>
<property name="validationQuery" value="${jdbc.validationQuery}"/>
<property name="testOnBorrow" value="true"/>
</bean>
<bean id="auditSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" destroy-method="destroy">
<property name="dataSource" ref="auditDataSource"/>
<property name="configLocation" value="classpath:hibernate.audit.cfg.xml"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.query.substitutions">true 'Y', false 'N'</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.format_sql">false</prop>
<prop key="hibernate.use_sql_comments">false</prop>
<!--<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>-->
<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</prop>
<!-- Hibernate Search index directory -->
<prop key="hibernate.search.default.indexBase">${app.search.index.basedir}</prop>
</props>
<!-- Turn batching off for better error messages under PostgreSQL -->
<!-- hibernate.jdbc.batch_size=0 -->
</property>
</bean>
<!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) -->
<bean id="auditTransactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="auditSessionFactory"/>
</bean>
<bean id="javersRepoConnectionProvider" class="com.dsc.discus.ng.audit.javers.JaversRepoConnectionProvider">
<constructor-arg name="dataSource" ref="auditDataSource"/>
</bean>
<bean id="auditController" class="com.dsc.discus.ng.audit.javers.JaversAuditController">
<constructor-arg name="javersRepoConnectionProvider" ref="javersRepoConnectionProvider"/>
<constructor-arg name="transactionManager" ref="auditTransactionManager"/>
</bean>
The JaversAuditController bean:
public class JaversAuditController extends AuditController {
private final JaversSqlRepository javersSqlRepository;
private final Javers javers;
public JaversAuditController(JaversRepoConnectionProvider javersRepoConnectionProvider, PlatformTransactionManager transactionManager) {
javersSqlRepository = SqlRepositoryBuilder.sqlRepository()
.withConnectionProvider(javersRepoConnectionProvider)
.withDialect(DialectName.MYSQL)
.build();
javers = TransactionalJaversBuilder.javers()
.withTxManager(transactionManager)
.withObjectAccessHook(new HibernateUnproxyObjectAccessHook())
.withMappingStyle(MappingStyle.BEAN)
.registerJaversRepository(javersSqlRepository)
.build();
}
#Override
public void addModified(BaseEntity entity) {
addModified(entity, null);
}
#Override
public void addModified(BaseEntity entity, Map<String, String> extraParams) {
if (javers != null && entity != null) {
if (extraParams != null) {
javers.commit(entity.getModifiedBy(), entity, extraParams);
}
else {
javers.commit(entity.getModifiedBy(), entity);
}
}
}
public JaversSqlRepository getJaversSqlRepository() {
return javersSqlRepository;
}
public Javers getJavers() {
return javers;
}
I have to use BEAN mapping style because the JPA annotations are on the accessors of the entities.
Here is the JaversRepoConnectionProvider bean:
public class JaversRepoConnectionProvider implements ConnectionProvider {
private DataSource dataSource;
public JaversRepoConnectionProvider(DataSource dataSource) {
this.dataSource = dataSource;
}
#Override
public Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
}
I am doing a manual audit. That is, every time an entity is saved, I'm calling the javers.commit() method. As it happens, the very first thing I try to save causes a MySQL syntax error stating that the table "jv_commit" doesn't exist. The documentation states that the necessary tables would automatically be created, so I must be missing something. Please advise and thanks in advance.
Truncated stack trace:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'discus_eng_audit.jv_commit' doesn't exist
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.Util.getInstance(Util.java:386)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1054)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4237)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4169)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2617)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2778)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2825)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2156)
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2323)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
at org.polyjdbc.core.transaction.Transaction.executeQuery(Transaction.java:59)
at org.polyjdbc.core.query.TransactionalQueryRunner.queryCollection(TransactionalQueryRunner.java:86)
at org.polyjdbc.core.query.TransactionalQueryRunner.queryList(TransactionalQueryRunner.java:76)
at org.javers.repository.sql.PolyUtil.queryForBigDecimalList(PolyUtil.java:27)
at org.javers.repository.sql.PolyUtil.queryForOptionalBigDecimal(PolyUtil.java:36)
at org.javers.repository.sql.repositories.CommitMetadataRepository.selectMaxCommitId(CommitMetadataRepository.java:86)
at org.javers.repository.sql.repositories.CommitMetadataRepository.getCommitHeadId(CommitMetadataRepository.java:75)
at org.javers.repository.sql.JaversSqlRepository.getHeadId(JaversSqlRepository.java:76)
at org.javers.repository.api.JaversExtendedRepository.getHeadId(JaversExtendedRepository.java:137)
at org.javers.core.commit.CommitIdFactory.nextId(CommitIdFactory.java:26)
at org.javers.core.commit.CommitFactory.newCommitMetadata(CommitFactory.java:79)
at org.javers.core.commit.CommitFactory.create(CommitFactory.java:69)
at org.javers.core.JaversCore.commit(JaversCore.java:82)
at org.javers.core.JaversCore.commit(JaversCore.java:67)
at org.javers.spring.jpa.JaversTransactionalDecorator.commit(JaversTransactionalDecorator.java:58)
at com.dsc.discus.ng.audit.javers.JaversAuditController.addModified(JaversAuditController.java:56)
at com.dsc.discus.ng.audit.javers.JaversAuditController.addModified(JaversAuditController.java:46)
at com.dsc.discus.ng.model.persistence.dao.hibernate.BaseDaoHibernate.save(BaseDaoHibernate.java:146)
at com.dsc.discus.ng.model.persistence.dao.hibernate.BaseDaoHibernate.save(BaseDaoHibernate.java:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
In Spring app, Javers instance should be registered as a Spring bean. JaVers uses #PostConstruct annotation and Spring calls ensureSchema() when txManager is ready.
See JaversTransactionalDecorator impl:
#PostConstruct
public void ensureSchema() {
TransactionTemplate tmpl = new TransactionTemplate(txManager);
tmpl.execute(new TransactionCallbackWithoutResult() {
#Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
javersSqlRepository.ensureSchema();
}
});
}
In your case, this method isn't called because you have created the Javers instance in your Controller and not as a Spring bean. You should configure your app as docs says - https://javers.org/documentation/spring-integration/#jpa-entity-manager-integration
It turns out that the TransactionalJaversBuilder.javers().build() method does not ensure the tables are created, like the standard JaversBuilder.javers().build() method does. I am not sure if this is bug in the TransactionalJaversBuilder or not. My workaround is to call the ensureSchema() after the Javers object is built:
public JaversAuditController(JaversRepoConnectionProvider javersRepoConnectionProvider, PlatformTransactionManager transactionManager) {
javersSqlRepository = SqlRepositoryBuilder.sqlRepository()
.withConnectionProvider(javersRepoConnectionProvider)
.withDialect(DialectName.MYSQL)
.build();
javers = TransactionalJaversBuilder.javers()
.withTxManager(transactionManager)
.withObjectAccessHook(new HibernateUnproxyObjectAccessHook())
.withMappingStyle(MappingStyle.BEAN)
.registerJaversRepository(javersSqlRepository)
.build();
javersSqlRepository.ensureSchema();
}
Related
I'm having an issue with Spring and Hibernate Search. Here is my code:
#Slf4j
#Repository
public class DefaultIndexBuilderDao implements IndexBuilderDao {
#PersistenceContext
#Getter
#Setter
private EntityManager entityManager;
#Override
public void rebuildIndex() {
try {
log.debug("Starting the reindex process...");
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(getEntityManager());
fullTextEntityManager.createIndexer().startAndWait();
log.debug("Reindex complete.");
} catch( InterruptedException e ) {
log.warn("Error rebuilding index: {}", e.getMessage(), e);
}
}
}
I'm getting:
Caused by: java.lang.ClassCastException: com.sun.proxy.$Proxy62 cannot be cast to org.hibernate.engine.spi.SessionImplementor
at org.hibernate.search.impl.FullTextSessionImpl.<init>(FullTextSessionImpl.java:62)
at org.hibernate.search.impl.ImplementationFactory.createFullTextSession(ImplementationFactory.java:35)
at org.hibernate.search.Search.getFullTextSession(Search.java:45)
at com.domainwww.dao.DefaultIndexBuilderDao.rebuildIndex(DefaultIndexBuilderDao.java:38)
at com.domainwww.service.DefaultIndexBuilderService.rebuildIndex(DefaultIndexBuilderService.java:30)
at com.domainwww.beans.admin.IndexBean.reindex(IndexBean.java:29)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.el.parser.AstValue.invoke(AstValue.java:247)
at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:267)
at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:107)
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:87)
... 57 more
Here are the versions from my POM (properties) (in case this is a version conflict)
<spring.version>5.3.1</spring.version>
<hibernate.version>5.4.24.Final</hibernate.version>
<hibernate.search.version>5.11.7.Final</hibernate.search.version>
Here is by bean for entityManager:
<bean id="entityManager" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="net.xxxx,com.xxxx.dbmanager3.settings" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.dialect.storage_engine">innodb</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.connection.autocommit">false</prop>
<prop key="hibernate.search.default.directory_provider">filesystem</prop>
<prop key="hibernate.search.default.indexBase">/opt/xxx/lucene/indexes</prop>
</props>
</property>
</bean>
So I get that Spring is injecting a Proxy, so how should I be obtaining the FullTextEntityManager, unwrapping seems to leave me with the same error? Thanks!
This is typically what happens when using Hibernate Search 5.11.5.Final and below with Spring boot 2.4 / Spring 5.3. See https://github.com/spring-projects/spring-framework/issues/26090
Given the ClassCastException occurs at FullTextSessionImpl.java:62, I suspect you are not actually using Hibernate Search 5.11.7.Final: in Hibernate Search 5.11.7.Final, this line is just an instanceof test. In 5.11.5.Final and below, this line actually is a cast.
I see you set property hibernate.search.version to 5.11.7.Final, but did you use this property anywhere in your POM? Spring Boot doesn't manage the dependency to Hibernate Search, so you need to specify the version yourself in your <dependency> markup.
İ developed a web application using spring and hibernate. This is pretty huge app and i have to get some services from outside of controllers as well. For this i used xmlclasspathcontext to get beans at the same time.
Currently i am using threadlocal and opensession. So far i do not have problem except reading old data when update somethings. İ know this happens because of threadlocal keep current session.
What i want to learn is, İF i remove threadlocal and use öpensession and close session is it a good approach?
Because i cant use getcurrentsession with controllers and getbeans at the same time. İam getting no session found err at the xmXML get bean side. Is there a way to get getcurrentsession at both side? Or do i haveto use open and close session approach? What İF i do not close each opwnsession?
<?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"
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/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
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<context:component-scan base-package="com.yupsoft.grid" />
<tx:annotation-driven transaction-manager="hibernateTransactionManager"/>
<bean id="jspViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
<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/grid" />
<property name="username" value="myuser" />
<property name="password" value="mypass" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.yupsoft.yupsoft.model.LanguageTextParameter</value>
<value>com.yupsoft.yupsoft.model.LoginHistory</value>
<value>com.yupsoft.yupsoft.model.Session</value>
<value>com.yupsoft.yupsoft.model.User</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<!--
<prop key="hibernate.connection.autocommit">false</prop>
-->
<prop key="hibernate.connection.charSet">utf8</prop>
<prop key="hibernate.connection.characterEncoding">utf8</prop>
<prop key="hibernate.connection.useUnicode">true</prop>
<prop key="hibernate.connection.autoReconnect">true</prop>
<prop key="current_session_context_class">thread</prop>
<prop key="hibernate.connection.pool_size">1</prop>
<prop key="hibernate.c3p0.min_size">10</prop>
<prop key="hibernate.c3p0.max_size">100</prop>
<prop key="hibernate.c3p0.timeout">1800</prop>
<prop key="hibernate.c3p0.max_statements">50</prop>
<prop key="hibernate.c3p0.idle_test_period">30</prop>
<prop key="hibernate.c3p0.acquire_increment">1</prop>
<prop key="hibernate.c3p0.max_statements">0</prop>
<prop key="hibernate.c3p0.preferredTestQuery">select 1;</prop>
<prop key="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</prop>
<prop key="hibernate.connection.isolation">8</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</prop>
<prop key="hibernate.cache.use_query_cache">false</prop>
<prop key="hibernate.cache.use_second_level_cache">false</prop>
</props>
</property>
</bean>
<bean id="hibernateTransactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
This is Controller class that I am getting requests
#Controller
public class UserController {
#Autowired
private UserService userService;
#Autowired
private LoginHistoryService loginHistoryService;
#RequestMapping(value = "/loginAttempt", method = RequestMethod.POST)
public #ResponseBody
String loginAttempt(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
String userName = request.getParameter("userName");
String password = request.getParameter("password");
User user = userService.getByUserNameAndPassword(userName, password);
if (user != null) {
if (user.isActive()) {
LoginHistory loginHistory = new LoginHistory();
loginHistory.setCreated(new Date());
loginHistory.setIpAddress(request.getRemoteAddr());
loginHistory.setSessionId(request.getSession().getId());
loginHistory.setAccountVerified(Boolean.TRUE);
loginHistory.setUser(user);
boolean loginHistoryCreated = loginHistoryService.create(loginHistory);
if (loginHistoryCreated) {
return "ok";
} else {
//Error
return "err";
}
} else {
return "err";
}
}
return "ok";
}
}
This is Service layer
#Service("loginHistoryService")
#Transactional(propagation = Propagation.REQUIRED, readOnly = true, isolation = Isolation.SERIALIZABLE)
public class LoginHistoryServiceImpl extends GenericServiceImpl implements LoginHistoryService {
#Autowired
private LoginHistoryDAO loginHistoryDAO;
public LoginHistoryDAO getLoginHistoryDAO() {
return loginHistoryDAO;
}
public void setLoginHistoryDAO(LoginHistoryDAO loginHistoryDAO) {
this.loginHistoryDAO = loginHistoryDAO;
setGenericDAO(loginHistoryDAO);
}
#Transactional(propagation = Propagation.REQUIRED, readOnly = false)
#Override
public boolean create(LoginHistory obj) {
return loginHistoryDAO.create(obj);
}
This part is DAO layer
#Repository("loginHistoryDAO")
public class LoginHistoryDAOImpl extends GenericDAOImpl implements LoginHistoryDAO {
#Autowired
private SessionDAO sessionDAO;
#Override
public boolean create(LoginHistory obj) {
try {
//beginTransaction();
save(obj);
if (obj.isAccountVerified()) {
Session s = new Session();
s.setActive(Boolean.TRUE);
s.setIpAddress(obj.getIpAddress());
s.setCreated(new Date());
s.setSessionId(obj.getSessionId());
s.setUser(obj.getUser());
sessionDAO.save(s);
}
//commitTransaction();
} catch (Exception e) {
handleException(e);
return false;
}
return true;
}
}
And last part is generic part
#SuppressWarnings("unchecked")
#Repository
public abstract class GenericDAOImpl implements GenericDAO {
#Autowired
private SessionFactory sessionFactory;
private final Class<T> persistentClass;
public GenericDAOImpl() {
this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
public Class<T> getPersistentClass() {
return persistentClass;
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public Session getCurrentSession() throws HibernateException {
return sessionFactory.getCurrentSession();
}
#Override
public Transaction beginTransaction() {
return getCurrentSession().beginTransaction();
}
#Override
public void commitTransaction() {
getCurrentSession().getTransaction().commit();
I am trying to replace openSession() to getCurrentSession()
and I require to control beginTransaction() and tx.commit(). Because I have more than one entity to save or update at the same time. So, I need to wrap those intities in a transaction, be sure all done or all did not done.
When I use getCurrentSession() I am getting this error;
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.transaction.TransactionSystemException: Could not commit Hibernate transaction; nested exception is org.hibernate.TransactionException: Transaction not successfully started
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:656)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:560)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at com.virdyn.grid.core.system.filter.SessionFilter.doFilter(SessionFilter.java:88)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:563)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:399)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:317)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:204)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:311)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Caused by: org.springframework.transaction.TransactionSystemException: Could not commit Hibernate transaction; nested exception is org.hibernate.TransactionException: Transaction not successfully started
at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:660)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:412)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at com.sun.proxy.$Proxy166.create(Unknown Source)
at com.virdyn.grid.controller.UserController.loginAttempt(UserController.java:75)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:421)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:409)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:771)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:716)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
... 25 more
Caused by: org.hibernate.TransactionException: Transaction not successfully started
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:100)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:656)
... 43 more
I want to cancel ThreadLocal and use getCurrentSession.
What is wrong in here Or do you have other purposes. In fact I can use opensession() and closeSession for any method in all dao's. If I do that is it to slow my system?
I am waiting solutions thanks
I am performing retrieval operation to get list of students from database. But I am getting 'empty' data from database. Used HibernateTemplate in
Spring with Hibernate integration,
domain class:-
#Entity
#Table(name="student")
public class StdBO {
#Id
private int sno;
private String sname,sadd;
//setters and getters
}
How can I use HibernateCallBack() interface for search operation? This is my first time that integrating spring with hibernate, is the below way correct? I tried many ways to perform search operations using HibernateTemplate but failing to get the details
DAO
#Repository
public class StdDAO {
private HibernateTemplate ht;
public void setHt(HibernateTemplate ht) {
this.ht = ht;
}
public List<StdBO> select(){
List<StdBO> list = ht.executeFind(new HibernateCallback() {
public Object doInHibernate(Session ses)
throws HibernateException, SQLException {
Criteria criteria=ses.createCriteria(StdBO.class);
System.out.println("before printing sutdents");
List<StdBO> bos = criteria.list();
System.out.println("students are"+bos);//here getting empty list
return bos;
}
});
return list;
}
xml
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="annotatedClasses">
<list>
<value>com.nt.dao.StdDAO</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
</props>
</property>
</bean>
<bean id="template" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<bean id="dao" class="com.nt.dao.StdDAO">
<property name="ht" ref="template" />
</bean>
You need begin (and commit) a transaction to query data. You can do it manually by session.beginTransaction() or using #Transactional annotation. For using #Transactional annotation you will need to do some additional spring configuration:
Hibernate Transaction Annotation Configuration.
I am trying to implement a simple DAO using hibernate 4 and Spring 3.
When I try to save or delete a row in the db the transaction is not persisted. I have included some code to show how the saving in the db doesnt work:
I have a junit test which simply tries to save a StockEntityDTO in the db.
#RunWith(SpringJUnit4ClassRunner.class)
public class StocksDAOImplTest extends
AbstractTransactionalJUnit4SpringContextTests {
#Autowired
protected StocksDAO stockDao;
#Test
public void shouldInsertIntoDatabase() {
BigDecimal price = new BigDecimal(653.50);
StockEntityDTO savedStock = new StockEntityDTO("GOOG", price, "google");
stockDao.create(savedStock);
StockEntityDTO retrievedStock = stockDao.getById(savedStock.getId());
assertEquals(savedStock, retrievedStock);
}
The test passes but the expected row (1, "GOOG", 653.50, "google") is not persisted in the db.
The DAO looks like this:
#Transactional
public abstract class AbstractHibernateDAO<T extends Serializable> {
private Class<T> clazz;
#Resource(name = "sessionFactory")
private SessionFactory sessionFactory;
public void setClazz(final Class<T> clazzToSet) {
this.clazz = clazzToSet;
}
public void create(final T entity) {
Session session = this.getCurrentSession();
session.save(entity);
}
Application Context:
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="oracle.jdbc.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:#localhost:1521:orcl" />
<property name="username" value="gtp" />
<property name="password" value="gtp" />
</bean>
<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.ubs.gtp.data.domain" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext
</prop>
</props>
</property>
</bean>
Hope someone can help. As is probably evident from my code, I am very new to spring.
AbstractTransactionalJUnit4SpringContextTests rolls back after the test. Try setting a breakpoint at the last line and then inspecting the database. You can use the Rollback annotation if you don't want this default behaviour.
I've seen several similar questions, but none of the suggested solutions helped me.
Summary: when I create and inject the beans on the .xml, it works; but when I use #Autowire or #Resource, it doesn't.
Environment: Spring3, Hibernate4, Tomcat7.
Details: the following setup DOES work:
web.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/root-context.xml
/WEB-INF/spring/security-context.xml
/WEB-INF/spring/users-context.xml
</param-value>
</context-param>
root-context.xml:
<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/venus" />
<property name="username" value="root" />
<property name="password" value="" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.airbus.genesis.marte.dal" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<tx:annotation-driven transaction-manager="txManager" />
<bean id="txManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
users-context.xml:
<bean id="usersDAO" class="com.airbus.genesis.marte.dal.users.UsersDAO">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
BL object:
#Service("usersManager")
#Transactional(readOnly = true)
public class UsersManager implements IUsersManager {
#Autowired
#Qualifier("usersDAO")
private IUsersDAO usersDAO;
#Override
public List<User> getUsers() {
return usersDAO.getUsers();
}
}
DAO object (notice that #Repository and #Resource are commented):
//#Repository("usersDAO")
#Transactional(readOnly = true)
public class UsersDAO implements IUsersDAO {
// #Resource(name = "sessionFactory")
private SessionFactory sessionFactory;
#Override
public List<User> getUsers() {
#SuppressWarnings("unchecked")
List<User> res = (List<User>) getSessionFactory().getCurrentSession()
.createQuery("from User").list();
return res;
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
}
But the following one DOES NOT work:
users-context.xml:
<!--
<bean id="usersDAO" class="com.airbus.genesis.marte.dal.users.UsersDAO">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
-->
DAO object (notice that #Repository and #Resource are uncommented now):
#Repository("usersDAO")
#Transactional(readOnly = true)
public class UsersDAO implements IUsersDAO {
#Resource(name = "sessionFactory")
private SessionFactory sessionFactory;
#Override
public List<User> getUsers() {
#SuppressWarnings("unchecked")
List<User> res = (List<User>) getSessionFactory().getCurrentSession()
.createQuery("from User").list();
return res;
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
}
org.hibernate.HibernateException: No Session found for current thread is raised:
org.hibernate.HibernateException: No Session found for current thread
org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97)
org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:941)
com.airbus.genesis.marte.dal.users.UsersDAO.getUsers(UsersDAO.java:23)
com.airbus.genesis.marte.bl.users.UsersManager.getUsers(UsersManager.java:22)
[...]
The same happens if I use #Autowire instead of #Resource.
I guess it is some kind of misunderstanding on my side, but cannot find where. Any idea?
The problem is likely that #Repository and #Service annotations are being picked up in the dispatcher-servlet.xml configuration (do you use context:component-scan?), so these beans are created in the dispatcher servlet context instead of the root web app context.
A good practice is to put your service layer objects to the dedicated packages and use the specific package name as <context:component-scan/> base-package qualifier (like 'com.myproject.services'). You can also use filter expressions to include and exclude elements see examples here : #Service are constructed twice
and 4.10.3 section of the Spring documentation
See also Difference between applicationContext.xml and spring-servlet.xml in Spring Framework