Sunday, October 18, 2009

First steps with Apache Camel on Google App Engine

This post describes how to get a simple Camel 2 application running on Google App Engine (GAE). I'll focus on the workarounds and fixes that were necessary to succeed. Please note that the following descriptions are by no means best-practices or recommendations. They only describe my first steps for which better solutions will likely exist in the future. I plan to work on improvements to
  • make Camel deployments on GAE easier and to
  • allow Camel applications access GAE services via Camel components
For my experiments, I was using a Camel 2.1 development snapshot, the App Engine SDK 1.2.6 and the Google Plugin for Eclipse which makes local testing and remote deployment very easy. The Camel components I used are:
  • camel-core
  • camel-spring
  • camel-servlet
  • camel-http
The following snippet shows the route definition of the sample application. It uses the camel-servlet component to receive input via HTTP, converts the HTTP request body to a String, prepends a "Hello " to the body and returns the result.

package example;

import org.apache.camel.builder.RouteBuilder;

public class ExampleRoute extends RouteBuilder {

@Override
public void configure() throws Exception {
from("servlet:/test")
.convertBodyTo(String.class)
.transform(constant("Hello ").append(body()));
}
}

The route doesn't make use of any GAE services (URL fetch, tasks queues, storage, mail ...) Also, message processing is synchronous because GAE doesn't allow applications to create their own threads. For example, using SEDA or JMS queues will not work.

For processing HTTP requests, I created my own servlet class and extended the CamelHttpTransportServlet from the camel-servlet component.

package example;

import org.apache.camel.component.servlet.CamelHttpTransportServlet;
import org.apache.camel.management.JmxSystemPropertyKeys;

public class ExampleServlet extends CamelHttpTransportServlet {

static {
System.setProperty(JmxSystemPropertyKeys.DISABLED, "true");
}

}

The only thing this servlet does is to disable all JMX-related functionality because the GAE JRE doesn't support JMX. All request processing and dispatching is done by the CamelHttpTransportServlet. Configuring the servlet in the web.xml was done as follows.

<servlet>
<servlet-name>CamelServlet</servlet-name>
<servlet-class>example.ExampleServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>context.xml</param-value>
</init-param>
</servlet>

<servlet-mapping>
<servlet-name>CamelServlet</servlet-name>
<url-pattern>/camel/*</url-pattern>
</servlet-mapping>

The servlet init-param points to the Spring application context that configures the route builder and the Camel context:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<bean id="camelContext"
class="org.apache.camel.spring.CamelContextFactoryBean">
<property name="builderRefs">
<list>
<ref bean="routeBuilderRef"/>
</list>
</property>
</bean>

<bean id="routeBuilderRef"
class="org.apache.camel.model.RouteBuilderDefinition">
<constructor-arg value="routeBuilder" />
</bean>

<bean id="routeBuilder"
class="example.ExampleRoute">
</bean>

</beans>

A severe limitation is that one cannot use the Camel-specific configuration XML schema from the http://camel.apache.org/schema/spring namespace for configuring the Camel context. The problem is that the CamelNamespaceHandler uses JAXB to parse bean definitions which isn't supported by GAE either. One has to fallback to plain old <bean> definitions (POBD?) to configure the Camel context in Spring. Using Spring JavaConfig or something similar would make more sense here but I didn't try it.

Another JAXB-releated problem arises with Camel's Spring DSL. It is also processed with JAXB and therefore cannot be used on GAE.

Going completely without Spring leads to another problem. In this case the CamelContext uses a JndiRegistry by default that depends on javax.naming.InitialContext. This class isn't on the JRE whitelist either. Writing a simple Map-based implementation of org.apache.camel.impl.Registry and configuring the CamelContext with it does the trick.

The last obstacle to get the sample application running was to replace the Camel's UuidGenerator with another one that uses java.util.UUID from the JRE. Camel's original UuidGenerator also uses a class that is not on the JRE whitelist. Since replacement by configuration was not possible, changes to the Camel code base were necessary (patch already submitted).

After deploying the application to GAE and POSTing a request containing "Martin" to http://<appname>.appspot.com/camel/test I was able to send myself greetings. In the URL, <appname> must of course be replaced with the name of an existing application.

Wednesday, October 14, 2009

IPF 2.0 milestone 2 and IPF Tools milestones released

I'm pleased to announce the following milestone releases from the IPF core project and the IPF Tools project.

IPF 2.0 milestone 2 (release notes)
IPF Tools
- IPF Runtime 2.0 milestone 2 (release notes)
- IPF Manager 2.0 milestone 2 (release notes)
- IPF IDE 1.0 milestone 2 (release notes)

IPF 2.0 milestone 2

This release is feature-equivalent to IPF 1.7.0 but runs on Camel 2.0. Users who plan to upgrade to IPF 2.0 or Camel 2.0 in the near future are highly recommended to use this milestone release. Please note that IPF 2.0 is not backwards-compatible to IPF 1.x. This is mainly due to non-backwards compatible API changes in Camel 2.0. It is therefore important to carefully read the Camel 2.0.0 release notes as well as the IPF 2.0-m2 upgrade notes.

With the release of IPF 2.0-m2 and IPF 1.7.0, IPF 1.x development will go into maintainance mode and new features will be developed on the IPF 2.0 development branch. We leave it open whether to backport selected IPF 2.x features to IPF 1.x. Please add any backport requests to the IPF issue tracker.

Other changes compared to IPF 1.7.0 are:

  • The platform manager has been moved to the IPF Tools project.
  • The IPF OSGi distributable (IPF runtime) and the IPF OSGi documentation have been moved to the IPF Tools project.
  • The HL7-independent parts of the mapping service have been factored out into a new commons-map component.
  • The IPF 2.0 documentation has been forked from the IPF 1.7 documentation and revised.

IPF Runtime 2.0 milestone 2


The IPF Runtime is an IPF distribution that is running on the Equinox OSGi platform. It is available as Eclipse plugin or as standalone package. The runtime is used to develop OSGi-based IPF applications.

IPF Manager 2.0 milestone 2


IPF Manager is an Eclipse application for managing IPF services and applications. It is available as Eclipse plugin or as standalone package. In its current state it provides a flow management user interface and a general-purpose JMX client. The IPF Manager is compatible with IPF Runtime 2.0-m2.

IPF IDE 1.0 milestone 2


The IPF IDE supports developers in creating, testing and packaging IPF applications within the Eclipse plugin development environment (PDE) on top of the IPF runtime. The IPF IDE is compatible with IPF Runtime 2.0-m2.

Wednesday, October 7, 2009

IPF 1.7.0 released

I'm pleased to announce the release of IPF 1.7.0. The main focus of this release was support for clinical standards, in particular the IHE profiles XDS.a, XDS.b, PIX, PDQ and support for the clinical document architecture (CDA) and the Continuity of Care Document (CCD) content profile. The release notes are here.

With IPF's IHE support, IHE actor interfaces can be implemented in IPF routes via URIs. This is as simple as using other Camel or IPF components such as the HTTP or JMS components. The URIs denote individual transactions (ITI) in IHE profiles. For example

from('xds-iti18:myIti18Service')
...

implements the 'XDS Registry Stored Query' service interface of an XDS document registry and can be used from any XDS ITI18-compliant consumer. Such a consumer can also be implemented using the same IPF xds-iti18 component on client side e.g.

...
.to('xds-iti18://somehost:8080/myWebApp/services/myIti18Service')


All the low-level details like communicating with ebXML messages over SOAP etc. is handled by that component. IPF routes deal with easy-to-use object representations of messages exchanged within IHE transactions. The full list of supported transactions is given in the IHE quick reference.

With IPF's CDA and CCD support clinical documents can be created, parsed, rendered and queried/analyzed using a domain-specific language (DSL). This DSL hides away most of the technical details you usually encounter when dealing with the complex XML-representation of clinical documents. In addition to these content-DSL extensions, IPF also provides some route DSL extension for parsing, validating and marshalling CDA documents in IPF routes.

Here's an excerpt of new IPF 1.7.0 features added since 1.6.0

* IHE support
** IHE XDS.a+b transactions (ITI 14-18, 41-43)
** IHE PIX transactions (ITI 8-10)
** IHE PDQ transactions (ITI 21-22)
** IHE ATNA for all the above transactions
* CDA support
** Generic CDA support
** CCD profile support
* Advanced XML processing
** Caching XSLT transmogrifier
** Schematron validator
* Detailed XDS tutorial
* Performance measurement support
* Scheduled flow management database cleanup
* ...

IPF 1.7.0 is based on Camel 1.6. In parallel, a Camel 2.0-based version is developed on the IPF 2.0 branch. The current development snapshot is feature-equivalent with IPF 1.7.0 but runs on Camel 2.0. The next IPF 2.0 milestone 2 release will follow within the next one or two weeks. I recommend you to use the 2.0 milestone releases unless you upgrade from an older IPF 1.x release. After releasing IPF 2.0.0, work on IPF 1.x will go into maintainance mode (but we leave it open whether to backport selected IPF 2.x features).

Exciting new features in IPF 2.0 which didn't make it into IPF 1.7 are Eclipse-based IPF development tools and improvements to IPF's OSGi support. These features are developed and documented in a separate IPF Tools project. The Eclipse-based IPF management client has been moved to this project as well. I'll give a more detailed IPF 2.0 overview in a separate post.

Many thanks to the whole development team and contributors for their excellent and high-quality work!