OpenWebBeans
  1. OpenWebBeans
  2. OWB-655

CDI doesn´t inject stateless EJB by abstract class.

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.1.3
    • Fix Version/s: 1.1.4
    • Component/s: Enterprise Web Beans
    • Labels:
      None

      Description

      I have these classes:

      public abstract class PlcBaseDAO {}

      public abstract class PlcBaseJpaDAO extends PlcBaseDAO {}

      @Stateless
      public class AppJpaDAO extends PlcBaseJpaDAO {}

      And this injection doesn´t work.

      @Named
      public class AppCDI

      { @Inject private PlcBaseDAO baseDao; }

        Issue Links

          Activity

          Hide
          Mark Struberg added a comment -

          Hi Rogerio!

          What parts of OpenWebBeans do you use?
          OWB is built in a modular fashion. Our webbeans-impl.jar will only serve basic Java SE injection. If you add further plugins, e.g. webbeans-resource, webbeans-ee, etc then you will get more features.

          Injecting EJBs into CDI beans is one such 'extended' feature. If you use OpenWebBeans together with OpenEJB then your sample should work.

          How does your container setup look like currently? If you are using tomcat + OpenEJB + OpenWebBeans then you might try out TomEE [1] which is a pre-packaged EE Web-Profile for exactly such scenarios.

          hope that helps!

          LieGrue,
          strub

          [1] http://tomee.apache.org

          Show
          Mark Struberg added a comment - Hi Rogerio! What parts of OpenWebBeans do you use? OWB is built in a modular fashion. Our webbeans-impl.jar will only serve basic Java SE injection. If you add further plugins, e.g. webbeans-resource, webbeans-ee, etc then you will get more features. Injecting EJBs into CDI beans is one such 'extended' feature. If you use OpenWebBeans together with OpenEJB then your sample should work. How does your container setup look like currently? If you are using tomcat + OpenEJB + OpenWebBeans then you might try out TomEE [1] which is a pre-packaged EE Web-Profile for exactly such scenarios. hope that helps! LieGrue, strub [1] http://tomee.apache.org
          Hide
          Mark Struberg added a comment -

          PS: Instead of Stateless you can also make your AppJpaDAO an @ApplicationScoped CDI bean and use e.g. CODIs @Transational interceptor [2] to handle your EntityManager.

          [2] https://cwiki.apache.org/confluence/display/EXTCDI/JPA+Overview

          Show
          Mark Struberg added a comment - PS: Instead of Stateless you can also make your AppJpaDAO an @ApplicationScoped CDI bean and use e.g. CODIs @Transational interceptor [2] to handle your EntityManager. [2] https://cwiki.apache.org/confluence/display/EXTCDI/JPA+Overview
          Hide
          Rogerio Baldini added a comment -

          Hi LieGrue,

          This error occurs in Tomee-plus-1.0.0-beta-2.

          This injection just works if I inject concrete class.

          Thanks,
          Rogerio

          Show
          Rogerio Baldini added a comment - Hi LieGrue, This error occurs in Tomee-plus-1.0.0-beta-2. This injection just works if I inject concrete class. Thanks, Rogerio
          Hide
          Rogerio Baldini added a comment -

          Hi Mark,

          Thanks for your answer.

          I don´t intent to use another framework for transtion. I just want to use what is specified in JEE6/EJB3.1.

          Another important information: this example works fine with jBoss WELD.

          Thanks again,
          Rogerio.

          Show
          Rogerio Baldini added a comment - Hi Mark, Thanks for your answer. I don´t intent to use another framework for transtion. I just want to use what is specified in JEE6/EJB3.1. Another important information: this example works fine with jBoss WELD. Thanks again, Rogerio.
          Hide
          Eric Covener added a comment -

          Does it really require the base class to be abstract, IOW when the no-interface view is being used do other non-abstract super classes work for injection?

          Show
          Eric Covener added a comment - Does it really require the base class to be abstract, IOW when the no-interface view is being used do other non-abstract super classes work for injection?
          Hide
          Rogerio Baldini added a comment -

          Eric,

          I could change this implementation but it´s more complex than that, and I don´t have time enough to do this.
          If it worked in some way, it´d be fabulous.

          Thansk,
          Rogerio.

          Show
          Rogerio Baldini added a comment - Eric, I could change this implementation but it´s more complex than that, and I don´t have time enough to do this. If it worked in some way, it´d be fabulous. Thansk, Rogerio.
          Hide
          Romain Manni-Bucau added a comment -

          as a workaround this work (the injected class is concrete and i used @EJB instead of @Inject):

          import javax.ejb.EJB;
          import javax.ejb.Stateless;
          import javax.ejb.embeddable.EJBContainer;
          import javax.inject.Inject;
          import javax.inject.Named;
          import org.junit.Test;

          import static junit.framework.Assert.assertTrue;

          public class TmpTest {
          @Inject
          private AppCDI cdi;

          @Test
          public void app() throws Exception

          { final EJBContainer c = EJBContainer.createEJBContainer(); c.getContext().bind("inject", this); assertTrue(cdi.ok()); c.close(); }

          public static abstract class PlcBaseDAO {}

          public static class PlcBaseJpaDAO extends PlcBaseDAO {}

          @Stateless
          public static class AppJpaDAO extends PlcBaseJpaDAO {}

          @Named
          public static class AppCDI {
          @EJB
          private PlcBaseDAO baseDao;

          public boolean ok()

          { return baseDao != null; }

          }
          }

          Show
          Romain Manni-Bucau added a comment - as a workaround this work (the injected class is concrete and i used @EJB instead of @Inject): import javax.ejb.EJB; import javax.ejb.Stateless; import javax.ejb.embeddable.EJBContainer; import javax.inject.Inject; import javax.inject.Named; import org.junit.Test; import static junit.framework.Assert.assertTrue; public class TmpTest { @Inject private AppCDI cdi; @Test public void app() throws Exception { final EJBContainer c = EJBContainer.createEJBContainer(); c.getContext().bind("inject", this); assertTrue(cdi.ok()); c.close(); } public static abstract class PlcBaseDAO {} public static class PlcBaseJpaDAO extends PlcBaseDAO {} @Stateless public static class AppJpaDAO extends PlcBaseJpaDAO {} @Named public static class AppCDI { @EJB private PlcBaseDAO baseDao; public boolean ok() { return baseDao != null; } } }
          Hide
          Rogerio Baldini added a comment -

          Ok Romain, it works, thanks.

          I can´t use this way, because sometimes my concrete class could be ejb sometimes just a common bean.

          So is my example wrong or is a OWB/OpenEJB bug?

          Rogerio

          Show
          Rogerio Baldini added a comment - Ok Romain, it works, thanks. I can´t use this way, because sometimes my concrete class could be ejb sometimes just a common bean. So is my example wrong or is a OWB/OpenEJB bug? Rogerio
          Hide
          Romain Manni-Bucau added a comment -

          I think CDI doesn't handle such a case (injecting an abstract class) so you can't use @Inject here.

          Regarding EJB spec i'm not sure but it is something we should be able to do in OpenEJB/TomEE so i'll have a look.

          Show
          Romain Manni-Bucau added a comment - I think CDI doesn't handle such a case (injecting an abstract class) so you can't use @Inject here. Regarding EJB spec i'm not sure but it is something we should be able to do in OpenEJB/TomEE so i'll have a look.
          Hide
          Rogerio Baldini added a comment -

          If i can be able to inject an interface, I should be able to inject an abstract class as well, rigth?
          At truth, both are acting the same way. So CDI should be able to do this.

          Thanks

          Show
          Rogerio Baldini added a comment - If i can be able to inject an interface, I should be able to inject an abstract class as well, rigth? At truth, both are acting the same way. So CDI should be able to do this. Thanks
          Hide
          Eric Covener added a comment -

          We wouldn't inject an abstract class, we'd include the abstract class in the list of bean types of the EJB with a no-interface view.

          When someone requested a java type with that abstract class, and this was the only bean with that type, we'd find our way to this enterprise bean ask the container for an EJB and inject [a proxy to] that.

          Show
          Eric Covener added a comment - We wouldn't inject an abstract class, we'd include the abstract class in the list of bean types of the EJB with a no-interface view. When someone requested a java type with that abstract class, and this was the only bean with that type, we'd find our way to this enterprise bean ask the container for an EJB and inject [a proxy to] that.
          Hide
          Mark Struberg added a comment -

          I also don't think the abstract base type should be a problem. What counts is that the AppJpaDAO class is a valid type.

          I do think that in this very case we could lookup the EJB if we don't find a CDI Bean<PlcBaseDAO>. But in general the spec is imo not 100% clear what should happen with such 'mixed' scenarios: what happens if we have an @ApplicationScoped class OtherAppJpaDAO extends PlcBaseJpaDAO {} ?
          There are no @Alternative, @Specializes etc rules for mixed EJB/CDI cases defined yet imo.

          Show
          Mark Struberg added a comment - I also don't think the abstract base type should be a problem. What counts is that the AppJpaDAO class is a valid type. I do think that in this very case we could lookup the EJB if we don't find a CDI Bean<PlcBaseDAO>. But in general the spec is imo not 100% clear what should happen with such 'mixed' scenarios: what happens if we have an @ApplicationScoped class OtherAppJpaDAO extends PlcBaseJpaDAO {} ? There are no @Alternative, @Specializes etc rules for mixed EJB/CDI cases defined yet imo.
          Hide
          Mark Struberg added a comment -

          We clarified in the CDI EG that this indeed should work. See 3.2.2 of the CDI spec.
          We will look into the proper place to fix this

          Show
          Mark Struberg added a comment - We clarified in the CDI EG that this indeed should work. See 3.2.2 of the CDI spec. We will look into the proper place to fix this
          Hide
          Mark Struberg added a comment -

          addendum: this assumes that all your beans are in a jar which also has a META-INF/beans.xml.

          Show
          Mark Struberg added a comment - addendum: this assumes that all your beans are in a jar which also has a META-INF/beans.xml.
          Hide
          Rogerio Baldini added a comment -

          OK Mark. Thanks for your help.
          I am waiting for a solution.

          Rogerio.

          Show
          Rogerio Baldini added a comment - OK Mark. Thanks for your help. I am waiting for a solution. Rogerio.
          Hide
          Mark Struberg added a comment -

          After a long discussion with Roman and Eric on IRC we found the origin of the problem.
          OpenEJB creates a subclass CdiEjbBean which extends our abstract BaseEjbBean.
          This CdiEjbBean doesn't yet distinguish between NIV (no interface view) and old style session beans. It should detect NIV and overwrite BaseEjbBean#needsBeanLocalViewAddedToTypes() accordingly. Romain already created OPENEJB-1800 and will fix this issue soon.

          Show
          Mark Struberg added a comment - After a long discussion with Roman and Eric on IRC we found the origin of the problem. OpenEJB creates a subclass CdiEjbBean which extends our abstract BaseEjbBean. This CdiEjbBean doesn't yet distinguish between NIV (no interface view) and old style session beans. It should detect NIV and overwrite BaseEjbBean#needsBeanLocalViewAddedToTypes() accordingly. Romain already created OPENEJB-1800 and will fix this issue soon.
          Hide
          Mark Struberg added a comment -

          fixed in conjunction with the new OpenEJB version. See OPENEJB-1800.

          Show
          Mark Struberg added a comment - fixed in conjunction with the new OpenEJB version. See OPENEJB-1800 .
          Hide
          Mark Struberg added a comment -

          released with OWB-1.1.4

          Show
          Mark Struberg added a comment - released with OWB-1 .1.4

            People

            • Assignee:
              Mark Struberg
              Reporter:
              Rogerio Baldini
            • Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development