Simple Camel route in JBoss Fuse

For this tutorial and the following ones, I am going to use a Fuse instance on a Lubuntu Linux box. My IDE is Eclipse Luna and the build system is Apache Maven v. 3.5.2. Eclipse is actually running on Java 8 but it does not matter since I’m going to run all the builds from a terminal.

Let’s see how we can implement and deploy a simple Camel route in JBoss Fuse. We start by defining our requirements that, in this case, are going to be very trivial: we want to read messages from a queue, process them and the write them back to another queue. The processing step is going to be simple too: we will just log the message body.

First of all, we need two queues. Start Fuse and reach the console (see the previous post). In the menu bar, click on “ActiveMQ”. Then click on “+Create” on the submenu, select “queue” in the radio buttons group, type the appropriate name in the text box (I’m choosing “source-queue”) and finally click the “Create Queue” button (see pictures below). Repeat the process and create a “sink-queue” queue, it will be our destination queue. Later, we will be going to need to queue a message in the source queue through the web panel. In order to be able to do that, we have to set the username and password. In the web console, go to the drop down menu in the top right corner (where your username appears). Select “preferences”. Go to the “ActiveMQ” tab and insert your administrative username and password. The settings are automatically saved. Now that we have the infrastructure ready, let’s switch to the development side.

activemq-menu

create-queue

If you are going to develop projects for Fuse, Maven is the way to go. The default way you install new components in Fuse, is by telling it to get the artifacts from a Maven repository. For this tutorial I assume that you are quite familiar and comfortable with Maven and that you have a working installation of Maven on your system.

We can create the initial skeleton of the project starting from a Maven archetype. Open a Terminal and type:

mvn archetype:generate

choose the archetype named camel-archetype-blueprint (in my case is the number 449) and complete the process. Here is a dump of my terminal:

Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 510: 449
Choose org.apache.camel.archetypes:camel-archetype-blueprint version:
1: 2.8.0
[...]
42: 2.14.1
Choose a number: 42: 42
Downloading: https://repo.maven.apache.org/maven2/org/apache/camel/archetypes/camel-archetype-blueprint/2.14.1/camel-archetype-blueprint-2.14.1.jar
Downloaded: https://repo.maven.apache.org/maven2/org/apache/camel/archetypes/camel-archetype-blueprint/2.14.1/camel-archetype-blueprint-2.14.1.jar (17 KB at 14.1 KB/sec)
Downloading: https://repo.maven.apache.org/maven2/org/apache/camel/archetypes/camel-archetype-blueprint/2.14.1/camel-archetype-blueprint-2.14.1.pom
Downloaded: https://repo.maven.apache.org/maven2/org/apache/camel/archetypes/camel-archetype-blueprint/2.14.1/camel-archetype-blueprint-2.14.1.pom (3 KB at 10.9 KB/sec)
Define value for property 'groupId': : org.merka
Define value for property 'artifactId': : fuse-demo-blueprint
Define value for property 'version':  1.0-SNAPSHOT: : 1.0
Define value for property 'package':  org.merka: : org.merka.demo
[INFO] Using property: camel-version = 2.14.1
[INFO] Using property: log4j-version = 1.2.17
[INFO] Using property: maven-bundle-plugin-version = 2.3.7
[INFO] Using property: maven-compiler-plugin-version = 2.5.1
[INFO] Using property: maven-resources-plugin-version = 2.6
[INFO] Using property: slf4j-version = 1.7.7
Confirm properties configuration:
groupId: org.merka
artifactId: fuse-demo-blueprint
version: 1.0
package: org.merka.demo
camel-version: 2.14.1
log4j-version: 1.2.17
maven-bundle-plugin-version: 2.3.7
maven-compiler-plugin-version: 2.5.1
maven-resources-plugin-version: 2.6
slf4j-version: 1.7.7
Y: : Y
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: camel-archetype-blueprint:2.14.1
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: org.merka
[INFO] Parameter: artifactId, Value: fuse-demo-blueprint
[INFO] Parameter: version, Value: 1.0
[INFO] Parameter: package, Value: org.merka.demo
[INFO] Parameter: packageInPathFormat, Value: org/merka/demo
[INFO] Parameter: maven-bundle-plugin-version, Value: 2.3.7
[INFO] Parameter: maven-resources-plugin-version, Value: 2.6
[INFO] Parameter: groupId, Value: org.merka
[INFO] Parameter: maven-compiler-plugin-version, Value: 2.5.1
[INFO] Parameter: slf4j-version, Value: 1.7.7
[INFO] Parameter: version, Value: 1.0
[INFO] Parameter: log4j-version, Value: 1.2.17
[INFO] Parameter: camel-version, Value: 2.14.1
[INFO] Parameter: package, Value: org.merka.demo
[INFO] Parameter: artifactId, Value: fuse-demo-blueprint
[INFO] project created from Archetype in dir: /home/merka/workspace/fuse-demo-blueprint
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 05:20 min
[INFO] Finished at: 2014-12-23T20:29:24+01:00
[INFO] Final Memory: 13M/60M
[INFO] ------------------------------------------------------------------------

Now we can import the project in our IDE of choice and open it. Just to be sure that everything is OK, run a first build with the command mvn -DskipTests=true clean package from the shell and wait for the required dependencies to be downloaded.

The archetype project comes with a couple of “hello world” files that you can completely ignore at this point: they only serves as an example. It’s actually better if you delete all the hello-world-related stuff, unit test included.  Open the blueprint.xml file in the folder OSGI-INF/blueprint and comment out the existing route. You should also delete the “helloBean” definition. The file should look like this:

<?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:camel="http://camel.apache.org/schema/blueprint"
       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 http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">

  <camelContext id="blueprintContext" trace="false" xmlns="http://camel.apache.org/schema/blueprint">
<!--     <route id="timerToLog"> -->
<!--       <from uri="timer:foo?period=5000"/> -->
<!--       <setBody> -->
<!--           <method ref="helloBean" method="hello"/> -->
<!--       </setBody> -->
<!--       <log message="The message contains ${body}"/> -->
<!--       <to uri="mock:result"/> -->
<!--     </route> -->
  </camelContext>

</blueprint>

Before the camelContext element, add the following bean definition: it provides Camel with the credentials to access the ActiveMQ Broker:

	<!-- connect to the local ActiveMQ broker -->
	<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent">
		<property name="brokerURL" value="tcp://localhost:61616" />
		<property name="userName" value="merka" />
		<property name="password" value="merka" />
	</bean>

Then, add the following snippet inside the camelContext element. It defines a route that satisfies our requirements:

    <route id="queue2queue">
        <from uri="activemq:source-queue"></from>
        <log message="the message body is: ${body}" loggingLevel="INFO"></log>
        <to uri="activemq:sink-queue"></to>
    </route>

It is quite readable. The from element defines a consumer endpoint: it will read messages from the queue named source-queue (that we have just created), as soon as they are available. The message body is logged, thanks to the log element, and then it is written to sink-queue.

Build the project with Maven (mvn clean install). This puts the artifact in the local Maven repository, thus making it available to Fuse. To install the artifact in Fuse, go to the Karaf prompt and type

osgi:install mvn:org.merka/fuse-demo-blueprint/1.0

With this command you tell Karaf to search for the artifact with the given groupId/artifactId/version. If found, it answers with the id of the installed osgi bundle:

JBossFuse:karaf@root> osgi:install mvn:org.merka/fuse-demo-blueprint/1.0
Bundle ID: 251

You can see all the installed components typing list. Start the bundle with the commnand start <bundle-id>. Check the log for possible errors with log:display or log:tail. If no errors are found, go to the web console and manually send a message into the source-queue queue. The message is immediately consumed from the queue, the message body appears in the log and a brand new message is sent to sink-queue.

 send-msg

Advertisements

JBoss Fuse installation tutorial

At work I was given the task to study JBoss Fuse and become sufficiently comfortable developing and deploying basic projects on this platform. I’m going to write a series of post to share my experience and considerations.


Some random thoughts

I’m not going to rigorously explain you what Fuse actually is. But if you start from scratch, without any previous knowledge of a Service Bus middleware, it’s quite hard to get the essence of the system. And if you try to make an idea through what you find online, good luck. It’s hard to find something that tells you what you can really use Fuse for, possibly with some insightful examples. In fact, it is almost impossible. Sure you can find some “case studies” or articles that tell you how good Fuse is at integrating systems and how big a shitload of money they saved by using it instead of, say, building a similar monster from scratch. But those are only marketing mumbo jumbo and do not give you any useful tip on the technical side of the matter, which is what I really care about. What help me the most in these cases is bringing it down to a very trivial use case description and a set of practical examples. And this is what I am trying to do here.

Fuse is huge, very huge. It is a collection of subsystems taped together by Karaf, an OSGi container developed by the Apache Foundation. Here are only some of the subsystem included. I only knew the name of most of them until now, and some were completely unknown:

  • Karaf,
  • Camel,
  • CXF,
  • Hawtio,
  • Felix,
  • ActiveMQ,

JBoss Fuse is basically a Service Bus, a middleware, that allows you to host services and integrate a wide variety of heterogeneous systems. But this is not very helpful. So, this is the picture that I have after spending several hours using Fuse and developing tutorial and demo projects: if you have, say, a desktop application developed for Windows, a bunch of Web Services hosted in Tomcat in a Linux box, an external database that needs somehow to be updated and you want to let this system talk to each other, then Fuse might be the way to go. You can set up a Web Service in Fuse (REST or SOAP doesn’t matter) and use Apache Camel to connect the various pieces in a so called “route”. There already are a lot of components that automagically let you call an external web service, read and/or write to a database, reading or write a text file over FTP, reading or writing a directory over LDAP and whatnot. Here is a list of what is available. I particularly enjoyed the SSH connector and I’m looking forward to give it a try in a real project.

Another possible scenario is an Enterprise application that needs to interface with a legacy system. Think about an organization that wants, for some reasons, a new, cool, bleeding edge, good looking front end to amaze and fool the customers, but does not want to get rid of its 30-year-old COBOL code base running on IBM mainframes (nobody wants to do that). You can use Fuse to translate messages (from XML/JSON to plain text and back again), decouple the systems by using queues, log, and so on. Again, this is how I currently picture Fuse in my mind, I do not claim to give you a full coverage of the possible, numerous use cases.


Installation

Finally. Fuse is as easy to install and launch as Liferay, Alfresco and Pentaho (just to name few that I recently had to install). Even easier, in a sense. That is what you expect, since it’s completely Java based. Just unpack the tarball or the zip archive and launch <FUSE_DIR>/bin/fuse or <FUSE_DIR>\bin\fuse.bat, depending on what OS you are on. Keep in mind that the current release of Fuse (6.0.1) requires Java 7 and does not support Java 8. If you have your JAVA_HOME environment variable set to something different, you have to change it by either editing /etc/environment or the startup script. To do the second, which I recommend, Open the “<FUSE_DIR>/bin/karaf” script and add the variable definition, just like this:

#explicitly sets the value of JAVA_HOME to a compatible JDK
JAVA_HOME=/opt/jdk1.7.0_71

DIRNAME=`dirname "$0"`
PROGNAME=`basename "$0"`

#etc...

...

Now run the script named fuse and, if everything is OK, the Karaf console starts showing a prompt like the following:

JBossFuse:karaf@root>

The first thing that we want to do is to create an administrative user in order to access the Web console. So type:

JBossFuse:karaf@root> esb:create-admin-user

And there we go, we can now open a browser and navigate to http://localhost:8181, and have full access to the management web application.

Starting Android Studio behind a proxy

I recently installed the latest (stable) version of the new Android Studio, the one based on IntelliJ IDEA.
The installation went OK but when i started the program, it remained stuck in the splash screen, with a message box saying: “getting Android SDK Component information” or something like that. Then, after 10 minutes or something, it finally timed out and loaded another screen, the Setup Wizard, that should help you configure Android Studio on the first startup. Same thing happend, it remained stuck for about 20 minutes, then told me that something was wrong and so the application could not be started. That’s it, it seems that you can’t do anything about that.
As you might imagine, it’s a network related problem. Actually it is clearly stated that you should have a stable internet connection to run Android Studio without incurring into any problem. The point is I had a stable and fast Internet connection so the problem came down to the network proxy. After I tried to start AS without Internet (it failed immediately) and with a tethering connection with my phone (it quickly moved on from the first screen and greedily tried to download all the things from my phone), I was in a weird situation where I really needed to tell AS to use a proxy before starting but, unluckily, I could not do that without starting it and, without the right proxy setting, it won’t start.
Or will it… I also have a clean Intellij IDEA installation on my computer so I thought that, since they are basically the same thing, I could try to set the proxy on IDEA and see what happens. Hopefully it stores the information in some human readable configuration file and I can steal that snippet and paste it on the corresponding AS file.
After a bit of searching, it turns out that it is exactly the case. I found the file other.xml in the folder %HOME%\.IdeaIC12\config\options, where %HOME% is, quite obviously, your home folder under Windows.
The desired snippet is the following:


<component name="HttpConfigurable">
    <option name="PROXY_TYPE_IS_SOCKS" value="false" />
    <option name="USE_HTTP_PROXY" value="true" />
    <option name="USE_PROXY_PAC" value="false" />
    <option name="PROXY_HOST" value="101.116.3.251" />
    <option name="PROXY_PORT" value="3128" />
    <option name="PROXY_AUTHENTICATION" value="false" />
    <option name="PROXY_LOGIN" value="" />
    <option name="PROXY_PASSWORD_CRYPT" value="" />
    <option name="KEEP_PROXY_PASSWORD" value="false" />
    <option name="myGenericPasswords">
      <map />
    </option>
    <option name="myGenericCancelled">
      <set />
    </option>
    <option name="PROXY_EXCEPTIONS" value="localhost,127.0.0.1,101.*" />
  </component>

You can copy and paste it under the corresponding other.xml under %HOME%\.AndroidStudio\config\options and it will do the trick.
Done this, AS started without any problem.