Is it possible to have @EJB as generic type?
import javax.ejb.EJB;
public abstract class AbstractController<TEJB extends EntityEJB<TENTITY>, TENTITY extends EntityInterface> {
@EJB
protected TEJB ejb;
...
import javax.enterprise.context.SessionScoped;
import javax.faces.bean.ManagedBean;
@ManagedBean
@SessionScoped
public class UserController extends AbstractController<UserEJB, User> {
...
import javax.ejb.Stateless;
@Stateless
public abstract class EntityEJB<T extends EntityInterface> {
...
import javax.ejb.Stateless;
@Stateless
public class UserEJB extends EntityEJB<User> {
...
It compiles, deploys but whenever code goes into some EJB method, it throws:
[#|2011-02-14T12:36:20.531+0100|WARNING|glassfish3.0.1|javax.enterprise.system.container.ejb.com.sun.ejb.containers|_ThreadID=25;_ThreadName=Thread-1;|A system exception occurred during an invocation on EJB EntityEJB method public int ejb.EntityEJB.getItemCount()
javax.ejb.EJBException: javax.ejb.EJBException: javax.ejb.CreateException: Could not create stateless EJB
at com.sun.ejb.containers.StatelessSessionContainer._getContext(StatelessSessionContainer.java:448)
at com.sun.ejb.containers.BaseContainer.getContext(BaseContainer.java:2467)
at com.sun.ejb.containers.BaseContainer.preInvoke(BaseContainer.java:1860)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:188)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:84)
at $Proxy150.getItemCount(Unknown Source)
at ejb.__EJB31_Generated__EntityEJB__Intf____Bean__.getItemCount(Unknown Source)
at controller.AbstractController.getItemCount(AbstractController.java:88)
at controller.AbstractController.getPagingInfo(AbstractController.java:29)
at controller.AbstractController.getItems(AbstractController.java:40)
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:597)
at javax.el.BeanELResolver.getValue(BeanELResolver.java:302)
at javax.el.CompositeELResolver.getValue(CompositeELResolver.java:175)
at com.sun.faces.el.FacesCompositeELResolver.getValue(FacesCompositeELResolver.java:72)
at com.sun.el.parser.AstValue.getValue(AstValue.java:116)
at com.sun.el.parser.AstValue.getValue(AstValue.java:163)
at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:219)
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:102)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:190)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:178)
at javax.faces.component.UIData.getValue(UIData.java:554)
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:597)
at com.sun.faces.facelets.util.DevTools.writeAttributes(DevTools.java:368)
at com.sun.faces.facelets.util.DevTools.writeStart(DevTools.java:417)
at com.sun.faces.facelets.util.DevTools.writeComponent(DevTools.java:238)
at com.sun.faces.facelets.util.DevTools.writeComponent(DevTools.java:257)
at com.sun.faces.facelets.util.DevTools.writeComponent(DevTools.java:257)
at com.sun.faces.facelets.util.DevTools.writeComponent(DevTools.java:257)
at com.sun.faces.facelets.util.DevTools.writeComponent(DevTools.java:257)
at com.sun.faces.facelets.util.DevTools.writeComponent(DevTools.java:257)
at com.sun.faces.facelets.util.DevTools.debugHtml(DevTools.java:121)
at com.sun.faces.renderkit.RenderKitUtils.renderHtmlErrorPage(RenderKitUtils.java:1139)
at com.sun.faces.context.ExceptionHandlerImpl.throwIt(ExceptionHandlerImpl.java:249)
at com.sun.faces.context.ExceptionHandlerImpl.handle(ExceptionHandlerImpl.java:136)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:119)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:313)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1523)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97)
at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:325)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:226)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165)
at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791)
at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693)
at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954)
at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170)
at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88)
at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76)
at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53)
at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57)
at com.sun.grizzly.ContextTask.run(ContextTask.java:69)
at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330)
at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309)
at java.lang.Thread.run(Thread.java:619)
Caused by: javax.ejb.EJBException: javax.ejb.CreateException: Could not create stateless EJB
at com.sun.ejb.containers.StatelessSessionContainer$SessionContextFactory.create(StatelessSessionContainer.java:720)
at com.sun.ejb.containers.util.pool.NonBlockingPool.getObject(NonBlockingPool.java:200)
at com.sun.ejb.containers.StatelessSessionContainer._getContext(StatelessSessionContainer.java:443)
... 66 more
Caused by: javax.ejb.CreateException: Could not create stateless EJB
at com.sun.ejb.containers.StatelessSessionContainer.createStatelessEJB(StatelessSessionContainer.java:528)
at com.sun.ejb.containers.StatelessSessionContainer.access$000(StatelessSessionContainer.java:90)
at com.sun.ejb.containers.StatelessSessionContainer$SessionContextFactory.create(StatelessSessionContainer.java:718)
... 68 more
Caused by: java.lang.InstantiationException
at sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:30)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at java.lang.Class.newInstance0(Class.java:355)
at java.lang.Class.newInstance(Class.java:308)
at com.sun.ejb.containers.BaseContainer._constructEJBInstance(BaseContainer.java:1640)
at com.sun.ejb.containers.BaseContainer.createEjbInstanceAndContext(BaseContainer.java:1623)
at com.sun.ejb.containers.StatelessSessionContainer.createStatelessEJB(StatelessSessionContainer.java:469)
... 70 more
If I change EJB from generic type to concrete class (UserEJB), it works well. I'm sorry if this is beginner question, I'm just starting with Java ...
Bozho noted that abstract class should not be annotated with @Stateless. This makes sense but then it seems to crash even earlier - because it cannot find EJB named "EntityEJB". Ok, it seems that in former case dependency injector tries to inject instance of EntityEJB (this is superclass of generics TEJB) which is abstract class which cannot be instantiated (and therefore not injected) and this causes exception "Could not create stateless EJB". Whole stacktrace wihtout @Stateless:
com.sun.faces.mgbean.ManagedBeanCreationException: An error occurred performing resource injection on managed bean groupController
at com.sun.faces.mgbean.BeanBuilder.injectResources(BeanBuilder.java:211)
at com.sun.faces.mgbean.BeanBuilder.build(BeanBuilder.java:103)
at com.sun.faces.mgbean.BeanManager.createAndPush(BeanManager.java:405)
at com.sun.faces.mgbean.BeanManager.create(BeanManager.java:267)
at com.sun.faces.el.ManagedBeanELResolver.getValue(ManagedBeanELResolver.java:86)
at javax.el.CompositeELResolver.getValue(CompositeELResolver.java:175)
at com.sun.faces.el.FacesCompositeELResolver.getValue(FacesCompositeELResolver.java:72)
at com.sun.el.parser.AstIdentifier.getValue(AstIdentifier.java:99)
at com.sun.el.parser.AstValue.getValue(AstValue.java:158)
at com.sun.el.parser.AstPlus.getValue(AstPlus.java:55)
at com.sun.el.parser.AstDeferredExpression.getValue(AstDeferredExpression.java:59)
at com.sun.el.parser.AstCompositeExpression.getValue(AstCompositeExpression.java:64)
at com.sun.el.ValueExpre开发者_JAVA技巧ssionImpl.getValue(ValueExpressionImpl.java:219)
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:102)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:190)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:178)
at javax.faces.component.UIOutput.getValue(UIOutput.java:168)
at com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer.getValue(HtmlBasicInputRenderer.java:205)
at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.getCurrentValue(HtmlBasicRenderer.java:338)
at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeEnd(HtmlBasicRenderer.java:164)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:878)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1620)
at javax.faces.render.Renderer.encodeChildren(Renderer.java:168)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:848)
at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:287)
at com.sun.faces.renderkit.html_basic.GroupRenderer.encodeChildren(GroupRenderer.java:106)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:848)
at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:287)
at com.sun.faces.renderkit.html_basic.GridRenderer.renderRow(GridRenderer.java:185)
at com.sun.faces.renderkit.html_basic.GridRenderer.encodeChildren(GridRenderer.java:129)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:848)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1613)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1616)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1616)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:380)
at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:126)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:127)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:313)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1523)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97)
at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:325)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:226)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165)
at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791)
at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693)
at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954)
at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170)
at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88)
at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76)
at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53)
at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57)
at com.sun.grizzly.ContextTask.run(ContextTask.java:69)
at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330)
at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309)
at java.lang.Thread.run(Thread.java:619)
Caused by: com.sun.faces.spi.InjectionProviderException: com.sun.enterprise.container.common.spi.util.InjectionException: Exception attempting to inject Remote ejb-ref name=controller.AbstractController/ejb,Remote 3.x interface =ejb.EntityEJB,ejb-link=null,lookup=null,mappedName=,jndi-name=ejb.EntityEJB,refType=Session into class controller.AbstractController
at org.glassfish.faces.integration.GlassFishInjectionProvider.inject(GlassFishInjectionProvider.java:98)
at com.sun.faces.mgbean.BeanBuilder.injectResources(BeanBuilder.java:205)
... 63 more
Caused by: com.sun.enterprise.container.common.spi.util.InjectionException: Exception attempting to inject Remote ejb-ref name=controller.AbstractController/ejb,Remote 3.x interface =ejb.EntityEJB,ejb-link=null,lookup=null,mappedName=,jndi-name=ejb.EntityEJB,refType=Session into class controller.AbstractController
at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:614)
at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.inject(InjectionManagerImpl.java:384)
at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.injectInstance(InjectionManagerImpl.java:168)
at org.glassfish.faces.integration.GlassFishInjectionProvider.inject(GlassFishInjectionProvider.java:94)
... 64 more
Caused by: javax.naming.NamingException: Lookup failed for 'java:comp/env/controller.AbstractController/ejb' in SerialContext [Root exception is javax.naming.NamingException: Exception resolving Ejb for 'Remote ejb-ref name=controller.AbstractController/ejb,Remote 3.x interface =ejb.EntityEJB,ejb-link=null,lookup=null,mappedName=,jndi-name=ejb.EntityEJB,refType=Session' . Actual (possibly internal) Remote JNDI name used for lookup is 'ejb.EntityEJB#ejb.EntityEJB' [Root exception is javax.naming.NamingException: Lookup failed for 'ejb.EntityEJB#ejb.EntityEJB' in SerialContext [Root exception is javax.naming.NameNotFoundException: ejb.EntityEJB#ejb.EntityEJB not found]]]
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:442)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:513)
... 67 more
Caused by: javax.naming.NamingException: Exception resolving Ejb for 'Remote ejb-ref name=controller.AbstractController/ejb,Remote 3.x interface =ejb.EntityEJB,ejb-link=null,lookup=null,mappedName=,jndi-name=ejb.EntityEJB,refType=Session' . Actual (possibly internal) Remote JNDI name used for lookup is 'ejb.EntityEJB#ejb.EntityEJB' [Root exception is javax.naming.NamingException: Lookup failed for 'ejb.EntityEJB#ejb.EntityEJB' in SerialContext [Root exception is javax.naming.NameNotFoundException: ejb.EntityEJB#ejb.EntityEJB not found]]
at com.sun.ejb.EjbNamingReferenceManagerImpl.resolveEjbReference(EjbNamingReferenceManagerImpl.java:174)
at com.sun.enterprise.container.common.impl.ComponentEnvManagerImpl$EjbReferenceProxy.create(ComponentEnvManagerImpl.java:1040)
at com.sun.enterprise.naming.impl.GlassfishNamingManagerImpl.lookup(GlassfishNamingManagerImpl.java:688)
at com.sun.enterprise.naming.impl.GlassfishNamingManagerImpl.lookup(GlassfishNamingManagerImpl.java:657)
at com.sun.enterprise.naming.impl.JavaURLContext.lookup(JavaURLContext.java:148)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:428)
... 69 more
Caused by: javax.naming.NamingException: Lookup failed for 'ejb.EntityEJB#ejb.EntityEJB' in SerialContext [Root exception is javax.naming.NameNotFoundException: ejb.EntityEJB#ejb.EntityEJB not found]
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:442)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at com.sun.ejb.EjbNamingReferenceManagerImpl.resolveEjbReference(EjbNamingReferenceManagerImpl.java:169)
... 74 more
Caused by: javax.naming.NameNotFoundException: ejb.EntityEJB#ejb.EntityEJB not found
at com.sun.enterprise.naming.impl.TransientContext.doLookup(TransientContext.java:197)
at com.sun.enterprise.naming.impl.TransientContext.lookup(TransientContext.java:168)
at com.sun.enterprise.naming.impl.SerialContextProviderImpl.lookup(SerialContextProviderImpl.java:58)
at com.sun.enterprise.naming.impl.LocalSerialContextProviderImpl.lookup(LocalSerialContextProviderImpl.java:101)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:430)
... 76 more
From the exception stacktrace I'd assume you don't have a no-arg constructor. Make sure you have one and try again. There should be a problem with generics.
Also, you shouldn't be able to make an abstract class a stateless bean. So remove the annotation from here:
@Stateless
public abstract class EntityEJB
Btw, you are trying to inject .. an annotation? You should annotate a real stateless bean interface with @EJB
.
@EJB is a annotation used to inject it in your class. You cannot annotated it with a genneric class or your Container will not be able to find what instance should be used in this field.
Yes, it is possible. It compiles and it works (if you are using a solid EE application container like wildfly or weblogic).
Use the implements
on the beans which implement the interface definition (the annotated with e.g. @Local
). In the abstract class, you can implement all methods, which are shared among all bean implementations. Just don't place the @Override
annotation on any of those methods.
精彩评论