Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I customize the AuditingHandler injected by Spring-Data when using Auditing?

I'm using Spring Data 1.5 and Auditing. Part of the AuditingEntityListener has a setAuditingHandler method.

How can I customize the AuditingHandler and instruct Spring-Data to inject my custom handler instead of the default org.springframework.data.auditing.AuditingHandler?

I've tried instantiating my own AuditingEntityListener in which I inject my own Handler, but that is not doing the job. The default handler is still being injected. I've tried both via XML configuration and JavaConfig to see if one worked better than the other, but neither way works.

JavaConfig:

@Configuration
@EnableJpaAuditing(auditorAwareRef="auditorProvider")
public class AppConfig {

    @Bean
    public AuditorAware<User> auditorProvider(){
        return new SpringSecurityAuditorAware();
    }

    @Bean
    public AuditingEntityListener auditingEntityListener(){
        AuditingEntityListener listener = new AuditingEntityListener();
        listener.setAuditingHandler(new com.ia.persistence.AuditingHandler());
        return listener;
    }
}

My custom handler:

@Component
public class AuditingHandler extends  org.springframework.data.auditing.AuditingHandler {

    // SLF4J logger
    private static final Logger logger = LoggerFactory.getLogger(AuditingHandler.class);

    /* (non-Javadoc)
     * @see org.springframework.data.auditing.AuditingHandler#markCreated(java.lang.Object)
     */
    @Override
    public void markCreated(Object source) {
        logger.info("Custom handler");
        super.markCreated(source);
    }

    /* (non-Javadoc)
     * @see org.springframework.data.auditing.AuditingHandler#markModified(java.lang.Object)
     */
    @Override
    public void markModified(Object source) {
        logger.info("Custom handler");
        super.markModified(source);
    }
}

What am I doing wrong? With my JavaConfig, I do not even see Spring instantiating the listener using my configuration. Alternatively, I've tried using XML configuration to configure the listener, but the default listener is still the one that is used.

    <!-- enable Spring data-JPA repositories -->
    <jpa:repositories base-package="com.ia" />

    <bean id="auditingEntityListener" class="org.springframework.data.jpa.domain.support.AuditingEntityListener">
        <property name="auditingHandler" ref="auditingHandler"/>
    </bean>

Any suggestions would be helpful.

like image 274
Eric B. Avatar asked Mar 13 '14 03:03

Eric B.


1 Answers

I met the same question.

The short version

You have to register jpaAuditingHandler bean definition using BeanDefinitionRegistry.

The long version

the org.springframework.data.jpa.domain.support.AuditingEntityListener is a special class which mixed in with aspectj when compiling. see here

It need a bean definition to work. see the spring framework document.

the org.springframework.data.jpa.repository.config.EnableJpaAuditing you are using will register the bean definition with auditingHandler bind to a jpaAuditingHandler bean. It also will register the jpaAuditingHandler bean definition.

If you add a jpaAuditingHandler using @Component, it won't work because Spring prefer another one. see org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForConfigurationClass

So you have to register your bean definition using BeanDefinitionRegistry.

public class jpaAuditingHandlerRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        registry.registerBeanDefinition("jpaAuditingHandler", BeanDefinitionBuilder
                .rootBeanDefinition(JpaAuditingHandler.class)
                .addConstructorArgReference("jpaMappingContext")
                .getBeanDefinition());
    }
}

and add @Import(JpaAuditingHandlerRegistrar.class) to your Configuration class

@SpringBootApplication
@EnableJpaAuditing
@Import(JpaAuditingHandlerRegistrar.class)
public class Application {

I put sample code https://github.com/macdao/customize-auditing-handler

like image 168
Macdao Avatar answered Oct 08 '22 21:10

Macdao