0
votes

Having a deadlock in webservice + hibernate... No idea why.

I have the following webservice code (core code of the function)

public String createImageRecipe(...)
{
    Session session = ICDBHibernateUtil.getSessionFactory().getCurrentSession();
    try 
    {
        session.beginTransaction();

        User user = (User) session.load(User.class, userid);

        // Create the recipe
        Recipe recipe = new Recipe();
        ...
        ...
        ...

        session.save(recipe);
        session.save(user);

        ...
        ...
        ...

        session.update( recipe );

        // Add new entry to activity log
        Activitylog activityLog = new Activitylog(  user, 
                                                    (byte) ActivityTypeEnum.USER_SHARED_RECIPE.ordinal(), 
                                                    new Date() );
        activityLog.setRecipe(recipe);
        TimelineProcessor.saveTimeline( activityLog, null, true );

        session.getTransaction().commit();

        endMeasurement();

        return recipe.getRecipeid() + "," + recipe.getImageRecipeUrl();
    } 
    catch (RuntimeException e) 
    {
        ICDBHibernateUtil.getSessionFactory().getCurrentSession().getTransaction().rollback();
        throw e;
    }
}

Now the timeline thread (TimelineProcessor) does the following (after getting the message):

    Session session = ICDBHibernateUtil.getTimelineSessionFactory().openSession();
    try {
        session.getTransaction().begin();

        ...
        ...
        ...

        TimelineId tlId = new TimelineId();
        tlId.setUserId(userId);

        User u = new User();
        u.setUserid(userId);

        Timeline tl = new Timeline(tlId, timelineData.getActivitylog(), u);
        session.save(tl);

        session.getTransaction().commit();
        session.close();
    } catch (Exception e) {
        logger.error("Error while processing timeline :: ", e);
        session.getTransaction().rollback();
    }
}

Exceptions from log: Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions at org.hibernate.collection.AbstractPersistentCollection.setCurrentSession(AbstractPersistentCollection.java:435)

ERROR com.icdb.TimelineProcessor - processTimeline - Error while processing timeline :: org.hibernate.exception.LockAcquisitionException: could not insert: [com.icdb.data.Activitylog]

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

ERROR com.icdb.TimelineProcessor - processTimeline - Error while processing timeline :: org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions

Will really appriciate help... Thanks a lot

1

1 Answers

2
votes

Well Hibernate is telling you what it doesn't like:

Illegal attempt to associate a collection with two open sessions

You are opening two sessions, and have a transaction in each, and when you save the new timeline in the second session, it has an activityLog, and that activityLog has a user and a recipe that stem from the first session. That's where Hibernate croaks.

I'm not sure i see what you are trying to accomplish. Is there a reason you need two separate sessions? Is the timeline something that's semantically associated with the recipe/user entities or is it more like a timestamp collection? In the former case you probably want to store user, recipe and timeline in one and the same collection, or else you'll end up with corrupt data if one transaction succeeds and the other one fails. In the latter case the Timestamp service should take value objects as arguments rather than entities, because you're probably going to want to access it from different parts of your application.