11 Replies Latest reply on Jan 5, 2010 1:25 AM by meetoblivion

    Inrospect managed bean instances



      I'm trying to implement a property configuration mechanism, such that a custom annotation (not Qualifier) can be used to annotate fields of managed beans that may have an externally configured value:
      
      
      
      

      public class MyAction {
            @Configurable(page.size) private Integer pageSize;
      }

      
      
      
      An extension would introspect every bean instance, scan it for @Configurable fields and assign them a value from a property file, i.e.
      
      page.size=5





      Would would be the appropriate extension hook (event?) to use? How do I access managed bean instances after they are initialized? I guess I'm after something that is semantically equivalent of javax.annotation.PostConstruct that could be applied systematically to all managed beans.


      /johan

        • 1. Re: Inrospect managed bean instances


          I guess the requested approach is not in scope for CDI. I ended up with a solution based on producers:
          
          public class MyBean {
             @Inject @Configurable(page.size) private Integer pageSize; 
          }
          
          
          This is then supported by a framework that declares a @Configurable InjectionPoint producer method for each supported type, each delegating value retrieval to an injected ExternalPropertySource:
          
          
          
          ExternalPropertySource is an interface with the following method:
          
          public String getFromExternalPropertyConfig(InjectionPoint injectionPoint, Configurable a);
          
          One of the implementations retrieves values from property files.
          
          To summarize: the framework ("extension") declares the following types:
          
          Configurable (annotation)
          ExternalPropertyProducer (class that depends on ExternalPropertySource)
          ExternalPropertySource (interface)
          PropertyFilePropertySource (class that implements ExternalPropertySource)
          
          /Johan




          • 2. Re: Inrospect managed bean instances
            meetoblivion

            So I'm a bit confused.  You're not actually introspecting anything, right?  Since you're @Inject @Configurable(page.size) it just injects there, right?


            How do you determine what property file to read from?


            So like I mentioned on twitter, I also started working on something similar.  The use case is like this:


            @Inject @LoadedProperties(filename="/conf/myprops.properties") Properties props;


            Where the Properties object is an extension of java.util.Properties that has a few more methods - getInt, getLong, etc.  LoadProperties has a few more capabilities: XML format for properties, classpath support (not implemented yet), and timer based polling (not implemented yet).


            I'm not sure if it makes sense, maybe we could work together to make something that more people could use?  I was planning to release mine as APL2.  There's a google code page up - google code


            I'm not sure if you were looking to make yours more complex, e.g. database support.

            • 3. Re: Inrospect managed bean instances
              nickarls

              I assume Seam 3 will also have some sort of module for accessing properties from different sources (file, DB, JNDI etc). I haven't thought about it that much but I would assume it's just providing producer methods for the various approaches and have them fetch/inject the right stuff...

              • 4. Re: Inrospect managed bean instances
                nickarls

                (And yes, timeout based lazy loading would be nice. As well as manual invalidation)

                • 5. Re: Inrospect managed bean instances

                  I was after a CDI-sh version of this: My Link


                  The architecture I elaborated looks like this:


                  Injection point is property in an application bean:




                  @ConfigurationNS("myapp")
                  public class MyBean {
                     @Inject @Configurable("my.property") private int receiveTimeout;
                     ...
                  }





                  The use of @ConfigurationNS(myapp) depends on the specific implementation of a resolution mechanisms.


                  Then a framework producer class supporting a defined set of simple types:




                  public class ExternalPropertyProducer {
                          private @Inject ExternalPropertySource propSource;
                          
                          @Produces
                          @Configurable
                          public int produceInteger(InjectionPoint injectionPoint) {
                                  Configurable a = injectionPoint.getAnnotated().getAnnotation(
                                                  Configurable.class);
                                  return new Integer(propSource.getFromExternalPropertyConfig(injectionPoint, a));
                          }
                  
                          // ...etc for other configurable simple types...not sure whether conversion should be in producer or in ExternalPropertySource....
                  }
                  




                  Then an open end of implementations for ExternalPropertySource, one of which supports traditional property files. It would use value() from @ConfigurationNS(myapp) plus value from @Configurable(my.property) to build the property name. It would provide defaults based on injection point metadata for both of them. @ConfigurationNS would be optional. @Configurable would be required (value() defaults to empty string though). File name is provided as System Property supporting classpath: URL.


                  /Johan

                  • 6. Re: Inrospect managed bean instances
                    nickarls

                    Mmm, OK, I can see the general direction.


                    At which point would you give the configuration options that vary by provider type (JNDI name, DB datasource, filename etc)? Would they be separate annotations?

                    • 7. Re: Inrospect managed bean instances
                      meetoblivion

                      So my general thought is that this will end up being a lot of code to implement, in each application.


                      Now that I'm thinking about it, I think having an application scoped bean that handles source registration would actually make a lot of sense.




                      @ApplicationScoped
                      @Singleton
                      @Startup
                      public class PropertySourceHolder {
                      public void registerSource(Source source);
                      public PropertyContainer getProperties(String name);
                      }




                      What happens then is you have a @PostConstruct Singleton as well




                      @ApplicationScoped
                      @Singleton
                      @Startup
                      public class MyCustomPropertyRegister {
                      @Inject PropertySourceHolder sourceHolder;
                      @PostConstruct
                      public void init() {
                      sourceHolder.registerSource(new PropertyFileSource("/path/to/file","myname"));
                      sourceHolder.registerSource(new DBPropertiesSource("table_name","key_column","value_column","datasource_name","myname"));
                      //and so on..
                      }
                      }



                      You could then do some fancy injections:




                      @Inject @Configured("source_name") Map<String,String> props;
                      @Inject @Configured("source_name") Properties props; //and like I mentioned above, you could make Properties an extension of java.util.Properties
                      @Inject @Configured("source_name") Source props;
                      @Inject @Configured(source="source_name",propName="some.key") Instance<Integer> someInt;





                      then the application developer doesn't need to worry about writing some custom producers.  The down side (which I'm not sure if it's a down side or not) is that you need to be running w/ EJB 3.1 Lite minimum in this setup.

                      • 8. Re: Inrospect managed bean instances

                        The mechanism I'm after is one that will be used the same way regardless of environment. If it is OK to bind to J2EE and associated deployment processes, env entries via @Resource is fine. A very small minority (close to neglectable, I would say) of the solutions I see being built use anything else than file-based (90%) or db-based (10%) configuration.


                        For a java.util.Properties-based solution I would say that the existing apache solution is just fine. What I'm looking for is a solution to conveniently inject (file-configured) values. With Spring, you are (I think) limited to have a single property source per application context. I've never seen that being considered a limitation. So from my perspective, it is good enough to be able to provide an API-module consisting of the ExternalPropertySource interface and the ExternalPropertyProducer class, and then have optional framework bean archives that each implement the ExternalPropertySource. My app would always have a dependency to the api jar and then select the jar with the ExternalPropertySource implementation that I want to be default-injected into the ExternalPropertyProducer of the api bean archive. If my app needs a property file property source, I put that archive on my classpath and make sure the deployment instructions document the required system property to be set on the test case / Javee appserver console / shell script etc / whatever applies. If my app needs a db property source, I'd make sure the selected ExternalPropertySource implementation bean archive on my classpath etc.


                        /Johan

                        • 9. Re: Inrospect managed bean instances
                          nickarls

                          Not a big fan of application-scoped stuff, you always have the hmm, how do we reset this thing-problem. I prefer to keep stuff session-scoped unless there's a strong case for it.

                          • 10. Re: Inrospect managed bean instances

                            Not sure we are sharing use-cases here? I'm looking for a mechanism to configure the value of bean properties at deploy-time.


                            /Johan

                            • 11. Re: Inrospect managed bean instances
                              meetoblivion

                              @Johan


                              The way I see it, your use case is a specialized version of my use case.  In mine, I'm looking to access those properties via a Map or a Properties object.  In yours, you want to inject the actual key value into a bean member.  I see no issue with this approach, and a little bit of merit.  It's just not my ideal way to work on it.  I don't see a reason to limit the source types - I just proposed two, but there should be no reason that others cannot implement a new source, and hopefully the code would be robust enough that it could evolve without needing the framework around it.


                              @Nicklas


                              I don't think I was proposing that the configs would always be application scoped.  I think by default they'd all be dependent.  The idea I was throwing out there was the configuration of the property sources - e.g. some from files, which files, some from database, what table, what columns, etc, would be stored in an application scoped bean.  Of course, that's only because I'm thinking without an extension object.  I don't see a reason why we couldn't, using an extension, allow for the configuration of new property types in other scopes.  I'm not sure I see much of a benefit in this case, but at the same time I wouldn't immediately exclude it.