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

ksaksa at 2007-7-8 23:19:22 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 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
mauldinlaa at 2007-7-8 23:19:22 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 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

ksaksa at 2007-7-8 23:19:22 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 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

mauldinlaa at 2007-7-8 23:19:22 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 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

ksaksa at 2007-7-8 23:19:22 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 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>

mauldinlaa at 2007-7-8 23:19:22 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 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>

ksaksa at 2007-7-8 23:19:22 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 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

mauldinlaa at 2007-7-8 23:19:23 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 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
ksaksa at 2007-7-8 23:19:23 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 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

|#]

mauldinlaa at 2007-7-8 23:19:23 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 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.

ksaksa at 2007-7-8 23:19:23 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 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();

}

mauldinlaa at 2007-7-8 23:19:23 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 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

ksaksa at 2007-7-8 23:19:23 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 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

mauldinlaa at 2007-7-8 23:19:23 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 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.

m_fuchsa at 2007-7-21 16:52:36 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 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
-marinaa at 2007-7-21 16:52:36 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...