4 Replies Latest reply on Apr 13, 2008 10:03 AM by jaikiran

    Can ejb3 be used with generics?

    teknokrat

      I am trying to do the following:

      I have my local business interface defines with a type parameter and all my bean classes implement it specifying a concrete class for the type parameter. e.g. public class MyClass implements MyInterface

      However, the dependency injection is now getting confused as it can't seem to differentiate between the beans e.g.

      @EJB MyInterface<Integer> test1;
      @EJB MyInterface<String> test2;
      


      The above fails. Does anyone know whether what i am trying to do can work?

      cheers

        • 1. Re: Can ejb3 be used with generics?
          jaikiran

          As far as i know, the spec does not restrict this usecase. Which JBoss server do you use and which version of Java?

          I tried a simple application with a similar usecase on JBoss-4.2.2 with Sun Java 1.5. Here's the example:

          Interface:

          package org.myapp.ejb;
          
          public interface GenericsEJBInjection <T> {
          
           public T echoMessage(T msg);
          
          }
          


          Bean1 implementation:
          package org.myapp.ejb.impl;
          
          import javax.ejb.Remote;
          import javax.ejb.Stateless;
          
          import org.jboss.annotation.ejb.RemoteBinding;
          import org.myapp.ejb.GenericsEJBInjection;
          
          @Stateless
          @Remote ({GenericsEJBInjection.class})
          @RemoteBinding (jndiBinding = "GenericsEJBInjectionStringBean")
          public class GenericsEJBInjectionStringImpl implements GenericsEJBInjection <String> {
          
           public String echoMessage(String msg) {
           System.out.println("Echoing message...");
           return "Echo - " + msg;
           }
          
          }
          


          Bean2 implementation:

          package org.myapp.ejb.impl;
          
          import javax.ejb.Remote;
          import javax.ejb.Stateless;
          
          import org.jboss.annotation.ejb.RemoteBinding;
          import org.myapp.ejb.GenericsEJBInjection;
          
          @Stateless
          @Remote ({GenericsEJBInjection.class})
          @RemoteBinding (jndiBinding = "GenericsEJBInjectionIntegerBean")
          public class GenericsEJBInjectionIntegerImpl implements GenericsEJBInjection <Integer> {
          
           public Integer echoMessage(Integer msg) {
           System.out.println("Echoing integer");
           return msg;
           }
          
          
          }
          


          Finally, the bean in which these 2 beans are injected:
          /**
           * @author Jaikiran Pai
           * @since
           */
          @Stateless
          @Remote ({UserManager.class})
          @RemoteBinding (jndiBinding = "RemoteUserManagerBean")
          public class UserManagerBean implements UserManager {
          
           /**
           * Instance of logger
           */
           private static Logger logger = Logger.getLogger(UserManagerBean.class);
          
          
           
           @EJB
           private GenericsEJBInjection<String> genericsBean;
          
           @EJB
           private GenericsEJBInjection<Integer> anotherGenericsBean;
          
           /**
           *
           *
           */
           public UserManagerBean() {
           System.out.println("Default constructor of UserManagerBean " + this);
           }
          
          
           /**
           * Just a dummy method
           *
           * @see org.myapp.ejb.UserManager#getUser(long)
           */
           public User getUser(long id) {
          
           System.out.println("Generics EJB is = " + genericsBean);
           System.out.println("Generics EJB Echo = " + genericsBean.echoMessage("Hello gen ejb"));
          
           System.out.println("Another Generics EJB is = " + anotherGenericsBean);
           System.out.println("Generics Integer EJB Echo = " + anotherGenericsBean.echoMessage(2));
          
           return null;
           }
          }


          This does not deploy and fails with exception:
          java.lang.RuntimeException: could not resolve global JNDI name for @EJB for container UserManagerBean: reference class: org.myapp.ejb.GenericsEJBInjection ejbLink: duplicated in myapp_ejb3.jar
           at org.jboss.injection.EjbEncInjector.inject(EjbEncInjector.java:88)
           at org.jboss.ejb3.EJBContainer.start(EJBContainer.java:566)
           at org.jboss.ejb3.SessionContainer.start(SessionContainer.java:154)
           at org.jboss.ejb3.stateless.StatelessContainer.start(StatelessContainer.java:102)
           at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
           at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
           at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
           at java.lang.reflect.Method.invoke(Method.java:585)
           at org.jboss.ejb3.ServiceDelegateWrapper.startService(ServiceDelegateWrapper.java:103)
           at org.jboss.system.ServiceMBeanSupport.jbossInternalStart(ServiceMBeanSupport.java:289)
           at org.jboss.system.ServiceMBeanSupport.jbossInternalLifecycle(ServiceMBeanSupport.java:245)
           at sun.reflect.GeneratedMethodAccessor3.invoke(Unknown Source)
           at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
           at java.lang.reflect.Method.invoke(Method.java:585)
           at org.jboss.mx.interceptor.ReflectedDispatcher.invoke(ReflectedDispatcher.java:155)
           at org.jboss.mx.server.Invocation.dispatch(Invocation.java:94)
           at org.jboss.mx.server.Invocation.invoke(Invocation.java:86)
           at org.jboss.mx.server.AbstractMBeanInvoker.invoke(AbstractMBeanInvoker.java:264)
           at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:659)
           at org.jboss.system.ServiceController$ServiceProxy.invoke(ServiceController.java:978)
           at $Proxy0.start(Unknown Source)
           at org.jboss.system.ServiceController.start(ServiceController.java:417)
           at sun.reflect.GeneratedMethodAccessor9.invoke(Unknown Source)
           at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
           at java.lang.reflect.Method.invoke(Method.java:585)
           at org.jboss.mx.interceptor.ReflectedDispatcher.invoke(ReflectedDispatcher.java:155)
           at org.jboss.mx.server.Invocation.dispatch(Invocation.java:94)
           at org.jboss.mx.server.Invocation.invoke(Invocation.java:86)
           at org.jboss.mx.server.AbstractMBeanInvoker.invoke(AbstractMBeanInvoker.java:264)
           at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:659)
           at org.jboss.mx.util.MBeanProxyExt.invoke(MBeanProxyExt.java:210)
           at $Proxy97.start(Unknown Source)
           at org.jboss.ejb3.JmxKernelAbstraction.install(JmxKernelAbstraction.java:120)
           at org.jboss.ejb3.Ejb3Deployment.registerEJBContainer(Ejb3Deployment.java:301)
           at org.jboss.ejb3.Ejb3Deployment.start(Ejb3Deployment.java:362)
           at org.jboss.ejb3.Ejb3Module.startService(Ejb3Module.java:91)
           at org.jboss.system.ServiceMBeanSupport.jbossInternalStart(ServiceMBeanSupport.java:289)
           at org.jboss.system.ServiceMBeanSupport.jbossInternalLifecycle(ServiceMBeanSupport.java:245)
           at sun.reflect.GeneratedMethodAccessor3.invoke(Unknown Source)
           at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
           at java.lang.reflect.Method.invoke(Method.java:585)
           at org.jboss.mx.interceptor.ReflectedDispatcher.invoke(ReflectedDispatcher.java:155)
           at org.jboss.mx.server.Invocation.dispatch(Invocation.java:94)
           at org.jboss.mx.server.Invocation.invoke(Invocation.java:86)
           at org.jboss.mx.server.AbstractMBeanInvoker.invoke(AbstractMBeanInvoker.java:264)
           at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:659)
           at org.jboss.system.ServiceController$ServiceProxy.invoke(ServiceController.java:978)
           at $Proxy0.start(Unknown Source)
           at org.jboss.system.ServiceController.start(ServiceController.java:417)
           at sun.reflect.GeneratedMethodAccessor9.invoke(Unknown Source)
           at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
           at java.lang.reflect.Method.invoke(Method.java:585)
           at org.jboss.mx.interceptor.ReflectedDispatcher.invoke(ReflectedDispatcher.java:155)
           at org.jboss.mx.server.Invocation.dispatch(Invocation.java:94)
           at org.jboss.mx.server.Invocation.invoke(Invocation.java:86)
           at org.jboss.mx.server.AbstractMBeanInvoker.invoke(AbstractMBeanInvoker.java:264)
           at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:659)
           at org.jboss.mx.util.MBeanProxyExt.invoke(MBeanProxyExt.java:210)
           at $Proxy33.start(Unknown Source)
           at org.jboss.ejb3.EJB3Deployer.start(EJB3Deployer.java:512)
           at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
           at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
           at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
           at java.lang.reflect.Method.invoke(Method.java:585)
           at org.jboss.mx.interceptor.ReflectedDispatcher.invoke(ReflectedDispatcher.java:155)
           at org.jboss.mx.server.Invocation.dispatch(Invocation.java:94)
           at org.jboss.mx.interceptor.AbstractInterceptor.invoke(AbstractInterceptor.java:133)
           at org.jboss.mx.server.Invocation.invoke(Invocation.java:88)
           at org.jboss.mx.interceptor.ModelMBeanOperationInterceptor.invoke(ModelMBeanOperationInterceptor.java:142)
           at org.jboss.mx.interceptor.DynamicInterceptor.invoke(DynamicInterceptor.java:97)
           at org.jboss.system.InterceptorServiceMBeanSupport.invokeNext(InterceptorServiceMBeanSupport.java:238)
           at org.jboss.wsf.container.jboss42.DeployerInterceptor.start(DeployerInterceptor.java:87)
           at org.jboss.deployment.SubDeployerInterceptorSupport$XMBeanInterceptor.start(SubDeployerInterceptorSupport.java:188)
           at org.jboss.deployment.SubDeployerInterceptor.invoke(SubDeployerInterceptor.java:95)
           at org.jboss.mx.server.Invocation.invoke(Invocation.java:88)
           at org.jboss.mx.server.AbstractMBeanInvoker.invoke(AbstractMBeanInvoker.java:264)
           at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:659)
           at org.jboss.mx.util.MBeanProxyExt.invoke(MBeanProxyExt.java:210)
           at $Proxy34.start(Unknown Source)
           at org.jboss.deployment.MainDeployer.start(MainDeployer.java:1025)
           at org.jboss.deployment.MainDeployer.start(MainDeployer.java:1015)
           at org.jboss.deployment.MainDeployer.deploy(MainDeployer.java:819)
           at org.jboss.deployment.MainDeployer.deploy(MainDeployer.java:782)
           at sun.reflect.GeneratedMethodAccessor20.invoke(Unknown Source)
           at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
           at java.lang.reflect.Method.invoke(Method.java:585)
           at org.jboss.mx.interceptor.ReflectedDispatcher.invoke(ReflectedDispatcher.java:155)
           at org.jboss.mx.server.Invocation.dispatch(Invocation.java:94)
           at org.jboss.mx.interceptor.AbstractInterceptor.invoke(AbstractInterceptor.java:133)
           at org.jboss.mx.server.Invocation.invoke(Invocation.java:88)
           at org.jboss.mx.interceptor.ModelMBeanOperationInterceptor.invoke(ModelMBeanOperationInterceptor.java:142)
           at org.jboss.mx.server.Invocation.invoke(Invocation.java:88)
           at org.jboss.mx.server.AbstractMBeanInvoker.invoke(AbstractMBeanInvoker.java:264)
           at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:659)
           at org.jboss.mx.util.MBeanProxyExt.invoke(MBeanProxyExt.java:210)
           at $Proxy9.deploy(Unknown Source)


          However, the application deploys if i inject just one (instead of those 2 EJBs).

          Furthermore, there's a workaround to get this going (if you are stuck on this). The @EJB also accepts optional attributes like beanName or mappedName.

          What you could do is, inject the beans as follows:
          @EJB (mappedName="GenericsEJBInjectionStringBean")
           private GenericsEJBInjection<String> genericsBean;
          
           @EJB (mappedName="GenericsEJBInjectionIntegerBean")
           private GenericsEJBInjection<Integer> anotherGenericsBean;


          or maybe like this:
          @EJB (beanName="GenericsEJBInjectionStringImpl")
           private GenericsEJBInjection<String> genericsBean;
          
           @EJB (beanName="GenericsEJBInjectionIntegerImpl")
           private GenericsEJBInjection<Integer> anotherGenericsBean;


          I tried these workaround and they work fine. The bean gets deployed and i am able to invoke the methods.


          • 2. Re: Can ejb3 be used with generics?
            wolfc

            This defines the view that gets exposed (and injected):

            @Remote ({GenericsEJBInjection.class})

            Not the actual implementing of an interface. So you have two duplicate views in 1 deployment. So the 'workaround' specified by jaikiran is actually the correct way to resolve it.

            • 3. Re: Can ejb3 be used with generics?
              teknokrat

              1. I am using jboss 4.2.2 on java 6
              2. I am using Local beans

              and...

              3. I did try using the beanName and mappedName attributes. Sure enough, the deployment went fine, but then the dependency injection failed at runtime when the bean was instantiated.

              thanks for the effort guys

              • 4. Re: Can ejb3 be used with generics?
                jaikiran

                 

                "teknokrat" wrote:


                Sure enough, the deployment went fine, but then the dependency injection failed at runtime when the bean was instantiated.



                What exceptions do you see? Can you post the logs? The dependency injection had worked fine in my case. I was able to invoke the methods on the injected beans too.