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: JaxRS Remote Services on Karaf"

(14 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
==Introduction==
 
==Introduction==
  
[https://github.com/ECF/JaxRSProviders Jersey and CXF ] can be run on Karaf as an ECF [https://wiki.eclipse.org/Distribution_Providers distribution provider] for JaxRS-defined remote services.   
+
[https://github.com/ECF/JaxRSProviders Jersey] or [https://cxf.apache.org/ CXF] can be run on Karaf as an ECF [https://wiki.eclipse.org/Distribution_Providers distribution provider] for remote services that use standard JaxRS annotations.   
  
This tutorial describes installing and running an example JaxRS remote service on Karaf.  Developers can create and deploy arbitrary remote services by reusing the ECF RSA impl and the Jersey or CXF distribution provider.
+
This tutorial describes installing and running an example JaxRS remote service on Karaf.  Developers can create and deploy arbitrary remote services by reusing the ECF RSA impl and the Jersey (or CXF) distribution provider.
 +
 
 +
For more recent versions of the Jersey and CXF distribution provider components see [https://github.com/ECF/JaxRSProviders this github repo] and the karaf-features.xml in the build directory.
  
 
Requirements:  [http://karaf.apache.org Karaf 4.2.1+ running on Java 8+]
 
Requirements:  [http://karaf.apache.org Karaf 4.2.1+ running on Java 8+]
Line 9: Line 11:
 
===Install Jersey Distribution Provider via Karaf Console===
 
===Install Jersey Distribution Provider via Karaf Console===
  
Add the ECF Remote Services features repo:
+
Add the ECF JaxRS Provider features repo:
 
<pre>
 
<pre>
karaf@root()>feature:repo-add ecf
+
karaf@root()>feature:repo-add https://raw.githubusercontent.com/ECF/JaxRSProviders/master/build/karaf-features.xml
 
</pre>
 
</pre>
Install the Jersey Distribution Provider
+
Install the Jersey Distribution Provider and dependencies
 
<pre>
 
<pre>
karaf@root()>feature:install ecf-rs-distribution-jersey
+
karaf@root()>feature:install -v ecf-rs-distribution-jersey
 
</pre>
 
</pre>
 +
 +
The -v option (verbose) will produce a lot of output describing the bundles downloaded and installed.
  
 
To properly run in Karaf the org.osgi.service.http.port system property must be set to the desired port:
 
To properly run in Karaf the org.osgi.service.http.port system property must be set to the desired port:
Line 24: Line 28:
 
</pre>
 
</pre>
  
and since Karaf uses the root path (/) of the HttpService, it's necessary to set an explicit pathPrefix
+
and since Karaf typically uses the root path (/) of the HttpService, it's necessary to set an explicit pathPrefix to something other than the default of '/'
  
 
<pre>
 
<pre>
karaf@root()> system:property -p ecf.jaxrs.jersey.server.pathPrefix /rservices
+
karaf@root()> system:property -p ecf.jaxrs.server.pathPrefix /rservices
 
</pre>
 
</pre>
  
'''NOTE:  These and other parts of the remote service URL can be explicitly via either system properties as above OR service-instance-specific service properties.  These system|service properties are described [https://github.com/ECF/JaxRSProviders/wiki/JaxRS-Distribution-Provider-Configuration-Properties here].'''  
+
'''NOTE:  These and other parts of the dynamically-constructed remote service URL can be set via system properties OR service-instance-specific service properties.  For the [[https://github.com/ECF/JaxRSProviders JaxRSProviders] the system or service properties are described [https://github.com/ECF/JaxRSProviders/wiki/JaxRS-Distribution-Provider-Configuration-Properties here].'''  
  
Shutdown and restart Karaf so that the org.osgi.service.http.port system property set can take effect on startup.
+
'''Shutdown and restart Karaf so that the org.osgi.service.http.port system property set can take effect on startup'''.
  
 
===JaxRS Student Example===
 
===JaxRS Student Example===
Line 49: Line 53:
 
<pre>
 
<pre>
 
karaf@root()> feature:install ecf-rs-examples-jaxrs-student-host
 
karaf@root()> feature:install ecf-rs-examples-jaxrs-student-host
16:17:04.904;EXPORT_REGISTRATION;exportedSR=[com.mycorp.examples.student.Student
+
20:44:37.637;EXPORT_REGISTRATION;exportedSR=[com.mycorp.examples.student.StudentService];cID=URIID [uri=http://localhost:8181/rservices/rs1];rsId=1
Service];cID=URIID [uri=http://localhost:8181/1];rsId=1
+
 
--Endpoint Description---
 
--Endpoint Description---
 
<endpoint-descriptions xmlns="http://www.osgi.org/xmlns/rsa/v1.0.0">
 
<endpoint-descriptions xmlns="http://www.osgi.org/xmlns/rsa/v1.0.0">
 
   <endpoint-description>
 
   <endpoint-description>
     <property name="ecf.endpoint.id" value-type="String" value="http://localhost:8181/1"/>
+
     <property name="ecf.endpoint.id" value-type="String" value="http://localhost:8181/rservices/rs1"/>
 
     <property name="ecf.endpoint.id.ns" value-type="String" value="ecf.namespace.jaxrs"/>
 
     <property name="ecf.endpoint.id.ns" value-type="String" value="ecf.namespace.jaxrs"/>
     <property name="ecf.endpoint.ts" value-type="Long" value="1530573424662"/>
+
     <property name="ecf.endpoint.ts" value-type="Long" value="1573015476480"/>
 +
    <property name="ecf.jaxrs.server.pathPrefix" value-type="String" value="/rs1"/>
 
     <property name="ecf.rsvc.id" value-type="Long" value="1"/>
 
     <property name="ecf.rsvc.id" value-type="Long" value="1"/>
     <property name="endpoint.framework.uuid" value-type="String" value="7473f8a1-f0ac-4146-8087-0558ed8e46aa"/>
+
     <property name="endpoint.framework.uuid" value-type="String" value="a77850ca-06b5-48f8-803b-467bb441e47c"/>
     <property name="endpoint.id" value-type="String" value="c9e3bb65-f157-40fe-b4bb-6c98c926ca03"/>
+
     <property name="endpoint.id" value-type="String" value="7cb088e9-76ec-49a3-96e6-f68ba62d20bd"/>
 
     <property name="endpoint.package.version.com.mycorp.examples.student" value-type="String" value="1.0.0"/>
 
     <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="162"/>
+
     <property name="endpoint.service.id" value-type="Long" value="155"/>
 
     <property name="objectClass" value-type="String">
 
     <property name="objectClass" value-type="String">
 
       <array>
 
       <array>
Line 67: Line 71:
 
       </array>
 
       </array>
 
     </property>
 
     </property>
     <property name="osgi.basic.timeout" value-type="String" value="50000"/>
+
     <property name="osgi.basic.timeout" value-type="String" value="5000000"/>
 
     <property name="remote.configs.supported" value-type="String">
 
     <property name="remote.configs.supported" value-type="String">
 
       <array>
 
       <array>
         <value>ecf.jaxrs.cxf.server</value>
+
         <value>ecf.jaxrs.jersey.server</value>
 
       </array>
 
       </array>
 
     </property>
 
     </property>
Line 87: Line 91:
 
     <property name="service.imported.configs" value-type="String">
 
     <property name="service.imported.configs" value-type="String">
 
       <array>
 
       <array>
         <value>ecf.jaxrs.cxf.server</value>
+
         <value>ecf.jaxrs.jersey.server</value>
 +
      </array>
 +
    </property>
 +
    <property name="service.intents" value-type="String">
 +
      <array>
 +
        <value>osgi.async</value>
 +
        <value>jaxrs</value>
 
       </array>
 
       </array>
 
     </property>
 
     </property>
    <property name="service.intents" value-type="String" value="osgi.async"/>
 
 
   </endpoint-description>
 
   </endpoint-description>
 
</endpoint-descriptions>
 
</endpoint-descriptions>
 
---End Endpoint Description
 
---End Endpoint Description
Discovered student service=com.mycorp.examples.student.remoteservice.host.StudentServiceImpl@51154196
+
Discovered student service=com.mycorp.examples.student.remoteservice.host.StudentServiceImpl@8bb24f7
Student0=Student [id=06f375e2-859d-4077-9bf4-edf8a1128439, name=Joe Senior, grade=First, address=Address [street=111 Park Ave, city=New York, state=NY, postalCode=11111]]
+
Student0=Student [id=6871a134-554b-4096-a56d-6f8c213f390d, name=Joe Senior, grade=First, address=Address [street=111 Park Ave, city=New York, state=NY, postalCode=11111]]
Updated Student0=Student [id=06f375e2-859d-4077-9bf4-edf8a1128439, name=Joe Senior, grade=Eighth, address=Address [street=111 Park Ave, city=New York, state=NY, postalCode=11111]]
+
Updated Student0=Student [id=6871a134-554b-4096-a56d-6f8c213f390d, name=Joe Senior, grade=Eighth, address=Address [street=111 Park Ave, city=New York, state=NY, postalCode=11111]]
Student=0=Student [id=06f375e2-859d-4077-9bf4-edf8a1128439, name=Joe Senior, grade=Eighth, address=Address [street=111 Park Ave, city=New York, state=NY, postalCode=11111]]
+
getStudentCF().Student0=Student [id=6871a134-554b-4096-a56d-6f8c213f390d, name=Joe Senior, grade=Eighth, address=Address [street=111 Park Ave, city=New York, state=NY, postalCode=11111]]
Created student=Student [id=ba408587-9546-45f2-b311-9b2d65c5761c, name=April Snow, grade=null, address=null]
+
Created student=Student [id=09b63a9b-338e-450a-99b3-cf2c3261cab3, name=April Snow, grade=null, address=null]
Updated student=Student [id=ba408587-9546-45f2-b311-9b2d65c5761c, name=April Snow, grade=First, address=Address [street=111 NE 1st, city=Austin, state=Oregon, postalCode=97200]]
+
Updated student=Student [id=09b63a9b-338e-450a-99b3-cf2c3261cab3, name=April Snow, grade=First, address=Address [street=111 NE 1st, city=Austin, state=Oregon, postalCode=97200]]
Deleted student=Student [id=ba408587-9546-45f2-b311-9b2d65c5761c, name=April Snow, grade=First, address=Address [street=111 NE 1st, city=Austin, state=Oregon, postalCode=97200]]
+
Deleted student=Student [id=09b63a9b-338e-450a-99b3-cf2c3261cab3, name=April Snow, grade=First, address=Address [street=111 NE 1st, city=Austin, state=Oregon, postalCode=97200]]
</pre>
+
20:44:40.321;EXPORT_REGISTRATION;exportedSR=[com.mycorp.examples.student.StudentService];cID=URIID [uri=http://localhost:8181/rservices/rs2];rsId=2
 +
--Endpoint Description---
 +
<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:8181/rservices/rs2"/>
 +
    <property name="ecf.endpoint.id.ns" value-type="String" value="ecf.namespace.jaxrs"/>
 +
    <property name="ecf.endpoint.ts" value-type="Long" value="1573015480268"/>
 +
    <property name="ecf.jaxrs.server.pathPrefix" value-type="String" value="/rs2"/>
 +
    <property name="ecf.rsvc.id" value-type="Long" value="2"/>
 +
    <property name="endpoint.framework.uuid" value-type="String" value="a77850ca-06b5-48f8-803b-467bb441e47c"/>
 +
    <property name="endpoint.id" value-type="String" value="0441de73-e6fd-4ef3-8436-6ea526f71ce4"/>
 +
    <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="158"/>
 +
    <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="50000"/>
 +
    <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>
 +
---End Endpoint Description</pre>
  
The output in between the '''--Start Endpoint Description--''' and '''---End Endpoint Description---''' is debug output from the [https://wiki.eclipse.org/Gogo_Commands_for_Remote_Services_Development ECF RSA Console] for the remote service export.   
+
The output in between the first '''--Start Endpoint Description--''' and '''---End Endpoint Description---''' is debug output from the [https://wiki.eclipse.org/Gogo_Commands_for_Remote_Services_Development ECF RSA Console] for the remote service export of the first remote service.   
  
 
The output that begins '''Discovered student service...''' is output from the StudentService consumer when the remote service is discovered and injected into the client component so that it can be called.  This output shows the invocation of the JaxRS remote service methods by the client component.
 
The output that begins '''Discovered student service...''' is output from the StudentService consumer when the remote service is discovered and injected into the client component so that it can be called.  This output shows the invocation of the JaxRS remote service methods by the client component.
  
Note that once exported via a Jax-RS supporting provider (currently Jersey and CXF), the getStudents() service method can be accessed directly via an http get call via the following url:
+
The output in between the second '''--Start Endpoint Description--''' and '''---End Endpoint Description---''' is debug output from the second exported remote service.
 +
 
 +
Note that once exported, the getStudents() service methods on the two remote services can be accessed directly via an http get call via the following url:
 +
 
 +
First exported remote service
 +
 
 +
http://localhost:8181/rservices/rs1/studentservice/students
 +
 
 +
Second exported remote service
 +
 
 +
http://localhost:8181/rservices/rs2/studentservice/students
  
http://localhost:8181/1/studentservice/students
+
The URL path of these remote services breaks down into the following components:
  
This is because the ecf.endpoint.id=http://localhost:8181/1, the StudentService path is set to '''studentservice''', and the StudentService.getStudents() method path is set to 'students'.
+
'''/rservices''' - Set by the value of system property:  -Decf.jaxrs.server.pathPrefix=/rservices
 +
'''/rs1''' or '''/rs2''' - Set by the value of the service property:  ecf.jaxrs.server.pathPrefix=/rs1 on [https://github.com/ECF/JaxRSProviders/blob/master/examples/com.mycorp.examples.student.remoteservice.host/src/com/mycorp/examples/student/remoteservice/host/StudentServiceImpl.java#L22 line 22 of the StudentServiceImpl] class (first remote service) and the value of the same service property on [https://github.com/ECF/JaxRSProviders/blob/master/examples/com.mycorp.examples.student.remoteservice.host/src/com/mycorp/examples/student/remoteservice/host/StudentServiceImpl2.java#L22 line 22 of StudentServiceImpl2] class (second remote service).
 +
'''/studentservice''' - Set by the value given to the [https://github.com/ECF/JaxRSProviders/blob/master/examples/com.mycorp.examples.student.remoteservice.host/src/com/mycorp/examples/student/remoteservice/host/StudentServiceImpl2.java#L19 @Path jaxrs annotation] the the remote service class declaration.
 +
'''/students''' - Set by the [https://github.com/ECF/JaxRSProviders/blob/master/examples/com.mycorp.examples.student.remoteservice.host/src/com/mycorp/examples/student/remoteservice/host/AbstractStudentService.java#L54 @Path jaxrs annotation] on the abstract superclass used by both the StudentServiceImpl and the StudentServiceImpl2 class.
  
 
For example:
 
For example:
  
 
<pre>
 
<pre>
$ curl http://localhost:8181/1/studentservice/students
+
$ curl http://localhost:8181/rservices/rs1/studentservice/students
 
{"students":[{"id":"24e7dfdb-b9e1-4540-a450-b0c19bf43ec9","name":"Joe Senior","grade":"Eighth","address":{"street":"111 Park Ave","city":"New York","state":"NY","postalCode":"11111"}}]}
 
{"students":[{"id":"24e7dfdb-b9e1-4540-a450-b0c19bf43ec9","name":"Joe Senior","grade":"Eighth","address":{"street":"111 Park Ave","city":"New York","state":"NY","postalCode":"11111"}}]}
 
</pre>
 
</pre>
  
'''Note:'''  It's also possible to run the test client on another system, e.g. from within Eclipse workspace using the '''StudentClient.jersey.product''' configuration located  [https://github.com/ECF/JaxRSProviders/tree/master/examples/com.mycorp.examples.student.client/launch here] in the '''com.mycorp.examples.student.client''' example project.
+
and
 +
 
 +
<pre>
 +
$ curl http://localhost:8181/rservices/rs2/studentservice/students
 +
{"students":[{"id":"24e7dfdb-b9e1-4540-a450-b0c19bf43ec9","name":"Joe Senior","grade":"Eighth","address":{"street":"111 Park Ave","city":"New York","state":"NY","postalCode":"11111"}}]}
 +
</pre>
  
 
The client/remote service consumer [https://github.com/ECF/JaxRSProviders/blob/master/examples/com.mycorp.examples.student.client/src/com/mycorp/examples/student/client/StudentServiceClient.java source code is here].
 
The client/remote service consumer [https://github.com/ECF/JaxRSProviders/blob/master/examples/com.mycorp.examples.student.client/src/com/mycorp/examples/student/client/StudentServiceClient.java source code is here].
  
==Using CXF impl of JaxRS Rather than Jersey==
+
===Install CXF Distribution Provider via Karaf Console===
  
To use CXF rather than Jersey, all that's necessary is to install the CXF server and client distribution providers rather than Jersey providers.
+
Add the CXF features repo:
 +
<pre>
 +
karaf@root()>feature:repo-add cxf
 +
</pre>
  
Add the ECF Remote Services features repo:
+
Add the ECF JaxRS Provider features repo:
 
<pre>
 
<pre>
karaf@root()>feature:repo-add ecf
+
karaf@root()>feature:repo-add https://raw.githubusercontent.com/ECF/JaxRSProviders/master/build/karaf-features.xml
 
</pre>
 
</pre>
Install the CXF Distribution Provider
+
Install the CXF Distribution Provider and dependencies
 
<pre>
 
<pre>
karaf@root()>feature:install ecf-rs-distribution-cxf
+
karaf@root()>feature:install -v ecf-rs-distribution-cxf
 
</pre>
 
</pre>
  
Set the org.osgi.service.http.port system property to the desired server port (8181):
+
The -v option (verbose) will produce a lot of output describing the bundles downloaded and installed.
 +
 
 +
To properly run in Karaf the org.osgi.service.http.port system property must be set to the desired port:
  
 
<pre>
 
<pre>
Line 143: Line 224:
 
</pre>
 
</pre>
  
Shutdown and restart Karaf so that the org.osgi.service.http.port system property set can take effect on startup.
+
and since Karaf typically uses the root path (/) of the HttpService, it's necessary to set an explicit pathPrefix to something other than the default of '/'
  
Once the CXF provider is installed, the StudentService example may be installed and run in the same way [[#JaxRS_Student_Example |as shown above]], but now the CXF implementation will be used as the distribution system for exporting and importing the StudentService.
+
<pre>
 
+
karaf@root()> system:property -p ecf.jaxrs.server.pathPrefix /rservices
'''Note''': Similar to the Jersey example above, there is a StudentExample.cxf.product configuration file that allows one to [https://github.com/ECF/JaxRSProviders/tree/master/examples/com.mycorp.examples.student.client/launch run the example client] from an Eclipse workspace.
+
</pre>
 
+
==Creating a Custom Distribution Provider By Configuring and/or Extending Jersey or CXF==
+
 
+
It's possible to reuse the existing ECF JaxRSProvider code to create your own new Remote Service Distribution provider, with custom security, serialization, filters, or interceptors.  Here are the existing/default Jersey and CXF providers:
+
 
+
'''[https://github.com/ECF/JaxRSProviders/tree/master/bundles/org.eclipse.ecf.provider.jersey.server org.eclipse.ecf.provider.jersey.server]'''
+
 
+
'''[https://github.com/ECF/JaxRSProviders/tree/master/bundles/org.eclipse.ecf.provider.jersey.client org.eclipse.ecf.provider.jersey.client]'''
+
 
+
and
+
 
+
'''[https://github.com/ECF/JaxRSProviders/tree/master/bundles/org.eclipse.ecf.provider.cxf.server org.eclipse.ecf.provider.cxf.server]'''
+
 
+
'''[https://github.com/ECF/JaxRSProviders/tree/master/bundles/org.eclipse.ecf.provider.cxf.client org.eclipse.ecf.providerjersey.client]'''
+
 
+
These distribution provider provide an example of how to do this, and are themselves extendable.  The general process is:
+
 
+
1) Create and register as an OSGi service (usually upon bundle start) an impl of IRemoteServiceDistributionProvider.  The distribution provider provides a unique name/config type.  For example,[https://github.com/ECF/JaxRSProviders/blob/master/bundles/org.eclipse.ecf.provider.jersey.server/src/org/eclipse/ecf/provider/jersey/server/JerseyServerDistributionProvider.java here is the JerseyServerContainer] for the default Jersey server distribution provider.
+
  
2) Implement the createInstance method of the distribution provider service class by returning a new subclass of '''JaxRSServerContainer'''.  For example, [https://github.com/ECF/JaxRSProviders/blob/master/bundles/org.eclipse.ecf.provider.jersey.server/src/org/eclipse/ecf/provider/jersey/server/JerseyServerContainer.java see the JerseyServerContainer as an example].
+
'''NOTE:  These and other parts of the dynamically-constructed remote service URL can be set via system properties OR service-instance-specific service properties.  For the [[https://github.com/ECF/JaxRSProviders JaxRSProviders] the system or service properties are described [https://github.com/ECF/JaxRSProviders/wiki/JaxRS-Distribution-Provider-Configuration-Properties here].'''
  
3) Override and implement methods in JaxRSServerContainer to configure your distribution provider as appropriate for Jersey or CXF.  For example, the [https://github.com/ECF/JaxRSProviders/blob/master/bundles/org.eclipse.ecf.provider.jersey.server/src/org/eclipse/ecf/provider/jersey/server/JerseyServerContainer.java the JerseyServerContainer] configures a custom Jersey Binding, as well as other extenstion.  Note that you may extend JerseyServerContainer and override the appropriate methods if desired to configure Jersey as desired for your remote service distribution provider in terms of filtering requests, serialization, invocation or any of the JaxRS-standard or Jersey-specific extensions.
+
'''Shutdown and restart Karaf so that the org.osgi.service.http.port system property set can take effect on startup'''.
  
==Remote Service Implementation Details==
+
==See Also==
  
See the [[Tutorial:_Exposing_a_Jax_REST_service_as_an_OSGi_Remote_Service | Exposing a Jax REST service as a Remote Service]] tutorial.
+
[[Extending the JaxRS Distribution Providers]]

Revision as of 18:28, 8 December 2019

Introduction

Jersey or CXF can be run on Karaf as an ECF distribution provider for remote services that use standard JaxRS annotations.

This tutorial describes installing and running an example JaxRS remote service on Karaf. Developers can create and deploy arbitrary remote services by reusing the ECF RSA impl and the Jersey (or CXF) distribution provider.

For more recent versions of the Jersey and CXF distribution provider components see this github repo and the karaf-features.xml in the build directory.

Requirements: Karaf 4.2.1+ running on Java 8+

Install Jersey Distribution Provider via Karaf Console

Add the ECF JaxRS Provider features repo:

karaf@root()>feature:repo-add https://raw.githubusercontent.com/ECF/JaxRSProviders/master/build/karaf-features.xml

Install the Jersey Distribution Provider and dependencies

karaf@root()>feature:install -v ecf-rs-distribution-jersey

The -v option (verbose) will produce a lot of output describing the bundles downloaded and installed.

To properly run in Karaf the org.osgi.service.http.port system property must be set to the desired port:

karaf@root()> system:property -p org.osgi.service.http.port 8181

and since Karaf typically uses the root path (/) of the HttpService, it's necessary to set an explicit pathPrefix to something other than the default of '/'

karaf@root()> system:property -p ecf.jaxrs.server.pathPrefix /rservices

NOTE: These and other parts of the dynamically-constructed remote service URL can be set via system properties OR service-instance-specific service properties. For the [JaxRSProviders the system or service properties are described here.

Shutdown and restart Karaf so that the org.osgi.service.http.port system property set can take effect on startup.

JaxRS Student Example

In this tutorial an example REST service is presented. The completed example bundles with source are available in the ECF JaxRSProviders repository. To run this example you may wish to clone this repo, and import into Eclipse these three projects: examples/com.mycorp.examples.student, examples/com.mycorp.examples.remoteservice.host, and examples/com.mycorp.examples.client.

Install JaxRS Student Example Service Client and Host

karaf@root()> feature:install ecf-rs-examples-jaxrs-student-client
karaf@root()> feature:install ecf-rs-examples-jaxrs-student-host

This should produce output indicating the StudentService was exported

karaf@root()> feature:install ecf-rs-examples-jaxrs-student-host
20:44:37.637;EXPORT_REGISTRATION;exportedSR=[com.mycorp.examples.student.StudentService];cID=URIID [uri=http://localhost:8181/rservices/rs1];rsId=1
--Endpoint Description---
<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:8181/rservices/rs1"/>
    <property name="ecf.endpoint.id.ns" value-type="String" value="ecf.namespace.jaxrs"/>
    <property name="ecf.endpoint.ts" value-type="Long" value="1573015476480"/>
    <property name="ecf.jaxrs.server.pathPrefix" value-type="String" value="/rs1"/>
    <property name="ecf.rsvc.id" value-type="Long" value="1"/>
    <property name="endpoint.framework.uuid" value-type="String" value="a77850ca-06b5-48f8-803b-467bb441e47c"/>
    <property name="endpoint.id" value-type="String" value="7cb088e9-76ec-49a3-96e6-f68ba62d20bd"/>
    <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="155"/>
    <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>
---End Endpoint Description
Discovered student service=com.mycorp.examples.student.remoteservice.host.StudentServiceImpl@8bb24f7
Student0=Student [id=6871a134-554b-4096-a56d-6f8c213f390d, name=Joe Senior, grade=First, address=Address [street=111 Park Ave, city=New York, state=NY, postalCode=11111]]
Updated Student0=Student [id=6871a134-554b-4096-a56d-6f8c213f390d, name=Joe Senior, grade=Eighth, address=Address [street=111 Park Ave, city=New York, state=NY, postalCode=11111]]
getStudentCF().Student0=Student [id=6871a134-554b-4096-a56d-6f8c213f390d, name=Joe Senior, grade=Eighth, address=Address [street=111 Park Ave, city=New York, state=NY, postalCode=11111]]
Created student=Student [id=09b63a9b-338e-450a-99b3-cf2c3261cab3, name=April Snow, grade=null, address=null]
Updated student=Student [id=09b63a9b-338e-450a-99b3-cf2c3261cab3, name=April Snow, grade=First, address=Address [street=111 NE 1st, city=Austin, state=Oregon, postalCode=97200]]
Deleted student=Student [id=09b63a9b-338e-450a-99b3-cf2c3261cab3, name=April Snow, grade=First, address=Address [street=111 NE 1st, city=Austin, state=Oregon, postalCode=97200]]
20:44:40.321;EXPORT_REGISTRATION;exportedSR=[com.mycorp.examples.student.StudentService];cID=URIID [uri=http://localhost:8181/rservices/rs2];rsId=2
--Endpoint Description---
<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:8181/rservices/rs2"/>
    <property name="ecf.endpoint.id.ns" value-type="String" value="ecf.namespace.jaxrs"/>
    <property name="ecf.endpoint.ts" value-type="Long" value="1573015480268"/>
    <property name="ecf.jaxrs.server.pathPrefix" value-type="String" value="/rs2"/>
    <property name="ecf.rsvc.id" value-type="Long" value="2"/>
    <property name="endpoint.framework.uuid" value-type="String" value="a77850ca-06b5-48f8-803b-467bb441e47c"/>
    <property name="endpoint.id" value-type="String" value="0441de73-e6fd-4ef3-8436-6ea526f71ce4"/>
    <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="158"/>
    <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="50000"/>
    <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>
---End Endpoint Description

The output in between the first --Start Endpoint Description-- and ---End Endpoint Description--- is debug output from the ECF RSA Console for the remote service export of the first remote service.

The output that begins Discovered student service... is output from the StudentService consumer when the remote service is discovered and injected into the client component so that it can be called. This output shows the invocation of the JaxRS remote service methods by the client component.

The output in between the second --Start Endpoint Description-- and ---End Endpoint Description--- is debug output from the second exported remote service.

Note that once exported, the getStudents() service methods on the two remote services can be accessed directly via an http get call via the following url:

First exported remote service

http://localhost:8181/rservices/rs1/studentservice/students

Second exported remote service

http://localhost:8181/rservices/rs2/studentservice/students

The URL path of these remote services breaks down into the following components:

/rservices - Set by the value of system property: -Decf.jaxrs.server.pathPrefix=/rservices /rs1 or /rs2 - Set by the value of the service property: ecf.jaxrs.server.pathPrefix=/rs1 on line 22 of the StudentServiceImpl class (first remote service) and the value of the same service property on line 22 of StudentServiceImpl2 class (second remote service). /studentservice - Set by the value given to the @Path jaxrs annotation the the remote service class declaration. /students - Set by the @Path jaxrs annotation on the abstract superclass used by both the StudentServiceImpl and the StudentServiceImpl2 class.

For example:

$ curl http://localhost:8181/rservices/rs1/studentservice/students
{"students":[{"id":"24e7dfdb-b9e1-4540-a450-b0c19bf43ec9","name":"Joe Senior","grade":"Eighth","address":{"street":"111 Park Ave","city":"New York","state":"NY","postalCode":"11111"}}]}

and

$ curl http://localhost:8181/rservices/rs2/studentservice/students
{"students":[{"id":"24e7dfdb-b9e1-4540-a450-b0c19bf43ec9","name":"Joe Senior","grade":"Eighth","address":{"street":"111 Park Ave","city":"New York","state":"NY","postalCode":"11111"}}]}

The client/remote service consumer source code is here.

Install CXF Distribution Provider via Karaf Console

Add the CXF features repo:

karaf@root()>feature:repo-add cxf

Add the ECF JaxRS Provider features repo:

karaf@root()>feature:repo-add https://raw.githubusercontent.com/ECF/JaxRSProviders/master/build/karaf-features.xml

Install the CXF Distribution Provider and dependencies

karaf@root()>feature:install -v ecf-rs-distribution-cxf

The -v option (verbose) will produce a lot of output describing the bundles downloaded and installed.

To properly run in Karaf the org.osgi.service.http.port system property must be set to the desired port:

karaf@root()> system:property -p org.osgi.service.http.port 8181

and since Karaf typically uses the root path (/) of the HttpService, it's necessary to set an explicit pathPrefix to something other than the default of '/'

karaf@root()> system:property -p ecf.jaxrs.server.pathPrefix /rservices

NOTE: These and other parts of the dynamically-constructed remote service URL can be set via system properties OR service-instance-specific service properties. For the [JaxRSProviders the system or service properties are described here.

Shutdown and restart Karaf so that the org.osgi.service.http.port system property set can take effect on startup.

See Also

Extending the JaxRS Distribution Providers

Back to the top