0

In the process of migrating an old app from JBoss 5.1.0GA to WildFly 13. On the previous server we were using hibernate3 while on WildFly 13 we're trying to use hibernate 5.

A bit on the app - it's built as a multi-tenant app so it has tables that are common to all the clients and tables that are client specific. These client specific tables are suffixed with the clientId, so they would read Document_2, Document_3, ..., Document_n (e.g.).

The common tables definitions are in a .sar archive, under the hibernate.cfg.xml file.

For the common table mappings there is another class like so:

@Singleton
@Startup
public class MyHibernateService
    implements
    DynamicMBean {

    private MBeanServer platformMBeanServer;
    private ObjectName objectName = null;


    @PostConstruct
    public void start() {
        new Configuration().configure().buildSessionFactory();
        this.registerJMX();
    }


    private void registerJMX() {
        try {
            this.objectName = new ObjectName("jboss.jca:service=HibernateFactory,name=HibernateFactory");
            this.platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
            this.platformMBeanServer.registerMBean(this, this.objectName);
        } catch (Exception e) {
            throw new IllegalStateException("Exception during JMX registration :" + e);
        }
    }
....
}

This class binds the hibernate factory for the common tables under a JNDI name so it can be retrieved later.

The client specific tables definitions / mapping are derived from a template. On app boot we build session factories specific for each client. The way we do this is that we parse the template mapping and replace some sections with the client specific one. The template would read

<class name="com..DocumentMapping" table="TABLENAME">

where TABLENAME that would get replace at boot with e.g. Document_2.

This SessionFactoryManager class that does all the replacement looks like below:

if (SessionFactoryManager.LOGGER.isDebugEnabled()) {
    SessionFactoryManager.LOGGER.info("build custom SessionFactory for  datasource: " + databaseConfig);
}

Configuration cfg = new Configuration();

// build all mappings
for (Class c : mappingClasses) {

    try {
        Method m = c.getMethod("getInstance", (Class[])null);
        Helper dao = (Helper)m.invoke(null, (Object[])null);

        String tableName = dao.getTableName(id);

        String mapping = dao.getMappping();

        if (mapping == null) {
            throw new DAOException(DAOException.TYPE.SESSION_FACTORY, "Mapping not available from class: " + c.getName());
        }


        cfg.addXML(mapping);
    } catch (Exception e) {
        throw new DAOException(DAOException.TYPE.SESSION_FACTORY, e);
    }
}

cfg.setProperty("hibernate.dialect", databaseConfig.getDatabaseDialect().getClass().getName());

if (StringTools.isValidString(databaseConfig.getDatabaseJNDI())) {
    cfg.setProperty("hibernate.connection.datasource", databaseConfig.getDatabaseJNDI());
} else {
    cfg.setProperty("hibernate.connection.url", databaseConfig.getDatabaseURL());
    cfg.setProperty("hibernate.connection.driver_class", databaseConfig.getDatabaseDriverClass());
    cfg.setProperty("hibernate.connection.username", databaseConfig.getDatabaseUser());
    cfg.setProperty("hibernate.connection.password", databaseConfig.getDatabasePassword());
}

if (showSQL) {
    cfg.setProperty("hibernate.show_sql", "true");
    cfg.setProperty("hibernate.format_sql", "false");
}

if (operation == OPERATION.RECREATE) {
    cfg.setProperty("hibernate.hbm2ddl.auto", "update");
} else {
    // With create-drop, the database schema will be dropped when the SessionFactory is closed explicitly
    // this is necessary in order to remove client tables if something goes wrong at client creation time
    cfg.setProperty("hibernate.hbm2ddl.auto", "create-drop");
}


SessionFactory sf = cfg.configure().buildSessionFactory();

System.out.println(cfg.getNamedQueries());

The problem is that, although I see that cfg.addXML(String xml) is deprecated, the cfg.getNamedQueries() returns an empty map, as if the mapping is not loaded onto the configuration.

All the above code works fine for hibernate3.

I also tried changing:

SessionFactory sf = cfg.configure().buildSessionFactory();

to

StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder();
builder.applySettings(cfg.getProperties());
MetadataSources metaData = new MetadataSources(builder.build());
Metadata buildMetadata = metaData.buildMetadata(builder.build());
SessionFactory sf = buildMetadata.buildSessionFactory();

but to no avail.

Another change I tried was this:

SessionFactory sf = cfg.configure().buildSessionFactory();

i.e. calling configure on the cfg, after it loaded the mapping. In this case I get a duplicate query exception, as if the queries are not isolated per session factory.

The hibernate version I`m using is 5.1.14, the one shipped with WildFly 13 by default.

Any ideas ?

Sergiu
  • 2,502
  • 6
  • 35
  • 57

1 Answers1

0

Fixed by changing

cfg.addXML(mapping)

to

cfg.addInputStream(new ByteArrayInputStream(mapping.getBytes()));
Apostolos
  • 10,033
  • 5
  • 24
  • 39
Sergiu
  • 2,502
  • 6
  • 35
  • 57