1. Remote interface 2. Remote implementation (this is the actual remote object) 3. Server class 4. Client class
1. Remote interface: Should extend from java.rmi.remote. Declare the methods that the client can invoke here. All methods in this interface should throw RemoteException 2. Remote implementation: Should implement the remote interface and extend UnicastRemoteObject. Implement remote methods here. This is the remote object, the stub of which will be passed to the client. 3. Server Class: Registers the Remote object in a naming registry (use rmiregistry) 4. Client Class: Queries the registry for the remote object, gets the stub and calls the methods.
STEPS: 1. Write the four classes. You can find the classes in a lot of online tutorials. 2. Compile them. 3. Generate the stub and skeleton by using rmic compiler on the Remote implementation. 4. Run the server and bind the remote object to the registry 5. Run the client and invoke the methods.
NOTE: you don't need two systems to learn/run RMI programs though in realtime business, the client and server will run in 2 different machines. You can use a single machine.
Simple RMI uses JRMP. If you want to use IIOP, extend PortableRemoteObject instead of UnicastRemoteObject, and use Context to query the registry. You also have to narrow the stub before use.
As far as I am concerned, there are three big benefits in using EJB technology: distribution, transactions and messaging. If ever I hear of making remote calls, I reach for my EJB Server. This way, I can focus on solving business problems without getting too involved in the plumbing beneath the surface, like the details of RMI, marshalling, unmarshalling, streams, Socket connections, etc.