7 Replies Latest reply: Nov 24, 2010 10:04 AM by Keith Babo Branched to a new discussion. RSS

    Leveraging CDI

    Tom Fennelly Master

      Switchyard could use CDI in many different ways and leverage many capabilities provided by the Wel CDI container.  I just knocked up the first of what will prob be many experiments with CDI.


      I checked it in here: https://github.com/tfennelly/switchyard-cdi-experimental


      What I did was create a simple CDI Extension impl (ServiceDeployer) that registers any beans annotated with the @Service annotation as ESB Services.  These beans are wrapped in a ServiceProxyHandler instance (this is actually what's registered as the ESB Service).  Currently only supports a very simple invocation model, but is good enough for now.



      Seems to me like we could leverage Weld as a nice deployment container for ESB Services.  I'm fairly sure it can provide the lifecycle (need to look at how to do this with portable extensions etc), plus lots of other services.

        • 1. Re: Leveraging CDI
          Keith Babo Master

          This is super interesting.  I looked over the code and see a number of detail-level things that I want to talk about (e.g. fault handling, whether multiple parameters are supported, etc.).  I know from your post and comments in the code that you are aware of most of these, so I'll just roll them up in a list and post it back to the forum when I get back.


          A few higher-level questions/comments:


          Now that we've seen the provider side, it would be great to see the consumer side.  I assume this will happen via injection, which can also be handled through the CDI Extension.  The question in my mind is what gets injected?  Injecting an exchange is a one-shot deal - it can't be used for multiple invocations.  Even if we work around this with a factory-ish kind of solution, I'm not sure that the raw exchange API is the right level of interface for beans.  Let's assume that every service registered in SwitchYard has an interface.  A proxy to that interface could then be injected into the CDI bean and the proxy would handle creating the exchange and handling the invocation.  Might be worth playing around with.


          I'm a bit curious about the startup ordering of CDI and where it sits relative to SwitchYard.  I would guess that CDI can come up first, followed by SwitchYard, followed by annotation scanning in CDI to discover and bootstrap bean instances.  Does that sound right?


          After we get the consumer and provider side sorted, I would like to mock up a simple a->b->c service invocation scenario, where [a-c] are services hosted in SwitchYard.  The invocation pipeline from a->b->c could be done inside a single method in the CDI bean.  I would like to play with that some to see how easy it is to create that code, whether we can add some additional APIs to make it easier, and whether generating that code as a result of user input/config is doable.  My thinking here is that the user could declaratively define this service chain and we could create a bean which handles the invocation.  If the user is cool with the default implementation, they never look at the class.  If they want to do more, they can pop it open and have at it.  Not sure if this will end up as a good or bad idea, but I think it's worth exploring.

          • 2. Re: Leveraging CDI
            Keith Babo Master

            BTW, when I say above that "every service has an interface", I mean interface as in the service's contract (e.g. portType or Java interface).

            • 3. Re: Leveraging CDI
              Tom Fennelly Master

              Checked in some code experimenting with creation of an injectable client proxy bean in an effort explore the a -> b -> c style use case.  I have some weld issues at the moment creating the InjectionTarget instance for use in the client proxt bean instance.  Still trying ot fix that.

              • 4. Re: Leveraging CDI
                Tom Fennelly Master

                Have the basic injectable client side proxy working now: https://github.com/tfennelly/switchyard-cdi-experimental


                This means we can inject a remote interface (client side proxy) for a Service into another Service i.e. the Service invocation will be done through the ESB Exchange mechansim.  I have an example of this in the tests and it looks like this…


                public class WithProductsOrderManagementService {
                    private ProductService productService;
                    public OrderResponse createOrder(OrderRequest request) {
                        OrderResponse orderResponse = new OrderResponse(request.orderId);
                        orderResponse.product = productService.getProduct(request.productId);
                        return orderResponse;



                In the above code, the ProductService implementation is also an @ESBService bean.  The reference that gets @Inject 'ed however, is just a proxy that does all the ESB invocation magic.  Pete suggested that we make the remote aspect more explicit i.e. that the code would need a qualifier annotation if a proxy is to be added, otherwise a contextual reference to the actual @ESBService implementation bean is injected (i.e. normal CDI).  Maybe something like the following if you want a proxied reference to be injected...


                @Inject @Remote
                private ProductService productService;
                • 5. Re: Leveraging CDI
                  Tom Fennelly Master

                  Or we could just have 2 simple rules as follows…


                  Inject actual service bean instance (Normal CDI Injection):

                  private ProductService productService;


                  Inject remote/proxied service bean instance:

                  private ProductService productService;
                  • 6. Re: Leveraging CDI
                    Keith Babo Master

                    Nice!  A few comments/questions:

                    • Could you elaborate on the @Remote suggestion?  Your understanding of CDI magic is beyond mine now and I didn't get the signficance of a "contextual reference" being injected.  If the idea is that the life cycle of the injected service is independent of the entity into which it's being injected, then I agree with that.
                    • You are putting operation name in the message context, but this should be in the exchange context, no?
                    • Generally speaking, I think we should start thinking about this as a "bean component" instead of just CDI integration.  Reason being that I think we can replace user-implemented actions in ESB 4.9 with CDI beans in SwitchYard.  In fact, we may even port the existing action classes (the ones that make sense) as CDI beans.  It would be interesting to see how that plays out.
                    • We are using the same annotation for declaring that a bean implementation is a service as we are for declaring an interface as a consumer reference.  I haven't thought through the ins and out of this, but that may end up being a problem later on.  Then again, maybe not. :-)


                    I think the declaration of a service provider and the injection of a consumer reference are slick as all get out.  My next concern is how this scales beyond the straightforward CDI<->CDI case.  A few challenges that I see:

                    • How do we plan on dealing with non-object payloads (e.g. XML, JSON, etc.)?  Obviously this can be handled through handlers or other services, but my point is how would this be expressed easily by the developer that is adding the @Service annotation to provide or consume a service from a bean?
                    • How will this work in an environment where Weld and SwitchYard are deployed as indpedent services?  Lifecycle and classloading are two sticky points that need to be resolved.
                    • 7. Re: Leveraging CDI
                      Keith Babo Master

                      I goofed and branched Tom's reply on this thread while trying to split up the conversation into separate threads.  Here's the first of those: