Home

Awesome

Instructions

The MicroService Camel REST in action project consists of 2 maven modules camel-rest-client and camel-rest-service; one contain the code to play the role of a client sending HTTP requests and calling a REST Service exposed by another project. They both will be created as Microservice as they will be able to run into their own JVM, Container, without any ESB Bus, will be managed separately and independently.

Openshift Microservice

Prerequisites

Project creation

iPaas Archetype

mvn archetype:generate
...
19: remote -> io.fabric8.archetypes:cdi-camel-http-archetype (Creates a new Camel route using CDI in a standalone Java Container calling the remote camel-servlet quickstart))
...
Using these parameters

Archetype Version : 2.2.88
Archetype name : cdi-camel-http-archetype
Project : camel-rest-client
Package : org.jboss.fuse
Version: 1.0-SNAPSHOT

This archetype will be used as input to create a Camel route using the CDI Framework to inject the Beans and start the CamelContext. The purpose of the Apache Camel Route will be to send every 5s a message a HTTP request to the REST service using a Netty4-HTTP Endpoint as described hereafter.

@ContextName("myCdiCamelContext")
public class MyRoutes extends RouteBuilder {

    @Inject
    @Uri("timer:foo?period=5000")
    private Endpoint inputEndpoint;

    @Inject
    /** Local **/
    @Uri("netty4-http:http://localhost:8080?keepalive=false&disconnect=true")

    /** Docker Container **/
    //@Uri("netty4-http:http://172.17.0.8:8080?keepalive=false&disconnect=true")

    /** Pod Container + Kubernetes Service  **/
    //@Uri("netty4-http:http://{{service:hellorest}}?keepalive=false&disconnect=true")
    private Endpoint httpEndpoint;

    @Inject
    private SomeBean someBean;

    @Override
    public void configure() throws Exception {
        // you can configure the route rule with Java DSL here

        from(inputEndpoint)
            .setHeader("user").method(someBean,"getRandomUser")
            .setHeader("CamelHttpPath").simple("/camel/users/${header.user}/hello")
            .to(httpEndpoint)
            .log("Response : ${body}");

The url of the endpoint will be changed according to the environment where we will run the route: local, docker daemon or openshift v3.

The method getRandomUser has been added within the someBean class to generate from a list, the user saying Hello

@Singleton
@Named("someBean")
public class SomeBean {

    static List<String> users;

    public SomeBean() {
        users = new ArrayList<String>();
        users.add("James Strachan");
        users.add("Claus Ibsen");
        users.add("Hiram Chirino");
        users.add("Jeff Bride");
        users.add("Chad Darby");
        users.add("Rachel Cassidy");
        users.add("Bernard Tison");
        users.add("Nandan Joshi");
        users.add("Rob Davies");
        users.add("Guillaume Nodet");
        users.add("Marc Little");
        users.add("Mario Fusco");
        users.add("James Hetfield");
        users.add("Kirk Hammett");
        users.add("Steve Perry");
    }

    private int counter;

    public static String getRandomUser() {
        //0-11
        int index = new Random().nextInt(users.size());
        return users.get(index);
    }

The next project will be designed using the camel web archetype which is a Servlet Tomcat application and will be used to expose using the Camel REST DSL a REST service to get a User Hello Message.

The REST GET Service is defined as such : /camel/users/${id_of_the_user}/hello and this message will be returned '"Hello " + id + "! Welcome from pod/docker host : " + System.getenv("HOSTNAME")'

Here is the syntax of the Camel Route to be used

public class CamelRestRoute extends RouteBuilder {

    private static final String HOST = "0.0.0.0";
    private static final String PORT = "8080";

    @Override public void configure() throws Exception {

        restConfiguration().component("servlet").host(HOST).setPort(PORT);

        // use the rest DSL to define the rest services
        rest("/users/")
                .get("{id}/hello")
                .route()
                .process(new Processor() {
                    public void process(Exchange exchange) throws Exception {
                        String id = exchange.getIn().getHeader("id", String.class);
                        exchange.getOut().setBody("Hello " + id + "! Welcome from pod : " + System.getenv("HOSTNAME") );
                    }
                });

Add the <package> XML tag within the Camel XML Bean file

 <camelContext xmlns="http://camel.apache.org/schema/spring">
    <package>org.jboss.fuse</package>
  </camelContext>

The detail to be used to set the maven archetype is defined hereafter:

mvn archetype:generate
51: remote -> io.fabric8.archetypes:war-camel-servlet-archetype (Creates a new Camel route using Servlet deployed as WAR)

Archetype Version : 2.2.88
Archetype name : war-camel-servlet-archetype
Project : camel-rest-service
Package : org.jboss.fuse
Version: 1.0-SNAPSHOT

Remarks : We will use the following images (s2i-java for the camel cdi project and tomcat-8.0 for the camel web project) if this is not yet the case

      <docker.from>fabric8/s2i-java:1.2</docker.from>
      <docker.from>fabric8/tomcat-8.0</docker.from>

Using JBoss Forge

mvn archetype:generate
58: remote -> org.apache.camel.archetypes:camel-archetype-cdi (Creates a new Camel project using CDI.)

with these parameters

Project : camel-rest-client
Package : org.jboss.fuse
Version: 1.0-SNAPSHOT

and

mvn archetype:generate
19: remote -> io.fabric8.archetypes:cdi-camel-http-archetype (Creates a new Camel route using CDI in a standalone Java Container calling the remote camel-servlet quickstart))

with these parameters

Project : camel-rest-service
Package : org.jboss.fuse
Version: 1.0-SNAPSHOT

<plugin>
  <groupId>org.jolokia</groupId>
  <artifactId>docker-maven-plugin</artifactId>
  <version>${docker.maven.plugin.version}</version>
  <configuration>
    <images>
      <image>
        <name>${docker.image}</name>
        <build>
          <from>${docker.from}</from>
      <docker.from>fabric8/s2i-java:1.2</docker.from>
      <docker.from>fabric8/tomcat-8.0</docker.from>

Run locally the MicroServices

Openshift Microservice

mvn jetty:run
http GET http://localhost:8080/camel/users/charles/hello
HTTP/1.1 200 OK
Date: Mon, 18 Jan 2016 17:39:24 GMT
Server: Jetty(9.2.11.v20150529)
Transfer-Encoding: chunked

Hello charles! Welcome from pod : null

Use a Docker daemon started with boot2docker or docker-machine

Openshift Microservice

    export DOCKER_IP=192.168.99.100
    export DOCKER_REGISTRY="192.168.99.100:5000"
    export | grep 'DOCKER'
    export DOCKER_TLS_VERIFY="1"
    export DOCKER_HOST="tcp://192.168.99.100:2376"
    export DOCKER_CERT_PATH="/Users/chmoulli/.docker/machine/machines/default"
    export DOCKER_MACHINE_NAME="default"
    sudo route -n delete 172.0.0.0/8
    sudo route -n add 172.0.0.0/8 $DOCKER_IP
    docker run -d -p 5000:5000 --restart=always --name registry registry:2
    <docker.image>${docker.registryPrefix}fabric8/${project.artifactId}:${project.version}</docker.image>
    <docker.registryPrefix>${env.DOCKER_REGISTRY}/</docker.registryPrefix>
    mvn clean install docker:build
    docker run -it -p 8080:8080 -p 8778:8778 --name camel-rest-service 192.168.99.100:5000/fabric8/camel-rest-service:1.0-SNAPSHOT
    docker ps --filter="name=rest" | awk '{print $1}' | xargs docker inspect | grep "IPAddress"
docker ps --filter="name=rest"
CONTAINER ID        IMAGE                                                         COMMAND                  CREATED             STATUS              PORTS                                            NAMES
6da09e192031        192.168.99.100:5000/fabric8/camel-rest-service:1.0-SNAPSHOT   "/bin/sh -c /opt/tomc"   8 minutes ago       Up 8 minutes        0.0.0.0:8080->8080/tcp, 0.0.0.0:8778->8778/tcp   camel-rest-service
    @Uri("netty4-http:http://DOCKER_CONTAINER_IPADDRESS:8080?keepalive=false&disconnect=true")
http GET http://172.17.0.2:8080/camel/users/charles/hello
HTTP/1.1 200 OK
Date: Mon, 18 Jan 2016 17:57:55 GMT
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked

Hello charles! Welcome from pod : 6da09e192031
    mvn clean install docker:build
    docker run -it --name camel-rest-client 192.168.99.100:5000/fabric8/camel-rest-client:1.0-SNAPSHOT
    2016-01-18 18:06:22,201 [main           ] INFO  CdiCamelContext                - Route: route1 started and consuming from: Endpoint[timer://foo?period=5000]
    2016-01-18 18:06:22,268 [main           ] INFO  Bootstrap                      - WELD-ENV-002003: Weld SE container STATIC_INSTANCE initialized
    2016-01-18 18:06:23,468 [ClientTCPWorker] INFO  route1                         - Response : Hello Rob Davies! Welcome from pod : 6da09e192031
    http://172.17.0.2:8080/manager/html

    The IP address depends on the address generated by the docker container
    User / password : admin/admin

    Install the hawtio-default.war file available here : http://repo1.maven.org/maven2/io/hawt/hawtio-default/1.4.59/hawtio-default-1.4.59.war
    http://172.17.0.7:8080/hawtio-default-1.4.59/welcome

Openshift Microservice

Use OpenShift v3 instead of the Docker Container to use Kubernetes Service

Openshift Microservice

    oc login https://172.28.128.4:8443
    oc new-project demo
    <fabric8.service.name>hellorest</fabric8.service.name>
    <fabric8.service.port>9090</fabric8.service.port>
    <fabric8.service.containerPort>8080</fabric8.service.containerPort>
    <fabric8.service.type>LoadBalancer</fabric8.service.type>
    <fabric8.label.component>${project.artifactId}</fabric8.label.component>
    <fabric8.label.container>tomcat</fabric8.label.container>
    <fabric8.label.group>demo</fabric8.label.group>
    <fabric8.iconRef>camel</fabric8.iconRef>
    export KUBERNETES_DOMAIN=vagrant.f8
    export DOCKER_HOST=tcp://vagrant.f8:2375
    export DOCKER_IP=vagrant.f8
    mvn -Pf8-build
    mvn -Pf8-local-deploy
    <fabric8.label.component>${project.artifactId}</fabric8.label.component>
    <fabric8.label.container>java</fabric8.label.container>
    <fabric8.label.group>demo</fabric8.label.group>
    <fabric8.iconRef>camel</fabric8.iconRef>
    @Uri("netty4-http:http://{{service:hellorest}}?keepalive=false&disconnect=true")
    private Endpoint httpEndpoint;
    export KUBERNETES_DOMAIN=vagrant.f8
    export DOCKER_HOST=tcp://vagrant.f8:2375
    mvn -Pf8-build
    mvn -Pf8-local-deploy
oc get pods
NAME                       READY     STATUS    RESTARTS   AGE
camel-rest-client-4ej1q    1/1       Running   0          46s
camel-rest-service-4u9v9   1/1       Running   0          3m

 oc get service
NAME                 CLUSTER_IP      EXTERNAL_IP   PORT(S)    SELECTOR                                                                                                      AGE
camel-rest-client    None            <none>        1/TCP      component=camel-rest-client,container=java,group=quickstarts,project=camel-rest-client,provider=fabric8       2m
camel-rest-service   172.30.65.128   <none>        9101/TCP   component=camel-rest-service,container=tomcat,group=quickstarts,project=camel-rest-service,provider=fabric8   5m

oc get rc
CONTROLLER           CONTAINER(S)         IMAGE(S)                                                      SELECTOR                                                                                                                           REPLICAS   AGE
camel-rest-client    camel-rest-client    192.168.99.100:5000/fabric8/camel-rest-client:1.0-SNAPSHOT    component=camel-rest-client,container=java,group=quickstarts,project=camel-rest-client,provider=fabric8,version=1.0-SNAPSHOT       1          2m
camel-rest-service   camel-rest-service   192.168.99.100:5000/fabric8/camel-rest-service:1.0-SNAPSHOT   component=camel-rest-service,container=tomcat,group=quickstarts,project=camel-rest-service,provider=fabric8,version=1.0-SNAPSHOT   1          5m

oc get route
NAME                 HOST/PORT                            PATH      SERVICE              LABELS    TLS TERMINATION
camel-rest-client    camel-rest-client-demo.vagrant.f8              camel-rest-client
camel-rest-service   camel-rest-service-demo.vagrant.f8             camel-rest-service
2016-01-18 19:37:25,469 [main           ] INFO  CdiCamelContext                - Route: route1 started and consuming from: Endpoint[timer://foo?period=5000]
2016-01-18 19:37:25,521 [main           ] INFO  Bootstrap                      - WELD-ENV-002003: Weld SE container STATIC_INSTANCE initialized
2016-01-18 19:37:26,767 [ClientTCPWorker] INFO  route1                         - Response : Hello James Strachan! Welcome from pod : camel-rest-service-8pbq9
2016-01-18 19:37:31,494 [ClientTCPWorker] INFO  route1                         - Response : Hello Claus Ibsen! Welcome from pod : camel-rest-service-8pbq9
2016-01-18 19:37:36,490 [ClientTCPWorker] INFO  route1                         - Response : Hello Nandan Joshi! Welcome from pod : camel-rest-service-8pbq9
2016-01-18 19:39:06,534 [ClientTCPWorker] INFO  route1                         - Response : Hello Claus Ibsen! Welcome from pod : camel-rest-service-zyzec
2016-01-18 19:39:11,532 [ClientTCPWorker] INFO  route1                         - Response : Hello Rob Davies! Welcome from pod : camel-rest-service-f7fw7
2016-01-18 19:39:16,522 [ClientTCPWorker] INFO  route1                         - Response : Hello James Strachan! Welcome from pod : camel-rest-service-8pbq9

Clean project

oc delete pods -l group=demo
oc delete services -l group=demo
oc delete route -l group=demo
oc delete rc -l group=demo

Enjoy the Camel MicroService & MicroContainer !