EJB works First, I want to talk about RMI's working principle, because EJB is based on RMI. There are not many nonsense, the essence of RMI is the call between different JVMs, the working principle is as follows: its implementation method is to open a Stub and Skeleton in two JVMs, both through Socket communication to implement parameters And the transfer of the return value. There are a lot of examples on RMI, but most of them are implemented through extende interface java.rmi.Remote, which has been installed very well, and it is inevitable that people feel in fog. The following example is I saw in "Enterprise Javabeans", although it is rough, but it is very intuitive, it is good to learn about its working principle. 1. Define a Person interface, two business methods, getage () and getname ()
Code: public interface person {public interface () throws throwable; public string getName () throws throwable;} 2. Person's implementation of the Personserver class
Code: public class PersonServer implements Person {int age; String name; public PersonServer (String name, int age) {this.age = age; this.name = name;} public int getAge () {return age;} public String getName () {RETURN Name;}} 3. Well, we now have to call Getage () and getName () on the Client machine, so we have to write the corresponding Stub (Client end) and SKELETON (SERVER) program. This is the implementation of Stub:
Code: import java.io.ObjectOutputStream; import java.io.ObjectInputStream; import java.net.Socket; public class Person_Stub implements Person {Socket socket; public Person_Stub () throws Throwable {// connect to skeleton socket = new Socket ( " computer_name ", 9000);} public int getAge () throws Throwable {// pass method name to skeleton ObjectOutputStream outStream = new ObjectOutputStream (socket.getOutputStream ()); outStream.writeObject (" age "); outStream.flush (); ObjectInputStream inStream = new ObjectInputStream (socket.getInputStream ()); return inStream.readInt ();} public String getName () throws Throwable {// pass method name to skeleton ObjectOutputStream outStream = new ObjectOutputStream (socket.getOutputStream ()); outStream .writeObject ("name"); outstream.flush (); ObjectInputStream Instream = new ObjectInputst Ream (socket.getinputStream ()); return (String) Instream.readObject ();}} Note, like Person_stub and PersonServer, both imports person. They all enable both business method, different is that PersonServer is real implementation, and Person_STub is a Socket connection to the Skeleton, and then call the Personserver by Skeleton, and finally receive the result of returned . 4. Skeleton implementation
Code: import java.io.ObjectOutputStream; import java.io.ObjectInputStream; import java.net.Socket; import java.net.ServerSocket; public class Person_Skeleton extends Thread {PersonServer myServer; public Person_Skeleton (PersonServer server) {// get reference of object server this.myServer = server;} public void run () {try {// new socket at port 9000 serverSocket serverSocket = new serverSocket (9000); // accept stub's request Socket socket = serverSocket.accept (); while ( ! socket = null) {// get stub's request ObjectInputStream inStream = new ObjectInputStream (socket.getInputStream ()); String method = (String) inStream.readObject (); // check method name if (method.equals ( "age" )) {// Execute Object Server's business method int Age = MyServer.getage () ; ObjectOutputStream outStream = new ObjectOutputStream (socket.getOutputStream ()); // return result to stub outStream.writeInt (age); outStream.flush ();} if (method.equals ( "name")) {// execute object server's business method String name = myServer.getName (); ObjectOutputStream outStream = new ObjectOutputStream (socket.getOutputStream ()); // return result to stub outStream.writeObject (name);
Outstream.flush ();}}} catch (throwable t) {T.PrintStackTrace (); system.exit (0);}} public static void main (string args []) {// new object server personServer person = new Personserver ("Richard", 34); Person_Skeleton Skel = New Person_skeleton (Person); Skel.Start ();}} Skeleton class Extends from Thread, which is running in the background, receives the client sent by Client. And call the corresponding business method according to the sending key. 5. Last, Client's implementation code: public class persid {public static void main (string [] args) {Try {person Person = new person_stub (); int Age = person.getage (); string name = person.getname (); System.out.println (Name "IS" Age "Years Old");} catch (throwable t) {T.PrintStackTrace ();}}} Client's nature is that it must know the Person interface Definition, and instance a person_stub, call Business Method via Stub, as for how to communicate with Server, and Client does not have to manage. Pay attention to it: Person Person = New Person_stub (); not Person_stub Person = new person_stub (); why? Because it is necessary to facilitate interface programming, huh, huh. About RMI, I want to say so much. Here is the EJB of each class
The EJB class will not be used by WebLogic, here is combined with WebSphere to talk about the call relationships of each class. Assuming that we want to create a sessionbean that reads User information, we need to write 3 files: 1. UserviceHome.java HOME interface 2. Uservice.java Remote interface 3. UserviceBean.java bean implementation WSAD will eventually generate 10 Class. What is the other 7? Let's have a number of: 4. _USERSERSERVICEHOME_STUB.JAVA This is of course the Home interface in the Client side (dynamically loaded) Stub class, it is IMPLEments UserviceHome. 5._ejsremotestatelessuserServiceHome_A940AA04_TIE.JAVA HOME Interface The SKELETON class in the Server side, "A940AA04" should be randomly generated, all other related CLASS names will have this flag string, Tie is called Skeleton. 6. EJSREMOTASTATASSERSERSERVICEHOME_A940AA04.Java Home Interface Implementation in Server end, of course, it also imports UserviceHome. 7. EJSSTATASSERSERSERVICEHOMEBEAN_A940AA04.JAVA is called by # 6, Create _userService_stub. (Why can't # 6 can't use directly _userService_stub?) After later.) 8. _USERSERSERVICE_STUB.JAVA Remote Interface The stub class of the Client side (dynamically). It imports Uservice. 9. _ejsRemotestateLessuserService_a940aa04_tie.java Remote Interface The Skeleton class in the Server end. 10. EJSREMOTESTATELESSUSERSERVICE_A940AA04.Java Remote Interface Implementation in the Server end, of course, it is also imports Uservice. Also, it is responsible for calling UserServiceBean - that is, the bean we wrote bean implementation class - the business method inside. So, what is the call relationship between the various classes? Simply put, it is two RMI cycles.
script>
First RMI cycle first to see how the client's program is written:
Code: try {InitialContext ctx = new InitialContext (); // Step UserServiceHome home = (UserServiceHome) PortableRemoteObject.narrow (ctx.lookup (JNDIString), UserServiceHome.class); // home: _UserServiceHome_Stub System.out.println ( Home.toString ()); // Step 2 Uservice Object = Home.create (); // OjBect: _USERSERVICE_STUB System.out.println (Object.tostring ()); // Step 3 INT UserId = 1; userInfo UI = Object.getuserinfo (UserID); Look with Debug, I know that HOME is originally _USERSERSERVICEHOME_STUB instance. From the second step, we are concerned, although there is only a simple line of code, users.create (); but what is the system behind it? Let's go to the code: 1. Call home.create () code: userServiceHome Home; userservice obj = home.create (); 2. Actually call _USERSERSERVICEHOME_STUB.CREATE (), in this method, Stub Send Skeleton A crete string:
Code: org.omg.corba.portable.outputstream out = _Request ("create", true); in = (org.omg.corba_2_3.portable.inputstream) _invoke (out); 3. Skeleton of the Server Receive STUB sent Request, and call the corresponding method:
Code: _EJSREMOTESTATASSERSERSERVICEHOME_A940AA04_TIE._INVOKE () {... Switch (Method.Length ()) {Case 6: IF (Method.equals ("Create")) {Return Create (in, reply);} ... ...}}
Code: _EJSRemoteStatelessUserServiceHome_a940aa04_Tie.create () {EJSRemoteStatelessUserServiceHome_a940aa04 target = null; result = target.create (); org.omg.CORBA.portable.OutputStream out = reply.createReply (); Util.writeRemoteObject (out, result); return out; } 4. Skeleton end UserServiceHome Server is called the implementation class of the create method code: EJSRemoteStatelessUserServiceHome_a940aa04.create () {UserService _EJS_result; _EJS_result = EJSStatelessUserServiceHomeBean_a940aa04.create ();} 5. # 4 in turn calls EJSStatelessUserServiceHomeBean_a940aa04.create ()
Code: Uservice Result = Super.createWrapper (New BeanId (null)); to this, we finally ended the first RMI loop and got the Remote Interface Uservice's Stub class _USERSERVICE_STUB, which is # 5 in the RESULT. Here is a problem, why # 4 does not directly create _USERSERVICE_STUB, and turn a # 5 hand? Because # 4 extends from ejswrapper, it has no ability to create stub, so you must use the # 5, Which Extends from EJSHOME, so you can generate a STUB. If not to generate this stub, you should not leave # 5.
The second RMI loop OK, NOW We got the Object Which is instanceof _userService_stub, and IMPLEMENTS USERSERVICE Now our client end to the third step: userinfo ui = Object.getuserinfo (userid); continue to see the code, start the second RMI loop: 1. call Object.getUserInfo ()
Code: Uservice Object; Object.getuserinfo (UserID); 2. Actually call _USERSERVICE_STUB.GETUSERINFO (int Arg0), in this method, Stub sends a getUserInfo string and arg0 parameters to Skeleton:
Code: org.omg.corba.portable.outputStream out = _REQUEST ("getuserinfo", true); out.write_long (arg0); in = (org.omg.corba_2_3.portable.inputstream) _invoke (out); 3. Server The end SKELETON receives the Request sent by Stub and calls the corresponding method:
Code: _EJSREMOTESTATASSUSERSERVICE_A940AA04_TIE._INVOKE () {Switch (Method.Charat (5)) {Case 83: IF (Method.equals ("getuserInfo")) {Return getUserInfo (in, reply);} ...}} _EJSRemoteStatelessUserService_a940aa04_Tie.getUserInfo () {EJSRemoteStatelessUserService_a940aa04 target = null; int arg0 = in.read_long (); UserDTO result = target.getUserInfo (arg0); org.omg.CORBA_2_3.portable.OutputStream out = reply.createReply (); out.write_value (result, UserDTO.class); return out;} 4. Skeleton call is end UserService Server implementation class getUserInfo method code: EJSRemoteStatelessUserService_a940aa04.getUserInfo () {UserServiceBean _EJS_beanRef = container.preInvoke (this, 0, _EJS_s); _EJS_result = _Ejs_beanref.getuserInfo (ID);} The last final, # 4 finally called the getUserInfo method in the UserServiceBean we wrote, this is what we really want to do. At this point, the second RMI cycle is finally ended.
The call flow chart reviews the above analysis, you can see the process of two RMI loops, the following picture (see link) describe the entire process: http://www.pbase.com/image/27229257 Yellow 1, 6, 10 is to write by the programmer, the rest is the system generated. # 1 is home interface, # 2, and # 4 are both IMplements. # 6 is Remote Interface, # 7, and # 9 all imports. # 10 is a bean implementation.