2008-07-21

Reminder on how to use EJB3 with Weblogic 10

First of all, I'd like to point out the excellent tutorial by Greg Mally on using EJB3 within Workshop

How to define an EJB3 ?

Well, it's quite easy. According to the specification, you only have to use annotations to define your EJB. For instance, let's take the following EJB :
@Stateless( name = "PdfRetriever", mappedName = "ejb/stateless/PdfRetriever", description = "Gets a PDF file from the server") @Local ({PdfRetriever.class}) @Remote ({PdfRetrieverRemote.class}) public class PdfRetrieverBean implements PdfRetriever, PdfRetrieverRemote { [...] }


For specifying the interfaces (local or remote), you can choose to use only the annotations or the implementation declarations.
The use of annotations is maybe a bit quicker to read, but the implement declaration prevents you from missing an interface method.
I wrote both so that you can make your choice. As for the deployment descriptor, the ejb-jar.xml must have the correct declaration, that is to say :
<ejb-jar xmlns=http://java.sun.com/xml/ns/javaee xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd" version="3.0">

How to call it with remote interface ?


image


Here's the code to call the EJB :
Properties props = new Properties(); props.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory"); props.put(Context.PROVIDER_URL, "t3://localhost:8001"); InitialContext ctx = new InitialContext(props); PdfRetrieverRemote ejb = (PdfRetrieverRemote)ctx.lookup("ejb.stateless.PdfRetriever#sample.ejb.PdfRetrieverRemote"); ejb.getPdfFileFromServer("myFile.pdf");


Be aware that the JNDI name is not exactly the same as entered in the EJB definition ("ejb/stateless/PdfRetriever").
It has been postfixed with a # and the full-qualified name of the Remote interface.

How to call it with local interface ?


Note : "Local" doesn't refer to the same JVM but the same EAR.


The easiest way to call your EJB is through a Servlet thanks to an annotation. As explained above, your servlet must reside in the same EAR as the EJB3 module.   


image


You don't have to use JNDI to reach your EJB, just reference it that way :
@EJBprivate PdfRetriever pdfRetriever;public void myMethod () { byte[] myPdfFile = pdfRetriever.getPdfFileFromServer("myFile.pdf"); }


Note : Due to lots of messages asking me how to call an EJB3 from a pojo, I will write some details about that, but know that this is not the way it is sensed to be used.
According to the specification, an EJB3 is to be called via an annotation in a Servlet or another EJB. This solution lies on the "java:comp/env" mechanism.

EJB within a web application


First part : declaring the EJB

Taking the example quoted above, you will have to add an annotation to at least one servlet. Example :
@EJB(beanInterface=sample.ejb.PdfRetriever.class, name = "ejb/PdfRetriever") public class EjbInvoker extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {


This annotation replaces the EJB declaration in the web.xml file. It makes the EJB available for all the War context. Else you can declare your EJB in the web.xml :
<ejb-local-ref> <ejb-ref-name>ejb/PdfRetriever</ejb-ref-name> <local>sample.ejb.PdfRetriever</local> </ejb-local-ref>


http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd


As you can see, the attributes are different :

Deployment descriptorAnnotation
localbeanInterface
ejb-ref-namename


Note : With the annotation, the beanInterface attribute expects a class.
Second part : calling the EJB from the POJO

Now the EJB has been made visible within the whole web application, the code to call the EJB from the POJO is quite simple :
InitialContext ctx = new InitialContext(); PdfRetriever ejb = (PdfRetriever) ctx.lookup("java:comp/env/ejb/PdfRetriever");


Note : The lookup has been made on the name specified in "name" attribute for the annotation and "ejb-ref-name" for the DD, that is to say "ejb/PdfRetriever"
You can then manipulate your local EJB.

EJB within an EJB module


The scenario is the same as for the web application, except that the element you've got to add the EJB declaration to is now an EJB and the DD to modify is not the web.xml but the ejb-jar.xml


7 comments:

Anonymous said...

Good solutions for local beans - but why this shoudl be configured like this ?? this is very strange ...

mario said...

Very nice.

Can you please explain what role the ejb-link element (ejb-local-ref or ejb-ref) plays in web.xml?

That to me is the most confusing part. If the EJB is declared with a "name" or "mappedName" and in web.xml you declare the ejb-local-ref, then what is the ejb-link for? More confusing is that ejb-link is documented as being part of ejb-lccal-ref but the schema allows it for ejb-ref too !!??

Maxence Button said...

Hi Mario,

Thanks for the kind word.

Well, for a complete explanation on tags used in the web.xml, you should refer to Sun and/or Oracle|BEA documentation.
It's quite well explained there :
http://edocs.bea.com/wls/docs100/webapp/web_xml.html#wp1013984

http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd

If you're still in trouble, ask your question on http://forums.oracle.com

Regards.

Anonymous said...

>The scenario is the same than for the web application, except that the element you've got to add the EJB declaration to is now an EJB and the DD to modify is not the web.xml but the ejb-jar.xml

Can you explain this by example?

Vidhya said...

Hi!

Im a newbie to EJB3 and would be greatful if you could help me!
Im having problem with local lookup!
I have many such lookup in my project. And using @EJB ie injection for every lookup make me uncomfortable! Is there a way to have local interface lookup from a SLSB.
I am using weblogic 10.3!
I have made entry in web.xml for ejb-local-ref, but that is used for lookup from servlets, is it?.
I understand use of ejb-jar. But I dnt want to use descriptor too!

I use the following for local lookup:
ManagerLocal mgr = (ManagerLocal)ctx.lookup("Manager#[full-path-of-local-interface].ManagerLocal")

This gives me name not found exception!

Thank you.

Anonymous said...

This solution is wierd! Makes me fell like I wann throw up. Every EJB container that supports EJB 3 do local ejb lookup very easily. Why Weblogic does not?

nashwa said...

Hi!

I had the same problem but i found the solution on this post:
http://www.coderanch.com/t/451012/EJB-Other-Java-EE-Technologies/java/EJB-Local-Lookup-not-working
Please check it,it is very important.

Thanx