Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "Tutorial: Creating a RESTful Remote Service Provider"

(Created page with "==Introduction== When using ECF's implementation of OSGi Remote Services , service creator's can reuse an existing Remote Service provider to actually export the service.")
 
Line 1: Line 1:
 +
<!-- This CSS wraps code blocks in pretty boxes -->
 +
<css>
 +
.mw-code {
 +
  background-color: #fafafa;
 +
  padding: 20px;
 +
  border-color: #ddd;
 +
  border-width: 3px;
 +
  border-style: solid;
 +
  border-radius: 5px;
 +
  margin-left: 10px;
 +
  margin-right: 10px;
 +
  overflow-x: auto;
 +
}
 +
 +
.mw-headline {
 +
  font-family: Helvetica Neue,Helvetica,Arial,sans-serif;
 +
  color: rgb(51, 51, 51);
 +
}
 +
 +
p {
 +
  font-family: Helvetica Neue,Helvetica,Arial,sans-serif;
 +
  text-align: justify;
 +
}
 +
 +
h1 {
 +
  border-bottom-color: rgb(238, 238, 238);
 +
  font-weight: bold;
 +
  padding-bottom: 17px;
 +
  font-size: 30px;
 +
  line-height: 36px;
 +
}
 +
 +
h2 {
 +
  border-bottom-color: rgb(238, 238, 238);
 +
  padding-bottom: 12px;
 +
  font-weight: bold;
 +
  font-size: 24px;
 +
  line-height: 36px;
 +
}
 +
 +
h3 {
 +
  border-bottom-width: 1px;
 +
  border-bottom-style: solid;
 +
  border-bottom-color: rgb(238, 238, 238);
 +
  padding-bottom: 8px;
 +
  font-size: 18px;
 +
  line-height: 27px;
 +
}
 +
 +
h4 {
 +
  font-size: 14px;
 +
}
 +
 +
h5 {
 +
  font-size: 12px;
 +
}
 +
 +
h6 {
 +
  font-size: 11px;
 +
  color: #EBEBEB;
 +
  text-transform: uppercase;
 +
}
 +
 +
a {
 +
  color: rgb(0, 105, 214);
 +
  font-family: Helvetica Neue,Helvetica,Arial,sans-serif;
 +
}
 +
 +
a:visited {
 +
  color: rgb(0, 105, 214);
 +
}
 +
</css>
 +
 
==Introduction==
 
==Introduction==
  
When using ECF's implementation of OSGi Remote Services
+
In previous tutorials we've focused on how to use OSGi Remote Services to export a simple ITimeService and have a consumer use this service.
 +
 
 +
This tutorial will focus on customizing ECF's implementation of OSGi Remote Services to use a custom distribution provider...aka a Remote Service provider.  Creating a custom Remote Service provider is tantamount to creating your own implementation of the distribution function of OSGi Remote Services. 
 +
 
 +
Why would one want to do this?  One reason is interoperability and integration.  There are many existing services on the Internet currently...exposed through many different protocols (e.g. http+json, http+xml, JMS+json, etc., etc.).  By creating a new remote service provider, it's quite possible to take an existing service, implemented via an existing transport+serialization approach, and easily expose it as an OSGi Remote Service...while allowing existing services to run unmodified.
 +
 
 +
Another reason is that in the remoting of services, there are frequently non-functional requirements...e.g. for a certain kind of transport-level security, or using an existing protocol (e.g. http), or using a certain kind of serialization (e.g. json, or xml, or protocol buffers).  By creating a new distribution/remote service provider, these requirements can be met...simply by using the ECF provider architecture...rather than being required to reimplement all aspects of OSGi Remote Services/RSA.
 +
 
 +
==Exporting Using a Config Type==
 +
 
 +
As shown in [[Tutorial:_Building_your_first_OSGi_Remote_Service]], here is the remote service metadata needed to export a remote service using the ECF generic server distribution provider
 +
 
 +
<source lang="java">
 +
Dictionary<String, String> props = new Hashtable<String, String>();
 +
// OSGi Standard Property - indicates which of the interfaces of the service will be exported.  '*' means 'all'.
 +
props.put("service.exported.interfaces", "*");
 +
// OSGi Standard Property (optional) - indicates which provider config(s) will be used to export the service
 +
// (If not explicitly given here, the provider is free to choose a default configuration for the service)
 +
props.put("service.exported.configs","ecf.generic.server");
 +
// Register a new TimeServiceImpl with the above props
 +
bundleContext.registerService(ITimeService.class, new TimeServiceImpl(), props);
 +
</source>
 +
 
 +
Note the line:
 +
 
 +
<source lang="java">
 +
props.put("service.exported.configs","ecf.generic.server");
 +
</source>
 +
 
 +
This is one of the ECF-provided distribution providers, identified by as the config type "ecf.generic.server".  This provider is a general provider, capable of supporting the export of any service.
 +
 
 +
It's quite possible, however, to create a replacement provider, based upon our own http+rest+json transport protocol.  The remainder of this tutorial will step through how to create and run your own provider.
 +
 
 +
==Provider Step 1: Implement New Provider Namespace==
 +
 
 +
ECF allows providers to create their own namespaces, so that the endpoint id of the remote service can be properly interpreted.  Here is a TimeServiceRestNamespace class
 +
 
 +
<source lang="java">
 +
public class TimeServiceRestNamespace extends RestNamespace {
 +
 
 +
public static final String NAME = "com.mycorp.examples.timeservice.provider.rest.namespace";
 +
 +
@Override
 +
public ID createInstance(Object[] parameters) throws IDCreateException {
 +
return new TimeServiceRestID(this, URI.create((String) parameters[0]));
 +
}
 +
 
 +
public static class TimeServiceRestID extends RestID {
 +
 
 +
public TimeServiceRestID(Namespace namespace, URI uri) {
 +
super(namespace, uri);
 +
}
 +
}
 +
}
 +
</source>
  
 +
As can be seen above, when the createInstance call is made a new instance of TimeServiceRestID is created from the single String parameter[0] passed into the createInstance call.  Along with this class, we can define an extension in the plugin.xml of this bundle to allow this namespace to be used at the appropriate point.
  
, service creator's can reuse an existing Remote Service provider to actually export the service.
+
<source lang="xml">
 +
  <extension
 +
        point="org.eclipse.ecf.identity.namespace">
 +
      <namespace
 +
            class="com.mycorp.examples.timeservice.provider.rest.common.TimeServiceRestNamespace"
 +
            description="Timeservice Rest Namespace"
 +
            name="com.mycorp.examples.timeservice.provider.rest.namespace">
 +
      </namespace>
 +
  </extension>
 +
</source>

Revision as of 20:28, 10 December 2013


Introduction

In previous tutorials we've focused on how to use OSGi Remote Services to export a simple ITimeService and have a consumer use this service.

This tutorial will focus on customizing ECF's implementation of OSGi Remote Services to use a custom distribution provider...aka a Remote Service provider. Creating a custom Remote Service provider is tantamount to creating your own implementation of the distribution function of OSGi Remote Services.

Why would one want to do this? One reason is interoperability and integration. There are many existing services on the Internet currently...exposed through many different protocols (e.g. http+json, http+xml, JMS+json, etc., etc.). By creating a new remote service provider, it's quite possible to take an existing service, implemented via an existing transport+serialization approach, and easily expose it as an OSGi Remote Service...while allowing existing services to run unmodified.

Another reason is that in the remoting of services, there are frequently non-functional requirements...e.g. for a certain kind of transport-level security, or using an existing protocol (e.g. http), or using a certain kind of serialization (e.g. json, or xml, or protocol buffers). By creating a new distribution/remote service provider, these requirements can be met...simply by using the ECF provider architecture...rather than being required to reimplement all aspects of OSGi Remote Services/RSA.

Exporting Using a Config Type

As shown in Tutorial:_Building_your_first_OSGi_Remote_Service, here is the remote service metadata needed to export a remote service using the ECF generic server distribution provider

Dictionary<String, String> props = new Hashtable<String, String>();
// OSGi Standard Property - indicates which of the interfaces of the service will be exported.  '*' means 'all'.
props.put("service.exported.interfaces", "*");
// OSGi Standard Property (optional) - indicates which provider config(s) will be used to export the service
// (If not explicitly given here, the provider is free to choose a default configuration for the service)
props.put("service.exported.configs","ecf.generic.server");
// Register a new TimeServiceImpl with the above props
bundleContext.registerService(ITimeService.class, new TimeServiceImpl(), props);

Note the line:

props.put("service.exported.configs","ecf.generic.server");

This is one of the ECF-provided distribution providers, identified by as the config type "ecf.generic.server". This provider is a general provider, capable of supporting the export of any service.

It's quite possible, however, to create a replacement provider, based upon our own http+rest+json transport protocol. The remainder of this tutorial will step through how to create and run your own provider.

Provider Step 1: Implement New Provider Namespace

ECF allows providers to create their own namespaces, so that the endpoint id of the remote service can be properly interpreted. Here is a TimeServiceRestNamespace class

public class TimeServiceRestNamespace extends RestNamespace {
 
	public static final String NAME = "com.mycorp.examples.timeservice.provider.rest.namespace";
 
	@Override
	public ID createInstance(Object[] parameters) throws IDCreateException {
		return new TimeServiceRestID(this, URI.create((String) parameters[0]));
	}
 
	public static class TimeServiceRestID extends RestID {
 
		public TimeServiceRestID(Namespace namespace, URI uri) {
			super(namespace, uri);
		}
	}
}

As can be seen above, when the createInstance call is made a new instance of TimeServiceRestID is created from the single String parameter[0] passed into the createInstance call. Along with this class, we can define an extension in the plugin.xml of this bundle to allow this namespace to be used at the appropriate point.

   <extension
         point="org.eclipse.ecf.identity.namespace">
      <namespace
            class="com.mycorp.examples.timeservice.provider.rest.common.TimeServiceRestNamespace"
            description="Timeservice Rest Namespace"
            name="com.mycorp.examples.timeservice.provider.rest.namespace">
      </namespace>
   </extension>

Back to the top