12 Replies Latest reply on Dec 10, 2010 10:36 AM by tfennelly

    Bean Component

    kcbabo

      @Tom - I restructured the CDI deployer project in your repo and stripped off the transformation stuff.  You can check it out here:

       

      https://github.com/kcbabo/components


      Can you take a look and let me know if I messed anything up?  Once we agree on the format, I would like to create a components repository for jboss-switchyard and then you can commit the bean component there.  I want to start writing a bunch more tests to explore different facets of how bean components can be used, but I would prefer to do that once we have the component setup in the upstream jboss-switchyard account.

       

      You will note that I added a few more tests.  Two of these tests are failing because the @Inject is not working.  I can see that our injection logic is kicking in in the debugger and it looks like it's injecting the proxy, but the test gets an NPE.  I haven't debugged into the Weld code yet as I figured it might be something obvious to you.

       

      thanks,

      keith

        • 1. Re: Bean Component
          kcbabo

          Tom - went with your suggestion from IRC to not be cute and use @Service on a separate object instead of directly on the test itself.  Both tests pass now.  It would be nice if we could inject a bean directly into a test and poke it without sending an exchange.  I think this might work with an embedded runtime and Arquillian, but we should also be able to do it in a stand-alone unit test.  Is it possible to get at the bean through BeanManager or some other CDI hook?

          • 2. Re: Bean Component
            tfennelly

            The only way I can imagine it's possible is if we can hook into JUnit and create the Test bean instances for it (via the CDI BeanManager).  Weld would then handle all the injection points etc.  Perhaps Arquilian does do something lik this, but I'd imagine it would first require the hooks to be there in JUnit.  You could prob hack it using interceptors etc, but not sure I'd like the idea of that... would prob run into build-time issues with diff versions of JUnit etc.

             

            I do agree it would be nice though, but only if we could do it without a hack

            • 3. Re: Bean Component
              kcbabo

              My last post was probably not the clearest.  What I was referring to w/r/t BeanManager is that we would still have separate classes for the consumer bean, but we would not have to create an exchange in the test class in order to exercise the methods on that bean.  Instead, we could have a method in AbstractCDITest which takes a service name and returns a set of beans which provide that service.  You could then call this in your test instead of creating an exchange, e.g.

               

              @Test
              public void testBeanConsumer() {
                  String response = getServiceBean("HelloWorld").greeting();
              }
              

               

              The test class itself would not have to be a service.

              • 4. Re: Bean Component
                kcbabo

                BTW, the getServiceBean() method in AbstractCDITest could use BeanManager from WeldContainer or something similar to find the @Service beans.

                • 5. Re: Bean Component
                  kcbabo

                  Based on the current implementation and my own crazy thoughts, I have written up some processing rules for Bean Component.  Feedback welcome.

                   

                   

                  • @Service is used to declare that a CDI bean provides one or more services.

                   

                  • The default value element for the @Service annotation identifies the services provided by the bean.  This should be a comma-delimited list of interfaces that are implemented by the bean.  We specifically list these so that non-service interfaces (e.g. java.io.Serializable) are not exposed as services within SwitchYard.

                   

                  • Each interface named in the @Service annotation is registered as an independent service in SwitchYard.  The name of the service is equal to the name of the interface (package name excluded).

                   

                  • @Reference should be used to inject references to SwitchYard services.  We are using @Service now and I think this will potentially create confusion and will also constrain what we can use in terms of annotation elements (e.g. is the use of interface names as described above relevant for services which are being injected?).

                   

                  • @Reference should be used with an interface which is within compile and runtime scope for the bean using the reference.  This holds true whether the target service is Java-based or not.  We generate a proxy to talk to the target service and map the call details onto an Exchange.

                   

                  • Transformation between message formats (e.g. Object -> XML) is not part of the proxy handling mentioned above.

                   

                  • General error handling notes:
                    • Errors related to @Service registration are reported at bean instantiation time.
                    • Errors related to @Reference resolution are reported at service invocation time.  There is no need to eagerly query for registered services when the reference is injected.
                    • Errors/faults during service invocation should be reported as exceptions to the calling bean.

                   

                  • We need to address the case where a bean consumer or provider requires access to context information, particularly message context in case there are headers which are required in the bean's processing logic.  We may need to introduce a wrapper interface like Invoker<T> where 'T' represents the service interface and Invoker has additional methods to query/set context information.
                  • 6. Re: Bean Component
                    tfennelly
                    • The default value element for the @Service annotation identifies  the services provided by the bean.  This should be a comma-delimited  list of interfaces that are implemented by the bean.  We specifically  list these so that non-service interfaces (e.g. java.io.Serializable)  are not exposed as services within SwitchYard.

                     

                    • Each  interface named in the @Service annotation is registered as an  independent service in SwitchYard.  The name of the service is equal to  the name of the interface (package name excluded).

                     

                    Yep... sounds good.  The current impl requires the @Service annotation to be on the interfaces (Vs the impl) for the very reason you mention (i.e. so as to only expose those interfaces that you want exposed) .  Changing @Service to list the interfaces would allow it to be done on the service impl itself, which is clearer.  Good idea.

                     

                    I'll have a think about the use case of getting context level info into beans.

                    • 7. Re: Bean Component
                      kcbabo

                      I can't really take credit for the idea on @Service listing the interfaces as I picked that up from the SCA Java component specification.  I was curious about how they defined Java components in SCA so I read the spec.  I was quite surprised (pleasantly) to see many similarities between their definition of a component and what we had already been talking about.

                      • 8. Re: Bean Component
                        tfennelly

                        I think we should be able to define a custom scope(s) in CDI and have weld inject the context info.  The scope(s) would be based on our contexts.

                        • 9. Re: Bean Component
                          tfennelly

                          And of course... could also probably have context info injected as invocation params... that would probably get messy though I think.

                          • 10. Re: Bean Component
                            kcbabo

                            I agree that this would be the cleanest and most consistent path.  This would work well on the service provider side, as it's pretty similar to a request scope for a webapp.  On the consumer side, I'm not sure how this will work in terms of (a) passing additional context into an invocation and (b) pulling context out of a response from a service you are consuming.

                            • 11. Re: Bean Component
                              kcbabo

                              Tom - I pushed in your pull request, so bean component is now hosted in the SwitchYard components repository.

                               

                              For anyone interested, here's a link:

                              https://github.com/jboss-switchyard/components/tree/master/bean

                              • 12. Re: Bean Component
                                tfennelly

                                Oh cool... so there was nothing wrong with the pull request.

                                 

                                Thanks Keith.