Skip to content

HTTP RMI Service

mr-iulian-rotaru edited this page Nov 20, 2022 · 45 revisions

HTTP-RMI service facilitates access to application services using HTTP-RMI - Hyper Text Remote Invocation, protocol. HTTP-RMI has the same grammar as HTTP but with slightly different semantic. Basically HTTP-RMI takes care to convey class and method names, to serialize invocation arguments and to deserialize returned value, if not void; see protocol description.

HTTP-RMI service uses com.jslib.container.rmi.HttpRmiServlet to expose application services, declared remote accessible with @Remote annotation.

Server

All that application developer should do to enable HTTP-RMI access is to mark managed class with @Remote annotation. It is deployer responsibility to configure HTTP-RMI servlet and to map it, see deployment descriptor.

Although not mandatory, managed classes exposed remotely has a POJO interface and @Remote annotation is applied to implementation class. Interface is usually packaged in a client library that client applications use as compile dependency.

public interface IHumanResources {
	Employee getEmployee(int employeeID);
}

@Remote annotation may be accompanied by security related annotations: @RolesAllowed, @DenyAll and @PermitAll. By default, if there is no security annotation declared, all methods are remotely accessible.

@Remote
public class HumanResources implements IHumanResources {
	public Employee getEmployee(int employeeID) {
		...
		return employee;
	}
}

Client

Since HTTP-RMI uses standard HTTP protocol for transport, application services exposed by HTTP-RMI service are programming language agnostic. Any HTTP client or CLI tool can invoke exposed services. Anyway, for Java clients there is EJB annotation that inject a Java dynamic proxy for the remote interface. Proxy handler takes care to create HTTP request, to serialize arguments and deserialize returned value.

Here, an hypothetic application service - CustomerService, invokes services deployed on a remote server. All that application code needs to know is the remote service interface - com.server.IHumanResources, that is provided by remote application via a client library.

package com.server.IHumanResources;

public class CustomerService {
	@EJB
	private IHumanResources humanResources;

	public void getContract(int employeeID) {
		Employee employee = humanResources.getEmployee(empoyeeID);
	}
}

On runtime were client application is deployed, @EJB annotation required an environment variable that declares remote service implementation URL. This environment variable is similar to a JNDI simple environment entry and has the name ${interface-qualified-name}.url, in our example com.server.IHumanResources.url.

@EJB environment value should be the URL of the server application where remote service implementation is running. If remote application is not on server root, application context should be included. Here is an example from Tomcat context descriptor.

<Context>
	<Environment name="com.server.IHumanResources.url" type="java.lang.String" value="https://com.server/" />
</Context>

Response Status

Status Code Description
200 OK Remote method successfully executed with value returned.
204 No Content Void remote method executed successfully.
400 Bad Request Business constrain broken, body contains com.jslib.rmi.BusinessException instance encoded application/json.
401 Unauthorized Security constraint does not allow access from current request.
403 Forbidden Server understood the request but actively refuses to process it; common cause may be Tomcat filtering by remote address.
404 Not Found Request URI does not map to any remote method.
500 Internal Server Error Exception on remote method execution.

Project Integration

Server application has compile time dependency on @Remote annotation that is provided by j(s) EE API, included in every Tiny Container application.

Container HTTP-RMI service is provided by tiny-http-rmi module and need to be included into project runtime dependencies.

<dependency>
	<groupId>com.js-lib</groupId>
	<artifactId>tiny-http-rmi</artifactId>
	<version>1.3.3</version>
	<scope>provided</scope>
</dependency>

Deployment Descriptor

HTTP-RMI requests must be routed to com.jslib.container.rmi.HttpRmiServlet servlet. For this we need to declare the HTTP-RMI servlet on application deployment descriptor, web.xml. For HTTP-RMI servlet mapping use extension *.rmi.

<web-app>
	<servlet>
		<servlet-name>rmi-servlet</servlet-name>
		<servlet-class>com.jslib.container.rmi.HttpRmiServlet</servlet-class>
	</servlet>

	<servlet-mapping>
		<servlet-name>rmi-servlet</servlet-name>
		<url-pattern>*.rmi</url-pattern>
	</servlet-mapping>
</web-app>

References


Last updated 1/9/2022.

Clone this wiki locally