aspose file tools*
The moose likes Developer Certification (SCJD/OCMJD) and the fly likes RMI implementation Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Soft Skills this week in the Jobs Discussion forum!
JavaRanch » Java Forums » Certification » Developer Certification (SCJD/OCMJD)
Bookmark "RMI implementation" Watch "RMI implementation" New topic
Author

RMI implementation

Jashua Ni
Greenhorn

Joined: Jul 31, 2004
Posts: 17
Since DBAccess interface doesn't throws RmoteException, which is required by RMI interface, so do I have to create a wrap up interface for that?

Then the local mode and remote mode will need to be handled differently?

That's what I implemented right now, is there a better way to do it?

Thanks,

Jashua Ni
Anton Golovin
Ranch Hand

Joined: Jul 02, 2004
Posts: 476
I have DBClient interface for the business logic, and DB interface for data access. My remote class implements DBRemote interface, which extends DBClient and Remote.

DBClient is also implemented by the ClientController.

The way I try to do it, additionally, is to hide actual classes behind interfaces; in other words, my DataAdapter class gets a copy of Data class as a DB.


Anton Golovin (anton.golovin@gmail.com) SCJP, SCJD, SCBCD, SCWCD, OCEJWSD, SCEA/OCMJEA [JEE certs from Sun/Oracle]
Jashua Ni
Greenhorn

Joined: Jul 31, 2004
Posts: 17
Anton:

Thank you for your reply. So in another words, your DB Adaper implements DBClient interface, which has an instance of Data class, and delagate the call back to data class.

On the client side, only deal with DBclient interface, could be remote or local. So the DBAccess interface has been wrappped up to another interface, DBClient. No DBAcess interface directly exposed to the client.
Am I right?

OK, to me this is the only better approach I can think of. Thanks.

Jashua Ni
Anton Golovin
Ranch Hand

Joined: Jul 02, 2004
Posts: 476
In my program, the DBClient interface contains business-logic methods, such as book, create, delete. The DB interface (the data-access interface) is the one supplied by the assignment. DBClient "wraps" the functionality, like you wrote.

For the distinction between the remote and local runs of the client, I will create instances of DBRemote and DBClient, respectfully, thus achieving good, clean interfaces for the program. I still have to see if it will work for the remote, DBRemote, as I do not know if the stab will accept being called a DBRemote (the stab is of DataImpl variety, implementing the DBRemote.)

That's my design. I do believe that is exactly what will give the high marks because it is clear and maintainable.
Jashua Ni
Greenhorn

Joined: Jul 31, 2004
Posts: 17
Thanks,

The problem comes in, that it is a client server approach. Let's say everything you do will be on the client side. the backend database already being defined by Sun. That can be considered as database interface. You can make connection through local (no remoteException) or through server(has RemoteException). If you push you DBClient interface to the backend, as you said. then it defeats the client server design. It is not a thin client, every business rules should be encapsulated on the client side?

Am I right? Or you have different points?
K Madan
Greenhorn

Joined: Apr 08, 2004
Posts: 10
I am also having the same problem of deciding how to proceed with the remote interface for DBAccess. I wrote one controller which depending upon the mode (local/nw) can choose the correct implementation. My confusion is should I be creating a remote Interface which extends Remote and DBAccess ? As when you cannot do that because we want to add RemoteException to each of the method to throw.
Otherwise I will be having two different interfaces with same set of methods but remote will throw remote exceptions.
Is this a right approach ?
please reply
thanks
mike acre
Ranch Hand

Joined: Sep 23, 2003
Posts: 197
I have just finished a slight redesign in this area

I now have:

DBClient interface (aka 'The Beast') specifies all methods that will be remotely or locally called eg:

DBClient.book(xxxx) throws RemoteException, BusinessException, DataTransportException;

DataAdapter implements DBClient : concrete business methods

DBRemote extends DBClient, Remote : empty

DBRemoteImpl is a Proxy for DataAdapter

The Above are server side

Client Side I have DBClientProxy which is a simple wrapper for DBClient which it retrieves from a DBClientFactory, it does not care whether remote or local. ie could be DBRemoteImpl or DataAdapter
This class catches RemoteExceptions and chains them to a DataTransferException.

This is the best way to do it


SCJP 1.4, SCJD
Jashua Ni
Greenhorn

Joined: Jul 31, 2004
Posts: 17
Mike:

Like I said before, you are pushing the business function back to server. I don't see that for client server, server should not know about business rules at all.

Server usually always be database server. database server should know about business logic, some logic can be embeded inside the store procedure. But for this case, it it the right way to do that?

I thought it will be better to filter out from client side some how for the data return back by the database.

Does anybody have advice for this implementation?

Jashua Ni
mike acre
Ranch Hand

Joined: Sep 23, 2003
Posts: 197
Originally posted by Jashua Ni:
Mike:

Like I said before, you are pushing the business function back to server. I don't see that for client server, server should not know about business rules at all.



Whether the business bit is server or client side is irrelevent in this context. I just offered some way to interface the remote & local objects and how to deal with RemoteExceptions.

thin client server : thick client server - both are valid.
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
Some people have the business logic on the server. Let�s call the interface to the business logic B. Other people have only the database logic on the server. Let�s call the interface to the database D.

X is either B or D.

The problem is, the client must support local and remote mode. What interface does the client use?

Example 1. (RemoteX extends X)


Example 2. (a common superinterface)

Example 3. (wrap RemoteX, hide RemoteException)

[ August 18, 2004: Message edited by: Marlene Miller ]
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
Hi Jashua,

I showed three approaches to the problem of how a client might deal with both local and remote modes, (1) RemoteX extends X, (2) X and RemoteX extend a common interface, (3) RemoteX is wrapped and the RemoteException is handled/hidden in the wrapper.

As I see it, the first method wouldn�t work for you, because the methods of your X (DBAccess) do not throw RemoteException. The second method wouldn�t work for you, because your X does not extend a common interface. But something like the third method might work.

I am not suggesting these are the only ways to solve the problem. These happen to be the three simplest ways I could think of. I don�t claim to know the best way or even a good way to do this. Your idea of wrapping X is another way I hadn't thought of.

Marlene
[ August 17, 2004: Message edited by: Marlene Miller ]
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
Example 4. or 2b. (W wraps X)

[ August 18, 2004: Message edited by: Marlene Miller ]
mike acre
Ranch Hand

Joined: Sep 23, 2003
Posts: 197
I'll have to hand it to Marlene there. I was moving towards her solution #3. I'd done the client side bit in a similar way, just not removed the redundancy of my 'Beast' interface.

Perhaps in my next refactoring I'd have got there, but that probably is the best solution.
mike acre
Ranch Hand

Joined: Sep 23, 2003
Posts: 197
Originally posted by Marlene Miller:
Example 4. (wrapping X)



Is that the Rational Rose ASCII art plugin you've got there Marlene?
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
>>Is that the Rational Rose ASCII art plugin you've got there Marlene?

ho ho hee hee. What a pain in the neck, drawing ASCII. I am so happy someone took the time try to understand my ideas. Thank you.

(BTW I coded and tested all 4 examples in remote mode. So at least in this very simple context, the client can invoke a method on the server that delegates to the same object that would be used in local mode.)

>> Perhaps in my next refactoring I'd have got there, but that probably is the best solution.

Well, I am not so sure it's the best (although it is my favorite). I was a little shy about posting my ideas in front of all the experts here. I'd be interested in seeing some other ways, if you come across some in your refactoring.
[ August 17, 2004: Message edited by: Marlene Miller ]
Jashua Ni
Greenhorn

Joined: Jul 31, 2004
Posts: 17
Marlene:

Thanks and excellent thoughts about the RMI implemetation. definitely your thrid approach sounds great to me. And thanks for nice drawing too, which makes thing easier to understand and atrractive.

And I could consider the wrapper on the client side as the return connection from connectioManager, which either instantiates directly or get from RMI lookup.

Also in jdk 1.4, I don't have to do the exception chaining by myself. So hidding the RemoteException should be OK.

thanks a lot.

Jashua Ni
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
Hi Jashua,

>> Thanks and excellent thoughts about the RMI implemetation. definitely your thrid approach sounds great to me. And thanks for nice drawing too, which makes thing easier to understand and attractive.

Thank you Jashua. I am happy to know my ideas and drawings made sense to you. I am glad those primitive drawings were helpful. Thanks for letting me know.

>> And I could consider the wrapper on the client side as the return connection from connectionManager, which either instantiates directly or get from RMI lookup.

I understand what your ConnectionManager is doing. But I am not sure what you mean by the wrapper. In #3, the wrapper class wraps the object from RMI lookup, but it does not wrap the object that is instantiated directly. Not a problem. I am probably just misunderstanding words. We might have different definitions of wrapper. I am sure you have figured out what you need to do and how to adjust the ideas to fit your design.
[ August 17, 2004: Message edited by: Marlene Miller ]
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
The new, improved RationalTulip ASCII art plugin.
Example 3 revisited.

Client side:

Server side:

I think I stay with Visio.
[ August 18, 2004: Message edited by: Marlene Miller ]
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
And one more thing. For completeness, here is the JavaWorld article which discusses a pattern that I used for the server side.
http://www.javaworld.com/javaworld/jw-05-1999/jw-05-networked.html

I found this link while searching the SCJD archives thanks to Max.
mike acre
Ranch Hand

Joined: Sep 23, 2003
Posts: 197

[/qb]<hr></blockquote>


What exactly are you proposing to do with the caught RemoteException?
Presumably the user needs to know, and XException may not be meaningful as a wrapper for it. No Exception may even be thrown by that X interface method.

As I see it RemoteXWrapper has no responsibility to do view realated stuff like notify user, but maybe this is the only way to do it.
[ August 18, 2004: Message edited by: mike acre ]
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
What exactly are you proposing to do with the caught RemoteException?

This is a good question. I�m not sure I have a good answer. I like your reasoning better than mine. But here is what I was thinking.

I don�t know what I would do with RemoteException. I haven�t figured out what to do with the exceptions. At the moment, I want to see where they might occur.

In this example, I didn�t want the user of the service m() that is supported by this collaboration of classes to see the RemoteException. I didn�t want the user to know whether the mode was local or remote.

I was motivated by the thought that we sometimes make system calls and we don�t see what�s going on behind the scenes. For example, I work on a Tandem (HP nonstop, not Tandy) computer. A file can be partitioned and distributed across multiple nodes. When I write(), I think I would get a file error, not a network error, although I am not sure.

Presumably the user needs to know,

Yes, a network exception is bad news.

and XException may not be meaningful as a wrapper for it.

Yes, that could be the case. Or possibly the user of the service m() only wants to know that it didn�t work.

XException represents one or _more_ exceptions (not a superclass of all such exceptions) that might occur in a business or database class. It�s just a way to contrast application and network exceptions.

No Exception may even be thrown by that X interface method.

That�s true. Then there would be no way at all of relaying the occurrence of a RemoteException. Good point.

As I see it RemoteXWrapper has no responsibility to do view related stuff like notify user,

Yes, that makes sense. A wrapper is just delegating. Maybe we should give it a different name. :-)

but maybe this is the only way to do it.

The examples are simpler if I allow the RemoteException to go all the way to the user of m(). This is the simplest way I could think of if I want to hide the RemoteException.

What do you think?
[ August 18, 2004: Message edited by: Marlene Miller ]
mike acre
Ranch Hand

Joined: Sep 23, 2003
Posts: 197
Originally posted by Marlene Miller:

The examples are simpler if I allow the RemoteException to go all the way to the user of m(). This is the simplest way I could think of if I want to hide the RemoteException.

What do you think?

[ August 18, 2004: Message edited by: Marlene Miller ]



You can't do that, your interface X does not specify RemoteExceptions which it shouldn't for this design.

I am back to my original design which is your #1

My main interface declares all the exceptions my back end could possibly throw, RemoteExceptions and higherlevel versions (DataTransferException) and BusinessExceptions (I'm with the thin client brigade )

Then client side I wrap the Remote version in a wrapper that wraps the RemoteExceptions in DataTransferExceptions, then I allow my Controller to deal with DTEx & BusinessEx.

Now I really am going to stick with this... I think

The problem with your #3, is that you have 2 interfaces to maintain that are more or less identical, if you add a method, you have to add it to both, just that one has a RemoteException extra. Surely that is less than ideal? But then none are really ideal are they? Why because of the completely necessary restriction that an inheriting method cannot throw exceptions its super does not declare. This restriciton feels odd at first because we are used to adding behaviour with inheritence. And hence the prolifereation of composition style wrappers/adapters in these designs.
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
Thank you Mike.
Jashua Ni
Greenhorn

Joined: Jul 31, 2004
Posts: 17
Hi, All:

I think I need to change my design after I read the article Marlene recommended. And acturally some of the rules from EJB guide lines that make call using Coarse grained object instead, if it networked call, like EJB methods. Push the atomic business function and make the design as Marlene specified 4 type is more appropriate way to do that.

Thanks a lot, Mike and Marlene.

Jashua Ni
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
Hi Jashua,

I want to be sure you understand that all 4 of my examples contain (my way of understanding) the Adapter pattern that is described in the JavaWorld article. It might be hard to see in the primitive drawings.

The remote adapter is RemoteXImpl. It has a reference X x; to the local class XImpl (the adaptee). The remote method RemoteXImpl.m() invokes the local method XImpl.m(): x.m(obj)

The 4th example is a little more exotic. The remote adapter RemoteXImpl has a reference W w to WImpl that wraps the local class.

If DBaccess is your local interface, then it seems to me examples 1 and 2 wouldn't work for you, but something like either examples 3 or 4 would.

But what is more important than my examples is, perhaps you got some ideas on how to play with the interfaces in various ways to get what you want.

And it's also important to know that I am no expert. So I am glad you are also reading the EJB documents.
[ August 20, 2004: Message edited by: Marlene Miller ]
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
Jashua, in this long thread, don't loose sight of the very important point that Mike talked about. Whenever a new method is added to the local interface, it must also be added to all the other interfaces and classes that have the same method and delegate. That's a very compelling practical reason to try to find as few interfaces that will solve the problem.
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
I am adding this link to Noel's post, because he has explained the problem very well.

http://www.coderanch.com/t/186050/java-developer-SCJD/certification/RemoteException
mike acre
Ranch Hand

Joined: Sep 23, 2003
Posts: 197
Hi Marlene, Jashua ...

Here is my latest and simplest design please criticise it heavily



The client gets either XImpl for local mode
or RemoteStubWrapper for Network mode
X has no knowledge of RMI but defines highlevel exceptions like DataTransferException and DatabaseException
So RemoteStubWrapper can strip off the RemoteExceptions and wrap them in a DTEx.

The big difference with this design is that there are no interfaces that declare RemoteExceptions only concrete RemoteImpl does that.

It comes down to the fact - What do you want the interface for?
If the answer is 'To give the client a choice of different database objects that can do the job' then I think this is a good design.

If you have an interface for RemoteImpl (other than Remote) then what does it buy you? So you can swap in another Remote object implementation? All it does is wrap an XImpl, that already has an interface, if you want RemoteImpl to do something else, you just pass in a different implementation of X.

QED, my work is done here....... maybe.
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
No remote _interface_. Now that's a heresy. You and Philippe would get along quite well.

My "teacher" for RMI is the O'Reilly book Java RMI by William Grosso. I like it because it teaches principles as well as mechanisms. Before comment on your new idea, I'll try to understand what Grosso would say.
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
Hi Mike. You�ve raised a good question. Why have a remote interface?

Here are two mechanical RMI reasons we must create an interface that implements Remote.

1. Naming.lookup() returns an object that extends RemoteStub and implements the remote interface RemoteX and Remote.

RemoteStub stub = Naming.lookup(urlString);
Object obj2 = stub.m(obj1); // does not compile

The client wants to invoke methods of RemoteXImpl. But those methods are not members of the RemoteStub.

We must cast the object reference to the interface. Then we can access the methods of the object declared in the interface but not in the RemoteStub class.

RemoteX x = (RemoteX)stub;
Object obj2 = x.m(obj1);



2. Here is something I just learned. If we do not use a remote interface, that is, if the remote class implements Remote, the stub does not contain the methods of the remote class.

>rmic -v1.2 -keep RemoteBImpl



Besides those mechanical reasons, I thought of some other potential reasons why we might want to have a remote interface.

3. The interface Remote determines which methods of the remote object may be called by clients. A remote object may have many public methods, but only those declared in a remote interface can be invoked remotely.

4. In Java Networks by Elliot Rusty Harold, there is a picture of the RMI Layer Model.

So maybe the client layer should not be aware of �stubs�, only the interface.

5. I am reading a book called C++ Gotchas by Dewhurst. Gotcha #10 is about the role of idioms. The RMI remote interface might be an idiom. Grosso has a whole chapter called Designing the Remote Interface. The exam might be testing whether we know the idioms.
[ August 21, 2004: Message edited by: Marlene Miller ]
mike acre
Ranch Hand

Joined: Sep 23, 2003
Posts: 197
Originally posted by Marlene Miller:
Hi Mike. You�ve raised a good question. Why have a remote interface?

Here are two mechanical RMI reasons we must create an interface that implements Remote...


Brain Fart and Fiddlesticks!

Back to I think the unavoidable one or two interfaces problem

one interface that incoveniently must declare RemoteExceptions.

or

two almost identical interfaces to maintain.

I don't think there is much to choose between them.
Marcus Beale
Ranch Hand

Joined: Apr 13, 2004
Posts: 33
My design has a business logic server that uses the Data class. This way, my database can extend the DBAccess interface unaltered (aka without Remote Exceptions), but my business logic server can implement an interface of my choosing.



The client gets a reference to ContractorAccess from a Factory. This reference could be either a ContractorSearch (local mode) or a ContractorDeamon (remote mode). The client always has to deal with RemoteExceptions even in local mode. Anotherwords the same client code works for both modes.

, Marcus

PS. I hope this ASCII art comes out alright. Wish we had a preview button.
[ August 21, 2004: Message edited by: Marcus Beale ]
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
Hi Marcus. Thank you for presenting your solution. Your ASCII art turned out very nice and is easy to read.

Does the interface ContractorAccess implement Remote?

Now, if you wouldn�t mind, I am going to transform your solution into one of my generic examples. Instead of X, I'll use B for Business logic interface.

I am going to make one change, so that the local interface does not implement Remote.

Why did I split B into B and RemoteB? In Java Network Programming (O�Reilly), Elliot Rusty Harold says �Your subinterface of Remote determines which methods of the remote object may be called by the client. A remote object may have many public methods, but only those declared in a remote interface can be invoked remotely.� As I see it, the local class B does not have the same purpose as RemoteB, the subinterface of Remote.

Remote B extends Remote. Otherwise, B and RemoteB are the same. So I am going to make another change. RemoteB extends B. That way RemoteB does not duplicate the method declarations of B.

Marlene
[ August 21, 2004: Message edited by: Marlene Miller ]
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
Mike, yes, it seems that way to me too.
Marcus Beale
Ranch Hand

Joined: Apr 13, 2004
Posts: 33
Marlene,

Does the interface ContractorAccess implement Remote?

Yes it does.

Interesting post.

I believe that the logic of your decision to split the B Interface, means you should have B inherit from RemoteB (not the other way around). This is because you are basically saying that certain public methods should not be accessible remotely. RemoteB may have fewer methods than B, therefore B should implement RemoteB. Otherwise there is no reason to split the interfaces.

Now if you take the above argument to be true, I believe the design now has a problem. You now have to address which interface should be returned by the Server Factory used by the client code. There are two interfaces that could be returned by the factory method B or RemoteB. Which one should be used? I believe that you will have to use the RemoteB interface in remote mode and the B interface in local mode. This defeats the purpose of the factory.

I understand the reason you want to split the B Interface, but I think it shouldn't apply in the context of a Business Server. Business Servers usually (at least mine does) have pretty highlevel methods. I don't believe you will have any B interface methods that you would not want to be accessed remotely. Notice I didn't say public methods; a implimentation of the B interface can have a bunch of public methods that shouldn't be accessed through the B interface and thus not remotely.

, Marcus
[ August 22, 2004: Message edited by: Marcus Beale ]
mike acre
Ranch Hand

Joined: Sep 23, 2003
Posts: 197
Originally posted by Marcus Beale:

I believe that the logic of your decision to split the B Interface, means you should have B inherit from RemoteB



Does not the basic rule of inheritence mean that B is everything RemoteB is.

So B should really describe a Remote object with some extras.
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
Hi Marcus. Thank you for considering my comments and your thoughtful response. What you have said makes sense to me.

So I thought about my ideas in light of what you have said, and I found an unacknowledged assumption.

If you wouldn�t mind, I am going to rearrange your drawing. I�ve drawn the same interface twice to show something. It�s not proper UML, but it doesn�t invalidate the relationships.

Server side:

Assumption 1. �Your subinterface of Remote determines which methods of the remote object may be called by the client.�

Assumption 2. An interface that implements Remote is called a remote interface. A class that implements a remote interface is a remote object.

I made up #2. I�ve never read this. I derived it from #1.

These assumptions tell me that CS is a remote object. Or it could be. Although CS does not extend UnicastRemoteObject, it could be exported. But I think in the context of the SCJD assignments, probably it is not meant to be. The thing that the remote object CD points to is probably not intended to be a remote object.

Marlene
[ August 21, 2004: Message edited by: Marlene Miller ]
Marcus Beale
Ranch Hand

Joined: Apr 13, 2004
Posts: 33
Marlene,

I agree with your logic. I never considered that CS is a remote object. It's pretty easy to export a remote object that doesn't extend URO:



The stub still has to be put in the RMI registery (or have it accessible from another exported remote object), before anyone can access it remotely.

I don't however, think the design violates the Sun spec, since a remote stub for CS is never created/exported, thus no networking is performed.

The program must be able to work in a non-networked mode. In this mode, the database and GUI must run in the same VM and must perform no networking, must not use loopback networking, and must not involve the serialization of any objects when communicating between the GUI and database elements.


REFERENCES
RMI reference: Getting Started RMI
[ August 22, 2004: Message edited by: Marcus Beale ]
No�l Verdurmen
Ranch Hand

Joined: Jul 28, 2004
Posts: 33
This is a very interesting discussion. But, with every posed solution, there does remain a problem for me:

1) the DB-interface provided by sun cannot be exposed to the client, since it would have to throw a RemoteException, or
2) the client does not get a remote object of type DB, or
3) the coding is not very clear and hard to maintain

That's why I think I am going to redesign. A violation of problem 1 seems the best violation. I am going to let the server contain some business logic and create a DBClient interface that throws RemoteExceptions. That will be implemented by a class supporting RMI and by one that does not. It is quite similar to what Anton proposed at the beginning of this thread.

Like this, I think I can defend my design the best.


No�l
Marlene Miller
Ranch Hand

Joined: Mar 05, 2003
Posts: 1391
Hi Marcus, thank you for your comments.

>> I don't however, think the design violates the Sun spec, since a remote stub for CS is never created/exported, thus no networking is performed.

Yes. It is a very clean design without the baggage of extra supporting interfaces and wrappers.

>> It's pretty easy to export a remote object that doesn't extend URO:

In the book I am reading Java RMI (O�Reilly) by William Grosso, there is a section on extending UnicastRemoteObject or exporting. If we export, we must also implement equals and hash code, to handle the case of stubs.

(As one more thought experiment, we could toss out CD and export CS. Then CS would actually be a remote object.)

----
Thank you for presenting and discussing your solution.

Marlene
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: RMI implementation