Nous allons voir comment créer simplement une façade REST avec camel-cxf et la déployer dans un container OSGi.
Voici les versions utilisées :
Commençons tout d'abord par le pom du projet :
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.netapsys</groupId>
<artifactId>blog</artifactId>
<version>1.0.0</version>
<packaging>bundle</packaging>
<dependencies>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-cxf</artifactId>
<version>2.13.2</version>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Import-Package>*</Import-Package>
<Export-Package>!*</Export-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
pom.xml
et le code de la façade :
package com.netapsys.blog.facade;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
/**
* Blog facade
* @author ssenouci
*
*/
@Path("/")
public class BlogFacade {
/**
* Ask visitor's name
* @return
*/
@GET
@Path("/")
public String askName() {
return "";
}
/**
* Receive visitor's name
* @param content Visitor's name
* @return
*/
@POST
@Path("/")
public String receiveName(String content) {
return "";
}
}
BlogFacade.java
La façade comprend deux méthodes :
- askName() : bindée sur la méthode HTTP GET. Elle permettra de demander à l'utilisateur son nom.
- receiveName(String content) : bindée sur la méthode HTTP POST. Elle permettra de récupérer le nom de l'utilisateur
Pour traiter les requêtes HTTP, nous allons nous servir du composant camel-cxf.
Voici la route à utiliser :
package com.netapsys.blog.facade.route;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.builder.RouteBuilder;
/**
* Route used to process blog REST requests.
* @author ssenouci
*
*/
public class BlogFacadeRoute extends RouteBuilder {
/**
* Blog facade URI.
*/
private String blogFacadeUri;
/**
* Ask name URI
*/
private static final String ASK_NAME_URI = "direct:askName";
/**
* Receive name URI
*/
private static final String RECEIVE_NAME_URI = "direct:receiveName";
/* (non-Javadoc)
* @see org.apache.camel.builder.RouteBuilder#configure()
*/
@Override
public void configure() throws Exception {
from(blogFacadeUri)
.routeId(blogFacadeUri)
// Redirect exchange to matching route
.recipientList(simple("direct:${header.operationName}"));
// Route handling askName facade method requests / messages
from(ASK_NAME_URI)
.routeId(ASK_NAME_URI)
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
exchange.getOut().setBody("Hi. What's your name ?");
}
})
.end();
// Route handling receiveName facade method requests / messages
from(RECEIVE_NAME_URI)
.routeId(RECEIVE_NAME_URI)
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
exchange.getOut().setBody("Welcome " + exchange.getIn().getBody(String.class));
}
})
.end();
}
public void setBlogFacadeUri(String blogFacadeUri) {
this.blogFacadeUri = blogFacadeUri;
}
}
BlogFacadeRoute.java
Le point d'entrée de la route est bindé sur l'URI de la façade et chaque exchange sera redirigé vers une sous-route (appelée en direct), dont l'URI est défini par le nom de la méthode appelée dans la façade.
Pour terminer, voici le blueprint de notre bundle :
<?xml version="1.0" encoding="UTF-8"?><blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cxf="http://camel.apache.org/schema/blueprint/cxf"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://camel.apache.org/schema/blueprint/cxf http://camel.apache.org/schema/blueprint/cxf/camel-cxf.xsd">
<!-- Facade definitions -->
<cxf:rsServer id="blogFacade" address="/blog" serviceClass="com.netapsys.blog.facade.BlogFacade"/>
<!-- Route definitions -->
<bean id="blogFacadeRoute" class="com.netapsys.blog.facade.route.BlogFacadeRoute">
<property name="blogFacadeUri" value="cxfrs:bean:blogFacade?bindingStyle=SimpleConsumer" />
</bean>
<!-- Camel context definition -->
<camelContext id="blogCamelContext" autoStartup="true" trace="true" xmlns="http://camel.apache.org/schema/blueprint">
<routeBuilder ref="blogFacadeRoute" />
</camelContext>
</blueprint>
blueprint.xml
dans lequel nous retrouvons :
- La déclaration de la façade et du path auquel elle sera associée.
- La déclaration de la route, dans laquelle nous injectons l'URI de la façade.
Et voilà, c'est tout pour la partie code.
Passons à présent au déploiement. Voici le features repository associé à notre projet :
<?xml version="1.0" encoding="UTF-8"?>
<features xmlns="http://karaf.apache.org/xmlns/features/v1.0.0" name="blog-1.0.0">
<repository>mvn:org.apache.camel.karaf/apache-camel/2.13.2/xml/features</repository>
<!-- Project features -->
<feature name="com.netapsys.blog" version="1.0.0">
<feature>camel-http</feature>
<feature>camel-blueprint</feature>
<feature>camel-cxf</feature>
<bundle>mvn:com.netapsys/blog/1.0.0</bundle>
</feature>
</features>
features.xml
La feature com.netapsys.blog déploiera les features camel-http, camel-blueprint, camel-cxf ainsi que notre bundle.
Pour ce faire, démarrons Karaf et enregistrons notre features repository :
feature:repo-add mvn:com.netapsys/features/1.0.0/xml/features
Puis, installons notre feature :
feature:install com.netapsys.blog
L'appel en GET à l'URL http://localhost:8181/cxf/blog nous retourne bien la réponse suivante :
Hi. What's your name ?
Et l'appel en POST avec le body "John Doe" nous retourne "Welcome John Doe" comme escompté.