Reputation: 4615
I am trying to re-code some basic design patterns. There were just code snippets available for me and no complete running code examples. One is called proxy pattern.
I just want to invoce methods via remote. This is my simple code:
WebService.java
public class WebService extends UnicastRemoteObject implements IRemote {
private static final long serialVersionUID = 1L;
public static void main(String[] args) {
try {
IRemote service = new WebService();
Naming.rebind("RemoteCalculator", service);
} catch (Exception e) {
e.printStackTrace();
}
}
/** No arg default constructor */
public WebService() throws RemoteException { }
/** Methods of remote interface */
@Override
public double getRoot(double v) throws RemoteException {
return Math.sqrt(v);
}
}
... where IRemote is a simple interface extending the remote interface and defining the signature of a single example method (getRoot(double)).
And now the class that connects to the remote:
TestProxy.java
public class TestProxy implements Remote{
/**
* @param args
*/
public static void main(String[] args) {
new TestProxy().go(args[0]);
}
public TestProxy() {}
public void go(String ip) {
try {
System.out.println("Trying to lookup for service ...");
IRemote service = (IRemote) Naming.lookup("//" + ip + "/RemoteCalculator");
System.out.println("done");
double d = service.getRoot(5.0);
System.out.println(d);
} catch (Exception e) {
e.printStackTrace();
}
}
}
I am running rmiregistry.exe and made my WebService_Stub.class via rmic.exe, as shown in some documentations. Local connects with 127.0.0.1 as (ip-)argument work fine. But there isn't a way to connect via internet even if the port (1099) is open and checked by telnet.
When I start with commandline:
java net.mypackage.remote.TestProxy 78.2.2.2
It gives all the time the result:
Trying to lookup for service ... done java.rmi.ConnectException: Connection refused to host: 192.168.1.51; nested exce ption is: java.net.ConnectException: Connection timed out at sun.rmi.transport.tcp.TCPEndpoint.newSocket(Unknown Source) at sun.rmi.transport.tcp.TCPChannel.createConnection(Unknown Source) at sun.rmi.transport.tcp.TCPChannel.newConnection(Unknown Source) at sun.rmi.server.UnicastRef.invoke(Unknown Source) at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(Unkn own Source) at java.rmi.server.RemoteObjectInvocationHandler.invoke(Unknown Source) at $Proxy1.getRoot(Unknown Source) at net.gerdsmeier.remote.TestProxy.go(TestProxy.java:39) at net.gerdsmeier.remote.TestProxy.main(TestProxy.java:22) Caused by: java.net.ConnectException: Connection timed out at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source) at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source) at java.net.AbstractPlainSocketImpl.connect(Unknown Source) at java.net.SocksSocketImpl.connect(Unknown Source) at java.net.Socket.connect(Unknown Source) at java.net.Socket.connect(Unknown Source) at java.net.Socket.(Unknown Source) at java.net.Socket.(Unknown Source) at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(Unknown S ource) at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(Unknown S ource) ... 9 more
where 192.168.1.51 is my local ip-adress (i.e. port forwarding works fine).
Upvotes: 0
Views: 722
Reputation: 4615
Well, I've solved a part of the problem. It's behind the logic of server stubs:
On server-side, we have to add the information about the global hostname by adding the line
System.setProperty("java.rmi.server.hostname",Util.getGlobalAddress().getHostAddress());
... where the Util class may look like:
public class Util{
/**
* Finds this computer's global IP address
*
* @return The global IP address, or null if a problem occurred
*/
public static Inet4Address getGlobalAddress()
{
try
{
URLConnection uc = new URL( "http://vallentinsource.com/globalip.php" ).openConnection();
BufferedReader br = new BufferedReader( new InputStreamReader( uc.getInputStream() ) );
return ( Inet4Address ) InetAddress.getByName( br.readLine() );
}
catch( MalformedURLException e )
{
e.printStackTrace();
}
catch( IOException e )
{
e.printStackTrace();
}
return null;
}
}
Now it works in one direction, i.e. a client-side call like
service.printName("Pete");
works fine on server-side. On the other hand ...
d = service.getRoot(5.0);
System.out.println(d);
... on the client doesn't yet work. It doesn't raise an error but we don't get a result. However. You can fix it by adding the client ip adress/hostname as well:
System.setProperty("java.rmi.client.hostname", "ip.of.client.pc");
But a server can't know all client adresses beforehand. Anyways: That's a workaround and may help in some cases.
Upvotes: -1
Reputation: 1207
Ok, I'm guessing that your WebService is behind NAT and you have set up port forwarding on 1099 to get through to the RMI registry. This is not enough. The remote object will hang around listening on a port different from 1099. If you don't set up port forwarding to this port you will never connect, hence the exception at the double d = service.getRoot(5.0)
line.
The problem is which port to forward? If you don't specify the port, RMI will choose one high port randomishly. But you can specify the port by using a version of the UnicastRemoteObject constructor. So, you can pick a port number, do IRemote service = new WebService([portnumber]);
and set port forwarding on that port as well.
See if it cuts it!
Upvotes: 0