Results 1 to 5 of 5

Thread: Spring 3.1 - AnnotationConfigWebApplicationContext: scan vs. register method

  1. #1
    Join Date
    Feb 2012
    Posts
    9

    Default Spring 3.1 - AnnotationConfigWebApplicationContext: scan vs. register method

    Hi,

    I was playing around with the new java-config features of Spring 3.1 and I stumbled across what is either a bug or a misunderstanding of the supported behavior.

    Assume the following class definitions:

    Code:
    package com.foo;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class ComponentA {
    
    }

    Code:
    package com.bar;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class ComponentA {
    
    }
    Two classes, same simple name (same bean name), different packages. Let's also pretend that packages com.foo and com.bar also contain a bunch of different components. In a single context, I want the sum of all components defined in packages com.foo and com.bar, knowing that their would be a clash for ComponentA because it is defined in the two packages, so I tried the following:

    Code:
    package com.potato;
    
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.FilterType;
    
    @Configuration
    @ComponentScan(basePackages = {"com.foo", "com.bar"}, excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = com.foo.ComponentA.class)})
    public class TestConfig {
    
    }


    Code:
    public class Main {
    
    	public static void main(String[] args) {
    
    		AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
    		rootContext.scan("com.potato");
    		rootContext.refresh();
    		rootContext.close();
    	}
    
    }
    This throws the following exception

    Code:
    Exception in thread "main" org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'componentA' for bean class [com.bar.ComponentA] conflicts with existing, non-compatible bean definition of same name and class [com.foo.ComponentA]
    But, if I simply replace the usage of the "scan" method for the "register" method on the context, it works:

    Code:
    public class Main {
    
    	public static void main(String[] args) {
    
    		AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
    		rootContext.register(com.potato.TestConfig.class);
    		rootContext.refresh();
    		rootContext.close();
    	}
    
    }
    The reason I am using the "scan" method is because the com.potato package contains other configuration classes that I want loaded, as opposed to registering them one by one. Is this supposed to work? I put a breakpoint in "parse" method of the org.springframework.context.annotation.ComponentSc anAnnotationParser class where it seems to register the exclude filters, and when I register my config classes using the "scan" method of the AnnotationConfigWebApplicationContext, it never stops there (it does when I use the "register" method though). I know the work around is simply to register my config classes one by one, but it would be nice that it worked both ways.

    Thank you.

  2. #2
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,695

    Default

    The scan method scans for @Components and not only for @Configuration (basically you could use it to scan for your components without having a single @Configuration class), so it might be that something else is also doing a @ComponentScan (if you have other configuration classes).
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  3. #3
    Join Date
    Feb 2012
    Posts
    9

    Default

    Thanks for your reply. No, I don't have other classes. My package com.potato only contains a single class (for the moment). I debugged more and looked at the loadBeanDefinitions method of the AnnotationConfigWebApplicationContext. When registering a class through the register method, or when an entry of the configLocation property points to a class as opposed to a package, it uses the AnnotatedBeanDefinitionReader to process the specified class. When using the scan method or when an entry of the configLocation property points to a package, it uses the ClassPathBeanDefinitionScanner. The javadoc of the AnnotatedBeanDefinitionReader says "This is an alternative to ClassPathBeanDefinitionScanner, applying the same resolution of annotations but for explicitly registered classes only." Reading this, seems to me that what I was trying to do is right and there shouldn't be any difference in behavior whether you process a single class or a package name. The scenario that I outlined above shows that it's not the case. Thanks for your help. I'll open an issue in JIRA.

  4. #4
    Join Date
    Apr 2007
    Posts
    307

    Default

    The issue that Yannick opened is https://jira.springsource.org/browse/SPR-9100. I've just closed this as a duplicate of https://jira.springsource.org/browse/SPR-9031, which is resolved for Spring 3.1.1. See resolution comments there for complete details.
    Chris Beams
    Spring Framework committer, VMware
    http://github.com/cbeams

  5. #5
    Join Date
    Feb 2012
    Posts
    9

    Default

    Thanks! Sorry for the duplicate. I had seen the other one but wasn't entirely sure it was the exact same cause or that one would fix the other. I'll give it a go in 3.1.1.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •