Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it a bad idea to use both XML and annotation config in a single project with Spring?

I have a single .war app that uses Spring and initializes it's context in two different ways. It uses both annotation config and XML config. So my firs question is:

Is this always a bad practice and what problems can it lead to ?

Secondly it uses both annotations and XML because it sets up its REST controllers using annotations and its Services/DAOs using XML.

Now I have an advice that works great on the services, but doesn't fire at all if used on the REST controllers.

This is a relevant part of it:

@Aspect
public class SessionAwareAspect {

    private SessionManager sessionManager;

    private EngineActionResolver actionResolver;

    @Around("@annotation(sessionAware)")
    public Object authenticate(final ProceedingJoinPoint invocation, SessionAware sessionAware) {

        // some logic
    }

    @Required
    public void setSessionManager(SessionManager sessionManager) {
        this.sessionManager = sessionManager;
    }

    @Required
    public void setActionResolver(EngineActionResolver actionResolver) {
        this.actionResolver = actionResolver;
    }
}

It is initialized in the context like so:

<bean id="sessionAwareAspect" class="cayetano.pplive.core.session.SessionAwareAspect">
    <property name="sessionManager" ref="sessionManager"/>
    <property name="actionResolver" ref="engineActionResolver" />
</bean>

<aop:aspectj-autoproxy>
    <aop:include name="sessionAwareAspect" />
</aop:aspectj-autoproxy> 

So my second question is:

Is the fact that the context is initalized both with annotations and XML the reason why the aspect won't fire on the controllers ? If so how can I make it work ?

Thanks,


Some additional info from the deployment logs.

This is how the XML beans get instantiated:

Nov 01, 2013 1:02:09 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
[list of DAOs/Services]

.... irrelevant log
.... 50/100 lines after

Nov 01, 2013 1:02:22 PM org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor <init>
INFO: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
Nov 01, 2013 1:02:22 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
[list of REST controllers]

So if this actually creates 2 seperate bean contexts (does it ?), could it be the case that the aspect doesn't exist at all in the annotation initialized context ?

Thanks again,

like image 516
Simeon Avatar asked Nov 01 '13 11:11

Simeon


2 Answers

Which ways of configuring you use doesn't matter, you can mix and match XML/Annotations/Java and even properties files to express your bean configuration. How you mix/match those doesn't matter.

One thing to keep in mind is that Bean(Factory)PostProcessors only operate on beans in the same ApplicationContext as they are defined in. <aop:aspectj-autoproxy > registers a BeanPostProcessor which creates proxies and applies the advices (aspects) to beans. If this is defined in the context loaded by the ContextLoaderListener it will do nothing for beans which are in the context loaded by the DispatcherServlet.

Simply add the aspect and <aop:aspectj-autoproxy > to both configurations and your aspects should work. If not, you might need to force creation of class-based proxies (<aop:aspectj-autoproxy proxy-target-class="true">), this is the case if you your classes don't implement an interface (or only marker interfaces like Serializable).

like image 96
M. Deinum Avatar answered Sep 22 '22 18:09

M. Deinum


Turns out that the problem was in fact two separate contexts explicitly defined in the web.xml, that I didn't know of. One was simply missing the aspect.

As far as I've read so far it's not bad to use both annotation based and XML based config (apart from the fact that it's a bit inconsistent). It is even recommended in some cases.

like image 29
Simeon Avatar answered Sep 19 '22 18:09

Simeon