3 Replies Latest reply on Sep 30, 2011 12:30 PM by Guido Bonazza

    Switching between EJBs implementations using Weld

    Mylos Kathos Master

      Hi all,
      I have a standard java Enterprise 6 project where several @Singleton beans are defined.
      I'd like to switch between the EJB implementation at runtime, just like I would do in Spring with Spring beans.


      I'm not sure where to start: should I use an @Alternative annotation, or it can be done by simply using Qualifiers.
      Any help is highly appreciated.
      Mylos

        • 1. Re: Switching between EJBs implementations using Weld
          Guido Bonazza Newbie

          Hi Mylos!


          I would approach your problem in this way:


          Create a producer bean which contains the logic upon which you want to choose the proper service implementation; something like this:


          @RequestScoped
          public class MyServiceProvider {
              private @Inject MyServiceImpl1 impl1;
              private @Inject MyServiceImpl2 impl2;
              ...
          
              @Produces @SmartlyChoosen
              MyService getMyService() {
                  if (...)
                      return impl1;
                  else
                      return impl2;
              }
          }
          
          


          Here I assume that MyServiceImpl1 etc. are the @Singleton EJBs and MyService is the common interface.
          I also assume that the implementation  choice logic is per request, otherwise you can change the scope of the producer bean.



          You have to create the @SmartlyChoosen qualifier, and of course use it in the injection point:


              ...
              @Inject @SmartlyChoosen MyService myService;
              ...
          



          otherwise CDI would have multiple beans satisfying MyService, each actual EJB implementation plus the one from the producer method.


          Another approach would be this:


          First of all, create a different qualifier for each implementation of your service, and of course annotate each implementation of your service with a different qualifier.
          Than, when you need to use the service, ask for it to the BeanManager, using the getBeans method.


          The BeanManager can be injected, the getBeans method returns a Set of beans but you can safely assume you have only one unless you messed up with annotations :P


          But I think the first approach is far more elegant (that is actually to say that the second is really ugly).


          If someone has a better idea, please explain, I'm very interested!

          • 2. Re: Switching between EJBs implementations using Weld
            Mylos Kathos Master

            Hi Guido,
            thank you very much for your sueful suggestion. This does make sense to get started with Weld. Anyway, should I use just a configuration file to switch between implementations, my only option is using @Alternatives right ?
            thanks
            Mylos

            • 3. Re: Switching between EJBs implementations using Weld
              Guido Bonazza Newbie

              Glad to be useful Mylos :)


              If the choice of your service's implementation is known at deployment time (well, actually at packaging time), @Alternative is the basic way to go. For some more advanced use cases you will find Seam Config useful.
              It allows fine-grained bean configuration too. I've never had a chance to use it yet, so I cannot provide a simple example, but the documentation will do.


              In some cases, Seam Solder's @Default is enough, as it allows to define a default implementation bean that comes in when no other implementation is found.


              If, on the other hand, the configuration file is provided at runtime, you can use a mix of the two techniques I described: create a producer bean that reads the configuration file, and let the @Produces method find the right implementation getting it from the BeanManager, perhaps by class name. Just beware to provide the configuration file before the producer is invoked...