{"id":498,"date":"2021-02-10T18:21:30","date_gmt":"2021-02-10T18:21:30","guid":{"rendered":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/?page_id=498"},"modified":"2021-02-22T17:30:46","modified_gmt":"2021-02-22T17:30:46","slug":"remote-method-invocation-rmi","status":"publish","type":"page","link":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/","title":{"rendered":"Remote Method Invocation (RMI)"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_85 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-6a6d4958c9abe\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-6a6d4958c9abe\"  aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#What_is_RMI\" >What is RMI?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#Remote_Objects\" >Remote Objects<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#Remote_Method_Calls\" >Remote Method Calls<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#How_Does_RMI_Perform_a_Remote_Method_Call\" >How Does RMI Perform a Remote Method Call?<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#Components\" >Components<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#RMI_Class_Naming_Conventions\" >RMI Class Naming Conventions<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#The_RMI_Registry\" >The RMI Registry<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#How_do_we_locate_the_remote_object\" >How do we locate the remote object?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#A_Simple_Example\" >A Simple Example<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#The_Remote_Interface\" >The Remote Interface<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#The_Remote_Implementation\" >The Remote Implementation<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#The_Client_Program\" >The Client Program<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#Running_the_Example\" >Running the Example<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#Listing_Remote_Objects\" >Listing Remote Objects<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#An_Extended_Example\" >An Extended Example<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-16\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#BankAccount\" >BankAccount<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-17\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#BankAccountImpl\" >BankAccountImpl<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-18\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#BankAccountServer\" >BankAccountServer<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-19\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#BankAccountClient\" >BankAccountClient<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-20\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#Running_the_Example-2\" >Running the Example<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-21\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#Caveats\" >Caveats<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-22\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#Passing_Objects_in_RMI\" >Passing Objects in RMI<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-23\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#An_Example\" >An Example<\/a><ul class='ez-toc-list-level-5' ><li class='ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-24\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#ComputeEngineImpl\" >ComputeEngineImpl<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-25\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#Security_Policies\" >Security Policies<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-26\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#ComputePi\" >ComputePi<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-27\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#ComputeEngineClient\" >ComputeEngineClient<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-5'><a class=\"ez-toc-link ez-toc-heading-28\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#Running_the_Example-3\" >Running the Example<\/a><\/li><\/ul><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-29\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#Remote_Callbacks\" >Remote Callbacks<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-30\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#The_Remote_Interfaces\" >The Remote Interfaces<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-31\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#The_TimeServer\" >The TimeServer<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-32\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#The_TimeClient\" >The TimeClient<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-33\" href=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/course-topics\/remote-method-invocation-rmi\/#Running_the_Example-4\" >Running the Example<\/a><\/li><\/ul><\/li><\/ul><\/nav><\/div>\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"What_is_RMI\"><\/span>What is RMI?<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<blockquote class=\"wp-block-quote broad-point is-layout-flow wp-block-quote-is-layout-flow\"><p>It seems that, since I wrote this course back in 2008 or so, things have changed with RMI. <\/p><p>For one thing, it seems to have been removed from the Core Java books. <\/p><p>By many accounts, while RMI is still around, it is considered obsolete; today, people tend to choose to expose a remote server as web services, and access them via HTTP[S].<\/p><\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">RMI stands for&nbsp;<dfn>Remote Method Invocation<\/dfn>, and it&#8217;s a Java technology that supports distributed computing.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s what the <a rel=\"noreferrer noopener\" href=\"https:\/\/www.oracle.com\/java\/technologies\/javase\/remote-method-invocation-home.html\" target=\"_blank\">RMI Home page<\/a> says:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Java Remote Method Invocation (Java RMI) enables the programmer to create distributed Java technology-based to Java technology-based applications, in which the methods of remote Java objects can be invoked from other Java virtual machines, possibly on different hosts.<\/p><\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">The <a rel=\"noreferrer noopener\" href=\"https:\/\/www.oracle.com\/java\/technologies\/javase\/remote-method-invocation-distributed-computing.html\" target=\"_blank\">RMI White Paper<\/a> says:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p><em>Java Remote Method Invocation (RMI) allows you to write distributed objects using Java.<\/em><\/p><\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">The Wikipedia RMI page says, at <a rel=\"noreferrer noopener\" href=\"http:\/\/en.wikipedia.org\/wiki\/Java_remote_method_invocation\" target=\"_blank\">http:\/\/en.wikipedia.org\/wiki\/Java_remote_method_invocation<\/a>&nbsp;:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p><em>The&nbsp;<\/em><strong>Java Remote Method Invocation<\/strong><em>&nbsp;API, or&nbsp;<\/em><strong>Java RMI<\/strong><em>, is a Java application programming interface for performing the object equivalent of remote procedure calls.<\/em><\/p><\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Remote_Objects\"><\/span>Remote Objects<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Distributed systems involve not only clients and servers, but also remote objects.&nbsp; Java provides good support for all of these areas:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>RMI is a higher-level API built on top of the Sockets interface<\/li><li>RMI allows you not only to pass data among objects on different systems, but also to invoke methods on a remote object.<\/li><li>Remote objects can act as a client and\/or a server, depending on the requirements of what is being distributed.<\/li><li>RMI goes beyond the normal concepts of a remote procedure call by providing the ability to pass objects between clients and servers<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">There are also other technologies that support distributed objects, among them:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>CORBA (Common Object Request Broker Architecture) supports calls among distributed objects written in different languages.<\/li><li>SOAP (Simple Object Access Protocol) supports&nbsp;<em>web services<\/em>, which is a relatively hot topic at the time of writing (2008).<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">We won&#8217;t be talking about these other technologies;&nbsp; each of them could be a course unto itself!<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Remote_Method_Calls\"><\/span>Remote Method Calls<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"How_Does_RMI_Perform_a_Remote_Method_Call\"><\/span>How Does RMI Perform a Remote Method Call?<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">There are a number of components and actions involved in performing a remote method call:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>In order for a remote method call to appear as if it is local, there has to be a local object which &#8216;stands in for&#8217; the remote object &#8212; that is, it presents the same interface to the client as the remote object does.&nbsp;&nbsp;<ul><li>The local object is called the&nbsp;<dfn><strong>client stub<\/strong>.<\/dfn><\/li><li>The interface that both the stub and the remote object present is known as the&nbsp;<dfn><strong>remote interface<\/strong><\/dfn><\/li><\/ul><\/li><li>When a call is made to one of the methods in the client stub, the stub is responsible for somehow:<ul><li>Invoking the corresponding method on the remote object<\/li><li>Passing any parameters provided on the local call to the remote object&#8217;s method<\/li><li>Eventually, obtaining any return values from the remote method (output parameters, or the return value from the method) and passing them back to the local caller.<\/li><\/ul><\/li><li>The mechanism used to pass values back and forth between the client stub and the remote object is called&nbsp;<dfn><strong>marshalling<\/strong><\/dfn>:<ul><li>Data to be passed over the connection from the client to the server is first&nbsp;<dfn>marshalled<\/dfn>&nbsp;into a form that may be conveniently transported over the &#8216;wire&#8217;.<\/li><li>On the server side, the data is received, and must be&nbsp;<dfn>unmarshalled<\/dfn>&nbsp;into a form that can be used by, and supplied to, the remote object.<\/li><li>Data to be returned from the remote object to the client stub must similarly be&nbsp;<dfn>marshalled<\/dfn>&nbsp;on the server side, and subsequently&nbsp;<dfn>unmarshalled<\/dfn>&nbsp;on the client side.<\/li><li>Remember that code can cause exceptions to occur;&nbsp; exceptions can be&nbsp;<dfn>[un]marshalled<\/dfn>, too.<\/li><\/ul><\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Components\"><\/span>Components<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">So, here are the components that one must create in order to construct an RMI client\/server application:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>The remote object interface: This describes what methods may be called on the remote object. (Note that this is shared between the client and the server code.)<\/li><li>The remote object implementation: This provides the implementation for the remote object interface. (This only needs to exist on the server.)<\/li><li>The server program that creates remote objects. (Server only)<\/li><li>The client program that invokes the methods on the remote object. (Client-only)<\/li><li>The client stub: A local object that resides on the client and serves as a &#8216;surrogate&#8217; for the remote object. (Client-only)<\/li><li>The server skeleton: An object that resides on the server, and communicates with the client stub and the actual remote object. (Server-only)<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Note that, prior to JDK 1.5 (aka 5.0), you had to use a tool provided with the JDK,&nbsp;<strong>rmic<\/strong>&nbsp;(the RMI stub compiler), to generate the client stub and server skeleton classes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In JDK 1.5 and beyond, the stub class is dynamically generated.&nbsp; In JDK 1.2 and beyond, the skeleton class no longer exists as a separate entity.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"RMI_Class_Naming_Conventions\"><\/span>RMI Class Naming Conventions<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Here are the naming conventions for the above components:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><th>Description<\/th><th>Class\/Interface<\/th><th>Required?<\/th><\/tr><tr><td>Remote Object Interface<\/td><td><em>&lt;applicationName&gt;<\/em><\/td><td>Yes<\/td><\/tr><tr><td>Remote Object Implementation<\/td><td><em>&lt;applicationName&gt;<\/em><strong>Impl<\/strong><\/td><td>Yes<\/td><\/tr><tr><td>Server Program<\/td><td><em>&lt;applicationName&gt;<\/em><strong>Server<\/strong><\/td><td>Yes<\/td><\/tr><tr><td>Client Program<\/td><td><em>&lt;applicationName&gt;<\/em><strong>Client<\/strong><\/td><td>Yes<\/td><\/tr><tr><td>Client Stub<\/td><td><em>&lt;applicationName&gt;<\/em><strong>Impl_Stub<\/strong><\/td><td>Only prior to JDK 1.5<\/td><\/tr><tr><td>Server Skeleton<\/td><td><em>&lt;applicationName&gt;<\/em><strong>Impl_Skel<\/strong><\/td><td>Only prior to JDK 1.2<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"The_RMI_Registry\"><\/span>The RMI Registry<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">However, before we can actually perform a remote method invocation, we have one more thing to accomplish:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"How_do_we_locate_the_remote_object\"><\/span>How do we locate the remote object?<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The RMI library provides a&nbsp;<dfn><strong>bootstrap registry service<\/strong><\/dfn>&nbsp;through which the remote object may register itself, and then subsequently be located.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">There are a number of different ways in which the registry may be accessed. We&#8217;ll see some of them as we go through the examples.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The RMI Registry must be up and running before the server\/remote object can start up and register itself, and before the client can locate the remote object.&nbsp;&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The JDK supplies a utility,&nbsp;<strong>rmiregistry<\/strong>&nbsp;which must be run to start the service &#8212; that is, it must be run before you can perform any remote method invocations.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;Click&nbsp;<a href=\"https:\/\/docs.oracle.com\/javase\/1.5.0\/docs\/tooldocs\/windows\/rmiregistry.html\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>&nbsp;for a synopsis of the&nbsp;<strong>rmiregistry<\/strong>&nbsp;command.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>On Windows, it is recommended that you use the command:<br><strong>start rmiregistry [port]<\/strong><\/li><li>On Unix\/Linux, it is recommended that you use the command:<br><strong>rmiregistry [port] &amp;<\/strong><\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">In both cases, this causes the command to be run in the background, with any potential error messages appearing in the associated console window.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">(Naturally, the above commands assume that the <strong>rmiregistry<\/strong> executable directory location is included in the <strong>PATH<\/strong>.)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The default port number used by the RMI Registry is 1099, but you can override that (for example, if that port is already in use) by specifying the port number explicitly.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p><strong><em>Note:<\/em><\/strong>&nbsp;A peculiar restriction appears to be the case for&nbsp;<strong>rmiregistry<\/strong>:&nbsp;<\/p><p><strong><em>You must start the program in the directory which forms the top of your classes hierarchy. (In NetBeans, that will be your project&#8217;s Build\/classes subdirectory.)<\/em><\/strong><\/p><p><strong><em>You must ensure that you start the program with&nbsp;<u>no class path<\/u>&nbsp;and in a directory with&nbsp;<u>no class files<\/u>.<\/em><\/strong><\/p><\/blockquote>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>If you fail to do this, your server will fail in its startup, with a mysterious error about not being able to find the remote interface.<\/p><p>There is a reason for this strange behavior;&nbsp; see <a href=\"https:\/\/docs.oracle.com\/javase\/1.5.0\/docs\/guide\/rmi\/codebase.html\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>.<\/p><\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"A_Simple_Example\"><\/span>A Simple Example<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s a simple example.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We&#8217;ll implement a trivial &#8220;Hello&#8221; server and client.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"The_Remote_Interface\"><\/span>The Remote Interface<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">We&#8217;ll create a really trivial Hello server, which implements the following remote interface:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage rmi;\n\nimport java.rmi.Remote;\nimport java.rmi.RemoteException;\n\n\/**\n * RMI Remote interface for Hello Server\n * @author Bryan Higgs\n *\/\npublic interface Hello extends Remote\n{\n  String sayHello() throws RemoteException;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Note that:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>The interface must extend the&nbsp;<strong>java.rmi.Remote<\/strong>&nbsp;interface<\/li><li>Each remote method must throw the <strong>java.rmi.RemoteException<\/strong> exception.<\/li><\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"The_Remote_Implementation\"><\/span>The Remote Implementation<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s the implementation of the Hello server.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Notice that in this case the remote object and the remote server are the same class.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage rmiServer;\n\nimport java.rmi.AlreadyBoundException;\nimport java.rmi.RemoteException;\nimport java.rmi.registry.LocateRegistry;\nimport java.rmi.registry.Registry;\nimport java.rmi.server.UnicastRemoteObject;\n\nimport rmi.Hello;\n\n\/**\n * Server for RMI Hello\n *\n * @author Bryan Higgs\n * @version 1.0\n *\/\npublic class HelloServer implements Hello\n{\n  public String sayHello() throws RemoteException\n  {\n    return &quot;Hello, RMI world!&quot;;\n  }\n  \n  \/**\n   * Main entry point for server\n   * @param args the command line arguments\n   *             args&#x5B;0] contains the port number for the registry\n   *\/\n  public static void main(String&#x5B;] args)\n  {\n    \/\/ Determine the port number\n    int port = 1099;  \/\/ the default port number for the registry\n    if (args.length &gt; 0)\n    {\n      try\n      {\n        port = Integer.parseInt(args&#x5B;0]);\n      }\n      catch (NumberFormatException nfe)\n      {\n        System.err.println(&quot;Port number &quot; + args&#x5B;1] + &quot; invalid&quot;);\n        return;\n      }\n    }\n        \n    try\n    {\n      \/\/ Create the object that provides the service\n      HelloServer object = new HelloServer();\n      \/\/ Export the remote object to the Java RMI runtime\n      Hello stub = (Hello) UnicastRemoteObject.exportObject(object, 0);\n      \n      \/\/ Bind the remote object&#039;s stub in the RMI registry\n      Registry registry = LocateRegistry.getRegistry(port);\n      registry.bind(&quot;Hello&quot;, stub);\n      \n      System.err.println(&quot;Server ready...&quot;);\n    }\n    catch (AlreadyBoundException abe)\n    {\n      \/\/ The attempt to bind failed, because it&#039;s already bound\n      abe.printStackTrace();\n    }\n    catch (RemoteException re)\n    {\n      re.printStackTrace();\n    }\n  }\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Note that we:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Export the remote object to the Java RMI runtime, using the&nbsp;<a href=\"http:\/\/java.sun.com\/j2se\/1.5.0\/docs\/api\/java\/rmi\/server\/UnicastRemoteObject.html\" target=\"_blank\" rel=\"noreferrer noopener\">java.rmi.server.UnicastRemoteObject<\/a>&nbsp;class&#8217;s&nbsp;exportObject()&nbsp;method.&nbsp; This causes a corresponding stub class to be loaded and an instance of that stub class to be constructed<\/li><li>Use the&nbsp;<a href=\"http:\/\/java.sun.com\/j2se\/1.5.0\/docs\/api\/java\/rmi\/registry\/LocateRegistry.html\" target=\"_blank\" rel=\"noreferrer noopener\">java.rmi.registry.LocateRegistry<\/a>&nbsp;class to locate the registry (on the server machine), and then&nbsp;<a href=\"http:\/\/java.sun.com\/j2se\/1.5.0\/docs\/api\/java\/rmi\/registry\/Registry.html\" target=\"_blank\" rel=\"noreferrer noopener\">java.rmi.registry.Registry<\/a>&nbsp;to bind the remote object in the&nbsp;RMI registry.<\/li><li>If the object is already bound, then an AlreadyBoundException will occur.&nbsp; Another possible choice is to call the&nbsp;<a href=\"http:\/\/java.sun.com\/j2se\/1.5.0\/docs\/api\/java\/rmi\/registry\/Registry.html#rebind(java.lang.String,%20java.rmi.Remote)\" target=\"_blank\" rel=\"noreferrer noopener\">rebind()&nbsp;method<\/a>&nbsp;to cause this binding to replace any already existing one.<\/li><li>Implement the remote object in the&nbsp;sayHello()&nbsp;method.<\/li><\/ol>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"The_Client_Program\"><\/span>The Client Program<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s the client program:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage rmiClient;\n\nimport java.rmi.NotBoundException;\nimport java.rmi.RemoteException;\nimport java.rmi.registry.LocateRegistry;\nimport java.rmi.registry.Registry;\n\nimport rmi.Hello;\n\n\/**\n * Client for Hello RMI server.\n *\n * @author Bryan Higgs\n * @version 1.0\n *\/\npublic class HelloClient\n{\n  \/**\n   * Main entry point for client\n   * @param args the command line arguments\n   *             args&#x5B;0] contains the server hostname\n   *             args&#x5B;1] contains the port number for the registry\n   *\/\n  public static void main(String&#x5B;] args)\n  {\n    \/\/ Determine server hostname\n    String host = null;\n    if (args.length &gt; 0)\n      host = args&#x5B;0];\n    \n    \/\/ Determine the port number\n    int port = 1099;  \/\/ the default port number for the registry\n    if (args.length &gt; 1)\n    {\n      try\n      {\n        port = Integer.parseInt(args&#x5B;1]);\n      }\n      catch (NumberFormatException nfe)\n      {\n        System.err.println(&quot;Port number &quot; + args&#x5B;1] + &quot; invalid&quot;);\n        return;\n      }\n    }\n    \n    try\n    {\n      \/\/ Find the RMI registry\n      Registry registry = LocateRegistry.getRegistry(host, port);\n      \/\/ Look up the server\n      Hello stub = (Hello) registry.lookup(&quot;Hello&quot;);\n      \n      \/\/ Call the server at the sayHello entry point.\n      String response = stub.sayHello();\n      System.out.println(&quot;Response: &quot; + response);\n    }\n    catch (NotBoundException nbe)\n    {\n      nbe.printStackTrace();\n    }\n    catch (RemoteException re)\n    {\n      re.printStackTrace();\n    }\n  }\n  \n  \/**\n   * Creates a new instance of HelloClient\n   * (Make private to disable constructor)\n   *\/\n  public HelloClient()\n  {\n  }\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Note that we:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Use the&nbsp;<a rel=\"noreferrer noopener\" href=\"http:\/\/java.sun.com\/j2se\/1.5.0\/docs\/api\/java\/rmi\/registry\/LocateRegistry.html\" target=\"_blank\">java.rmi.registry.LocateRegistry<\/a>&nbsp;class to locate the registry (on the server machine), and then&nbsp;<a rel=\"noreferrer noopener\" href=\"http:\/\/java.sun.com\/j2se\/1.5.0\/docs\/api\/java\/rmi\/registry\/Registry.html\" target=\"_blank\">java.rmi.registry.Registry<\/a>&nbsp;to look up the remote object in the&nbsp;RMI registry.<\/li><li>Call the remote object by calling the stub&#8217;s&nbsp;<strong>sayHello()<\/strong>&nbsp;method.<\/li><li>Print out the response.<\/li><\/ol>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Running_the_Example\"><\/span>Running the Example<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Now, with all the pieces constructed, we can run the example.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It&#8217;s not as straightforward as running a regular Java program!&nbsp; Here&#8217;s what we have to do:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Start the RMI registry by running the&nbsp;<strong>rmiregistry<\/strong>&nbsp;utility.<\/li><li>Start the&nbsp;Hello&nbsp;Server:<br>On Windows:&nbsp;<strong>&nbsp;&nbsp;&nbsp;<\/strong>&nbsp;&nbsp;&nbsp;&nbsp;<strong>start java rmiServer.HelloServer<\/strong><br>On Unix\/Linux:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>java rmiServer.HelloServer &amp;<\/strong><br>If all goes well, the server should output:<br><strong>Server ready&#8230;<\/strong><\/li><li>Run&nbsp; the&nbsp;Hello&nbsp;client:<strong>java rmiClient.HelloClient<\/strong><br>If all goes well, the client should output:<br><strong>Response: Hello, RMI world!<\/strong><\/li><\/ol>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Note<\/strong>: The order in which we perform these steps is important!<\/p>\n\n\n\n<blockquote class=\"wp-block-quote broad-point is-layout-flow wp-block-quote-is-layout-flow\"><p>Well, as I said, things have changed since my initial coverage of RMI.<\/p><p>The above steps do not seem to work in the latest version of the JDK.<\/p><p>Investigating&#8230;<\/p><\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Listing_Remote_Objects\"><\/span>Listing Remote Objects<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">It can be useful to determine what objects are bound in the RMI registry.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s a program that does just that. It&#8217;s based on the textbook example, but augmented slightly.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage rmi;\n\nimport javax.naming.Context;\nimport javax.naming.InitialContext;\nimport javax.naming.NameClassPair;\nimport javax.naming.NamingEnumeration;\nimport javax.naming.NamingException;\n\n\/**\n * Class to list all the current RMI bindings\n *\n * @author Bryan Higgs\n * @version 1.0\n *\/\npublic class ShowRmiBindings\n{\n  \/**\n   * Main entry point\n   * @param args the command line arguments\n   *             args&#x5B;0] contains the host name\n   *             args&#x5B;1] contains the port number\n   *\/\n  public static void main(String&#x5B;] args)\n  {\n    String host = &quot;localhost&quot;;  \/\/ the default\n    int port = 1099;            \/\/ the default\n    if (args.length &gt; 0)\n    {\n      host = args&#x5B;0];\n      if (args.length &gt; 1)\n      {\n        try\n        {\n          port = Integer.parseInt(args&#x5B;1]);\n        }\n        catch (NumberFormatException nfe)\n        {\n          System.err.println(&quot;Port number &quot; + args&#x5B;1] + &quot; invalid&quot;);\n          return;\n        }\n      }\n    }\n    \n    \/\/ Construct the rmi URL\n    String rmiURL = &quot;rmi:\/\/&quot; + host + &quot;:&quot; + port;\n    \n    try\n    {\n      \/\/ Get the naming context\n      Context namingContext = new InitialContext();\n      \/\/ Get an emumeration of all RMI objects\n      NamingEnumeration&lt;NameClassPair&gt; enumeration \n                            = namingContext.list(rmiURL);\n      \/\/ Print them out\n      while (enumeration.hasMore())\n      {\n        System.out.println(enumeration.next().getName());\n      }\n    }\n    catch (NamingException ne)\n    {\n      ne.printStackTrace();\n    }\n  }\n}\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"An_Extended_Example\"><\/span>An Extended Example<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s a more complex example.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We&#8217;ll implement a simple bank account service that supports obtaining an account ID, holder name, current balance, and deposits and withdrawals.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"BankAccount\"><\/span>BankAccount<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s the BankAccount remote interface:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage rmi;\n\nimport java.rmi.Remote;\nimport java.rmi.RemoteException;\n\n\/**\n * A simple RMI remote interface to a bank account.\n * @author Bryan Higgs\n *\/\npublic interface BankAccount extends Remote\n{\n  \/**\n   * Returns the unique account id\n   * @return the unique account id\n   *\/\n  public int getAccountId() throws RemoteException;\n  \n  \/**\n   * Returns the name of the bank account holder.\n   * @return the name of the holder of this bank account\n   *\/\n  String getHolder() throws RemoteException;\n  \n  \/**\n   * Deposit an amount\n   * @param amount the amount to deposit\n   * @return the balance after the deposit completed.\n   *\/\n  double deposit(double amount) throws RemoteException;\n  \n  \/**\n   * Withdraw an amount\n   * @param amount the amount to withdraw\n   * @return the balance after the withdrawal completed.\n   *\/\n  double withdraw(double amount) throws RemoteException;\n  \n  \/**\n   * Gets the current balance\n   * @return the current balance in the account\n   *\/\n  double getBalance() throws RemoteException;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">It shows several methods, and also shows passing parameters to those methods, and the methods returning values.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"BankAccountImpl\"><\/span>BankAccountImpl<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s the BankAccountImpl class, which implements the BankAccount interface, and thus constitutes the remote object:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage rmiServer;\n\nimport java.rmi.RemoteException;\nimport java.rmi.server.UnicastRemoteObject;\n\nimport rmi.BankAccount;\n\n\/**\n * A BankAccount RMI remote object class.\n *\n * @author Bryan Higgs\n * @version 1.0\n *\/\npublic class BankAccountImpl \n    extends UnicastRemoteObject\n    implements BankAccount\n{\n  \/**\n   * Constructor\n   * @param id the unique account id\n   * @param holder the name of the account holder\n   * @param initialDeposit the amount of the initial deposit.\n   *\/\n  public BankAccountImpl(int id, String holder, double initialDeposit) \n    throws RemoteException\n  {\n    m_id = id;\n    m_holder = holder;\n    m_balance = initialDeposit;\n  }\n  \n  \/**\n   * Returns the unique account id\n   * @return the unique account id\n   *\/\n  public int getAccountId() throws RemoteException\n  {\n    return m_id;\n  }\n  \n  \/**\n   * Returns the name of the bank account holder.\n   * @return the name of the holder of this bank account\n   *\/\n  public String getHolder() throws RemoteException\n  {\n    return m_holder;\n  }\n  \n  \/**\n   * Deposit an amount\n   * @param amount the amount to deposit\n   * @return the balance after the deposit completed.\n   *\/\n  public double deposit(double amount) throws RemoteException\n  {\n    m_balance += amount;\n    return m_balance;\n  }\n\n  \/**\n   * Withdraw an amount\n   * @param amount the amount to withdraw\n   * @return the balance after the withdrawal completed.\n   *\/\n  public double withdraw(double amount) throws RemoteException\n  {\n    m_balance -= amount;\n    return m_balance;\n  }\n\n  \/**\n   * Gets the current balance\n   * @return the current balance in the account\n   *\/\n  public double getBalance() throws RemoteException\n  {\n    return m_balance;\n  }\n  \n\n  \/\/\/\/\/\/\/ Private data \/\/\/\/\/\/\n  private int     m_id; \n  private String  m_holder;\n  private double  m_balance;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Note that:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>It extends from&nbsp;<strong>java.rmi.server.UnicastRemoteObject<\/strong>&nbsp;.&nbsp; This causes the class to be exported automatically (done by the constructor for <strong>UnicastRemoteObject<\/strong>, which is automatically called from the <strong>BankAccountImpl<\/strong>&nbsp;constructor)<\/li><li>It has a constructor which allows us to construct an instance with a specified account ID, holder name, and initial balance.<\/li><\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"BankAccountServer\"><\/span>BankAccountServer<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s the <strong>BankAccountServer<\/strong> class, which is the remote server for all <strong>BankAccount<\/strong> remote objects:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage rmiServer;\n\nimport java.rmi.RemoteException;\nimport javax.naming.Context;\nimport javax.naming.InitialContext;\nimport javax.naming.NamingException;\n\nimport rmi.BankAccount;\n\n\/**\n * The BankAccount RMI server.\n *\n * @author Bryan Higgs\n * @version 1.0\n *\/\npublic class BankAccountServer\n{\n  \/**\n   * Main entry point for server\n   * @param args the command line arguments\n   *             args&#x5B;0] contains the port number for the registry\n   *\/\n  public static void main(String&#x5B;] args)\n  {\n    \/\/ Determine the port number\n    int port = 1099;  \/\/ the default port number for the registry\n    if (args.length &gt; 0)\n    {\n      try\n      {\n        port = Integer.parseInt(args&#x5B;0]);\n      }\n      catch (NumberFormatException nfe)\n      {\n        System.err.println(&quot;Port number &quot; + args&#x5B;1] + &quot; invalid&quot;);\n        return;\n      }\n    }\n        \n    try\n    {\n      System.err.println(&quot;Starting BankAccount Server...&quot;);\n      \n      System.err.println(&quot;Creating BankAccount objects...&quot;);\n            \n      \/\/ Create an object that provides the BankAccount service\n      BankAccountImpl account1 = new BankAccountImpl(1, &quot;Fred Bloggs&quot;, 10000);\n      \/\/ Create a second object that provides the BankAccount service\n      BankAccountImpl account2 = new BankAccountImpl(2, &quot;Mary Clark&quot;, 30000);\n      \n      System.err.println(&quot;Binding remote objects to registry...&quot;);\n      \n      Context namingContext = new InitialContext();\n      namingContext.bind(&quot;rmi:\/\/localhost:&quot; + port + &quot;\/Fred&quot;, account1);\n      namingContext.bind(&quot;rmi:\/\/localhost:&quot; + port + &quot;\/Mary&quot;, account2);\n      \n      System.err.println(&quot;BankAccount Server ready...&quot;);\n    }\n    catch (NamingException ex)\n    {\n      ex.printStackTrace();\n    }\n    catch (RemoteException re)\n    {\n      re.printStackTrace();\n    }\n  }\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Note the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>It creates the two <strong>BankAccountImpl<\/strong> instances.<\/li><li>It uses&nbsp;<a rel=\"noreferrer noopener\" href=\"http:\/\/java.sun.com\/j2se\/1.5.0\/docs\/api\/javax\/naming\/InitialContext.html\" target=\"_blank\">javax.naming.InitialContext<\/a>&nbsp;and&nbsp;<a rel=\"noreferrer noopener\" href=\"http:\/\/java.sun.com\/j2se\/1.5.0\/docs\/api\/javax\/naming\/Context.html\" target=\"_blank\">javax.naming.Context<\/a>&nbsp;, both from the&nbsp;<a rel=\"noreferrer noopener\" href=\"http:\/\/java.sun.com\/products\/jndi\/\" target=\"_blank\">Java Naming and Directory Interface (JNDI)<\/a>, to bind the two account remote objects, using the names &#8220;Fred&#8221; and &#8220;Mary&#8221; (This is just for example;&nbsp; in a real application, you would want a more robust naming convention, of course.)<\/li><\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"BankAccountClient\"><\/span>BankAccountClient<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s the BankAccountClient class:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage rmiClient;\n\nimport java.awt.event.ActionEvent;\nimport java.awt.event.ActionListener;\nimport java.rmi.RemoteException;\nimport javax.naming.Context;\nimport javax.naming.InitialContext;\nimport javax.naming.NamingException;\nimport javax.swing.JButton;\nimport javax.swing.JFrame;\nimport javax.swing.JLabel;\nimport javax.swing.JOptionPane;\nimport javax.swing.JPanel;\nimport javax.swing.JTextField;\n\nimport rmi.BankAccount;\nimport rmiServer.BankAccountImpl;\n\n\/**\n * A BankAccount RMI client\n *\n * @author Bryan Higgs\n * @version 1.0\n *\/\npublic class BankAccountClient extends JFrame\n{\n  \/**\n   * Creates a new instance of BankAccountClient\n   *\/\n  public BankAccountClient()\n  {\n    super(&quot;Bank Account Client&quot;);\n    JPanel contentPanel = new JPanel();\n    setContentPane(contentPanel);\n    contentPanel.add( new JLabel(&quot;Enter Account name: &quot;) );\n    contentPanel.add(m_name);\n    contentPanel.add(m_button);\n    m_button.addActionListener( new ActionListener()\n      {\n        public void actionPerformed(ActionEvent event)\n        {\n          findAccount();\n        }\n      }\n    );\n    pack();\n  }\n  \n  \/**\n   * Finds the account, using the name specified\n   *\/\n  private void findAccount()\n  {\n    String name = m_name.getText().trim();\n    BankAccount account;\n    try\n    {\n      account = (BankAccount) m_namingContext.lookup(m_baseURL + name);\n      JOptionPane.showOptionDialog(\n                  this,\n                  new BankAccountClientPanel(account),\n                  &quot;Bank Account Client Display&quot;,\n                  JOptionPane.DEFAULT_OPTION,\n                  JOptionPane.PLAIN_MESSAGE,\n                  null, null, null\n                 );\n    } \n    catch (NamingException ex)\n    {\n      JOptionPane.showMessageDialog(this, &quot;Could not find account&quot;,\n                                    &quot;Error&quot;, JOptionPane.ERROR_MESSAGE);\n      ex.printStackTrace();\n    }\n  }\n  \n  \/\/\/\/\/\/ Private instance data \/\/\/\/\/\/\n  \n  private JTextField m_name = new JTextField(10);\n  private JButton    m_button = new JButton(&quot;Find Account&quot;); \n  \n  \/**\n   * Main entry point for client\n   * @param args the command line arguments\n   *             args&#x5B;0] contains the server hostname\n   *             args&#x5B;1] contains the port number for the registry\n   *\/\n  public static void main(String&#x5B;] args)\n  {\n    \/\/ Determine server hostname\n    String host = null;\n    if (args.length &gt; 0)\n      host = args&#x5B;0];\n    \n    \/\/ Determine the port number\n    int port = 1099;  \/\/ the default port number for the registry\n    if (args.length &gt; 1)\n    {\n      try\n      {\n        port = Integer.parseInt(args&#x5B;1]);\n      }\n      catch (NumberFormatException nfe)\n      {\n        System.err.println(&quot;Port number &quot; + args&#x5B;1] + &quot; invalid&quot;);\n        return;\n      }\n    }\n    \n    \/\/ Construct the base URL for the lookups.\n    m_baseURL = &quot;rmi:\/\/&quot; + host + &quot;:&quot; + port + &quot;\/&quot;;\n    \n    \/\/ Obtain the initial naming context for later...\n    try\n    {\n      m_namingContext = new InitialContext();\n    }\n    catch (NamingException ne)\n    {\n      ne.printStackTrace();\n      return;\n    }\n    \n    \/\/ Now construct the GUI\n    \n    JFrame frame = new BankAccountClient();\n    frame.setVisible(true);\n  }\n  \n  \/\/\/\/\/ Private data \/\/\/\/\/\n  private static Context m_namingContext;\n  private static String  m_baseURL;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Note that it:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Sets up the initial naming context and a base RMI URL in the main method, and then fires up a BankAccountClient JFrame.<\/li><li>When the &#8220;Find Account&#8221; button is clicked, the findAccount method does a look up in the naming context, based on the name specified in the <strong>JTextField<\/strong>.&nbsp; It does this by first constructing an RMI URL from the base URL and the supplied name.<\/li><li>If it succeeds in this look up, it then constructs a <strong>BankAccountClientPanel<\/strong>, passing in the <strong>BankAccount<\/strong> stub found in the look up, and then uses this panel in a <strong>JOptionPane<\/strong> options dialog to display the account details.<\/li><li>If the look up fails, then a <strong>JOptionPane<\/strong> error message dialog to tell the user.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Here is the BankAccountClientPanel class:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage rmiClient;\n\nimport java.awt.BorderLayout;\nimport java.awt.Color;\nimport java.awt.event.ActionEvent;\nimport java.awt.event.ActionListener;\nimport java.rmi.RemoteException;\nimport javax.swing.JButton;\nimport javax.swing.JLabel;\nimport javax.swing.JOptionPane;\nimport javax.swing.JPanel;\nimport javax.swing.JTextField;\nimport javax.swing.SwingConstants;\n\nimport rmi.BankAccount;\nimport rmiServer.BankAccountImpl;\n\n\/**\n * The GUI frame for the Bank Account client\n *\n * @author Bryan Higgs\n * @version 1.0\n *\/\npublic class BankAccountClientPanel extends JPanel\n{\n  \/**\n   * Creates a new instance of BankAccountClientPanel\n   *\/\n  public BankAccountClientPanel(BankAccount account)\n  {\n    m_account = account;\n    \n    setLayout( new BorderLayout() );\n    \n    try\n    {\n      JPanel northPanel = new JPanel();\n      add( northPanel, BorderLayout.NORTH );\n      northPanel.add( new JLabel(&quot;Bank Account #: &quot;) );\n      northPanel.add( m_id );\n      m_id.setEditable(false);\n      m_id.setText( &quot;&quot; + m_account.getAccountId() );\n      \n      JPanel centerPanel = new JPanel( new BorderLayout() );\n      add( centerPanel, BorderLayout.CENTER );\n      JPanel holderPanel = new JPanel();\n      centerPanel.add( holderPanel, BorderLayout.NORTH );\n      holderPanel.add( new JLabel(&quot;Holder: &quot;) );\n      holderPanel.add( m_holder );\n      m_holder.setEditable(false);\n      m_holder.setText( m_account.getHolder() );\n      \n      JPanel middlePanel = new JPanel( new BorderLayout() );\n      centerPanel.add( middlePanel, BorderLayout.SOUTH );\n      JPanel depositPanel = new JPanel();\n      middlePanel.add( depositPanel, BorderLayout.NORTH );\n      depositPanel.add( m_depositButton );\n      m_depositButton.addActionListener( new ActionListener()\n        {\n          public void actionPerformed(ActionEvent event)\n          {\n            depositMoney();\n          }\n        }\n      );\n      depositPanel.add( new JLabel(&quot;$&quot;) );\n      depositPanel.add( m_depositAmount );\n      JPanel withdrawPanel = new JPanel();\n      middlePanel.add( withdrawPanel, BorderLayout.SOUTH );\n      withdrawPanel.add( m_withdrawButton );\n      m_withdrawButton.addActionListener( new ActionListener()\n        {\n          public void actionPerformed(ActionEvent event)\n          {\n            withdrawMoney();\n          }\n        }\n      );\n      withdrawPanel.add( new JLabel(&quot;$&quot;) );\n      withdrawPanel.add( m_withdrawAmount );\n      \n      JPanel southPanel = new JPanel();\n      add( southPanel, BorderLayout.SOUTH );\n      southPanel.add( new JLabel(&quot;Balance: &quot;) );\n      southPanel.add( new JLabel(&quot;$&quot;) );\n      southPanel.add( m_balance );\n      m_balance.setEditable(false);\n      setBalance( m_account.getBalance() );\n    }\n    catch (RemoteException ex)\n    {\n      ex.printStackTrace();\n    }\n  }\n  \n  \/**\n   * Sets the balance in the JTextField\n   * and sets its color appropriately\n   *\/\n  private void setBalance(double balance)\n  {\n    m_balance.setText( &quot;&quot; + balance );\n    if (balance &lt; 0)\n      m_balance.setForeground(Color.RED);\n    else\n      m_balance.setForeground(Color.BLACK);\n  }\n  \n  \/**\n   * Deposits money into the account\n   *\/\n  private void depositMoney()\n  {\n    Double amount = getAmount(m_depositAmount);\n    if (amount != null)\n    {\n      double balance = 0.0;\n      try\n      {\n        balance = m_account.deposit(amount);\n      } \n      catch (RemoteException ex)\n      {\n        ex.printStackTrace();\n      }\n      setBalance(balance);\n    }\n    else\n    {\n      showErrorMessage();\n    }\n  }\n  \n  \/**\n   * Withdraws money from the account\n   *\/\n  private void withdrawMoney()\n  {\n    Double amount = getAmount(m_withdrawAmount);\n    if (amount != null)\n    {\n      double balance = 0.0;\n      try\n      {\n        balance = m_account.withdraw(amount);\n      } \n      catch (RemoteException ex)\n      {\n        ex.printStackTrace();\n      }\n      setBalance(balance);\n    }\n    else\n    {\n      showErrorMessage();\n    }\n  }\n  \n  \/**\n   * Check that the amount is valid for deposit or withdrawal\n   *\/\n  private Double getAmount(JTextField amountField)\n  {\n    double amount = 0.0;\n    String amountString = amountField.getText();\n    amountString = amountString.trim();\n    if (amountString == null || amountString.equals(&quot;&quot;))\n      amountString = null;\n    else\n    {\n      try\n      {\n        amount = Double.parseDouble(amountString);\n      }\n      catch (NumberFormatException nfe)\n      {\n        amountString = null;\n      }\n    }  \n    if (amountString != null)\n      return amount;\n    else\n      return null;\n  }\n  \n  \/**\n   * Show error message dialog\n   *\/\n  private void showErrorMessage()\n  {\n    JOptionPane.showMessageDialog(this, &quot;Amount improperly specified&quot;,\n                                  &quot;Error&quot;, JOptionPane.ERROR_MESSAGE);\n  }\n  \n  \/\/\/\/\/ Private data \/\/\/\/\/\n  \n  private BankAccount m_account;\n  private JTextField m_id = new JTextField(4);\n  private JTextField m_holder = new JTextField(15);\n  private JTextField m_depositAmount = new JTextField(10);\n  private JButton    m_depositButton = new JButton(&quot;Deposit this amount&quot;);\n  private JTextField m_withdrawAmount = new JTextField(10);\n  private JButton    m_withdrawButton = new JButton(&quot;Withdraw this amount&quot;);\n  private JTextField m_balance = new JTextField(15);\n  \n  \/**\n   * Main entry point (for testing)\n   *\/\n  public static void main(String&#x5B;] args)\n  {\n    try\n    {\n    JOptionPane.showOptionDialog(\n                  null,\n                  new BankAccountClientPanel(\n                        new BankAccountImpl(53, &quot;Darth Vader&quot;, 10000.00)),\n                  &quot;Bank Account Client Display&quot;,\n                  JOptionPane.DEFAULT_OPTION,\n                  JOptionPane.PLAIN_MESSAGE,\n                  null, null, null\n                 );\n    }\n    catch (RemoteException re)\n    {\n      re.printStackTrace();\n    }\n  }\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Note that it:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Has a main method which uses a local <strong>BankAccountImpl<\/strong> instance to test the class without relying on remote objects.<\/li><li>Has a constructor that accepts a <strong>BankAccount<\/strong>;&nbsp; this allows for either a local or remote (i.e. stub) instance.<\/li><li>Uses calls to the <strong>BankAccount<\/strong> to obtain:<ul><li>The account ID<\/li><li>The holder name<\/li><li>The current balance (which it displays in red if the balance is negative)<\/li><\/ul><\/li><li>Is basically ignorant of whether the <strong>BankAccount<\/strong> it is using is local or remote (aside from the testing code in the main method).<\/li><\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Running_the_Example-2\"><\/span>Running the Example<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">As before, in order to run the example, we have to do the following steps:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Start the RMI registry by running the&nbsp;<strong>rmiregistry<\/strong>&nbsp;utility.<\/li><li>Start the&nbsp;BankAccount&nbsp;server:<br>On Windows:&nbsp;<strong>&nbsp;&nbsp;&nbsp;<\/strong>&nbsp;&nbsp;&nbsp;&nbsp;   <strong>start java rmiServer.BankAccountServer<\/strong><br>On Unix\/Linux:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>java rmiServer.BankAccountServer &amp;<\/strong><br>If all goes well, the server should output:<br><strong>Starting BankAccount Server&#8230; <\/strong><br><strong>Creating BankAccount objects&#8230; <\/strong><br><strong>Binding remote objects to registry&#8230; <\/strong><br><strong>BankAccount Server ready&#8230;<\/strong><\/li><li>Run&nbsp; the&nbsp;BankAccount&nbsp;client:<br><strong>java rmiClient.BankAccountClient<\/strong><br>If all goes well, the client should display:<\/li><\/ol>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"370\" height=\"70\" src=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/02\/Runnin1.jpg\" alt=\"\" class=\"wp-image-522\" srcset=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/02\/Runnin1.jpg 370w, https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/02\/Runnin1-300x57.jpg 300w\" sizes=\"auto, (max-width: 370px) 100vw, 370px\" \/><\/figure><\/div>\n\n\n\n<div style=\"height:14px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><strong><em><u>Note:<\/u><\/em><\/strong>&nbsp;Again, the order in which we perform these steps is important!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Now, we can enter a name by which the bank account client can identify the bank account remote object.&nbsp; Remember we have two accounts, one with a name&nbsp;<strong>Fred<\/strong>, and the other with a name&nbsp;<strong>Mary<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As shown above, if we enter the name&nbsp;<strong>Mary<\/strong>, we&#8217;ll see a second window come up:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"328\" height=\"251\" src=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/02\/Runnin2.jpg\" alt=\"\" class=\"wp-image-523\" srcset=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/02\/Runnin2.jpg 328w, https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/02\/Runnin2-300x230.jpg 300w\" sizes=\"auto, (max-width: 328px) 100vw, 328px\" \/><\/figure><\/div>\n\n\n\n<div style=\"height:11px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">We can then deposit some money into Mary&#8217;s account:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"328\" height=\"251\" src=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/02\/Runnin3.jpg\" alt=\"\" class=\"wp-image-524\" srcset=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/02\/Runnin3.jpg 328w, https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/02\/Runnin3-300x230.jpg 300w\" sizes=\"auto, (max-width: 328px) 100vw, 328px\" \/><\/figure><\/div>\n\n\n\n<div style=\"height:11px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">and withdraw money from her account:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"328\" height=\"251\" src=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/02\/Runnin4.jpg\" alt=\"\" class=\"wp-image-525\" srcset=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/02\/Runnin4.jpg 328w, https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/02\/Runnin4-300x230.jpg 300w\" sizes=\"auto, (max-width: 328px) 100vw, 328px\" \/><\/figure><\/div>\n\n\n\n<div style=\"height:13px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Then we can dismiss the dialog box by clicking on the OK button, which will allow us to enter another account name:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"370\" height=\"70\" src=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/02\/Runnin5.jpg\" alt=\"\" class=\"wp-image-526\" srcset=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/02\/Runnin5.jpg 370w, https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/02\/Runnin5-300x57.jpg 300w\" sizes=\"auto, (max-width: 370px) 100vw, 370px\" \/><\/figure><\/div>\n\n\n\n<div style=\"height:12px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">and thereby bring up another dialog box with Fred&#8217;s account details:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"328\" height=\"251\" src=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/02\/Runnin6.jpg\" alt=\"\" class=\"wp-image-527\" srcset=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/02\/Runnin6.jpg 328w, https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/02\/Runnin6-300x230.jpg 300w\" sizes=\"auto, (max-width: 328px) 100vw, 328px\" \/><\/figure><\/div>\n\n\n\n<div style=\"height:11px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">where we can also deposit and\/or withdraw money from that account.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">On the other hand, if we enter an account name that doesn&#8217;t exist:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"370\" height=\"70\" src=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/02\/Runnin7.jpg\" alt=\"\" class=\"wp-image-528\" srcset=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/02\/Runnin7.jpg 370w, https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/02\/Runnin7-300x57.jpg 300w\" sizes=\"auto, (max-width: 370px) 100vw, 370px\" \/><\/figure><\/div>\n\n\n\n<div style=\"height:11px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">we get the following displayed:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"268\" height=\"122\" src=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/02\/Runnin8.jpg\" alt=\"\" class=\"wp-image-529\"\/><\/figure><\/div>\n\n\n\n<div style=\"height:11px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">In this case, our client also does a stack trace, which looks something like:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>javax.naming.NameNotFoundException: Bozo\n        at com.sun.jndi.rmi.registry.RegistryContext.lookup(RegistryContext.java:95)\n        at com.sun.jndi.toolkit.url.GenericURLContext.lookup(GenericURLContext.java:185)\n        at javax.naming.InitialContext.lookup(InitialContext.java:351)\n        at rmiClient.BankAccountClient.findAccount(BankAccountClient.java:58)\n        at rmiClient.BankAccountClient.access$000(BankAccountClient.java:25)\n        at rmiClient.BankAccountClient$1.actionPerformed(BankAccountClient.java:42)\n\t...<\/strong><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Caveats\"><\/span>Caveats<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">RMI can be very tricky to get working.&nbsp; Here are some of the areas where you may have to spend some time figuring things out:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>Deployment<\/strong> &#8212; The textbook goes into a fair amount of detail on deployment, and for good reason: If you don&#8217;t do it right, things won&#8217;t work!<\/li><li><strong>Security<\/strong> &#8212; You may find that you will need to set up your own security policy, which involves setting up a policy file and using a security manager.&nbsp; Again, if you don&#8217;t grant all the permissions you need, things simply won&#8217;t work.&nbsp; See the textbook for details.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">One of the reasons for these difficulties is that it&#8217;s very difficult to diagnose the underlying problem when things don&#8217;t work.&nbsp; You&#8217;re likely to get error messages that seem to bear no relationship to what the r\/eal problem might be.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Be prepared for some degree of frustration!<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Passing_Objects_in_RMI\"><\/span>Passing Objects in RMI<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The <a rel=\"noreferrer noopener\" href=\"https:\/\/docs.oracle.com\/javase\/tutorial\/rmi\/implementing.html\" target=\"_blank\">Java RMI Tutorial<\/a> says&nbsp;:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Arguments to or return values from remote methods can be of almost any type, including local objects, remote objects, and primitive data types. More precisely, any entity of any type can be passed to or from a remote method as long as the entity is an instance of a type that is a primitive data type, a remote object, or a&nbsp;<em>serializable<\/em>&nbsp;object, which means that it implements the interface&nbsp;<code>java.io.Serializable.<\/code><\/p><\/blockquote>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Some object types do not meet any of these criteria and thus cannot be passed to or returned from a remote method. Most of these objects, such as threads or file descriptors, encapsulate information that makes sense only within a single address space. Many of the core classes, including the classes in the packages&nbsp;<code>java.lang<\/code>&nbsp;and&nbsp;<code>java.util<\/code>, implement the&nbsp;<code>Serializable<\/code>&nbsp;interface.<\/p><\/blockquote>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>The rules governing how arguments and return values are passed are as follows:<\/p><\/blockquote>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Remote objects are essentially passed by reference. A&nbsp;<em>remote object reference<\/em>&nbsp;is a stub, which is a client-side proxy that implements the complete set of remote interfaces that the remote object implements.<\/p><p>Local objects are passed by copy, using object serialization. By default, all fields are copied except fields that are marked&nbsp;<code>static<\/code>&nbsp;or&nbsp;<code>transient<\/code>. Default serialization behavior can be overridden on a class-by-class basis.<\/p><\/blockquote>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Passing a remote object by reference means that any changes made to the state of the object by remote method invocations are reflected in the original remote object. When a remote object is passed, only those interfaces that are remote interfaces are available to the receiver. Any methods defined in the implementation class or defined in non-remote interfaces implemented by the class are not available to that receiver.<\/p><\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">&#8230;<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>In the parameters and return values of remote method invocations, objects that are not remote objects are passed by value. Thus, a copy of the object is created in the receiving Java virtual machine. Any changes to the object&#8217;s state by the receiver are reflected only in the receiver&#8217;s copy, not in the sender&#8217;s original instance. Any changes to the object&#8217;s state by the sender are reflected only in the sender&#8217;s original instance, not in the receiver&#8217;s copy.<\/p><\/blockquote>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"An_Example\"><\/span>An Example<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s an example, based on the example shown in the <a rel=\"noreferrer noopener\" href=\"https:\/\/docs.oracle.com\/javase\/tutorial\/rmi\/index.html\" target=\"_blank\">Java RMI Tutorial<\/a> :<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We&#8217;ll implement a simple Compute Server, which can accept anything that implements a <strong>Task<\/strong> interface.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s the <strong>Task<\/strong> interface:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage rmi;\n\n\/**\n * An Interface describing a task to be performed\n *\n * @author Bryan Higgs\n *\/\npublic interface Task&lt;T&gt;\n{\n  T execute();\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">And here is the remote interface,&nbsp;<strong>ComputeEngine<\/strong>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage rmi;\n\nimport java.rmi.Remote;\nimport java.rmi.RemoteException;\n\n\/**\n * An RMI remote interface for a compute engine.\n *\n * @author Bryan Higgs\n *\/\npublic interface ComputeEngine extends Remote\n{\n  \/**\n   * Computes the specified task\n   * @param task the task to be performed.\n   *\/\n  &lt;T&gt; T compute(Task&lt;T&gt; task) throws RemoteException;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Note how general this interface is:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>The&nbsp;<strong>ComputeEngine<\/strong>&nbsp;interface contains a single method,&nbsp;<strong>compute()<\/strong>.<\/li><li>The&nbsp;<strong>compute()<\/strong>&nbsp;method accepts an argument of type&nbsp;<strong>Task<\/strong>&nbsp;&#8212; that is, any class that implements that interface.<\/li><li>The&nbsp;<strong>compute()<\/strong>&nbsp;method returns a&nbsp;<strong>Task<\/strong>.<\/li><\/ul>\n\n\n\n<h5 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"ComputeEngineImpl\"><\/span>ComputeEngineImpl<span class=\"ez-toc-section-end\"><\/span><\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s the&nbsp;ComputeEngineImpl&nbsp;class.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">There&#8217;s nothing much different here than from earlier examples, except for one thing, which we&#8217;ll examine below.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage rmiServer;\n\nimport java.net.MalformedURLException;\nimport java.rmi.Naming;\nimport java.rmi.RMISecurityManager;\nimport java.rmi.RemoteException;\nimport java.rmi.server.UnicastRemoteObject;\nimport javax.naming.Context;\nimport javax.naming.InitialContext;\nimport javax.naming.NamingException;\n\nimport rmi.ComputeEngine;\nimport rmi.Task;\n\n\/**\n * An implementation of an RMI remote compute engine.\n *\n * @author Bryan Higgs\n * @version 1.0\n *\/\npublic class ComputeEngineImpl\n    extends UnicastRemoteObject\n    implements ComputeEngine\n{\n  \/**\n   * Creates a new instance of ComputeEngineImpl\n   *\/\n  public ComputeEngineImpl() throws RemoteException\n  {\n  }\n\n  \/**\n   * Computes the specified task\n   * @param task the task to be performed.\n   *\/\n  public &lt;T&gt; T compute(Task&lt;T&gt; task) throws RemoteException\n  {\n    return task.execute();\n  }\n  \n  \/**\n   * Main entry point\n   * @param args the command line arguments\n   *             args&#x5B;0] contains the port number for the registry\n   *\/\n  public static void main(String&#x5B;] args)\n  {\n    System.out.println(&quot;Setting java.security.policy ...&quot;);   \n    System.setProperty(&quot;java.security.policy&quot;, &quot;policies\/server.policy&quot;);\n    \/\/ Use a security manager\n    System.err.println(&quot;Setting SecurityManager ...&quot;);\n    System.setSecurityManager( new SecurityManager() );\n    \n    \/\/ Determine the port number\n    int port = 1099;  \/\/ the default port number for the registry\n    if (args.length &gt; 0)\n    {\n      try\n      {\n        port = Integer.parseInt(args&#x5B;0]);\n      }\n      catch (NumberFormatException nfe)\n      {\n        System.err.println(&quot;Port number &quot; + args&#x5B;1] + &quot; invalid&quot;);\n        return;\n      }\n    }\n    \n    System.err.println(&quot;Using port &quot; + port);\n\n    try\n    {\n      System.err.println(&quot;Creating ComputeEngineImpl instance...&quot;);\n      ComputeEngineImpl engine = new ComputeEngineImpl();\n      \n      System.err.println(&quot;&#x5B;Re]binding ComputeEngineImpl instance in registry...&quot;);\n      String url = &quot;rmi:\/\/localhost:&quot; + port + &quot;\/ComputeEngine&quot;;\n      System.err.println(&quot;Using url: &quot; + url);\n      \n      Context namingContext = new InitialContext();\n      namingContext.rebind(&quot;rmi:\/\/localhost:&quot; + port + &quot;\/ComputeEngine&quot;, engine);\n      \n      System.err.println(&quot;Ready to compute...&quot;);\n    }\n    catch (NamingException ne)\n    {\n      ne.printStackTrace();\n    }\n    catch (RemoteException re)\n    {\n      re.printStackTrace();\n    }\n  }\n}\n<\/pre><\/div>\n\n\n<div style=\"height:65px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h5 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Security_Policies\"><\/span>Security Policies<span class=\"ez-toc-section-end\"><\/span><\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">The&nbsp;ComputeEngineImpl&nbsp;class has a significant difference from previous RMI examples we&#8217;ve seen so far:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>It uses&nbsp;<a href=\"http:\/\/http\/\/java.sun.com\/j2se\/1.5.0\/docs\/api\/java\/lang\/SecurityManager.html\" target=\"_blank\" rel=\"noreferrer noopener\">java.lang.SecurityManager<\/a>&nbsp;as the security manager for the program.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Why?&nbsp; Because RMI&#8217;s class loader will not download any classes from remote locations if no security manager has been set.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here is the relevant piece of code that implements this:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>    System.setProperty(\"java.security.policy\", \"policies\/server.policy\");\n    System.setSecurityManager( new SecurityManager() );<\/strong><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The second line sets the security manager.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The first line specified a security policy file to be used.&nbsp; In this case, I set up a&nbsp;server.policy&nbsp;file in a&nbsp;policies&nbsp;subfolder below the current working directory of the server program.&nbsp; It contained the following:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>grant\n{\n  permission java.net.SocketPermission\n    \"localhost:1024-65535\", \"connect,accept\";\n};<\/strong><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">which grants the necessary permission to connect to, and accept connections from, a socket on the localhost, in the range 1024 to 65535.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Security is an important issue for RMI applications.&nbsp; However, figuring out how to set up the security, and deciding what permissions need to be granted adds to the complexity of developing RMI programs.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"ComputePi\"><\/span>ComputePi<span class=\"ez-toc-section-end\"><\/span><\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">Now, here&#8217;s a compute class, <strong>ComputePi<\/strong>, that computes the value of&nbsp;\u03c0&nbsp;to a specified number of places:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage rmiClient;\n\nimport java.io.Serializable;\nimport java.math.BigDecimal;\n\nimport rmi.Task;\n\n\/**\n * Class to compute the value of Pi\n *\n * (Based on the client.Pi class in the Java RMI Tutorial, at\n *  http:\/\/java.sun.com\/docs\/books\/tutorial\/rmi\/client.html )\n *\/\npublic class ComputePi implements Task&lt;BigDecimal&gt;, Serializable\n{\n  \/**\n   * Construct a task to calculate pi to the specified\n   * precision.\n   * @param digits the precision\n   *\/\n  public ComputePi(int digits)\n  {\n    m_digits = digits;\n  }\n  \n  \/**\n   * Calculate pi.\n   *\/\n  public BigDecimal execute()\n  {\n    return computePi(m_digits);\n  }\n  \n  \/**\n   * Compute the value of pi to the specified number of\n   * digits after the decimal point.  The value is\n   * computed using Machin&#039;s formula:\n   *\n   *          pi\/4 = 4*arctan(1\/5) - arctan(1\/239)\n   *\n   * and a power series expansion of arctan(x) to\n   * sufficient precision.\n   *\n   * @param digits the number of digits of precision\n   *\/\n  public static BigDecimal computePi(int digits)\n  {\n    int scale = digits + 5;\n    BigDecimal arctan1_5 = arctan(5, scale);\n    BigDecimal arctan1_239 = arctan(239, scale);\n    BigDecimal pi = arctan1_5.multiply(FOUR)\n                             .subtract(arctan1_239)\n                             .multiply(FOUR);\n    return pi.setScale(digits, BigDecimal.ROUND_HALF_UP);\n  }\n  \n  \/**\n   * Compute the value, in radians, of the arctangent of\n   * the inverse of the supplied integer to the specified\n   * number of digits after the decimal point.  The value\n   * is computed using the power series expansion for the\n   * arc tangent:\n   *\n   * arctan(x) = x - (x^3)\/3 + (x^5)\/5 - (x^7)\/7 + (x^9)\/9 ...\n   *\/\n  public static BigDecimal arctan(int inverseX, int scale)\n  {\n    BigDecimal result, numerator, term;\n    BigDecimal invX = BigDecimal.valueOf(inverseX);\n    BigDecimal invX2 = BigDecimal.valueOf(inverseX * inverseX);\n    \n    numerator = BigDecimal.ONE.divide(invX, scale, ROUNDING_MODE);\n    \n    result = numerator;\n    int i = 1;\n    do\n    {\n      numerator = numerator.divide(invX2, scale, ROUNDING_MODE);\n      int denominator = 2 * i + 1;\n      term = numerator.divide(BigDecimal.valueOf(denominator),\n                              scale, ROUNDING_MODE);\n      if ((i % 2) != 0)\n      {\n        result = result.subtract(term);\n      }\n      else\n      {\n        result = result.add(term);\n      }\n      i++;\n    } while (term.compareTo(BigDecimal.ZERO) != 0);\n    return result;\n  }\n  \n  \/\/\/\/\/ Private data \/\/\/\/\/\n    \n  private static final long serialVersionUID = 227L;\n  \n  \/** constants used in pi computation *\/\n  private static final BigDecimal FOUR = BigDecimal.valueOf(4);\n  \n  \/** rounding mode to use during pi computation *\/\n  private static final int ROUNDING_MODE = BigDecimal.ROUND_HALF_EVEN;\n  \n  \/** digits of precision after the decimal point *\/\n  private final int m_digits;\n}\n<\/pre><\/div>\n\n\n<h5 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"ComputeEngineClient\"><\/span>ComputeEngineClient<span class=\"ez-toc-section-end\"><\/span><\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s the&nbsp;<strong>ComputeEngineClient<\/strong>&nbsp;class.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Note that the original version on the Java RMI Tutorial web site also set a security manager for the client.&nbsp; However, I found that it did not appear to be necessary for the application to work.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage rmiClient;\n\nimport java.math.BigDecimal;\nimport java.net.MalformedURLException;\nimport java.rmi.Naming;\nimport java.rmi.NotBoundException;\nimport java.rmi.RemoteException;\nimport javax.naming.NamingException;\nimport rmi.ComputeEngine;\n\n\/**\n * A class to act as a compute engine client\n * for a remote RMI compute engine object.\n *\n * @author Bryan Higgs\n * @version 1.0\n *\/\npublic class ComputeEngineClient\n{\n  \/**\n   * Main entry point for client\n   * @param args the command line arguments\n   *             args&#x5B;0] contains the server hostname\n   *             args&#x5B;1] contains the port number for the registry\n   *\/\n  public static void main(String&#x5B;] args)\n  {\n    \/\/ Determine server hostname\n    String host = &quot;localhost&quot;;\n    if (args.length &gt; 0)\n      host = args&#x5B;0];\n    \n    \/\/ Determine the port number\n    int port = 1099;  \/\/ the default port number for the registry\n    if (args.length &gt; 1)\n    {\n      try\n      {\n        port = Integer.parseInt(args&#x5B;1]);\n      }\n      catch (NumberFormatException nfe)\n      {\n        System.err.println(&quot;Port number &quot; + args&#x5B;1] + &quot; invalid&quot;);\n        return;\n      }\n    }\n    \n    System.out.println(&quot;Using port &quot; + port);\n    \n    \/\/ Construct the base URL for the lookups.\n    String url = &quot;rmi:\/\/&quot; + host + &quot;:&quot; + port + &quot;\/ComputeEngine&quot;;\n    \n    \/\/ Obtain the initial naming context for later...\n    try\n    {\n      \/\/ Locate the compute engine in the registry\n      System.out.println(&quot;Locating remote ComputeEngine...&quot;);\n      ComputeEngine engine = (ComputeEngine) Naming.lookup(url);\n      \n      System.err.println(&quot;Creating ComputePi instance...&quot;);\n      ComputePi task = new ComputePi(40); \/\/ Compute PI to 40 places\n      \n      System.err.println(&quot;Requesting remote computation...&quot;);\n      BigDecimal pi = engine.compute(task);\n      \n      System.err.println(&quot;Result: PI = &quot; + pi);    \n    }\n    catch (NotBoundException nbe)\n    {\n      nbe.printStackTrace();\n    }\n    catch (MalformedURLException ex)\n    {\n      ex.printStackTrace();\n    }\n    catch (RemoteException ex)\n    {\n      ex.printStackTrace();\n    }\n  }\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Note that it:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Uses&nbsp;<a rel=\"noreferrer noopener\" href=\"http:\/\/java.sun.com\/j2se\/1.5.0\/docs\/api\/java\/rmi\/Naming.html\" target=\"_blank\">java.rmi.Naming<\/a>&nbsp;to perform the look up.<\/li><li>Creates an instance of&nbsp;<strong>ComputePi<\/strong>, specifying 40 places.<\/li><li>Calls the&nbsp;<strong>ComputeEngine<\/strong>&#8216;s&nbsp;<strong>compute()<\/strong>&nbsp;method, passing in a reference to the&nbsp;<strong>ComputePi<\/strong>&nbsp;instance.<\/li><li>Prints out the result.<\/li><\/ul>\n\n\n\n<h5 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Running_the_Example-3\"><\/span>Running the Example<span class=\"ez-toc-section-end\"><\/span><\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">As before, in order to run the example, we have to do the following steps:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Start the RMI registry by running the&nbsp;<strong>rmiregistry<\/strong>&nbsp;utility.<\/li><li>Start the&nbsp;ComputeEngine&nbsp;server:<br>On Windows:&nbsp;<strong>&nbsp;&nbsp;&nbsp;<\/strong>&nbsp;&nbsp;&nbsp;&nbsp;   <strong>start java rmiServer.ComputeEngineServer<\/strong><br>On Unix\/Linux:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>java rmiServer.ComputeEngineServer &amp;<\/strong><br>If all goes well, the server should output:<br><strong>Setting SecurityManager &#8230; <\/strong><br><strong>Using port 2001 <\/strong><br><strong>Creating ComputeEngineImpl instance&#8230; <\/strong><br><strong>[Re]binding ComputeEngineImpl instance in registry&#8230; <\/strong><br><strong>Using url: rmi:\/\/localhost:2001\/ComputeEngine <\/strong><br><strong>Ready to compute&#8230;<\/strong><br>(Your port number may vary.)<\/li><li>Run&nbsp; the&nbsp;ComputeEngine&nbsp;client:<br><strong>java rmiClient.ComputeEngineClient<\/strong><br>If all goes well, the client should display:<br><strong>Using port 2001 <\/strong><br><strong>Locating remote ComputeEngine&#8230; <\/strong><br><strong>Creating ComputePi instance&#8230; <\/strong><br><strong>Requesting remote computation&#8230; <\/strong><br><strong>Result: PI = 3.1415926535897932384626433832795028841972<\/strong><\/li><\/ol>\n\n\n\n<p class=\"wp-block-paragraph\"><strong><em><u>Note:<\/u><\/em><\/strong>&nbsp;Again, the order in which we perform these steps is important!<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Remote_Callbacks\"><\/span>Remote Callbacks<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">It is possible to have the remote object call the client back.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This can be useful for a number of purposes, for example to provide feedback on progress, etc.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s an example of how this can be done using RMI.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We&#8217;ll implement a simple <strong>Time<\/strong> server, where the client registers, and then subsequently receives regular callbacks to report the time.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"The_Remote_Interfaces\"><\/span>The Remote Interfaces<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Here are the remote interfaces for our time server.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">First, the interface to the <strong>Time<\/strong> server&#8217;s functionality:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage rmi;\n\nimport java.rmi.Remote;\nimport java.rmi.RemoteException;\n\nimport rmiClient.TimeMonitor;\n\n\/**\n * A Time interface\n * @author Bryan Higgs\n *\/\npublic interface Time extends Remote\n{\n  void registerTimeMonitor(TimeMonitor monitor) throws RemoteException;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Next, the interface to the client&#8217;s callback functionality:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage rmiClient;\n\nimport java.rmi.Remote;\nimport java.rmi.RemoteException;\nimport java.util.Date;\n\n\/**\n * A TimeMonitor interface\n * @author Bryan Higgs\n *\/\npublic interface TimeMonitor extends Remote\n{\n  void tellMeTheTime(Date time) throws RemoteException;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Note that:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>The <strong>Time<\/strong> interface makes reference to the <strong>TimeMonitor<\/strong> interface.<\/li><li>Both are specified as implementing the <strong>Remote<\/strong> interface.<\/li><\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"The_TimeServer\"><\/span>The TimeServer<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s the TimeServer:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\npackage rmiServer;\n\nimport java.net.MalformedURLException;\nimport java.rmi.Naming;\nimport java.rmi.RMISecurityManager;\nimport java.rmi.Remote;\nimport java.rmi.RemoteException;\nimport java.rmi.UnknownHostException;\nimport java.rmi.registry.LocateRegistry;\nimport java.rmi.server.UnicastRemoteObject;\nimport java.util.Date;\n\nimport rmi.Time;\nimport rmiClient.TimeMonitor;\n    \n\/**\n * TimeServer acts as a server for the remote &quot;Time&quot; service.\n *\/\npublic class TimeServer \n    extends UnicastRemoteObject\n    implements Time\n{\n  \/**\n   * Constructor\n   *\/\n  public TimeServer() throws RemoteException\n  { }\n  \n  \/**\n   * Registers the specified TimeMonitor\n   *\/\n  public void registerTimeMonitor(TimeMonitor monitor)\n  {\n    System.out.println( &quot;Client registering a TimeMonitor&quot; );   \n    new TimeTicker(monitor).start();\n    System.out.println( &quot;Timer Started&quot; );\n  }\n  \n  \/**\n   * Main entry point\n   *\/\n  public static void main(String&#x5B;] args)\n  {\n    System.out.println(&quot;Setting java.security.policy ...&quot;);   \n    System.setProperty(&quot;java.security.policy&quot;, &quot;policies\/server.policy&quot;);\n    \n    \/\/ Use a security manager\n    System.err.println(&quot;Setting SecurityManager ...&quot;);\n    System.setSecurityManager( new SecurityManager() );\n       \n    try\n    {\n      TimeServer server = new TimeServer();\n      System.out.print(&quot;Creating registry...&quot;);\n      LocateRegistry.createRegistry(PORT);\n      System.out.println(&quot;created&quot;);\n      System.out.println(&quot;&#x5B;Re]binding to registry...&quot;);\n      Naming.rebind(&quot;rmi:\/\/&quot; + HOST + &quot;:&quot; + PORT + &quot;\/&quot; + &quot;TimeServer&quot;, server);\n      System.out.println(&quot;Binding done&quot; );    \n      System.out.println(&quot;Waiting for Client requests&quot;);\n    }\n    catch (UnknownHostException uhe)\n    {\n      uhe.printStackTrace();\n    }\n    catch (RemoteException re)\n    {\n      re.printStackTrace();\n    }\n    catch (MalformedURLException mue)\n    {\n      mue.printStackTrace();\n    }\n  }\n  \n  \/\/\/ Private data \/\/\/\/\n  private static final String HOST = &quot;localhost&quot;;\n  private static final int PORT = 2002;\n}\n\n\/**\n * A TimeTicker class, used to update the client\n * on a regular basis.\n *\/\nclass TimeTicker extends Thread\n{\n  \/**\n   * Constructor\n   *\/\n  TimeTicker(TimeMonitor monitor)\n  {\n    m_monitor = monitor;\n  }\n  \n  \/**\n   * The run method for the thread.\n   *\/\n  public void run()\n  {\n    boolean done = false;\n    while (!done)\n    {\n      try\n      {\n        sleep(2000); \/\/ 2 seconds\n        m_monitor.tellMeTheTime( new Date() );\n      }\n      catch ( Exception e )\n      {\n        done = true;\n      }\n    }\n  }\n  \n  \/\/\/\/ Private data \/\/\/\/\n  private TimeMonitor m_monitor;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Note that:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>We&#8217;re creating our own registry, at a specified port<\/li><li>When a client request to register a <strong>TimeMonitor<\/strong> comes in, a new instance of <strong>TimeTicker<\/strong> is created, and started up in a new thread.<\/li><li>Periodically, this thread calls the <strong>TimeMonitor<\/strong> back at its <strong>tellMeTheTime() <\/strong>method.<\/li><\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"The_TimeClient\"><\/span>The TimeClient<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s the TimeClient:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\npackage rmiClient;\n\nimport java.awt.BorderLayout;\nimport java.awt.event.ActionEvent;\nimport java.awt.event.ActionListener;\nimport java.net.MalformedURLException;\nimport java.rmi.Naming;\nimport java.rmi.NotBoundException;\nimport java.rmi.Remote;\nimport java.rmi.RemoteException;\nimport java.rmi.server.UnicastRemoteObject;\nimport java.util.Date;\nimport javax.swing.JButton;\nimport javax.swing.JFrame;\nimport javax.swing.JPanel;\nimport javax.swing.JScrollPane;\nimport javax.swing.JTextArea;\nimport rmi.Time;\n\nimport rmiServer.TimeServer;\n\n\/**\n * A Time client class\n *\n * @author Bryan Higgs\n * @version 1.0\n *\/\npublic class TimeClient\n    extends JFrame\n{\n  \/**\n   * Creates a new instance of TimeClient\n   *\/\n  public TimeClient()\n  {\n    setDefaultCloseOperation(EXIT_ON_CLOSE);\n    \n    JPanel panel = new JPanel( new BorderLayout() );\n    setContentPane(panel);\n    panel.add( new JScrollPane(m_textArea), BorderLayout.CENTER );\n    \n    JPanel buttonPanel = new JPanel();\n    panel.add(buttonPanel, BorderLayout.SOUTH);\n    buttonPanel.add(m_connectButton);\n    m_connectButton.addActionListener( new ActionListener()\n    {\n      public void actionPerformed(ActionEvent event)\n      {\n        connect();\n      }\n    }\n    );\n    buttonPanel.add(m_clearButton);\n    m_clearButton.addActionListener( new ActionListener()\n    {\n      public void actionPerformed(ActionEvent event)\n      {\n        m_textArea.setText(&quot;&quot;);\n      }\n    }\n    );\n    \n    pack();\n  }\n  \n  \/**\n   * Connect to the time server\n   *\/\n  private void connect()\n  {\n    try\n    {\n      String serverURL = &quot;rmi:\/\/&quot; + HOST + &quot;:&quot; + PORT + &quot;\/TimeServer&quot; ;      \n      System.out.println( &quot;Looking up TimeService at: &quot; + serverURL );\n      Time stub = null;\n      try\n      {\n        stub = (Time) Naming.lookup(serverURL);\n      }\n      catch (NotBoundException nbe)\n      {\n        nbe.printStackTrace();\n      }\n      catch (MalformedURLException mue)\n      {\n        mue.printStackTrace();\n      }\n      \n      System.out.println(&quot;Exporting the TimeMonitor object&quot;);\n      TimeMonitorImpl monitor = new TimeMonitorImpl(m_textArea);\n      UnicastRemoteObject.exportObject(monitor, 0);\n      \n      \/\/ Register the time monitor\n      stub.registerTimeMonitor(monitor);\n      System.out.println(&quot;We are registered!&quot;);\n    }\n    catch ( RemoteException re )\n    {\n      System.out.println( &quot;&quot; + re );\n    }\n  }\n  \n  \/**\n   * Main entry point\n   *\/\n  public static void main(String&#x5B;] args)\n  {\n    System.err.println(&quot;Setting java.security.policy ...&quot;);\n    System.setProperty(&quot;java.security.policy&quot;, &quot;policies\/client.policy&quot;);\n    \n    \/\/ Use a security manager\n    System.err.println(&quot;Setting SecurityManager ...&quot;);\n    System.setSecurityManager( new SecurityManager() );\n    \n    JFrame frame = new TimeClient();\n    frame.setVisible(true);\n  }\n  \n  \/\/\/\/ Private data \/\/\/\/\n  private static final String HOST = &quot;localhost&quot;;\n  private static final int    PORT = 2002;\n  \n  private TimeServer m_server;\n  private JTextArea  m_textArea = new JTextArea(10, 20);\n  private JButton    m_connectButton = new JButton(&quot;Connect&quot;);\n  private JButton    m_clearButton = new JButton(&quot;Clear&quot;);\n}\n\n\/**\n * A Class that implements the TimeMonitor interface\n *\/\nclass TimeMonitorImpl implements TimeMonitor\n{\n  TimeMonitorImpl(JTextArea textArea)\n  {\n    m_textArea = textArea;\n  }\n  \n  \/**\n   * The method to be called back\n   *\/\n  public void tellMeTheTime(Date time)\n  {\n    m_textArea.append(time + &quot;\\n&quot; );\n  }\n\n  \/\/\/ Private data \/\/\/\/\n  private JTextArea m_textArea;\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Note that:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>We must use a security manager and specify a security policy.\u00a0 In this case, the client security policy needed to be:<br><strong>grant <\/strong><br><strong>{<\/strong><br>  <strong> permission java.net.SocketPermission <\/strong><br>      <strong>&#8220;localhost:1024-65535&#8221;, &#8220;connect,accept&#8221;; <\/strong><br>   <strong>permission java.awt.AWTPermission<\/strong><br><strong>      &#8220;showWindowWithoutWarningBanner&#8221;; <\/strong><br><strong>};<\/strong><br><br>That is, we must specify socket connect\u00a0<em>and<\/em>\u00a0access permissions.<br>The second permission suppresses a &#8220;Java Applet Window&#8221; label that is displayed on any part of the GUI.<\/li><li>We must export the class that implements the <strong>TimeMonitor<\/strong> interface, so that it may be called (back).<\/li><\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Running_the_Example-4\"><\/span>Running the Example<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">This time, because we created our own registry, we did not need to run the&nbsp;rmiregistry&nbsp;utility ahead of time.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When you run the <strong>TimeServer<\/strong>, assuming all goes well, you should see something like:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>Setting java.security.policy ...\nSetting SecurityManager ...\nCreating registry...created\n[Re]binding to registry...\nBinding done\nWaiting for Client requests<\/strong><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">When you run the client (or multiple clients), you will see:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>Setting java.security.policy ...\nSetting SecurityManager ...<\/strong><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">and then a window comes up:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"231\" height=\"233\" src=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/02\/RunTime1.jpg\" alt=\"\" class=\"wp-image-538\" srcset=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/02\/RunTime1.jpg 231w, https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/02\/RunTime1-150x150.jpg 150w\" sizes=\"auto, (max-width: 231px) 100vw, 231px\" \/><\/figure><\/div>\n\n\n\n<div style=\"height:20px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">When you click on the Connect button, you should see the following output from the client:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>Looking up TimeService at: rmi:\/\/localhost:2002\/TimeServer\nExporting the TimeMonitor object\nWe are registered!<\/strong><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">and the display should update itself every 2 seconds or so:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"alignleft size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"231\" height=\"233\" src=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/02\/RunTime2.jpg\" alt=\"\" class=\"wp-image-539\" srcset=\"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/02\/RunTime2.jpg 231w, https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-content\/uploads\/2021\/02\/RunTime2-150x150.jpg 150w\" sizes=\"auto, (max-width: 231px) 100vw, 231px\" \/><\/figure><\/div>\n\n\n\n<div style=\"height:15px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">and the server should display:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><strong>Client registering a TimeMonitor\nTimer Started<\/strong><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>What is RMI? It seems that, since I wrote this course back in 2008 or so, things have changed with RMI. For one thing, it seems to have been removed from the Core Java books. By many accounts, while RMI is still around, it is considered obsolete; today, people tend to choose to expose a [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"parent":19,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_eb_attr":"","ocean_front_end_style_editor":"no","ocean_post_layout":"left-sidebar","ocean_both_sidebars_style":"","ocean_both_sidebars_content_width":0,"ocean_both_sidebars_sidebars_width":0,"ocean_sidebar":"ocs-course-topics-sidebar","ocean_second_sidebar":"0","ocean_disable_margins":"enable","ocean_add_body_class":"","ocean_shortcode_before_top_bar":"","ocean_shortcode_after_top_bar":"","ocean_shortcode_before_header":"","ocean_shortcode_after_header":"","ocean_has_shortcode":"","ocean_shortcode_after_title":"","ocean_shortcode_before_footer_widgets":"","ocean_shortcode_after_footer_widgets":"","ocean_shortcode_before_footer_bottom":"","ocean_shortcode_after_footer_bottom":"","ocean_display_top_bar":"default","ocean_display_header":"default","ocean_header_style":"","ocean_center_header_left_menu":"0","ocean_custom_header_template":"0","ocean_custom_logo":0,"ocean_custom_retina_logo":0,"ocean_custom_logo_max_width":0,"ocean_custom_logo_tablet_max_width":0,"ocean_custom_logo_mobile_max_width":0,"ocean_custom_logo_max_height":0,"ocean_custom_logo_tablet_max_height":0,"ocean_custom_logo_mobile_max_height":0,"ocean_header_custom_menu":"0","ocean_menu_typo_font_family":"0","ocean_menu_typo_font_subset":"","ocean_menu_typo_font_size":0,"ocean_menu_typo_font_size_tablet":0,"ocean_menu_typo_font_size_mobile":0,"ocean_menu_typo_font_size_unit":"px","ocean_menu_typo_font_weight":"","ocean_menu_typo_font_weight_tablet":"","ocean_menu_typo_font_weight_mobile":"","ocean_menu_typo_transform":"","ocean_menu_typo_transform_tablet":"","ocean_menu_typo_transform_mobile":"","ocean_menu_typo_line_height":0,"ocean_menu_typo_line_height_tablet":0,"ocean_menu_typo_line_height_mobile":0,"ocean_menu_typo_line_height_unit":"","ocean_menu_typo_spacing":0,"ocean_menu_typo_spacing_tablet":0,"ocean_menu_typo_spacing_mobile":0,"ocean_menu_typo_spacing_unit":"","ocean_menu_link_color":"","ocean_menu_link_color_hover":"","ocean_menu_link_color_active":"","ocean_menu_link_background":"","ocean_menu_link_hover_background":"","ocean_menu_link_active_background":"","ocean_menu_social_links_bg":"","ocean_menu_social_hover_links_bg":"","ocean_menu_social_links_color":"","ocean_menu_social_hover_links_color":"","ocean_disable_title":"default","ocean_disable_heading":"default","ocean_post_title":"","ocean_post_subheading":"","ocean_post_title_style":"","ocean_post_title_background_color":"","ocean_post_title_background":0,"ocean_post_title_bg_image_position":"","ocean_post_title_bg_image_attachment":"","ocean_post_title_bg_image_repeat":"","ocean_post_title_bg_image_size":"","ocean_post_title_height":0,"ocean_post_title_bg_overlay":0.5,"ocean_post_title_bg_overlay_color":"","ocean_disable_breadcrumbs":"default","ocean_breadcrumbs_color":"","ocean_breadcrumbs_separator_color":"","ocean_breadcrumbs_links_color":"","ocean_breadcrumbs_links_hover_color":"","ocean_display_footer_widgets":"default","ocean_display_footer_bottom":"default","ocean_custom_footer_template":"0","footnotes":""},"class_list":["post-498","page","type-page","status-publish","hentry","entry"],"_links":{"self":[{"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/pages\/498","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/comments?post=498"}],"version-history":[{"count":14,"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/pages\/498\/revisions"}],"predecessor-version":[{"id":540,"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/pages\/498\/revisions\/540"}],"up":[{"embeddable":true,"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/pages\/19"}],"wp:attachment":[{"href":"https:\/\/bhiggs.x10hosting.com\/HighOctaneJava\/wp-json\/wp\/v2\/media?parent=498"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}