Spring Bean sessionFactory with NullPointerException error

2

Good morning.

I'm trying to make a setting in the spring-jpa.xml file to support a multitenancy architecture by separating each client by Schema. I use a dataSource that has been configured in JBoss Wildfly to connect to the database where the schemas are.

What's missing in the settings?

  

Context initialization failed: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/spring/spring-jpa.xml]: Invocation of init method failed; nested exception is java.lang.NullPointerException.

Full stack trace:

11:26:23,712 ERROR [org.springframework.web.context.ContextLoader] (MSC service thread 1-7) Context initialization failed: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/spring/spring-jpa.xml]: Invocation of init method failed; nested exception is java.lang.NullPointerException
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1553) [spring-beans-4.0.5.RELEASE.jar:4.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539) [spring-beans-4.0.5.RELEASE.jar:4.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475) [spring-beans-4.0.5.RELEASE.jar:4.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304) [spring-beans-4.0.5.RELEASE.jar:4.0.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228) [spring-beans-4.0.5.RELEASE.jar:4.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300) [spring-beans-4.0.5.RELEASE.jar:4.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195) [spring-beans-4.0.5.RELEASE.jar:4.0.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:684) [spring-beans-4.0.5.RELEASE.jar:4.0.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760) [spring-context-4.0.5.RELEASE.jar:4.0.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482) [spring-context-4.0.5.RELEASE.jar:4.0.5.RELEASE]
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403) [spring-web-4.0.5.RELEASE.jar:4.0.5.RELEASE]
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306) [spring-web-4.0.5.RELEASE.jar:4.0.5.RELEASE]
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106) [spring-web-4.0.5.RELEASE.jar:4.0.5.RELEASE]
    at io.undertow.servlet.core.ApplicationListeners.contextInitialized(ApplicationListeners.java:173) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:190) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentService.startContext(UndertowDeploymentService.java:87)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentService.start(UndertowDeploymentService.java:72)
    at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1948)
    at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1881)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [rt.jar:1.8.0_20]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [rt.jar:1.8.0_20]
    at java.lang.Thread.run(Thread.java:745) [rt.jar:1.8.0_20]
Caused by: java.lang.NullPointerException
    at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:126) [hibernate-core-4.3.5.Final.jar:4.3.5.Final]
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:111) [hibernate-core-4.3.5.Final.jar:4.3.5.Final]
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:234) [hibernate-core-4.3.5.Final.jar:4.3.5.Final]
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:206) [hibernate-core-4.3.5.Final.jar:4.3.5.Final]
    at org.hibernate.cfg.Configuration.buildTypeRegistrations(Configuration.java:1885) [hibernate-core-4.3.5.Final.jar:4.3.5.Final]
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1843) [hibernate-core-4.3.5.Final.jar:4.3.5.Final]
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1928) [hibernate-core-4.3.5.Final.jar:4.3.5.Final]
    at org.springframework.orm.hibernate4.LocalSessionFactoryBuilder.buildSessionFactory(LocalSessionFactoryBuilder.java:343) [spring-orm-4.0.5.RELEASE.jar:4.0.5.RELEASE]
    at org.springframework.orm.hibernate4.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:431) [spring-orm-4.0.5.RELEASE.jar:4.0.5.RELEASE]
    at org.springframework.orm.hibernate4.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:416) [spring-orm-4.0.5.RELEASE.jar:4.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1612) [spring-beans-4.0.5.RELEASE.jar:4.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1549) [spring-beans-4.0.5.RELEASE.jar:4.0.5.RELEASE]
    ... 21 more

11:26:23,716 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-7) MSC000001: Failed to start service jboss.undertow.deployment.default-server.default-host./projectERP: org.jboss.msc.service.StartException in service jboss.undertow.deployment.default-server.default-host./projectERP: Failed to start service
    at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1904) [jboss-msc-1.2.2.Final.jar:1.2.2.Final]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [rt.jar:1.8.0_20]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [rt.jar:1.8.0_20]
    at java.lang.Thread.run(Thread.java:745) [rt.jar:1.8.0_20]
Caused by: java.lang.RuntimeException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/spring/spring-jpa.xml]: Invocation of init method failed; nested exception is java.lang.NullPointerException
    at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:219)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentService.startContext(UndertowDeploymentService.java:87)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentService.start(UndertowDeploymentService.java:72)
    at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1948) [jboss-msc-1.2.2.Final.jar:1.2.2.Final]
    at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1881) [jboss-msc-1.2.2.Final.jar:1.2.2.Final]
    ... 3 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/spring/spring-jpa.xml]: Invocation of init method failed; nested exception is java.lang.NullPointerException
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1553)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:684)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
    at io.undertow.servlet.core.ApplicationListeners.contextInitialized(ApplicationListeners.java:173)
    at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:190)
    ... 7 more
Caused by: java.lang.NullPointerException
    at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:126)
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:111)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:234)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:206)
    at org.hibernate.cfg.Configuration.buildTypeRegistrations(Configuration.java:1885)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1843)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1928)
    at org.springframework.orm.hibernate4.LocalSessionFactoryBuilder.buildSessionFactory(LocalSessionFactoryBuilder.java:343)
    at org.springframework.orm.hibernate4.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:431)
    at org.springframework.orm.hibernate4.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:416)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1612)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1549)
    ... 21 more

11:26:23,733 ERROR [org.jboss.as.controller.management-operation] (DeploymentScanner-threads - 2) JBAS014613: Operation ("deploy") failed - address: ([("deployment" => "projectERP.war")]) - failure description: {"JBAS014671: Failed services" => {"jboss.undertow.deployment.default-server.default-host./projectERP" => "org.jboss.msc.service.StartException in service jboss.undertow.deployment.default-server.default-host./projectERP: Failed to start service
    Caused by: java.lang.RuntimeException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/spring/spring-jpa.xml]: Invocation of init method failed; nested exception is java.lang.NullPointerException
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/spring/spring-jpa.xml]: Invocation of init method failed; nested exception is java.lang.NullPointerException
    Caused by: java.lang.NullPointerException"}}
11:26:23,946 INFO  [org.jboss.as.server] (DeploymentScanner-threads - 2) JBAS018559: Deployed "projectERP.war" (runtime-name : "projectERP.war")
11:26:23,947 INFO  [org.jboss.as.controller] (DeploymentScanner-threads - 2) JBAS014774: Service status report
JBAS014777:   Services which failed to start:      service jboss.undertow.deployment.default-server.default-host./projectERP: org.jboss.msc.service.StartException in service jboss.undertow.deployment.default-server.default-host./projectERP: Failed to start service

Spring-jpa.xml:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:tx="http://www.springframework.org/schema/tx"
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/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
                       http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
                       http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.0.xsd
                       http://www.springframework.org/schema/context http://www.springframework.org/schema/task/spring-context-3.0.xsd">

<jee:jndi-lookup id="dataSource"
    jndi-name="java:jboss/datasources/dataSource"
    lookup-on-startup="true" proxy-interface="javax.sql.DataSource" />

<bean id="sessionFactory"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan">
        <list>
            <value>com.package.*.model</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <map>
            <entry key="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL82Dialect" />
            <entry key="hibernate.show_sql" value="true" />
            <entry key="hibernate.multiTenancy" value="SCHEMA" />
            <entry key="hibernate.multi_tenant_connection_provider"
                value="com.package.security.MultiTenantConnectionProviderImpl" />
            <entry key="hibernate.tenant_identifier_resolver"
                value="com.package.security.MultiTenantIdentifierResolverImpl" />
        </map>
    </property>
</bean>

<bean id="transactionManager"
    class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="autodetectDataSource" value="true" />
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

Persistence.xml:

<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

<persistence-unit name="persistenceUnit" transaction-type="JTA">

</persistence-unit>

MultiTenantIdentifierResolvImp.class:

package com.package.security;

import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MultiTenantIdentifierResolverImpl implements CurrentTenantIdentifierResolver {

    private static final Logger LOGGER = LoggerFactory.getLogger(MultiTenantIdentifierResolverImpl.class);

    @Override
    public String resolveCurrentTenantIdentifier() {
        String tenantResoloved = resolveCurrentTenantIdentifier();

        LOGGER.debug("Tenant Schema resolved by SchemaResolverAdmin " + tenantResoloved);

        return "public";
    }

    @Override
    public boolean validateExistingCurrentSessions() {
        return false;
    }

}

MultiTenantConnectionProvider.class:

package com.package.security;

import java.sql.Connection;
import java.sql.SQLException;

import javax.sql.DataSource;

import org.hibernate.HibernateException;
import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MultiTenantConnectionProviderImpl implements
        MultiTenantConnectionProvider {

    /**
     * 
     */
    private static final long serialVersionUID = 9064120876236832566L;

    private static final Logger LOGGER = LoggerFactory.getLogger(MultiTenantConnectionProviderImpl.class);  

    @Override
    public boolean isUnwrappableAs(Class unwrapType) {
        return false;
    }

    @Override
    public <T> T unwrap(Class<T> unwrapType) {
        return null;
    }

    @Override
    public Connection getAnyConnection() throws SQLException {
        return null;
    }

    @Override
    public void releaseAnyConnection(Connection connection) throws SQLException {

    }

    @Override
    public Connection getConnection(String tenantIdentifier)
            throws SQLException {
        final Connection connection = getAnyConnection();
        try {
            connection.createStatement().execute(
                    "SET schema " + tenantIdentifier);
        } catch (SQLException e) {
            throw new HibernateException(
                    "Could not alter JDBC connection to specified schema ["
                            + tenantIdentifier + "]", e);
        }
        return connection;

    }

    @Override
    public void releaseConnection(String tenantIdentifier, Connection connection)
            throws SQLException {
        try {
            connection.createStatement().execute("SET schema " + tenantIdentifier);
        } catch (SQLException e) {
            throw new HibernateException(
                    "Could not alter JDBC connection to specified schema ["
                            + tenantIdentifier + "]", e);
        }
        connection.close();
    }

    @Override
    public boolean supportsAggressiveRelease() {
        return false;
    }

}
    
asked by anonymous 06.02.2015 / 12:46

1 answer

3

Save!

Since you can change the implementation of TransactionManager of your application, I suggest the following approach:

applicatioContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:tx="http://www.springframework.org/schema/tx"
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/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
                       http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
                       http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.0.xsd
                       http://www.springframework.org/schema/context http://www.springframework.org/schema/task/spring-context-3.0.xsd">
    <jee:jndi-lookup id="dataSource"
        jndi-name="java:jboss/datasources/dataSource"
        lookup-on-startup="true" proxy-interface="javax.sql.DataSource" />

    <!-- EM do container -->
    <jee:jndi-lookup id="entityManager"
        jndi-name="java:comp/env/persistence/meu-em"
        lookup-on-startup="true" proxy-interface="javax.persistence.EntityManager" />

    <!-- TransactionManager do Container -->
    <bean id="transactionManager"
        class="org.springframework.transaction.jta.JtaTransactionManager">
    </bean>
</beans>

Notice that there is no setting for EntityManager here. Since we're using Wildfly, I'll let him create it. I only make reference to JNDI. Spring will do the rest.

persistence.xml

<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
    <persistence-unit name="persistenceUnit" transaction-type="JTA">
        <!-- Using the example datasource set up by WildFly 8 For your application, 
            set up a managed datasource and use that instead -->
        <jta-data-source>java:jboss/datasources/dataSource</jta-data-source>
        <!-- 
          ref.: http://docs.jboss.org/hibernate/stable/entitymanager/reference/en/html/configuration.html
         -->
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL82Dialect" />
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.multiTenancy" value="SCHEMA" />
            <property name="hibernate.multi_tenant_connection_provider" value="com.package.security.MultiTenantConnectionProviderImpl" />
            <property name="hibernate.tenant_identifier_resolver" value="com.package.security.MultiTenantIdentifierResolverImpl" />
            <!-- scan das suas entidades -->
            <property name="hibernate.archive.autodetection" value="class"/>
        </properties>
    </persistence-unit>
</persistence>

Since it is Wildfly that will manage EM you have to define it in the container itself. This file can be in your classpath and be distributed along with your application or be installed as a Wildfly module that will be used by your application. It depends on your scenario.

Now you need to reference the EM in your web application so Wildfly know you'll use the feature. In your web.xml file, add the following:

<persistence-context-ref>
    <persistence-context-ref-name>persistence/meu-em</persistence-context-ref-name>
    <persistence-unit-name>persistenceUnit</persistence-unit-name>
</persistence-context-ref>

In your data access layer, reference EntityManager via Spring injection:

@Inject
public void setEntityManager(EntityManager entityManager) {
    this.entityManager = entityManager;
}

You can use @Autowire if you do not use the common JSR-330 interfaces.

I can not test here because I have no project with configuration via xml . If you give a bough, let me know in the comments so I can get it right and help you.

As a reference, I have a project in Github using the data layer configuration via class ( @Configuration ).

    
21.07.2015 / 20:25