How to Update an Entity from a Thread in Dropwizard, Hibernate - java

I have a thread that waits until a process is complete and then needs to update an entity. But I get
Exception in thread "Thread-22" org.hibernate.HibernateException: No session currently bound to execution context
I have tried opening a new session (see the code below). Session management is normally handled by #UnitOfWork, but this annotation seems to apply only to resources.
public class ConfigDAO extends AbstractDAO<Config>
{
private final SessionFactory sessionFactory;
public ConfigDAO(SessionFactory factory) {
super(factory);
this.sessionFactory = factory;
}
public Config updateFromNewSession(Config config) {
System.out.print("current session: ");
Session session = sessionFactory.openSession();
System.out.println(session);
session.persist(config);
session.close();
return config;
}

Related

Correct configuration to mock Hibernate's sessionFactory.getCurrentSession()

I have the following:
#Repository
#Transactional
#HibernateProfile
public class PersonaHibernateRepository implements PersonaRepository {
private static final Logger logger = LoggerFactory.getLogger(PersonaHibernateRepository.class.getSimpleName());
private final SessionFactory sessionFactory;
public PersonaHibernateRepository(SessionFactory sessionFactory){
logger.info("{} constructor", PersonaHibernateRepository.class.getSimpleName());
this.sessionFactory = sessionFactory;
}
#Override
public Persona saveOne(Persona persona) {
String generatedIdentifier = (String) sessionFactory.getCurrentSession().save(persona);
logger.info("generatedIdentifier: {}", generatedIdentifier);
return persona;
}
...
Each crud method has sessionFactory.getCurrentSession().
With Mockito the following sentence:
when(sessionFactory.getCurrentSession().save(persona)).thenReturn(persona.getId());
always throws java.lang.NullPointerException. I've confirmed sessionFactory.getCurrentSession() is the point of the problem.
I already have read the following:
Mocking Hibernate Session
Unit test of DAO layer with mockito
Thus the java.lang.NullPointerException was removed.
But I always get now:
org.mockito.exceptions.verification.TooManyActualInvocations:
sessionFactory.getCurrentSession();
Wanted 1 time:
-> at com.manuel.jordan.repository.hibernate.PersonaHibernateRepositoryTest_.saveOneTest(PersonaHibernateRepositoryTest_.java:76)
But was 2 times. Undesired invocation:
-> at com.manuel.jordan.repository.hibernate.PersonaHibernateRepository.saveOne(PersonaHibernateRepository.java:43)
These two times happens due the mock invocation and target invocation.
Currently my configuration is:
private PersonaHibernateRepository personaHibernateRepository;
private SessionFactory sessionFactory;
private Session session;
...
#Before
public void setup(){
sessionFactory = mock(SessionFactory.class);
session = mock(Session.class);
personaHibernateRepository = new PersonaHibernateRepository(sessionFactory);
//Removes NullPointerException - 'A'
when(sessionFactory.getCurrentSession()).thenReturn(session);
}
#Test
public void saveOneTest(){
//java.lang.NullPointerException removed thanks to 'A'
when(sessionFactory.getCurrentSession().save(persona)).thenReturn(persona.getId());
Persona persona_ = personaHibernateRepository.saveOne(persona);
assertThat(persona_, is(persona));
//B
verify(sessionFactory).getCurrentSession().save(persona);
}
Just playing, if I change:
From: verify(sessionFactory).getCurrentSession().save(persona);
To: verify(sessionFactory, times(2)).getCurrentSession().save(persona); (observe times(2))
Again appears the java.lang.NullPointerException thrown now by verify(sessionFactory, times(2)).getCurrentSession().save(persona); (B)
Same exception if in #Before the when(sessionFactory.getCurrentSession()).thenReturn(session) is changed to doReturn(session).when(sessionFactory).getCurrentSession()
What is the correct configuration?
In the setup() method you correctly tell Mockito to return the mocked session instance when sessionFactory.getCurrentSession() is invoked so from them on your assertions should focus on the session instance not the sessionFactory. For example:
#Test
public void saveOneTest(){
// you have already told Mockito to return this session instance when sessionFactory.getCurrentSession() is
// invoked so now your when (and optionally verify) should focus on session rather than on sessionFactory
when(session.save(persona)).thenReturn(persona.getId());
Persona persona_ = personaHibernateRepository.saveOne(persona);
assertThat(persona_, is(persona));
verify(session).save(persona);
}

No transactional entitymanager available in #PostConstruct

Problem:
entityManager.unwrap(SessionImplementor.class) cause no transactional entitymanager available exception.
Code:
#Component
public class HibernateEventWiring {
#Autowired
private ViewListener listener;
#PersistenceContext(unitName = "config-punit")
private EntityManager entityManager;
#PostConstruct
public void registerListeners() {
SessionFactory sessionFactory = getSessionFactory();
EventListenerRegistry registry = ((SessionFactoryImpl) sessionFactory).getServiceRegistry().getService(
EventListenerRegistry.class);
registry.getEventListenerGroup(EventType.PRE_UPDATE).appendListener(listener);
}
#Transactional
private SessionFactory getSessionFactory() {
// EXCEPTION: No transactional entitymanager available
return entityManager.unwrap(SessionImplementor.class).getFactory();
}
}
According to this excelent answer:
In the #PostConstruct (as with the afterPropertiesSet from the InitializingBean interface) there is no way to ensure that all the post processing is already done, so (indeed) there can be no Transactions.
As I see, you do not need a transaction nor an entity manager bean, but rather an entity manager factory bean. I think you should simply autowire the EntityManagerFactory and then unwrap the Hibernate SessionFactory from it.
#Autowired
private EntityManagerFactory entityManagerFactory;
#PostConstruct
public void registerListeners() {
SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
...
}

PropertyPlaceholderConfigurer break my hibernate session

I have an issue in my Spring project when, after create my hibernateSession and TransactionManager I initilize a bean that extends PropertyPlaceholderConfigurer
I dont know why but in that moment my hibermnate session is ruin to be used for the rest of my DAO´s. The error that is throwing is this one.
Caused by: org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
Any suggestions?
I´m trying to extract from database some data to create a properties class and set to a class that I´ve create that extends PropertyPlaceholderConfigurer
This is the class
public class PropertiesSourceImpl extends PropertyPlaceholderConfigurer{
public ConfigurationSource configurationSource;
public Properties properties;
public void init() {
for (ConfigurationProperty prop : configurationSource.getEnabledConfigurationPropertiesByType(ConfigurationProperty.PropertyType.MAIL)) {
System.out.println(prop);
// properties.setProperty(prop.getPropertyKey(), prop.getPropertyValue());
}
}
public Properties getProperties() {
return properties;
}
#Required
public void setConfigurationSource(final ConfigurationSource configurationSource) {
this.configurationSource = configurationSource;
}
}
and here my bean definition
<bean id="propertiesSource" class="nl.greenvalley.digipolis.config.PropertiesSourceImpl" init-method="init">
<property name="configurationSource" ref="configurationSource"/>
</bean>
Finally I found a solution. Instead of use hibernate I just create a new session and transaction before the hibernate session and transaction would be created.
SessionFactory sessionFactory;
public void init() {
Session session = sessionFactory.openSession();
Transaction tx = null;
try {
Properties properties = new Properties();
tx = session.beginTransaction();
List<ConfigurationProperty> dbProperties = session.createCriteria(ConfigurationProperty.class).list();
for (ConfigurationProperty property : dbProperties) {
properties.setProperty(property.getPropertyKey(), property.getPropertyValue());
}
setProperties(properties);
tx.commit();
} finally {
session.close();
}
}

Migrating form Hibernate3 to Hibernate4 keep getting nested transactions not supported

A week before we migrated the application from hibernate3 to hibernate4 every thing worked fine in hibernate3 but after migrating to hibernate4. I keep getting nested transactions not supported.
Below is my service layer which is calling the dao
public class LeaveApplicationService implementsSerializable,LeaveApplicationInterfaceService{
#Autowired
private LeaveApplicationInterfaceDao _leavApplicationInterfaceDao;
//getter setter
#Override
public synchronized void clickOnAddLeaveButton(LeaveApplicationViewBean leaveApplicationViewBean) {
SessionFactory sessionFactory=(SessionFactory) ObjectFactory.getBean("sessionFactory");
sessionFactory.getCurrentSession().beginTransaction();
try{
leaveApplicationViewBean.get_employeeListObj().clear();
leaveApplicationViewBean.get_leaveTypelist().clear();
leaveApplicationViewBean.get_leaveApproveers().clear();
//leaveApplicationViewBean.set_employeeListObj(get_leavApplicationInterfaceDao().getEmployeeList());
leaveApplicationViewBean.set_leaveTypelist(get_leavApplicationInterfaceDao().getLeaveType());
leaveApplicationViewBean.set_leaveApproveers(get_leavApplicationInterfaceDao().getLeaveApprover(CmsUtil.getSession("userId").toString()));
}catch(Exception e){
CmsLogger.errorLog(LeaveApplicationService.class, e);
}finally{
sessionFactory.getCurrentSession().close();
}
}
The Dao layer
public class LeaveApplicationDao extends TransactionService implements Serializable,LeaveApplicationInterfaceDao{
private static final long serialVersionUID = 6237725881698448330L;
public List<LeaveApprover> getLeaveApprover(String userId) throws Exception {
List<LeaveApprover> _leavApprovers=new ArrayList<LeaveApprover>();
Iterator it=getSessionFactory().getCurrentSession().createQuery(sql.toString()).setParameter("practiceAreaId",CmsUtil.getSession("practiceAreaId").toString()) .setParameter("userId",userId).setCacheable(true)
.list().iterator();
while(it.hasNext()){
Object[] obj=(Object[]) it.next();
LeaveApprover leaveApprover=new LeaveApprover();
leaveApprover.set_approverId((String) obj[0]);
leaveApprover.set_approverName((String) obj[1]);
_leavApprovers.add(leaveApprover);
}
return _leavApprovers;
}
public List<TimeProjectCategory> getLeaveType() throws Exception{
List<TimeProjectCategory> timeProjectCategories=new ArrayList<TimeProjectCategory>();
Iterator it =getSessionFactory().getCurrentSession().createQuery(sql.toString()).setCacheable(true).list().iterator();
while(it.hasNext()){
Object[] obj=(Object[]) it.next();
TimeProjectCategory category=(TimeProjectCategory) ObjectFactory.getBean("domainTimeProjectCategoryObj");
category.getProjectId().set_projectId((String) obj[0]);
category.setTimeCategory((String) obj[1]);
category.setTimeProjectCategoryId((String) obj[2]);
timeProjectCategories.add(category);
}
return timeProjectCategories;
}
}
And my TransactionService class
public class TransactionService{
/**
*
*/
private static final long serialVersionUID = 3747504246445270484L;
#Autowired
private DataSource dataSource;
#Autowired
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
}
And the exception I see in the stack-track is
Stack Trace for the code
My db.xml
db.xml file
There are two possibilities:
Implementation-defined behavior with open transactions on session close:
Make sure you commit (or rollback, doesn't matter for read-only) the transaction before closing the connection. Hibernate Session.close() closes the underlying connection; and http://docs.oracle.com/javase/6/docs/api/java/sql/Connection.html#close%28%29 states that the behavior when a transaction is open is implementation-defined (i.e. some implementations will automatically close the transaction, others may reference count the connection and hold it open).
The general pattern is:
try {
Transaction t = sessionFactory.getCurrentSession().beginTransaction();
try {
// do work
t.commit();
} catch (Exception e) {
t.rollback();
throw e;
}
} finally {
sessionFactory.getCurrentSession().close();
}
A previous transaction is still active:
If a previous transaction is still active from somewhere else, you can do this:
Transaction t = session.getTransaction();
if (t == null || !t.isActive())
t = session.beginTransaction();
// then use t (or session's current transaction, same thing)
Or, if you're not passing the Transaction around:
if (session.getTransaction() == null || !session.getTransaction().isActive())
session.beginTransaction();
// then use session's current transaction
But you will still probably want to examine your code to see where else a transaction is being opened on a given connection.

Hibernate Session is closed in spring transaction after calling method second time

First of all I am a beginner in spring.I have created a simple Spring service that has DAO injected and transaction is managed by HibernateTransactionManager of spring, like as below.(And transaction configuration is used using annotations )
#Service(value="daopowered")
public class UserServiceImplDao implements UserService
{
#Inject
private UserDao userDao;
#Override
#Transactional
public User autheticate( String userId, String password )
{
return userDao.findByIdAndPassword(userId, password);
}
My transaction configuration is following
<bean id="txMgr"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="txMgr" />
Now the problem is when I call authenticate method first time using some controller then it works fine ( does DB operations successfully) but after calling it again second time hibernate session is closed exception is coming ? Please guide me what I am doing it wrong or how to handle this scenario ? Why wont spring opens a new transaction when I call this method second time ?
Exception Trace:
2013-05-22T21:04:18.041+0530 DEBUG [14208212-2] lerExceptionResolver Resolving exception from handler [com.akhi.store.controller.HomeController#5d9d277e]: org.springframework.orm.hibernate3.HibernateSystemException: Session is closed!; nested exception is org.hibernate.SessionException: Session is closed!
2013-05-22T21:04:18.044+0530 DEBUG [14208212-2] tusExceptionResolver Resolving exception from handler [com.akhi.store.controller.HomeController#5d9d277e]: org.springframework.orm.hibernate3.HibernateSystemException: Session is closed!; nested exception is org.hibernate.SessionException: Session is closed!
2013-05-22T21:04:18.044+0530 DEBUG [14208212-2] lerExceptionResolver Resolving exception from handler [com.akhi.store.controller.HomeController#5d9d277e]: org.springframework.orm.hibernate3.HibernateSystemException: Session is closed!; nested exception is org.hibernate.SessionException: Session is closed!
2013-05-22T21:04:18.046+0530 DEBUG [14208212-2] et.DispatcherServlet Could not complete request
org.springframework.orm.hibernate3.HibernateSystemException: Session is closed!; nested exception is org.hibernate.SessionException: Session is closed!
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:658)
at org.springframework.orm.hibernate3.AbstractSessionFactoryBean.convertHibernateAccessException(AbstractSessionFactoryBean.java:245)
at org.springframework.orm.hibernate3.AbstractSessionFactoryBean.translateExceptionIfPossible(AbstractSessionFactoryBean.java:224)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:58)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:163)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at com.sun.proxy.$Proxy28.findByIdAndPassword(Unknown Source)
EDIT: The DAO code
#Repository
public class UserDaoImpl extends GenericHibernateDAO<User, Long>
implements
UserDao
{
#Override
public User findByIdAndPassword( String id, String password )
{
Criteria crit = getSession().createCriteria(User.class).add(Restrictions.eq("userId",
id)).add(Restrictions.eq("password",
password)).setMaxResults(1);
List<?> list = crit.list();
if (list.size() > 0)
return (User) list.get(0);
else
return null;
}
and getSession() implementation is
protected Session getSession() {
if (session == null) {
session = sessionFactory.getCurrentSession();
}
return session;
}
Also the abstract DAO class has sessionfactory injected
public abstract class GenericHibernateDAO<T, ID extends Serializable>
implements GenericDAO<T, Long> {
private Class<T> persistentClass;
protected Session session;
#Autowired
private SessionFactory sessionFactory;
Your ObjectDao need a SessionFactory and the annotation Transaction. Something like this :
#Component
public class userDao{
#AutoWired
private SessionFactory sessionFactory;
#Transactional
public User findByIdAndPassword(String id , String password){
....
}
{getters and setters}
}
Dont do that :
protected Session getSession() {
if (session == null) {
session = sessionFactory.getCurrentSession();
}
return session;
}
just return the current session , the Transactional annotation is responsible for opening and closing sessions , like this :
protected Session getSession() {
return sessionFactory.getCurrentSession();
}

Categories

Resources