I want to understand how the dynamic proxy stub implementation is actually done behind the scene. According to what I read, by the time a remote object is exported if no pre-generated stub class is found, the RMI runtime would generate a dynamic proxy to act as the stub. That stub is then bound to the RMI Registry and later accessible by some RMI client.
The question is: since the stub is actually a dynamically generated proxy, its class definition would not be available on the client side, then how come the client is still able to retrieve the stub from the RMI Registry? Is there some kind of dynamic class-loading happening behind the scene or does RMI use another technique to work-around this?
Java.lang.reflect.Proxy is serializable and it has special support in ObjectOutputStream and ObjectInputStream. Basically just the interfaces implemented and the invocation handler are serialized, and a new dynamic proxy is constructed from that during deserialization.
RMI does use dynamic classloading - the classpath is sent alongwith the call as a 'classpath annotation' from which the client loads the class. You can look at the RMI implementation for more info - it's available as part of the JDK source. Specifically, the classes ObjectOutputStream and RMIClassloader.
Update: RMI does not start an HTTP server - in fact, you would need your custom solution for this. One of them as you mention can be an HTTP server that you run, make the classes available through the server, and pass the codebase with the HTTP server's address/port in your stubs, so that your clients can download them.
Related
As per my knowledge, in the EJB 2.x, the client uses the home interface to ask for a reference to the component interface and calls Enterprise java bean’s business method using that reference.
But the concept of stub and skeleton are not clear to me.
Is the reference to the component interface acts as a stub? Then which one act as a skeleton?
Please clarify.
Stub and skeleton are actually RMI concepts, EJB is just reusing them. As such, they are only needed when you are using remote interfaces.
Stub is used by the client to invoke methods on the remote EJB -- it is basically a proxy object that implements the remote interface. It is responsible for serializing the invocation into a byte stream and sending it to the server hosting the EJB.
Skeleton is running on the server side -- it receives the remote calls from the stub over the network, deserializes the invocation and and delegates it to the EJB.
See also: Java RMI : What is the role of the stub-skeleton that are generated by the rmic compiler
Nowadays, stubs and skeletons are typically generated at runtime (or the same function is just handled via reflection), so you do not need to worry about them (see also Do I need RMI stubs to access EJBs from my java client? - this is specific to Glassfish, but the general principles usually apply also to other containers).
Skeletons have been obsolete since 1998. Don't worry about them.
Well stub and skeleton are just there when you are using Remote interfaces.
Stub is an object implementing Remote interface (implemented usually by code generation) and skeleton is implemented inside the container and invokes method on the EJB (inside the container).
When I use JNDI to get an object from a remote server, the object can be serialised to the local JVM, this way I am assuming that we can call methods on this object locally without RMI, so why we need RMI?
JNDI is a look-up and directory service. It provides a standardized way to acquire resources by name within some context. Usually it used for acquiring shared resources from an application-server context, but depending on implementation, it can also provide for looking up items in a standardized way that represent remote resources.
RMI is a remote method invocation technology built-in to the Java platform. It allows for calling remote java object methods over a binary protocol. It uses Java's built-in serialization handling to make the remote invocation and parameter passing over the network seem transparent. RMI requires it's own directory/look-up service that or might not be integrated with a given JNDI implementation. (Usually they are not integrated.)
So, with all that in mind, hopefully you can see why your question isn't very clear. You might look-up a remote RMI service via JNDI. You might be able to save (serialize) that remote RMI reference to disk and then reconstruct it to use it again later (although that is probably not a good idea.) But regardless, JNDI and RMI are two different things.
When I use JNDI to get an object from a remote server, the object can be serialised to the local JVM, this way I am assuming that we can call methods on this object locally without RMI, so why we need RMI?
So you can call methods remotely. An object that has been deserialized into your local JVM executes in your JVM. A remote object executes in a remote JVM even though you called it from your local JVM.
I am assuming that we can call methods on this object locally without
RMI
No,It is important to understand that you need two extra objects when you make a remote method invocation. The Stub which runs on the client side and de Skeleton which runs on the server side. These objects performs the necessary low level operations.
When the client invokes a remote method it never call directly the object, instead it uses the Stub object.
Therefore, what you get from JNDI service is the Stub not the remote object.
I am currently learning Java RMI (Remote Method Invocation), and I followed the tutorial provided by Oracle on it´s website. I have a particular question however:
What is the use of the stub-skeleton generated by rmic? Do I really need it?
The Stub/Skeleton hides the communication details away from the developer. The Stub is the class that implements the remote interface. It serves as a client-side placeholder for the remote object. The stub communicates with the server-side skeleton.
The skeleton is the stub's counterpart on server-side. Both communicate via the network. The skeleton actually knows the real remote objects delegates the stub's request to it and returns the response to the stub.
You require both as they are the essential building blocks for RMI.
I don't know very well how to create a proxy in java rmi. My client A invokes the server B (unicast) successfully. Now i want that the client A invokes a proxy server C wich invokes the server B. How i can create the proxy? I need a code example to adapt at my situation.
If you want to proxy just one remote interface, it's easy: just write another implementation of it that looks up and calls the real implementation via RMI, and binds itself to a Registry that the client can lookup.
If you want to do it for arbitrary remote interfaces, it's highly non-trivial, trust me, if you are going to get the proxy to do anything useful, such as access control, SSL, etc. There are commercial products that do this, and I vend one of them.
Any one dealing with the RMI would certainly have come across this dilemma of how to easily maintain the interfaces to objects providing remote method invocation service to other client applications. Whenever we decide to have a minor change in the method declaration or adding/deleting methods declared in the interface, we have to manually replicate the change in all the clients that would be using that interface for accessing RMI service from a remote server.
Think about having a downloadable (Serializable) agent that has a more stable interface used by the client, and that uses the remote interface to do its job. You can use the codebase feature to ensure its availability to all clients. The agent needs to contain the stub. You can bind the agent to the Registry, or return it from some other remote method.
Or, use JWS to distribute new versions of the clients.
Or, design your remote interfaces more stably so they don't have to change -:)
One of the good workaround I came up with is to
put all the interfaces provided by the RMI server in a separate
project which will pack itself into a jar file when built.
Then just add that jar file as dependency or in the
classpath of the server application which is meant to provide the
RMI service as well as to any of the client applications that
want to use those interfaces for invoking remote methods.
This will ease the task of maintaining RMI interfaces by updating them at just one place. Extra effort of changing method signature in some interface will be limited to changing the application code which calls that method.