I am working with Spring Framework 4.3.3 in a Web Environment:
I have two contexts:
RootApplicationContext
ServletApplicationContext
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
AopConfig
is scanned byRootApplicationContext
- I trust that
ServletApplicationContext
can refer that@Configuration
through 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})
RootApplicationContext
andServletApplicationContext
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:
- Spring AOP Advice on Annotated Controllers
- AspectJ does not work on Spring @Controller methods
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 @Bean
s 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
.