0

Our Spring MVC web app is trying to follow the recommended style. It uses AppContext (ContextLoaderListener) to store the DAO's and Services. It uses WebAppContext (DispatcherServlet) to store Controllers.

The DAO objects are getting into both the AppContext and the WebAppContext. I don't understand why.

The AppContext config is supposed to load everything except the Controllers (and a class that loads code tables into the ServletContext):

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true)
@EnableTransactionManagement
@EnableScheduling
@ComponentScan(
  basePackages = {"blah"},
  excludeFilters = {
    @Filter(type = FilterType.ANNOTATION, value = {Controller.class}),
    @Filter(type = FilterType.ASSIGNABLE_TYPE, value = LoadOnStartup.class) 
  } 
)
public class SpringRootConfiguration {

and the web part is supposed to load the Controllers only:

@Configuration
@EnableWebMvc
@ComponentScan(
 basePackages = {"blah"},
 includeFilters = @Filter(type = FilterType.ANNOTATION, classes={Controller.class})
)
public class SpringWebConfiguration extends WebMvcConfigurerAdapter {

(The above classes are in a separate package that is a sibling to 'blah'; there's no self-scanning going on).

Of course, the Controllers reference DAO objects. In the Controller, those DAO objects are @Autowired.

My expectation was that those @Autowired DAO objects are retrieved from the AppContext, and not created a second time, and placed in the WebAppContext. But I think they are being created a second time. For example, this line appears twice in the log, once for AppContext, and once for WebAppContext:

Creating shared instance of singleton bean 'labelDao'

Am I missing something?

It's as if the parent-child relation between the root context and the web context is missing.

John
  • 1,635
  • 15
  • 22
  • 1
    You are missing `useDefaultFilters=false` on the `SpringWebConfiguration`. Including something doesn't automatically exclude everything else, i.e. the defaults. – M. Deinum Feb 24 '16 at 13:38
  • I am not at expert in Spring (not even close) but... I believe that beans/@Component/@Repository are singletons by default. This may help: http://stackoverflow.com/questions/28039901/spring-repository-best-practices – kazbeel Feb 24 '16 at 13:41
  • @M. Deinum - that's the fix... If you add an answer (as opposed to a comment), I will accept it as the correct one. – John Feb 24 '16 at 17:48

1 Answers1

2

When using an include filter that doesn't automatically mean that the defaults are disabled. By default @ComponentScan will detect all @Component classes, regardless of what yu specify by the include. So if you want to explicitly to control which annotations to scan you first have to disable the defaults. To do set the useDefaultFilters attribute of @ComponentScan to false.

@ComponentScan(
 basePackages = {"blah"},
 useDefaultFilters=false,
 includeFilters = @Filter(type = FilterType.ANNOTATION, classes={Controller.class})
)

Now it will only detect @Controller annotated beans.

M. Deinum
  • 115,695
  • 22
  • 220
  • 224