As I understand it, rmi creates new instances of the server object in a separate thread for each client connection. It seems, at least according to the RHE book, that there is some strong level of expectation that multi-threading above and beyond that be implemented. " I do not understand how any additional server side multi-threading could be implemented in a way that provides additional or even usable functionality to the project. I do not synchronize anywhere in the rmi server. The only time the letters "synchronize" appear in my project is in reference to a collection used exclusively by the lock and unlock functions in the data class extension. If any rmi server side methods are synchronized it opens the potential for a server side deadlock while the lock function blocks. I have run tests to verify that rmi is using multiple threads and operating correctly as follows: Using one instance of rmi registered server: 1. locked a record from a dummy client instance 2. requested a record lock for the same record from another client instance 3. Waited 120 seconds while the second instance is still blocking: 3. locked a different record and then unlocked it from a third client instance 4. unlocked the the first record from a fourth client instance
5. The second instance then obtained the lock and returned. 6. Then I unlocked the newly obtained lock with the second instance
I sincerely do not understand the discrepancies between how my program implements multi-threading, and what most of the literature seems to suggest is required for the assignment. Do you think most of the manual multi-threading implementation is referring to a sockets deployment, or is there something obvious that I am completely missing? Thanks [This message has been edited by Ben Nichols (edited May 18, 2000).] [This message has been edited by Ben Nichols (edited May 18, 2000).] [This message has been edited by Ben Nichols (edited May 18, 2000).]
3.2 Thread Usage in Remote Method Invocations A method dispatched by the RMI runtime to a remote object implementation may or may not execute in a separate thread. The RMI runtime makes no guarantees with respect to mapping remote object invocations to threads. Since remote method invocation on the same remote object may execute concurrently, a remote object implementation needs to make sure its implementation is thread-safe. Vladan
...may or may not execute in a separate thread. My application can handle it if it does execute in a separate thread. The RMI runtime makes no guarantees with respect to mapping remote object invocations to threads. Does this mean that I must add additional code to guarantee the multithreaded execution of methods in my server class.
[This message has been edited by Ben Nichols (edited May 19, 2000).]
I think that a server should be "thread-safe" and not multithreaded( in this case it might be or not, depending on RMI). I guess what "thread-safe" means is "if there are multiple threads" and they can call the same method at the same time then You must decide which portions of code(method) would You make Synchronized or simply declare that method Synchronized. That is what I think is going on here. Or someone have different idea ???
I guess I completely agree. According to the Instructions: <quote>"...must create a data server that will accept multiple concurrent network connections. ...because multiple concurrent network connections may exist you must make your server class threadsafe. ...you may implement your threaded server in more than one class."</quote> My confusion has lain specifically with the RHE book, which seems to strongly insist that there is much more multithreading going on than just the rmi... <quote>"If multithreading is added as an afterthought [to rmi], the application could well be at risk."(RHE, 488)</quote> following the rmi section: <quote>"Up to this point...we've discussed threading...suggesting a few possible ways to deploy them, but without creating a robust, working model of any one type."(RHE, 490)</quote> <quote>"One complex aspect of writing a multithreaded application server is choosing a way to define how client requests will run.(RHE, 490)</quote> Additionally I leafed through one other SCJD book and it said something like, "when you implement your multithreaded server it will either need to extend Thread or implement Runnable." These statements have collectively convinced me of requirements beyond the ones issued with the programming assignment, which is really what I am trying to nail down in this topic. Benjamin
Probably covering known ground, but: RMI multithreads, thereby fulfilling that requirements. It just doesn't make any guarantees [EM]how[/EM] it multithreads, or when it chooses to spawn a new thread. Plain vanilla RMI is what I used in my assignment and, seeing the score I got, there can't have been a lot wrong with it. By the way, if you use RMI, it is worth exploring the java.rmi.server.Unreferenced interface.
Peter den Haan | peterdenhaan.com | quantum computing specialist, Objectivity Ltd
Peter, I looked into the java.rmi.server.Unreferenced interface. I have been thinking of an application for it in the assignment, and I don't quite get it. I don't want to be a pain, but could you elaborate. Thanks, Benjamin
I wanted to add one more quote that I missed earlier from RHE, just so people are aware. "Once the choice of network technique has been made, however, we can give a more thought to how threading plays a role in the whole scheme. This is admittedly a lot trickier in to contend with in an RMI scheme, and multithreading questions should be pursued early in an RMI scheme rather than later."(RHE, 499) [This message has been edited by Ben Nichols (edited May 24, 2000).]
Hi all, In socket based networking code we can take care of keeping track of the number of active clients or spawning a new server thread for each client request, pretty easily. The socket sever does an accept() for each client connection request and waits in a loop. So we can incrment the activeclients count after accept() and decrement it when the server thread completes. I do read that RMI automatically takes care of multithreading the server part for you, but your code should be thread safe. I would like to know how can we keep track of or get information about the number of currently active client requests and when they finish. Any information on this are highly appreciated. Thanks.
java.rmi.server.Unreferenced if implemented would allow your RMI Server to be notified when there are no more active clients... but tell me... why would you want to do this? I am curious as to how that would affect the assignment. Thanks, Ben
Nope. As per RMI FAQ, if your server implements java.rmi.Unreferenced, it will be notified only when the server stub has no references in the registry (i.e. there are no clients left) and not when each client ends. I have not tried that out though. Why I wanted to know this ? - to be able to shut down the server gracefully without affecting any active clients. I would like to do something like this: 1. Server admin selects 'Stop Server' from the menu 2. Server checks if there are any client requests currently active. 3. If no clients are active, server exits immediately else it sets 'do not accept any more connections' flag to true. From this point onwards any client requests will be rejected by the server. 4. Server waits in a loop, occassionally checking for completion of active client requests. When all active client requests complete server exits. Do not exactly know whether this approach is appropriate or even possible! -Mahesh H.
Try this... (First of all I know that this is not a pretty way of doing this... but, it should work...) 1.create a local RMI client instance. dummyClient = new RMIClientWrapper(); When the server attempts to close: 1. Unbind the RMI ServerName( this prevents new clients) 2. close your dummy client instance(set to null, whatever) When unreferenced get called 1. exit (and other cleanup) The rmi garbage collector uses default 10 minute leases so if you have Leased active stubs out to downed network connections, it should clean them up by then. On the flipside, I don't know whether RMI clients need the ServerName bound to renew their active leases if they are still working. I would test this, but it would seem odd. I believe the Server Name only has to be bound for a client to receive the initial copy of the stub.
Another method that could be used to shut clients down, but not during a request is: boolean isUnexported = [UnicastRemoteObject].unexportObject(ref, false); This only unexports the object if there are no pending or in-progress calls.
Thanks Ben. I will try out the methods suggested by you. Meanwhile I am having a hard time testing dynamic stub downloading in RMI. Here is the long mail on the problems I am facing and my efforts to solve it.. Have you or anyone else tested Dynamic stub download in RMI using File URL as Codebase ? I am trying to do that and not able to make it work and can not figure out why it won't work. I tried all the methods mentioned in different tutorials and books but to no avail. I have following directory structure (all on same PC): c:\rmi - no .class files in this directory c:\rmi\server - all server related .class files (including _stub) c:\rmi\client - all client related .class files my CLASSPATH is - .;.. (current and parent directory only) Now I do the following to execute the RMI application: 1. start rmiregistry with 'start rmiregistry' command from c:\rmi directory (note that no .class files are in this directory and hence rmiregistry should not find _stub class file in its CLASSPATH). 2. start RMI server from c:\rmi\server directory with codebase set to c:\rmi\server. This step works fine. I know that because, if I do not specify the correct directory on the File URL, I get a 'Unmarshalling error' during Naming.rebind() call. This means that rmiregistry is indeed anotating _stub properly with server's codebase, right ? Is there a way to verify (by a System.out.println() may be) _stub's codebase as annotated by rmiregistry, after Naming.rebind() call ? But I do have a question here. I am on Win95 and any of the following 3 forms of file URLs seem to work fine: file:///c:/rmi/server/ file:/c:/rmi/server/ file:///c:\rmi\server/ which one is correct as per you ? 3. start RMI client from c:\rmi\client directory. This is where I get 'Unmarshalling error'. (Client does work fine if I copy _stub to c:\rmi\client directory. Of course then I have not used dynamic downloading of _stub). As per all tutorials I read, dynamic downloading should happen if: -rmiregistry does not find download classes in its classpath -server has correct codebase -client does not find _stub in it's local classpath I think I am satisfying all the three criteria. What am I missing ? I also have other questions: 1. If I have a HTTP server running and I use an HTTP URL for codebase, _stub is downloaded to client using HTTP protocol, right? How does the download take place when I use a File URL? FTP ? If FTP, who provides the FTP service ? 2. Do I need to set codebase for RMI client also, to make it work ? 3. I had to set java.policy on client also (besides server) to come to 'unamrshalling error' on client side. Is that always necessary ? 4. My PC has Computer name = 'D071479' on Control Pannel/Network/Identification panel. I tried setting java.rmi.server.hostname=D071479 also. But it did not work either 5. Do you think I should go for HTTP URL instead of File URL for server codebase ? Which method did you use for RMI testing ? All your time and help are greatly appreciated. Thanks, Mahesh H
pie. tiny ad:
Building a Better World in your Backyard by Paul Wheaton and Shawn Klassen-Koop