hexabot / carmine

Lightweight Java RMI alternative using HTTP(S)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

carmine

This library provides a lightweight alternative to RMI (Remote Method Invocation) or [Spring HTTP Invoker] (http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/remoting/httpinvoker/package-summary.html), using HTTP(S) protocol for communication between the client and server side.

Key features

  • Java-to-Java remote method invocation is done using HTTP(S) protocol
  • working with remote objects on the client side differs only in instantiation process (new keyword VS CarmineManager#getRemote())
  • very simple implementation of the server side (e.g. Java EE Servlet)
  • exceptions thrown by the remote method implementation are transparently rethrown on the client side
  • no dependencies on external libraries - just one small JAR file
  • Java SE 6+ compatible

Overview

Carmine has been designed for as much simple Java-to-Java remote method invocation as possible, not only for the ease of usage (invocation of remote method is exactly the same as local one, except the object instantiation), but also for the ease of implementing the server side, responsible for method implementation invocation.

The only two things the developer has to do to make things work are:

  1. Implement the CarmineInvoker#getImplementation() method, which takes interface name and returns the actual implementation for it.
  2. Connect the CarmineInvoker instance to the input/output stream to handle client requests and responses (e.g. HttpServletRequest#getInputStream() and HttpServletResponse#getOutputStream() when using Java EE Servlet).

Basic example - client side

Note that similar code can be found in the Main class, placed in the carmine-demo-client demo project.

URL remoteServerURL = null;

try {
  remoteServerURL = new URL("http://localhost:8080/carmine-demo-server/CarmineServlet");
} catch (MalformedURLException ex) {
   // handle the exception
}

CarmineManager cm = new CarmineManager(remoteServerURL);

/*
 * RemoteTest.class is the interface class. The real implementation
 * of this interface is on the server and all the methods are called
 * remotely.
 */
RemoteTest remoteTest = cm.getRemote(RemoteTest.class);

// this is the remotely called method, taking String as an argument
String greetings = remoteTest.getGreetings("Arthur");

// prints 'Greetings from the remote server, Arthur' to console
System.out.println(greetings);

Basic example - server side

Note that this is the code snippet from the CarmineServlet Java EE Servlet, which can be found in the carmine-demo-server demo project.

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {

    // create the instance of the carmine remote invoker
    CarmineInvoker invoker = new CarmineInvoker() {

        @Override
        @SuppressWarnings("unchecked")
        public Object getImplementation(
                 String interfaceName,
                 Map<String, Object> properties) throws Exception {
            /*
             * Represents very simple implementation of this method, trying
             * to instantiate an implementation class for the passed
             * interface name using the interface name + "Impl" postfix.
             *
             * Example:
             *      com.norcane.carmine.demo.RemoteTest
             *   -> com.norcane.carmine.demo.RemoteTestImpl
             *
             * In real-world scenario, some security checks should be
             * performed before returning the instance back (e.g. whether
             * the connected local side is allowed to access this class, or
             * implement some kind of authorization using properties map).
             */
             String className = interfaceName + "Impl";
             Class theClass = Class.forName(className);
             return theClass.newInstance();
        }

    };

    invoker.processRequest(request.getInputStream(), response.getOutputStream());
}

Using connection properties

Sometimes some additional data are required to be shared between the client and server side within the Carmine connection (e.g. credentials, security token, etc). To allow this, Carmine offers mechanism of connection properties, represented by the Map<String, Object> object. Any property set either on client or server side will be available to both of them, during every remote method invocation, until the property is removed from the map or connection is closed.

To access properties from the client side, simply use CarmineManager instance:

CarmineManager cm = new CarmineManager(remoteServerUrl);
cm.addProperty("foo", "bar");       // to add property
cm.removeProperty("foo")     // to remove property
Map<String, Object> properties = cm.getProperties();    // readonly map of properties

To access the properties on the server side, simply use the parameter passed to the CarmineInvoker#getImplementation() method.

Requirements

  • to avoid possible serialization problems, the same major version of JVM should be used on both server and client side (Java SE 6 or newer)
  • all objects returned as the result of remote method invocation must be serializable
  • all exception objects thrown during remote method invocation must be serializable (allows to transparently rethrow the exception on the client)
  • all connection properties values must be serializable

About

Lightweight Java RMI alternative using HTTP(S)

License:GNU Lesser General Public License v3.0


Languages

Language:Java 100.0%