I am working with Spring Framework 4.3.3 in a Web Environment:
I have two contexts:
RootApplicationContextServletApplicationContext
I know the ServletApplicationContext contains all the beans about the web side, for example @Controller. Furthermore ServletApplicationContext is able to access all the context or beans from the RootApplicationContext for example @Service, @Repository etc. Until here I am fine.
Note it applies for @Configuration classes too. (Infrastructure)
Therefore with the previous introduction we can think in the following way:
ServletApplicationContext-->RootApplicationContext
Something important to take in consideration is that the inverse is not possible.
Therefore
RootApplicationContext-->ServletApplicationContext
is not possible. It has sense and is Ok. Server side should not access the Web side
About AspectJ. I have the following:
@Configuration
@EnableAspectJAutoProxy
public class AopConfig {
}
Here one important point:
- This
AopConfigis scanned byRootApplicationContext- I trust that
ServletApplicationContextcan refer that@Configurationthrough the access ofRootApplicationContext
- I trust that
Ok, when I run my @Test methods.
When I execute a Test class from the server side I use
@ContextConfiguration(classes={RootApplicationContext.class} )- Only
RootApplicationContext
- Only
And AOP works fine. I can confirm through AOP + logging the following process:
@Service->@Repository
When I execute a Test class from the Web side I use:
@ContextConfiguration(classes={RootApplicationContext.class, ServletApplicationContext.class})RootApplicationContextandServletApplicationContext
And AOP works fine. I can confirm through AOP + logging the following process:
@Controller->@Service->@Repository
Now for production I have:
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[]{RootApplicationContext.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[]{ServletApplicationContext.class};
}
But when I export the project for a .war file and through an URL/URI a Controller is executed the expected behaviour or process works fine. But about AOP through AOP + logging the following process happens:
@Service->@Repository
@Controller does not appear for the output. The expected flow process should be:
@Controller->@Service->@Repository
So why works in Testing and not in production?
I already did a research and I have found these two posts:
Practically they say that the @Configuration class with @EnableAspectJAutoProxy should be scanned through ServletApplicationContext and not through RootApplicationContext
Even when it is true (according with new experiments), consider that Server side should be tested without a Web Environment.
For other @Beans about infrastructure through @Configuration the relation already explained about ServletApplicationContext --> RootApplicationContext works how is expected. Just with AOP has this situation.
Question 01: So why this behaviour?
Question 02: How keep the AopConfig scanned by RootApplicationContext and get the expected behaviour for production?
Note if AopConfig is scanned by ServletApplicationContext. The following about testing is valid and mandatory for the server side @ContextConfiguration(classes={RootApplicationContext.class, AopConfig.class} ). See the addition of AopConfig.class but I think AopConfig should be scanned by RootApplicationContext.