4 Replies Latest reply on Jul 3, 2012 11:21 PM by ron_sigal

    BeanManager.getBeans() and EJBs

    ron_sigal

      Hi,

       

      I'm getting some odd behavior with BeanManager.getBeans().  I'm writing some Resteasy integration tests, and I have two classes:

       

      @Stateful

      @Provider

      public class EJBBookReaderImpl implements EJBBookReader

      {...}

       

      and

       

      @Provider

      public class EJBBookWriterImpl implements EJBBookWriter

      {...}

       

      First, two facts about these classes:

       

      1) I'm not sure if this is relevant, but Resteasy has a ResteasyCdiExtension class which @Observes ProcessAnnotatedType<T> event's, and, when it sees @Provider, it returns a new AnnotatedType in the Application scope.  This modification is made for both EJBBookReaderImpl and EJBBookWritererImpl.

       

      2) As you can see, EJBBookReaderImpl is a session EJB and EJBBookWriterImpl is not.

       

      In any case, the output of

       

        System.out.println(beanManager.getBeans(EJBBookWriterImpl.class));
        System.out.println(beanManager.getBeans(EJBBookReaderImpl.class));
        System.out.println(beanManager.getBeans(Object.class));

       

      is

       

        16:49:02,394 INFO  [stdout] (http-talon-127.0.0.1-8080-3) [Managed Bean [class org.jboss.resteasy.ejb.EJBBookWriterImpl] with qualifiers [@Any @Default]]

        16:49:04,028 INFO  [stdout] (http-talon-127.0.0.1-8080-3) []

        16:49:05,409 INFO  [stdout] (http-talon-127.0.0.1-8080-3) [... Session bean [class org.jboss.resteasy.ejb.EJBBookReaderImpl with qualifiers [@Any @Default]; local interfaces are [EJBBookReader] ...]

       

      I.e, the BeanManager knows about EJBBookReaderImpl, but BeanManager.getBeans() doesn't recognize the name.

       

      Is this a problem with BeanManager?  Does the class name of EJBBookReaderImpl get mangled somehow?  If so, how can I get BeanManager.getBeans() to work?

       

      I've got a workaround:

       

        Set<Bean<?>> allBeans = beanManager.getBeans(Object.class);
        Iterator<Bean<?>> it = allBeans.iterator();
        while (it.hasNext())
        {
               Bean<?> b = it.next();
              if (EJBBookReaderImpl.class.equals(b.getBeanClass()))
              {
                    ...
              }
        }

       

      But it would be nice to understand what's going on.

       

      Thanks,

      Ron

        • 1. Re: BeanManager.getBeans() and EJBs
          atomicknight

          Section 4.9.7 of the EJB 3.1 specification defines how client views are determined for EJBs. Because your EJB implements a single interface, the EJB is assumed to have a single client view, which is the local interface EJBBookReader. Therefore, EJBBookReaderImpl does not exist as a bean type because it is not a client view of the EJB.

           

          Now, this should work if you modify the definition of EJBBookReaderImpl to be the following:

           

          {code}

          @Stateful

          @Local(EJBBookReader.class)

          @LocalBean

          @Provider

          public class EJBBookReaderImpl implements EJBBookReader { ... }{code}

           

          However, what you probably should be doing instead is looking up the EJB by interface:

           

          {code}System.out.println(beanManager.getBeans(EJBBookReader.class));{code}

          • 2. Re: BeanManager.getBeans() and EJBs
            ron_sigal

            Hi Abraham,

             

            Thank you so much for jumping in.  Just to expand on your answer, I see that Section 3.2.2 "Bean types of a session bean" of the CDI doc, "JSR-299: Contexts and Dependency Injection forthe Java EE platform" says

             

              "The unrestricted set of bean types for a session bean contains all local interfaces of the bean and their superinterfaces. If

              the session bean has a bean class local view, the unrestricted set of bean types contains the bean class and all superclasses."

             

            I'm still curious about two things.

             

            1. Why does BeanManager.getBeans(Object.class) return

             

              [... Session bean [class org.jboss.resteasy.ejb.EJBBookReaderImpl with qualifiers [@Any @Default]; local interfaces are [EJBBookReader] ...]

             

            2. Something else a little interesting is happening.  The interface EJBBookReader is defined

             

              @Local

              @Provider 

              @Consumes("application/test+xml")

              public interface EJBBookReader extends MessageBodyReader<Book>

              { ... }

             

            and I gave the definition of EJBBookReaderImpl above.  When ResteasyCdiExtension processes EJBBookReaderImpl, it puts it in the application scope, but it ignores EJBBookReader.  However, the output of

             

               System.out.println(beanManager.getBeans(EJBBookReader.class).iterator().next().getScope());

             

            is

             

              interface javax.enterprise.context.ApplicationScoped

             

            It seems that Weld is, in a sense, conflating EJBBookReader and EJBBookReaderImpl.  I don't see anything in the CDI doc that supports this behavior.  Just curious.

             

            Thanks,

            Ron

            • 3. Re: BeanManager.getBeans() and EJBs
              atomicknight

               

              {quote}1. Why does BeanManager.getBeans(Object.class) return

               

               

                [... Session bean [class org.jboss.resteasy.ejb.EJBBookReaderImpl with qualifiers {noformat}[@Any @Default]{noformat}; local interfaces are {noformat}[EJBBookReader]{noformat} ...]{quote}

               

               

               

               

              This is actually specified in the sentence immediately following your quote from section 3.2.2:

               

              {quote}In addition, java.lang.Object is a bean type of every session bean.{quote}

               

               

              {quote}It seems that Weld is, in a sense, conflating EJBBookReader and EJBBookReaderImpl.{quote}

               

              I think you might be confusing the concept of a "bean" with that of a "bean type." You apply a scope like @ApplicationScoped to a bean (implementation), but you access the bean via one of its bean types. In most cases, the implementation is itself one of the bean types, but this is not always the case (like in this scenario).

              1 of 1 people found this helpful
              • 4. Re: BeanManager.getBeans() and EJBs
                ron_sigal

                Curious thing 1:

                Abraham Lin wrote:

                 

                I think you might be confusing the concept of a "bean" with that of a "bean type."

                 

                Yep, I think that's the answer.   As you said, EJBBookReaderImpl does not exist as a bean type.  However, THERE IS a Bean<?> EJBBookReaderImpl with bean type Object.  Thanks.

                 

                Curious thing 2:

                Abraham Lin wrote:

                 

                You apply a scope like @ApplicationScoped to a bean (implementation), but you access the bean via one of its bean types. In most cases, the implementation is itself one of the bean types, but this is not always the case (like in this scenario).

                 

                Ah.  So BeanManager.getBeans(EJBBookReader.class) is returning the Bean<?> for EJBBookReaderImpl, which has application scope.  I see.

                 

                Again, thank you so much.

                 

                -Ron