Internally a client will look like
prepare for discovery
|
discover a lookup service
|
prepare a template for lookup search
|
lookup a service
|
call the service
|
The following code is simplified from the real case.
It attempts to find a FileClassifier
service, calling the method
getMIMEType()
on this service.
public class TestUnicastFileClassifier {
public static void main(String argv[]) {
new TestUnicastFileClassifier();
}
public TestUnicastFileClassifier() {
LookupLocator lookup = null;
ServiceRegistrar registrar = null;
FileClassifier classifier = null;
// Prepare for discovery
lookup = new LookupLocator("jini://www.all_about_files.com");
// Discover a lookup service
// This uses the synchronous unicast protocol
registrar = lookup.getRegistrar();
// Prepare a template for lookup search
Class[] classes = new Class[] {FileClassifier.class};
ServiceTemplate template = new ServiceTemplate(null, classes, null);
// Lookup a service
classifier = (FileClassifier) registrar.lookup(template);
// Call the service
MIMEType type;
type = classifier.getMIMEType("file1.txt");
System.out.println("Type is " + type.toString());
}
} // TestUnicastFileClassifier
prepare for discovery
|
discover a lookup service
|
create information about a service
|
export a service
|
renew leasing periodically
|
The following code is simplified from the real case.
It exports an implementation of a file classifier service, as a
FileClassifierImpl
object.
public class FileClassifierServer implements DiscoveryListener {
protected LeaseRenewalManager leaseManager = new LeaseRenewalManager();
public static void main(String argv[]) {
new FileClassifierServer();
// keep server running forever to
// - allow time for locator discovery and
// - keep re-registering the lease
Thread.currentThread().sleep(Lease.FOREVER);
}
public FileClassifierServer() {
LookupDiscovery discover = null;
// Prepare for discovery - empty here
// Discover a lookup service
// This uses the asynchronous multicast protocol,
// which calls back into the discovered() method
discover = new LookupDiscovery(LookupDiscovery.ALL_GROUPS);
discover.addDiscoveryListener(this);
}
public void discovered(DiscoveryEvent evt) {
ServiceRegistrar registrar = evt.getRegistrars()[0];
// At this point we have discovered a lookup service
// Create information about a service
ServiceItem item = new ServiceItem(null,
new FileClassifierImpl(),
null);
// Export a service
ServiceRegistration reg = registrar.register(item, Lease.FOREVER);
// Renew leasing
leaseManager.renewUntil(reg.getLease(), Lease.FOREVER, this);
}
} // FileClassifierServer
reggie
LookupLocator
handles unicast discovery
public class LookupLocator {
public LookupLocator(String url);
public LookupLocator(String host, int port);
String getHost();
int getPort();
ServiceRegistrar getRegistrar() throws ...;
}
LookupDiscovery
specifies the url. Its getRegistrar()
method returns a proxy for the lookup service
import net.jini.core.discovery.LookupLocator;
import net.jini.core.lookup.ServiceRegistrar;
public class UnicastRegister {
static public void main(String argv[]) {
new UnicastRegister();
}
public UnicastRegister() {
LookupLocator lookup = null;
ServiceRegistrar registrar = null;
try {
lookup = new LookupLocator("jini://localhost");
} catch(java.net.MalformedURLException e) {
System.err.println("Lookup failed: " + e.toString());
System.exit(1);
}
try {
registrar = lookup.getRegistrar();
} catch (java.io.IOException e) {
System.err.println("Registrar search failed: " + e.toString());
System.exit(1);
} catch (java.lang.ClassNotFoundException e) {
System.err.println("Registrar search failed: " + e.toString());
System.exit(1);
}
System.out.println("Registrar found");
// the code takes separate routes from here for client or service
}
} // UnicastRegister
LookupDiscovery
public class LookupDiscovery {
public LookupDiscovery(String[] groups);
addDiscoveryListener(LookupDiscoveryListener l);
}
interface LookupDiscoveryListener {
public void discovered(DiscoveryEvent e);
public void discarded(DiscoveryEvent e);
}
public class DiscoveryEvent {
Registrar[] getRegistrars();
}
import net.jini.discovery.LookupDiscovery;
import net.jini.discovery.DiscoveryListener;
import net.jini.discovery.DiscoveryEvent;
import net.jini.core.lookup.ServiceRegistrar;
public class MulticastRegister implements DiscoveryListener {
static public void main(String argv[]) {
new MulticastRegister();
// stay around long enough to receive replies
try {
Thread.currentThread().sleep(10000L);
} catch(java.lang.InterruptedException e) {
// do nothing
}
}
public MulticastRegister() {
LookupDiscovery discover = null;
try {
discover = new LookupDiscovery(LookupDiscovery.ALL_GROUPS);
} catch(Exception e) {
System.err.println(e.toString());
e.printStackTrace();
System.exit(1);
}
discover.addDiscoveryListener(this);
}
public void discovered(DiscoveryEvent evt) {
ServiceRegistrar[] registrars = evt.getRegistrars();
for (int n = 0; n < registrars.length; n++) {
ServiceRegistrar registrar = registrars[n];
// the code takes separate routes from here for client or service
System.out.println("found a service locator");
}
}
public void discarded(DiscoveryEvent evt) {
}
} // MulticastRegister
ServiceRegistrar
.
This is a proxy for the lookup service
public interface ServiceRegistrar {
public ServiceRegistration register(ServiceItem i,
long leaseDuration);
public Object lookup(ServiceTemplate tmpl);
public ServiceMatches lookup(ServiceTemplate tmpl, int maxMatches);
LookupLocator getLocator();
}
register()
method is used by a service
lookup()
methods are used by a client.
The first returns a single service, the second a set of services
getLocator()
method can say where the lookup service is
Entry
public interface Entry {}
Address
Comment
Name
ServiceInfo
Entry[] entries = new Entry[] {new Comment("best toaster made"),
new Name("Classy Toaster")};
public class MIMEType implements java.io.Serializable {
protected String contentType;
protected String subType;
public MIMEType(String contentTpe, String subType) {...}
public String toString() {...}
}
(It may need to be serialized, to move it from one machine to another)
public interface FileClassifier {
MIMEType getMIMEType(String fileName)
throws java.rmi.RemoteException;
}
(The method may be executing remotely, so can throw a remote exception)
package client;
import common.FileClassifier;
import common.MIMEType;
import net.jini.core.discovery.LookupLocator;
import net.jini.core.lookup.ServiceRegistrar;
import net.jini.core.lookup.ServiceItem;
import net.jini.core.lookup.ServiceRegistration;
import java.rmi.RMISecurityManager;
import net.jini.core.lookup.ServiceTemplate;
public class TestUnicastFileClassifier {
public static void main(String argv[]) {
new TestUnicastFileClassifier();
}
public TestUnicastFileClassifier() {
LookupLocator lookup = null;
ServiceRegistrar registrar = null;
FileClassifier classifier = null;
try {
lookup = new LookupLocator("jini://www.all_about_files.com");
} catch(java.net.MalformedURLException e) {
System.err.println("Lookup failed: " + e.toString());
System.exit(1);
}
System.setSecurityManager(new RMISecurityManager());
try {
registrar = lookup.getRegistrar();
} catch (java.io.IOException e) {
System.err.println("Registrar search failed: " + e.toString());
System.exit(1);
} catch (java.lang.ClassNotFoundException e) {
System.err.println("Registrar search failed: " + e.toString());
System.exit(1);
}
Class[] classes = new Class[] {FileClassifier.class};
ServiceTemplate template = new ServiceTemplate(null, classes, null);
try {
classifier = (FileClassifier) registrar.lookup(template);
} catch(java.rmi.RemoteException e) {
e.printStackTrace();
System.exit(1);
}
if (classifier == null) {
System.out.println("Classifier null");
System.exit(2);
}
MIMEType type;
try {
type = classifier.getMIMEType("file1.txt");
System.out.println("Type is " + type.toString());
} catch(java.rmi.RemoteException e) {
System.err.println(e.toString());
}
// System.exit(0);
}
} // TestUnicastFileClassifier
package client;
import common.FileClassifier;
import common.MIMEType;
import java.rmi.RMISecurityManager;
import net.jini.discovery.LookupDiscovery;
import net.jini.discovery.DiscoveryListener;
import net.jini.discovery.DiscoveryEvent;
import net.jini.core.lookup.ServiceRegistrar;
import net.jini.core.lookup.ServiceTemplate;
public class TestFileClassifier implements DiscoveryListener {
public static void main(String argv[]) {
new TestFileClassifier();
// stay around long enough to receive replies
try {
Thread.currentThread().sleep(100000L);
} catch(java.lang.InterruptedException e) {
// do nothing
}
}
public TestFileClassifier() {
System.setSecurityManager(new RMISecurityManager());
LookupDiscovery discover = null;
try {
discover = new LookupDiscovery(LookupDiscovery.ALL_GROUPS);
} catch(Exception e) {
System.err.println(e.toString());
System.exit(1);
}
discover.addDiscoveryListener(this);
}
public void discovered(DiscoveryEvent evt) {
ServiceRegistrar[] registrars = evt.getRegistrars();
Class [] classes = new Class[] {FileClassifier.class};
FileClassifier classifier = null;
ServiceTemplate template = new ServiceTemplate(null, classes,
null);
for (int n = 0; n < registrars.length; n++) {
System.out.println("Service found");
ServiceRegistrar registrar = registrars[n];
try {
classifier = (FileClassifier) registrar.lookup(template);
} catch(java.rmi.RemoteException e) {
e.printStackTrace();
System.exit(2);
}
if (classifier == null) {
System.out.println("Classifier null");
continue;
}
MIMEType type;
try {
type = classifier.getMIMEType("file1.txt");
System.out.println("Type is " + type.toString());
} catch(java.rmi.RemoteException e) {
System.err.println(e.toString());
}
// System.exit(0);
}
}
public void discarded(DiscoveryEvent evt) {
// empty
}
} // TestFileClassifier
FileClassifier
FileClassifierImpl
FileClassifierImpl
FileClassifier
FileClassifierImpl
FileClassifierimpl_Stub
is exported to the service locator
FileClassifier
(like before - it
doesn't care what the proxy is)
FileClassifierImpl
and a FileClassifierProxy
FileClassifierProxy
FileClassifier
FileClassifierImpl
and a FileClassifierProxy
FileClassifierProxy
and a FileClassifierImpl_Stub
package option2;
import common.MIMEType;
import common.FileClassifier;
public class FileClassifierImpl implements FileClassifier {
public MIMEType getMIMEType(String fileName) {
if (fileName.endsWith(".gif")) {
return new MIMEType("image", "gif");
} else if (fileName.endsWith(".jpeg")) {
return new MIMEType("image", "jpeg");
} else if (fileName.endsWith(".mpg")) {
return new MIMEType("video", "mpeg");
} else if (fileName.endsWith(".txt")) {
return new MIMEType("text", "plain");
} else if (fileName.endsWith(".html")) {
return new MIMEType("text", "html");
} else
// fill in lots of other types,
// but eventually give up and
return null;
}
public FileClassifierImpl() {
// empty
}
} // FileClassifierImpl
package option2;
import java.rmi.RMISecurityManager;
import net.jini.discovery.LookupDiscovery;
import net.jini.discovery.DiscoveryListener;
import net.jini.discovery.DiscoveryEvent;
import net.jini.core.lookup.ServiceRegistrar;
import net.jini.core.lookup.ServiceItem;
import net.jini.core.lookup.ServiceRegistration;
import net.jini.core.lease.Lease;
import com.sun.jini.lease.LeaseRenewalManager;
import com.sun.jini.lease.LeaseListener;
import com.sun.jini.lease.LeaseRenewalEvent;
public class FileClassifierServer implements DiscoveryListener,
LeaseListener {
protected LeaseRenewalManager leaseManager = new LeaseRenewalManager();
public static void main(String argv[]) {
new FileClassifierServer();
// keep server running forever to
// - allow time for locator discovery and
// - keep re-registering the lease
try {
Thread.currentThread().sleep(Lease.FOREVER);
} catch(java.lang.InterruptedException e) {
// do nothing
}
}
public FileClassifierServer() {
LookupDiscovery discover = null;
try {
discover = new LookupDiscovery(LookupDiscovery.ALL_GROUPS);
} catch(Exception e) {
System.err.println(e.toString());
System.exit(1);
}
discover.addDiscoveryListener(this);
}
public void discovered(DiscoveryEvent evt) {
ServiceRegistrar[] registrars = evt.getRegistrars();
for (int n = 0; n < registrars.length; n++) {
ServiceRegistrar registrar = registrars[n];
ServiceItem item = new ServiceItem(null,
new FileClassifierImpl(),
null);
ServiceRegistration reg = null;
try {
reg = registrar.register(item, Lease.FOREVER);
} catch(java.rmi.RemoteException e) {
System.err.println("Register exception: " + e.toString());
}
System.out.println("service registered");
// set lease renewal in place
leaseManager.renewUntil(reg.getLease(), Lease.FOREVER, this);
}
}
public void discarded(DiscoveryEvent evt) {
}
public void notify(LeaseRenewalEvent evt) {
System.out.println("Lease expired " + evt.toString());
}
} // FileClassifierServer
JoinManager
(which will change
in later versions of Jini)
public class JoinManager {
public JoinManager(java.lang.Object obj,
Entry[] attrSets,
java.lang.String[] groups,
LookupLocator[] locators,
ServiceIDListener callback,
LeaseRenewalManager leaseMgr);
...
}
package joinmgr;
import option2.FileClassifierImpl;
import com.sun.jini.lookup.JoinManager;
import net.jini.core.lookup.ServiceID;
import com.sun.jini.lookup.ServiceIDListener;
import com.sun.jini.lease.LeaseRenewalManager;
import net.jini.discovery.LookupDiscovery;
public class FileClassifierServer implements ServiceIDListener {
public static void main(String argv[]) {
new FileClassifierServer();
// stay around long enough to receive replies
try {
Thread.currentThread().sleep(1000000L);
} catch(java.lang.InterruptedException e) {
// do nothing
}
}
public FileClassifierServer() {
JoinManager joinMgr = null;
try {
joinMgr = new JoinManager(new FileClassifierImpl(),
null,
LookupDiscovery.ALL_GROUPS,
null,
this,
new LeaseRenewalManager());
} catch(Exception e) {
e.printStackTrace();
System.exit(1);
}
}
public void serviceIDNotify(ServiceID serviceID) {
System.out.println("got service ID " + serviceID.toString());
}
} // FileClassifierServer
grant {
permission java.security.AllPermission "", "";
};
grant {
permission net.jini.discovery.DiscoveryPermission "*";
// multicast request address
permission java.net.SocketPermission "224.0.1.85", "connect,accept";
// multicast announcement address
permission java.net.SocketPermission "224.0.1.84", "connect,accept";
// RMI connections
permission java.net.SocketPermission "*.dstc.edu.au:1024-", "connect,accept";
permission java.net.SocketPermission "130.102.176.249:1024-", "connect,accept";
permission java.net.SocketPermission "127.0.0.1:1024-", "connect,accept";
// reading parameters
// like net.jini.discovery.debug!
permission java.util.PropertyPermission "net.jini.discovery.*", "read";
};
grant {
permission net.jini.discovery.DiscoveryPermission "*";
// multicast request address
permission java.net.SocketPermission "224.0.1.85", "connect,accept";
// multicast announcement address
permission java.net.SocketPermission "224.0.1.84", "connect,accept";
// RMI connections
permission java.net.SocketPermission "127.0.0.1:1024-", "connect,accept";
permission java.net.SocketPermission "*.dstc.edu.au:1024-", "connect,accept";
permission java.net.SocketPermission "130.102.176.249:1024-", "connect,accept";
// DANGER
// HTTP connections - this is where external code may come in - careful!!!
permission java.net.SocketPermission "127.0.0.1:80", "connect,accept";
permission java.net.SocketPermission "*.dstc.edu.au:80", "connect,accept";
// reading parameters
// like net.jini.discovery.debug!
permission java.util.PropertyPermission "net.jini.discovery.*", "read";
};
Button
generates an ActionEvent
PropertyChange
events
for Java beans
public interface RemoteEventListener {
public void notify(RemoteEvent evt) throws ...:
}
public class RemoteEvent {
public long getID(); // distinguish event types
public long getSequenceNumber(); // like a timestamp
public MarshalledObject getRegistrationObject(); // handback
addActionListener()
,
addPropertyChangeListener()
, etc. Each object must look
after its own listener list and decide when and how to call it. But...
public class EventRegistration {
public EventRegistration(long eventID, Object source,
Lease lease, long seqNum);
public long getID();
public Object getSource();
public Lease getLease();
public long getSequenceNumber();
}
A list with only one listener on it can be done by
protected RemoteEventListener listener = null;
public EventRegistration addRemoteListener(RemoteEventListener listener)
throws java.util.TooManyListenersException {
if (this.listener == null {
this.listener = listener;
} else {
throw new java.util.TooManyListenersException();
}
return new EventRegistration(0L, this, null, 0L);
}
The source object can send an event to its listener by
protected void fireNotify(long eventID,
long seqNum) {
if (listener == null) {
return;
}
RemoteEvent remoteEvent = new RemoteEvent(this, eventID,
seqNum, null);
listener.notify(remoteEvent);
}
Allow the file classifier to change its list of MIME type mappings, and
notify listeners when it does so
package mutable;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.MarshalledObject;
import net.jini.core.event.RemoteEventListener;
import net.jini.core.event.RemoteEvent;
import net.jini.core.event.EventRegistration;
import java.rmi.RemoteException;
import net.jini.core.event.UnknownEventException ;
import javax.swing.event.EventListenerList;
import common.MIMEType;
import common.MutableFileClassifier;
import java.util.Map;
import java.util.HashMap;
public class FileClassifierImpl extends UnicastRemoteObject
implements RemoteFileClassifier {
/**
* Map of String extensions to MIME types
*/
protected Map map = new HashMap();
/**
* Listeners for change events
*/
protected EventListenerList listenerList = new EventListenerList();
public MIMEType getMIMEType(String fileName)
throws java.rmi.RemoteException {
MIMEType type;
String fileExtension;
int dotIndex = fileName.lastIndexOf('.');
if (dotIndex == -1 || dotIndex + 1 == fileName.length()) {
// can't find suitable suffix
return null;
}
fileExtension= fileName.substring(dotIndex + 1);
type = (MIMEType) map.get(fileExtension);
return type;
}
public void addType(String suffix, MIMEType type)
throws java.rmi.RemoteException {
map.put(suffix, type);
fireNotify(ADD_TYPE);
}
public void removeMIMEType(String suffix, MIMEType type)
throws java.rmi.RemoteException {
if (map.remove(suffix) != null) {
fireNotify(REMOVE_TYPE);
}
}
public EventRegistration addRemoteListener(RemoteEventListener listener)
throws java.rmi.RemoteException {
listenerList.add(RemoteEventListener.class, listener);
return new EventRegistration(0, this, null, 0);
}
// Notify all listeners that have registered interest for
// notification on this event type. The event instance
// is lazily created using the parameters passed into
// the fire method.
protected void fireNotify(long eventID) {
RemoteEvent remoteEvent = null;
// Guaranteed to return a non-null array
Object[] listeners = listenerList.getListenerList();
// Process the listeners last to first, notifying
// those that are interested in this event
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == RemoteEventListener.class) {
RemoteEventListener listener = (RemoteEventListener) listeners[i+1];
if (remoteEvent == null) {
remoteEvent = new RemoteEvent(this, eventID,
0L, null);
}
try {
listener.notify(remoteEvent);
} catch(UnknownEventException e) {
e.printStackTrace();
} catch(RemoteException e) {
e.printStackTrace();
}
}
}
}
public FileClassifierImpl() throws java.rmi.RemoteException {
// load a predefined set of MIME type mappings
map.put("gif", new MIMEType("image", "gif"));
map.put("jpeg", new MIMEType("image", "jpeg"));
map.put("mpg", new MIMEType("video", "mpeg"));
map.put("txt", new MIMEType("text", "plain"));
map.put("html", new MIMEType("text", "html"));
}
} // FileClassifierImpl
CommAPI
package rcx;
public class RCXPort {
public RCXPort(String port);
public void addRCXListener(RCXListener rl);
public boolean open();
public void close();
public boolean isOpen();
public OutputStream getOutputStream();
public InputStream getInputStream();
public synchronized boolean write(byte[] bArray);
public void processRead();
public String getLastError();
public void showTable();
public static byte[] parseString(String str);
}
This is best done as an RMI proxy to the service on the server.
The service has an RCXPort
as attribute, and passes
on messages to it.
package rcx.jini;
import java.rmi.server.UnicastRemoteObject;
import net.jini.core.event.RemoteEvent;
import net.jini.core.event.RemoteEventListener;
import rcx.*;
import java.io.*;
import java.util.*;
public class RCXPortImpl extends UnicastRemoteObject
implements RemoteRCXPort, RCXListener {
protected String error = null;
protected byte[] message = null;
protected RCXPort port = null;
protected RemoteEventListener listener = null;
protected long messageSeqNo, errorSeqNo;
public RCXPortImpl()
throws java.rmi.RemoteException {
Properties parameters;
String portName = null;
File f = new File("parameters.txt");
if (!f.exists()) {
f = new File(System.getProperty("user.dir")
+ System.getProperty("path.separator")
+ "parameters.txt");
}
if (f.exists()) {
try {
FileInputStream fis = new FileInputStream(f);
parameters = new Properties();
parameters.load(fis);
fis.close();
portName = parameters.getProperty("port");
} catch (IOException e) { }
} else {
System.err.println("Can't find parameters.txt with \"port=...\" specified");
System.exit(1);
}
port = new RCXPort(portName);
port.addRCXListener(this);
}
public boolean write(byte[] byteCommands)
throws java.rmi.RemoteException {
return port.write(byteCommands);
}
public byte[] parseString(String command)
throws java.rmi.RemoteException {
return RCXPort.parseString(command);
}
/**
* Received a message from the RCX.
* Send it to the listener
*/
public void receivedMessage(byte[] message) {
this.message = message;
// Send it out to listener
if (listener == null) {
return;
}
RemoteEvent evt = new RemoteEvent(this, MESSAGE_EVENT, messageSeqNo++, null);
try {
listener.notify(evt);
} catch(net.jini.core.event.UnknownEventException e) {
e.printStackTrace();
} catch(java.rmi.RemoteException e) {
e.printStackTrace();
}
}
/**
* Received an error message from the RCX.
* Send it to the listener
*/
public void receivedError(String error) {
// System.err.println(error);
// Send it out to listener
if (listener == null) {
return;
}
this.error = error;
RemoteEvent evt = new RemoteEvent(this, ERROR_EVENT, errorSeqNo, null);
try {
listener.notify(evt);
} catch(net.jini.core.event.UnknownEventException e) {
e.printStackTrace();
} catch(java.rmi.RemoteException e) {
e.printStackTrace();
}
}
/**
* Expected use: the RCX has returned a message,
* and we have informed the listeners. They query
* this method to find the message for the message
* seqence number they were given in the RemoteEvent.
* We could use this as an index into a table of messages.
*/
public byte[] getMessage(long msgSeqNo) {
return message;
}
/**
* Expected use: the RCX has returned an error message,
* and we have informed the listeners. They query
* this method to find the error message for the error message
* seqence number they were given in the RemoteEvent.
* We could use this as an index into a table of messages.
*/
public String getError(long errSeqNo) {
return error;
}
/**
* Add a listener for RCX messages.
* Should allow more than one, or throw
* TooManyListeners if more than one registers
*/
public void addListener(RemoteEventListener listener) {
this.listener = listener;
messageSeqNo = 0;
errorSeqNo = 0;
}
} // RCXPortImpl
module corba {
module HelloApp {
interface Hello {
string sayHello();
};
};
};
package corba.HelloApp;
public interface Hello
extends org.omg.CORBA.Object,
org.omg.CORBA.portable.IDLEntity {
String sayHello();
}
package corba;
import org.omg.CosNaming.*;
import org.omg.CORBA.*;
import corba.HelloApp.*;
public class JavaHelloImpl implements JavaHello {
protected Hello helloRef = null;
protected String[] argv;
public JavaHelloImpl(String[] argv) {
this.argv = argv;
}
public String sayHello() {
// Hello helloRef = null;
if (helloRef == null) {
helloRef = getHelloRef();
}
// now invoke methods on the CORBA proxy
String hello = helloRef.sayHello();
return hello;
}
protected Hello getHelloRef() {
ORB orb = null;
// Act like a CORBA client
try {
orb = ORB.init(argv, null);
// find the CORBA name server
org.omg.CORBA.Object objRef =
orb.resolve_initial_references("NameService");
NamingContext ncRef = NamingContextHelper.narrow(objRef);
// find the CORBA Hello proxy
NameComponent nc = new NameComponent("Hello", "");
NameComponent path[] = {nc};
org.omg.CORBA.Object obj = ncRef.resolve(path);
Hello helloRef = HelloHelper.narrow(obj);
return helloRef;
} catch(Exception e) {
e.printStackTrace();
return null;
}
}
} // JavaHelloImpl