J2EE development practices based on JBoss in Win2K environment
---- Third, the development of stateful session beans and the implementation of multiple invoking state session bean methods
Description: This section is written after the previous section, in the last two sections, we implemented the configuration of the JBoss development platform and the configuration of the database connection pool, and we give a stateless session in the example of the first quarter. Instance of Bean HelloWorld. In this section, we will then learn EJB development. Note: This series is published in the Chinese programmer website (www.9cbs.net), all of the author's original, any website and individuals need to reprint, please contact the author (Josserchai@yahoo.com), this The tutorial series is written in the request of the majority of netizens, and anyone must not be used for commercial purposes. If you want to include this tutorial for publication, please contact the author. Otherwise it is considered illegal. I. Development and deployment of stateful session bean 1. Basic knowledge In the first quarter, we gave a HelloWorld's stateless session bean, in the EJB2.0 specification, EJB includes three beans, the first place is Session bean, and then there is an entity bean (EntityBean) and message-driven bean. Session beans include stateless sessions beans, and there is a status session bean. The main difference is that the former does not save the status information of the bean during the execution process, which is not a state domain, that is, the stateless session bean is just an execution process. We call it to complete our task, it cannot save the BEAN state in the container pool. The latter will save the execution status of the bean when executed in the container, and the stateful session bean also corresponds to the state domain, ie the session bean will save the session state of the fixed client during execution. use. However, there is a status session bean that does not have a primary key class, and the client cannot find out it corresponding to EJBOBJECT in the container pool, then how do we reuse our EJBOBJECT? In this article, we provide two ways and give an example program: the first method is the Handle (handle) with stateful session beans. In order to get the handle, you can call the geTHandle () method of the EJBOBJECT interface. Returns a Handle instance, in order to rebuild the reference to the same EJBObject, you can use the getEJBObject () method of the HANDLE interface. This method returns a corresponding Handle's EJB object, using this object, we can reconstruct the corresponding EJBOBJECT, as shown : Count count = counthome.create (); // Generate a Remote interface object javax.ejb.handle handle = count.getHandle (); // Get the handle of the Remote interface ... Object obj = handle.getejbobject (); // Get Handle corresponds to the EJBOBJECT object in the container pool. Count Recount = (count) portableremoteObject.narrow (Obj, count.class); // Reconstruct this object to a remote interface object to recall its method for the second method of reused it is HOMEHANDLE with stateful session bean, it is similar to Handle, but cannot be used to reference EJBOBJECT.
HOMEHANDLE contains enough information to reconstruct ejbhome () references. Its practice is to call the gethomeHandle () method and getEbHome () method. This method returns a corresponding Handle's EJBHOME object, using this object, can regenerate the corresponding EJBOBJECT object, and then call it. The following example: Content ctx = new InitialContext (); Object h = ctx.lookup ( "CountHome"); CountHome home = (CountHome) PortableRemoteObject.narrow (h, CountHome.class); HomeHandle homehandle = home.getHomeHandle (); / / Get homehandle .... counthome = (counthome) HomeHandle.Getejbhromou (); count recount = rehy.create (); Using the above two methods, we can automatically store and rebuild EJB in the Reference Reed Required Session Bean information. Ok, learn more about the above knowledge, let's take a real session bean to see its way of operation! 2. Development and deployment of a stateful session bean to develop a session bean, basic should follow the following steps, first develop the Remote interface, write the Home interface, then Bean itself. At the same time, in order to distinguish, we should follow the following naming rules by default, the Remote interface is named directly with XXX, and the home interface is named with XXXBean. First, we manually establish the development environment, in the C: / JBoss directory (here, refer to the installation directory of JBoss, see the next section) Newly built a directory MYPROJACT that stores our project, and then build a reserved this count session bean in MyProject Directory CounterstateFullSessionBean, used to store all related files for this bean. Then, then build three directories in the CountersTateFullSessionBean directory: EJB, JSP, and SRCs are used to store EJB classes, web application files (JSP files, and servlet classes) and our source program. Then, then build a client directory and a counter.jar directory in the EJB directory and a CLIENT test program and server-side class. Then, in the client and counter.jar directory, each new counter directory is created, and then build an EJB directory in the Counter directory, which is our name. Then build a META-INF directory in the Counter.jar directory to store our EJB profile. Then, then create a new counter directory to save the Web Send a program, and then create a new web-inflicity under the counter.war, and create a ClassSes directory in the web-INF directory. Package directory Counter and the EJB directory under the directory of the COUNTER.
Ok, our directory has been established, our directory structure is shown in Figure 1: Figure 1 is good, we use the above knowledge to build a stateful session bean and its test procedure. We introduce a session bean in "mastering ejb" (SECOND Edition), namely Count. This bean has a state domain named Val, which is used to save the number of times of the corresponding client calling the EBJ method. We entered the src directory, all the source programs we all prepared and stored in this directory. Write the Remote interface, the code is as follows: //count.java
Package counter.ejb; import javax.ejb. *; import java.rmi.remoteException; public interface count extends ejbobject {public int count () throws remoteException;}
Write the Home interface, the code is as follows:
//CountHome.java package counter.ejb; import javax.ejb *;. Import java.rmi.RemoteException; public interface CountHome extends EJBHome {Count create (int val) throws RemoteException, CreateException;}
Write the bean class, the code is as follows: //countbean.java package counter.ejb; import javax.ejb. *; Public class countben importben implements sessionBean {// Current count value is a dialog state public int val; private sessionContext CTX; // EJB Method public int count () {system.out.println ("count ()"); Return Val;}
// EJB must
Public void ejbcreate (int val)...............
System.out.println ("ejbcreate ()");
}
Public void ejbremove () {
System.out.println ("ejbremove ()");
}
Public void ejbactivate () {
System.out.println ("ejbactivate ()");
}
Public void ejbpassivate () {
System.out.println ("ejbpassivate ()");
}
Public void setsessionContext (sessionContext CTX) {
THIS.CTX = CTX;
}
Public sessionContext GetSessionContext () {
Return this.ctX;
}
Ok, we have three Java files in the src directory, which is the class of EJB, which we use the com.bat file written in the first section to compile them. Through the SRC directory, you will have three .class files. Let's deploy our EJB. First write deployment descriptors, enter: c: /jboss/myproject/counterstateFullSessionBean/ejb/counter.jar/meta-inf directory, create a new ejb-jar.xml file, the content is as follows: XML Version = "1.0" Encoding = "GB2312"?>
"http://java.sun.com/dtd/ejb-jar_2_0.dtd">
session>
enterprise-beans>
ejb-jar>
This is an EJB deployment descriptor file, which declares some properties of this CountBean, such as declaring the type of local interface, remote interface, and bean. Where
XML Version = "1.0" encoding = "GB2312"?>
session>
enterprise-beans>
jboss>
This file describes some of this EJB in the JNDI tree when our client calls this EJB. As with the above declaration, we can use JNDI names in the client to find this countbean, and call it EJB method, which corresponds to the bean described in
Import java.util. *;
Import java.io. *;
Import javax.naming.initialcontext;
Import javax.rmi.portableremoteObject;
Import javax.naming.context;
Import javax.rmi.portableremoteObject;
Public Class CountClient
{
Public static void main (string [] args)
{
// JNDI configuration, implemented as an external property file
InitialContext CTX = NULL;
Try {
Properties env = new property ();
The //config.properties file should be placed in the same-level directory in the directory where the Hello package directory is located. That is, it and the Hello folder are in a folder.
Env.Load (New FileInputStream ("config.properties");
// Get a naming context
System.out.println (ENV);
CTX = New javax.naming.initialcontext (env);
System.out.println ("got context");
// Get a reason to the INTEREST bean // jboss default jndi named EJB-JAR.XML: EJB-NAME and JNDI-NAME specified
Object ref = ctx.lookup ("count");
System.out.println ("Got Reference");
CountHome Counthome = (CountHome) PortableRemoteObject.Narrow (Ref, Counthome.class);
// Create An Count Object from The Home Interface
INT VAL = 0;
Count count = countHome.create (VAL);
// Call the count () Method
For (int i = 0; i <10; i ) {
System.out.println ("The value of count in SessionBean is:" count.count ());
}
// Remove the Object
Count.remove ();
} catch (Exception E)
{
System.out.println (E.TOString ());
} finally {
IF (ctx! = null) {
Try {
CTX.Close ();
} catch (javax.naming.namingexception ex) {
}
}
}
}
}
Then, compile it, enter the src directory, run: com * .java, you will compile the countClient.java, after compiling, four Class files will be generated in our SRC directory. Let's deploy and test this client program, copy the countclient.class, count.class, and counthome.class to our client program, copy to: C: / JBoss / MYPROJECT / CounterStateFullSessionBean / EJB / Client / Counter / EJB directory. Then build a config.properties file below the Client directory, as follows:
Java.naming.factory.initial = org.jnp.interfaces.namingContextFactory
Java.naming.factory.url.pkgs = org.jboss.naming.client
Java.naming.Provider.URL = jnp: //10.0.0.18: 1099 / / This is the IP address of this unit.
This file is propituted by the JNDI entry information. Enter the client directory in the DOS mode, execute: Runclient Counter / EJB / CountClient can see the correct output. Third, the page calls the stateful session bean and the stateful session bean Reusal Method Let's write our EJB sample programs in the web page, to verify that our EJB is stateful session bean, it can save our status The state of the session bean, we use the following way: call the EJB method in the servlet and run it to make the VAL value in the state session bean count to a value; then, we guide the URL to the JSP file in the servlet, and then in JSP Check if the status value in the session bean in the file is saved. The status conversion diagram of the test program is shown in Figure 2: Figure 2 First Write the servlet file, enter the src directory, create a custservlet.java file, the content is as follows: package counter;
Import javax.servlet. *;
Import javax.servlet.http. *;
Import java.io. *;
Import javax.ejb. *;
Import javax.naming.initialcontext;
Import javax.naming.context;
Import java.util. *;
Import javax.servlet.RequestDispatcher;
Import counter.ejb. *;
Public Class CountServlet Extends Httpservlet
{
Private counthome counthome = null;
Public void init () throws servletexception {
CONTEXT CTX = NULL;
Try {
String InitctXFactory = getinitParameter (Context.Initial_Context_Factory);
String providerurl = getinitParameter (context.provider_url);
Properties env = new property ();
IF (InitctXFactory! = NULL) {
Env.put (Context.Initial_Context_Factory, InitctXFactory);
}
IF (providerurn! = null) {
Env.put (Context.Provider_URL, ProviderURL);
}
CTX = New InitialContext (ENV);
Object objref = ctx.lookup ("count");
// main interface
Counthome = (countHome) javax.rmi.portableremoteObject.narrow (Objref, Counter.ejb.counethome.class);
} catch (javax.naming.namingexception ne) {
System.out.println ("Create Exception Caught: NE);
Throw new servletexception (ne.tostring ());
} catch (exception e) {
Throw new servletException (e.tostring ());
} finally {
IF (ctx! = null) {
Try {ctx.close ();
} catch (javax.naming.namingexception ex) {
}
}
}
}
Public void service (httpservletRequest Req, httpservletResponse respon) throws oException, servletexception {
Try {
// Component interface
INT VAL = 0;
Count countbean = counthome.create (val);
// Get the Handle of the session bean, use it after
Handle countHandle = countBean.getHandle ();
// Call the method of stateful session bean
For (int i = 0; i <10; i )
{
// Call 10 methods in EJB
County.count ();
}
// Save the handle of the status session bean into the session to reuse the status session bean in JSP
HttpSession session = req.getations (TRUE);
Session.setttribute ("countHandle", counthandle;
/ / Redirect to the JSP file, get the status of this stateful session bean in the JSP file
RequestDispatcher Disp = GetServletContext (). GetRequestDispatcher ("/ page.jsp");
// Note: You cannot access servletoutputStream or PrintWriter before calling the Disp.Forward method. You cannot output a stream to be accessed.
Disp.Forward (Req, ResP);
// Do not call Remove here, otherwise delete the status session bean in the container pool, and the JSP cannot be used.
//countbean.remove ();
// Reuse this session bean method is as follows
// The first method, obtains EJB's Handle (Javax.ejb.handle) with EJBOBJECT's getHandle () method.
// Use the following method when used
// count count = (count) javax.rmi.portableremoteObject.narrow (counthandle.getejbobject (), counter.ejb.count.class;
//count.count ();
//count.remove (); // Used to delete EJB instances
// Second method, with homeHomeHandle (), example below:
// HOMEHANDLE HOMEHANDLE = countome.getHomeHandle ();
// Object Recount = homehandle.getejbhome ();
// countHome newhomeref = (countHome) PortableRemoteObject.narrow (Recount, Counter.ejb.counethome.class);
} catch (javax.ejb.createexception ce) {
System.out.println ("Create Exception Caught: CE);
} catch (java.rmi.RemoteException Re) {
System.out.println ("Remote Exception Caught: Re);} catch (javax.servlet.servletException Re) {
System.out.println ("Servlet Exception Caught: Re);
} catch (exception re) {
System.out.println ("Exception Caught: Re);
}
}
}
Next, we create a new page.jsp file, the content is as follows:
<% @ Page PageEncoding = "GB2312"%>
<% @ Page ContentType = "text / html; charset = GB2312"%>
<% Request.SetCharacterencoding ("GB2312");%>
<% @ Page Import = "javax.ejb.handle"%>
<% @ page import = "javax.naming.initialcontext"%>
<% @ Page Import = "javax.naming.context"%>
<% @ Page Import = "java.util. *"%>
<% @ Page Import = "counter.ejb. *"%>
<%
Httpsession mysession = request.getations (FALSE);
Handle countHandle = (Handle) MySession.getaTRibute ("counthandle");
INT NO = -1;
If (countHandle == NULL) {// Directly request this JSP file with the following code
CONTEXT CTX = NULL;
Counthome counthome = null;
Properties env = new property ();
CTX = New InitialContext (ENV);
Object objref = ctx.lookup ("count");
// main interface
Counthome = (countHome) javax.rmi.portableremoteObject.narrow (Objref, Counter.ejb.counethome.class);
Count count = counthome.create (0);
NO = count.count ();
Count.remove ();
CTX.Close ();
} else if (countHandle! = null) {// from the servlet
Count count = (count) javax.rmi.portableremoteObject.narrow (counthandle.getejbobject (), counter.eb.count.class; // Recommend this session bean
NO = count.count ();
Count.remove ();
Mysession.Removettribute ("counthandle"); // Delete Attribute in Session
}
%>
hEAD>
<%
IF (NO! = - 1) {
%>
The current value in the SESSIONBEAN is <% = no%>!
<%}%>
p> body> html>
We can then deploy our web client, first deploy the servlet, copy countservlet.class to: c: /jboss/myproject/counterstateFullSessionBean/jsp/counter.war/web-inf/classes/counter, then Edit the new web.xml in the c: /jboss/myproject/counterstatefullsessionBean/jsp/counter.war/web-inf directory, as follows:
XML Version = "1.0" encoding = "GB2312"?>
servlet>
servlet-maping>
web-app>