Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
hi i have searched the internet for a long time trying to find some thing that talk about how to start rmi registry in windows 7 using cmd so if any one know how to do that pleas let me to know how to do it or if any one can provide us a good link for that... thx in advance
ok thanx for all how answered my question when i asked the question i was not fully understand the RMI system or how it work but know i have good idea i will summarized this for provide all with an idea for the RMI system and if i have any mistake please correct me
so
Remote Interface:
We need an interface that extends from the Remote class and defined the method that we would like to invoke remotely
note:
Remote is a "marker" interface that identifies interfaces whose methods may be invoked from a non-local virtual machine.
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.Calendar;
public interface CalendarTask extends Remote {
Calendar getDate() throws RemoteException;
}
The Remote Object:
We need class that create a Remote object's so we crate class object implement the Remote Interface to make the object's that created by this class object remote object's and we link this object's to the RMI System by extends from this class UnicastRemoteObjec so When a class extends from UnicastRemoteObject, it must provide a constructor declaring this constructor calls super(), it activates code in UnicastRemoteObject, which performs the RMI linking and remote object initialization.
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.Calendar;
public class CalendarImpl extends UnicastRemoteObject implements CalendarTask {
private int counter = 1;
public CalendarImpl() throws RemoteException {}
public Calendar getDate() throws RemoteException{
System.out.print("Method called on server:");
System.out.println("counter = " + counter++);
return Calendar.getInstance();
}
}
Writing the Server:
3.1 The server's job is to accept requests from a client, perform some service, and then send the results back to the client.
3.2 The server must specify an interface that defines the methods available to clients as a service. we do that above in the first step (Remote Interface)
3.3 The server creates the remote object, registers it under some arbitrary name, then waits for remote requests
3.4 so for register The remote object we use java.rmi.registry.LocateRegistry class allows the RMI registry service (provided as part of the JVM) to be started within the code by calling its createRegistry() method.
3.5 The java.rmi.registry.Registry class provides two methods for binding objects to the registry.
• Naming.bind("ArbitraryName", remoteObj);
throws an Exception if an object is already bound under the "ArbitrayName".
• Naming.rebind ("ArbitraryName", remoteObj);
binds the object under the "ArbitraryName" if it does not exist or overwrites the object that is bound.
3.6 The example on the following acts as a server that creates a CalendarImpl object and makes it available to clients by binding it under a name of "TheCalendar"
import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
public class CalendarServer {
public static void main(String args[]) {
System.out.println("Starting server...");
// Start RMI registry service and bind
// object to the registry
try {
LocateRegistry.createRegistry(1099);
Naming.rebind("TheCalendar",
new CalendarImpl());
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
System.out.println("Server ready");
}
}
Writing the Client:
4.1 An RMI client is a program that accesses the services provided by a remote object
4.2 The java.rmi.registry.LocateRegistry class allows the RMI registry service to be located by a client by its getRegistry() method
4.3 The java.rmi.registry.Registry class provides a lookup() method that takes the "ArbitraryName" the remote object was bound to by the server.
Once the client obtains a reference to a remote object, it invokes methods as if the object were local
import java.rmi.registry.*;
import java.util.Calendar;
public class CalendarClient {
public static void main(String args[]) {
Calendar c = null;
CalendarTask remoteObj;
String host = "localhost";
if(args.length == 1)
host = args[0];
try {
Registry r =
LocateRegistry.getRegistry(host, 1099);
Object o = r.lookup("TheCalendar");
remoteObj = (CalendarTask) o;
c = remoteObj.getDate();
} catch (Exception e) {
e.printStackTrace();
}
System.out.printf("%tc", c);
}
}
The code you have written doesn't start a registry. LocateRegistry.getRegistry() doesn't do that. Check the Javadoc. It assumes the Registry is already running. LocateRegistry.getRegistry() just constructs a Registry stub according to the host and port you provide. It doesn't even do any network operations.
To start a Registry from within your JVM, use LocateRegistry.createRegistry(), as its Javadoc states.
EDIT: There's a lot of misinformation in your edit.
Remote is a "marker" interface that identifies interfaces whose methods may be invoked from a non-local virtual machine.
Only if implemented by an exported remote object whose stub has been transmitted to that VM. The remote interface itself doesn't have any such magical property. All methods defined in a remote interface must be declared to throw RemoteException, although the implementations of these methods generally don't need to be so declared (i.e. unless they perform remote operations themselves: the compiler will tell you).
We need class that create a Remote object's so we crate class object implement the Remote Interface to make the object's that created by this class object
Far too much confusion here. We need a class. The class must implement the remote interface. This is not an 'object' yet: it is a piece of code that must be compiled to a .class file. A class doesn't 'make objects'. An application does that, with the new operator.
we link this object's to the RMI System by extends from this class UnicastRemoteObjec so When a class extends from UnicastRemoteObject, it must provide a constructor declaring this constructor calls super(), it activates code in UnicastRemoteObject, which performs the RMI linking and remote object initialization
There is no 'link' step in RMI. There is an 'export' step. It is performed either by extending UnicastRemoteObject or by calling UnicastRemoteObject.exportObject(). If you don't extend UnicastRemoteObject you don't need the constructor you described.
The server's job is to accept requests from a client, perform some service, and then send the results back to the client.
The server's job is to implement the methods in the remote interface. RMI does all the rest for you.
The server creates the remote object, registers it under some arbitrary name, then waits for remote requests
Or else the server is the remote object and it registers itself.
for register The remote object we use java.rmi.registry.LocateRegistry class allows the RMI registry service (provided as part of the JVM) to be started within the code by calling its createRegistry() method.
Or you can use an external Registry via the rmiregistry command. Or you can use an LDAP server via JNDI.
LocateRegistry.createRegistry(1099);
Naming.rebind("TheCalendar",
new CalendarImpl());
This won't work unless you store the result of createRegistry() into a static variable. And having stored it, you may as well use it to do the bind, instead of using the Naming class. If you don't store it into a static variable it will be garbage-collected and so will the remote object.
The java.rmi.registry.LocateRegistry class allows the RMI registry service to be located by a client by its getRegistry() method
Or you can use the Naming class, see below.
The java.rmi.registry.Registry class provides a lookup() method that takes the "ArbitraryName" the remote object was bound to by the server.
So does the Naming class. It takes an rmi: URL which specifies the host and port and bind-name. You can omit the rmi:// part. If you omit the host it defaults to 'localhost', but this is only useful if the client is running in the same host as the server, which isn't itself very useful. If you omit the port it defaults to 1099.
Related
Can i attach java shutdown hook across jvm .
I mean can I attach shut down from my JVM to weblogic server running in different jvm?
The shutdown hook part is in Runtime.
The across JVM part you'll have to implement yourself, because only you know how your JVMs can discover and identify themselves.
It could be as simple as creating a listening socket at JVM1 startup, and sending port number of JVM2 to it. JVM1 would send shutdown notification to JVM2 (to that port) in its shutdown hook.
The short anser is: You can, but not out of the box and there are some pitfalls so please read the section pitfalls at the end.
A shutdown hook must be a thread object Runtime.addShutdownHook(Thread) that the jvm can access. Thus it must be instantiated within that jvm.
The only way I see to do it is to implement a Runnable that is also Serializable and some kind of remote service (e.g. RMI) which you can pass the SerializableRunnable. This service must then create a Thread pass the SerializableRunnable to that Thread's constructor and add it as a shutdown hook to the Runtime.
But there is also another problem in this case. The SerializableRunnable has no references to objects within the remote service's jvm and you have to find a way how that SerializableRunnable can obtain them or to get them injected. So you have the choice between a ServiceLocator or an
dependency injection mechanism. I will use the service locator pattern for the following examples.
I would suggest to define an interface like this:
public interface RemoteRunnable extends Runnable, Serializable {
/**
* Called after de-serialization from a remote invocation to give the
* RemoteRunnable a chance to obtain service references of the jvm it has
* been de-serialized in.
*/
public void initialize(ServiceLocator sl);
}
The remote service method could then look like this
public class RemoteShutdownHookService {
public void addShutdownhook(RemoteRunnable rr){
// Since an instance of a RemoteShutdownHookService is an object of the remote
// jvm, it can provide a mechanism that gives access to objects in that jvm.
// Either through a service locator
ServiceLocator sl = ...;
rr.initialize(sl);
// or a dependency injection.
// In case of a dependecy injection the initialize method of RemoteRunnable
// can be omitted.
// A short spring example:
//
// AutowireCapableBeanFactory beanFactory = .....;
// beanFactory.autowireBean(rr);
Runtime.getRuntime().addShutdownHook(new Thread(rr));
}
}
and your RemoteRunnable might look lioke this
public class SomeRemoteRunnable implements RemoteRunnable {
private static final long serialVersionUID = 1L;
private SomeServiceInterface someService;
#Override
public void run() {
// call someService on shutdown
someService.doSomething();
}
#Override
public void initialize(ServiceLocator sl) {
someService = sl.getService(SomeServiceInterface.class);
}
}
Pitfalls
There is only one problem with this approach that is not obvious. The RemoteRunnable implementation class must be available in the remote service's classpath. Thus you can not just create a new RemoteRunnable class and pass an instance of it to the remote service. You always have to add it to the remote JVMs classpath.
So this approach only makes sense if the RemoteRunnable implements an algorithm that can be configured by the state of the RemoteRunnable.
If you want to dynamically add arbitrary shutdown hook code to the remote JVM without the need to modify the remote JVMs classpath you must use a dynamic language and pass that script to the remote service, e.g. groovy.
I have a server and a client communicating through RMI. Their goal is to share a simple object, work on it together, and then simulate a server disconnect.
The sever has its name bound to the rmiregistry. The client uses the rmiregistry to get a remote reference to the server. Then it uses this reference to call a method that returns a reference to the object they will share. Further communication is to be done through this shared object.
The shared object is a UnicastRemoteObject, the server owns its implementation and has a method the returns a reference to the client.
The client knows the interface of the shared object, gets a remote reference from the server and then acts on it. Please note the server should return a remote reference, not a serialized copy.
This is the shared object interface
public interface CInterface extends Remote {
boolean testMethod() throws RemoteException;
}
And this is its implementation
public class CImpl implements CInterface {
#Override
public boolean testMethod() throws RemoteException {
return false;
}
}
This is the method of the server that should return a remote reference when the client calls it
public CInterface exportRefToC() throws RemoteException {
return new CImpl();
}
If I call it from the client, it gives me this exception
java.rmi.UnmarshalException: error unmarshalling return; nested
exception is: java.io.WriteAbortedException: writing aborted;
java.io.NotSerializableException: sandbox.CImpl
I can get the method to work and return a remote reference if I write it this way
public CInterface exportRefToC() throws RemoteException {
refToC = new CImpl();
return (CInterface) UnicastRemoteObject.exportObject(refToC, 1099);
}
What I don't get is why I need to go through the registry again, though not explicitly binding a the name, just to return a remote reference. The client got a reference to the server before, using the rmiregistry, so the bootstrap is done. Now, why can't the server just return a reference to the client without knowing the port of the rmiregistry (1099)?
Bonus question, if the server wants to make the object it shared with the client unavailable (to simulate a disconnection), is there a better way than doing this
UnicastRemoteObject.unexportObject(refToC, true);
EDIT: if I extend the UnicastRemoteObject in the implementation of the shared object, the first version of the method works, however, the unexport does not work and return this exception
java.rmi.ServerException: RemoteException occurred in server thread;
nested exception is: java.rmi.NoSuchObjectException: object not
exported
EDIT2: checked again, it does work, just need to save the reference before returning it
public CInterface exportRefToC() throws RemoteException {
refToC = new CImpl();
return refToC;
}
The shared object is a UnicastRemoteObject
No it isn't. Look again:
public class CImpl implements CInterface
Add extends UnicastRemoteObject to that, and provide an appropriate constructor, and your problem will disappear.
You don't need to call exportObject(), and you don't need a second binding to the Registry.
Your last question embodies a mistake. It should be unexportObject(), and that is the correct way of making the object unavailable.
I have a certain problem: I'm using RMI to communicate between server and client.
public class RemoteMap
extends java.rmi.server.UnicastRemoteObject
implements RemoteMapInterface {
private TreeMap<String, GeneralSprite> sprites;
...
This is my remote object. But I want the client to be able to change this object's content. And after the change the server can execute some operation based on this.
Example at the client side:
map = (RemoteMapInterface) (registry.lookup("map"));
map.getSprites.get("object1").setDx(-1);
I'm using serialiable on the GeneralSprite, but I guess it passed by value. So when I did some changes at the GeneralSprite, it wasn't transported to the server . Do I have to make GeneralSprite to an Remote object too? Or is it even possibly?
Thanks in advance, and sorry for my bad english, I hope you can understand.
Everything which does not implement the Remote interface, whether directly or indirectly, will get serialized for the remote method invocation. So it’s a “call-by-copy” behavior. You can implement a new Map which implements Remote, but you can also add a method like setDx(String spriteName, int value) to your RemoteMapInterface and implement it as sprites.get(spriteName) .setDx(value); on the server side.
In books, I read that when we compile implementation class with rmic, it creates two objects: stub and skeleton. But when I compile server side implementation class it only creates a stub object file. The code is:
import java.rmi.*;
import java.rmi.server.*;
public class ServerImp extends UnicastRemoteObject implements testRmi
{
ServerImp() throws RemoteException
{
}
public void getText(String gt) throws RemoteException
{
System.out.println(gt);
}
}
Can somebody tell me when the skeleton file is created?
Since rmic 1.2 onwards, Java doesn't generate skeleton class any more. New JRMP protocol supported for RMI has got rid of the use of skeleton files.
A skeleton for a remote object is a JRMP protocol server-side entity
that has a method that dispatches calls to the actual remote object
implementation.
Skeletons were replaced by general server-side dispatch code in JDK 1.2 (released 1998). Statically generated stubs were replaced by dynamic proxies in JDK 5 (released 2004). There is no longer need to use rmic to generate stubs for running RMI over JRMP. (Note however that rmic is still necessary for using IIOP.)
I'm astounded by the number of questions on stackoverflow asking about rmic, stubs, and skeletons. People must be looking at very old books and very out-of-date web tutorials. It would be helpful if links were posted to some of these so that the authors can be contacted to update or remove the obsolete information.
Maybe the old stub support should be deprecated. That might help avoid the confusion.
Edit: Oh, I guess maybe I should answer the question too. :-)
Edit2: removed erroneous statement about UnicastRemoteObject constructor.
Statically generated skeletons are no longer necessary. In your code above, your remote object extends UnicastRemoteObject. When your object is constructed, the UnicastRemoteObject constructor is called. This hooks up the object to the RMI internal infrastructure that handles socket listening and remote method dispatch. In other words, it "exports" the object.
I am trying to send an object in java over a physical network (not over localhost) but it seems I have something wrong.
The interface to the object (client and server have this):
public interface distributable extends Serializable {
public void test();
}
The Object I am trying to send (only server has this):
class ObjectToSend implements distributable {
public ObjectToSend() {
}
public void test() {
system.out.println("worked!");
}
}
Server:
private ObjectToSend obj = new ObjectToSend();
obj_out_stream.writeObject(obj);
obj_out_stream.flush();
Client:
private distributable ReceivedObj = null;
try {
ReceivedObj = (distributable) obj_in_steam,readObject();
} catch (ClassNotFoundException e) {
System.err.println("Error<w_console>: Couldn't recieve application code!");
}
ReceivedObj.test();
Everything was working when the ObjectToSend class implemented Serializable and I wasn't using an interface because all my classes were in one directory so the client 'knew' about the object. Now I want it to work across a physical network so the client only has the interface to the object. It seems that client can not receive the object as the exception is thrown every time.
As the other answers suggest, the Client also has to know the class of the object you want to send.
Usually, one creates three packages/projects for such a classic client-server example:
Common: Code that is used by client and server; the class definition of the objects you want to send from the server to the client belongs here
Client: All code only the client needs to know about
Server: All code only the server needs to know about
To be able to serialize and deserialize objects with objectinput/outputstream the classes must implement Serializable.
Also the deserializer must be able to find the classes on the classpath that you are trying to deserialize since this is embedded in the Serialized form.
If you want the client to have only the interface -- at compile time -- then you'll need to download the actual class from the server at run-time.
Jini (aka Apache River) makes this easy.
It's supposed to be like this. What can you do with a class whose code you don't have?
Have a look here: stackoverflow.com/questions/8175052/java-polymorphism-my-teacher-claims-you-can-distribute-an-executable-object-thr