RMI Remoting

This example is based on the simple object example.

Example Description

  • This example is based on the simple object example.
  • The RMI server project binds the exported service via the RMI-Registry. (see MainServer.java)
  • The RMI client project binds the service via the RMI-Registry for invoking it. (see RmiExampleRegistry.java)
  • Complete Docker containerized example.

Server Configuration

  • Docker Configuration.
  • Create Docker Image
  • Java main program to start the registry and bind the Java service beans.
Docker Containerization Config
Docker Configuration : Dockerfile
FROM openjdk:8u212-jdk-alpine3.9
WORKDIR /app
COPY target/rmi_factoryapi_server-jar-with-dependencies.jar /app
EXPOSE 1098 1099
CMD ["java", "-Djava.rmi.server.hostname=0.0.0.0", "-jar", "rmi_factoryapi_server-jar-with-dependencies.jar"]
Create Docker Image
The Docker Image is created during the Maven build process.
XML-File : pom.xml (part)
...
<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>exec-maven-plugin</artifactId>
  <executions>
    <execution>
      <id>docker-build</id>
      <phase>install</phase>
      <goals>
        <goal>exec</goal>
      </goals>
      <configuration>
        <executable>docker</executable>
        <workingDirectory>${project.basedir}</workingDirectory>
        <arguments>
          <argument>build</argument>
          <argument>-t</argument>
          <argument>rmi_factoryapi_server:${project.version}</argument>
          <argument>.</argument>
        </arguments>
      </configuration>
    </execution>
  </executions>
</plugin>
...
Server Main Program
  • The server main program starts the RMI-Registry and register all beans to the registry.
  • The Oracle Database configuration parameter are set thru environment variables set during starting the Docker container from the client.
Java Class : MainServerFactoryApi.java
package application;

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

import javax.sql.DataSource;

import factory.RmiServerRegistry;
import oracle.ucp.jdbc.PoolDataSource;
import oracle.ucp.jdbc.PoolDataSourceFactory;

public class MainServerFactoryApi {
  public static void main(String[] args)
  {
    try {
      Registry registry = LocateRegistry.createRegistry(1099);

      // call bindServices to register services and set data source
      RmiServerRegistry.bindServices(registry, Integer.parseInt(System.getenv("port")), getDataSource());
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }

  public static DataSource getDataSource() throws Exception
  {
    PoolDataSource poolDataSource = PoolDataSourceFactory.getPoolDataSource();
    poolDataSource.setConnectionFactoryClassName("oracle.jdbc.pool.OracleDataSource");

    // environment variables are set in rmi_factoryapi_client/pom.xml docker execution in docker-start
    poolDataSource.setURL(System.getenv("db.url"));
    poolDataSource.setUser(System.getenv("db.username"));
    poolDataSource.setPassword(System.getenv("db.password"));
    poolDataSource.setInitialPoolSize(1);
    poolDataSource.setMinPoolSize(2);
    poolDataSource.setMaxPoolSize(10);
    poolDataSource.setLoginTimeout(10);
    poolDataSource.setInactiveConnectionTimeout(30);
    poolDataSource.setTimeoutCheckInterval(15);
    poolDataSource.setValidateConnectionOnBorrow(true);
    poolDataSource.setConnectionWaitTimeout(60);
    return poolDataSource;
  }
}

Client Configuration

  • Start the Docker Container including the Oracle datasource parameter.
  • Java client registry setup.
  • Java example calling the remote service.
Start Docker Image
  • The Docker Image is started during the Maven client build process.
  • The Oracle Database configuration parameter are set as environment variables.
XML-File : pom.xml (part)
...
<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>exec-maven-plugin</artifactId>
  <executions>
    <!-- start docker -->
    <execution>
      <id>docker-start</id>
      <phase>process-test-classes</phase>
      <goals>
        <goal>exec</goal>
      </goals>
      <configuration>
        <executable>docker</executable>
        <workingDirectory>${project.basedir}</workingDirectory>
        <arguments>
          <argument>run</argument>
          <argument>--name</argument>
          <argument>rmi_factoryapi_server</argument>
          <argument>--rm</argument>
          <argument>-p</argument>
          <argument>1098:1098</argument>
          <argument>-p</argument>
          <argument>1099:1099</argument>
          <argument>-d</argument>
          <argument>-e</argument>
          <!-- configure the database url here -->
          <argument>db.url=jdbc:oracle:thin:@192.168.0.109:1521/orcl</argument>
          <argument>-e</argument>
          <!-- configure the database username here -->
          <argument>db.username=dbw_examples</argument>
          <argument>-e</argument>
          <!-- configure the database password here -->
          <argument>db.password=dbw_examples</argument>
          <argument>-e</argument>
          <argument>port=1098</argument>
          <argument>rmi_factoryapi_server:${project.version}</argument>
        </arguments>
      </configuration>
    </execution>
  </executions>
</plugin>
...
Client Setup
Set up the registry. This registry configuration is used by the factory.
Java Class : RmiClientRegistryFactoryApi.java
package factory;

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class RmiClientRegistryFactoryApi {
  private static Registry registry;

  public static synchronized Registry getRegistry() throws RemoteException
  {
    if (registry == null) {
      registry = LocateRegistry.getRegistry();
    }
    return registry;
  }
}
Calling the Remote Services
Java Class : RmiServerInfoFactoryApi.java
package plsql_workbench_examples;

import factory.ExamplesRPCFactory;
import service.ServerInfoSimpleObjectService;
import transferobject.SimpleObject;

public class RmiServerInfoFactoryApi {
  public static void main(String[] args)
  {
    try {
      int diff = 10;

      // get the service
      ServerInfoSimpleObjectService service = ExamplesRPCFactory.getServerInfoSimpleObjectService();

      // calling the stored procedure, receiving a transfer object
      SimpleObject info = service.call(diff);

      // print server information
      System.out.println("database date(+" + diff + "):" + info.d);
      System.out.println("database timestamp(-" + diff + "):" + info.ts);
      System.out.println("database instance name:" + info.instance);
      System.out.println("database version:" + info.dbVersion + "." + info.dbRelease);
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
}

Configuring and Running the Example

  • The PL/SQL package has been installed in your Oracle database.
  • Docker is installed and running.
  • Configure the database connection parameter in the client/pom.xml.
  • Just run mvn clean package from the RMI-Example parent folder.