📄 rmi.html
字号:
client.
<P>
If the calling client is written in the Java programming language, and is not,
for example, a web page, the server can update the client as soon as the results
are ready. But, the HTTP protocol used in most browsers does not allow results
to be pushed to the client without a request for those results. This means the
results web page is not created until the results are ready, which can add a small delay.
<A NAME="class"></A>
<H4>Class Overview</H4>
The two main classes in the RMI-based auction implementation are
<A HREF="./Code/rmi/SellerBean.java">SellerBean</A> and the remote
<A HREF="./Code/rmi/RegistrationServer.java">RegistrationServer</A>.
<CODE>SellerBean</CODE> is called from
<A HREF="./Code/rmi/AuctionServlet.java">AuctionServlet</A>
to insert an auction item into the database, and check for low
account balances.
<P>
The example models the Enterprise JavaBeans architecture in that a
user's registration details are separate from the code to create and find
the registration details. That is, the user's registration details provided
by the
<A HREF="./Code/rmi/Registration.java">Registration.java</A> class
are separate from the code to create and find a <CODE>Registration</CODE>
object, which is in the
<A HREF="./Code/rmi/RegistrationHome.java">RegistrationHome.java</A>
class.
<P>
The remote interface implementation in
<A HREF="./Code/rmi/RegistrationHome.java">RegistrationHome.java</A>
is bound to the <CODE>rmiregistry</CODE>. When a client program
wants to manipulate a user's registration details, it must first look
up the reference to the
<A HREF="./Code/rmi/RegistrationHome.java">RegistrationHome.java</A>
object in the <CODE>rmiregistry</CODE>.
<A NAME="file"></A>
<H4>File Summary</H4>
All the source code files for the RMI-based example are described
in the bullet list below.
<UL>
<LI><FONT FACE="Verdana, Arial, Helvetica, sans-serif">
<A HREF="./Code/rmi/SellerBean.java">SellerBean.java</A>:
Client program that calls the <CODE>RegistrationServer.verifypasswd</CODE> and
<CODE>RegistrationServer.findLowCreditAccounts</CODE> remote methods.
<CODE>SellerBean</CODE> also exports its <CODE>updateResults</CODE>
method that <CODE>RegistrationServer</CODE> calls when it completes its
<CODE>RegistrationServer.findLowCreditAccounts</CODE> search.</FONT>
<P>
<LI><FONT FACE="Verdana, Arial, Helvetica, sans-serif">
<A HREF="./Code/rmi/RegistrationServer.java">RegistrationServer.java</A>:
Remote server object that implements the <CODE>RegistrationHome</CODE> and
<CODE>Registration</CODE> remote interfaces.</FONT>
<P>
<LI><FONT FACE="Verdana, Arial, Helvetica, sans-serif">
<A HREF="./Code/rmi/Registration.java">Registration.java</A>:
Remote interface that declares the <CODE>getUser</CODE>,
<CODE>verifypasswd</CODE>, and other remote methods for managing
a user's registration details.</FONT>
<P>
<LI><FONT FACE="Verdana, Arial, Helvetica, sans-serif">
<A HREF="./Code/rmi/RegistrationHome.java">RegistrationHome.java</A>:
remote interface that declares the <CODE>create</CODE>,
<CODE>findByPrimaryKey</CODE>, and <CODE>findLowCreditAccounts</CODE>
remote methods that create or return instances of registration details.</FONT>
<P>
<LI><FONT FACE="Verdana, Arial, Helvetica, sans-serif">
<A HREF="./Code/rmi/RegistrationServer.html#RegistrationImpl">RegistrationImpl.java</A>:
The <CODE>RegistrationServer.java</CODE> source file includes the implementation
for the <CODE>Registration</CODE> remote interface as class
<CODE>RegistrationImpl</CODE></FONT>
<P>
<LI><FONT FACE="Verdana, Arial, Helvetica, sans-serif">
<A HREF="./Code/rmi/RegistrationPK.java">RegistrationPK.java</A>:
Class that represents a user's registration details using
just the primary key of the database record.</FONT>
<P>
<LI><FONT FACE="Verdana, Arial, Helvetica, sans-serif">
<A HREF="./Code/rmi/ReturnResults.java">ReturnResults.java</A>:
Remote interface that declares the <CODE>updateResults</CODE> method
the <CODE>SellerBean</CODE> class implements as a callback.</FONT>
<P>
<LI><FONT FACE="Verdana, Arial, Helvetica, sans-serif">
<A HREF="./Code/rmi/AuctionServlet.java">AuctionServlet.java</A>:
Modified version of the original <CODE>AuctionServlet</CODE> class
where registration accounts are created by calling the RMI
<CODE>RegistrationServer</CODE> directly. The auction
servlet also calls the <CODE>SellerBean.auditAccounts</CODE> method, which
returns a list of users with a low account balance.
<P>
The <CODE>auditAccounts</CODE> method is called with the following
Uniform Resource Locator (URL), which does a simple check to verify
the request came from the local host.</FONT>
<PRE>
http://phoenix.eng.sun.com:7001/
AuctionServlet?action=auditAccounts
</PRE>
</UL>
You also need a
<A HREF="./Code/rmi/java.policy">java.policy</A> security policy
file to grant the permissions needed to run the example on
the Java 2 platforms.
<P>
Most RMI applications need the two socket permissions for
socket and HTTP access to the specified ports. The two thread permissions,
were listed in a stack trace as being needed for the
<CODE>RegistrationImpl</CODE> class to create a new inner thread.
<P>
In the Java 2 platform, when a program does not have all the permissions
it needs, the Java<A HREF="#TJVM"><SUP>1</SUP></A> virtual machine (VM) generates a stack trace that lists
the permissions that need to be added to the security policy file.
See <A HREF="signed.html">Chapter 9: Program Signing and Security</A> for more information.
<P>
<PRE>
grant {
permission java.net.SocketPermission
"*:1024-65535", "connect,accept,resolve";
permission java.net.SocketPermission "*:80",
"connect";
permission java.lang.RuntimePermission
"modifyThreadGroup";
permission java.lang.RuntimePermission
"modifyThread";
};
</PRE>
<A NAME="compile"></A>
<H4>Compile the Example</H4>
Before describing the RMI-based code for the above classes, here
is the command sequence to compile the example on the Unix and Win32 platforms:
<PRE>
<STRONG>Unix:</STRONG>
javac registration/Registration.java
javac registration/RegistrationPK.java
javac registration/RegistrationServer.java
javac registration/ReturnResults.java
javac seller/SellerBean.java
rmic -d . registration.RegistrationServer
rmic -d . registration.RegistrationImpl
rmic -d . seller.SellerBean
</PRE>
<PRE>
<STRONG>Win32:</STRONG>
javac registration\Registration.java
javac registration\RegistrationPK.java
javac registration\RegistrationServer.java
javac registration\ReturnResults.java
javac seller\SellerBean.java
rmic -d . registration.RegistrationServer
rmic -d . registration.RegistrationImpl
rmic -d . seller.SellerBean
</PRE>
<P>
<A NAME="rmiregis"></A>
<H4>Start the RMI Registry</H4>
Because you are using your own RMI code, you have to explicitly start the
RMI Registry so the <CODE>SellerBean</CODE> object can find the remote
Enterprise Beans. The <CODE>RegistrationServer</CODE> uses the RMI
Registry to register or bind enterprise Beans that can be called remotely.
The <CODE>SellerBean</CODE> client contacts the registry to look up and
get references to the remote <CODE>AuctionItem</CODE> and <CODE>Registration</CODE>
Enterprise Beans.
<P>
Because RMI allows code and data to be transferred, you must be sure
the system <CODE>classloader</CODE> does not load extra classes that
could be mistakenly sent to the client. In this example, extra classes
would be the Stub and Skel class files, and the <CODE>RegistrationSever</CODE>
and <CODE>RegistrationImpl</CODE> classes, and to prevent them being
mistakenly sent, they should not appear anywhere in the <CODE>CLASSPATH</CODE>
when you start the RMI Registry. Because the current path could be included
automatically, you need to start the RMI Registry away from the code workspace too.
<P>
The following commands prevent the sending of extra classes
by unsetting the <CODE>CLASSPATH</CODE> before starting the RMI
Registry on the default 1099 port. You can specify a different port by
adding the port number as follows: <CODE>rmiregistry 4321 &</CODE>. If you
specify a different port number, you must specify the same port number in
both you client <CODE>lookup</CODE> and server <CODE>rebind</CODE> calls.
<PRE>
<STRONG>Unix:</STRONG>
export CLASSPATH=""
rmiregistry &
</PRE>
<PRE>
<STRONG>Win32:</STRONG>
unset CLASSPATH
start rmiregistry
</PRE>
<A NAME="start"></A>
<H4>Start the Remote Server </H4>
Once the <CODE>rmiregistry</CODE> is running, you can start the
remote server, <CODE>RegistrationServer</CODE>.
The <CODE>RegistrationServer</CODE> program registers the name
<CODE>registration2</CODE> with the <CODE>rmiregistry</CODE> name server,
and any client can use this name to retrieve a reference to the
remote server object, <CODE>RegistrationHome</CODE>.
<P>
To run the example, copy the <CODE>RegistrationServer</CODE> and
<CODE>RegistrationImpl</CODE> classes and the associated stub
classes a remotely accessible area and start the server program.
<PRE>
<STRONG>Unix:</STRONG>
cp *_Stub.class
/home/zelda/public_html/registration
cp RegistrationImpl.class
/home/zelda/public_html/registration
cd /home/zelda/public_html/registration
java -Djava.server.hostname=
phoenix.eng.sun.com RegistrationServer
<STRONG>Windows:</STRONG>
copy *_Stub.class
\home\zelda\public_html\registration
copy RegistrationImpl.class
\home\zelda\public_html\registration
cd \home\zelda\public_html\registration
java -Djava.server.hostname=
phoenix.eng.sun.com RegistrationServer
</PRE>
<P>
The following key properties used to configure RMI servers
and clients. These properties can be set inside the program or supplied
as command line properties to the Java VM.
<UL>
<LI><FONT FACE="Verdana, Arial, Helvetica, sans-serif">The <CODE>java.rmi.server.codebase</CODE> property specifies
where the publicly accessible classes are located. On the server this
can be a simple file URL to point to the directory or JAR file that
contains the classes. If the URL points to a directory, the URL must
terminate with a file separator character, "/".
<P>
If you are not using a file URL, you will either need an HTTP server
to download the remote classes or have to manually deliver the remote
client stub and remote interface classes in, for example, a JAR file.</FONT>
<P>
<LI><FONT FACE="Verdana, Arial, Helvetica, sans-serif">The <CODE>java.rmi.server.hostname</CODE> property is the
complete host name of the server where the publicly accessible
classes reside. This is only needed if the server has problems
generating a fully qualified name by itself.</FONT>
<P>
<LI><FONT FACE="Verdana, Arial, Helvetica, sans-serif">The <CODE>java.rmi.security.policy</CODE> property specifies
the <A HREF="./Code/rmi/java.policy">policy file</A>
with the permissions needed to run the remote server object and
access the remote server classes for download.</FONT>
</UL>
<A NAME="remote"></A>
<H3>Establishing Remote Communications</H3>
Client programs communicate with each other through the
server. The server program consists of three files. The
<CODE>Registration.java</CODE> and <CODE>RegistrationHome.java</CODE>
remote interface files define the methods that can
be called remotely, and the <CODE>RegistrationServer.java</CODE> class file
defines the <CODE>RegistrationServer</CODE> and <CODE>RegistrationImpl</CODE>
classes that implement the methods.
<P>
To establish remote communications, both the client and server programs
need to access the remote interface classes. The server needs the interface
classes to generate the interface implementation, and the client uses the
remote interface class to call the remote server method implementation.
<P>
For example, <CODE>SellerBean</CODE> creates a reference to
<CODE>RegistrationHome</CODE>, the interface, and not
<CODE>RegistrationServer</CODE>, the implementation, when it needs to
create a user registration.
<P>
Besides the server interfaces and classes, you need stub and
skeleton classes to establish remote communications. The
stub and skeleton classes needed in this example are generated
when you run the <CODE>rmic</CODE> compiler command on the
<CODE>RegistrationServer</CODE> and <CODE>SellerBean</CODE> classes.
<P>
The generated <CODE>SellerBean</CODE>, <CODE>SellerBean_Stub.class</CODE> and
<CODE>SellerBean_Skel.class</CODE> classes are needed for the callback from the
server to the <CODE>SellerBean</CODE> client. It is the <CODE>_Stub.class</CODE>
file on the client that marshals data to and unmarshals it from the server, while
the <CODE>_Skel.class</CODE> class does the same for the server.
<P>
<BLOCKQUOTE>
<HR>
<STRONG>Note:</STRONG> In the Java 2 platform, the server side,
<CODE>_Skel.class</CODE> file is no longer needed because its
function has been taken over by the Java Virtual Machine classes
<HR>
</BLOCKQUOTE>
<H4>Data Marshaling</H4>
Marshaling and unmarshaling data means that when you call the
<CODE>RegistrationHome.create</CODE> method from <CODE>SellerBean</CODE>,
this call is forwarded to the <CODE>RegistrationServer_Stub.create</CODE>
method. The <CODE>RegistrationServer_Stub.create</CODE> method
wraps the method arguments and sends a serialized stream of bytes
to the <CODE>RegistrationServer_Skel.create</CODE> method.
<P>
<IMG SRC="./Art/marshal.gif" ALIGN="LEFT">
The <CODE>RegistrationServer_Skel.create</CODE> method unwraps the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -