Last updated Apr 20, 2022

Rate this page:

How to update your app for Hibernate2 removal

AvailabilityConfluence 7.17 or later

In Confluence 8.0, we will remove support for Hibernate2 across Confluence. This will allow us to upgrade Hibernate more frequently without breaking your app, or requiring you to do significant testing and rework when things change.

For apps this means:

  1. No direct usage of Hibernate in plugins.
  2. No use of deprecated code from Confluence plugin API.

How to check if your app uses Hibernate2?

Your app uses Hibernate2 if:

  • The Java source code of your app has any references to classes from net.sf.hibernate.* packages.
  • The app code uses any Hibernate APIs directly.
  • The app code uses any deprecated classes or methods from Confluence API.

When testing your app in Confluence, you can also set the following system property. It will log warnings if your app makes use of PluginHibernateSessionFactory to use Hibernate sessions directly. This property is available from Confluence 7.18.

1
2
-Dcheck-confluence8-compatibility=true

Changes required to pom.xml

Check your app's pom.xml, look for any dependencies on Hibernate 2 packages, and remove them.

You should also remove any occurrences of net.sf.hibernate.*.

1
2
<build>
  <plugins>
      <plugin>
        ...
          <configuration>
            <instructions>
              <Import-Package>
              ...
                net.sf.hibernate,
                net.sf.hibernate,
                net.sf.hibernate.cache,
                net.sf.hibernate.collection,
                net.sf.hibernate.connection,
                net.sf.hibernate.dialect,
                net.sf.hibernate.engine,
                net.sf.hibernate.exception,
                net.sf.hibernate.metadata,
                net.sf.hibernate.persister,
                net.sf.hibernate.type,        
             ...
             </Import-Package>
        ...
  </build>

Changes required to Java code

Custom Hibernate queries

If your app uses any Custom Hibernate queries, there is a new way of using custom queries. You should use content-custom-query over content-hibernate-2-query.

If your code uses any implementations of com.atlassian.confluence.content.persistence.hibernate.HibernateContentQueryFactory make sure you remove the override of the deprecated method and use the non-deprecated methods. For example:

Existing code
1
2
public class FindInSpaceByMessageIdQueryFactory implements HibernateContentQueryFactory {
    @Override
    public Query getQuery(Session session, Object... parameters) throws HibernateException {
        long spaceId = (Long) parameters[0];
        String messageId = (String) parameters[1];

        Query query = session.createQuery("from CustomContentEntityObject content " +
                "left join content.contentProperties as props " +
                "where content.originalVersion is null and " +
                "content.space.id = :spaceId and " +
                "props.name = 'messageId' and " +
                "props.stringValue = :messageId ");
        query.setParameter("spaceId", spaceId, Hibernate.LONG);
        query.setParameter("messageId", messageId, Hibernate.STRING);
        return query;
    }
}
New code
1
2
public class FindInSpaceByMessageIdQueryFactory implements HibernateContentQueryFactory {

    @Override
    public Query getQuery(EntityManager entityManager, Object... parameters) throws PersistenceException {
        long spaceId = (Long) parameters[0];
        String messageId = (String) parameters[1];

        Query query = entityManager.createQuery("from CustomContentEntityObject content " +
                "left join content.contentProperties as props " +
                "where content.originalVersion is null and " +
                "content.space.id = :spaceId and " +
                "props.name = 'messageId' and " +
                "props.stringValue = :messageId ");
        query.setParameter("spaceId", spaceId);
        query.setParameter("messageId", messageId);
        return query;
    }
}

The tag content-custom-query was introduced in Confluence 7.17.  We recommended you use content-custom-query over content-hibernate-2-query as content-hibernate-2-query may be removed in future. 

In the meantime, you can use both to define your custom queries with two modules having version restrictions as in the example below.

1
2
<content-hibernate-2-query query-name="query-name" key="legacy-query-name" class="com.test.MyQueryFactory">
   <restrict application="confluence" version="(,7.17.0)" />
</content-hibernate-2-query>

<content-custom-query query-name="query-name" key="my-query-name" class="com.test.MyQueryFactory">
   <restrict application="confluence" version="[7.17.0,)" />
</content-custom-query>

PluginHibernateSessionFactory usages

PluginHibernateSessionFactory usage is no longer supported. If your code uses the com.atlassian.hibernate.PluginHibernateSessionFactory class to get sessions you should remove the component-import for this class from atlassian-plugin.xml (if present) and use the EntityManagerProvider instead.

Existing code
1
2
<component-import key="pluginHibernateSessionFactory"
interface="com.atlassian.hibernate.PluginHibernateSessionFactory"/>
New code
1
2
<component-import key="entityManagerProvider"
interface="com.atlassian.confluence.persistence.EntityManagerProvider"/>

You should also remove the component-import annotations for this class from your java code (if present) and use the EntityManagerProvider instead.

Existing code
1
2
@ComponentImport PluginHibernateSessionFactory pluginHibernateSessionFactory
New code
1
2
@ComponentImport EntityManagerProvider entityManagerProvider,

The EntityManagerProvider can be used to replace the corresponding methods from Session.

Existing code
1
2
Session session = pluginHibernateSessionFactory.getSession();
session.save(someObject);
session.delete(someObject);
Query titleQuery = hibernateSession.createQuery(queryString);
List<String> titles = (List<String>) titleQuery.list();
New code
1
2
EntityManager entityManager = entityManagerProvider.getEntityManager();
entityManager.persist(propertySetItem);
entityManager.remove(propertySetItem);
Query titleQuery = entityManager.createQuery(queryString);
List<String> titles = (List<String>) titleQuery.getResultList();

Getting a JDBC connection

We strongly recommend you use EntityManagerProvider to execute the database queries. In some cases getting a JDBC connection may be required. 

TransactionalExecutorFactory  provides the ability to execute a block of code/lambda with a JDBC connection.

Existing code
1
2
PluginHibernateSessionFactory pluginHibernateSessionFactory;
Connection connection = pluginHibernateSessionFactory.getSession().getConnection();
doSomethingUsingConnection(connection);
New code
1
2
TransactionalExecutorFactory transactionalExecutorFactory;
transactionalExecutorFactory.create().execute(connection -> {
  doSomethingUsingConnection(connection);
});

Rate this page: