Java Remote Method Invocation (Java RMI) enables the programmer to create distributed Java technology-based to Java technology-based applications, in which the methods of remote Java objects can be invoked from other Java virtual machines, possibly on different hosts. RMI uses object serialization to marshal and unmarshal parameters and does not truncate types, supporting true object-oriented polymorphism.
Let’s just say RMI is the “older version” of ejb remote. Because in EJB, enterprise beans are made available for remote clients using RMI.
In this example, im trying to create 2 different project, one is the RMI Server and another one is RMI Client.
First is a simple interface, i will use this interface to create invocation methods and implementations. This interface will be on both Server’s and Client’s side.
package com.edw.rmi; import java.rmi.Remote; import java.rmi.RemoteException; public interface Message extends Remote { void sayHello(String name) throws RemoteException; }
and next is the implementation for my interface, it is exist only on the server’s side. It has to implements my interface and extends to UnicastRemoteObject class.
package com.edw.rmi; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; public class MessageImpl extends UnicastRemoteObject implements Message { public MessageImpl() throws RemoteException { } @Override public void sayHello(String name) throws RemoteException { System.out.println("hello "+name); } }
And next is creating my server side application. Im running on port 1099 for RMI port.
package com.edw.main; import com.edw.rmi.MessageImpl; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; public class Main { private void startServer(){ try { // create on port 1099 Registry registry = LocateRegistry.createRegistry(1099); // create a new service named myMessage registry.rebind("myMessage", new MessageImpl()); } catch (Exception e) { e.printStackTrace(); } System.out.println("system is ready"); } public static void main(String[] args) { Main main = new Main(); main.startServer(); } }
And this is my client’s side application
package com.edw.main; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import com.edw.rmi.Message; public class Main { private void doTest(){ try { // fire to localhost port 1099 Registry myRegistry = LocateRegistry.getRegistry("127.0.0.1", 1099); // search for myMessage service Message impl = (Message) myRegistry.lookup("myMessage"); // call server's method impl.sayHello("edwin"); System.out.println("Message Sent"); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { Main main = new Main(); main.doTest(); } }
This is the screenshot of what happen on my netbeans’ console, for my RMI client’s side
and this is my netbeans’ project
While this is what RMI messages looks like
Have fun with RMI 🙂
Hello,
Thanks a lot for your article, but this code does not work. I guess you should start RMI in console. Right?
I am sorry, your example works. Problem is in my implementation.
Hi Ilya,
yes Thank you for your comment 🙂
(Y)
thanks………. it is helpful
Thank you alpesh, glad it could help
Hi edwin . COmpliments for yours interessant tutorials.
Escuse my bad english.
I you ask how use the codebase into RMI . I know that it is possible download all class for client from codebase .
But you can make me a example?????
tank you .
mauro
Hi Mauro,
usually the server side provide interface class to communicate with the client’s side.
Hy Edwin!
I try to connect to a mysql database, and it’s throwing an exception like this: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
what can I do?
Hi Robert,
There are lots of reasons why it happened, one of the reason is because mysql close it’s connection. Try to post more detailed exception.
Thanks. This saved me a lot of trouble.
Hi Eric, glad it can help.
Thanks! This sure makes the difference! The other RMI tutorial only ended up with a connection error.
Still I am stuck with a small thing. I want to return a String on the remote server in stead of only printing something to the console, but it does not seem to work like that. Do you know how I can return a String?
Currently I have:
String hello = conn.sayHello();
Hi Sietse,
create a method to return String on your RMI Interface
perhaps something like,
public interface Message extends Remote {
String sayHello(String name) throws RemoteException;
}
Excelente ayuda, me sirvio mucho, apenas inicio con rmi.
Now i try in english.
Thanks, it’s helpful,, i’m new in the workd of rmi
Hi Lupe
thanks, glad it could help 🙂
Hello, Edwin.
Thank you for your helpful RMI tutorial.
Greetings from Cincinnati (600 km SE of Chicago). A long way from Indonesia!
Hi Tony, greetings from Indonesia.
Thank you for your comment. 🙂
hello edwin,good article.very helpfull tutorial.greeting from malang indonesia.
😀
Hi Joko, glad it can help 🙂
Hello,
RMI Works on First Run then Connection Refused.
Error Log
Connection refused to host: 10.114.154.208;nested exception is: java.net.ConnectException: Connection refused: connectjava.lang.Throwable:
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
at sun.rmi.transport.Transport$1.run(Unknown Source)
Hi Tarun,
perhaps your RMI server is shutdown after receiving the first message. Try check whether the server’s application is still alive or not 🙂
hi i have problem error log is below
java.lang.UnsupportedOperationException: helloedwin
at com.luk.rmi.MessageImpl.sayHello(MessageImpl.java:19)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:322)
at sun.rmi.transport.Transport$1.run(Transport.java:177)
at sun.rmi.transport.Transport$1.run(Transport.java:174)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:173)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:553)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:808)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:667)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:273)
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:251)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:160)
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:194)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:148)
at $Proxy0.sayHello(Unknown Source)
at com.luk.main.Main.doTest(Main.java:14)
at com.luk.main.Main.main(Main.java:23)
ok nvm implementation error ;]
big thx for the tutorial 🙂
Hi Luk, glad it can help 🙂
Hej and thanks for a very useful tutorial on java RMI.
I tried your program and in runs fine. I was just wondering that the Client program terminates when it’s run. But the Server does terminate after execution. How come?
Best regards
Javid
I mean to say that the Server program does NOT terminate after execution. Can you explain why?
Hi Javid, it is because the server side runs as a daemon thread.
It keeps on running just like a webserver 🙂
Thanks for your answer.
I have another question. I have seen several other java RMI tutorials in the past, where you had to deal with setting the security manager on the client side and setting policy file. And also you had to start rmiregistry process before anything else.
Was that with old versions of java?
Looking forward to hearing from you
Regards
Hi Javid, sorry i missed your question 🙂 .
Im using java6.0 and i dont need to use security manager because security manager is needed only in the case when RMI downloads code from the remote machine.
If both client and server use the same classes, it’s not needed.
what about the security problems and policy file it wouldn’t be complete to test the app.
Hi REMM,
if you got AccessControlException, SocketPermission
you need to create a policy file,
grant {
// Allow everything, do not use in production
permission java.security.AllPermission;
};
and run the application using -Djava.security.policy parameter.
why I got this error ???
“no security manager: RMI class loader disabled”
caused by: on my client interfaces it said, “java.lang.ClassNotFoundException”
how can I solved this problem ?
Hi Budi,
it’s because the client interface cannot found the class you wanted, thats why it raise “java.lang.ClassNotFoundException”.
hi , please help me i am stuck due to this error at client side , i have also included the policy file at the build folder but still not solving any problem for me …
java.security.AccessControlException: access denied (“java.net.SocketPermission” “127.0.0.1:1099” “connect,resolve”)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:366)
at java.security.AccessController.checkPermission(AccessController.java:560)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
at java.lang.SecurityManager.checkConnect(SecurityManager.java:1051)
at java.net.Socket.connect(Socket.java:574)
at java.net.Socket.connect(Socket.java:528)
at java.net.Socket.(Socket.java:425)
at java.net.Socket.(Socket.java:208)
at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:40)
at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:146)
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:613)
at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:216)
at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202)
at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:340)
at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
at rmichatapplication.RMIChatApplicationClient.main(RMIChatApplicationClient.java:31)
Hi Ahsan,
you need to create a policy file to fix it.
grant {
permission java.security.AllPermission;
};
Hi Edwin,
I am trying to get my head around the use of RMI in Netbeans 7.3. Do I have to deploy the server code to the appliocation server? I assume so, but what is the best way to do that in Netbeans7.3? When deploying Ajax2 WebServices there is a ‘Deploy to Server’ context menu item. Once I have got my code on to the application server do I have to manually start the RMIRegistry, or does it start automatically?
Regards,
Stuart
Hi Stuart,
there are lots of difference between RMI and Webservice. So you cannot compare apple to apple between both of them.
RMI could alive with or without application server, but to have RMI server run from your applicationserver is a little bit tricky.
First you need to create a ServletContextListener, and you can call RMI server from inside contextInitialized method
dont forget to register your ServletContextListener to your web.xml okay 😉
When I use the following:
System.setSecurityManager(new java.rmi.RMISecurityManager());
I get the following exception:
Exception in thread “main” java.security.AccessControlException: access denied (“java.net.SocketPermission” “127.0.0.1:1099” “connect,resolve”)
I am running the ClientMain application with the following VM option:
-Djava.security.policy=”C:/Program Files/Java/jdk1.7.0_17/jre/lib/security/java.policy”
If I comment out the above line then I get the following exception:
java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
java.lang.ClassNotFoundException: com.homeserve.rmi.server.impl.Message (no security manager: RMI class loader disabled)
The java.policy file is default.
Any ideas to resolve this would be much appreciated.
Regards,
Stuart
Hi Stuart, you could remove the securityManager or adding these line of codes to your java.policy (not recommended though)
Como se puede hacer que el servidor mande mensajes al cliente? Es que este solo manda mensajes de cliente a servidor
Hi Ana, RMI is not like a long polling ajax or jswebsocket, where the server can push message to the client. In RMI your client retrieves messages from server. You could fetch your messages periodically from server by using ThreadPool.
Would you help me with this code? I’m trying my Server sends messages to my Client, because only my Client sends the messages to Server. I’m programming with the code “A Simple Java RMI Tutorial”. But, I can’t. Please, help me.
Hi Lola, so you want to send messages from server to client? What you need is like a push ajax or a long polling ajax. A server does not typically push messages to a client, the client retrieves them from the server. The workaround is creating a thread that retrieves messages from server periodically.
Hi Edwin,
Could you provide a tutorial on how to configure the policy file? Please?
Hi Carlo, try something like this,
Never mind, got it to work already. Thank you for the awesome tutorial! 😀
Hi Carlo, glad it can help 🙂
Ok, ok… how can make this method? Please help with the code.
Solution for NoClassFound Exception in RMI Client.
Case:
You have the server implementation in one folder and the client in a different folder in a different package.
Solution:
In the client folder, create a package with the same name of the package holding the server and keep the server stub (interface) under this package. In client side java file, import the package having the server stub.
Cool, thanks Samsad.
can be use this example on command prompt….i tried
but server is not started..so plz let me know, how it will work
Hi Vinod, could you share your error log? Perhaps there is something you’ve missed?
Edwin Thanks a lot. I struggled to run RMI in netbeans and finally you solved my problem…! 😀
Hi edwin I have a small doubt in the code. What does at “127.0.0.1”(host) means. Is there any other way to connect to the server using client…!
Hi Thamizh,
it is the location of your RMI ip server, you can change it into your server’s ip.
Thanks Edwin for the tutorial. Simply helpful for guidance near deadline 🙂
Glad it can help, Jono 🙂
NICE Edwin!!
This is explains RMI a lot easier then the oracle tutorial. 🙂
And u dont have to use any commandline compilation-and set-up.
This deserves a beer (B) !
By the SayHello methode in the interface, u make the client and server communicate.
So by creating a ‘Message impl = (Message) myRegistry.lookup(“myMessage”);’ in Main-server u can send data from the server to the client, correct?
Greetings,
Be!
Hi Be,
actually it’s one way trip, not 2 ways
the client could send data to server but not the other way around, the server side can only reply to client’s request message
because the server doesnt know what is the client’s ip address.
hello edwin , i have a problems with my rmi program . At server side , my remote interface define a function : public long add(long a,long b) . I want server will send result of adding 2 long a and b . I run server , it’s ok ! I run client , it’s ok but nothing print to the screen , i use : System.out.println(cal.add(5, 7)); . Can you help me ?
Hi Long,
it supposed to work, do you have any exceptions happen on your server side?
Thank you Sir…
Glad it could help 🙂
can i know how to send a file using rmi … plz help me find it i try lot of ways but i cant find it thank you
Hi Nethanz,
you can convert the file into byte[] and send it directly.
Thanks a lot man !!
🙂
After looking here and there and after searching so may places At last I found your blog and It’s done without any exception (y)
really helpful. I bookmark your site and its very helpful that you upload your work with photos 🙂
thanks again 🙂
I have the concept and my code is perfectly running but can I know why some people are using
rmic ….(generate stub and skel)
then rmiregistry
then run the code
But I didn’t and its working fine any idea bro
Hi edwin.
I copied your application but splited the server and client into diferent projects. I have no errors executing it. But it prints nothing than “system is ready”. Client’s execution ends qickly without errors or the expected output!
only that ur type of people really helps. Thanks from heart.and i wish u should always happy
Excellent, thanks a lot
muchas graciass Excelente
Hi, your example worked very well, thank you. I have a question, do you know maybe how to handle files instead of strings via RMI ? or maybe do you have another tutorial ? it would be great
thanks again !
Hi,
you could use byte[ ] instead of String as parameter.