Oracle Application Server Containers for J2EE User's Guide 10g (9.0.4) Part Number B10322-01 |
|
After you have installed Oracle Application Server Containers for J2EE (OC4J) and configured the base server and default Web site, you can start developing J2EE applications. This chapter assumes that you have a working familiarity with simple J2EE concepts and a basic understanding for EJB development.
The following sections describe how to develop and deploy EJB applications with OC4J:
This chapter uses a stateless session bean example to show you each development phase and deployment steps for an EJB. As an introduction to EJBs, a simple EJB with a basic OC4J-specific configuration is used. You can download the stateless session bean example from the OC4J sample code page on the OTN Web site.
For more information on EJBs in OC4J, see the Oracle Application Server Containers for J2EE Enterprise JavaBeans Developer's Guide.
You develop EJB components for the OC4J environment in the same way as in any other standard J2EE environment. Here are the steps to develop EJBs:
Although you can develop your application in any manner, we encourage you to use consistent naming for locating your application easily. One method would be to implement your enterprise Java application under a single parent directory structure, separating each module of the application into its own subdirectory.
Our hello example was developed using the directory structure mentioned in "Creating the Development Directory". Notice in Figure 7-1 that the EJB and Web modules exist under the hello
application parent directory and are developed separately in their own directory.
When you implement a session or entity EJB, create the following:
Note: Message-driven beans have similar, but not the same, requirements as listed below. See the Oracle Application Server Containers for J2EE Enterprise JavaBeans Developer's Guide for more information. |
create
method for your bean. If the bean is an entity bean, it also defines the finder method(s) for that bean.
javax.ejb.SessionBean
or javax.ejb.EntityBean
interfaces.
ejb*
methods that match the home interface create
methods:
ejbCreate
method with no parameters.
ejbCreate
method with parameters matching those of the create method as defined in the home interfaces.
ejbCreate
and ejbPostCreate
methods with parameters matching those of the create
method as defined in the home interfaces.
The home interfaces (remote and local) are used to create the bean instance; thus, they define the create
method for your bean. Each type of EJB can define the create
method in the following ways:
For each create
method, a corresponding ejbCreate
method is defined in the bean implementation.
Any remote client invokes the EJB through its remote interface. The client invokes the create
method that is declared within the remote home interface. The container passes the client call to the ejbCreate
method--with the appropriate parameter signature--within the bean implementation. You can use the parameter arguments to initialize the state of the new EJB object.
javax.ejb.EJBHome
interface.
create
methods must throw the following exceptions:
The following code sample illustrates a remote home interface for a session bean called HelloHome
.
package hello; import javax.ejb.*; import java.rmi.*; public interface HelloHome extends EJBHome { public Hello create() throws CreateException, RemoteException;
}
An EJB can be called locally from a client that exists in the same container. Thus, a collocated bean, JSP, or servlet invokes the create
method that is declared within the local home interface. The container passes the client call to the ejbCreate
method--with the appropriate parameter signature--within the bean implementation. You can use the parameter arguments to initialize the state of the new EJB object.
javax.ejb.EJBLocalHome
interface.
create
methods may throw the following exceptions:
The following code sample shows a local home interface for a stateless session bean called HelloLocalHome
.
package hello; import javax.ejb.*; public interface HelloLocalHome extends EJBLocalHome { public HelloLocal create() throws CreateException, EJBException;
}
The component interfaces define the business methods of the bean that a client can invoke.
The remote interface defines the business methods that a remote client can invoke. Here are the requirements for developing the remote interface:
javax.ejb.EJBObject
interface, and its methods must throw the java.rmi.RemoteException
exception.
public
for remote clients.
EJBException
and RemoteException
, are transferred back to the client as remote runtime exceptions.
The following code sample shows a remote interface called Hello
with its defined methods, each of which will be implemented in the stateless session bean.
package hello; import javax.ejb.*; import java.rmi.*; public interface Hello extends EJBObject { public String sayHello(String myName) throws RemoteException; }
The local interface defines the business methods of the bean that a local (collocated) client can invoke.
javax.ejb.EJBLocalObject
interface.
public
.
The following code sample contains a local interface called HelloLocal
with its defined methods, each of which will be implemented in the stateless session bean.
package hello; import javax.ejb.*; public interface HelloLocal extends EJBLocalObject { public String sayHello(String myName) throws EJBException; }
The bean contains the business logic for your application. It implements the following methods:
RemoteException
. Since both the local and the remote interfaces use the bean implementation, the bean implementation cannot throw the RemoteException
.
SessionBean
or EntityBean
interface. These include the ejb<Action>
methods, such as ejbActivate
, ejbPassivate
, and so on.
ejbCreate
methods that correspond to the create
method(s) that are declared in the home interfaces. The container invokes the appropriate ejbCreate
method when the client invokes the corresponding create
method.
The following code shows the bean implementation for the hello example.
Note: You can download this example on OTN from the OC4J sample code page. |
package hello; import javax.ejb.*; public class HelloBean implements SessionBean { public SessionContext ctx; public HelloBean() { // constructor } public void ejbCreate() throws CreateException { // when bean is created } public void ejbActivate() { // when bean is activated } public void ejbPassivate() { // when bean is deactivated } public void ejbRemove() { // when bean is removed } public void setSessionContext(SessionContext ctx) { this.ctx = ctx; } public void unsetSessionContext() { this.ctx = null; } public String sayHello(String myName) throws EJBException { return ("Hello " + myName); } }
Note: You can download this example on OTN from the OC4J sample code page. |
All EJB clients perform the following steps to instantiate a bean, invoke its methods, and destroy the bean:
create
method on the home interface causes a new bean to be instantiated and returns a bean reference.
remove
method. This will either remove the bean instance or return it to a pool. The container controls how to act on the remove
method.
In order to access EJBs, the client-side must download
If the client is not on an Oracle Application Server installation, you must also download the
Important:
oc4j_client.zip
file from http://otn.oracle.com/
. Unzip the JAR into a directory that is in your CLASSPATH. This JAR contains the classes necessary for client interaction. If you download this JAR into a browser, you must grant certain permissions. See the "Granting Permissions" section of the Security chapter in the Oracle Application Server Containers for J2EE Enterprise JavaBeans Developer's Guide for a list of these permissions.
software/products/ias/devuse.htmloptic.jar
file, which is located in ORACLE_HOME/opmn/lib
on your Oracle Application Server installation. This JAR file must be in the CLASSPATH.
The following example is executed from a servlet that is collocated with the Hello bean. Thus, the session bean uses the local interface, and the JNDI lookup does not require JNDI properties.
package hello; import javax.servlet.http.*; import javax.servlet.*; import javax.ejb.*; import javax.naming.*; import java.io.IOException; public class HelloServlet extends HttpServlet { HelloLocalHome helloHome; HelloLocal hello; public void init() throws ServletException { try { // 1. Retreive the Home Interface using a JNDI Lookup // Retrieve the initial context for JNDI.
// No properties needed when local Context context = new InitialContext(); // Retrieve the home interface using a JNDI lookup using // the java:comp/env bean environment variable
// specified in web.xml helloHome = (HelloLocalHome)
context.lookup("java:comp/env/ejb/HelloBean"); //2. Narrow the returned object to be an HelloHome object.
// Since the client is local, cast it to the correct object type. //3. Create the local Hello bean instance, return the reference hello = (HelloLocal)helloHome.create(); } catch(NamingException e) { throw new ServletException("Error looking up home", e); } catch(CreateException e) { throw new ServletException("Error creating local hello bean", e); } } public void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); ServletOutputStream out = response.getOutputStream(); try { out.println("<html>"); out.println("<body>"); //4. Invoke a business method on the local interface reference. out.println(hello.sayHello("James Earl")); out.println("</body>"); out.println("</html>"); } catch(EJBException e) { out.println("EJBException error: " + e.getMessage()); } catch(IOException e) { out.println("IOException error: " + e.getMessage()); } finally { out.close(); } } }
Note: You can download this example on OTN from the OC4J sample code page. |
The following example is executed from a pure Java client that is a remote client. Any remote client must set up JNDI properties before retrieving the object, using a JNDI lookup.
The jndi.properties
file for this client is as follows:
java.naming.factory.initial=
com.evermind.server.ApplicationClientInitialContextFactory java.naming.provider.url=opmn:ormi://opmnhost:oc4j_inst1/helloworld java.naming.security.principal=admin java.naming.security.credentials=welcome
The pure Java client that invokes Hello
remotely is as follows:
package hello; import javax.ejb.*; import javax.naming.*; import javax.rmi.PortableRemoteObject; import java.io.*; import java.util.*; import java.rmi.RemoteException; /* * A simple client for accessing an EJB. */ public class HelloClient { public static void main(String[] args) { System.out.println("client started..."); try { // Initial context properties are set in the jndi.properties file //1. Retrieve remote interface using a JNDI lookup*/ Context context = new InitialContext(); // Lookup the HelloHome object. The reference is retrieved from the // application-local context (java:comp/env). The variable is // specified in the application-client.xml). Object homeObject = context.lookup("java:comp/env/Helloworld"); //2. Narrow the reference to HelloHome. Since this is a remote
// object, use the PortableRemoteObject.narrow method. HelloHome home = (HelloHome) PortableRemoteObject.narrow
(homeObject, HelloHome.class); //3. Create the remote object and narrow the reference to Hello. Hello remote = (Hello) PortableRemoteObject.narrow(home.create(), Hello.class); //4. Invoke a business method on the remote interface reference. System.out.println(remote.sayHello("James Earl")); } catch(NamingException e) { System.err.println("NamingException: " + e.getMessage()); } catch(RemoteException e) { System.err.println("RemoteException: " + e.getMessage()); } catch(CreateException e) { System.err.println("FinderException: " + e.getMessage()); } } }
Note: You can download this example on OTN from the OC4J sample code page. |
After implementing and compiling your classes, you must create the standard J2EE EJB deployment descriptor for all beans in the module. The XML deployment descriptor (defined in the ejb-jar.xml
file) describes the EJB module of the application. It describes the types of beans, their names, and attributes. The structure for this file is mandated in the DTD file, which is provided at " http://java.sun.com/dtd/ejb-jar_2_0.dtd".
Any EJB container services that you want to configure is also designated in the deployment descriptor. For information about data sources and JTA, see the Oracle Application Server Containers for J2EE Services Guide. For information about security, see the Oracle Application Server Containers for J2EE Security Guide.
After creation, place the deployment descriptors for the EJB application in the META-INF
directory that is located in the same directory as the EJB classes. See Figure 7-1 for more information.
The following example shows the sections that are necessary for the Hello
example, which implements both a remote and a local interface.
The following is the deployment descriptor for a version of the hello example that uses a stateless session bean. This example defines both the local and remote interfaces. You do not have to define both interface types; you may define only one of them.
<?xml version="1.0"?> <!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN" "http://java.sun.com/j2ee/dtds/ejb-jar_1_1.dtd"> <ejb-jar> <display-name>hello</display-name> <description> An EJB app containing only one Stateless Session Bean </description> <enterprise-beans> <session> <description>no description</description> <display-name>HelloBean</display-name><ejb-name>HelloBean</ejb-name>
<home>hello.HelloHome</home>
<remote>hello.Hello</remote>
<local-home>hello.HelloLocalHome</local-home>
<local>hello.HelloLocal</local>
<ejb-class>hello.HelloBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type> </session> </enterprise-beans> <assembly-descriptor> <container-transaction> <method> <ejb-name>HelloBean</ejb-name> <method-name>*</method-name> </method> <trans-attribute>Supports</trans-attribute> </container-transaction> <security-role> <role-name>users</role-name> </security-role> </assembly-descriptor> </ejb-jar>
Note: You can download this example on OTN from the OC4J sample code page. |
After you have finalized your implementation and created the deployment descriptors, archive your EJB application into a JAR file. The JAR file should include all EJB application files and the deployment descriptor.
Note: If you have included a Web application as part of this enterprise Java application, follow the instructions for building the Web application in the Oracle Application Server Containers for J2EE User's Guide. |
For example, to archive your compiled EJB class files and XML files for the Hello
example into a JAR file, perform the following in the ../hello/ejb_module
directory:
% jar cvf helloworld-ejb.jar .
This archives all files contained within the ejb_module
subdirectory within the JAR file.
To prepare the application for deployment, you do the following:
application.xml
file with the modules of the enterprise Java application.
These steps are described in the following sections:
The application.xml
file acts as the standard J2EE application descriptor file for the application and contains a list of the modules that are included within your enterprise application. You use each <module>
element defined in the application.xml
file to designate what comprises your enterprise application. Each module describes one of three things: EJB JAR, Web WAR, or any client files. Respectively, designate the <ejb>
, <web>
, and <java>
elements in separate <module>
elements.
<ejb>
element specifies the EJB JAR filename.
<web>
element specifies the Web WAR filename in the <web-uri>
element, and its context in the <context>
element.
<java>
element specifies the client JAR filename, if any.
As Figure 7-2 shows, the application.xml
file is located under a META-INF
directory under the parent directory for the application. The JAR, WAR, and client JAR files should be contained within this directory. Because of this proximity, the application.xml
file refers to the JAR and WAR files only by name and relative path--not by full directory path. If these files were located in subdirectories under the parent directory, then these subdirectories must be specified in addition to the filename.
For example, the following example modifies the <ejb>
, <web>
, and <java>
module elements within application.xml
for the Hello
EJB application that also contains a servlet that interacts with the EJB.
<?xml version="1.0"?> <!DOCTYPE application PUBLIC "-//Sun Microsystems, Inc.//DTD J2EE Application 1.2//EN" "http://java.sun.com/j2ee/dtds/application_1_ 2.dtd"> <application> <display-name>helloworld j2ee application</display-name> <description> A sample J2EE application that uses a Helloworld Session Bean on the server and calls from java/servlet/JSP clients. </description> <module> <ejb>helloworld-ejb.jar</ejb> </module> <module> <web> <web-uri>helloworld-web.war</web-uri> <context-root>/helloworld</context-root> </web> </module> <module> <java>helloworld-client.jar</java> </module> </application>
Create the EAR file that contains the JAR, WAR, and XML files for the application. Note that the application.xml
file serves as the EAR application descriptor file.
To create the helloworld.ear
file, execute the following in the hello
directory contained in Figure 7-2:
% jar cvf helloworld.ear .
This step archives the application.xml
, the helloworld-ejb.jar
, the helloworld-web.war
, and the helloworld-client.jar
files into the helloworld.ear
file.
After archiving your application into an EAR file, deploy the application to OC4J. See "Deploying Applications" for information on how to deploy your application.
|
![]() Copyright © 2002, 2003 Oracle Corporation. All Rights Reserved. |
|