Announcement Announcement Module
Collapse
No announcement yet.
Programmatically @Import multiple configuration classes. Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Programmatically @Import multiple configuration classes.

    Hey,

    This trouble is related with the java-based configuration model for Spring.
    I'm having a lots of problems trying to programmatically import configuration classes from one external @Configuration class.
    The situation is as follows:

    - I have on class annotated as @Configuration that reads one properties file with the corresponding @PropertySource annotation and access to the properties in that file by using the Environment

    Code:
    @Configuration
    @PorpertySource("........")
    public class ConfigurationBig(){
      @Autowired 
      private Environment env;
      
      ....
    }
    - I have also some other @Configuration classes defined

    Code:
    @Configuration
    public class ConfigurationOne(){
      ....
    }
    @Configuration
    public class ConfigurationTwo(){
      ....
    }
    @Configuration
    public class ConfigurationThree(){
      ....
    }
    I know that in order to do the import I should add the annotation @Import({ConfigurationOne.class,ConfigurationTwo.c lass,ConfigurationThree.class}) but the problem is...What if I don't know now and only in Runtime the number of configuration files (and also the name) that should be imported? I want the user to be able to state in the property file (lets say property "configurationClases") which classes he wants to be imported (by stating "configurationClases=ConfigurationOne,Configuratio nTwo,ConfigurationThree").

    Any ideas so far?

    Thank you in advance !

    Shagrash

  • #2
    @Configuration classes are @Components and as such can be scanned/detected. So there isn't a need to specify all of them...

    Comment


    • #3
      I know that...but there really is a need in this case because I just want these specific configuration files to be imported (not only detected, but imported so that the main application context can also beans from the ConfigurationX classes just by charging the ConfigurationBig class)
      Maybe I'm not getting what you mean...

      Comment


      • #4
        I strongly suggest a read of the reference guide...

        @Configuration classes can be automatically detected and as such are added as other @Configuration classes... The same way you could import/load xml files with a certain convention like *-context.xml would load all xml files ending with -context.xml and construct and applicationcontext from that.

        You can do the same with @Configuration classes, component-scanning can detect those and will use them to build the application context.

        Comment


        • #5
          Ok. I can make the application context to add all the configuration classes that he can find. But the problem is doing that automatically and from the main Configuration class so the structure would be something like:
          Code:
          ApplicationContext appCtx = new AnnotationConfigApplicationContext(ConfigurationBig.class);
          appCtx.getBean("beanOne");
          where beanOne is a bean defined in the configuration class ConfigurationOne.

          Code:
          @Configuration
          public class ConfigurationOne{
            @Bean
            public String beanOne(){
                ...... 
            }
          }
          In that way, the final user don't have to change the code everytime he want's to add a new configuration file, he just have to specify the name of the class in the properties file and Spring will do the rest...
          The problem is that I don't want to do specific calls to the applicationContext.register(...) because after that I should call refresh() over the applicationContext and then I got an IllegalStateException for multiple refresh attemps...
          I have tried to implement this on the constructor of the ConfigurationBig class (it gives me NullPointerException because the Environment is not wired yet and so I can't access the properties file) and also with the @PostConstructor annotation (there I got the IllegalStateException if I try to refresh or simply a NotBeanFoundException if I don't call refresh )

          Comment


          • #6
            Read...

            @ComponentScan detects @Configuration classes (as mentioned before twice) you don't have to register them they will be detected, constructed and used to build the application context.

            Comment


            • #7
              I already understood that you can scan all the components with the @ComponentScan. That I already know it. The problem is how can I let the user to explicitly specify which ones he want to scan by modifying one properties document.
              So the question could be rewritten as: How can I access Enviroment properties within a @ComponentScan annotation?
              Code:
              @Configuratio
              @ComponentScan(env.getProperty("configurationClases"))
              public class ConfigurationBig{
              ...
              }

              Comment


              • #8
                You cannot... Why do you want to burden the user with specifing which configuration classes to use instead of automatically pick up the files...

                Comment


                • #9
                  Because is not for the "user". I'm developing one logging module and I want other developers to be able to provide different's ways of making the log (let's say, DAO with hibernate and JPA, memory, remote logging...) just by creating the java class that implements the interface with their corresponding configuration class, and so they you just have to go to the properties file and change the field to specify which "ways" of loggin they want to apply (I'm trying to apply Strategy pattern).
                  The idea was to read the properties file and then apply the same method (in this case 'log') in all the ways found there, each one with his corresponding configuration file...
                  I think is not a bad idea as long as let you a lot of flexibility but if it's not possible.... I would have to think another way to do it...

                  Comment

                  Working...
                  X