📄 corba.html
字号:
<A NAME="stub"></A>
<H4>Stubs and Skeletons</H4>
Corba and RMI are similar in that compilation generates a stub file for
the client and a skeleton file for the server. The stub (or proxy),
and skeleton (or servant) are used to marshal and unmarshal data between the
client and the server. The skeleton (or servant) is implemented by the
server. In this example, the IDL <CODE>RegistrationHome</CODE> interface
mapping generates a <CODE>_RegistrationHomeImplBase</CODE> class
(the skeleton or servant class) that the generated
<CODE>RegistrationServer</CODE> class extends.
<P>
<IMG SRC="./Art/marshal2.gif">
<P>
When requesting a remote CORBA object or calling a remote method, the
client call passes through the stub class before reaching the server. This
proxy class invokes CORBA requests for the client program. The following
example is the code automatically generated for the
<CODE>RegistrationHomeStub.java</CODE> class.
<PRE>
org.omg.CORBA.Request r = _request("create");
r.set_return_type(
registration.RegistrationPKHelper.type());
org.omg.CORBA.Any _theuser = r.add_in_arg();
</PRE>
<A NAME="orb"></A>
<H3>Object Request Broker</H3>
The center of the CORBA distributed network is the Object Request Broker
or ORB. The ORB is involved in marshaling and unmarshaling objects between
the client and server. Other services such as the Naming Service and Event
Service work with the ORB.
<P>
The Java 2 platform includes an ORB in the distribution called the IDL ORB.
This ORB is different from many other ORBs because it does not include a distinct
Basic Object Adapter (BOA) or Portable Object Adapter (POA).
<P>
An object adapter manages the creation and lifecycle of objects in the CORBA
distributed space. This can be compared to the container in the Enterprise JavaBeans
server managing the lifecycle of the session and entity beans.
<P>
The <A HREF="./Code/corba/AuctionServlet.java">AuctionServlet</A> and
<A HREF="./Code/corba/SellerBean.java">SellerBean</A> programs
create and initialize a Java 2 ORB like this:
<PRE>
ORB orb = ORB.init(args, null);
</PRE>
In the <A HREF="./Code/corba/RegistrationServer.java">RegistrationServer</A>
program, the server object to be distributed is bound to the ORB
using the <CODE>connect</CODE> method:
<PRE>
RegistrationServer rs = new RegistrationServer();
orb.connect(rs);
</PRE>
An object connected to an ORB can be removed with the <CODE>disconnect</CODE>
method:
<PRE>
orb.disconnect(rs);
</PRE>
Once connected to a CORBA server object, the Java 2 ORB keeps the server
alive and waits for client requests to the CORBA server.
<PRE>
java.lang.Object sync = new java.lang.Object();
synchronized(sync) {
sync.wait();
}
</PRE>
<A NAME="make"></A>
<H4>Making the CORBA Server Accessible</H4>
Although this object is now being managed by the ORB, the clients do
not yet have a mechanism to find the remote object. This can be solved by
binding the CORBA server object to a naming service.
<P>
The Java 2 naming service is called <CODE>tnameserv</CODE>. The naming service
by default uses port 900; however, this value can be changed by setting
the argument <CODE>-ORBInitialPort portnumber</CODE> when starting
<CODE>tnameserv</CODE> or setting the property
<CODE>org.omg.CORBA.ORBInitialPort</CODE> when starting the client and
server processes.
<P>
These next sections describes the <CODE>main</CODE> method from the
<CODE>RegistrationServer</CODE> class.
<PRE>
java.util.Properties props=System.getProperties();
props.put("org.omg.CORBA.ORBInitialPort", "1050");
System.setProperties(props);
ORB orb = ORB.init(args, props);
</PRE>
The next lines show the initial naming reference is initialized by
requesting the service
called <CODE>NameService</CODE>. The <CODE>NamingContext</CODE> is retrieved
and the name built up and bound to the naming service as
<CODE>NameComponent</CODE> elements. The name in this example has
a root called <CODE>auction</CODE> with this object being bound
as <CODE>RegistrationBean</CODE> from that <CODE>auction</CODE> root. The
name could be compared to a class by the name of
<CODE>auction.RegistrationBean</CODE>.
<PRE>
org.omg.CORBA.Object nameServiceObj =
orb.resolve_initial_references("NameService") ;
NamingContext nctx =
NamingContextHelper.narrow(nameServiceObj);
NameComponent[] fullname = new NameComponent[2];
fullname[0] = new NameComponent("auction", "");
fullname[1] = new NameComponent(
"RegistrationBean", "");
NameComponent[] tempComponent = new NameComponent[1];
for(int i=0; i < fullname.length-1; i++ ) {
tempComponent[0]= fullname[i];
try{
nctx=nctx.bind_new_context(tempComponent);
}catch (Exception e){
System.out.println("bind new"+e);}
}
tempComponent[0]=fullname[fullname.length-1];
try{
nctx.rebind(tempComponent, rs);
}catch (Exception e){
System.out.println("rebind"+e);
}
</PRE>
<A NAME="plug"></A>
<H4>Plugging in a new ORB</H4>
The Java 2 IDL ORB does not currently include some of the services
available in many other commercial ORBS such as the security or event
(notification) services. You can use another ORB in the Java 2
runtime by configuring two properties and including any necessary
object adapter code.
<P>
Using a new ORB in the registration server requires the
<CODE>org.omg.CORBA.ORBClass</CODE> and
<CODE>org.omg.CORBA.ORBSingletonClass</CODE> properties point to the
appropriate ORB classes. In this example the ORBacus ORB is used instead
of the Java 2 IDL ORB. To use another ORB, the code below should be plugged into
the <CODE>RegistrationServer.main</CODE> method.
<P>
In the example code, a <CODE>SingletonClass</CODE> ORB is used.
The <CODE>SingletonClass</CODE> ORB is not a full ORB, and is primarily
used as a factory for <CODE>TypeCodes</CODE>. The call to <CODE>ORB.init()</CODE>
in the last line creates the Singleton ORB.
<PRE>
Properties props= System.getProperties();
props.put("org.omg.CORBA.ORBClass",
"com.ooc.CORBA.ORB");
props.put("org.omg.CORBA.ORBSingletonClass",
"com.ooc.CORBA.ORBSingleton");
System.setProperties(props);
ORB orb = ORB.init(args, props) ;
</PRE>
<P>
In the Java 2 IDL, there is no distinct object adapter. As shown in the
example code segment below, using the Basic
Object Adapter from ORBacus requires an explicit cast to the ORBacus
ORB. The Broker Object Architecture (BOA)
is notified that the object is ready to be distributed
by calling the <CODE>impl_is_ready(null)</CODE> method.
<PRE>
BOA boa = ((com.ooc.CORBA.ORB)orb).BOA_init(
args, props);
...
boa.impl_is_ready(null);
</PRE>
<P>
Although both the <CODE>ORBSingletonClass</CODE> and
<CODE>ORBClass</CODE> ORBs build the object name using
<CODE>NameComponent</CODE>, you have to use a different
ORBacus Naming Service. The <CODE>CosNaming.Server</CODE>
service is started as follows where the
<CODE>-OAhost</CODE> parameter is optional:
<PRE>
java com.ooc.CosNaming.Server -OAhost localhost -OAport 1060
</PRE>
Once the naming service is started, the server and client programs
find the naming service using the IIOP protocol
to the host and port named when starting the Naming service:
<PRE>
java registration.RegistrationServer
-ORBservice NameService
iiop://localhost:1060/DefaultNamingContext
</PRE>
<A NAME="name"></A>
<H4>Naming Service Access by CORBA Clients</H4>
CORBA clients access the naming service in a similar way to the server,
except that instead of binding a name, the client resolves the name
built from the <CODE>NameComponents</CODE>.
<P>
The <CODE>AuctionServlet</CODE> and <CODE>SellerBean</CODE>
classes use the following code to look up the CORBA server:
<PRE>
NameComponent[] fullname = new NameComponent[2];
fullname[0] = new NameComponent("auction", "");
fullname[1] = new NameComponent(
"RegistrationBean", "");
RegistrationHome regRef =
RegistrationHomeHelper.narrow(
nctx.resolve(fullname));
</PRE>
In the case of the ORBacus ORB, the clients also need a Basic Object
Adapter if callbacks are used as in the
<CODE>SellerBean.auditAccounts</CODE> method.
The naming context helper is also configured differently for the ORBacus
server started earlier:
<PRE>
Object obj =
((com.ooc.CORBA.ORB)orb).get_inet_object (
"localhost",
1060,
"DefaultNamingContext");
NamingContext nctx = NamingContextHelper.narrow(obj);
</PRE>
<A NAME="help"></A>
<H3>Helper and Holder classes</H3>
References to remote objects in CORBA use a <CODE>Helper</CODE> class to retrieve
a value from that object. A commonly used method is the <CODE>Helper</CODE>
narrow method, which ensures the object is cast correctly.
<P>
<CODE>Holder</CODE> classes hold values returned when using <CODE>inout</CODE>
or <CODE>out</CODE> parameters in a method. The caller first instantiates the
appropriate <CODE>Holder</CODE> class for that type and retrieves the value from
the class when the call returns. In the next example, the count value for
<CODE>customSearch</CODE> is set and retrieved after <CODE>customSearch</CODE> has
been called.
On the server side the count value is set by calling
<CODE>count.value=newvalue</CODE>.
<PRE>
IntHolder count= new IntHolder();
sfield=regRef.customSearch(sfield,count);
System.out.println("count now set to "+count.value);
</PRE>
<A NAME="gar"></A>
<H3>Garbage Collection</H3>
Unlike RMI, CORBA does not have a distributed garbage collection mechanism.
References to an object are local to the client proxy and the server servant.
This means each Java<A HREF="#TJVM"><SUP>1</SUP></A> virtual machine (JVM) is free to reclaim that object and
garbage collect it if there are no longer references to it. If an object is no longer
needed on the server, the <CODE>orb.disconnect(object)</CODE> needs
to be called to allow the object to be garbage collected.
<A NAME="call"></A>
<H3>CORBA Callbacks</H3>
The new <CODE>findLowCreditAccounts</CODE> method is called from
the <CODE>AuctionServlet</CODE> using the Uniform Resource Locator (URL)
<CODE>http://localhost:7001/AuctionServlet?action=auditAccounts</CODE>.
<P>
The <CODE>AuctionServlet.auditAccounts</CODE> method
calls the <CODE>SellerBean.auditAccounts</CODE> method, which
returns an <CODE>ArrayList</CODE> of Registration records.
<PRE>
//AuctionServlet.java
private void auditAccounts(ServletOutputStream out,
HttpServletRequest request) throws IOException{
// ...
SellerHome home = (SellerHome) ctx.lookup("seller");
Seller si= home.create();
if(si != null) {
ArrayList ar=si.auditAccounts();
for(Iterator i=ar.iterator(); i.hasNext();) {
Registration user=(Registration)(i.next());
addLine("<TD>"+user.getUser() +
"<TD><TD>"+user.getBalance()+
"<TD><TR>", out);
}
addLine("<TABLE>", out);
}
</PRE>
The <CODE>SellerBean</CODE> object calls the CORBA
<CODE>RegistrationHome.findLowCreditAccounts</CODE> method implemented in
the <CODE>RegistrationServer.java</CODE> file, and passes a reference
to itself. The reference is passed as the <CODE>SellerBean</CODE>
class implements the <CODE>ReturnResults</CODE> inteface declared in
the <CODE>Registration.idl</CODE>.
<PRE>
//SellerBean.java
public ArrayList auditAccounts() {
try{
NameComponent[] fullname = new NameComponent[2];
fullname[0] = new NameComponent("auction", "");
fullname[1] = new NameComponent(
"RegistrationBean", "");
RegistrationHome regRef =
RegistrationHomeHelper.narrow(
nctx.resolve(fullname));
regRef.findLowCreditAccounts(this);
synchronized(ready) {
try{
ready.wait();
}catch (InterruptedException e){}
}
return (returned);
}catch (Exception e) {
System.out.println("error in auditAccounts "+e);
}
return null;
}
</PRE>
The <CODE>RegistrationServer.findLowCreditAccounts</CODE> method retrieves
user records from the database registration table that have a credit
value less than three. It then returns the list of Registration records
in an <CODE>ArrayList</CODE> by calling the <CODE>SellerBean.updateResults</CODE>
method that it has a reference to.
<PRE>
//RegistrationServer.java
public void findLowCreditAccounts(
final ReturnResults client)
throws Finder Exception {
Runnable bgthread = new Runnable() {
public void run() {
Connection con = null;
ResultSet rs = null;
PreparedStatement ps = null;
ArrayList ar = new ArrayList();
try{
con=getConnection();
ps=con.prepareStatement(
"select theuser,
balance from registration
where balance < ?");
ps.setDouble(1, 3.00);
ps.executeQuery();
rs = ps.getResultSet();
RegistrationImpl reg=null;
while (rs.next()) {
try{
reg= new RegistrationImpl();
}catch (Exception e) {
System.out.println("creating reg"+e);
}
reg.theuser = rs.getString(1);
reg.balance = rs.getDouble(2);
ar.add(reg);
}
rs.close();
RegistrationImpl[] regarray =
(RegistrationImpl [])ar.toArray(
new RegistrationImpl[0]);
client.updateResults(regarray);
}catch (Exception e) {
System.out.println(
"findLowCreditAccounts: "+e);
return;
}
finally {
try{
if(rs != null) {
rs.close();
}
if(ps != null) {
ps.close();
}
if(con != null) {
con.close();
}
}catch (Exception ignore) {}
}
}//run
};
Thread t = new Thread(bgthread);
t.start();
}
</PRE>
The <CODE>SellerBean.updateResults</CODE> method updates
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -