{"id":1303,"date":"2023-09-10T14:47:17","date_gmt":"2023-09-10T14:47:17","guid":{"rendered":"https:\/\/www.w3computing.com\/articles\/?p=1303"},"modified":"2023-09-10T14:47:24","modified_gmt":"2023-09-10T14:47:24","slug":"java-remote-method-invocation-rmi","status":"publish","type":"post","link":"https:\/\/www.w3computing.com\/articles\/java-remote-method-invocation-rmi\/","title":{"rendered":"Java Remote Method Invocation (RMI)"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p>Java Remote Method Invocation (RMI) is a technology that allows developers to create distributed Java applications where objects on one Java Virtual Machine (JVM) can invoke methods on objects residing in another JVM. RMI forms the backbone of many distributed applications and services in Java. By understanding RMI, you unlock a whole dimension of networking capabilities in the Java world.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What is Java RMI?<\/h3>\n\n\n\n<p>Java RMI, or Remote Method Invocation, is a mechanism provided by the Java programming language that facilitates the communication between objects in different JVMs. Think of it as a way for objects in one Java application to &#8220;talk&#8221; to objects in another application, possibly on a different machine, as if they were local. RMI leverages Java&#8217;s object serialization capabilities to marshal and unmarshal method arguments and results, allowing objects in one JVM to interact seamlessly with objects in another JVM.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Advantages of using RMI<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Transparency<\/strong>: One of the biggest advantages of RMI is its transparency. Developers can invoke methods on remote objects just as they would on local objects. RMI handles the underlying communication transparently.<\/li>\n\n\n\n<li><strong>Object-Oriented<\/strong>: RMI is inherently object-oriented. It doesn&#8217;t just transfer raw data \u2013 it transfers serialized Java objects, retaining their type and behavior. This feature makes it synergize well with Java&#8217;s overall object-oriented paradigm.<\/li>\n\n\n\n<li><strong>Language Specific<\/strong>: Since RMI is specific to Java, it leverages Java\u2019s inherent security and portability features. This means that RMI-based applications can be run on any platform that supports a JVM without any modification.<\/li>\n\n\n\n<li><strong>Garbage Collection<\/strong>: RMI integrates with Java&#8217;s garbage collection to manage the lifecycle of remote objects, ensuring that remote objects are garbage-collected when they are no longer referenced by any client.<\/li>\n\n\n\n<li><strong>Built-in Security<\/strong>: Java RMI can work with Java&#8217;s security managers and policy files, ensuring a secure environment for executing remote calls and protecting sensitive data during transmission.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">RMI Architecture Overview<\/h3>\n\n\n\n<p>At a high level, the RMI architecture consists of three primary layers:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Stub and Skeleton Layer<\/strong>: The client-side stub is responsible for sending the client&#8217;s invocation request to the server and then sending the result back to the client. On the server side, the skeleton receives the client&#8217;s invocation request, delegates the call to the actual remote object, and then sends the result back to the stub.<\/li>\n\n\n\n<li><strong>Remote Reference Layer<\/strong>: This layer deals with the semantics of how references to remote objects are managed. It determines things like whether to create a new remote object or use an existing one, and how to handle garbage collection for remote objects.<\/li>\n\n\n\n<li><strong>Transport Layer<\/strong>: This layer is concerned with setting up connections between client and server, as well as ensuring data transmission occurs reliably and efficiently. It&#8217;s the foundation that allows RMI to work across different network topologies and communication protocols.<\/li>\n<\/ol>\n\n\n\n<p>Each of these layers contributes to the overall functionality and robustness of RMI, ensuring seamless and transparent communication between remote objects.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Setting up CLASSPATH for RMI<\/h2>\n\n\n\n<p>CLASSPATH is an environment variable that tells the Java Virtual Machine (JVM) and the Java compiler where to look for user-defined classes and packages in Java. For RMI, it&#8217;s essential to ensure that your CLASSPATH is correctly set up, especially when dealing with RMI&#8217;s stubs and skeletons.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Locate the RMI Packages<\/strong>: RMI&#8217;s classes are part of the Java standard library, located in the <code>rt.jar<\/code> file inside your JDK&#8217;s <code>jre\/lib<\/code> directory.<\/li>\n\n\n\n<li><strong>Set the CLASSPATH<\/strong>:\n<ul class=\"wp-block-list\">\n<li><strong>Windows<\/strong>:\n<ol class=\"wp-block-list\">\n<li>Right-click on &#8216;My Computer&#8217; or &#8216;This PC&#8217; and select &#8216;Properties&#8217;.<\/li>\n\n\n\n<li>Navigate to the &#8216;Advanced&#8217; tab and click on &#8216;Environment Variables&#8217;.<\/li>\n\n\n\n<li>Under &#8216;System variables&#8217;, click &#8216;New&#8217; and add <code>CLASSPATH<\/code> as the variable name.<\/li>\n\n\n\n<li>For the variable value, enter the path to the <code>jre\/lib<\/code> directory inside your JDK installation, ensuring you include <code>rt.jar<\/code>. It might look like:<br><code>C:\\Program Files\\Java\\jdkx.x.x_x\\jre\\lib\\rt.jar<\/code>.<\/li>\n<\/ol>\n<\/li>\n\n\n\n<li><strong>Linux\/macOS<\/strong>:\n<ol class=\"wp-block-list\">\n<li>Open a terminal.<\/li>\n\n\n\n<li>Add the following line to your <code>.bashrc<\/code>, <code>.bash_profile<\/code>, or <code>.zshrc<\/code> file (based on your shell):<br><code>export CLASSPATH=$CLASSPATH:\/path\/to\/jdk\/jre\/lib\/rt.jar<\/code><br>Replace <code>\/path\/to\/jdk<\/code> with the actual path to your JDK installation.<\/li>\n<\/ol>\n<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Verification<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Open a terminal or command prompt.<\/li>\n\n\n\n<li>Enter <code>echo %CLASSPATH%<\/code> on Windows or <code>echo $CLASSPATH<\/code> on Linux\/macOS.<\/li>\n\n\n\n<li>Ensure that the path to <code>rt.jar<\/code> appears in the output.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Core Components of RMI<\/h2>\n\n\n\n<p>RMI&#8217;s strength lies in its architectural components that facilitate smooth communication between distributed objects. This section delves into the heart of RMI by exploring its core components, focusing on Remote Interfaces and their significance.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Remote Interfaces<\/h3>\n\n\n\n<p>In RMI, a remote interface acts as a contract between the client and the server. It defines which methods a remote object can invoke. Since this interface is shared by both the client and the server, it ensures that both parties understand and adhere to the agreed-upon communication protocols.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Defining a Remote Interface<\/h3>\n\n\n\n<p>To define a remote interface:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>The interface should be public.<\/li>\n\n\n\n<li>It must extend the <code>java.rmi.Remote<\/code> interface.<\/li>\n\n\n\n<li>Each method in this interface should throw a <code>java.rmi.RemoteException<\/code>. This exception caters to the various issues that might arise during remote communication.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Extending the Remote Interface<\/h3>\n\n\n\n<p>While the <code>java.rmi.Remote<\/code> interface is a marker interface (it doesn&#8217;t define any methods), it&#8217;s mandatory for any remote interface to extend it. The reason is to signal to the JVM and the RMI system that the object implementing this interface can be accessed remotely.<\/p>\n\n\n\n<p>Remember, you can also extend other remote interfaces, leading to a hierarchy of remote interfaces. This capability allows you to design complex systems with layered functionalities, all the while maintaining the contractual essence of remote interfaces.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Code Example: Creating a Simple Remote Interface<\/h3>\n\n\n\n<p>Consider a scenario where we want to implement a basic calculator remotely. Here&#8217;s how you&#8217;d define a remote interface for this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-comment\">\/\/ Import required RMI classes<\/span>\r\n<span class=\"hljs-keyword\">import<\/span> java.rmi.Remote;\r\n<span class=\"hljs-keyword\">import<\/span> java.rmi.RemoteException;\r\n\r\n<span class=\"hljs-comment\">\/\/ Define the Remote Interface<\/span>\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">interface<\/span> <span class=\"hljs-title\">Calculator<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Remote<\/span> <\/span>{\r\n\r\n    <span class=\"hljs-comment\">\/\/ Declare remote methods with RemoteException<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">double<\/span> <span class=\"hljs-title\">add<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">double<\/span> a, <span class=\"hljs-keyword\">double<\/span> b)<\/span> <span class=\"hljs-keyword\">throws<\/span> RemoteException<\/span>;\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">double<\/span> <span class=\"hljs-title\">subtract<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">double<\/span> a, <span class=\"hljs-keyword\">double<\/span> b)<\/span> <span class=\"hljs-keyword\">throws<\/span> RemoteException<\/span>;\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">double<\/span> <span class=\"hljs-title\">multiply<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">double<\/span> a, <span class=\"hljs-keyword\">double<\/span> b)<\/span> <span class=\"hljs-keyword\">throws<\/span> RemoteException<\/span>;\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">double<\/span> <span class=\"hljs-title\">divide<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">double<\/span> a, <span class=\"hljs-keyword\">double<\/span> b)<\/span> <span class=\"hljs-keyword\">throws<\/span> RemoteException<\/span>;\r\n\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Here, the <code>Calculator<\/code> interface extends <code>Remote<\/code> and declares four methods corresponding to basic arithmetic operations. Each of these methods can throw a <code>RemoteException<\/code>, signaling potential issues during remote invocation.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Implementing the Remote Object<\/h2>\n\n\n\n<p>Once a remote interface is defined, the next step in the RMI process is to provide an implementation for this interface. The implementation serves as the actual remote object that resides on the server and provides the desired functionality to clients.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Extending <code>UnicastRemoteObject<\/code><\/h3>\n\n\n\n<p>To create a remote object:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Your class should implement the remote interface.<\/li>\n\n\n\n<li>It&#8217;s common practice (though not strictly mandatory with modern RMI) for the implementing class to extend <code>java.rmi.server.UnicastRemoteObject<\/code>. By doing so, you ensure that the remote object inherits certain functionalities necessary for remote method invocation, such as the ability to accept incoming calls from clients.<\/li>\n<\/ol>\n\n\n\n<p>The <code>UnicastRemoteObject<\/code> class provides point-to-point communication with the client and server. It essentially handles the networking aspect of RMI, making remote method invocation possible.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Implementing Remote Methods<\/h3>\n\n\n\n<p>When you implement the remote interface in your class, you&#8217;re required to provide concrete implementations for all of its methods. These methods will execute on the server-side when invoked by a client.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Code Example: Implementing a Remote Object<\/h3>\n\n\n\n<p>Continuing with the <code>Calculator<\/code> example, let&#8217;s implement this remote interface:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-comment\">\/\/ Import required RMI classes<\/span>\r\n<span class=\"hljs-keyword\">import<\/span> java.rmi.RemoteException;\r\n<span class=\"hljs-keyword\">import<\/span> java.rmi.server.UnicastRemoteObject;\r\n\r\n<span class=\"hljs-comment\">\/\/ Implement the Calculator Remote Interface<\/span>\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">CalculatorImpl<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">UnicastRemoteObject<\/span> <span class=\"hljs-keyword\">implements<\/span> <span class=\"hljs-title\">Calculator<\/span> <\/span>{\r\n\r\n    <span class=\"hljs-comment\">\/\/ Constructor<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">protected<\/span> <span class=\"hljs-title\">CalculatorImpl<\/span><span class=\"hljs-params\">()<\/span> <span class=\"hljs-keyword\">throws<\/span> RemoteException <\/span>{\r\n        <span class=\"hljs-keyword\">super<\/span>();\r\n    }\r\n\r\n    <span class=\"hljs-comment\">\/\/ Implement the add method<\/span>\r\n    <span class=\"hljs-meta\">@Override<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">double<\/span> <span class=\"hljs-title\">add<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">double<\/span> a, <span class=\"hljs-keyword\">double<\/span> b)<\/span> <span class=\"hljs-keyword\">throws<\/span> RemoteException <\/span>{\r\n        <span class=\"hljs-keyword\">return<\/span> a + b;\r\n    }\r\n\r\n    <span class=\"hljs-comment\">\/\/ Implement the subtract method<\/span>\r\n    <span class=\"hljs-meta\">@Override<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">double<\/span> <span class=\"hljs-title\">subtract<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">double<\/span> a, <span class=\"hljs-keyword\">double<\/span> b)<\/span> <span class=\"hljs-keyword\">throws<\/span> RemoteException <\/span>{\r\n        <span class=\"hljs-keyword\">return<\/span> a - b;\r\n    }\r\n\r\n    <span class=\"hljs-comment\">\/\/ Implement the multiply method<\/span>\r\n    <span class=\"hljs-meta\">@Override<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">double<\/span> <span class=\"hljs-title\">multiply<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">double<\/span> a, <span class=\"hljs-keyword\">double<\/span> b)<\/span> <span class=\"hljs-keyword\">throws<\/span> RemoteException <\/span>{\r\n        <span class=\"hljs-keyword\">return<\/span> a * b;\r\n    }\r\n\r\n    <span class=\"hljs-comment\">\/\/ Implement the divide method<\/span>\r\n    <span class=\"hljs-meta\">@Override<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">double<\/span> <span class=\"hljs-title\">divide<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">double<\/span> a, <span class=\"hljs-keyword\">double<\/span> b)<\/span> <span class=\"hljs-keyword\">throws<\/span> RemoteException <\/span>{\r\n        <span class=\"hljs-keyword\">if<\/span>(b == <span class=\"hljs-number\">0<\/span>) {\r\n            <span class=\"hljs-keyword\">throw<\/span> <span class=\"hljs-keyword\">new<\/span> ArithmeticException(<span class=\"hljs-string\">\"Division by zero is not allowed!\"<\/span>);\r\n        }\r\n        <span class=\"hljs-keyword\">return<\/span> a \/ b;\r\n    }\r\n\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In this implementation, the <code>CalculatorImpl<\/code> class extends <code>UnicastRemoteObject<\/code> and implements the <code>Calculator<\/code> remote interface. Each method from the interface is then given a concrete implementation, allowing clients to perform basic arithmetic operations.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">RMI Registry<\/h2>\n\n\n\n<p>A critical component in the RMI ecosystem is the RMI registry\u2014a simple server-side naming facility that allows clients to get a reference to a remote object. Without the registry, clients wouldn&#8217;t know where or how to find the remote objects they wish to communicate with.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The role of the RMI registry<\/h3>\n\n\n\n<p>The RMI registry plays several pivotal roles:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Discovery<\/strong>: It allows clients to discover available remote objects using simple string names.<\/li>\n\n\n\n<li><strong>Binding<\/strong>: Remote objects can be associated (or &#8220;bound&#8221;) with names, allowing them to be easily discovered and accessed by clients.<\/li>\n\n\n\n<li><strong>Centralization<\/strong>: It acts as a centralized service on the server for all the exported remote objects, simplifying the process of remote object management and access.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Starting the RMI registry<\/h3>\n\n\n\n<p>Before you can register remote objects, you need to start the RMI registry. This can be done in two primary ways:<\/p>\n\n\n\n<p><strong>Command-Line Tool<\/strong>: Use the <code>rmiregistry<\/code> tool included with the JDK.<\/p>\n\n\n\n<p>Navigate to the directory containing your compiled remote objects (<code>.class<\/code> files).<\/p>\n\n\n\n<p>Run the command:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">rmiregistry &#91;port]<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Replace <code>[port]<\/code> with the port number you want the registry to listen on (default is 1099).<\/p>\n\n\n\n<p><strong>Programmatically<\/strong>: Use Java&#8217;s built-in <code>LocateRegistry<\/code> class.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">import java.rmi.registry.LocateRegistry;\r\n\r\npublic class StartRegistry {\r\n    public static void main(String&#91;] args) {\r\n        try {\r\n            LocateRegistry.createRegistry(1099);\r\n            System.out.println(<span class=\"hljs-string\">\"RMI registry started on port 1099\"<\/span>);\r\n        } catch (RemoteException e) {\r\n            e.printStackTrace();\r\n        }\r\n    }\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Registering Remote Objects<\/h3>\n\n\n\n<p>Once the RMI registry is running, remote objects can be registered (or &#8220;bound&#8221;) to it using a unique name. This name is later used by clients to get a reference to the remote object.<\/p>\n\n\n\n<p>You generally use the <code>rebind<\/code> method from the <code>Naming<\/code> class to bind or replace an existing binding. Alternatively, use <code>bind<\/code> to set a new binding, but be cautious as it will throw an exception if a binding with the same name already exists.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Code Example: Registering and Locating Remote Objects<\/h3>\n\n\n\n<p>Using the <code>CalculatorImpl<\/code> class from the previous example:<\/p>\n\n\n\n<p>javaCopy code<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">import<\/span> java.rmi.Naming;\r\n<span class=\"hljs-keyword\">import<\/span> java.rmi.RemoteException;\r\n<span class=\"hljs-keyword\">import<\/span> java.rmi.registry.LocateRegistry;\r\n\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Server<\/span> <\/span>{\r\n\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">main<\/span><span class=\"hljs-params\">(String&#91;] args)<\/span> <\/span>{\r\n        <span class=\"hljs-keyword\">try<\/span> {\r\n            <span class=\"hljs-comment\">\/\/ Start the RMI registry programmatically (alternatively, you can start it via command line)<\/span>\r\n            LocateRegistry.createRegistry(<span class=\"hljs-number\">1099<\/span>);\r\n            \r\n            <span class=\"hljs-comment\">\/\/ Create an instance of the remote object<\/span>\r\n            CalculatorImpl calculator = <span class=\"hljs-keyword\">new<\/span> CalculatorImpl();\r\n            \r\n            <span class=\"hljs-comment\">\/\/ Bind the remote object to a name in the RMI registry<\/span>\r\n            Naming.rebind(<span class=\"hljs-string\">\"CalculatorService\"<\/span>, calculator);\r\n            System.out.println(<span class=\"hljs-string\">\"Calculator Service is ready and waiting for client requests.\"<\/span>);\r\n            \r\n        } <span class=\"hljs-keyword\">catch<\/span> (Exception e) {\r\n            e.printStackTrace();\r\n        }\r\n    }\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>A client can then locate and communicate with this remote object as follows:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">import<\/span> java.rmi.Naming;\r\n\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Client<\/span> <\/span>{\r\n\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">main<\/span><span class=\"hljs-params\">(String&#91;] args)<\/span> <\/span>{\r\n        <span class=\"hljs-keyword\">try<\/span> {\r\n            <span class=\"hljs-comment\">\/\/ Locate the remote object using its name<\/span>\r\n            Calculator calculator = (Calculator) Naming.lookup(<span class=\"hljs-string\">\"rmi:\/\/localhost\/CalculatorService\"<\/span>);\r\n            \r\n            <span class=\"hljs-comment\">\/\/ Invoke methods on the remote object<\/span>\r\n            <span class=\"hljs-keyword\">double<\/span> result = calculator.add(<span class=\"hljs-number\">5<\/span>, <span class=\"hljs-number\">3<\/span>);\r\n            System.out.println(<span class=\"hljs-string\">\"Result of 5 + 3 = \"<\/span> + result);\r\n            \r\n        } <span class=\"hljs-keyword\">catch<\/span> (Exception e) {\r\n            e.printStackTrace();\r\n        }\r\n    }\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Developing the RMI Client<\/h2>\n\n\n\n<p>Once the server-side components are set up, crafting the RMI client is the next essential step. The client&#8217;s primary role is to locate the remote object, invoke methods on it, and manage any potential exceptions during these interactions.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Looking up Remote Objects<\/h3>\n\n\n\n<p>The first task a client has is to locate the desired remote object. This is done using the RMI registry, which keeps references to all registered remote objects. The <code>Naming.lookup<\/code> method is commonly employed for this purpose, passing in the URL of the remote object.<\/p>\n\n\n\n<p>The general format of the lookup URL is:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\">rmi:<span class=\"hljs-comment\">\/\/&#91;hostname]\/&#91;remoteObjectName]<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Invoking Methods on Remote Objects<\/h3>\n\n\n\n<p>After obtaining a reference to a remote object, the client can invoke methods on it just like they would on a local object. The only distinction is that these method invocations occur over the network, and the results (or exceptions) are transmitted back to the client.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Handling Remote Exceptions<\/h3>\n\n\n\n<p>Remote method invocations can throw a <code>RemoteException<\/code>, which encapsulates various issues that might arise during remote communication. It&#8217;s vital for clients to handle this exception gracefully to ensure a smooth user experience.<\/p>\n\n\n\n<p>When a <code>RemoteException<\/code> occurs, it&#8217;s a good practice to:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Log the error details for debugging.<\/li>\n\n\n\n<li>Provide a user-friendly message to the end-user.<\/li>\n\n\n\n<li>Consider a retry mechanism, depending on the nature of the operation.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Code Example: Developing a Simple RMI Client<\/h3>\n\n\n\n<p>Building on our calculator example:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">import<\/span> java.rmi.Naming;\r\n<span class=\"hljs-keyword\">import<\/span> java.rmi.RemoteException;\r\n\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">CalculatorClient<\/span> <\/span>{\r\n\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">main<\/span><span class=\"hljs-params\">(String&#91;] args)<\/span> <\/span>{\r\n        <span class=\"hljs-keyword\">try<\/span> {\r\n            <span class=\"hljs-comment\">\/\/ 1. Locate the remote object using its name<\/span>\r\n            Calculator calculator = (Calculator) Naming.lookup(<span class=\"hljs-string\">\"rmi:\/\/localhost\/CalculatorService\"<\/span>);\r\n            \r\n            <span class=\"hljs-comment\">\/\/ 2. Invoke methods on the remote object<\/span>\r\n            <span class=\"hljs-keyword\">double<\/span> sum = calculator.add(<span class=\"hljs-number\">5<\/span>, <span class=\"hljs-number\">3<\/span>);\r\n            System.out.println(<span class=\"hljs-string\">\"Result of 5 + 3 = \"<\/span> + sum);\r\n            \r\n            <span class=\"hljs-keyword\">double<\/span> product = calculator.multiply(<span class=\"hljs-number\">5<\/span>, <span class=\"hljs-number\">3<\/span>);\r\n            System.out.println(<span class=\"hljs-string\">\"Result of 5 x 3 = \"<\/span> + product);\r\n\r\n        } <span class=\"hljs-keyword\">catch<\/span> (RemoteException e) {\r\n            <span class=\"hljs-comment\">\/\/ 3. Handle RemoteException<\/span>\r\n            System.err.println(<span class=\"hljs-string\">\"Remote computation failed.\"<\/span>);\r\n            e.printStackTrace();\r\n        } <span class=\"hljs-keyword\">catch<\/span> (Exception e) {\r\n            System.err.println(<span class=\"hljs-string\">\"General exception: \"<\/span> + e.toString());\r\n            e.printStackTrace();\r\n        }\r\n    }\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In this client application:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The client locates the <code>CalculatorService<\/code> remote object using its URL.<\/li>\n\n\n\n<li>It then invokes the <code>add<\/code> and <code>multiply<\/code> methods on this remote object.<\/li>\n\n\n\n<li>Any exceptions that might arise during this process are caught and handled appropriately.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">RMI Under the Hood<\/h2>\n\n\n\n<p>While users of RMI might often remain shielded from the intricate details of its inner workings, understanding these mechanisms provides a richer perspective and better problem-solving capabilities. In this section, we delve deeper into the underpinnings of RMI.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Stub and Skeleton Layers<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Stub<\/strong>:\n<ul class=\"wp-block-list\">\n<li>The stub is a client-side proxy for the remote object. When the client invokes a method on the stub, it feels like a regular local method call. But in reality, the stub is responsible for forwarding this invocation request to the server&#8217;s remote object.<\/li>\n\n\n\n<li>The stub marshals (i.e., packages) the method parameters into a format suitable for transport to the server, typically using Java&#8217;s serialization mechanism.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Skeleton<\/strong>:\n<ul class=\"wp-block-list\">\n<li>Earlier versions of RMI used skeletons on the server side, which acted as counterparts to the stubs. The skeleton was responsible for unmarshalling the client&#8217;s request, invoking the desired method on the actual remote object, and then marshaling the result (or exception) back to the client stub.<\/li>\n\n\n\n<li>However, with modern versions of RMI, the skeleton&#8217;s role is handled by the RMI runtime itself, and explicit skeleton classes aren&#8217;t typically used or required.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Dynamic Class Loading<\/h3>\n\n\n\n<p>Dynamic class loading is a powerful feature in RMI that can be both an advantage and a challenge:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Advantage<\/strong>: When a client receives a serialized object from the server, and if the client doesn&#8217;t have the class definition for that object, RMI can automatically download the required class files from the server. This dynamic, on-the-fly class loading can greatly simplify deployment and versioning.<\/li>\n\n\n\n<li><strong>Challenge<\/strong>: Dynamic class loading, if not managed correctly, can pose security risks. For instance, a malicious server might send bytecode that can harm the client. Hence, it&#8217;s essential to secure and, if needed, restrict dynamic class loading.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">RMI Transport Layer<\/h3>\n\n\n\n<p>RMI&#8217;s transport layer takes care of the actual network communication between client stubs and server remote objects:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Connections<\/strong>: By default, RMI uses a reusable connection pool. When a stub makes a remote call, it might reuse an existing connection or establish a new one, depending on availability.<\/li>\n\n\n\n<li><strong>Java Remote Reference Layer<\/strong>: This layer translates and manages references made from clients to remote objects, ensuring the correct server-side instance is invoked.<\/li>\n\n\n\n<li><strong>Garbage Collection<\/strong>: RMI includes a distributed garbage collection mechanism. A reference-counting approach ensures that a remote object is not garbage collected as long as any client holds a reference to it.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Enhancing RMI Applications<\/h2>\n\n\n\n<p>RMI&#8217;s core features are often sufficient for many distributed applications. However, as requirements grow more complex, enhancements such as callbacks can make a significant difference, allowing for more interactive and dynamic behavior between clients and servers.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Implementing Callback Mechanisms<\/h3>\n\n\n\n<p>In a typical RMI interaction, the client initiates communication by invoking methods on the remote object. But what if the server needs to notify the client or send data without waiting for a client request? This is where callbacks come in. By implementing callbacks, you enable bi-directional communication\u2014i.e., the server can &#8220;call back&#8221; the client when necessary.<\/p>\n\n\n\n<p>To achieve this:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Client-side Remote Interface<\/strong>: The client needs to provide an interface and its implementation, which the server can call upon. This interface is just like any RMI remote interface and must be known to both the client and server.<\/li>\n\n\n\n<li><strong>Registering with the Server<\/strong>: When the client starts, it registers its callback object with the server. Now, the server holds a reference to this object and can invoke methods on it whenever required.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">Code Example: Callback in RMI<\/h4>\n\n\n\n<p>Let&#8217;s illustrate this with an example. Imagine a server that alerts registered clients about certain events:<\/p>\n\n\n\n<p><strong>Client-side Remote Interface<\/strong>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-comment\">\/\/ AlertListener.java<\/span>\r\n<span class=\"hljs-keyword\">import<\/span> java.rmi.Remote;\r\n<span class=\"hljs-keyword\">import<\/span> java.rmi.RemoteException;\r\n\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">interface<\/span> <span class=\"hljs-title\">AlertListener<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Remote<\/span> <\/span>{\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">alert<\/span><span class=\"hljs-params\">(String message)<\/span> <span class=\"hljs-keyword\">throws<\/span> RemoteException<\/span>;\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Client&#8217;s implementation:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-comment\">\/\/ ClientAlertImpl.java<\/span>\r\n<span class=\"hljs-keyword\">import<\/span> java.rmi.server.UnicastRemoteObject;\r\n<span class=\"hljs-keyword\">import<\/span> java.rmi.RemoteException;\r\n\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">ClientAlertImpl<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">UnicastRemoteObject<\/span> <span class=\"hljs-keyword\">implements<\/span> <span class=\"hljs-title\">AlertListener<\/span> <\/span>{\r\n\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">ClientAlertImpl<\/span><span class=\"hljs-params\">()<\/span> <span class=\"hljs-keyword\">throws<\/span> RemoteException <\/span>{}\r\n\r\n    <span class=\"hljs-meta\">@Override<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">alert<\/span><span class=\"hljs-params\">(String message)<\/span> <\/span>{\r\n        System.out.println(<span class=\"hljs-string\">\"Received server alert: \"<\/span> + message);\r\n    }\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><strong>Server side<\/strong>:<\/p>\n\n\n\n<p>Suppose the server provides a method to register client listeners:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-comment\">\/\/ AlertServer.java<\/span>\r\n<span class=\"hljs-keyword\">import<\/span> java.rmi.Remote;\r\n<span class=\"hljs-keyword\">import<\/span> java.rmi.RemoteException;\r\n\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">interface<\/span> <span class=\"hljs-title\">AlertServer<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Remote<\/span> <\/span>{\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">registerAlertListener<\/span><span class=\"hljs-params\">(AlertListener listener)<\/span> <span class=\"hljs-keyword\">throws<\/span> RemoteException<\/span>;\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Server&#8217;s implementation:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-comment\">\/\/ AlertServerImpl.java<\/span>\r\n<span class=\"hljs-keyword\">import<\/span> java.rmi.server.UnicastRemoteObject;\r\n<span class=\"hljs-keyword\">import<\/span> java.rmi.RemoteException;\r\n<span class=\"hljs-keyword\">import<\/span> java.util.ArrayList;\r\n<span class=\"hljs-keyword\">import<\/span> java.util.List;\r\n\r\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">AlertServerImpl<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">UnicastRemoteObject<\/span> <span class=\"hljs-keyword\">implements<\/span> <span class=\"hljs-title\">AlertServer<\/span> <\/span>{\r\n    <span class=\"hljs-keyword\">private<\/span> List&lt;AlertListener&gt; listeners;\r\n\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">AlertServerImpl<\/span><span class=\"hljs-params\">()<\/span> <span class=\"hljs-keyword\">throws<\/span> RemoteException <\/span>{\r\n        listeners = <span class=\"hljs-keyword\">new<\/span> ArrayList&lt;&gt;();\r\n    }\r\n\r\n    <span class=\"hljs-meta\">@Override<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">registerAlertListener<\/span><span class=\"hljs-params\">(AlertListener listener)<\/span> <\/span>{\r\n        listeners.add(listener);\r\n    }\r\n\r\n    <span class=\"hljs-comment\">\/\/ Sample method to simulate triggering alerts<\/span>\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">triggerAlert<\/span><span class=\"hljs-params\">(String message)<\/span> <\/span>{\r\n        <span class=\"hljs-keyword\">for<\/span> (AlertListener listener : listeners) {\r\n            <span class=\"hljs-keyword\">try<\/span> {\r\n                listener.alert(message);\r\n            } <span class=\"hljs-keyword\">catch<\/span> (RemoteException e) {\r\n                e.printStackTrace();\r\n            }\r\n        }\r\n    }\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>When the server invokes the <code>triggerAlert<\/code> method, all registered clients receive the alert message via their implemented <code>alert<\/code> method.<\/p>\n\n\n\n<p>Callbacks in RMI enable a more reactive model, allowing servers to communicate with clients proactively. This capability can be particularly useful in applications like chat systems, event notification systems, and real-time monitoring tools.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">RMI with Java Security Manager<\/h3>\n\n\n\n<p>RMI applications, especially with dynamic class loading, have inherent security risks. Malicious code could potentially be loaded and executed, compromising the integrity of your application. To mitigate these risks, it&#8217;s crucial to integrate RMI applications with the Java Security Manager, which allows you to specify detailed security policies and control the execution environment.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Setting up the Security Policy<\/h4>\n\n\n\n<p>Java&#8217;s security policy mechanism lets you define permissions for different code sources. For RMI:<\/p>\n\n\n\n<p><strong>Create a security policy file<\/strong>: This file will specify the permissions. Here&#8217;s an example policy for an RMI server:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\">grant codeBase <span class=\"hljs-string\">\"file:\/path\/to\/your\/classes\/\"<\/span> {\r\n    <span class=\"hljs-comment\">\/\/ Allow everything within this codebase<\/span>\r\n    permission java.security.AllPermission;\r\n};\r\n\r\ngrant codeBase <span class=\"hljs-string\">\"file:\/path\/to\/rmi\/registry\/\"<\/span> {\r\n    <span class=\"hljs-comment\">\/\/ Permissions for RMI registry<\/span>\r\n    permission java.rmi.RuntimePermission <span class=\"hljs-string\">\"createRegistry\"<\/span>;\r\n    permission java.rmi.RuntimePermission <span class=\"hljs-string\">\"useRegistry\"<\/span>;\r\n};\r\n\r\ngrant {\r\n    <span class=\"hljs-comment\">\/\/ Minimal permissions for other code (including dynamically loaded classes)<\/span>\r\n    permission java.net.SocketPermission <span class=\"hljs-string\">\"*:1024-65535\"<\/span>, <span class=\"hljs-string\">\"connect,accept\"<\/span>;\r\n    permission java.net.SocketPermission <span class=\"hljs-string\">\"*:80\"<\/span>, <span class=\"hljs-string\">\"connect\"<\/span>;\r\n};<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><strong>Apply the policy file<\/strong>: When starting your RMI application (client or server), provide the policy file using the JVM argument:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"plaintext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">-Djava.security.policy=path_to_policy_file<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">plaintext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h4 class=\"wp-block-heading\">Code Example: Secured RMI Application<\/h4>\n\n\n\n<p>For this example, let&#8217;s secure our previous <code>AlertServer<\/code>:<\/p>\n\n\n\n<p><strong>Set up the Security Manager in your application<\/strong>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">AlertServerMain<\/span> <\/span>{\r\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">main<\/span><span class=\"hljs-params\">(String&#91;] args)<\/span> <\/span>{\r\n        <span class=\"hljs-comment\">\/\/ Set the security manager<\/span>\r\n        <span class=\"hljs-keyword\">if<\/span> (System.getSecurityManager() == <span class=\"hljs-keyword\">null<\/span>) {\r\n            System.setSecurityManager(<span class=\"hljs-keyword\">new<\/span> SecurityManager());\r\n        }\r\n\r\n        <span class=\"hljs-keyword\">try<\/span> {\r\n            AlertServerImpl server = <span class=\"hljs-keyword\">new<\/span> AlertServerImpl();\r\n            Naming.rebind(<span class=\"hljs-string\">\"rmi:\/\/localhost\/AlertServerService\"<\/span>, server);\r\n            System.out.println(<span class=\"hljs-string\">\"Server started and waiting for connections...\"<\/span>);\r\n        } <span class=\"hljs-keyword\">catch<\/span> (Exception e) {\r\n            e.printStackTrace();\r\n        }\r\n    }\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><strong>Running the Secured Application<\/strong>:<\/p>\n\n\n\n<p>Before starting the server, ensure that you have a policy file that grants the necessary permissions.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">java -Djava.security.policy=server.policy AlertServerMain<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In the example above, we&#8217;ve added a security manager to the server&#8217;s main class. When the server starts, it will adhere to the permissions defined in the <code>server.policy<\/code> file.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Troubleshooting Common RMI Issues<\/h2>\n\n\n\n<p>RMI, while powerful, can occasionally present challenges, especially when deploying or modifying distributed applications. Understanding common pitfalls and their resolutions can save developers valuable time and frustration.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">ClassNotfoundException: Stub Classes<\/h3>\n\n\n\n<p><strong>Problem<\/strong>: When trying to bind or look up a remote object, you might encounter a <code>ClassNotFoundException<\/code> related to the stub class.<\/p>\n\n\n\n<p><strong>Cause<\/strong>: This usually arises because the stub class hasn&#8217;t been generated or isn&#8217;t available in the CLASSPATH.<\/p>\n\n\n\n<p><strong>Solution<\/strong>:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Ensure you&#8217;ve generated the stub class using the <code>rmic<\/code> tool.<\/li>\n\n\n\n<li>Confirm the generated stub class is in the CLASSPATH of both the client and server.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">RMI Connection Refusals<\/h3>\n\n\n\n<p><strong>Problem<\/strong>: When trying to connect to an RMI server, you might receive a &#8220;Connection Refused&#8221; error.<\/p>\n\n\n\n<p><strong>Cause<\/strong>:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>The RMI registry isn&#8217;t running.<\/li>\n\n\n\n<li>Wrong hostname or port number provided.<\/li>\n\n\n\n<li>Network issues, such as firewalls blocking the RMI port.<\/li>\n<\/ol>\n\n\n\n<p><strong>Solution<\/strong>:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Check if the RMI registry is active using tools like <code>ps<\/code> (on Unix-like systems) or Task Manager (on Windows).<\/li>\n\n\n\n<li>Ensure you&#8217;re using the correct hostname and port number. By default, RMI uses port <code>1099<\/code>.<\/li>\n\n\n\n<li>Check network configurations, ensuring firewalls or security groups allow traffic on the RMI port.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Remote Exceptions During Lookup<\/h3>\n\n\n\n<p><strong>Problem<\/strong>: When attempting to look up a remote object using its name, you might encounter a <code>RemoteException<\/code>.<\/p>\n\n\n\n<p><strong>Cause<\/strong>:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>The remote object isn&#8217;t bound to the name you&#8217;re trying to look up.<\/li>\n\n\n\n<li>The RMI server or registry has crashed or been restarted, causing remote references to become stale.<\/li>\n\n\n\n<li>Network issues causing packet loss or disruptions.<\/li>\n<\/ol>\n\n\n\n<p><strong>Solution<\/strong>:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Double-check the name used to bind the remote object and ensure it matches the lookup name.<\/li>\n\n\n\n<li>If the RMI server or registry was restarted, reinitialize the client to obtain fresh remote references.<\/li>\n\n\n\n<li>Test the network connectivity between the client and server, checking for any potential issues.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Best Practices for RMI Development<\/h2>\n\n\n\n<p>While Java RMI offers a powerful framework for building distributed applications, adhering to best practices ensures that these applications are robust, scalable, and maintainable.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Versioning for RMI Interfaces<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Why it Matters<\/strong>: As your application evolves, so will the methods and behaviors of your remote objects. Without versioning, you risk breaking backward compatibility.<\/li>\n\n\n\n<li><strong>Practice<\/strong>: Whenever you modify a remote interface, create a new version instead of modifying the existing one. Also, utilize the <code>serialVersionUID<\/code> to keep track of different versions and maintain compatibility.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Using Proper Exception Handling<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Why it Matters<\/strong>: RMI applications inherently involve network communication, which can lead to many unexpected scenarios like connection loss, timeouts, or data issues.<\/li>\n\n\n\n<li><strong>Practice<\/strong>: Always anticipate and handle <code>RemoteException<\/code> and its subtypes. This ensures that your application remains responsive and user-friendly even when unexpected issues occur.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Limiting Remote Object Lifespan<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Why it Matters<\/strong>: Long-lived remote objects can consume resources and might lead to memory leaks if not properly managed.<\/li>\n\n\n\n<li><strong>Practice<\/strong>: Whenever possible, use short-lived, stateless remote objects. If a remote object must maintain state, ensure there&#8217;s a mechanism to clean it up, either through a timeout or by explicitly removing it once it&#8217;s no longer needed.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Using Java&#8217;s Naming Service for Scalability<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Why it Matters<\/strong>: For smaller applications, binding remote objects by name might suffice. However, as applications scale, a more dynamic and scalable mechanism for naming and directory services becomes necessary.<\/li>\n\n\n\n<li><strong>Practice<\/strong>: Instead of relying solely on RMI&#8217;s naming, consider using Java&#8217;s JNDI (Java Naming and Directory Interface). JNDI provides a more flexible naming and directory service, supporting a variety of backends and allowing for more complex, hierarchical namespaces.<\/li>\n<\/ul>\n\n\n\n<p>Adhering to best practices in RMI development ensures that your distributed applications not only function efficiently but also scale well and are easier to maintain. As with any development paradigm, the key is to anticipate challenges, plan for change, and ensure that your solutions are robust and adaptable.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction Java Remote Method Invocation (RMI) is a technology that allows developers to create distributed Java applications where objects on one Java Virtual Machine (JVM) can invoke methods on objects residing in another JVM. RMI forms the backbone of many distributed applications and services in Java. By understanding RMI, you unlock a whole dimension of [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_genesis_hide_title":false,"_genesis_hide_breadcrumbs":false,"_genesis_hide_singular_image":false,"_genesis_hide_footer_widgets":false,"_genesis_custom_body_class":"","_genesis_custom_post_class":"","_genesis_layout":"","_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[5,4],"tags":[],"class_list":{"0":"post-1303","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-java","7":"category-programming-languages","8":"entry"},"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Java Remote Method Invocation (RMI)<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.w3computing.com\/articles\/java-remote-method-invocation-rmi\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Java Remote Method Invocation (RMI)\" \/>\n<meta property=\"og:description\" content=\"Introduction Java Remote Method Invocation (RMI) is a technology that allows developers to create distributed Java applications where objects on one Java Virtual Machine (JVM) can invoke methods on objects residing in another JVM. RMI forms the backbone of many distributed applications and services in Java. By understanding RMI, you unlock a whole dimension of [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.w3computing.com\/articles\/java-remote-method-invocation-rmi\/\" \/>\n<meta property=\"article:published_time\" content=\"2023-09-10T14:47:17+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-09-10T14:47:24+00:00\" \/>\n<meta name=\"author\" content=\"w3compadmin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"w3compadmin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"20 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"TechArticle\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/java-remote-method-invocation-rmi\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/java-remote-method-invocation-rmi\\\/\"},\"author\":{\"name\":\"w3compadmin\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#\\\/schema\\\/person\\\/a550b3e20d78bb4f79b7c6b7b53f0561\"},\"headline\":\"Java Remote Method Invocation (RMI)\",\"datePublished\":\"2023-09-10T14:47:17+00:00\",\"dateModified\":\"2023-09-10T14:47:24+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/java-remote-method-invocation-rmi\\\/\"},\"wordCount\":3184,\"commentCount\":0,\"articleSection\":[\"Java\",\"Programming Languages\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/java-remote-method-invocation-rmi\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/java-remote-method-invocation-rmi\\\/\",\"url\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/java-remote-method-invocation-rmi\\\/\",\"name\":\"Java Remote Method Invocation (RMI)\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#website\"},\"datePublished\":\"2023-09-10T14:47:17+00:00\",\"dateModified\":\"2023-09-10T14:47:24+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#\\\/schema\\\/person\\\/a550b3e20d78bb4f79b7c6b7b53f0561\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/java-remote-method-invocation-rmi\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/java-remote-method-invocation-rmi\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/java-remote-method-invocation-rmi\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Articles Home\",\"item\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Programming Languages\",\"item\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/programming-languages\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/programming-languages\\\/java\\\/\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Java Remote Method Invocation (RMI)\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#website\",\"url\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/\",\"name\":\"Developer Articles Hub\",\"description\":\"\",\"alternateName\":\"Developer Articles\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/#\\\/schema\\\/person\\\/a550b3e20d78bb4f79b7c6b7b53f0561\",\"name\":\"w3compadmin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/wp-content\\\/litespeed\\\/avatar\\\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1776115684\",\"url\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/wp-content\\\/litespeed\\\/avatar\\\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1776115684\",\"contentUrl\":\"https:\\\/\\\/www.w3computing.com\\\/articles\\\/wp-content\\\/litespeed\\\/avatar\\\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1776115684\",\"caption\":\"w3compadmin\"},\"sameAs\":[\"http:\\\/\\\/w3computing.com\\\/articles\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Java Remote Method Invocation (RMI)","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.w3computing.com\/articles\/java-remote-method-invocation-rmi\/","og_locale":"en_US","og_type":"article","og_title":"Java Remote Method Invocation (RMI)","og_description":"Introduction Java Remote Method Invocation (RMI) is a technology that allows developers to create distributed Java applications where objects on one Java Virtual Machine (JVM) can invoke methods on objects residing in another JVM. RMI forms the backbone of many distributed applications and services in Java. By understanding RMI, you unlock a whole dimension of [&hellip;]","og_url":"https:\/\/www.w3computing.com\/articles\/java-remote-method-invocation-rmi\/","article_published_time":"2023-09-10T14:47:17+00:00","article_modified_time":"2023-09-10T14:47:24+00:00","author":"w3compadmin","twitter_card":"summary_large_image","twitter_misc":{"Written by":"w3compadmin","Est. reading time":"20 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"TechArticle","@id":"https:\/\/www.w3computing.com\/articles\/java-remote-method-invocation-rmi\/#article","isPartOf":{"@id":"https:\/\/www.w3computing.com\/articles\/java-remote-method-invocation-rmi\/"},"author":{"name":"w3compadmin","@id":"https:\/\/www.w3computing.com\/articles\/#\/schema\/person\/a550b3e20d78bb4f79b7c6b7b53f0561"},"headline":"Java Remote Method Invocation (RMI)","datePublished":"2023-09-10T14:47:17+00:00","dateModified":"2023-09-10T14:47:24+00:00","mainEntityOfPage":{"@id":"https:\/\/www.w3computing.com\/articles\/java-remote-method-invocation-rmi\/"},"wordCount":3184,"commentCount":0,"articleSection":["Java","Programming Languages"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.w3computing.com\/articles\/java-remote-method-invocation-rmi\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.w3computing.com\/articles\/java-remote-method-invocation-rmi\/","url":"https:\/\/www.w3computing.com\/articles\/java-remote-method-invocation-rmi\/","name":"Java Remote Method Invocation (RMI)","isPartOf":{"@id":"https:\/\/www.w3computing.com\/articles\/#website"},"datePublished":"2023-09-10T14:47:17+00:00","dateModified":"2023-09-10T14:47:24+00:00","author":{"@id":"https:\/\/www.w3computing.com\/articles\/#\/schema\/person\/a550b3e20d78bb4f79b7c6b7b53f0561"},"breadcrumb":{"@id":"https:\/\/www.w3computing.com\/articles\/java-remote-method-invocation-rmi\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.w3computing.com\/articles\/java-remote-method-invocation-rmi\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.w3computing.com\/articles\/java-remote-method-invocation-rmi\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Articles Home","item":"https:\/\/www.w3computing.com\/articles\/"},{"@type":"ListItem","position":2,"name":"Programming Languages","item":"https:\/\/www.w3computing.com\/articles\/programming-languages\/"},{"@type":"ListItem","position":3,"name":"Java","item":"https:\/\/www.w3computing.com\/articles\/programming-languages\/java\/"},{"@type":"ListItem","position":4,"name":"Java Remote Method Invocation (RMI)"}]},{"@type":"WebSite","@id":"https:\/\/www.w3computing.com\/articles\/#website","url":"https:\/\/www.w3computing.com\/articles\/","name":"Developer Articles Hub","description":"","alternateName":"Developer Articles","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.w3computing.com\/articles\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.w3computing.com\/articles\/#\/schema\/person\/a550b3e20d78bb4f79b7c6b7b53f0561","name":"w3compadmin","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.w3computing.com\/articles\/wp-content\/litespeed\/avatar\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1776115684","url":"https:\/\/www.w3computing.com\/articles\/wp-content\/litespeed\/avatar\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1776115684","contentUrl":"https:\/\/www.w3computing.com\/articles\/wp-content\/litespeed\/avatar\/bd481d404e42caa2763662a3bfe825f8.jpg?ver=1776115684","caption":"w3compadmin"},"sameAs":["http:\/\/w3computing.com\/articles"]}]}},"featured_image_src":null,"featured_image_src_square":null,"author_info":{"display_name":"w3compadmin","author_link":"https:\/\/www.w3computing.com\/articles\/author\/w3compadmin\/"},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/posts\/1303","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/comments?post=1303"}],"version-history":[{"count":17,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/posts\/1303\/revisions"}],"predecessor-version":[{"id":1320,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/posts\/1303\/revisions\/1320"}],"wp:attachment":[{"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/media?parent=1303"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/categories?post=1303"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.w3computing.com\/articles\/wp-json\/wp\/v2\/tags?post=1303"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}