Accueil > Apache CXF, DOSGi, Eclipse RAP, Eclipse RCP, Equinox ServletBridge, Libra, WAR Product > Eclipse RCP/RAP and Remoting with JAX-RS, Spring Data JPA and CXF DOSGi [step4]

Eclipse RCP/RAP and Remoting with JAX-RS, Spring Data JPA and CXF DOSGi [step4]


In [step3] we have managed our UserService on Client and Server side with JAX-RS and Apache CXF DOSGi.

Embedding an HTTP server in Equinox

At this step the server side works with the HTTP Server Jetty which is an OSGi bundles. This mode is called Embedding an HTTP server in OSGi container : it means that HTTP server and WEB application are OSGi bundles. The OSGi container starts the HTTP server bundle. Embedding an HTTP server in Equinox explains how this mean is done with Equinox.

You can resume « embedding an HTTP server in OSGi container » like this :

OSGi container -> HTTP Server (bundle) -> WEB Application (bundle).

Equinox in a Servlet Container (ServletBridge)

It works great but sometimes you have not the luck to have an HTTP Server which supports OSGi like Apache Tomcat. For instance in our case, when we wished to deploy our XDocReport RAP Application on CloudBees, whish provides an Non OSGI HTTP Server Apache Tomcat.

Fortunatly, Server-Side Equinox provides Embedding OSGi container in a servlet container mode : it means that it’s a WEB Application which contains the OSGi container (and another bundles) which start the OSGi container. Equinox in a Servlet Container explains how this mean is done with Equinox.
You can resume « embedding OSGi container in a servlet container » like this :

HTTP Server -> WEB Application -> OSGi container.

To manage this mode you must create a classic WAR which hosts your OSGi plugins and ServletBridge. In this article we will explain how to create a WAR with our UserService on server side with the Eclipse Plug-In Libra WAR Product which was created for creating WAR from RAP Application launches. But it can be used too with OSGi launches (like we need in this article).

To create a WAR of CXF DOSGi application (server side), you must :

  • register your JAX-RS service with HttpService :
    <!-- HttpService -->
    <entry key="org.apache.cxf.rs.httpservice.context" value="/UserService" />
    
  • create a WAR which hosts OSGi bundles and ServletBridge. WAR Product gives you the capability to create a *.warproduct file from a launch (RAP, RCP, OSGi lanches, etc). This *.warproduct file is used to export it into a WAR to generate WAR.

At the end of this article we will create the the cxf-dosgi-jpa.war WAR. I have deployed this WAR on the CloudBees to see it on action. You can test for instance go at http://cxf-dosgi-war.opensagres.cloudbees.net/UserService/user/findAll to see JSON of the all users.

Download

WAR

You can download the following WAR that we will create in this article:

Bundles

You can download eclipse_spring_dosgi_step4.zip which contains the bundles and JARs explained in this article.

To use this zip, unzip it :

  1. import those projects in a workspace.
  2. open the TargetPlatform/eclipsespring.target file and click on Set as Target Platform. If you have problem with Target Definition, please read Problem with Install with Nebula (Incubation) P2.
  3. select TargetPlatform/launch/Server Remoting – JAXRS DOSGi – JPA Dao.launch to test the Remoting UserService JAX-RS with Mock Dao and Run it.
  4. select TargetPlatform/launch/Server Remoting – JAXRS DOSGi – JPA Dao.launch to test the Remoting UserService JAX-RS with JPA Dao and Run it.
  5. select TargetPlatform/launch/Client Remoting – JAXRS DOSGi – Simple OSGi Client.launch to test the Client Remoting UserService JAX-RS and Run it.

Prerequisite

Install WAR Product Plug-in

To follow this article you must install Eclipse Plug-In Libra WAR Product. To do that, please read Install WAR Product article.

Install RAP Target Platform.

To create a WAR from a WAR Product created by an OSGi launches, we need ServletBridge. The more easy mean is to install RAP Target Platform. To do that, open the TargetPlatform/eclipsespring_rap.target file and click on Set as Target Platform. If you have problem with Target Definition, please read Problem with Install with Nebula (Incubation) P2 :

Server Remoting – JAXRS DOSGi – JPA Dao [RAP TP]

The launch works with with Embedding an HTTP server in OSGi container mode, on other words the HTTP Server (Jetty) is an OSGi bundle. The OSGi container (Equinox) starts the HTTP Server which is a n OSGi bundle.

The Server Remoting – JAXRS DOSGi – JPA Dao launch was created when RCP Target Platform was activated. Now we have activated RAP Target Platform, so we need adjust a little this launch. To do that duplicate Server Remoting – JAXRS DOSGi – JPA Dao to Server Remoting – JAXRS DOSGi – JPA Dao [RAP TP].

After that, you must modify the launch, by selecting:

  • javax.servlet.

and selecting:

  • org.eclipse.equinox.console.
  • org.apache.felix.gogo.shell.
  • org.apache.felix.gogo.runtime.

to avoid having this error :

!MESSAGE Could not find bundle: org.eclipse.equinox.console
!STACK 0
org.osgi.framework.BundleException: Could not find bundle: org.eclipse.equinox.console
	at org.eclipse.osgi.framework.internal.core.ConsoleManager.checkForConsoleBundle(ConsoleManager.java:211)
fr.opensagres.dao.jpa.eclipselink

Run the launch, open a WEB Browser and go at http://127.0.0.1:9000/fr/opensagres/services/UserService/user/findAll , you will see JSON content :

{"user":[{"firstName":"Angelo","lastName":"Zerr"},{"firstName":"Pascal","lastName":"Leclercq"},{"firstName":"Amine","lastName":"Bousta"},{"firstName":"Mickael","lastName":"Baron"},{"firstName":"Jawher","lastName":"Moussa"},{"firstName":"Arnaud","lastName":"Cogoluegnes"},{"firstName":"Lars","lastName":"Vogel"},{"firstName":"Olivier","lastName":"Gierke"},{"firstName":"Tom","lastName":"Schindl"},{"firstName":"Wim","lastName":"Jongman"}]}

Server Remoting – JAXRS DOSGi – Mock Dao [RAP TP]

You can do the same thing for the Mock Dao by creating the Server Remoting – JAXRS DOSGi – Mock Dao [RAP TP] by duplicating the Server Remoting – JAXRS DOSGi – Mock Dao launch.

Modify fr.opensagres.dao.jpa.eclipselink

Remove the .qualifier used in the OSGi Fragment fr.opensagres.dao.jpa.eclipselink for Hosts:

to avoid having this error

when WAR will be generated. For more information please read Create a WAR from RAP Application with Libra WAR Product [step3].

HttpService

ServletBridge works with « Equinox in a Servlet Container (ServletBridge) » mode, it means that it’s classic WEB Application with web.xml which declares ServletBridge servlet. This servlet starts the OSGi container Equinox. This ServletBridge provides too an implementation of HttpService which is registered in the OSGi services registry. The HttpService gives the capability to register/unregister a Servlet.

To use ServletBridge with CXF DOSGi, the JAX-RS service must be registered in the HttpService.

Manage ONLY Equinox in a Servlet Container (ServletBridge)

The section Service Provider properties For Configuring RESTful JAXRS-based endpoints and consumers shows you that it’s possible to do that with the org.apache.cxf.rs.httpservice.context property.

In our case we will do that:

<!-- HttpService -->
<entry key="org.apache.cxf.rs.httpservice.context" value="/UserService" />

and our service will be available with /UserService path like http://cxf-dosgi-war.opensagres.cloudbees.net/UserService?_wadl whish shows you the WADL of the UserService on the CloudBees.

Modify the META-INF/spring/module-osgi-context.xml of the fr.opensagres.remoting.exporter.dosgi.jaxrs bundle like this:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:osgi="http://www.springframework.org/schema/osgi"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                      http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">

	<osgi:reference id="userService" interface="fr.opensagres.services.UserService" />

	<osgi:service interface="fr.opensagres.services.UserService">
		<osgi:service-properties>
			<entry key="service.exported.interfaces" value="*" />
			<entry key="service.exported.configs" value="org.apache.cxf.rs" />
			<entry key="service.exported.intents" value="HTTP" />
			<entry key="org.apache.cxf.rs.databinding" value="jaxb" />
			<!-- Logs -->
			<entry key="org.apache.cxf.rs.in.interceptors" value="org.apache.cxf.interceptor.LoggingInInterceptor" />
			<entry key="org.apache.cxf.rs.out.interceptors" value="org.apache.cxf.interceptor.LoggingOutInterceptor" />
			<!-- JAXB Context -->
			<entry key="org.apache.cxf.rs.provider">
				<array>
					<ref bean="jsonProvider" />
				</array>
			</entry>
			<!-- HttpService -->
			<entry key="org.apache.cxf.rs.httpservice.context" value="/UserService" />
		</osgi:service-properties>
		<ref bean="userService" />
	</osgi:service>

	<bean id="jsonProvider" class="org.apache.cxf.jaxrs.provider.JSONProvider">
		<property name="singleJaxbContext" value="true" />
		<property name="extraClass">
			<list>
				<value>fr.opensagres.domain.User</value>
			</list>
		</property>
	</bean>

</beans>

At this step we can create a WAR Product to export after the WAR, but we will do that after.

Manage « Embedding an HTTP server in OSGi container » and « Equinox in a Servlet Container (ServletBridge) » both

At this step, our JAX-RS UserService works with HttpService. If you start the launch Server Remoting – JAXRS DOSGi – JPA Dao [RAP TP] you will see this error :

INFO: ListenerHookImpl: skipping import request for excluded classs [org.osgi.service.http.HttpService]
6094 [pool-1-thread-1] INFO  org.apache.cxf.dosgi.dsw.service.RemoteServiceAdminCore  - found handler for fr.opensagres.services.UserService  -> org.apache.cxf.dosgi.dsw.handlers.JaxRSHttpServiceConfigurationTypeHandler@d3199e
Exception in thread "pool-1-thread-1" org.osgi.framework.ServiceException: CXF DOSGi: No HTTP Service could be found to publish CXF endpoint in.
	at org.apache.cxf.dosgi.dsw.handlers.HttpServiceConfigurationTypeHandler.getHttpService(HttpServiceConfigurationTypeHandler.java:235)
...

This error comes from that there is none HttpService registered because we are in Embedding an HTTP server in OSGi container mode. It’s possible to manage the both mode by setting the property org.apache.cxf.rs.httpservice.context with dynamic mean:

<!-- HttpService -->
<entry key="${httpservice-config.key}" value="/UserService" />

The (optional) ${httpservice-config.key} value :

  • for Embedding an HTTP server in OSGi container mode: is not defined. It means that you will do that :
    <!-- HttpService -->
    <entry key="${httpservice-config.key}" value="/UserService" />
    

    and HttpService for CXF DOSGi will be disabled.

  • for Equinox in a Servlet Container (ServletBridge) mode : it comes from a property file httpservice-config.properties which is hosted by the fr.opensagres.remoting.exporter.dosgi.jaxrs-httpservice fragment linked to the fr.opensagres.remoting.exporter.dosgi.jaxrs bundle with this content :
    httpservice-config.key=org.apache.cxf.rs.httpservice.context
    

    It means that you will do that :

    <!-- HttpService -->
    <entry key="org.apache.cxf.rs.httpservice.context" value="/UserService" />
    

    and HttpService will be used to register our UserService with CXF DOSGi with /UserService path.

Use ${httpservice-config.key}

To use optional ${httpservice-config.key} we need to define a property-placeholder like this:

<context:property-placeholder location="classpath:httpservice-config.properties"
		ignore-resource-not-found="true" ignore-unresolvable="true" />

The attribute :

  • ignore-resource-not-found= »true » means that if httpservice-config.properties field is not found, Spring doesn’t throw an error (in the case of Embedding an HTTP server in OSGi container mode.
  • ignore-unresolvable= »true » means that the use of ${httpservice-config.key} will not throw an error if it doesn’t found (in the case of Embedding an HTTP server in OSGi container mode.

Modify the META-INF/spring/module-osgi-context.xml of the fr.opensagres.remoting.exporter.dosgi.jaxrs bundle like this:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:osgi="http://www.springframework.org/schema/osgi"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/osgi  
       http://www.springframework.org/schema/osgi/spring-osgi-1.0.xsd
       http://www.springframework.org/schema/beans   
       http://www.springframework.org/schema/beans/spring-beans.xsd
	   http://www.springframework.org/schema/context 
	   http://www.springframework.org/schema/context/spring-context.xsd">

	<context:property-placeholder location="classpath:httpservice-config.properties"
		ignore-resource-not-found="true" ignore-unresolvable="true" />
		
	<osgi:reference id="userService" interface="fr.opensagres.services.UserService" />

	<osgi:service interface="fr.opensagres.services.UserService">
		<osgi:service-properties>
			<entry key="service.exported.interfaces" value="*" />
			<entry key="service.exported.configs" value="org.apache.cxf.rs" />
			<entry key="service.exported.intents" value="HTTP" />
			<entry key="org.apache.cxf.rs.databinding" value="jaxb" />
			<!-- Logs -->
			<entry key="org.apache.cxf.rs.in.interceptors" value="org.apache.cxf.interceptor.LoggingInInterceptor" />
			<entry key="org.apache.cxf.rs.out.interceptors" value="org.apache.cxf.interceptor.LoggingOutInterceptor" />
			<!-- JAXB Context -->
			<entry key="org.apache.cxf.rs.provider">
				<array>
					<ref bean="jsonProvider" />
				</array>
			</entry>
			<!-- HttpService -->
			<entry key="${httpservice-config.key}" value="/UserService" />
		</osgi:service-properties>
		<ref bean="userService" />
	</osgi:service>

	<bean id="jsonProvider" class="org.apache.cxf.jaxrs.provider.JSONProvider">
		<property name="singleJaxbContext" value="true" />
		<property name="extraClass">
			<list>
				<value>fr.opensagres.domain.User</value>
			</list>
		</property>
	</bean>

</beans>

If you start the launch Server Remoting – JAXRS DOSGi – JPA Dao [RAP TP] you will see that it’s work.

fr.opensagres.remoting.exporter.dosgi.jaxrs-httpservice

Create the OSGI fragment fr.opensagres.remoting.exporter.dosgi.jaxrs-httpservice linked to the fr.opensagres.remoting.exporter.dosgi.jaxrs OSGi bundle.

In this fragment, create the src/httpservice-config.properties with this content:

httpservice-config.key=org.apache.cxf.rs.httpservice.context

Create WAR Product

In this section we will create WAR Product from the OSGi Server Remoting – JAXRS DOSGi – JPA Dao [RAP TP] launch like explained in the Create WAR Product article. Once the WAR Product will be created, we will add the fragment fr.opensagres.remoting.exporter.dosgi.jaxrs-httpservice to the WAR Product Configuration.

Create the TargetPlatform/warproducts/cxf-dosgi-jpa folder which will hosts the cxf-dosgi-jpa.warproduct :

Go to the File/New/Other… menu item, select Plug-in Development/WAR Product Configuration and click on Next button:

The New WAR Product Configuration wizard is displayed:

  1. Select the TargetPlatform/warproducts/cxf-dosgi-jpa folder.
  2. fill File name field with cxf-dosgi-jpa.warproduct.
  3. select the Server Remoting – JAXRS DOSGi – JPA Dao [RAP TP] launch because we will create a WAR Product from this launch.

Click on Finish button to generate the WAR Product:

With the WAR Product Editor, Add the fr.opensagres.remoting.exporter.dosgi.jaxrs-httpservice fragment (to register the UserService with HttpService) with the Add button :

Create WAR

At this step we can generate the WAR by following the Create a WAR from RAP Application with Libra WAR Product [step3] article.

Validate WAR product

Before creating WAR, click on Validate WAR product menu item to check you have not problem with Plug-Ins/Fragments of the WAR Product:

Export WAR product

If you have none errors, we can start exporting the WAR. To do that, click on Export WAR product menu item:

This action opens the Export dialog :

  • choose the file name of the generated WAR (here we will export WAR to generate the C:\cxf-dosgi-jpa.war).
  • select the « Allow for binary cycles in target platform » checkbox.

Click on Finish button which starts the export of the WAR.

Test WAR cxf-dosgi-jpa.war

At this step we can test our WAR. In my case, I have tested the WAR with Apache Tomcat and follow thoses steps:

  • Install Apache Tomcat.
  • Copy/paste the cxf-dosgi-jpa.war in the webapps folder of the root of the Tomcat.
  • Start the Tomcat on the 8080 port by using the bin/startup.bat (or startup.sh).

Web Browser

Once the HTTP Server has deployed the war, tries to go to the URL http://127.0.0.1:8080/cxf-dosgi-jpa/UserService/user/findAll and you will see the JSON of the user list :

{"user":[{"firstName":"Angelo","lastName":"Zerr"},{"firstName":"Pascal","lastName":"Leclercq"},{"firstName":"Amine","lastName":"Bousta"},{"firstName":"Mickael","lastName":"Baron"},{"firstName":"Jawher","lastName":"Moussa"},{"firstName":"Arnaud","lastName":"Cogoluegnes"},{"firstName":"Lars","lastName":"Vogel"},{"firstName":"Olivier","lastName":"Gierke"},{"firstName":"Tom","lastName":"Schindl"},{"firstName":"Wim","lastName":"Jongman"}]}

Our CXF DOSGi application works now with a WAR!

JAX-RS Clients

Now we will test our WAR with our OSGI, RCP and RAP launches. To do that we need just modify the module-osgi-context.xml of the fr.opensagres.remoting.importer.dosgi.jaxrs bundle :

<jaxrs:client id="jaxrsUserService"
	address="${jaxrs-config.base-url}/fr/opensagres/services/UserService"

with this new content :

<jaxrs:client id="jaxrsUserService"
	address="${jaxrs-config.base-url}/UserService"

Equinox in a Servlet Container (ServletBridge) – Localhost

To test with your Local Apache Tomcat, modify the base-url like this :

jaxrs-config.base-url=http://127.0.0.1:8080/cxf-dosgi-jpa/

Start the Client Remoting – JAXRS DOSGi – Simple OSGi Client or (Client Remoting – JAXRS DOSGi – Simple OSGi Client [RAP TP] if you have RAP Target Platform activated) launch, to check it works. You can test too RCP (Client Remoting – JAXRS DOSGI – RCP Client) and RAP (Client Remoting – JAXRS DOSGI – RAP Client) launches.

Cloudbees

The cxf-dosgi-jpa.war was deployed on CloudBees. You can test URLs with Web Browser like:

To test with WAR deployed on CloudBees, modify the base-url like this :

jaxrs-config.base-url=http://cxf-dosgi-war.opensagres.cloudbees.net

Start the Client Remoting – JAXRS DOSGi – Simple OSGi Client or (Client Remoting – JAXRS DOSGi – Simple OSGi Client [RAP TP] if you have RAP Target Platform activated) launch, to check it works. You can test too RCP (Client Remoting – JAXRS DOSGI – RCP Client) and RAP (Client Remoting – JAXRS DOSGI – RAP Client) launches.

Embedding an HTTP server in Equinox – Localhost with Jetty

To test with OSGI Jetty (launch Server Remoting – JAXRS DOSGi – JPA Dao [RAP TP]), modify the base-url like this :

jaxrs-config.base-url=http://127.0.0.1:9000/fr/opensagres/services

Start the Client Remoting – JAXRS DOSGi – Simple OSGi Client or (Client Remoting – JAXRS DOSGi – Simple OSGi Client [RAP TP] if you have RAP Target Platform activated) launch, to check it works. You can test too RCP (Client Remoting – JAXRS DOSGI – RCP Client) and RAP (Client Remoting – JAXRS DOSGI – RAP Client) launches.

Conclusion

In this article we have seen how to create a WAR for a CXF DOSGi Application by using WAR Product which is created from OSGi launches and give you the capability to export a WAR with ServletBridge.

  1. Ilias
    août 3, 2012 à 2:11

    Hi there,
    First off thank you very much for this great article. It did help me a lot.
    I tried to deploy the war into Tomcat and it worked, but tried too with Websphere and it didn’t.
    Do you have any idea the reason behind the failure?

    Thank you in advance

    • août 3, 2012 à 2:25

      Hi lilas,

      No sorry I cannot help you. Problem with Websphere is that it override a lot of standard JAR and it causes problem (with OSGi, RAP, CXF etc).
      I suggest you to post your question on CXF forum or RAP forum according your problem.

      Good luck.

      Regards Angelo

      • Ilias
        août 6, 2012 à 5:35

        Thanks Angelo for your quick response🙂

      • Ilias
        août 7, 2012 à 2:41

        Hi Angelo,
        Thanks again for your post. I did manage to get the WAR works within both Websphere/Tomcat. It’s just a matter of configuration regarding the classloader strategy (put it as Classes loaded with local class loader first(parent last)).

        Thanks again

  2. décembre 3, 2013 à 2:51

    Hi Angelo
    I’m struggling with Spring Data and OSGI.
    Trying to use the actual Spring data doesn’t know the jpa:repository tag as used in your example. Do you have an example how to make OSGI know about spring data repositories? What du you suggest – usijng Spring DM or gemini blueprint?

    Thanks
    Rene

    • décembre 3, 2013 à 2:55

      Hi rene,

      I’m sorry, I cannot help you more. It was so long time that I have not played with Spring Data.

      Please post your question on Spring Data forum.

      Regards Angelo

      • décembre 3, 2013 à 3:00

        thanks Angelo, I’ll try

  1. novembre 30, 2012 à 2:19

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

%d blogueurs aiment cette page :