1 2 Previous Next 23 Replies Latest reply on Jan 3, 2010 5:45 AM by meetoblivion Go to original post
      • 15. Re: Dynamic Injection
        asookazian

        type-safety?


        @MessageBus(topic="deals")


        I thought quotes were not allowed in annotations for type-safety?


        Otherwise, I don't follow the purpose to begin with.  Why do you need to inject the configured objects?  What is the advantage of configured objects?


        Sorry, this one went over my head...

        • 16. Re: Dynamic Injection
          gavin.king
          type-safety?

          @MessageBus(topic="deals")

          I thought quotes were not allowed in annotations for type-safety?


          It's just an example. This might be a JNDI name of a JMS topic. It's just like @Resource(lookup="jndiName").



          Otherwise, I don't follow the purpose to begin with.  Why do you need to inject the configured objects?  What is the advantage of configured objects?

          Sorry, this one went over my head...


          Then don't worry about it. This stuff is a very advanced feature for framework developers. John will understand what I'm talking about.

          • 17. Re: Dynamic Injection
            meetoblivion

            Gavin King wrote on Dec 29, 2009 22:42:


            Then don't worry about it. This stuff is a very advanced feature for framework developers. John will understand what I'm talking about.


            I can't tell if this is a compliment or not. heh.


            This is the trouble I'm having.  Most importantly, I agree wholehearted that XML is not the answer, however what I think we're missing is an abstraction level that would allow us to define any random thing we want and throw it in there, similar to how XML namespaces work.  Spring did this with the p namespace way back.  Basically, a developer was able to define any property they wanted in spring by created a bean and marking it p:camelCase="value".  It wasn't perfect, it didn't support ref beans properly, but it did the trick most of the time.  It seems really odd that my idea won't work,.  Then again, the last time I played with stuff like this was when webbeans didn't support servlet inject and I had to lookup the manager on java:app/Manager (which now, it's not called Manager and it's not found there).  I have to keep fluttering around with my idea a bit more.  I think for the short term, a work around I've come up with is a @Produces in a Singleton, where the singleton maintains a HashMap of String,JcrEngine ; string being the file and JcrEngine being the associated engine.  I only need to produce Sessions and I have everything I need to make the session.  If that won't work, for me it's more important that the code works rather than it's using Weld properly.


            I have to dig a bit deeper into extensions too, as I'm not sure it's even going to do what I need it to do.  Another thing, looking at your previous remarks, I think you might be over complicating the need based on how I've stated it.  An instance of javax.jcr.Repository has to be, by definition, ApplicationScoped, once the application's up, the Repository config itself cannot be modified.  Simiarly, the javax.jcr.Session will always be RequestScoped, possibly SessionScoped.  I'm not looking for anything as complex as an SMPC, there's just no benefit to it at this point.  Each instance of Session should follow the same life cycle - you login to the repo (to get your session, kind of like the PostConstruct), do some unit of work, then on destroy save the session.


            To be perfectly honest, I've already gotten my code to kind of work, but it didn't allow me to be more generic.  In the POC application we only had one repo.  The real version has to have 4 repos in it.  I'm also using the Factory pattern to get an instance of the Repo/Engine.



            @Named("sessionWrapper")
            @RequestScoped
            public class JcrSessionWrapper implements java.io.Serializable{
                 @Inject SecurityContext securityContext;
                 private static final Logger logger = Logger.getLogger(JcrSessionWrapper.class);
                 Session session;
                 @PostConstruct
                 public void postConstruct() {
                      try{
                           Repository repo = DNARepositoryFactory.getInstance().getRepository();
                           this.session = repo.login(new SecurityContextCredentials(securityContext));
                      } catch (RepositoryException e) {
                           logger.error("Error loading repository",e);
                      }
                 }
                 
                 @PreDestroy
                 public void destroy() {
                      try{
                           session.save();
                           session.logout();
                      } catch (RepositoryException e) {
                           logger.error("Error saving repository",e);
                      }
                 }
                 @Produces @WrapperType @RequestScoped
                 public Session getSession() {
                      return session;
                 }
            }



            Different Actions will end up using different repos.  I guess in the simpler use case, limiting it to a single JcrEngine (since you really don't need multiple) should suffice, and then wrapping the JcrEngine in a bean like above to get Sessions would also work, with the minor change that the producer becomes




            @Produces @Qualifier @RequestScoped
            public Session getSession(InjectionPoint ip) {
            ...
            }



            Where I'd just have to keep track of the open sessions within the bean and save them on completion.

            • 18. Re: Dynamic Injection
              william.drai

              @Produces
              @MessageBus(topic="default") 
              Topic topic;
              
              @Produces @Prices 
              @MessageBus(topic="prices") 
              Topic prices;
              
              @Produces @Deals 
              @MessageBus(topic="deals") 
              Topic deals;




              I guess this is supposed to be the replacement of this components.xml :


              <component id="defaultTopic" class="Topic" topic="default"/>
              
              <component id="pricesTopic" class="Topic" topic="prices"/>
              
              <component id="dealsTopic" class="Topic" topic="deals"/>
              



              or even :


              <messagebus:topic id="pricesTopic" topic="prices"/>



              Your proposed solution is a bit more verbose but this is largely acceptable with the improved typesafety.


              What do you think is blocking to implement this with the existing SPI ?

              • 19. Re: Dynamic Injection
                gavin.king

                I guess this is supposed to be the replacement of this components.xml

                It's a bit more than that. In Seam2 or Spring XML, you can only define one bean per XML declaration. With this feature, you can define a whole interacting graph of beans with different scopes, with a single producer field declaration. That's something I've struggled with for a long time. I think this is a potentially big improvement in usability.



                Your proposed solution is a bit more verbose but this is largely acceptable with the improved typesafety.

                Actually it will work out much less verbose. In most of these cases you have several objects, for example the JPA EntityManager and EntityManagerFactory, the JMS Topic, TopicConnection, TopicSession, TopicSubscriber, TopicPublisher and ConnectionFactory, the Drools RuleBase and WorkingMemory, the JDBC Datasource and Connection, etc. I want to set them up all in one line of code.



                What do you think is blocking to implement this with the existing SPI ?

                The things I really need to make this elegant are:




                And perhaps also




                However, it is almost certainly possible to implement this stuff (perhaps with some limitations) without these features. You would need to do it by creating AnnotatedTypes. You will need this stuff. Someone just needs to actually sit down and try to make it work.

                • 20. Re: Dynamic Injection
                  william.drai

                  Gavin King wrote on Dec 30, 2009 00:36:


                  I guess this is supposed to be the replacement of this components.xml

                  It's a bit more than that. In Seam2 or Spring XML, you can only define one bean per XML declaration. With this feature, you can define a whole interacting graph of beans with different scopes, with a single producer field declaration. That's something I've struggled with for a long time. I think this is a potentially big improvement in usability.


                  Not exactly true for Spring. In Spring you can define bean parsers for XML namespaces that will create as many bean definitions as necessary from a single xml declaration. I've just struggled with this for a few days : the API is absolutely awful but it exists.


                  <messagebus:topic id="pricesTopic" topic="prices"/>

                  could define both the topic and the session, which is very nice for the end user, but with an immense effort from the framework developer. Also I'm not sure it could be made in a typesafe manner but Spring users generally don't care or this.


                  Anyway I had not understood the grouped beans declaration and it looks indeed very powerful. I guess I'll have to try to implement this PE by myself, at least to try understanding what the hell you are talking about in your wishlist :-)

                  • 21. Re: Dynamic Injection
                    gavin.king

                    Not exactly true for Spring. In Spring you can define bean parsers for XML namespaces that will create as many bean definitions as necessary from a single xml declaration. I've just struggled with this for a few days : the API is absolutely awful but it exists.

                    Sure, but this is more or less similar to what you can do with a CDI portable extension. You read your metadata, create a bunch of beans and register them. In fact, I would venture to say that the CDI SPI for this is a whole lot better than absolutely awful.


                    But I want something better than that. I want a declarative way to handle these kind of problems, an approach than doesn't involve directly messing with any SPIs. Seam2 doesn't have that, and I don't believe that Spring has it either.



                    I guess I'll have to try to implement this PE by myself, at least to try understanding what the hell you are talking about in your wishlist :-)

                    I think to implement this is full generality with no annoying restrictions will be somewhat hard (hopefully not absolutely awful). But by scoping the feature down a little bit, you can probably get it done pretty easily. But you will need this stuff.

                    • 22. Re: Dynamic Injection
                      gavin.king

                      implement this is full generality

                      implement this in full generality

                      • 23. Re: Dynamic Injection
                        meetoblivion

                        so I thought I had this all figured out.


                        Just looking through code this evening I noticed that one of my annotations was missing @Qualifier.  Figuring I screwed this up, I added @Qualifier to it.  I had noticed that my producer was getting null for ip.getAnnoated().getAnnotation(MyQualifier.class) and figured that I had just missed an injection point somewhere.  I am noticing though that if my producer is something like




                        @Produces
                        @RepositorySession
                        public Session produceRepositorySession(InjectionPoint ip) {
                        ...
                        }





                        it seems to ignore the RepositorySession qualifier.  E.g. my code has this Injection Point:




                        @Inject @ RepositorySession("ContentRepo") Session session;





                        And RepositorySession went back and forth between:






                        @Qualifier
                        @Target({TYPE, METHOD, PARAMETER, FIELD})
                        @Retention(RUNTIME)
                        public @interface NamedRepository {
                        
                         @Nonbinding String value() default "";
                        }





                        And




                        public @interface NamedRepository {
                            String value() default "";
                        }





                        I would get some odd errors.  In the latter (since I royally f'd up the annotation) the injection point would become @Inject @Dependent Session session but the producer at the same time did not become @Produces @Dependent public Session produceSession...  The more curious one is the former.  In order to get an injection point using the former to work, the producer has to be marked @Produces public Session produceRepositorySession instead of @Produces @RepositorySession.  This doesn't make any sense to me.

                        1 2 Previous Next