Bind certain Web-Applications to specific HttpConnectors II

With Pax-Web 3.0.0 it’s now also possible to bind web-applications to certain httpConnectors via the whiteboard extender, if you want to know how it’s done with a published war take a look at the previous post about this.

Assuming you do use the extended configuration for jetty as described in Bind certain Web-Applications to specific HttpConnectors, let’s move on to the actual work to bind your application to a specific HttpConnector vie WhiteBoard-Extender.

props.put( ExtenderConstants.PROPERTY_HTTP_CONTEXT_ID, "extended" );
HashMap<String,String> contextMappingParams = new HashMap<String,String>();
contextMappingParams.put(ExtenderConstants.PROPERTY_HTTP_VIRTUAL_HOSTS, "localhost");
contextMappingParams.put(ExtenderConstants.PROPERTY_HTTP_CONNECTORS, "jettyConn1");
m_httpContextMappingReg = bundleContext.registerService( HttpContextMapping.class, new WhiteboardHttpContextMapping("extended", "foo", contextMappingParams), props );

So how does this actually work? First of all you need to register a HttpContextMapping as a Service. Therefore you create a new Map containing the HTTP_VIRTUAL_HOSTS and PROPERTY_CONNECTORS after that you register this map as the first HTTP_CONTEXT_ID. This will give you the first configuration for a connecting to a new virtual hosting environment extended. Now you just need to bind your Servlets to this context.

props = new Hashtable<String, String>();
props.put( ExtenderConstants.PROPERTY_ALIAS, "/whiteboard" );
props.put( ExtenderConstants.PROPERTY_HTTP_CONTEXT_ID, "extended" );
m_servletReg = bundleContext.registerService( Servlet.class, new WhiteboardServlet( "/whiteboard" ), props );

Registering your Servlet is straight forward, you just need to make sure you’re connecting to the right HTTP_CONTEXT_ID, in this case it’s the extended one.

Again, I have to thank a lot the community to actively help Pax-Web to be where it is today.

Integration in the cloude with Camel, Karaf and Cellar

This post is a summary of the presentation I held at the JAX 2013 in Mainz. It has been a real exciting experience for me to be a speaker at the JAX. I had this opportunity due to my new employer the Inovex GmbH, for which I’m very greatful.

The Goal of the presentation and therefore of this blog post is to show the possibilities of combining a integration solution like Apache Camel with a clustered Apache Karaf by using Apache Karaf Cellar.

Integration-Cloud-ClusterIdea

Clustering Apache Karaf with Cellar

The Cellar project is a subproject of the Karaf Server, it enables Karaf to be run in Clustered environment. The basis of Cellar is a Hazelcast based memory cluster configuration which replicates itself to all known nodes in the cluster. For details on how Hazelcast does this take a look at the project documentation. (hazelcast-documentation)

The default configuration for Hazelcast is to search for other instances within the same subnet through multicast. By doing so it’s quite fast in detecting other instances and at that point the Karaf servers start to synchronize the configuration and the state of the servers.

At this point Cellar is already helping in farming a cluster. For example if one of the server does retrieve a new bundle this information is distributed among the other nodes for them to also install this bundle. To make sure not every configuration or installed bundle (or features) is distributed a black and whitelisting is possible. Below is a simple sample of how a feature is “farmed” on both nodes, and the second one shows how one feature is blocked by the blacklisting.

Cellar-Farming_1

Farming feature XXX:

  1. Installing feature XXX on Node1, by issuing command features:install xxx
  2. Node1 replicates this information throughout the cluster
  3. Node2 picks up this information and installes the required feature.

Cellar-Farming_2

 

Blocking feature:

  1. Installing feature ZZZ on Node2, by issuing the command features:install zzzz
  2. Nod2 informs the cluster
  3. Node1 checks black/whitelists and discards the information

Karaf in the Cloud, or how to discover other nodes on a cloud system

Besides working in a closed network environment where multicasting is applicable it might be needed to run this kind of setup in a Cloud environment like for example on a Amazon Cloud system. When running in a cloud system the nodes are not able to find each other with sending multicast requests, another drawback of running in a cloud environment  you never know if your node will have the same IP in case it has been shut down. Therefore it’s vital for a Cloud environment that all nodes are able to find each other in another way. For example to store the information in a cloude wide visible storage, e.g. a S3 bucket. This can either be achieved by configuring the underlying hazelcast instance to do a AWS multicast by using a S3 storage or let Cellar itself do this. Since the focus of this blog is on showing how to do this with Cellar the shown solution is using the Cellar-Cloud feature.

Cellar is able to find other nodes by using a cloud storage system. At first it will look for the configured storage system and will try to find the required objects at this location which should contain the information needed to connect to the other nodes of the “Cloud-Cluster”.

Showcase for distributed Cloud/Cluster working

Now it’s time to start with a working example on how all this works together.

Requirement

First of all three separate Karaf instances, which are not supposed to know each other and  a S3 storage is needed. For small use-cases you’re able to retrieve free test environments at Amazon.

You’ll also need a java compiler and maven installed, since you’re going to need to compile this sample and possibly the latest version of Apache Karaf-Cellar.

The initial setup of this showcase contained of three instances, two of those instances where deployed to two separate Amazon EC2 Linux images. The third instance was run locally. The Exchange of the IP Adresses for the Karaf Cluster on the Amazon EC2 systems was achieved by using a S3 Bucket and cellars own discovery method.

For the CXF Webservice an external usable IP is needed, therefor an Elastic IP was attached to one of the two EC2 instances.

How does it work

This Sample provides three modules, each module will be installed on a separate Karaf Instance. The first instance will call a CXF Webservice on the first Amazon EC2 instance. This first EC2 system in return will send the message retrieved to a hazelcast queue provided by the Karaf-Cellar infrastructure. The second Amazon EC2 instance will retrieve the message from the hazelcast queue and will write the result to the S3 bucket.

Showcase-JAX2013

Using this Showcase

Download Karaf in version 2.2.9. You’re going to find this version of Karaf at the download location. Along with Karaf you’re going to need to use Cellar 2.2.6, it’s currently not released but coming within days.
For this showcase it’s required to do a clean rebuild of Cellar 2.2.6-SNAPSHOT.

Building Apache Karaf Cellar

Get the sources from SVN by using the following:

svn co https://svn.apache.org/repos/asf/karaf/cellar/branches/cellar-2.2.x

change to the cellar-2.2.x folder and issue a maven build

mvn clean install

Building showcase

Retrieve the sources from the Inovex GitHub at this location and call the following command in the base folder:

mvn clean install

This will create all needed modules a features.xml for the project defining all needed dependencies. As an extra it’ll also build pre-configured Karaf instances for easy usage. Even though those are available, it’s better to follow the instructions below for an easier understanding.

Installing cellar

Extract the retrieved Apache Karaf zip or tar.gz to location of your choice. For the Local node and the CXF-Consuming Node (the one with the EIP) you need to rename the jre.properties file in the etc folder to jre.properties.orig and copy the jre.properties.cxf file to jre.properties. This is needed for CXF to run smoothly with Apache Karaf, and won’t be needed with Apache Karaf >= 2.3.0.

Start the Apache Karaf server by calling karaf from within the bin folder. Right after you started the server we need to make sure it’s running with equinox (while working on this showcase my OSS colleague JB and I discovered some real strange issus with Felix).

dev:framework equinox
dev:restart -c

On the first Node of your cluster environment, where you changed the jre.properties to use the cxf needed configuration you need to install some bundles first. Without those you’re going to receive some unwanted errors when installing cellar.

install -s mvn:org.apache.geronimo.specs/geronimo-annotation_1.0_spec/1.1.1
install -s mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.activation-api-1.1/2.0.0
install -s mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.stax-api-1.0/1.9.0
install -s mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.jaxb-api-2.2/1.9.0

Preparation is done now, let’s start installing Apache Karaf Cellar by first registering the features.xml:

features:addurl mvn:org.apache.karaf.cellar.samples/camel-hazelcast-app/2.2.6-SNAPSHOT/xml/features

and second installing the required feature:

features:install -v -c cellar-cloud

Now you have to possibilities of installing the showcase either the lazy all-in-one feature or by using the farming possibilities. Since we’re here to have some fun let’s take a look on the farming version first.

Installing the showcase with Farming!

First of all we need to make sure the correct configuration is set for cellar. Cause we don’t want every feature to be synchronized to the complete cluster.

config:edit org.apache.karaf.cellar.groups
config:propappend default.features.blacklist.outbound ,showcase-cxf-consumer-light
config:propappend default.features.blacklist.outbound ,showcase-hazelcast-consumer-light
config:propappend default.features.blacklist.outbound ,camel-aws
config:propappend default.features.blacklist.inbound ,showcase-cxf-consumer-light
config:propappend default.features.blacklist.inbound ,showcase-hazelcast-consumer-light
config:propappend default.features.blacklist.inbound ,camel-aws
config:propappend default.config.blacklist.inbound ,org.ops4j.pax.web
config:propappend default.config.blacklist.inbound ,org.apache.karaf.cellar.cloud*
config:propappend default.config.blacklist.inbound ,org.apache.karaf.cellar.discovery
config:propappend default.config.blacklist.outbound ,org.ops4j.pax.web
config:propappend default.config.blacklist.outbound ,org.apache.karaf.cellar.cloud*
config:propappend default.config.blacklist.outbound ,org.apache.karaf.cellar.discovery
config:propset default.bundle.sync false
config:update

All machines need to know of the showcase features.xml to be added to the features repository, therefore issue the following command on only one of the nodes.

features:addurl mvn:de.inovex.jax2013.showcase/feature/1.0.0/xml/features

After done this, take a look at the second node to check if the features url has been added to the repository

features:listurl

This should show you the features repository urls. Since the showcase features.xml also contains information about the cxf and camel features repository those will show up also.

Now let the Farming beginn!
Install the camel-blueprint feature first cause it’s the basis for all other features.

features:install -v -c camel-blueprint

After this is done, check the second node again if this feature has also been installed at the second node. To list all available bundles just issue a la at the command line. Depending on the speed of the second node all bundles should be installed or even active already. After this feature has been farmed let’s install the second needed feature for the cluster.

features:install -v -c camel-cxf

Ok, so the farming did work out quite nicely, and both nodes now do have the same basic setup needed to run the showcases. Now we need to install the showcases to the dedicated servers. if you didn’t configure the nodes yet you’re required to do so otherwise you’re gonna have fun with distributed showcases :-)

So let’s install the cxf-consumer showcase on the first node (it’s the one with the elastic IP attached to it).

features:install -v -c showcase-cxf-consumer-light

Now just for the fun of it check if this showcase is not installed on the second node ;-)

So let’s get on with it and install the hazelcast-consumer showcase to the second node. But this one also needs another camel feature so we need to install two features!

features:install -v -c camel-aws
features:install -v -c showcase-hazelcast-consumer-light

So this is it, it’s that simple to distribute your features throughout the cluster and white/blacklist parts of it. At this point we just need to setup the producing node which is your local server and therefore is not connected to the cluster.

features:addurl mvn:de.inovex.jax2013.showcase/feature/0.1.0-SNAPSHOT/xml/features
features:install -v showcase-cxf-producer

Now we only need to configure the three nodes correctly to get on with it, so you should skip the next “chapter” and need to go directly to the configuration description.

Installing the showcase with one Go!

before installing the showcase feature we need to make sure the correct white and blacklist entries are set.

config:edit org.apache.karaf.cellar.groups
config:propappend default.features.blacklist.outbound ,showcase-cxf-consumer
config:propappend default.features.blacklist.outbound ,showcase-hazelcast-consumer 
config:propappend default.features.blacklist.inbound ,showcase-cxf-consumer 
config:propappend default.features.blacklist.inbound ,showcase-hazelcast-consumer  
config:propappend default.config.blacklist.inbound ,org.ops4j.pax.web
config:propappend default.config.blacklist.inbound ,org.apache.karaf.cellar.cloud*
config:propappend default.config.blacklist.inbound ,org.apache.karaf.cellar.discovery
config:propappend default.config.blacklist.outbound ,org.ops4j.pax.web
config:propappend default.config.blacklist.outbound ,org.apache.karaf.cellar.cloud*
config:propappend default.config.blacklist.outbound ,org.apache.karaf.cellar.discovery
config:propset default.bundle.sync false
config:propset default.features.sync false
config:update

All machines need to know of the showcase features.xml to be added to the features repository, therefore issue the following command.

features:addurl mvn:de.inovex.jax2013.showcase/feature/1.0.0/xml/features

Now you’re able to install the following features dependent on their location. The private or local machine does only retrieve the cxf-producer module and therefore only the following needs to be installed on this node:

features:install showcase-cxf-producer

On the first EC2 node which is accessible through an elastic IP (EIP) install the CXF consuming route module:

features:install showcase-cxf-consumer

On the second EC2 node which only consumes internally but accesses the S3 bucket install the following:

features:install showcase-hazelcast-consumer

Configuration

All of the three nodes need some extra configuration after installation. The features install process already placed those configuration files in the `etc` folder of the Apach Karaf server.

Local Node

Edit the `de.inovex.jax2013.showcase.cxf.producer.cfg` file. and change the `cxf.remote.url` to the external CXF server to your accessible EIP. Also change the `file.location` parameter to a valid folder in your system.  For example one might use the config commands as previously used for the black and whitelists.

config:edit de.inovex.jax2013.showcase.cxf.producer 
config:propset cxf.remote.url http://<elastic-ip>:8181/cxf/messenger 
config:propset file.location ~/Documents/importDir/ 
config:update

First EC2 Node

No extra configuration is needed.

Second EC2 Node

Edit the `de.inovex.jax2013.showcase.s3.producer.cfg` file.a and change the aws key and security key to your own keys. Again use the shell commands to do so:

config:edit de.inovex.jax2013.showcase.s3.producer.cfg
config:propset aws.accessKey <access-key>
config:propset aws.secretKey <secret-key>
config:propset bucket.name <bucket-name>
config:update

Running this Showcase

Now only place a text file to the configured Folder and you’ll shortly will see a `messageOut.txt` file in your S3 bucket.

I hope you enjoyed the JAX as I did and also this showcase.

Pax Web breaks the 200.000 downloads barrier

Kurzmitteilung

Pax Web breaks the 200.000 downloads barrier

just today I checked the latest download numbers from the central statistics for the pax-web project. It’s been good that I’ve been sitting already, cause a increase from 125.000 to more then 200.000 downloads, that’s quite impressive.

Thanks to all the people using Pax-Web, this number gives me faith in beeing on the right track with Pax-Web.

Bellow are just some graphics from the download statistics, as usual the three most important. All Artefacts downloaded (which is 200.000), all pax-web-jetty bundles (> 35.000) and all pax-web-jetty-bundles (the prebundled pax-web including jetty with around 4.000).

Pax Web all Downloads

PAX Web all downloads

 

Pax Web the pax-web-jetty bundle

pax-web-jetty_march_2013

 

Pax Web the all inclusive jetty bundle pax-web-jetty-bundle

pax-web-jetty-bundle_march_2013

Just Annotation

Starting with version 2.0 of Pax-Web it’s possible to use Servlet 3.0 annotations for Servlets in a web application bundle (WAB). As defined in the Servlet spec it’s possible to have servlet definitions and configuration either in a web.xml or in the annotations of the Servlet. In this case the annotation of the servlet does override the configuration found in the web.xml. According to the servlet spec it’s even possible to skip the web.xml completely. That’s the part where Pax-Web 3.0 will kick in. Starting with version 3.0.0.M2 it’s possible to deploy a purely annotated WAB. It just needs a annotated Servlet

package org.ops4j.pax.web.itest.support;

import java.io.IOException;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet (value="/test", name="test")
public class AnnotatedTestServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  private boolean initCalled;

  @Override
  public void init(ServletConfig config) throws ServletException {
    this.initCalled = true;
    super.init(config);
  }

  public boolean isInitCalled() {
    return initCalled;
  }

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    resp.getWriter().write("TEST OK");
  }
}

and a little manifest entry

Web-ContextPath: /annotatedTest

That’s all it takes. In this case you don’t even need to create a war bundle, a standard osgi jar bundle will do already.

As usual a complete and working sample can be found at the Pax-Web itest submodule:
ServletAnnotatedIntegrationTest.java

Bind certain Web-Applications to specific HttpConnectors

Starting with Pax-Web 2.1 it’s possible to bind web applications to a specific http-connector. For this to work you need to configure an additional http connector through jetty.xml. The jetty.xml for pax-web uses a slightly different way of configuring connectors. Instead of setting a new Connector the jetty.xml is interpreted after the Jetty Server has already been configured. Therefore you need to add a connector, not create a new one.

    <Call name="addConnector">
      <Arg>
          <New class="org.eclipse.jetty.server.nio.SelectChannelConnector">
            <Set name="host"><Property name="jetty.host" /></Set>
            <Set name="port"><Property name="jetty.port" default="8282"/></Set>
            <Set name="maxIdleTime">300000</Set>
            <Set name="Acceptors">2</Set>
            <Set name="statsOn">false</Set>
            <Set name="confidentialPort">8443</Set>
            <Set name="name">jettyConn1</Set>
	    <Set name="lowResourcesConnections">20000</Set>
	    <Set name="lowResourcesMaxIdleTime">5000</Set>
          </New>
      </Arg>
    </Call>

Make sure you have a name configured for this connector. The sample uses jettyConn1 as name.

The Manifest of this Web-Application Bundle needs two additional entries. Web-Connectors and Web-VirtualHosts.

Web-Connectors: jettyConn1
Web-VirtualHosts: localhost

Another alternative way of binding your Web-Application to a certain Web-Connector or Virtual host is to add it to the installation URL.

webbundle:mvn:groupId/artifactId/version/war?Web-ContextPath=test&Web-Connectors=jettyConn1&Web-VirtualHosts=localhost

The Pax-Web itests do contain two working examples for more details check the two links below:
JettyConfigurationExtendedIntegrationTest
JettyConfigurationExtendedTwoIntegrationTest

What’s new in OPS4j Pax Web 3.0.0

This article will try to give you a brief overview on what’s new in the soon to come Pax-Web 3.0.0. First of all, the most outstanding new feature will be the support for Tomcat as an alternative Container. Right now it supports basic HTTP Services, but this is being worked on.

Second there is a new support for binding Web-Applications to certain Http-Connectors aka Virtual-Hosts. More on this can be found soon on this blog. Find it here.

Third it’s now possible to deploy WABs without a web.xml. This requires “Servlet 3.0″ compliant Servlets within. A quick howto will also be available soon on this blog. Find it here

Last but not least, thanks to the awsome work of Harald, Pax-Web supports Pax-Cdi. This opens the possibilities to inject OSGi services into Servlets.

… more to come …

Pax Web in the year 2012

Now, that the year 2012 is over, it’s time to sum up the last year on what happened. Gather some statistics and a give an introduction of what is on the road-map for the next year.

What did happen in 2012

A quick overview of the timeline in 2012

December/January

The last release of Pax Web in December 2011 was 1.0.8 which was a bug-fix release which was very important for Pax Web, it’s been a good foundation for all others to come. In January Pax Web in version 1.1.2 was released this has been an important bug-fix release, It contained about 30 fixes.

April

In April Pax Web in version 1.0.9 has been released which just proves the maturity of the project.

May

May has been a very active Month, 4 bug-fix versions have been released 1.0.10 and 1.0.11 together with 1.1.3 and 1.1.4. The amount of bug-fixes also gives a good impression on how it’s used and supposedly how stable Pax Web seems to be.

June

This had been a very important month for Pax Web. Version 2.0.0 had been released, this was the first version of Pax Web supporting Servlet API 3.0 and the latest Jetty Server.
It took almost a year to resolve those 77 issues.

July

In July the first bug-fix releases for the 2.0 line with a sum of 7 bug-fixes.
Based on 2.0 it didn’t take long for a 2.1 to show up. New features had been introduced as for example Web Virtual Hosts, which makes it possible to bind Web Application Bundles (WAB) to a certain Virtual Host.

October

In October the End Of Life (EOL) for two version lines has been announced, the long working though stable version 1.0.x and the not so long but new version 2.0.x which has been superseded by the much feature richer version 2.1.x.
Also in October Versions 1.1.5, 2.0.3 and 1.0.12 have been released.

November

Concentrating on a 2.1.x line did show it’s success in November, 2.1.1 has been released  containing about 14 needed bug-fixes.

December

In December Pax Web did receive a long needed bug-fix as it seems. There has been an issue with configuration changes. This did result in a 2.1.2 which is quite stable now.

While working on a stable 2.1.x and 1.1.x line, the Pax Web team also has been working on a 3.0 trying to introduce an alternate Web-Container. This Work started around June and was pushed by a nice impulse right in the beginning. Some contributions through the community. A first preview version of it has been released already a 3.0.0.M1. The 3.0.0.M2 is soon to come.

Statistics of 2012

The download statistics show a nice increase over time on how Pax Web has been used over the  last year.

Though those number represent all versions and all artifacts of Pax Web it’s still impressive. At the peak of November Maven Central registered a total of more than 120,000  downloads.

Downloads of pax-web-jetty

The next and the following chart will try to break those numbers down a bit more. The first is showing just the downloads for all pax-web-jetty artifacts, while still taking into account all of the versions available.

Downloads of pax-web-jetty-bundle

This is probably the most interesting statistics. We do have a constant increase of usage of the jetty-bundle which is certainly used without Apache Karaf.

Issues

Lot’s of versions means a lot of issues. In the range of March 2012 to the beginning of January 2013 around 125 Issues have been created and also resolved. The Chart below tries to give you a impression of this.

Below is a nicely formatted table showing you the actual data behind this graph.

Period Created Resolved
March 2012 6 2
April 2012 10 11
May 2012 8 11
June 2012 9 8
July 2012 15 16
August 2012 13 14
September 2012 12 5
October 2012 16 20
November 2012 15 15
December 2012 12 7
January 2013 4 4

Conclusion

After interpreting all those statistics and looking at all the different version numbers. I’m proud to say: Pax-Web does actually provide value to people out there. It isn’t just for playing with OSGi and Web, the increase in usage does show the using community is actually quite big and increasing.

Preview of 2013 …

So let’s take a look at that glass micro-sphere. Most of the current effort is invested in  Pax-Web 3.0. It willl support such great things as CDI, thanks to Harald and his Pax-CDI project. Support for Tomcat is still in progress. Although only basic HTTP-Services are supported right now a fully featured version should be included in 3.0, if everything works out as expected ;-) . A version 3.0.0.M2 is on it’s way and I think somewhere between the  first and the second quarter of 2013 will be a good place for a 3.0.0 Final.

… last words

I’m really proud of this Project and how the community did grow around it lately. After I stepped in to take the lead I was pretty much on my own, fixing issues and adding new needed functionalities. This has changed! The community is growing in numbers and so are the contributions. Thanks to all those people contributing in either working on the code or issues reporting.

Pax Web 2.0.0

It’s released, at last.
This release did consume quite an amount of time.
I started to work on Pax Web 2.0.0 in July 2011, about the same time
we bought our new house with lots of renovation to be done.
77 Issues where resolved with 2.0.0 of Pax Web.
I’d say about 5k lines of Code where added in this time, at lease
that’s what git tries to tell me :)
Take a look at the image from Git hub for the Code Frequency at github.

Lot’s of improvements where made to Pax Web, Bugfixes, new features and so on.
To get a better picture take a look at http://team.ops4j.org/wiki/display/paxweb/Pax+Web+-+2.0.0

Hope you have as much fun with it as I had creating it.