Skip to main content

Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "Using Properties to Import Endpoint Descriptions"

 
(8 intermediate revisions by 2 users not shown)
Line 11: Line 11:
 
</pre>
 
</pre>
  
In the [https://git.eclipse.org/c/ecf/org.eclipse.ecf.git/tree/examples/bundles/com.mycorp.examples.timeservice.consumer.filediscovery/timeserviceendpointdescription.xml timeserviceendpointdescription.xml file] is the TimeService EDEF.  When this bundle is started, the ECF RSA implementation will read and parse this file, and import the given endpoint description as a remote service proxy.
+
In the [https://git.eclipse.org/c/ecf/org.eclipse.ecf.git/tree/examples/bundles/com.mycorp.examples.timeservice.consumer.filediscovery com.mycorp.examples.timeservice.consumer.filediscovery project] is the TimeService EDEF.  When this bundle is started, the ECF RSA implementation will read and parse this file, and import the given endpoint description as a remote service proxy.
  
 
Although EDEF is general, it's not as easy-to-use as it could be under some circumstances.  For example, both RSA as specified, and ECF's implementation require that some properties be set, while other properties in the EDEF are optional.  It's often a lot to ask that the EDEF creator know the required vs. optional properties.
 
Although EDEF is general, it's not as easy-to-use as it could be under some circumstances.  For example, both RSA as specified, and ECF's implementation require that some properties be set, while other properties in the EDEF are optional.  It's often a lot to ask that the EDEF creator know the required vs. optional properties.
  
## Solution:  EDEF Properties Files
+
== EDEF Properties Files ==
  
ECF has recently introduced a mechanism to make it easier to create and import Endpoint Descriptions in EDEF format.  If a properties file '''of the same name''' but with extension '.properties' rather than '.xml' is provided all of the properties and their values will be read and the given values replaced or added to the EDEF file.
+
ECF has recently introduced a mechanism to make it easier to create and import Endpoint Descriptions using properties files. Properties files can be used to override values in an underlying XML EDEF file, with the properties file values always taking precedence.  
  
For example, [https://github.com/ECF/JaxRSProviders/tree/master/examples/com.mycorp.examples.student.client.filediscovery here] is an example project with the Remote-Service header in the [https://github.com/ECF/JaxRSProviders/blob/master/examples/com.mycorp.examples.student.client.filediscovery/META-INF/MANIFEST.MF manifest.mf]:
+
Properties files can now also be used as an '''alternative''' to XML-based endpoint definition. You can now remove the XML file entirely and specify the properties file in your bundle manifest.
  
 
<pre>
 
<pre>
Remote-Service: edef/studentserviceEDEF.xml
+
Remote-Service: edef/timeserviceendpointdescription.properties
 
</pre>
 
</pre>
  
Also, there is the [https://github.com/ECF/JaxRSProviders/blob/master/examples/com.mycorp.examples.student.client.filediscovery/edef/studentserviceEDEF.xml edef/studentserviceEDEF.xml]
+
== Properties file content ==
  
<source lang="xml">
+
While EDEF properties files are structured as name/value pairs, they can contain all the attributes usually found in XML-based EDEF files. Support has been added for various data types including arrays and also the generation of random values (e.g. UUIDs) if needed. The structure for a property entry is:
<?xml version="1.0" encoding="UTF-8"?>
+
<endpoint-descriptions xmlns="http://www.osgi.org/xmlns/rsa/v1.0.0">
+
  <endpoint-description>
+
    <property name="ecf.endpoint.id.ns" value-type="String" value="ecf.namespace.jaxrs"/>
+
    <property name="ecf.rsvc.id" value-type="Long" value="1"/>
+
    <property name="endpoint.framework.uuid" value-type="String" value="f838e874-d17d-4328-806e-a9cd869b3f35"/>
+
    <property name="endpoint.id" value-type="String" value="fabcb5ab-6937-4f31-9f97-c10bb9660bb8"/>
+
    <property name="endpoint.package.version.com.mycorp.examples.student" value-type="String" value="1.0.0"/>
+
    <property name="endpoint.service.id" value-type="Long" value="94"/>
+
    <property name="objectClass" value-type="String">
+
      <array>
+
        <value>com.mycorp.examples.student.StudentService</value>
+
      </array>
+
    </property>
+
    <property name="osgi.basic.timeout" value-type="String" value="5000000"/>
+
    <property name="remote.configs.supported" value-type="String">
+
      <array>
+
        <value>ecf.jaxrs.jersey.server</value>
+
      </array>
+
    </property>
+
    <property name="remote.intents.supported" value-type="String">
+
      <array>
+
        <value>passByValue</value>
+
        <value>exactlyOnce</value>
+
        <value>ordered</value>
+
        <value>osgi.async</value>
+
        <value>osgi.private</value>
+
        <value>osgi.confidential</value>
+
        <value>jaxrs</value>
+
      </array>
+
    </property>
+
    <property name="service.imported" value-type="String" value="true"/>
+
    <property name="service.imported.configs" value-type="String">
+
      <array>
+
        <value>ecf.jaxrs.jersey.server</value>
+
      </array>
+
    </property>
+
    <property name="service.intents" value-type="String">
+
      <array>
+
        <value>osgi.async</value>
+
        <value>jaxrs</value>
+
      </array>
+
    </property>
+
  </endpoint-description>
+
</endpoint-descriptions>
+
</source>
+
  
and the https://github.com/ECF/JaxRSProviders/blob/master/examples/com.mycorp.examples.student.client.filediscovery/edef/studentserviceEDEF.properties studentserviceEDEF.properties file] with content
+
<pre>
 +
#
 +
# String properties do not require a type
 +
#
 +
# Leaving value blank generates default
 +
#
 +
# name:type=value (leave value blank to generate default)
 +
#
 +
 
 +
# String
 +
ecf.endpoint.id=ecftcp://localhost:3288/server
 +
 
 +
# Boolean
 +
service.imported:boolean=true
 +
 
 +
# UUID
 +
endpoint.id:uuid=0
 +
 
 +
# Long
 +
endpoint.service.id:Long=0
 +
 
 +
# Long nanoTime
 +
ecf.endpoint.ts:Long:nanoTime=0
 +
 
 +
# Array with one element
 +
objectClass:array=com.mycorp.examples.timeservice.ITimeService
 +
 
 +
# Array with multiple elements
 +
remote.intents.supported:array=passByValue,exactlyOnce,ordered
 +
</pre>
 +
 
 +
 
 +
== Properties file usage ==
 +
 
 +
EDEF properties files can be used in a variety of ways:
 +
 
 +
# Default properties files - applies to all of service endpoints defined in a bundle (or in a specific folder)
 +
# Service-specific properties files - applies to a specific service endpoint definition
 +
# Profile-specific properties files - can be specified either for default or for service-specific properties and activated by a command line parameter
 +
 
 +
 
 +
These three types of properties files can be combined in a variety of ways depending on your specific needs. In any case, all attributes defined in properties files will override anything in an XML EDEF file, if that file exists.
 +
 
 +
 
 +
== Default properties files ==
 +
 
 +
A default properties file must be named '''edef_defaults.properties'''. If this file is located in the bundle root folder, then the defaults will apply to '''all''' remote services defined in the bundle. This can be useful if all of your remote services share the same provider. For example, all [https://github.com/ECF/JaxRSProviders Jersey JAX-RS client] definitions share the following properties:
  
 
<pre>
 
<pre>
ecf.endpoint.id=http://localhost:8080/rservices/rs1
+
endpoint.id:uuid=0
 +
ecf.endpoint.id.ns=ecf.namespace.jaxrs
 +
remote.configs.supported:array=ecf.jaxrs.jersey.server
 +
remote.intents.supported:array=passByValue, exactlyOnce, ordered, jaxrs
 +
service.imported.configs:array=ecf.jaxrs.jersey.server
 +
service.intents:array=osgi.async
 +
ecf.endpoint.rsfilter=(objectClass=*)
 +
ecf.rsvc.id:Long=0
 
</pre>
 
</pre>
  
in the same [https://github.com/ECF/JaxRSProviders/blob/master/examples/com.mycorp.examples.student.client.filediscovery/edef /edef/ directory location] as the xml file.
+
You can also place an edef_defaults.properties file in a directory (e.g. 'edef' or 'OSGI-INF') that contains a specific set of endpoint definitions. In this case the defaults will apply only to those endpoints specified in that directory.
  
When this bundle is started, ECF's RSA impl will read the studentServiceEDEF.xml file, parse it, and then read and substitute the all name=value pairs in the studentserviceEDEF.properties file into the EndpointDescription used to import the remote service.  As many properties as desired may be put into the properties file, and all such properties will all be either added (if not already present in parsed EDEF) or values replaced (if already present in parsed EDEF).  For example, if the studentserviceEDEF.properties files had these properties:
+
Properties specified in a specific directory will override those specified in the bundle root.
  
 
<pre>
 
<pre>
ecf.endpoint.id=http://localhost:8080/rservices/rs1
+
bundle root
endpoint.id=myendpointid
+
 
endpoint.framework.uuid=ffffffff-dddd-4444-8888-aaaaaaaaa
+
/edef_defaults.properties (applied first)
 +
 
 +
/edef
 +
    edef_defaults.properties (applied to services in folder and override base defaults)
 +
    timeserviceendpointdescription.xml
 
</pre>
 
</pre>
  
Then the resulting EndpointDescription would be:
+
== Service-specific properties files ==
 +
 
 +
A properties file can contain all or some of the properties needed to define an endpoint. If a properties file is meant to override values in an existing XML EDEF file, then it must be named the same except for the file extension.
 +
 
 +
<pre>
 +
bundle root
 +
 
 +
/edef_defaults.properties
 +
 
 +
/edef
 +
    edef_defaults.properties
 +
    timeserviceendpointdescription.xml
 +
    timeserviceendpointdescription.properties (overrides all default and XML properties)
 +
</pre>
 +
 
 +
Again, you can also specify the properties file directly in your bundle manifest and eliminate the XML file entirely.
 +
 
 +
<pre>
 +
Remote-Service: edef/timeserviceendpointdescription.properties
 +
</pre>
 +
 
 +
 
 +
 
 +
== Profile-specific properties ==
 +
 
 +
Endpoint definitions often need to vary based on some runtime configuration. For example, you may have a different endpoint URL for various environments.
 +
 
 +
<pre>
 +
Development environment - http://dev.myserver.com/rservices/rs1
 +
Test environment - http://test.myserver.com/rservices/rs1
 +
Production environment - http://prod.myserver.com/rservices/rs1
 +
</pre>
 +
 
 +
Profile-specific properties files allow you to do this by overriding both the default and service-specific properties described above. First, a profile name can be specified as a command line argument:
 +
 
 +
<pre>
 +
-Dorg.eclipse.ecf.osgi.services.remoteserviceadmin.EndpointDescriptionLocator.localPropertiesProfile=[profile-name]
 +
</pre>
 +
 
 +
If a profile is specified, the framework will attempt to locate properties files with the profile name specified as a suffix. Profile-based properties can be specified for both defaults and endpoint-specific properties.
 +
 
 +
For example, if the profile name is set as 'dev', then the framework would look at this file structure:
 +
 
 +
<pre>
 +
 
 +
bundle root
 +
 
 +
/edef_defaults.properties
 +
/edef-defaults-dev.properties (overrides non-profile defaults)
 +
 
 +
/edef
 +
    edef_defaults.properties
 +
    edef-defaults-dev.properties (overrides all root defaults and folder defaults)
 +
 
 +
    timeserviceendpointdescription.properties
 +
    timeserviceendpointdescription-dev.properties (overrides all non-profile defaults)
 +
</pre>
  
<source lang="xml">
 
<?xml version="1.0" encoding="UTF-8"?>
 
<endpoint-descriptions xmlns="http://www.osgi.org/xmlns/rsa/v1.0.0">
 
  <endpoint-description>
 
    <property name="ecf.endpoint.id" value-type="String" value="http://localhost:8080/rservices/rs1"/>
 
    <property name="ecf.endpoint.id.ns" value-type="String" value="ecf.namespace.jaxrs"/>
 
    <property name="ecf.rsvc.id" value-type="Long" value="1"/>
 
    <property name="endpoint.framework.uuid" value-type="String" value="ffffffff-dddd-4444-8888-aaaaaaaaa"/>
 
    <property name="endpoint.id" value-type="String" value="myendpointid"/>
 
    <property name="endpoint.package.version.com.mycorp.examples.student" value-type="String" value="1.0.0"/>
 
    <property name="endpoint.service.id" value-type="Long" value="94"/>
 
    <property name="objectClass" value-type="String">
 
      <array>
 
        <value>com.mycorp.examples.student.StudentService</value>
 
      </array>
 
    </property>
 
    <property name="osgi.basic.timeout" value-type="String" value="5000000"/>
 
    <property name="remote.configs.supported" value-type="String">
 
      <array>
 
        <value>ecf.jaxrs.jersey.server</value>
 
      </array>
 
    </property>
 
    <property name="remote.intents.supported" value-type="String">
 
      <array>
 
        <value>passByValue</value>
 
        <value>exactlyOnce</value>
 
        <value>ordered</value>
 
        <value>osgi.async</value>
 
        <value>osgi.private</value>
 
        <value>osgi.confidential</value>
 
        <value>jaxrs</value>
 
      </array>
 
    </property>
 
    <property name="service.imported" value-type="String" value="true"/>
 
    <property name="service.imported.configs" value-type="String">
 
      <array>
 
        <value>ecf.jaxrs.jersey.server</value>
 
      </array>
 
    </property>
 
    <property name="service.intents" value-type="String">
 
      <array>
 
        <value>osgi.async</value>
 
        <value>jaxrs</value>
 
      </array>
 
    </property>
 
  </endpoint-description>
 
</endpoint-descriptions>
 
</source>
 
  
## EDEF Templates
+
== EDEF Properties for Importing JaxRS Remote Services into an Eclipse RCP Application ==
  
The properties mechanism allows EDEF files to be used as templates, with any/all property values that are required for importing a given remote service automatically substituted into the EDEF before remote service import.
+
Patrick Paulin has blogged about using EDEF properties for [https://modumind.com/2020/11/05/ecf-and-rest-improved-support-for-properties-and-profiles/ importing JaxRS Remote Services into an Eclipse RCP Application].

Latest revision as of 13:39, 1 September 2021

OSGi Remote Services can be imported by service consumers via several methods. One method is to have a network-based discovery provider, that uses some communications protocol to publish, discover and import remote services over some network.

Here is the current list of ECF-supported discovery providers

Another method is to have File-Based Remote Services Discovery. The OSGI Remote Services and Remote Service Admin specifications define an xml-formatted document called the the Endpoint Description Extender Format (EDEF).

According to the RSA specification, EDEF files can be provided in the bundle MANIFEST.MF after the 'Remote-Service header, and when this bundle is started, all given EDEF files will be read by ECF RSA implementation, and all endpoint descriptions will be imported. For example, in this manifest...which is part of the ECF Timeservice Example...there is this header:

Remote-Service: timeserviceendpointdescription.xml

In the com.mycorp.examples.timeservice.consumer.filediscovery project is the TimeService EDEF. When this bundle is started, the ECF RSA implementation will read and parse this file, and import the given endpoint description as a remote service proxy.

Although EDEF is general, it's not as easy-to-use as it could be under some circumstances. For example, both RSA as specified, and ECF's implementation require that some properties be set, while other properties in the EDEF are optional. It's often a lot to ask that the EDEF creator know the required vs. optional properties.

EDEF Properties Files

ECF has recently introduced a mechanism to make it easier to create and import Endpoint Descriptions using properties files. Properties files can be used to override values in an underlying XML EDEF file, with the properties file values always taking precedence.

Properties files can now also be used as an alternative to XML-based endpoint definition. You can now remove the XML file entirely and specify the properties file in your bundle manifest.

Remote-Service: edef/timeserviceendpointdescription.properties

Properties file content

While EDEF properties files are structured as name/value pairs, they can contain all the attributes usually found in XML-based EDEF files. Support has been added for various data types including arrays and also the generation of random values (e.g. UUIDs) if needed. The structure for a property entry is:

#
# String properties do not require a type
#
# Leaving value blank generates default
# 
# name:type=value (leave value blank to generate default)
#

# String
ecf.endpoint.id=ecftcp://localhost:3288/server

# Boolean
service.imported:boolean=true

# UUID
endpoint.id:uuid=0

# Long
endpoint.service.id:Long=0

# Long nanoTime
ecf.endpoint.ts:Long:nanoTime=0

# Array with one element
objectClass:array=com.mycorp.examples.timeservice.ITimeService

# Array with multiple elements
remote.intents.supported:array=passByValue,exactlyOnce,ordered


Properties file usage

EDEF properties files can be used in a variety of ways:

  1. Default properties files - applies to all of service endpoints defined in a bundle (or in a specific folder)
  2. Service-specific properties files - applies to a specific service endpoint definition
  3. Profile-specific properties files - can be specified either for default or for service-specific properties and activated by a command line parameter


These three types of properties files can be combined in a variety of ways depending on your specific needs. In any case, all attributes defined in properties files will override anything in an XML EDEF file, if that file exists.


Default properties files

A default properties file must be named edef_defaults.properties. If this file is located in the bundle root folder, then the defaults will apply to all remote services defined in the bundle. This can be useful if all of your remote services share the same provider. For example, all Jersey JAX-RS client definitions share the following properties:

endpoint.id:uuid=0
ecf.endpoint.id.ns=ecf.namespace.jaxrs
remote.configs.supported:array=ecf.jaxrs.jersey.server
remote.intents.supported:array=passByValue, exactlyOnce, ordered, jaxrs
service.imported.configs:array=ecf.jaxrs.jersey.server
service.intents:array=osgi.async
ecf.endpoint.rsfilter=(objectClass=*)
ecf.rsvc.id:Long=0

You can also place an edef_defaults.properties file in a directory (e.g. 'edef' or 'OSGI-INF') that contains a specific set of endpoint definitions. In this case the defaults will apply only to those endpoints specified in that directory.

Properties specified in a specific directory will override those specified in the bundle root.

bundle root

/edef_defaults.properties (applied first)

/edef
     edef_defaults.properties (applied to services in folder and override base defaults)
     timeserviceendpointdescription.xml

Service-specific properties files

A properties file can contain all or some of the properties needed to define an endpoint. If a properties file is meant to override values in an existing XML EDEF file, then it must be named the same except for the file extension.

bundle root

/edef_defaults.properties

/edef
     edef_defaults.properties
     timeserviceendpointdescription.xml
     timeserviceendpointdescription.properties (overrides all default and XML properties)

Again, you can also specify the properties file directly in your bundle manifest and eliminate the XML file entirely.

Remote-Service: edef/timeserviceendpointdescription.properties


Profile-specific properties

Endpoint definitions often need to vary based on some runtime configuration. For example, you may have a different endpoint URL for various environments.

Development environment - http://dev.myserver.com/rservices/rs1
Test environment - http://test.myserver.com/rservices/rs1
Production environment - http://prod.myserver.com/rservices/rs1

Profile-specific properties files allow you to do this by overriding both the default and service-specific properties described above. First, a profile name can be specified as a command line argument:

-Dorg.eclipse.ecf.osgi.services.remoteserviceadmin.EndpointDescriptionLocator.localPropertiesProfile=[profile-name]

If a profile is specified, the framework will attempt to locate properties files with the profile name specified as a suffix. Profile-based properties can be specified for both defaults and endpoint-specific properties.

For example, if the profile name is set as 'dev', then the framework would look at this file structure:


bundle root

/edef_defaults.properties
/edef-defaults-dev.properties (overrides non-profile defaults)

/edef
     edef_defaults.properties
     edef-defaults-dev.properties (overrides all root defaults and folder defaults)

     timeserviceendpointdescription.properties
     timeserviceendpointdescription-dev.properties (overrides all non-profile defaults)


EDEF Properties for Importing JaxRS Remote Services into an Eclipse RCP Application

Patrick Paulin has blogged about using EDEF properties for importing JaxRS Remote Services into an Eclipse RCP Application.

Back to the top