Christian Kalkhoff
Christian Kalkhoff

Reputation: 192

Prevent Spring from meddling with CDI annotations even for factory created instances

I have a legacy product's JAR that contain Spring (4.3.8) managed classes. I need to integrate it with CDI (JavaEE 7).

I have an interface from the legacy JAR, that is implemented by a CDI bean. The CDI bean is requested from the CDI BeanManager and returned from a factory method. The factory method is registered inside Spring XML and works as expected.

The problem occurs, when a Spring bean of the legacy JAR depends on the implemented interface. Spring than injects the CDI implementation instance and scans the class it for known annotations, namingly @Inject. It then tries to resolve the dependency, which doesn't work since the dependency is not available to Spring.

I already tweaked context:property-placeholder excludes, but that changes nothing.

So how can I tell Spring to stop trying to inject something in my factory produced bean instance?

Upvotes: 1

Views: 752

Answers (2)

Aníbal
Aníbal

Reputation: 925

It's a bit easier. AutowiredAnnotationBeanPostProcessor is already a bean, so you can configure it before Spring starts to scan with a ServletContextListener to exclude @Inject annotations. At least from Spring 4.1+, AutowiredAnnotationBeanPostProcessor has a method setAutowiredAnnotationTypes, e.g.:

@WebListener
public class ApplicationConfigListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent event) {
        ApplicationContext appCtx = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
        Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<Class<? extends Annotation>>();
        AutowiredAnnotationBeanPostProcessor bean = appCtx.getBean(AutowiredAnnotationBeanPostProcessor.class);
        autowiredAnnotationTypes.add(Autowired.class);
        autowiredAnnotationTypes.add(Value.class);
        bean.setAutowiredAnnotationTypes(autowiredAnnotationTypes);
    }
}

You could use a SpringBeanAutowiringInterceptor too. This is explained here.

Upvotes: 0

Christian Kalkhoff
Christian Kalkhoff

Reputation: 192

I finally was able to solve (work around) the problem. I had to remove all CDI-Annotations in the legacy JAR (by replacining them with their Spring counterparts), so spring would any longer work.

Then I added the following XML block to the applicationContext.xml of my CDI WAR:

<context:component-scan annotation-config="false" base-package="com.example">
</context:component-scan>
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor">
    <property name="autowiredAnnotationTypes">
        <set>
            <value>org.springframework.beans.factory.annotation.Autowired</value>
            <value>org.springframework.beans.factory.annotation.Value</value>
        </set>
    </property>
</bean>
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" />
<bean class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
    <property name="customQualifierTypes">
        <set>
            <value>org.springframework.beans.factory.annotation.Qualifier</value>
        </set>
    </property>
</bean>

Basically that drops the support for @Inject, etc. from Spring and leaves it where it belongs: CDI.

Upvotes: 0

Related Questions