Shows how to publish and use a simple REST and SOAP service in karaf using cxf and blueprint.

To run the example you need to install the http feature of karaf. The default http port is 8080 and can be configured using the config admin pid “org.ops4j.pax.web”. You also need to install the cxf feature. The base url of the cxf servlet is by default “/cxf”. It can be configured in the config pid “org.apache.cxf.osgi”.

If you use Talend ESB instead of plain karaf then the default http port is 8044 and the default cxf servlet name is “/services”.

PersonService Example

You can find the full source on github.

The “business case” is to manage a list of persons. As service should provide the typical CRUD operations. Front ends should be a REST service, a SOAP service and a web UI.

Image

The example consists of four projects

Installation and test run

First we build, install and run the example to give an overview of what it does. The following main chapter then explains in detail how it works.

Installing Karaf and preparing for CXF

We start with a fresh Karaf 4.0.4

mvn clean install
Install service and ui in karaf
feature:repo-add cxf 3.1.5
feature:install http cxf-jaxws http-whiteboard
install -s mvn:net.lr.tutorial.karaf.cxf.personservice/personservice-model/1.0-SNAPSHOT
install -s mvn:net.lr.tutorial.karaf.cxf.personservice/personservice-server/1.0-SNAPSHOT
install -s mvn:net.lr.tutorial.karaf.cxf.personservice/personservice-proxy/1.0-SNAPSHOT
install -s mvn:net.lr.tutorial.karaf.cxf.personservice/personservice-webui/1.0-SNAPSHOT

Test the service

The person service should show up in the list of currently installed services that can be found here http://localhost:8181/cxf/

Test the proxy and web UI http://localhost:8181/personui

You should see the list of persons managed by the personservice and be able to add new persons.

How it works

Defining the model

The model project is a simple java maven project that defines a JAX-WS service and a JAXB data class. It has no dependencies to cxf. The service interface is just a plain java interface with the @WebService annotation.

@WebService
public interface PersonService {
    public abstract Person[] getAll();
    public abstract Person getPerson(String id);
    public abstract void updatePerson(String id, Person person);
    public abstract void addPerson(Person person);
}

The Person class is just a simple pojo with getters and setters for id, name and url and the necessary JAXB annotations. Additionally you need an ObjectFactory to tell JAXB what xml element to use for the Person class. There is also no special code for OSGi in this project. So the model works perfectly inside and outside of an OSGi container.

The service is defined java first. SOAP and rest are used quite transparently. This is very suitable to communicate between a client and server of the same application. If the service is to be used by other applications the wsdl first approach is more suitable. In this case the model project should be configured to generate the data classes and service interface from a wsdl (see cxf wsdl_first example pom file). For rest services the java first approach is quite common in general as the client typically does not use proxy classes anyway.

Service implementation (server)

PersonServiceImpl is a java class the implements the service interface. The server project also contains a small starter class that allows the service to be published directly from eclipse. This class is not necessary for deployment in karaf.

The production deployment of the service is done in src/main/resources/OSGI-INF/blueprint/blueprint.xml.

As the file is in the special location OSGI-INF/blueprint it is automatically processed by the blueprint implementation aries in karaf. The REST service is published using the jaxrs:server element and the SOAP service is published using the jaxws:endpoint element. The blueprint namespaces are different from spring but apart from this the xml is very similar to a spring xml.

Service proxy

The service proxy project only contains a blueprint xml that uses the CXF JAXWS client to consume the SOAP service and exports it as an OSGi Service. Encapsulating the service client as an OSGi service (proxy project) is not strictly necessary but it has the advantage that the webui is then completely independent of cxf. So it is very easy to change the way the service is accessed. So this is considered a best practice in OSGi.

See blueprint.xml

Web UI (webui)

This project consumes the PersonService OSGi service and exports the PersonServlet as an OSGi service. The pax web whiteboard extender will then publish the servlet on the location /personui. The PersonServlet gets the PersonService injected and uses to get all persons and also to add persons.

The wiring is done using a blueprint context.

PersonService REST

The personservice REST example is very similar to to SOAP one but it uses jaxrs to expose a REST service instead.

The example can be found in github Karaf-Tutorial cxf personservice-rest. It contains these modules:

Build

mvn clean install

Install

feature:repo-add cxf 3.1.5
feature:install cxf-jaxrs http-whiteboard
install -s mvn:net.lr.tutorial.karaf.cxf.personrest/personrest-model/1.0-SNAPSHOT
install -s mvn:net.lr.tutorial.karaf.cxf.personrest/personrest-server/1.0-SNAPSHOT
install -s mvn:net.lr.tutorial.karaf.cxf.personrest/personrest-webui/1.0-SNAPSHOT

How it works The interface of the service must contain jaxrs annotations to tell CXF how to map rest requests to the methods.

@Produces(MediaType.APPLICATION_XML)
public interface PersonService {
    @GET
    @Path("/")
    public Person[] getAll();

    @GET
    @Path("/{id}")
    public Person getPerson(@PathParam("id") String id);

    @PUT
    @Path("/{id}")
    public void updatePerson(@PathParam("id") String id, Person person);

    @POST
    @Path("/")
    public void addPerson(Person person);
}

In blueprint the implementation of the rest service needs to be published as a REST resource:

<bean id="personServiceImpl" class="net.lr.tutorial.karaf.cxf.personrest.impl.PersonServiceImpl"/>

<jaxrs:server address="/person" id="personService">
    <jaxrs:serviceBeans>
        <ref component-id="personServiceImpl" />
    </jaxrs:serviceBeans>
    <jaxrs:features>
        <cxf:logging />
    </jaxrs:features>
</jaxrs:server>

Test the service

The person service should show up in the list of currently installed services that can be found here http://localhost:8181/cxf/

List the known persons

http://localhost:8181/cxf/person This should show one person “chris”

Add a person

Now using a firefox extension like Poster or Httprequester you can add a person.

Send the following xml snippet:

<?xml version="1.0" encoding="UTF-8"?>
<person>
    <id>1001</id>
    <name>Christian Schneider</name>
    <url>http://www.liquid-reality.de</url>
</person>

with Content-Type:text/xml using PUT:http://localhost:8181/cxf/person/1001 or to this url using POST:http://localhost:8181/cxf/person

Now the list of persons should show two persons.

Now using a firefox extension like Poster or Httprequester you can add a person. Send the content of server/src/test/resources/person1.xml to the following url using PUT: http://localhost:8181/cxf/person/1001

Or to this url using POST: http://localhost:8181/cxf/person

Now the list of persons should show two persons

Test the web UI http://localhost:8181/personuirest

You should see the list of persons managed by the personservice and be able to add new persons.

Some further remarks

The example uses blueprint instead of spring dm as it works much better in an OSGi environment. The bundles are created using the maven bundle plugin. A fact that shows how well blueprint works is that the maven bundle plugin is just used with default settings. In spring dm the imports have to be configured as spring needs access to many implementation classes of cxf. For spring dm examples take a look at the Talend Service Factory examples (https://github.com/Talend/tsf/tree/master/examples).

The example shows that writing OSGi applications is quite simple with aries and blueprint. It needs only 153 lines of java code (without comments) for a complete little application. The blueprint xml is also quite small and readable.

Back to Tutorials