1

I am trying to use an entityInterceptor to log changes on certain objects for purposes of Audit trail.

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>   
        <property name="entityInterceptor">    
            <bean class="x.y.z.PropertyChangeInterceptor"/>  
        </property>         
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                ------ ------
            </props>
        </property>
        <property name="packagesToScan">
            <array>
                <value>x.y.z</value>
            </array>
        </property>
    </bean>

I had custom change listeners for the object I want to monitor to PropertyChangeInterceptor constructor and it has override methods for onFlushDirty,onSave, and postFlush.

 public PropertyChangeInterceptor() {
   listeners = new HashMap<>();
       listeners.put(Customer.class, new CustomerChangeListener());
   }

Now the problem comes in my CustomerChangeListener class. I am injecting a service that I intend to use to save the audit logs to my database. The service throws a nullpointer exception when I try to use it. Interesting enough is the fact that this service works well on all my other Controllers except in this class. The class implement PropertyChangeListener.

@Component
public class CustomerChangeListener implements PropertyChangeListener<Customer> {

    Logger log = LoggerFactory.getLogger(CustomerChangeListener.this.getClass());

    @Resource(name = "audittrailService")
    private ServiceInterface audittrailService;
       ......
       ......
 @Override
    public void logIt(String action, Object entity) {
        try {
            audittrailService.findById(1); **<==Error Occurs here**
            ..........
            audittrailService.save(trail);
        } catch (UnknownHostException uhe) {
            log.error("Error Saving audit trail -UnknownHostException", uhe);
        } catch (Exception e) {
            log.error("Error Saving audit trail", e);
        }
    }

I believe my Spring Anotation configs are ok since they work on other classes.

<!-- Enable Spring Annotation Configuration -->
    <context:annotation-config/>

    <aop:aspectj-autoproxy proxy-target-class="true" />

    <!-- Necessary to get the entity manager injected into the factory bean -->
    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /> 

    <!--Enable Spring's Exception Translation Mechanism-->
   <!-- Enable Spring Annotation Configuration -->
    <context:annotation-config/>

    <aop:aspectj-autoproxy proxy-target-class="true" />

    <!-- Necessary to get the entity manager injected into the factory bean -->
    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /> 

    <!--Enable Spring's Exception Translation Mechanism-->
    <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

    <context:component-scan base-package="com.anchor.anchorfused4.Service"/>
    <context:component-scan base-package="..."/>
    <context:component-scan base-package="..."/>
    <context:component-scan base-package="com.anchor.anchorfused4.Listeners"/>

Here is the error log.

Severe:   java.lang.NullPointerException
at com.anchor.anchorfused4.Listeners.CustomerChangeListener.logIt(CustomerChangeListener.java:59)
at com.anchor.anchorfused4.Listeners.PropertyChangeInterceptor.postFlush(PropertyChangeInterceptor.java:107)
at org.hibernate.event.internal.AbstractFlushingEventListener.postFlush(AbstractFlushingEventListener.java:388)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:53)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1234)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:404)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:558)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:757)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:726)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:496)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:276)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653)
at com.anchor.anchorfused4.Service.Impl.CustomerService$$EnhancerBySpringCGLIB$$3bf59009.update(<generated>)
at com.anchor.anchorfused4.Controller.CustomerController.updateCustomer(CustomerController.java:280)

Startup log as requested by @dit

Info:   GlassFish Server Open Source Edition  4.1  (13) startup time : Felix (6,084ms), startup services(1,620ms), total(7,704ms)
Info:   Grizzly Framework 2.3.15 started in: 2ms - bound to [/0.0.0.0:7676]
Info:   HV000001: Hibernate Validator 5.0.0.Final
Info:   JMXStartupService has started JMXConnector on JMXService URL service:jmx:rmi://user-PC:8686/jndi/rmi://user-PC:8686/jmxrmi
Info:   Registered com.sun.enterprise.glassfish.bootstrap.osgi.EmbeddedOSGiGlassFishImpl@55b89494 as OSGi service registration: org.apache.felix.framework.ServiceRegistrationImpl@6e889444.
Info:   Grizzly Framework 2.3.15 started in: 8ms - bound to [/0.0.0.0:8080]
Info:   Grizzly Framework 2.3.15 started in: 15ms - bound to [/0.0.0.0:8181]
Info:   visiting unvisited references
Info:   Java security manager is disabled.
Info:   Entering Security Startup Service.
Info:   Loading policy provider com.sun.enterprise.security.provider.PolicyWrapper.
Info:   Security Service(s) started successfully.
Info:   Created HTTP listener http-listener-1 on host/port 0.0.0.0:8080
Info:   Created HTTP listener http-listener-2 on host/port 0.0.0.0:8181
Info:   Created HTTP listener admin-listener on host/port 0.0.0.0:4848
Info:   Created virtual server server
Info:   Created virtual server __asadmin
Info:   Setting JAAS app name glassfish-web
Info:   Virtual server server loaded default web module 
Info:   Initializing Mojarra 2.2.7 ( 20140610-1547 https://svn.java.net/svn/mojarra~svn/tags/2.2.7@13362) for context '/MinjaAnchorERP'
Info:   SecretKey: J8WnmCmANrta3jQL3rPITA==
Info:   Running on PrimeFaces 5.3
Info:   Running on PrimeFaces Extensions 4.0.0
Info:   WebModule[null] ServletContext.log():Initializing Spring root WebApplicationContext
Severe:   [admin-listener(5)] INFO org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization started
Severe:   [admin-listener(5)] INFO org.springframework.web.context.support.XmlWebApplicationContext - Refreshing Root WebApplicationContext: startup date [Mon Sep 05 12:37:49 EAT 2016]; root of context hierarchy
Severe:   [admin-listener(5)] INFO org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from ServletContext resource [/WEB-INF/config/web-application-config.xml]
Severe:   [admin-listener(5)] INFO org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from ServletContext resource [/WEB-INF/config/data-access-config.xml]
Severe:   [admin-listener(5)] INFO org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from ServletContext resource [/WEB-INF/config/webflow-config.xml]
Severe:   [admin-listener(5)] INFO org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from ServletContext resource [/WEB-INF/config/webmvc-config.xml]
Severe:   [admin-listener(5)] INFO org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from ServletContext resource [/WEB-INF/config/security-config.xml]
Severe:   [admin-listener(5)] INFO org.springframework.security.core.SpringSecurityCoreVersion - You are running with Spring Security Core 3.2.5.RELEASE
Severe:   [admin-listener(5)] INFO org.springframework.security.config.SecurityNamespaceHandler - Spring Security 'config' module version is 3.2.5.RELEASE
.......
.......
Severe:   [admin-listener(5)] INFO com.anchor.anchorfused4.Listeners.PropertyChangeInterceptor - Init
Info:   HCANN000001: Hibernate Commons Annotations {4.0.2.Final}
Info:   HHH000412: Hibernate Core {4.2.4.Final}
Info:   headless=true
Severe:   [admin-listener(5)] INFO com.anchor.anchorfused4.Listeners.CustomerChangeListener - init CustomerChangeListener
Severe:   [admin-listener(5)] INFO com.anchor.anchorfused4.Listeners.PropertyChangeInterceptor - Init
Severe:   [admin-listener(5)] INFO com.anchor.anchorfused4.Controller.PermissionMapController - Init
Severe:   [admin-listener(5)] INFO org.springframework.cache.ehcache.EhCacheManagerFactoryBean - Initializing EhCache CacheManager
S.Serem
  • 101
  • 2
  • 12

1 Answers1

2

I managed to fix the issue.

I realized I needed to Autowire the custom class CustomerChangeListener instead of creating it using new CustomerChangeListener(), but Autowiring this class refused to work. The project could not even start unlike earlier where it threw exception on save.

A little research based on this new error and I found the reason for the null pointer on the classes injected via spring annotation is because the entityInterceptor is hibernate managed and not spring managed.

The answer here https://stackoverflow.com/a/25275333/2576937 helped a lot.

In addition to creating the DelegateInterceptor I had to move the listeners from the PropertyChangeInterceptor constructor to its @PostConstruct

public PropertyChangeInterceptor() {
   //listeners = new HashMap<>(); 
   //listeners.put(Customer.class, new CustomerChangeListener());
}

@PostConstruct
public void init() {
    StaticDelegateInterceptor.setInterceptor(this);
    listeners = new HashMap<>(); //move to here
    listeners.put(Customer.class, customerChangeListener);
}
Community
  • 1
  • 1
S.Serem
  • 101
  • 2
  • 12
  • Also, we should not use @Resource annotation on service layer, instead it is meant for dao layer – Sandeep Sep 06 '16 at 06:39