EJB 3.0 Local References
I have an EJB module that contains a session bean, MasterBean, with a local interface MasterLocal, packaged in an EAR file. I am trying to look up a reference to MasterLocal in a regular Java class in the same EAR file. I am able to look up the MasterLocal in my WAR file using the following code
web.xml:
<ejb-local-ref>
<ejb-ref-name>ejb/MasterLocal</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>facade.MasterLocal</local>
<ejb-link>MasterBean</ejb-link>
</ejb-local-ref>
Lookup:
MasterLocal masterLocal =null;
try{
InitialContext ic =new InitialContext();
masterLocal = (MasterLocal) ic.lookup("java:comp/env/ejb/MasterLocal");
}catch (NamingException ex){
logger.severe("Error getting MasterLocal: " + ex.getMessage());
}
How can I use similar code to look up a reference to MasterLocal in the EAR module?
Luke Mauldin
[1297 byte] By [
mauldinlaa] at [2007-11-26 16:51:39]

# 1
Hi Luke,
It depends under which component context the utility class is invoked.If it is called by
a web component, then the utility class can access the same ejb dependency you defined
for the .war.In Java EE, the component environment (java:comp/env) is scoped to the
entire .war.That is different from ejb, where the component environment is scoped to
each ejb component.So, if the same utility class were invoked from an ejb, you would
only have visibility to the dependencies defined within that ejb's component environment.
--ken
# 2
Ken,The utility class is in the EAR module and it is called by another class in the EAR module. Another important fact is that my interface, MasterLocal, is a Local interface, not a Remote interface. How would I look up MasterLocal, which is a local interface?Luke Mauldin
# 3
> Ken,
>
> The utility class is in the EAR module and it is
> called by another class in the EAR module.
Yes, but what entry point into the server results in the invocation of these
utility classes? An http invocation, Remote EJB , web services ?
Is the utility code invoked from within the web tier or from some ejb
component or either?That's what determines which component
environment is active at the time your utility code runs.
>Another
> important fact is that my interface, MasterLocal, is
> a Local interface, not a Remote interface. How would
> I look up MasterLocal, which is a local interface?
The same way as your original code, via java:comp/env.The only
question is whether you need to define the same dependency
again for one or more other components so that it is available
to your utility code.
>
> Luke Mauldin
# 4
It is invoked by another EJB in the same EAR module. I tried looking it up using:
MasterLocal masterLocal = (MasterLocal) ic.lookup("java:comp/env/ejb/MasterLocal");
However, I do not think that it worked because I MasterLocal is a local interface because it did not work from my web component until I added the lines to the web.xml.
Luke Mauldin
# 5
Yes, that makes sense. The ejb-refs in your web.xml only apply to code running within the
context of a web application invocation.Since your utility class is called from an ejb,
you'll need to define whatever environment dependencies it needs within that ejb's component
environment.Just add the ejb-local-ref elements to the calling EJB's portion of ejb-jar.xml.
--ken
# 6
Will the method you suggested work for EJB 3.0 and Sun Application Server 9.0? Is it a matter of just pasting the below code into a file called ejb-jar.xml?
<ejb-local-ref>
<ejb-ref-name>ejb/MasterLocal</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>facade.MasterLocal</local>
<ejb-link>MasterBean</ejb-link>
</ejb-local-ref>
# 7
Yes, it will work for any compliant Java EE 5 implementation. If you're using EJB 3.0,
you can also just use a class-level @EJB annotation on the calling ejb, e.g.
@EJB(name="ejb/MasterLocal", beanInterface=facade.MasterLocal.class)
@Stateless public class MyBean
This defines the local ejb dependency within this ejb's environment. It's
equivalent to using an ejb-local-ref.
To do the same with ejb-jar.xml, you would need to at least have a <session> entry for the
bean and put the ejb-local-ref within that.E.g.
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" metadata-complete="true" version="3.0" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd">
<enterprise-beans>
<session>
<ejb-name>MyBean</ejb-name>
<session-type>Stateless</session-type>
<ejb-local-ref>
<ejb-ref-name>ejb/MasterLocal</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>facade.MasterLocal</local>
<ejb-link>MasterBean</ejb-link>
</ejb-local-ref>
</session>
</enterprise-beans>
</ejb-jar>
# 8
I placed the following reference on my EJB MasterBean:
@EJB(name="ejb/MasterLocal", beanInterface=facade.MasterLocal.class)
@Stateless
public class MasterBean implements MasterLocal {
facade.MasterLocal looks like this:
@Local
public interface MasterLocal {
I then tried to use the following code in a class in the same EAR module to lookup a reference to MasterLocal:
private MasterLocal lookupMasterBean() {
try {
Context c = new InitialContext();
return (MasterLocal) c.lookup("java:comp/env/ejb/MasterLocal");
}
catch(NamingException ne) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE,"exception caught" ,ne);
throw new RuntimeException(ne);
}
}
An exception was thrown saying: No object bound to name java:comp/env/ejb/MasterLocal
I am using JDK 1.5.0_10 and Sun Application Server 9.0 UR1.
Luke Mauldin
# 9
Hi Luke,The @EJB definition looks fine.Please post the stack trace. Again, the issue is notonly whether the utility class is packaged in the same EAR. The issue is whether the ejbthat defines the dependency is in scope when the utility class is invoked. --ken
# 10
[#|2007-02-01T12:09:04.263-0600|INFO|sun-appserver-pe9.0|javax.enterprise.system.container.ejb|_ThreadID=15;_ThreadName=httpWorkerThread-8080-0;|
javax.ejb.EJBException
at com.sun.ejb.containers.BaseContainer.processSystemException(BaseContainer.java:3730)
at com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:3630)
at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:3431)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1247)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:192)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:71)
at $Proxy93.searchVisitorBadge(Unknown Source)
at securitylog.login.SelectVisitors.search_action(SelectVisitors.java:752)
at securitylog.login.SelectVisitors.init(SelectVisitors.java:712)
at com.sun.rave.web.ui.appbase.servlet.LifecycleListener.fireInit(LifecycleListener.java:555)
at com.sun.rave.web.ui.appbase.servlet.LifecycleListener.attributeAdded(LifecycleListener.java:405)
at org.apache.coyote.tomcat5.CoyoteRequest.setAttribute(CoyoteRequest.java:1634)
at org.apache.coyote.tomcat5.CoyoteRequestFacade.setAttribute(CoyoteRequestFacade.java:522)
at javax.servlet.ServletRequestWrapper.setAttribute(ServletRequestWrapper.java:295)
at com.sun.faces.context.RequestMap.put(ExternalContextImpl.java:1055)
at com.sun.faces.application.ApplicationAssociate.createAndMaybeStoreManagedBeans(ApplicationAssociate.java:525)
at com.sun.faces.el.ManagedBeanELResolver.getValue(ManagedBeanELResolver.java:82)
at javax.el.CompositeELResolver.getValue(CompositeELResolver.java:143)
at com.sun.faces.el.FacesCompositeELResolver.getValue(FacesCompositeELResolver.java:62)
at com.sun.el.parser.AstIdentifier.getValue(AstIdentifier.java:65)
at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:192)
at com.sun.faces.application.ValueBindingValueExpressionAdapter.getValue(ValueBindingValueExpressionAdapter.java:102)
at com.sun.rave.web.ui.appbase.faces.ViewHandlerImpl.pageBean(ViewHandlerImpl.java:666)
at com.sun.rave.web.ui.appbase.faces.ViewHandlerImpl.pageBean(ViewHandlerImpl.java:641)
at com.sun.rave.web.ui.appbase.faces.ViewHandlerImpl.renderView(ViewHandlerImpl.java:249)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:133)
at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:244)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:140)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:245)
at org.apache.catalina.core.ApplicationFilterChain.servletService(ApplicationFilterChain.java:397)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:184)
at com.sun.webui.jsf.util.UploadFilter.doFilter(UploadFilter.java:203)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:216)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:184)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:276)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:566)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:536)
at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:240)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:179)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:566)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:73)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:182)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:566)
at com.sun.enterprise.web.VirtualServerPipeline.invoke(VirtualServerPipeline.java:120)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:939)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:137)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:566)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:536)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:939)
at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:239)
at com.sun.enterprise.web.connector.grizzly.ProcessorTask.invokeAdapter(ProcessorTask.java:667)
at com.sun.enterprise.web.connector.grizzly.ProcessorTask.processNonBlocked(ProcessorTask.java:574)
at com.sun.enterprise.web.connector.grizzly.ProcessorTask.process(ProcessorTask.java:844)
at com.sun.enterprise.web.connector.grizzly.ReadTask.executeProcessorTask(ReadTask.java:287)
at com.sun.enterprise.web.connector.grizzly.ReadTask.doTask(ReadTask.java:212)
at com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java:252)
at com.sun.enterprise.web.connector.grizzly.WorkerThread.run(WorkerThread.java:75)
Caused by: java.lang.RuntimeException: javax.naming.NameNotFoundException: No object bound to name java:comp/env/ejb/MasterLocal
at model.listeners.VisitorBadgeListener.lookupMasterBean(VisitorBadgeListener.java:67)
at model.listeners.VisitorBadgeListener.PostLoad(VisitorBadgeListener.java:45)
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 oracle.toplink.essentials.internal.security.PrivilegedAccessHelper.invokeMethod(PrivilegedAccessHelper.java:307)
at oracle.toplink.essentials.internal.ejb.cmp3.metadata.listeners.MetadataEntityListener.invokeMethod(MetadataEntityListener.java:302)
at oracle.toplink.essentials.internal.ejb.cmp3.metadata.listeners.MetadataEntityListener.invokeMethod(MetadataEntityListener.java:324)
at oracle.toplink.essentials.internal.ejb.cmp3.metadata.listeners.MetadataEntityListener.postClone(MetadataEntityListener.java:404)
at oracle.toplink.essentials.descriptors.DescriptorEventManager.notifyListener(DescriptorEventManager.java:640)
at oracle.toplink.essentials.descriptors.DescriptorEventManager.notifyEJB30Listeners(DescriptorEventManager.java:591)
at oracle.toplink.essentials.descriptors.DescriptorEventManager.executeEvent(DescriptorEventManager.java:199)
at oracle.toplink.essentials.internal.descriptors.ObjectBuilder.populateAttributesForClone(ObjectBuilder.java:2088)
at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.populateAndRegisterObject(UnitOfWorkImpl.java:2816)
at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.cloneAndRegisterObject(UnitOfWorkImpl.java:673)
at oracle.toplink.essentials.internal.sessions.UnitOfWorkIdentityMapAccessor.getAndCloneCacheKeyFromParent(UnitOfWorkIdentityMapAccessor.java:152)
at oracle.toplink.essentials.internal.sessions.UnitOfWorkIdentityMapAccessor.getFromIdentityMap(UnitOfWorkIdentityMapAccessor.java:90)
at oracle.toplink.essentials.internal.sessions.IdentityMapAccessor.getFromIdentityMap(IdentityMapAccessor.java:295)
at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.registerExistingObject(UnitOfWorkImpl.java:3055)
at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.registerExistingObject(UnitOfWorkImpl.java:3004)
at oracle.toplink.essentials.queryframework.ObjectBuildingQuery.registerIndividualResult(ObjectBuildingQuery.java:319)
at oracle.toplink.essentials.internal.descriptors.ObjectBuilder.buildWorkingCopyCloneNormally(ObjectBuilder.java:441)
at oracle.toplink.essentials.internal.descriptors.ObjectBuilder.buildObjectInUnitOfWork(ObjectBuilder.java:406)
at oracle.toplink.essentials.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:372)
at oracle.toplink.essentials.queryframework.ReportQueryResult.processItem(ReportQueryResult.java:205)
at oracle.toplink.essentials.queryframework.ReportQueryResult.buildResult(ReportQueryResult.java:167)
at oracle.toplink.essentials.queryframework.ReportQueryResult.<init>(ReportQueryResult.java:83)
at oracle.toplink.essentials.queryframework.ReportQuery.buildObject(ReportQuery.java:579)
at oracle.toplink.essentials.queryframework.ReportQuery.buildObjects(ReportQuery.java:628)
at oracle.toplink.essentials.queryframework.ReportQuery.executeDatabaseQuery(ReportQuery.java:776)
at oracle.toplink.essentials.queryframework.DatabaseQuery.execute(DatabaseQuery.java:609)
at oracle.toplink.essentials.queryframework.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:677)
at oracle.toplink.essentials.queryframework.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:731)
at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2218)
at oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:937)
at oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:909)
at oracle.toplink.essentials.internal.ejb.cmp3.base.EJBQueryImpl.executeReadQuery(EJBQueryImpl.java:346)
at oracle.toplink.essentials.internal.ejb.cmp3.base.EJBQueryImpl.getResultList(EJBQueryImpl.java:447)
at facade.DataLookupBean.searchVisitorBadge(DataLookupBean.java:416)
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.enterprise.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1050)
at com.sun.enterprise.security.SecurityUtil.invoke(SecurityUtil.java:165)
at com.sun.ejb.containers.BaseContainer.invokeTargetBeanMethod(BaseContainer.java:2766)
at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:3847)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:184)
... 53 more
Caused by: javax.naming.NameNotFoundException: No object bound to name java:comp/env/ejb/MasterLocal
at com.sun.enterprise.naming.NamingManagerImpl.lookup(NamingManagerImpl.java:751)
at com.sun.enterprise.naming.java.javaURLContext.lookup(javaURLContext.java:156)
at com.sun.enterprise.naming.SerialContext.lookup(SerialContext.java:307)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at model.listeners.VisitorBadgeListener.lookupMasterBean(VisitorBadgeListener.java:63)
... 101 more
|#]
# 11
Your @EJB dependency is defined on MasterBean, but the stack trace shows that the ejb
component that causes the VisitorBadgeListener to be invoked(as a result of a Java
Persistence API call) is DataLookupBean :
at facade.DataLookupBean.searchVisitorBadge(DataLookupBean.java:416)
Add the @EJB to that bean instead and the VisitorBadgeListener should be able to see it.
# 12
Thank you very much. That did indeed work. I have two remaining questions:
1) If in the utility class, VisitorBadgeListener, if I wanted to lookup a reference to the DataLookupBean, what steps would I take? I tried to put another @EJB reference in the MasterBean class but I get a compiler error:
@EJB(name="ejb/DataLookupBean", beanInterface=facade.DataLookupLocal.class)
@EJB(name="ejb/MasterLocal", beanInterface=facade.MasterLocal.class)
@Stateless
public class MasterBean implements MasterLocal
2) Using EJB 3.0 Persistence, if I have a method in a Stateless Session bean that persists an object to the database and that object has an identity generated primary key, how do I get the value of the primary key and return it back to the calling function? See the code below, workflow.getId() is still NULL when the function returns
public Integer createApprovalWorkflow(Integer visitorID, Integer propertyApprovalID, String type) throws Exception {
ApprovalWorkflow workflow = new ApprovalWorkflow();
workflow.setApprovalType(type);
workflow.setApprovalID(propertyApprovalID);
workflow.setVisitorID(dataLookupLocal.getVisitorBadge(visitorID));
em.persist(workflow);
return workflow.getId();
}
# 13
> Thank you very much. That did indeed work.
Glad to hear it.
>
> 1) If in the utility class, VisitorBadgeListener, if
> I wanted to lookup a reference to the DataLookupBean,
> what steps would I take? I tried to put another @EJB
> reference in the MasterBean class but I get a
> compiler error:
> @EJB(name="ejb/DataLookupBean",
> beanInterface=facade.DataLookupLocal.class)
> @EJB(name="ejb/MasterLocal",
> beanInterface=facade.MasterLocal.class)
> @Stateless
> public class MasterBean implements
> MasterLocal
This is because of a basic annotation restriction. The same annotation cannot
appear twice at a given level.For this reason, we have special aggregate
environment annotations : @EJBs, @Resources, etc. The syntax is a bit
complicated but it would look like this :
@EJBs( {
@EJB(...) ,
@EJB(...)
} )
>
> 2) Using EJB 3.0 Persistence, if I have a method in
> a Stateless Session bean that persists an object to
> the database and that object has an identity
> generated primary key, how do I get the value of the
> primary key and return it back to the calling
> function? See the code below, workflow.getId() is
> still NULL when the function returns
> [code]public Integer
> createApprovalWorkflow(Integer visitorID, Integer
> propertyApprovalID, String type) throws Exception {
> ApprovalWorkflow workflow = new
> ApprovalWorkflow();
>workflow.setApprovalType(type);
> workflow.setApprovalID(propertyApprovalID);
>
> orkflow.setVisitorID(dataLookupLocal.getVisitorBadge(v
> isitorID));
> em.persist(workflow);
> return workflow.getId();
>}[/code
I'll have someone from our persistence team follow-up on this.
--ken
# 14
1) Thank you. I was able to use the following line of code to make it work:
@EJBs({@EJB(name="ejb/DataLookupLocal", beanInterface=facade.DataLookupLocal.class), @EJB(name="ejb/DataLookupLocal", beanInterface=facade.DataLookupLocal.class)})
2) I look forward with speaking to someone from the persistence team.
Luke Mauldin
# 15
TopLink-essentials assigs generated ids only on commit or flush, so you should call em.flush() before getting the id value. Another way would be using a UUID generator and setting the id in a prePersist listener, which are geranteed to be executed by the persistence provider before the persist operation is called.
# 16
You can try to refresh the entity, or flush all the changes via em.flush so that the database provided values become available to the EntityManager.HTH,-marina