We are developing a client-server application with Java RMI and, for testing, we will use a computer both as client and as server. So both the client and the server applications must call rmiregistry on the same machine, but they are two different JVMs obviously. How can we do that? We hoped that it was necessary only to give different ports to LocateRegistry but we get NotBoundException...
What is the correct way?
You can run as many as you like, but why? You don't need to. Have the server start its own Registry via LocateRegistry.createRegistry(), and have the client lookup that one. You seem to think the client needs its own Registry, which isn't correct.
If you got a NotBoundException clearly either the service wasn't bound at all in any registry, or you looked up the wrong one.
RMI Registry is a server which maintains a registry of services.
So your server should connect to the RMI registry and register itself in it, while client should connect to RMI registry and look up your server
So you need to run a single RMI Registry on your machine.
It seems that you're getting the NotBoundException cause you have two of them
Related
I know how to make a socket between a server and client if they are both on my computer. What I don't understand is how to make a socket connection between a client on my computer, and my server running on a different network. I can't just do:
new Socket("Machine name", PortNumber);
right?
You can create a socket with a hostname or ip address. However this does not work in Java applets: They typically are restricted to only connect to the machine the web page has been loaded from. Similar restriction (Java does this with a special SecurityManager) applies to some old fashioned and strict application servers.
But with stand-alone Java programs nothing is stopping you from doing it. If you have problems it might be best to tell us what error message you get.
Java RMI stand-alone applications
Is it possible to create a Server – Client Java application using RMI that can run just by running the server and the client (with servers IP), without any change on any environment variable, or installation of any other program?
As far as I know, to make an RMI compo (Server – Client) to work, you need:
server application
client application
protocol file(s) (implementations) common for both
but the location of the server must be accessible by the client. Is there a way that java can make it accessible without any help?
Is it possible to create a Server – Client Java application using RMI that can run just by running the server and the client (with servers IP), without any change on any environment variable, or installation of any other program?
RMI doesn't have environment variables or separate programs.
As far as I know, to make an RMI compo (Server – Client) to work, you need: server application client application protocol file(s) (implementations) common for both
No you don't. There is no such thing. You just need the relevant .class files in each place. I can't imagine where you are getting this misinformation from.
but the location of the server must be accessible by the client. Is there a way that java can make it accessible without any help?
No. Accessibility is a property of firewalls. If you could change that from the client there wouldn't be any point in having them in the first place.
I'm looking for a secure way to tunnel RMI traffic.
In My application(java Webstart) i must assume that the only port that is open is port 80.
I have the looked att socketfactories for rmi but do i really need a proxy then.
I need to do all my tunneling on the client side.
The only firewall i am trying to get past is on the client side.
I'm not able to open 1099 with port ranges above.
Would be nice to see some implementations.
Thanks!
Port 1099 was reserved for RMI at IANA in about 1995. There is no reason for it not to be open for outbound access in the client-side firewall.
RMI can be made to use fixed port numbers by supplying a port number when constructing (super(port)) or exporting (exportObject(object, port)). Better still, if you create the Registry within the server JVM via LocateRegistry.createRegistry(), all subequently exported remote objects will use that port unless they specify a different port or they use a server socket factory.
BUT ... RMI already includes HTTP tunneling 'out of the box'. No external solution required. You have to deploy the RMI-Servlet provided with the JDK, at the server end.
(a)
although not the newest fashion, exposing remote services with Hessian and Burlap seems to be a simple solution to avoid problem working across firewalls: http://hessian.caucho.com/doc/
see sample code for the server and client side:
http://www.javatpoint.com/spring-remoting-by-hessian-example
(b) or consider using Spring HttpInvokder (see some sample code here: http://www.javatpoint.com/spring-remoting-by-http-invoker-example)
HttpInvokder provides more customization options through the RemoteInvocationFactory, RemoteInvocationExecutor and HttpInvokerRequestExecutor strategies (for example, to add custom context information (such as user credentials) to the remote invocation, or using java’s built-in object serialization etc.), see:
http://docs.spring.io/spring-framework/docs/2.0.x/api/org/springframework/remoting/support/RemoteInvocationFactory.html
I am trying to understand a JMX service URL.
service:jmx:rmi://192.168.30.10:1234/jndi/rmi://192.168.30.10:2344/jmxrmi
It would be great, if someone can help me understand this.
Thanks
I will reuse an answer I wrote up earlier for this question: Cannot connect to Tomcat's MBeanServer via jconsole in Java6
It's not complete, but might help:
Suppose you have the JMX Server (alias 'JMX Agent' alias 'the JVM you want to connect to') running on 'TARGET MACHINE' with the RMI registry port at 'RMI REGISTRY PORT' and the JMX RMI server port at 'JMX RMI SERVER PORT'.
Note:
The RMI registry tells JMX clients where to find the JMX RMI server port; information can be obtained under key jmxrmi.
The RMI registry port is generally known as it is set through system properties at JVM startup.
The JMX RMI server port is generally not known as the JVM chooses it at random (if no other precautions are taken).
The following URI will lead to successful connection (tested)
service:jmx:rmi://<TARGET_MACHINE>:<JMX_RMI_SERVER_PORT>/jndi/rmi://<TARGET_MACHINE>:<RMI_REGISTRY_PORT>/jmxrmi
This looks nasty. Let's cut it apart.
This URI is an RFC2609 "Service Location Protocol URL" (well, it's really an URI, right?)
It is composed of:
service - a constant
jmx:rmi - the service type composed of: abstract type jmx and URL scheme rmi
the rest - the sap (service access protocol specification)
sap is decomposed into:
//<TARGET_MACHINE>:<JMX_RMI_SERVER_PORT> - ipsite
/jndi/rmi://<TARGET_MACHINE>:<RMI_REGISTRY_PORT>/jmxrmi - URL part
A well-informed JMX client connects to the "ipsite" to do JMX-over-RMI exchanges; but what of the JMX client that doesn't KNOW that port? Patience...
URL part is decomposed into:
/jndi/ - This seems to tell the JMX client that it can get lookup information at the location that follows
rmi://<TARGET_MACHINE>:<RMI_REGISTRY_PORT>/jmxrmi - Yep, we get information about the JMX RMI Server at the RMI registry, under the lookup key jmxrmi
This is somewhat cart-before-horse, as one has to contact the RMI registry given by the latter part of the SLP URL first.
After scratching head, intuitively, let's try:
service:jmx:rmi://<TARGET_MACHINE>/jndi/rmi://<TARGET_MACHINE>:<RMI_REGISTRY_PORT>/jmxrmi
Yes, that works! The JMX RMI server port is nicely obtained from the registry. On second thoughts, the target machine should also be obtained from the registry, thus:
service:jmx:rmi:///jndi/rmi://<TARGET_MACHINE>:<RMI_REGISTRY_PORT>/jmxrmi
Even better, that works, too!
References:
http://download.oracle.com/javase/6/docs/api/javax/management/remote/rmi/package-summary.html
http://download.oracle.com/javase/6/docs/api/javax/management/remote/JMXServiceURL.html
http://mx4j.sourceforge.net/docs/ch03s04.html
http://download.oracle.com/javase/6/docs/technotes/guides/management/agent.html#gdevg
http://www.rfc-editor.org/rfc/rfc2609.txt
To explain:
service:jmx:rmi://192.168.30.10:1234/jndi/rmi://192.168.30.10:2344/jmxrmi
service:jmx:rmi://192.168.30.10:1234 - says that there is a JMX Agent on the machine with IP address 192.168.30.10. The JMX agent is using (TCP) port 1234 to provide JMX service(s) over RMI (basically acts as an RMI server).
/jndi/rmi://192.168.30.10:2344/jmxrmi - says that the RMI stub to interact with the JMX Agent over RMI can be found in the RMI registry which is running on the machine with IP address 192.168.30.10 and is using (TCP) port 2344. To get the RMI stub you need to lookup the "jmxrmi" binding.
Previous answers suggest that the 2nd part of the URL is to obtain the server port of the JMX RMI server. That is not correct. The JMX RMI server port is (TCP) 1234 and is part of the URL. What you get from the RMI registry is the RMI stub (javax.management.remote.rmi.RMIServerImpl_Stub) which you can use to talk to JMX Agent (MBean Server) over RMI.
Hope this helps.
According to javax.management.remote.rmi
this url is assembled like this
service:jmx:rmi://ignoredhost/jndi/rmi://myhost/myname
How can I use RMI with a applet client behind a firewall?
How can I use RMI with a firewalled server and firewalled applet client? (If possible)
I know that the RMI server uses port 1099 (by default, but this is configurable); however after this the communication requires a new socket on a different random port. I also know that you can set the proxy on the client for RMI over HTTP tunneling which in theory should solve my issue. But I can't make it work (I tried setting the environmental properties on my XP client, but Internet Explorer keeps ignoring them).
See http://java.sun.com/javase/6/docs/technotes/guides/rmi/faq.html#firewall
If the servers code is in your hand you could also restrict RMI to use a predifined port by providing a custom RMISocketFactory as described here: http://insidecoffe.blogspot.com/2012/02/firewall-friently-rmi-port-fixing.html
(Note specially the hint that it may cause problems if you use JMX in parallel)
Have not looked into it to deeply my self yet, but while looking around for a project I am currently doing I came accross LipeRMI.
You might want to have a look at it as it geared towards internet usage and mentions "shadow the clients in such way they can be behind a local network, router or firewall;"
Edit:
Remembered another implementation I came across a while back called RMI Doves 1.0: Solution for Java RMI firewall problem you might want to have a look at that one as well.
in your Server put the code like this:
RmiInterface stub = (RmiInterface) UnicastRemoteObject.exportObject(rmi, 35400);
LocateRegistry.createRegistry(1099);
Naming.rebind("//192.168.102.128:1099/rmi", stub);