<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2708349453904691513</id><updated>2012-02-01T07:42:28.012+01:00</updated><category term='open ehealth'/><category term='zookeeper'/><category term='scala'/><category term='scalability'/><category term='REST'/><category term='jaxb'/><category term='scalate'/><category term='restful'/><category term='ccd'/><category term='immutable'/><category term='jax-rs'/><category term='stm'/><category term='jersey'/><category term='camel'/><category term='JSR 311'/><category term='cda'/><category term='Google App Engine'/><category term='gae'/><category term='event-sourced'/><category term='grails'/><category term='ihe'/><category term='integration'/><category term='restlet'/><category term='actor model'/><category term='event-driven'/><category term='ClientLogin'/><category term='akka'/><category term='cqrs'/><category term='ehealth'/><category term='oauth'/><category term='jaxrs'/><category term='bookkeeper'/><category term='IPF'/><title type='text'>Martin Krasser's Blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://krasserm.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://krasserm.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Martin Krasser</name><uri>http://www.blogger.com/profile/11765963540395771125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://4.bp.blogspot.com/_LrEpKPgi9gI/TI-WeznHzsI/AAAAAAAAACM/FO3hdlxwrdI/S220/Bild006a.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>18</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2708349453904691513.post-1731588851939782350</id><published>2012-01-20T17:34:00.013+01:00</published><updated>2012-01-21T09:09:08.161+01:00</updated><title type='text'>Building an Event-Sourced Web Application - Part 2: Projections, Persistence, Consumers and Web Interface</title><content type='html'>&lt;span style="font-style:italic;"&gt;&lt;span style="font-weight:bold;"&gt;NOTE:&lt;/span&gt; This is a draft. In its current state, this blog post gives an &lt;a href="#ovr"&gt;overview&lt;/a&gt; of the latest event-sourcing &lt;a href="https://github.com/krasserm/eventsourcing-example/tree/part-2"&gt;example application&lt;/a&gt; developments. It also serves as a guide to the relevant code sections with more detailed descriptions to follow. One topic that is already covered in more detail is &lt;a href="#sle"&gt;Service Layer Enhancements&lt;/a&gt;.&lt;/span&gt;&lt;br /&gt;&lt;a name="ovr"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Overview&lt;/h2&gt; A few weeks ago I &lt;a href="http://krasserm.blogspot.com/2011/11/building-event-sourced-web-application.html"&gt;started&lt;/a&gt; a blog post series to summarize my experiences in building an event-sourced web application using Scala and Akka. This was done based on an example application (see &lt;a href="https://github.com/krasserm/eventsourcing-example/tree/part-1"&gt;branch part-1&lt;/a&gt;). There, I gave an overview of the application architecture and presented some details of the immutable domain model and the service layer. Since then, the example application has been extended (see &lt;a href="https://github.com/krasserm/eventsourcing-example/tree/part-2"&gt;branch part-2&lt;/a&gt;) with a number of new features and enhancements. Here's an overview: &lt;br /&gt;&lt;br /&gt;Enhancements are:&lt;ul&gt;&lt;li&gt;The STM-based state management was completely revised and generalized into the traits &lt;code&gt;&lt;a href="https://github.com/krasserm/eventsourcing-example/blob/part-2/src/main/scala/dev/example/eventsourcing/state/Projection.scala#L20"&gt;UpdateProjection&lt;/a&gt;&lt;/code&gt; and &lt;code&gt;&lt;a href="https://github.com/krasserm/eventsourcing-example/blob/part-2/src/main/scala/dev/example/eventsourcing/state/Projection.scala#L71"&gt;EventProjection&lt;/a&gt;&lt;/code&gt;. An &lt;code&gt;UpdateProjection&lt;/code&gt; is similar to an &lt;a href="http://akka.io/docs/akka/1.2/scala/agents.html"&gt;Akka Agent&lt;/a&gt;: it applies state transition functions asynchronously and can participate in STM transactions. The major difference is that an &lt;code&gt;UpdateProjection&lt;/code&gt; is specialized on domain object updates and can log captured events to a persistent event log. By default, update events are logged before state changes are visible via STM references (this is an important difference to the service layer of &lt;a href="http://krasserm.blogspot.com/2011/11/building-event-sourced-web-application.html"&gt;part 1&lt;/a&gt;). &lt;code&gt;UpdateProjection&lt;/code&gt; implementors (such as the example application's &lt;code&gt;&lt;a href="https://github.com/krasserm/eventsourcing-example/blob/part-2/src/main/scala/dev/example/eventsourcing/service/InvoiceService.scala#L9"&gt;InvoiceService&lt;/a&gt;&lt;/code&gt;) are domain event producers. &lt;code&gt;EventProjection&lt;/code&gt; implementors, on the other hand, are domain event consumers. They internally use plain Akka Agents to manage state and derive new state values from received domain events (using an application-defined event projection function). &lt;code&gt;EventProjection&lt;/code&gt; implementors are usually components that manage read models or coordinate business processes in event-driven architectures, for example.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The &lt;a href="https://github.com/krasserm/eventsourcing-example/blob/part-2/src/main/scala/dev/example/eventsourcing/domain/Invoice.scala#L1"&gt;domain model&lt;/a&gt; was enhanced by introducing the domain classes &lt;code&gt;DraftInvoice&lt;/code&gt;, &lt;code&gt;SentInvoice&lt;/code&gt; and &lt;code&gt;PaidInvoice&lt;/code&gt; to represent the states an invoice can have. Valid state transitions are defined by the methods on these domain classes and can therefore be checked by the compiler. This approach is explained more detailed &lt;a href="http://blog.zilverline.com/2011/02/07/towards-an-immutable-domain-model-%E2%80%93-believe-the-type-part-4/"&gt;here&lt;/a&gt; although the implementation used in our example application slightly differs. In &lt;a href="http://krasserm.blogspot.com/2011/11/building-event-sourced-web-application.html"&gt;part 1&lt;/a&gt;, we only had a single &lt;code&gt;Invoice&lt;/code&gt; class and valid state transitions had to be checked at runtime.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;New features include: &lt;ul&gt;&lt;li&gt;A revised &lt;code&gt;&lt;a href="https://github.com/krasserm/eventsourcing-example/blob/part-2/src/main/scala/dev/example/eventsourcing/event/Event.scala#L9"&gt;EventLog&lt;/a&gt;&lt;/code&gt; trait together with two implementations: &lt;code&gt;&lt;a href="https://github.com/krasserm/eventsourcing-example/blob/part-2/src/main/scala/dev/example/eventsourcing/event/impl/JournalioEventLog.scala#L17"&gt;JournalioEventLog&lt;/a&gt;&lt;/code&gt; is based on &lt;a href="https://github.com/sbtourist/Journal.IO"&gt;Journal.IO&lt;/a&gt; and &lt;code&gt;&lt;a href="https://github.com/krasserm/eventsourcing-example/blob/part-2/src/main/scala/dev/example/eventsourcing/event/impl/BookkeeperEventLog.scala#L16"&gt;BookkeeperEventLog&lt;/a&gt;&lt;/code&gt; on &lt;a href="http://zookeeper.apache.org/doc/r3.3.3/bookkeeperOverview.html"&gt;Apache BookKeeper&lt;/a&gt;. An &lt;code&gt;EventLog&lt;/code&gt; supports synchronous and asynchronous appending of events as well as iterating over stored events, either from the beginning or from an application-defined position in the event history. Event log entries are also assigned sequence numbers so that event consumers can detect gaps in event streams or re-order (resequence) them, if needed.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Event consumers. One example is &lt;code&gt;&lt;a href="https://github.com/krasserm/eventsourcing-example/blob/part-2/src/main/scala/dev/example/eventsourcing/service/InvoiceStatistics.scala#L7"&gt;InvoiceStatistics&lt;/a&gt;&lt;/code&gt;, an &lt;code&gt;EventProjection&lt;/code&gt; that derives invoice update statistics from domain events. Here, a separate read model is used (following the CQRS pattern) to serve invoice statistic queries. Another example is &lt;code&gt;&lt;a href="https://github.com/krasserm/eventsourcing-example/blob/part-2/src/main/scala/dev/example/eventsourcing/service/InvoiceReplicator.scala#L7"&gt;InvoiceReplicator&lt;/a&gt;&lt;/code&gt;, an &lt;code&gt;EventProjection&lt;/code&gt; that simply reconstructs the invoice map (as maintained by the &lt;code&gt;InvoiceService&lt;/code&gt;) from invoice events at a different location. It can be used to replicate application state across different nodes and to serve (eventually consistent) reads. The replicated state could also be used by a snapshot service to take snapshots of application state. &lt;code&gt;InvoiceReplicator&lt;/code&gt; needs to receive events in the correct order and is therefore &lt;a href="https://github.com/krasserm/eventsourcing-example/blob/part-2/src/main/scala/dev/example/eventsourcing/service/InvoiceReplicator.scala#L19"&gt;configured to resequence&lt;/a&gt; the received event stream. A third example is the &lt;code&gt;&lt;a href="https://github.com/krasserm/eventsourcing-example/blob/part-2/src/main/scala/dev/example/eventsourcing/service/PaymentProcess.scala#L6"&gt;PaymentProcess&lt;/a&gt;&lt;/code&gt;. It coordinates the activities of &lt;code&gt;InvoiceService&lt;/code&gt; and &lt;code&gt;PaymentService&lt;/code&gt;. Instead of having these services sending commands to each other, it is the &lt;code&gt;PaymentProcess&lt;/code&gt; that sends commands to (i.e. calls methods on) these services in reaction to domain events. This event-driven approach to implementing business processes not only decouples the services from each other but also lets other components extend (or monitor) the business process by subscribing to and reacting on the relevant domain events. The &lt;code&gt;PaymentProcess&lt;/code&gt; is currently stateless. Processes that need to maintain state should implement &lt;code&gt;EventProjection&lt;/code&gt; and recover the process state during application start (or failover) from the event history.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;A RESTful web interface for invoices and invoice statistics with support for HTML, XML and JSON representations. These can be negotiated with the HTTP Accept header. The web layer is based on the &lt;a href="http://jersey.java.net/"&gt;Jersey&lt;/a&gt; web framework (the &lt;a href="http://jcp.org/en/jsr/detail?id=311"&gt;JAX-RS&lt;/a&gt; reference implementation). HTML representations are rendered with the &lt;a href="http://scalate.fusesource.org/"&gt;Scalate&lt;/a&gt; template engine. The mapping between XML and JSON representations and immutable domain classes is based on &lt;a href="http://jcp.org/en/jsr/detail?id=222"&gt;JAXB&lt;/a&gt; annotations. A JAXB-based XML provider must be supported by any JAX-RS implementation but Jersey additionally comes with a JAXB-based &lt;a href="http://jersey.java.net/nonav/documentation/latest/user-guide.html#d4e911"&gt;JSON provider&lt;/a&gt; so that the same metadata (JAXB annotations) can be used to generate both XML and JSON representations. Following some simple rules, it is possible to &lt;a href="https://github.com/krasserm/eventsourcing-example/blob/part-2/src/main/scala/dev/example/eventsourcing/domain/Invoice.scala#L47"&gt;JAXB-annotate Scala case classes&lt;/a&gt; without polluting them with Java collection types or getters and setters. One major drawback of the current JAX-RS specification is that it doesn't support asynchronous responses yet. This will change with &lt;a href="http://jcp.org/en/jsr/detail?id=339"&gt;JAX-RS 2.0&lt;/a&gt; and then we can make full use of the asynchronous &lt;code&gt;InvoiceService&lt;/code&gt; responses.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;A communication &lt;code&gt;&lt;a href="https://github.com/krasserm/eventsourcing-example/blob/part-2/src/main/scala/dev/example/eventsourcing/event/Channel.scala#L5"&gt;Channel&lt;/a&gt;&lt;/code&gt; for connecting domain event producers to consumers. The example application provides a &lt;code&gt;&lt;a href="https://github.com/krasserm/eventsourcing-example/blob/part-2/src/main/scala/dev/example/eventsourcing/event/Channel.scala#L12"&gt;SimpleChannel&lt;/a&gt;&lt;/code&gt; implementation for local communication. Alternative implementations, for example, could connect to a distributed event bus to communicate events across components of a distributed application.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Running the example application&lt;/h2&gt;The example application can be started with &lt;br /&gt;&lt;br /&gt;&lt;code&gt;sbt run-main dev.example.eventsourcing.server.Webserver&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Two classes relevant for starting the application are:&lt;ul&gt;&lt;li&gt;&lt;code&gt;&lt;a href="https://github.com/krasserm/eventsourcing-example/blob/part-2/src/main/scala/dev/example/eventsourcing/server/Appserver.scala#L15"&gt;Appserver&lt;/a&gt;&lt;/code&gt;: configures the event log, services, read models and processes and connects them via an event channel. It also recovers application state from the event history.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;&lt;a href="https://github.com/krasserm/eventsourcing-example/blob/part-2/src/main/scala/dev/example/eventsourcing/server/Webserver.scala#L21"&gt;Webserver&lt;/a&gt;&lt;/code&gt;: configures the web service layer and starts an embedded web server (Jetty).&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;To experiment with the BookKeeper based event log, you need to replace &lt;code&gt;JournalioEventLog&lt;/code&gt; with &lt;code&gt;BookkeeperEventLog&lt;/code&gt; in &lt;code&gt;Appserver&lt;/code&gt; and additionally start a test BookKeeper instance with&lt;br /&gt;&lt;br /&gt;&lt;code&gt;sbt run-main dev.example.eventsourcing.server.Zookeeper&lt;br /&gt;sbt run-main dev.example.eventsourcing.server.Bookkeeper&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Examples how to interact with the RESTful web interface can be found &lt;a href="https://github.com/krasserm/eventsourcing-example/blob/part-2/README.md"&gt;here&lt;/a&gt;.&lt;a name="sle"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Service Layer Enhancements&lt;/h2&gt; In the service layer implementation from part 1 we've seen how to keep the order of logged events in correspondence with the order of updates to the application state. We used a transient event log that could participate in STM transactions. After the transaction commits, the events from the transient event log have been transferred to a persistent event log. A drawback of this approach is that one can loose updates in case of crashes after an STM reference has been updated but before the changes have been written to the persistent event log. This can lead to situations where clients can already see application state that cannot be recovered from the event log. While some applications may tolerate this, others may require that any visible application state must be fully recoverable from the event log. Therefore, an alternative approach must be chosen.&lt;br /&gt;&lt;br /&gt;We need a way to write events, captured during domain object updates, to a persistent event log &lt;span style="font-weight:bold;"&gt;before&lt;/span&gt; the STM reference is updated. But writing to the persistent event log must be done outside an STM transaction for reasons explained in part 1. Updates must also be based on the current (i.e. latest) application state. We therefore need to&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Get the current state value from a transactional reference (STM transaction 1)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Update domain object(s) obtained from the current state (no STM transaction)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Write the captured update event(s) to a persistent event log (no STM transaction)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Compute a new state value from the domain object update and write it to the transactional reference (STM transaction 2)&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Since steps 1-4 are not a single transaction we must prevent their concurrent execution. This can be achieved using a single actor, for example. This actor is the single writer to the transactional reference. This is actually very similar to how Akka Agents work internally. The main difference in our case is that the computation of a new state value occurs outside an STM transaction, whereas Akka Agents apply update functions within STM transactions. This difference allows us to have side effects, such as writing to a persistent event log. The example application provides the above functionality in the &lt;code&gt;UpdateProjection&lt;/code&gt; trait:&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1648358.js?file=service-01.scala"&gt;&lt;/script&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Instances of &lt;code&gt;UpdateProjection&lt;/code&gt; manage (part of) application state with a transactional &lt;code&gt;ref&lt;/code&gt; of type &lt;code&gt;Ref[S]&lt;/code&gt; where &lt;code&gt;S&lt;/code&gt; is the state value type. Clients concurrently read application state via &lt;code&gt;currentState&lt;/code&gt;. Sequential writes to the transactional &lt;code&gt;ref&lt;/code&gt; are done exclusively by the &lt;code&gt;updater&lt;/code&gt; actor (more on write concurrency below).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;UpdateProjection&lt;/code&gt; implementors change application state with the &lt;code&gt;transacted&lt;/code&gt; method. The &lt;code&gt;update&lt;/code&gt; parameter is a function that computes a domain object &lt;code&gt;Update[Event, B]&lt;/code&gt; from current state &lt;code&gt;S&lt;/code&gt; where &lt;code&gt;B&lt;/code&gt; is a domain object type. The update result (either &lt;code&gt;Success[B]&lt;/code&gt; or &lt;code&gt;Failure[DomainError]&lt;/code&gt;) is returned as future value from the &lt;code&gt;transacted&lt;/code&gt; method.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The &lt;code&gt;update&lt;/code&gt; function and the underlying &lt;code&gt;Future&lt;/code&gt; implementation object (&lt;code&gt;promise&lt;/code&gt;) are sent to the updater actor with an &lt;code&gt;ApplyUpdate&lt;/code&gt; message. The &lt;code&gt;updater&lt;/code&gt; then reads the current state and applies the &lt;code&gt;update&lt;/code&gt; function to it. If the update succeeds, it writes the captured events to an &lt;code&gt;EventLog&lt;/code&gt; and projects the update result onto the current state. The projection is done with the &lt;code&gt;project&lt;/code&gt; function. It creates a new state value from the current state and the update result. The new state value is then finally set on the transactional &lt;code&gt;ref&lt;/code&gt; and the &lt;code&gt;promise&lt;/code&gt; is completed with the update result.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Furthermore, the &lt;code&gt;transacted&lt;/code&gt; method can participate in STM transactions. If there's an enclosing transaction, the &lt;code&gt;updater&lt;/code&gt; actor will only be triggered if the enclosing transaction successfully commits. If there's no enclosing transaction the &lt;code&gt;updater&lt;/code&gt; actor will always be triggered.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;The example application uses &lt;code&gt;UpdateProjection&lt;/code&gt; to implement the stateful &lt;code&gt;InvoiceService&lt;/code&gt;. The state is of type &lt;code&gt;Map[String, Invoice]&lt;/code&gt; i.e. a single map containing draft, sent and paid invoices. Here's a simplified version of &lt;code&gt;InvoiceService&lt;/code&gt;:&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1648358.js?file=service-02.scala"&gt;&lt;/script&gt;&lt;br /&gt;The &lt;code&gt;updateInvoice&lt;/code&gt; method uses the &lt;code&gt;transacted&lt;/code&gt; method of the &lt;code&gt;UpdateProjection&lt;/code&gt; trait. It tries to get an invoice with given &lt;code&gt;invoiceId&lt;/code&gt; from the current state and applies the supplied update function &lt;code&gt;f&lt;/code&gt; to it. The &lt;code&gt;updateInvoice&lt;/code&gt; method is used by &lt;code&gt;updateDraftInvoice&lt;/code&gt; for updating draft invoices in the invoice map. The &lt;code&gt;updateDraftInvoice&lt;/code&gt; method is used by the service methods &lt;code&gt;addInvoiceItem&lt;/code&gt; and &lt;code&gt;sendInvoiceTo&lt;/code&gt;. Adding an item to an existing draft invoice yields a future value of an updated draft invoice (return type &lt;code&gt;Future[DomainValidation[DraftInvoice]]&lt;/code&gt;). Sending an existing draft invoice, on the other hand, causes a state transition of that invoice to a sent invoice (return type &lt;code&gt;Future[DomainValidation[SentInvoice]]&lt;/code&gt;) i.e. the service methods make use of the newly introduced domain object types. The &lt;code&gt;InvoiceService&lt;/code&gt; must also implement the abstract members &lt;code&gt;project&lt;/code&gt;, &lt;code&gt;initialState&lt;/code&gt; and &lt;code&gt;eventLog&lt;/code&gt; (declared by &lt;code&gt;Projection&lt;/code&gt; and &lt;code&gt;UpdateProjection&lt;/code&gt;).&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The &lt;code&gt;project&lt;/code&gt; implementation projects an updated invoice onto the current state by simply adding it to the map of invoices (replacing an old invoice if present).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;An &lt;code&gt;initialState&lt;/code&gt; (empty map by default) and an &lt;code&gt;EventLog&lt;/code&gt; instance are provided during construction of an &lt;code&gt;InvoiceService&lt;/code&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;The above &lt;code&gt;InvoiceService&lt;/code&gt; implementation supports concurrent reads but only sequential writes to the whole invoice map. This may be sufficient for many applications but if a higher degree of write concurrency is needed, one could choose to have a separate &lt;code&gt;UpdateProjection&lt;/code&gt; instance per invoice object (which is comparable to have a separate Akka Agent for each invoice object). This allows both concurrent reads and writes to the invoices of an application. The following snippet shows the general idea (not part of the example project).&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1648358.js?file=service-03.scala"&gt;&lt;/script&gt;&lt;br /&gt;Here, an &lt;code&gt;InvoiceService&lt;/code&gt; maintains a map of &lt;code&gt;PersistentInvoice&lt;/code&gt; instances where a &lt;code&gt;PersistentInvoice&lt;/code&gt; is an &lt;code&gt;UpdateProjection&lt;/code&gt; that contains a reference to a single (draft, sent or paid) invoice. Consequently, updates to different invoices can now be made concurrently. The projection function degenerates to a function that simply returns the updated invoice.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Event Logs&lt;/h2&gt;TODO&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;CQRS and Consistency&lt;/h2&gt;TODO&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Business Processes&lt;/h2&gt;TODO&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Web Interface&lt;/h2&gt;TODO&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2708349453904691513-1731588851939782350?l=krasserm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://krasserm.blogspot.com/feeds/1731588851939782350/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://krasserm.blogspot.com/2012/01/building-event-sourced-web-application.html#comment-form' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/1731588851939782350'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/1731588851939782350'/><link rel='alternate' type='text/html' href='http://krasserm.blogspot.com/2012/01/building-event-sourced-web-application.html' title='Building an Event-Sourced Web Application - Part 2: Projections, Persistence, Consumers and Web Interface'/><author><name>Martin Krasser</name><uri>http://www.blogger.com/profile/11765963540395771125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://4.bp.blogspot.com/_LrEpKPgi9gI/TI-WeznHzsI/AAAAAAAAACM/FO3hdlxwrdI/S220/Bild006a.jpg'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2708349453904691513.post-371508144843543204</id><published>2011-11-29T13:06:00.032+01:00</published><updated>2011-12-09T07:37:41.826+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='restful'/><category scheme='http://www.blogger.com/atom/ns#' term='bookkeeper'/><category scheme='http://www.blogger.com/atom/ns#' term='event-driven'/><category scheme='http://www.blogger.com/atom/ns#' term='akka'/><category scheme='http://www.blogger.com/atom/ns#' term='jersey'/><category scheme='http://www.blogger.com/atom/ns#' term='stm'/><category scheme='http://www.blogger.com/atom/ns#' term='zookeeper'/><category scheme='http://www.blogger.com/atom/ns#' term='cqrs'/><category scheme='http://www.blogger.com/atom/ns#' term='scalate'/><category scheme='http://www.blogger.com/atom/ns#' term='jaxb'/><category scheme='http://www.blogger.com/atom/ns#' term='immutable'/><category scheme='http://www.blogger.com/atom/ns#' term='event-sourced'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>Building an Event-Sourced Web Application - Part 1: Domain Model, Events and State</title><content type='html'>Over the last few months I was working for a project in which we built an event-sourced healthcare web application from scratch with Scala and &lt;a href="http://akka.io/"&gt;Akka&lt;/a&gt;. This is the first of a series of blog posts where I want to share some of my experiences and design decisions.&lt;br /&gt;&lt;br /&gt;The application architecture follows an architectural pattern that has been described as &lt;a href="http://martinfowler.com/bliki/MemoryImage.html"&gt;memory image&lt;/a&gt; or &lt;a href="http://en.wikipedia.org/wiki/System_Prevalence"&gt;system prevalence&lt;/a&gt;: application state is kept in memory rather than written to a database. Only state changes are written to a persistent store in terms of domain events. Snapshots of application state are saved to disk at regular intervals. Application state can be reconstructed by replaying the logged events (either beginning from scratch or from a saved snapshot). We've chosen this architecture because&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The state of our application easily fits within 2 GB of memory. Should this become a limitation in the future, we can easily partition the application state across several nodes (which can also be used to scale writes, if needed).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Very low latency can be achieved for read and write access to application state. To ensure atomicity, consistency and isolation, we use a &lt;a href="http://en.wikipedia.org/wiki/Software_transactional_memory"&gt;Software Transactional Memory&lt;/a&gt; (STM). Durability is achieved with a persistent event log.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The application must be able to answer queries not only based on its current state but also based on the history of state changes. Requirements for such queries are often not known from the beginning and can therefore not be considered during initial database design. Using a persistent event log instead, one can build suitable read models any time later by replaying the whole event history.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Multiple copies of the application state can be created on other nodes by consuming domain events that have been published by a writer (or leader) node. Should the current writer go down, one can easily switch to another node to achieve high-availability.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;From the memory image approach, we excluded all data that are written only once and are not modified later, such as large medical image files or clinical documents. They are stored directly on a (distributed) file system and only references to it are kept in memory.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Application Overview&lt;/h2&gt;The following list briefly summarizes some of the concepts and technologies used to implement the different parts of the application. In this blog post I'll focus on the domain model and the service layer. The other parts will be described in follow-up posts.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The &lt;span style="font-weight: bold;"&gt;domain model&lt;/span&gt; is an immutable domain model. One advantage of immutable domain objects is that you can safely share with other application components, for example, by sending them along with event messages. Immutable domain objects are also needed when using them together with Software Transactional Memory (see also &lt;a href="http://outputstream.io/dear-scalasphere-why-arent-we-talking-more-ab"&gt;this article&lt;/a&gt;).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The &lt;span style="font-weight: bold;"&gt;service layer&lt;/span&gt; provides transactional access to the application state. Application state is managed by transactional references. State values are (immutable) domain objects. State changes occur by updating the transactional references with new domain object values. For transaction management, &lt;a href="http://akka.io/docs/akka/1.2/scala/stm.html"&gt;Akka's Software Transactional Memory&lt;/a&gt; (STM) is used. The application's approach to state, identity and concurrency mainly follows the concepts described in &lt;a href="http://clojure.org/state"&gt;State and Identity&lt;/a&gt; (which is part of the &lt;a href="http://clojure.org/"&gt;Clojure&lt;/a&gt; documentation).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The &lt;span style="font-weight: bold;"&gt;persistence layer&lt;/span&gt; comprises a persistent event log and snapshots of the application state. In the production system, we use &lt;a href="http://zookeeper.apache.org/doc/r3.3.4/bookkeeperOverview.html"&gt;Apache BookKeeper&lt;/a&gt; as distributed, highly-available and scalable event log. Snapshots are stored on a distributed file system.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The &lt;span style="font-weight: bold;"&gt;web layer&lt;/span&gt; provides a RESTful service interface to application resources (domain objects) with support for HTML, XML and JSON as representation formats. We use &lt;a href="http://jersey.java.net/"&gt;Jersey&lt;/a&gt; as web framework for implementing the RESTful service interface together with &lt;a href="http://scalate.fusesource.org/"&gt;Scalate&lt;/a&gt; to render the HTML representations of domain objects. For XML and JSON bindings we use &lt;a href="http://jcp.org/en/jsr/detail?id=222"&gt;JAXB&lt;/a&gt; annotations on Scala case classes - seriously :)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Read models&lt;/span&gt; are used to serve more complex queries that cannot be (efficiently) answered by using the current application state. Read models are also event-sourced. Their structure is optimized to answer complex queries in a very efficient way. The approach to separate write models from read models is called &lt;a href="http://martinfowler.com/bliki/CQRS.html"&gt;Command Query Responsibility Segregation&lt;/a&gt; (CQRS). Read models can be stored in-memory (and reconstructed by replaying events) or persisted to a database. We use &lt;a href="http://akka.io/docs/akka/1.2/scala/agents.html"&gt;Akka agents&lt;/a&gt; to maintain in-memory read models.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Business process executors&lt;/span&gt; are stateful event listeners that implement long-running business processes. In reaction to domain events, they may change application state (via the service layer), coordinate changes across aggregate roots or interact with external services. We use &lt;a href="http://akka.io/docs/akka/1.2/scala/actors.html"&gt;Akka actors&lt;/a&gt; to implement business process executors.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Versioning of domain objects is used to support &lt;span style="font-weight: bold;"&gt;conditional updates&lt;/span&gt;. Only if the current version of a domain object matches a client-supplied version number, an update can proceed. We added this form of optimistic concurrency control in addition to that of STM transactions.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;For &lt;span style="font-weight: bold;"&gt;distributed coordination&lt;/span&gt;, we use &lt;a href="http://zookeeper.apache.org/"&gt;Apache Zookeeper&lt;/a&gt;. There's one node in our distributed system that performs state changes (the current writer or leader). Should the current leader go down, another leader is elected using a leader election algorithm implemented on top of Zookeeper. All nodes in the distributed system can serve (eventually consistent) reads. Strongly consistent reads can only be served by the current leader. We can therefore easily scale eventually consistent reads which is the majority of reads in our application.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Example application&lt;/h2&gt;There's also an &lt;a href="https://github.com/krasserm/eventsourcing-example"&gt;example project&lt;/a&gt; on github that demonstrates how to combine the contents of the following sections to a running application. I'll extend the application as I make progress on this blog post series. The branch referred to by this blog post is &lt;a href="https://github.com/krasserm/eventsourcing-example/tree/part-1"&gt;part-1&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The example application will cover some elements of our production system but not all of them. To keep things simple, I omitted performance optimizations and decided to use an over-simplified domain model from an other than the healthcare domain.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Domain Model&lt;/h2&gt;The approach to implement an immutable domain model was taken from the excellent article series &lt;a href="http://blog.zilverline.com/?s=immutable+domain+model&amp;amp;searchsubmit="&gt;Towards an Immutable Domain Model&lt;/a&gt; by Erik Rozendaal. In the following I'll briefly summarize this approach (with some modifications). For a more detailed description, please read through these articles series.&lt;br /&gt;&lt;br /&gt;The domain model of the example application is defined by the case classes &lt;code&gt;Invoice&lt;/code&gt;, &lt;code&gt;InvoiceItem&lt;/code&gt; and &lt;code&gt;InvoiceAddress&lt;/code&gt; (see &lt;a href="https://github.com/krasserm/eventsourcing-example/blob/part-1/src/main/scala/dev/example/eventsourcing/domain/Invoice.scala"&gt;Invoice.scala&lt;/a&gt;). &lt;code&gt;Invoice&lt;/code&gt; is the aggregate root with methods to add an &lt;code&gt;InvoiceItem&lt;/code&gt;, set a discount and send an &lt;code&gt;Invoice&lt;/code&gt; (to a destination defined by &lt;code&gt;InvoiceAddress&lt;/code&gt;).&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1404555.js?file=domain-01.scala"&gt;&lt;/script&gt;&lt;br /&gt;The methods &lt;code&gt;addItem&lt;/code&gt;, &lt;code&gt;setDiscount&lt;/code&gt; and &lt;code&gt;sendTo&lt;/code&gt; generate the domain events &lt;code&gt;InvoiceItemAdded&lt;/code&gt;, &lt;code&gt;InvoiceDiscountSet&lt;/code&gt; and &lt;code&gt;InvoiceSent&lt;/code&gt;, respectively (see later). These are then handled by the &lt;code&gt;handle&lt;/code&gt; method. The &lt;code&gt;handle&lt;/code&gt; method creates &lt;code&gt;Invoice&lt;/code&gt; copies with updated members.&lt;br /&gt;&lt;br /&gt;In addition to generating domain events, the methods &lt;code&gt;addItem&lt;/code&gt;, &lt;code&gt;setDiscount&lt;/code&gt; and &lt;code&gt;sendTo&lt;/code&gt; not only execute business logic (by checking preconditions, for example) but also capture the generated events. Generated events are captured with the &lt;a href="https://github.com/krasserm/eventsourcing-example/blob/part-1/src/main/scala/dev/example/eventsourcing/domain/Update.scala#L5"&gt;&lt;code&gt;Update&lt;/code&gt;&lt;/a&gt; monad (a state monad) which is the return type of these methods. This is shown for &lt;code&gt;sendTo&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1404555.js?file=domain-02.scala"&gt;&lt;/script&gt;&lt;br /&gt;A successful update adds the generated &lt;code&gt;InvoiceSent&lt;/code&gt; event and the updated &lt;code&gt;Invoice&lt;/code&gt; to the returned &lt;code&gt;Update&lt;/code&gt; instance (using the &lt;code&gt;update&lt;/code&gt; method from the &lt;code&gt;EventSourced&lt;/code&gt; trait). A failed update is reported with a &lt;a href="https://github.com/krasserm/eventsourcing-example/blob/part-1/src/main/scala/dev/example/eventsourcing/domain/package.scala#L7"&gt;&lt;code&gt;DomainError&lt;/code&gt;&lt;/a&gt; (using &lt;code&gt;Update.reject&lt;/code&gt;). Update results are instances of &lt;a href="https://github.com/scalaz/scalaz/blob/6.0.3/core/src/main/scala/scalaz/Validation.scala#L3"&gt;&lt;code&gt;Validation&lt;/code&gt;&lt;/a&gt; (either &lt;code&gt;Success&lt;/code&gt; or &lt;code&gt;Failure&lt;/code&gt;) which can be obtained by calling &lt;code&gt;result()&lt;/code&gt; on the monad&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1404555.js?file=domain-03.scala"&gt;&lt;/script&gt;&lt;br /&gt;where &lt;code&gt;Success&lt;/code&gt; contains the updated &lt;code&gt;Invoice&lt;/code&gt; and &lt;code&gt;Failure&lt;/code&gt; contains the reported error. To get access to the captured events, call the result method with a callback function.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1404555.js?file=domain-04.scala"&gt;&lt;/script&gt;&lt;br /&gt;This function is only called for successful updates with the captured events and the updated &lt;code&gt;Invoice&lt;/code&gt;. We will see a concrete usage example later. Since &lt;code&gt;Update&lt;/code&gt; is a monad, we can also chain domain object updates with a for-comprehension.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1404555.js?file=domain-05.scala"&gt;&lt;/script&gt;&lt;br /&gt;Only if all individual updates are successful, the overall update will be successful. If one or more individual updates fail, the overall update will fail. Finally, we want to be able to reconstruct an &lt;code&gt;Invoice&lt;/code&gt; object from the history of events. This can be done with the &lt;code&gt;Invoice.handle(events: List[InvoiceEvent])&lt;/code&gt; method on the &lt;code&gt;Invoice&lt;/code&gt; companion object, as shown in the following example.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1404555.js?file=domain-06.scala"&gt;&lt;/script&gt;&lt;br /&gt;Having these domain model properties in place, we can now use immutable &lt;code&gt;Invoice&lt;/code&gt; objects to define application state and use captured events to write them to a (persistent) event log.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Service Layer&lt;/h2&gt;Application state is managed in the application's service layer. Here, &lt;code&gt;InvoiceService&lt;/code&gt; maintains a map of &lt;code&gt;Invoice&lt;/code&gt; objects where map keys are invoice ids.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1404574.js?file=service-01.scala"&gt;&lt;/script&gt;&lt;br /&gt;To control concurrent access to the invoices map, a transactional reference (&lt;code&gt;akka.stm.Ref&lt;/code&gt;) is used. It is part of &lt;a href="http://akka.io/docs/akka/1.2/scala/stm.html"&gt;Akka's STM&lt;/a&gt; (Multiverse) but rewriting the example using &lt;a href="http://nbronson.github.com/scala-stm/"&gt;Scala's STM&lt;/a&gt; shouldn't be a big deal. Using a single transactional reference for all &lt;code&gt;Invoice&lt;/code&gt; objects is a rather naive approach because it can easily lead to high contention on the &lt;code&gt;invoicesRef&lt;/code&gt;, but it keeps the example as simple as possible. (Using a single transactional reference for all &lt;code&gt;Invoice&lt;/code&gt; objects is a reasonable approach only if updates to different &lt;code&gt;Invoice&lt;/code&gt; objects depend on each other which is usually not the case, or if there aren't many concurrent writes. We will see better approaches, causing less contention, later in this section). An alternative approach for managing state is using actors but I'll leave that for another blog post.&lt;br /&gt;&lt;br /&gt;Changes to the application state are made inside an &lt;code&gt;atomic {...}&lt;/code&gt; block, as shown for the &lt;code&gt;addInvoiceItem&lt;/code&gt; method (see also &lt;a href="https://github.com/krasserm/eventsourcing-example/blob/master/src/main/scala/dev/example/eventsourcing/service/InvoiceService.scala"&gt;InvoiceService.scala&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1404574.js?file=service-02.scala"&gt;&lt;/script&gt;&lt;br /&gt;If any two updates to the &lt;code&gt;Invoice&lt;/code&gt; map are conflicting, one update will succeed, the other one will be retried by re-executing the &lt;code&gt;atomic&lt;/code&gt; block. Since we are using immutable domain objects, retrying updates is not an issue. What's still missing is to log the captured events (obtained from the &lt;code&gt;Update&lt;/code&gt; monad) to a persistent event log. In the following, we require that the order of logged events must correspond to the order of updates to the application state (otherwise we could get problems during a replay of events). We also make the assumption that our persistent event log cannot directly participate in STM transactions (which is the case for Apache BookKeeper, for example). We could try to:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Write captured events to the persistent event log within a transaction. Writing to a persistent event log involves IO operations (side-effects) that cannot be rolled back. Should the STM retry the transaction, the atomic block is re-executed and the captured events would be written to the event log again and this is not what we want.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Write the captured events after the STM transaction commits with the thread that started the transaction. This would solve the problem of redundantly logged events but then we cannot guarantee any more that the order of logged events still corresponds to the order of updates to the application state. This is because the writes could be done by different threads which introduces a race.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;So these two approaches don't work. One possible solution is the following approach:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Write the captured events to a transient, transactional event log inside the atomic block. This ensures that events are not redundantly logged and the order of events corresponds to the order of updates to the application state. The simplest possible transient, transactional event log is a &lt;code&gt;Ref[List[Event]]&lt;/code&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Transfer the logged events from the transactional event log to a persistent event log by preserving the order of events. Preserving the order of events can be achieved with a single thread (or actor) that reads from the transactional event log and writes events to the persistent event log. Any time an STM transaction commits we need to trigger this thread (or actor) to do the transfer.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Let's say this functionality is available through an &lt;code&gt;EventLog&lt;/code&gt; trait:&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1404574.js?file=service-03.scala"&gt;&lt;/script&gt;&lt;br /&gt;where&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;the &lt;code&gt;log&lt;/code&gt; method adds events to the transactional &lt;code&gt;eventsRef&lt;/code&gt; (must be called within a transaction) and&lt;/li&gt;&lt;br /&gt;&lt;li&gt;the &lt;code&gt;store*&lt;/code&gt; methods transfer the events from the &lt;code&gt;eventsRef&lt;/code&gt; to the persistent event log (must be called after the transaction commits). The &lt;code&gt;store&lt;/code&gt; method waits for the transfer to complete whereas &lt;code&gt;storeAsync&lt;/code&gt; returns immediately.&lt;/li&gt;&lt;/ul&gt;Having an implementation of &lt;code&gt;EventLog&lt;/code&gt; in place, it can be used as follows:&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1404574.js?file=service-04.scala"&gt;&lt;/script&gt;&lt;br /&gt;Within the transaction, captured events are added to the transactional event log. After the transaction successfully commits, the events are transferred to the persistent event log. This is done within the &lt;code&gt;deferred&lt;/code&gt; block which is executed only once after commit. Here, we don't wait for the events being persisted (&lt;code&gt;storeAsync&lt;/code&gt;). We could also extend the &lt;code&gt;storeAsync&lt;/code&gt; and &lt;code&gt;addInvoiceItem&lt;/code&gt; method signatures to let clients provide an asynchronous completion callback function in order to be notified when events have been written successfully (or an error occurred during writing). A production-ready implementation of &lt;code&gt;EventLog&lt;/code&gt; should also provide strategies to recover from errors writing to the persistent event log. In a follow-up blog post I'll show an implementation of &lt;code&gt;EventLog&lt;/code&gt; that uses Apache BookKeeper (&lt;b&gt;update&lt;/b&gt;: I'll also show how to do write-ahead logging which first writes events to the event log and then, if writing was successful, updates the invoices map. This can be done by queueing up updates). In its current state the example application has an &lt;code&gt;EventLog&lt;/code&gt; implementation that stores events in memory, for testing purposes (see &lt;a href="https://github.com/krasserm/eventsourcing-example/blob/master/src/main/scala/dev/example/eventsourcing/log/TestEventLog.scala"&gt;TestEventLog.scala&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;The &lt;code&gt;InvoiceService&lt;/code&gt; also provides methods for reading invoices. Supporting consistent reads is as easy as&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1404574.js?file=service-05.scala"&gt;&lt;/script&gt;&lt;br /&gt;Here &lt;code&gt;invoicesRef()&lt;/code&gt; implicitly starts a new transaction, so we don't need to make the read operation within an &lt;code&gt;atomic {...}&lt;/code&gt; block. There are some situations where consistent reads are needed by clients (for example, in a web application during a post/redirect/get cycle where invoices must be immediately available for reading after their creation). In this case, the &lt;code&gt;InvoiceService&lt;/code&gt; should be used. In other situations, eventually consistent reads are sufficient. In that case, we wouldn't use the &lt;code&gt;InvoiceService&lt;/code&gt; to obtain &lt;code&gt;Invoice&lt;/code&gt; objects, we'd rather obtain it from a separate (event-sourced) read model that is asynchronously generated from published events (using CQRS). This will be shown in a follow-up blog post.&lt;br /&gt;&lt;br /&gt;Finally, lets look at some options how contention on the &lt;code&gt;invoicesRef&lt;/code&gt; (and the transactional event log) can be reduced (in situations with many concurrent writes). We can say that&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Updates to different &lt;code&gt;Invoice&lt;/code&gt; entities are independent, so we don't need to care about ordering of events in this case.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Updates to the same &lt;code&gt;Invoice&lt;/code&gt; entity are dependent, so the order of logged events must correspond to the order of updates to that entity.&lt;/li&gt;&lt;/ul&gt;This means that we can use transactional references for each individual &lt;code&gt;Invoice&lt;/code&gt; entity. Consequently, updates to different invoice entities do not interfere with each other.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1404574.js?file=service-06.scala"&gt;&lt;/script&gt;&lt;br /&gt;The transactional reference for the whole map is only needed for the case that new invoices are concurrently added to the map (and to ensure consistent reads, of course). We could also use a separate event log for each &lt;code&gt;Ref[Invoice]&lt;/code&gt;, so that there's no contention on the transactional event log for independent updates.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1404574.js?file=service-07.scala"&gt;&lt;/script&gt;&lt;br /&gt;In this case, different transactional event logs would share the same persistent event log backend.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Summary&lt;/h2&gt;We started to build an event-sourced application whose state is kept entirely in memory, only state changes are persisted to an event log in terms of domain events. Application state is defined by immutable domain objects which are accessed through transactional references. A state change means updating the transactional references with new domain objects (new state value) within a STM transaction. Events that have been generated during domain object updates are written to a transient, transactional event log. Transfer to a persistent event log occurs once the transaction commits. It was also shown how the order of logged events can be kept consistent with the order of state changes. This is important when application state must be recovered from the event history (for example, during application start or failover to another node).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2708349453904691513-371508144843543204?l=krasserm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://krasserm.blogspot.com/feeds/371508144843543204/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://krasserm.blogspot.com/2011/11/building-event-sourced-web-application.html#comment-form' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/371508144843543204'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/371508144843543204'/><link rel='alternate' type='text/html' href='http://krasserm.blogspot.com/2011/11/building-event-sourced-web-application.html' title='Building an Event-Sourced Web Application - Part 1: Domain Model, Events and State'/><author><name>Martin Krasser</name><uri>http://www.blogger.com/profile/11765963540395771125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://4.bp.blogspot.com/_LrEpKPgi9gI/TI-WeznHzsI/AAAAAAAAACM/FO3hdlxwrdI/S220/Bild006a.jpg'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2708349453904691513.post-1834105871225667769</id><published>2011-02-28T07:53:00.009+01:00</published><updated>2011-06-28T10:29:15.611+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='camel'/><category scheme='http://www.blogger.com/atom/ns#' term='akka'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>Akka Producer Actors: New Features and Best Practices</title><content type='html'>In a &lt;a href="http://krasserm.blogspot.com/2011/02/akka-consumer-actors-new-features-and.html"&gt;previous post&lt;/a&gt; I wrote about new features and best practices for Akka consumer actors. In this post, I'll cover Akka producer actors. For the following examples to compile and run, you'll need the current Akka 1.1-SNAPSHOT.&lt;br /&gt;&lt;br /&gt;Again, I assume that you already have a basic familiarity with &lt;a href="http://akka.io/"&gt;Akka&lt;/a&gt;, &lt;a href="http://camel.apache.org/"&gt;Apache Camel&lt;/a&gt; and the &lt;a href="http://akka.io/docs/akka-modules/1.1/modules/camel.html"&gt;akka-camel&lt;/a&gt; integration module. If you are new to it, you may want to read the &lt;a href="http://www.manning.com/ibsen/appEsample.pdf"&gt;Akka and Camel&lt;/a&gt; chapter (free pdf) of the &lt;a href="http://www.manning.com/ibsen/"&gt;Camel in Action&lt;/a&gt; book or the &lt;a href="http://akka.io/docs/akka-modules/1.1/modules/camel.html#introduction"&gt;Introduction&lt;/a&gt; section of the official akka-camel documentation first.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Basic usage&lt;/h2&gt;&lt;br /&gt;Akka producer actors can send messages to any Camel endpoint, provided that the corresponding Camel component is on the classpath. This allows Akka actors to interact with external systems or other components over a large number of protocols and APIs.&lt;br /&gt;&lt;br /&gt;Let's start with a simple producer actor that sends all messages it receives to an external HTTP service and returns the response to the initial sender. For sending messages over HTTP we can use the Camel &lt;a href="http://camel.apache.org/jetty.html"&gt;jetty&lt;/a&gt; component which features an asynchronous HTTP client. &lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/847006.js?file=HttpProducer.scala"&gt;&lt;/script&gt;&lt;br /&gt;Concrete producer actors inherit a default implementation of &lt;code&gt;Actor.receive&lt;/code&gt; from the &lt;code&gt;Producer&lt;/code&gt; trait. For simple use cases, only an endpoint URI must be defined. Producer actors also require a started &lt;code&gt;CamelContextManager&lt;/code&gt; for working properly. A &lt;code&gt;CamelContextManager&lt;/code&gt; is started when an application starts a &lt;code&gt;CamelService&lt;/code&gt; e.g. via &lt;code&gt;CamelServiceManager.startCamelService&lt;/code&gt; or when starting the &lt;code&gt;CamelContextManager&lt;/code&gt; directly via&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/847006.js?file=CamelContextManager.scala"&gt;&lt;/script&gt;&lt;br /&gt;The latter approach is recommended when an application uses only producer actors but no consumer actors. This slightly reduces the overhead when starting actors. After starting the producer actor, clients can interact with the HTTP service via the actor API.&lt;br /&gt;kra&lt;br /&gt;&lt;script src="https://gist.github.com/847006.js?file=HttpProducerClientBangBang.scala"&gt;&lt;/script&gt;&lt;br /&gt;Here, &lt;code&gt;!!&lt;/code&gt; is used for sending the message and waiting for a response. Alternatively, one can also use &lt;code&gt;!&lt;/code&gt; together with an implicit sender reference. &lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/847006.js?file=HttpProducerClientBang.scala"&gt;&lt;/script&gt;&lt;br /&gt;In this case the &lt;code&gt;sender&lt;/code&gt; will receive an asynchronous reply from the producer actor. Before, the producer actor itself receives an asynchronous reply from the jetty endpoint. The asynchronous jetty endpoint doesn't block a thread waiting for a response and the producer actor doesn't do that either. This is important from a scalability perspective, especially for longer-running request-response cycles.&lt;br /&gt;&lt;br /&gt;By default, a producer actor initiates an in-out message exchange with its Camel endpoint i.e. it expects a response from it. If a producer actor wants to initiate an in-only message exchange then it must override the &lt;code&gt;oneway&lt;/code&gt; method to return &lt;code&gt;true&lt;/code&gt;. The following example shows a producer actor that initiates an in-only message exchange with a &lt;a href="http://camel.apache.org/jms.html"&gt;JMS&lt;/a&gt; endpoint.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/847006.js?file=JmsProducer.scala"&gt;&lt;/script&gt;&lt;br /&gt;This actor adds any message it receives to the &lt;code&gt;test&lt;/code&gt; JMS queue. By default, producer actors that are configured with &lt;code&gt;oneway = true&lt;/code&gt; don't reply. This behavior is defined in the &lt;code&gt;Producer.receiveAfterProduce&lt;/code&gt; method which is implemented as follows.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/847006.js?file=ReceiveAfterProduceDefault.scala"&gt;&lt;/script&gt;&lt;br /&gt;The &lt;code&gt;receiveAfterProduce&lt;/code&gt; method has the same signature as &lt;code&gt;Actor.receive&lt;/code&gt; and is called with the result of the message exchange with the endpoint (please note that in-only message exchanges with Camel endpoints have a result as well). The result type for successful message exchanges is &lt;a href="https://github.com/jboner/akka-modules/blob/v1.0/akka-camel/src/main/scala/akka/camel/Message.scala#L20"&gt;&lt;code&gt;Message&lt;/code&gt;&lt;/a&gt;, for failed message exchanges it is &lt;a href="https://github.com/jboner/akka-modules/blob/v1.0/akka-camel/src/main/scala/akka/camel/Message.scala#L222"&gt;&lt;code&gt;Failure&lt;/code&gt;&lt;/a&gt; (see below). &lt;br /&gt;&lt;br /&gt;Concrete producer actors can override this method. For example, the following producer actor overrides &lt;code&gt;onReceiveAfterProduce&lt;/code&gt; to reply with a constant &lt;code&gt;"done"&lt;/code&gt; message. &lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/847006.js?file=JmsReplyingProducer.scala"&gt;&lt;/script&gt;&lt;br /&gt;The result of the message exchange with the JMS endpoint is ignored (&lt;code&gt;case _&lt;/code&gt;).&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Failures&lt;/h2&gt;&lt;br /&gt;Messages exchanges with a Camel endpoint can fail. In this case, &lt;code&gt;onReceiveAfterProduce&lt;/code&gt; is called with a &lt;/code&gt;Failure&lt;/code&gt; message containing the cause of the failure (a &lt;code&gt;Throwable&lt;/code&gt;). Let's extend the &lt;code&gt;HttpProducer&lt;/code&gt; usage example to deal with failure responses.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/847006.js?file=HttpProducerClientFailure.scala"&gt;&lt;/script&gt;&lt;br /&gt;In addition to a failure cause, a &lt;code&gt;Failure&lt;/code&gt; message can also contain endpoint-specific headers with failure details such as the HTTP response code, for example. When using &lt;code&gt;!&lt;/code&gt; instead of &lt;code&gt;!!&lt;/code&gt;, together with an implicit sender reference (as shown in the previous section), that sender will then receive the &lt;code&gt;Failure&lt;/code&gt; message asynchronously. The &lt;code&gt;JmsReplyingProducer&lt;/code&gt; example can also be extended to return more meaningful responses: a &lt;code&gt;"done"&lt;/code&gt; message only on success and an error message on failure.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/847006.js?file=JmsReplyingProducerFailure.scala"&gt;&lt;/script&gt;&lt;br /&gt;Failed message exchanges never cause the producer actor to throw an exception during execution of &lt;code&gt;receive&lt;/code&gt;. Should &lt;code&gt;Producer&lt;/code&gt; implementations want to throw an exception on failure (for whatever reason) they can do so in &lt;code&gt;onReceiveAfterProduce&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/847006.js?file=SomeProducer.scala"&gt;&lt;/script&gt;&lt;br /&gt;In this case failure handling should be done in combination with a supervisor (see below). &lt;br /&gt;&lt;br /&gt;Let's look at another example. What if we want&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/847012.js?file=SomeProducerClient.scala"&gt;&lt;/script&gt;&lt;br /&gt;to throw an exception on failure (instead of returning a &lt;code&gt;Failure&lt;/code&gt; message) but to respond with a normal &lt;code&gt;Message&lt;/code&gt; on success? In this case, we need to use &lt;code&gt;self.senderFuture&lt;/code&gt; inside &lt;code&gt;onReceiveAfterProduce&lt;/code&gt; and complete it with an exception. &lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/847012.js?file=SomeProducerException.scala"&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Forwarding results&lt;/h2&gt;&lt;br /&gt;Another option to deal with message exchange results inside &lt;code&gt;onReceiveAfterProduce&lt;/code&gt; is to forward them to another actor. Forwarding a message also forwards the initial sender reference. This allows the receiving actor to reply to the initial sender. &lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/847012.js?file=JmsForwardingProducer.scala"&gt;&lt;/script&gt;&lt;br /&gt;With producer actors that forward message exchange results to other actors (incl. other producer actors) one can build actor-based message processing pipelines that integrate external systems. In combination with consumer actors, this could be extended towards a scalable and distributed enterprise service bus (ESB) based on Akka actors ... but this is a topic for another blog post.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Correlation identifiers&lt;/h2&gt;&lt;br /&gt;The Producer trait also supports correlation identifiers. This allows clients to correlate request messages with asynchronous response messages. A correlation identifier is a message header that can be set by clients. The following example uses the correlation identifier (or message exchange identifier) &lt;code&gt;123&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/847012.js?file=CorrelationIdentifier.scala"&gt;&lt;/script&gt;&lt;br /&gt;An asynchronous response (&lt;code&gt;Message&lt;/code&gt; or &lt;code&gt;Failure&lt;/code&gt;) from &lt;code&gt;httpProducer&lt;/code&gt; will contain that correlation identifier as well.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Fault-tolerance&lt;/h2&gt;&lt;br /&gt;A failed message exchange by default does not cause a producer actor to throw an exception. However, concrete producer actors may decide to throw an exception inside &lt;code&gt;onReceiveAfterProduce&lt;/code&gt;, for example, or there can be a system-level Camel problem that causes a runtime exception. An application that wants to handle these exceptions should supervise its producer actors. &lt;br /&gt;&lt;br /&gt;The following example shows how to implement a producer actor that replies to the initial sender with a &lt;code&gt;Failure&lt;/code&gt; message when it is restarted or stopped by a supervisor.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/847012.js?file=SupervisedProducerNew.scala"&gt;&lt;/script&gt;&lt;br /&gt;To handle restart callbacks, producer actors must override the &lt;code&gt;preRestartProducer&lt;/code&gt; method instead of &lt;code&gt;preRestart&lt;/code&gt;. The &lt;code&gt;preRestart&lt;/code&gt; method is implemented by the &lt;code&gt;Producer&lt;/code&gt; trait and does additional resource de-allocation work after calling &lt;code&gt;preRestartProducer&lt;/code&gt;. More information about replies within &lt;code&gt;preRestart&lt;/code&gt; and &lt;code&gt;postStop&lt;/code&gt; can be found in my &lt;a href="http://krasserm.blogspot.com/2011/02/akka-consumer-actors-new-features-and.html"&gt;previous blog post&lt;/a&gt; about consumer actors.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2708349453904691513-1834105871225667769?l=krasserm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://krasserm.blogspot.com/feeds/1834105871225667769/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://krasserm.blogspot.com/2011/02/akka-producer-actor-new-features-and.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/1834105871225667769'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/1834105871225667769'/><link rel='alternate' type='text/html' href='http://krasserm.blogspot.com/2011/02/akka-producer-actor-new-features-and.html' title='Akka Producer Actors: New Features and Best Practices'/><author><name>Martin Krasser</name><uri>http://www.blogger.com/profile/11765963540395771125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://4.bp.blogspot.com/_LrEpKPgi9gI/TI-WeznHzsI/AAAAAAAAACM/FO3hdlxwrdI/S220/Bild006a.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2708349453904691513.post-3108150540378872567</id><published>2011-02-17T13:58:00.028+01:00</published><updated>2011-07-06T20:54:30.121+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='camel'/><category scheme='http://www.blogger.com/atom/ns#' term='akka'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>Akka Consumer Actors: New Features and Best Practices</title><content type='html'>In this blog post I want to give some guidance how to implement consumer actors with the &lt;a href="http://akka.io/docs/akka-modules/1.1/modules/camel.html"&gt;akka-camel&lt;/a&gt; module. Besides basic usage scenarios, I will also explain how to make consumer actors fault-tolerant, redeliver messages on failure, deal with bounded mailboxes etc. The code examples shown below require the current Akka 1.1-SNAPSHOT to compile and run.&lt;br /&gt;&lt;br /&gt;In the following, I assume t&lt;span style="font-size:100%;"&gt;hat&lt;/span&gt; you already have a basic familiarity with &lt;a href="http://akka.io/"&gt;Akka&lt;/a&gt;, &lt;a href="http://camel.apache.org/"&gt;Apache Camel&lt;/a&gt; and the akka-camel integration module. If you are new to it, you may want to read the &lt;a href="http://www.manning.com/ibsen/appEsample.pdf"&gt;Akka and Camel&lt;/a&gt; chapter (free pdf) of the &lt;a href="http://www.manning.com/ibsen/"&gt;Camel in Action&lt;/a&gt; book or the &lt;a href="http://akka.io/docs/akka-modules/1.1/modules/camel.html#introduction"&gt;Introduction&lt;/a&gt; section of the official akka-camel documentation first.&lt;p&gt;&lt;h2&gt;Basic usage&lt;/h2&gt;Akka consumer actors can receive messages from any Camel endpoint, provided that the corresponding Camel component is on the classpath. This allows clients to interact with Akka actors over a large number of protocols and APIs.&lt;br /&gt;&lt;br /&gt;Camel endpoints either initiate in-only (one-way) message exchanges with consumer actors or in-out (two-way) message exchanges. Replies from consumer actors are mandatory for in-out message exchanges but optional for in-only message exchanges. For replying to a Camel endpoint, the consumer actor uses the very same interface as for replying to any other sender (e.g. to another actor). Examples are &lt;code&gt;self.reply&lt;/code&gt; or &lt;code&gt;self.reply_?&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Let's start by defining a simple consumer actor that accepts messages via tcp on port 6200 and replies to the tcp client (tcp support is given by Camel's &lt;a href="http://camel.apache.org/mina.html"&gt;mina&lt;/a&gt; component).&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/835076.js?file=InOutConsumer.scala"&gt;&lt;/script&gt;&lt;br /&gt;For consumer actors to work, applications need to start a &lt;code&gt;CamelService&lt;/code&gt; which is managed by the &lt;code&gt;CamelServiceManager&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/835076.js?file=StartCamelService.scala"&gt;&lt;/script&gt;&lt;br /&gt;When starting a consumer actor, the endpoint defined for that actor will be activated asynchronously by the &lt;code&gt;CamelService&lt;/code&gt;. If your application wants to wait for consumer endpoints to be finally activated you can do so with the &lt;code&gt;awaitEndpointActivation&lt;/code&gt; method (which is especially useful for testing).&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/835076.js?file=InOutConsumerClient.scala"&gt;&lt;/script&gt;&lt;br /&gt;For sending a test message to the consumer actor, the above code uses a Camel &lt;code&gt;ProducerTemplate&lt;/code&gt; which can be obtained from the &lt;code&gt;CamelContextManager&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;If Camel endpoints, such as the &lt;a href="http://camel.apache.org/file2.html"&gt;file&lt;/a&gt; endpoint, create in-only message exchanges then consumer actors need not reply, by default. The message exchange is completed once the input message has been added to the consumer actor's mailbox.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/835076.js?file=InOnlyConsumer.scala"&gt;&lt;/script&gt;&lt;br /&gt;When placing a file into the &lt;code&gt;data/input&lt;/code&gt; directory, the Camel file endpoint will pick up that file and send its content as message to the consumer actor. Once the message is in the actor's mailbox, the file endpoint will delete the corresponding file (see &lt;code&gt;delete=true&lt;/code&gt; in the endpoint URI).&lt;br /&gt;&lt;br /&gt;If you want to let the consumer actor decide when the file should be deleted, then you'll need to turn auto-acknowledgements off as shown in the following example (&lt;code&gt;autoack = false&lt;/code&gt;). In this case the consumer actor must reply with a special &lt;code&gt;Ack&lt;/code&gt; message when message processing is done. This asynchronous reply finally causes the file endpoint to delete the consumed file.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/835076.js?file=InOnlyAckConsumer.scala"&gt;&lt;/script&gt;&lt;br /&gt;Turning auto-acknowledgements on and off is only relevant for in-only message exchanges because, for in-out message exchanges, consumer actors need to reply in any case with an (application-specific) message. Consumer actors may also reply with a &lt;code&gt;Failure&lt;/code&gt; message to indicate a processing failure. &lt;code&gt;Failure&lt;/code&gt; replies can be made for both in-only and in-out message exchanges. A &lt;code&gt;Failure&lt;/code&gt; reply can be done inside &lt;code&gt;receive&lt;/code&gt; method but there are better ways as shown in the next sections.&lt;p&gt;&lt;h2&gt;Fault-tolerance and message redelivery&lt;/h2&gt;Message processing inside receive may throw exceptions which usually requires a failure response to Camel (i.e. to the consumer endpoint). This is done with a &lt;code&gt;Failure&lt;/code&gt; message that contains the failure reason (an instance of &lt;code&gt;Throwable&lt;/code&gt;). Instead of catching and handling the exception inside &lt;code&gt;receive&lt;/code&gt;, consumer actors should be part of supervisor hierarchies and send failure responses from within restart callback methods. Here's an example of a fault-tolerant file consumer.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/847012.js?file=SupervisedFileConsumer.scala"&gt;&lt;/script&gt;&lt;br /&gt;The above file consumer overrides the preRestart and postStop callback methods to send reply messages to Camel. A reply within preRestart and postStop is possible after receive has thrown an exception (new feature since Akka 1.1). When receive returns normally it is expected that any necessary reply has already been done within receive.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;If the lifecycle of the &lt;code&gt;SupervisedFileConsumer&lt;/code&gt; is configured to be &lt;code&gt;PERMANENT&lt;/code&gt;, a supervisor will restart the consumer upon failure with a call to &lt;code&gt;preRestart&lt;/code&gt;. Within &lt;code&gt;preRestart&lt;/code&gt; a &lt;code&gt;Failure&lt;/code&gt; reply is sent which causes the file endpoint to redeliver the content of the consumed file and the consumer actor can try to process it again. Should the processing succeed in a second attempt, an &lt;code&gt;Ack&lt;/code&gt; is sent within &lt;code&gt;receive&lt;/code&gt;. A reply within &lt;code&gt;preRestart&lt;/code&gt; must be a safe reply via &lt;code&gt;self.reply_?&lt;/code&gt; because an unsafe &lt;code&gt;self.reply&lt;/code&gt; will throw an exception when the consumer is restarted without having failed. This can be the case in context of all-for-one restart strategies.&lt;/li&gt;&lt;li&gt;If the lifecycle of the &lt;code&gt;SupervisedFileConsumer&lt;/code&gt; is configured to be &lt;code&gt;TEMPORARY&lt;/code&gt;, a supervisor will shut down the consumer upon failure with a call to &lt;code&gt;postStop&lt;/code&gt;. Within &lt;code&gt;postStop&lt;/code&gt; an &lt;code&gt;Ack&lt;/code&gt; is sent which causes the file endpoint to delete the file. One can, of course, choose to reply with a &lt;code&gt;Failure&lt;/code&gt; here, so that files that couldn't be processed successfully are kept in the input directory. A reply within &lt;code&gt;postStop&lt;/code&gt; must be a safe reply via &lt;code&gt;self.reply_?&lt;/code&gt; because an unsafe &lt;code&gt;self.reply&lt;/code&gt; will throw an exception when the consumer has been stopped by the application (and not by a supervisor) after successful execution of &lt;code&gt;receive&lt;/code&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Another frequently discussed consumer actor example is a fault-tolerant JMS consumer. A JMS consumer actor should acknowledge a message receipt upon successful message processing and trigger a message redelivery on failure. This is exactly the same pattern as described for the &lt;code&gt;SupervisedFileConsumer&lt;/code&gt; above. You just need to change the file endpoint URI to a &lt;a href="http://camel.apache.org/jms.html"&gt;jms&lt;/a&gt; or &lt;a href="http://camel.apache.org/activemq.html"&gt;activemq&lt;/a&gt; endpoint URI and you're done (of course, you additionally need to configure the JMS connection with a redelivery policy and, optionally, use transacted queues. An explanation how to do this would however exceed the scope of this blog post).&lt;p&gt;&lt;h2&gt;Simplifications and tradeoffs with &lt;code&gt;blocking=true&lt;/code&gt;&lt;/h2&gt;In all the examples so far the internally created Camel routes use the &lt;code&gt;!&lt;/code&gt; (bang) operator to send the input message to the consumer actor. This means that the Camel route does not block a thread waiting for a response. It's an asynchronous reply will cause the Camel route to resume processing. That's also the reason why any exception thrown by receive isn't reported back to Camel directly but must be done explicitly with a &lt;code&gt;Failure&lt;/code&gt; response.&lt;br /&gt;&lt;br /&gt;If you want that exceptions thrown by receive are reported back to Camel directly (i.e. without sending &lt;code&gt;Failure&lt;/code&gt; responses) then you'll need to set &lt;code&gt;blocking = true&lt;/code&gt; for the consumer actor. This causes the Camel route to send the input message with the &lt;code&gt;!!&lt;/code&gt; (bangbang) operator and to wait for a response. However, this will block a thread until the consumer sends a response or throws an exception within &lt;code&gt;receive&lt;/code&gt;. The advantage of this approach is that error handling is strongly simplified in this case but scalability will likely decrease.&lt;br /&gt;&lt;br /&gt;Here's an example of a consumer actor that uses the simplified approach to error handling. Any exception thrown by receive will still cause the file endpoint to redeliver the message but a thread will be blocked by Camel during the execution of receive.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/835076.js?file=FileConsumer.scala"&gt;&lt;/script&gt;&lt;br /&gt;No supervisor is needed here. It depends on the non-functional requirements of your application whether to go for this simple but blocking approach or to use a more scalable, non-blocking approach in combination with a supervisor.&lt;p&gt;&lt;h2&gt;Bounded mailboxes and error handling with custom Camel routes&lt;/h2&gt;For consumer actors that require a significant amount of time for processing a single message, it can make sense to install a bounded mailbox. A bounded mailbox throws an exception if its capacity is reached and the Camel route tries to add additional messages to the mailbox. Here's an example of a file consumer actor that uses a bounded mailbox with a capacity of 5. Processing is artificially delayed by 1 second using a &lt;code&gt;Thread.sleep&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/835076.js?file=BoundedMailboxFileConsumer.scala"&gt;&lt;/script&gt;&lt;br /&gt;When, let's say, 10 files are put into the &lt;code&gt;data/input&lt;/code&gt; directory, they will be picked up by the file endpoint and added to the actor's mailbox. The capacity of the mailbox will be reached soon because the file endpoint can send messages much faster than the consumer actor can process it. Exceptions thrown by the mailbox are directly reported to the Camel route which causes the file consumer to redeliver messages until they can be added to the mailbox. The same applies to JMS and other endpoints that support redelivery.&lt;br /&gt;&lt;br /&gt;When dealing with endpoints that do not support redelivery, one needs to customize the Camel route to the consumer actor with a special error handler that does the redelivery. This is shown for a consumer actor that consumes messages from a &lt;a href="http://camel.apache.org/direct.html"&gt;direct&lt;/a&gt; endpoint.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/835076.js?file=BoundedMailboxDirectConsumer.scala"&gt;&lt;/script&gt;&lt;br /&gt;Here we use &lt;code&gt;onRouteDefinition&lt;/code&gt; to define how the Camel route should be customized during its creation. In this example, an error handler is defined that attempts max. 3 redeliveries with a delay of 1000 ms. For details refer to the &lt;a href="http://akka.io/docs/akka-modules/1.1/modules/camel.html#intercepting-route-construction"&gt;intercepting route construction&lt;/a&gt; section in the akka-camel documentation. When using a producer template to send messages to this endpoint, some of them will be added to the mailbox on first attempt, some of them after a second attempt triggered by the error handler.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/835076.js?file=SendTenMessages.scala"&gt;&lt;/script&gt;&lt;br /&gt;The examples presented in this post cover many of the consumer-actor-related questions and topics that have been asked and discussed on the &lt;a href="http://groups.google.com/group/akka-user"&gt;akka-user&lt;/a&gt; mailing list. In another post I plan to cover best practices for implementing Akka producer actors.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2708349453904691513-3108150540378872567?l=krasserm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://krasserm.blogspot.com/feeds/3108150540378872567/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://krasserm.blogspot.com/2011/02/akka-consumer-actors-new-features-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/3108150540378872567'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/3108150540378872567'/><link rel='alternate' type='text/html' href='http://krasserm.blogspot.com/2011/02/akka-consumer-actors-new-features-and.html' title='Akka Consumer Actors: New Features and Best Practices'/><author><name>Martin Krasser</name><uri>http://www.blogger.com/profile/11765963540395771125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://4.bp.blogspot.com/_LrEpKPgi9gI/TI-WeznHzsI/AAAAAAAAACM/FO3hdlxwrdI/S220/Bild006a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2708349453904691513.post-6296294200685751636</id><published>2010-08-30T10:28:00.016+02:00</published><updated>2011-06-28T10:48:59.894+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='camel'/><category scheme='http://www.blogger.com/atom/ns#' term='akka'/><category scheme='http://www.blogger.com/atom/ns#' term='actor model'/><title type='text'>Akka's grown-up hump</title><content type='html'>It's quite some time ago when I &lt;a href="http://krasserm.blogspot.com/2010/04/akka-features-for-application.html"&gt;last wrote&lt;/a&gt; about &lt;a href="http://akka.io/docs/akka-modules/1.1/modules/camel.html"&gt;Akka's Camel integration&lt;/a&gt;. An initial version of the akka-camel module was released with Akka 0.7. Meanwhile Akka 0.10 is out with an akka-camel module containing numerous new features and enhancements. Some of them will be briefly described in this blog post.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;Java API&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The akka-camel module now offers a Java API in addition to the Scala API. Both APIs are fully covered in the &lt;a href="http://akka.io/docs/akka-modules/1.1/modules/camel.html"&gt;online documentation&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Support for typed consumer actors&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Methods of &lt;a href="http://akka.io/docs/akka/1.1/java/typed-actors.html"&gt;typed actors&lt;/a&gt; can be published at Camel endpoints by annotating them with &lt;span style="font-family:courier new;"&gt;@consume&lt;/span&gt;. The annotation value defines the endpoint URI. Here's an example of a &lt;a href="http://akka.io/docs/akka-modules/1.1/modules/camel.html#typed-actors"&gt;typed consumer&lt;/a&gt; actor in Java.&lt;br /&gt;&lt;pre class="brush:java"&gt;import org.apache.camel.Body;&lt;br /&gt;import org.apache.camel.Header;&lt;br /&gt;import se.scalablesolutions.akka.actor.TypedActor;&lt;br /&gt;import se.scalablesolutions.akka.camel.consume;&lt;br /&gt;&lt;br /&gt;public interface MyTypedConsumer {&lt;br /&gt;   @consume("file:data/foo")&lt;br /&gt;   public void foo(String body);&lt;br /&gt;&lt;br /&gt;   @consume("jetty:http://localhost:8877/camel/bar")&lt;br /&gt;   public String bar(@Body String body, @Header("Content-Type") String contentType);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class MyTypedConsumerImpl extends TypedActor implements MyTypedConsumer {&lt;br /&gt;   public void foo(String body) {&lt;br /&gt;       System.out.println(String.format("Received message: ", body));&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public String bar(String body, String contentType) {&lt;br /&gt;       return String.format("body=%s Content-Type header=%s", body, conctentType);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;When creating an instance of the typed actor with&lt;br /&gt;&lt;pre class="brush:java"&gt;import se.scalablesolutions.akka.actor.TypedActor;&lt;br /&gt;&lt;br /&gt;// Create typed actor and activate endpoints&lt;br /&gt;MyTypedConsumer consumer = TypedActor.newInstance(&lt;br /&gt;   MyTypedConsumer.class, MyTypedConumerImpl.class);&lt;br /&gt;&lt;/pre&gt;then the actor's &lt;span style="font-family:courier new;"&gt;foo&lt;/span&gt; method can be invoked by dropping a file into the &lt;span style="font-family:courier new;"&gt;data/foo&lt;/span&gt; directory. The file content is passed via the &lt;span style="font-family:courier new;"&gt;body&lt;/span&gt; parameter. The &lt;span style="font-family:courier new;"&gt;bar&lt;/span&gt; method can be invoked by POSTing a message to &lt;span style="font-family:courier new;"&gt;http://localhost:8877/camel/bar&lt;/span&gt;. The HTTP message body is passed via the &lt;span style="font-family:courier new;"&gt;body&lt;/span&gt; parameter and the &lt;span style="font-family:courier new;"&gt;Content-Type&lt;/span&gt; header via the &lt;span style="font-family:courier new;"&gt;contentType&lt;/span&gt; parameter. For parameter binding, Camel's &lt;a href="http://camel.apache.org/parameter-binding-annotations.html"&gt;parameter binding annotations&lt;/a&gt; are used.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Endpoint lifecycle&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Consumer actor endpoints are &lt;a href="http://akka.io/docs/akka-modules/1.1/modules/camel.html#consumer-publishing"&gt;activated&lt;/a&gt; when the actor is started and &lt;a href="http://akka.io/docs/akka-modules/1.1/modules/camel.html#consumer-un-publishing"&gt;de-activated&lt;/a&gt; when the actor is stopped. This is the case for both typed and untyped actors. An actor can either be stopped explicitly by an application or by a supervisor.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Fault tolerance&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When a consumer actor isn't stopped but &lt;a href="http://akka.io/docs/akka-modules/1.1/modules/camel.html#fault-tolerance"&gt;restarted&lt;/a&gt; by a supervisor, the actor's endpoint remains active. Communication partners can continue to exchange messages with the endpoint during the restart phase but message processing will occur only after restart completes. For in-out message exchanges, response times may therefore increase. Communication partners that initiate in-only message exchanges with the endpoint won't see any difference.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Producer actors&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Actors that want to &lt;a href="http://akka.io/docs/akka-modules/1.1/modules/camel.html#produce-messages"&gt;produce&lt;/a&gt; messages to endpoints either need to mixin the &lt;span style="font-family:courier new;"&gt;Producer&lt;/span&gt; trait (Scala API) or extend the abstract &lt;span style="font-family:courier new;"&gt;UntypedProducerActor&lt;/span&gt; class (Java API). Although the &lt;span style="font-family:courier new;"&gt;Producer&lt;/span&gt; trait was already available in the initial version of akka-camel, many enhancements have been made since then. Most of them are internal enhancements such as performance improvements and support for asynchronous routing. Also, extensions to the API have been made to support&lt;br /&gt;&lt;ul&gt;&lt;li&gt;pre-processing of messages before they are sent to an endpoint and &lt;/li&gt;&lt;li&gt;post-processing of messages after they have been received as response from an endpoint.&lt;/li&gt;&lt;/ul&gt;For example, instead of replying to the original sender (default behavior) a producer actor could do a custom post-processing e.g. by forwarding the response to another actor (together with the initial sender reference)&lt;br /&gt;&lt;pre class="brush:scala"&gt;import se.scalablesolutions.akka.actor.Actor&lt;br /&gt;import se.scalablesolutions.akka.camel.Producer&lt;br /&gt;&lt;br /&gt;class MyProducer(target: ActorRef) extends Actor with Producer {&lt;br /&gt; def endpointUri = "http://example.org/some/external/service"&lt;br /&gt;&lt;br /&gt; override protected def receiveAfterProduce = {&lt;br /&gt;   // do not reply to initial sender but&lt;br /&gt;   // forward result to a target actor&lt;br /&gt;   case msg =&gt; target forward msg&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Forwarding results to other actors makes it easier to create actor-based message processing pipelines that make use of external services. &lt;a http://akka.io/docs/akka-modules/1.1/modules/camel.html#examples"&gt;Examples&lt;/a&gt; are given in the akka-camel documentation.&lt;br /&gt;&lt;br /&gt;Typed actors need to use Camel's &lt;span style="font-family:courier new;"&gt;ProducerTemplate&lt;/span&gt; directly to produce messages to Camel endpoints. A managed instance of a &lt;span style="font-family:courier new;"&gt;ProducerTemplate&lt;/span&gt; can be obtained via &lt;span style="font-family:courier new;"&gt;CamelContextManager.template&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Asynchronous routing&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Since Akka 0.10, Camel's &lt;a href="http://akka.io/docs/akka-modules/1.1/modules/camel.html#examples"&gt;asynchronous routing engine&lt;/a&gt; is &lt;a href="http://doc.akkasource.org/Camel#async-routing"&gt;fully supported&lt;/a&gt;: in-out and in-only messages exchanges between endpoints and actors are designed to be asynchronous. This is the case for both, consumer and producer actors.&lt;br /&gt;&lt;br /&gt;This is especially important for actors that participate in long-running request-reply interactions with external services. Threads are no longer blocked for the full duration of an in-out message exchange and are available for doing other work. There's also an &lt;a href="http://akka.io/docs/akka-modules/1.1/modules/camel.html#examples"&gt;asynchronous routing example &lt;/a&gt;described in the online documentation.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Routes to actors&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Typed an untyped actors can also be &lt;a href="http://akka.io/docs/akka-modules/1.1/modules/camel.html#custom-camel-routes"&gt;accessed from Camel routes&lt;/a&gt; directly, using Akka's &lt;span style="font-family:courier new;"&gt;TypedActorComponent&lt;/span&gt; and &lt;span style="font-family:courier new;"&gt;ActorComponent&lt;/span&gt;, respectively. These are Camel components supporting &lt;span style="font-family:courier new;"&gt;typed-actor&lt;/span&gt; and and &lt;span style="font-family:courier new;"&gt;actor&lt;/span&gt; endpoint URIs in route definitions. For example,&lt;br /&gt;&lt;pre class="brush:java"&gt;from("seda:test").to("actor:uuid:12345678");&lt;br /&gt;&lt;/pre&gt;routes a message from a &lt;a href="http://camel.apache.org/seda.html"&gt;SEDA&lt;/a&gt; queue to an untyped actor with &lt;span style="font-family:courier new;"&gt;uuid&lt;/span&gt; 12345678. The &lt;span style="font-family:courier new;"&gt;actor&lt;/span&gt; endpoint looks up the actor in Akka's actor registry.&lt;br /&gt;&lt;br /&gt;The &lt;span style="font-family:courier new;"&gt;TypedActorComponent&lt;/span&gt; is an extension of Camel's &lt;a href="http://camel.apache.org/bean.html"&gt;bean&lt;/a&gt; component where method invocations follow the semantics of the &lt;a href="http://en.wikipedia.org/wiki/Actor_model"&gt;actor model&lt;/a&gt;. Here is an example route from a &lt;a href="http://camel.apache.org/direct.html"&gt;direct&lt;/a&gt; endpoint to the &lt;span style="font-family:courier new;"&gt;foo&lt;/span&gt; method of a typed actor.&lt;br /&gt;&lt;pre class="brush:java"&gt;from("direct:test").to("typed-actor:sample?method=foo");&lt;br /&gt;&lt;/pre&gt;The typed actor is registered under the name &lt;span style="font-style: italic;"&gt;sample&lt;/span&gt; in the Camel registry. For more details how to add typed actors to the Camel registry, follow &lt;a href="http://akka.io/docs/akka-modules/1.1/modules/camel.html#access-to-typed-actors"&gt;this link&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;CamelService&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Prerequisite for endpoints being activated when starting consumer actors is a &lt;a href="http://akka.io/docs/akka-modules/1.1/modules/camel.html#consumers-and-the-camelservice"&gt;running &lt;span style="font-family:courier new;"&gt;CamelService&lt;/span&gt;&lt;/a&gt;. When starting Akka in Kernel mode or using the Akka &lt;a style="font-family: courier new;" href="http://akka.io/docs/akka/1.1/scala/http.html"&gt;Initializer&lt;/a&gt; in a web application, a &lt;span style="font-family:courier new;"&gt;CamelService&lt;/span&gt; is started automatically. In all other cases a &lt;span style="font-family:courier new;"&gt;CamelService&lt;/span&gt; must be started by the application itself. This can be done either programmatically with&lt;br /&gt;&lt;pre class="brush:scala"&gt;import se.scalablesolutions.akka.camel.CamelServiceManager._&lt;br /&gt;&lt;br /&gt;startCamelService&lt;br /&gt;&lt;/pre&gt;or declaratively in a Spring XML configuration file.&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;beans xmlns="http://www.springframework.org/schema/beans"&lt;br /&gt; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt; xmlns:akka="http://www.akkasource.org/schema/akka"&lt;br /&gt; xmlns:camel="http://camel.apache.org/schema/spring"&lt;br /&gt; xsi:schemaLocation="&lt;br /&gt;http://www.springframework.org/schema/beans&lt;br /&gt;http://www.springframework.org/schema/beans/spring-beans-2.5.xsd&lt;br /&gt;http://www.akkasource.org/schema/akka&lt;br /&gt;http://scalablesolutions.se/akka/akka-0.10.xsd&lt;br /&gt;http://camel.apache.org/schema/spring&lt;br /&gt;http://camel.apache.org/schema/spring/camel-spring.xsd"&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;!– A custom CamelContext (SpringCamelContext) –&amp;gt;&lt;br /&gt; &amp;lt;camel:camelContext id="camelContext"&amp;gt;&lt;br /&gt;   &amp;lt;!– … –&amp;gt;&lt;br /&gt; &amp;lt;/camel:camelContext&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;!– Create a CamelService using a custom CamelContext –&amp;gt;&lt;br /&gt; &amp;lt;akka:camel-service&amp;gt;&lt;br /&gt;   &amp;lt;akka:camel-context ref="camelContext" /&amp;gt;&lt;br /&gt; &amp;lt;/akka:camel-service&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/beans&amp;gt;&lt;/pre&gt;Usage of the &lt;camel-service&gt; element requires the &lt;a href="http://akka.io/docs/akka-modules/1.1/modules/spring.html"&gt;akka-spring&lt;/a&gt; jar on the classpath. This example also shows how the Spring-managed &lt;span style="font-family:courier new;"&gt;CamelService&lt;/span&gt; is configured with a custom &lt;span style="font-family:courier new;"&gt;CamelContext&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;A running &lt;span style="font-family:courier new;"&gt;CamelService&lt;/span&gt; can be stopped either by closing the application context or by calling the &lt;span style="font-family:courier new;"&gt;CamelServiceManager.stopCamelService&lt;/span&gt; method.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Outlook&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The next Akka release will be Akka 1.0 (targeted for late fall) and akka-camel development will mainly focus on API stabilization. If you'd like to have some additional features in the next Akka release, want to give feedback or ask some questions, please contact the Akka community at the &lt;a href="http://groups.google.com/group/akka-user"&gt;akka-user&lt;/a&gt; mailing list.&lt;br /&gt;&lt;br /&gt;&lt;/camel-service&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2708349453904691513-6296294200685751636?l=krasserm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://krasserm.blogspot.com/feeds/6296294200685751636/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://krasserm.blogspot.com/2010/08/akkas-grown-up-hump.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/6296294200685751636'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/6296294200685751636'/><link rel='alternate' type='text/html' href='http://krasserm.blogspot.com/2010/08/akkas-grown-up-hump.html' title='Akka&apos;s grown-up hump'/><author><name>Martin Krasser</name><uri>http://www.blogger.com/profile/11765963540395771125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://4.bp.blogspot.com/_LrEpKPgi9gI/TI-WeznHzsI/AAAAAAAAACM/FO3hdlxwrdI/S220/Bild006a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2708349453904691513.post-8004463190423350163</id><published>2010-04-03T10:59:00.009+02:00</published><updated>2011-06-28T10:53:13.880+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='integration'/><category scheme='http://www.blogger.com/atom/ns#' term='open ehealth'/><category scheme='http://www.blogger.com/atom/ns#' term='IPF'/><category scheme='http://www.blogger.com/atom/ns#' term='ihe'/><category scheme='http://www.blogger.com/atom/ns#' term='camel'/><category scheme='http://www.blogger.com/atom/ns#' term='akka'/><category scheme='http://www.blogger.com/atom/ns#' term='scalability'/><category scheme='http://www.blogger.com/atom/ns#' term='ehealth'/><category scheme='http://www.blogger.com/atom/ns#' term='actor model'/><title type='text'>Akka features for application integration</title><content type='html'>&lt;a href="http://akka.io/"&gt;Akka&lt;/a&gt; is a platform for event-driven, scalable and fault-tolerant architectures on the JVM. It is mainly written in Scala. One of its core features is support for the &lt;a href="http://en.wikipedia.org/wiki/Actor_model"&gt;actor model&lt;/a&gt; that provides a higher level of abstraction for writing concurrent and distributed systems.&lt;br /&gt;&lt;br /&gt;Since version 0.7, Akka offers a new feature that let actors send and receive messages over a great variety of protocols and APIs. In addition to the native Scala actor API, actors can now exchange messages with other systems over large number of protcols and APIs such as HTTP, SOAP, TCP, FTP, SMTP or JMS, to mention a few. At the moment, approximately 80 protocols and APIs are supported. This new feature is provided by Akka's &lt;a href="http://akka.io/docs/akka-modules/1.1/modules/camel.html"&gt;Camel module&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;At the core of this new feature is &lt;a href="http://camel.apache.org/"&gt;Apache Camel&lt;/a&gt;, IMHO the most powerful and feature-rich integration framework currently available for the JVM. For an introduction to Apache Camel you may want to read &lt;a href="http://architects.dzone.com/articles/apache-camel-integration"&gt;this article&lt;/a&gt;. Camel comes with a large number of &lt;a href="http://camel.apache.org/components.html"&gt;components&lt;/a&gt; that provide bindings to different protocols and APIs. Usage of Camel's integration components in Akka is essentially a one-liner. Here's an example.&lt;br /&gt;&lt;pre class="brush:scala"&gt;&lt;br /&gt;import se.scalablesolutions.akka.actor.Actor&lt;br /&gt;import se.scalablesolutions.akka.actor.Actor._&lt;br /&gt;import se.scalablesolutions.akka.camel.{Message, Consumer}&lt;br /&gt;&lt;br /&gt;class MyActor extends Actor with Consumer {&lt;br /&gt;  def endpointUri =&lt;br /&gt;    "mina:tcp://localhost:6200?textline=true"&lt;br /&gt;&lt;br /&gt;  def receive = {&lt;br /&gt;    case msg: Message =&gt; { /* ... */}&lt;br /&gt;    case _            =&gt; { /* ... */}&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;// start and expose actor via tcp&lt;br /&gt;val myActor = actorOf[MyActor].start&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The above example exposes an actor over a tcp endpoint on port 6200 via Apache Camel's &lt;a href="http://camel.apache.org/mina.html"&gt;Mina component&lt;/a&gt;. The &lt;span style="font-family:courier new;"&gt;endpointUri&lt;/span&gt; is an abstract method declared in the &lt;span style="font-family:courier new;"&gt;Consumer&lt;/span&gt; trait. After starting the actor, tcp clients can immediately send messages to and receive responses from that actor. If the message exchange should go over HTTP (via Camel's &lt;a href="http://camel.apache.org/jetty.html"&gt;Jetty component&lt;/a&gt;), only the actor's &lt;span style="font-family:courier new;"&gt;endpointUri&lt;/span&gt; must be redefined.&lt;br /&gt;&lt;pre class="brush:scala"&gt;&lt;br /&gt;class MyActor extends Actor with Consumer {&lt;br /&gt;  def endpointUri =&lt;br /&gt;    "jetty:http://localhost:8877/example"&lt;br /&gt;&lt;br /&gt;  def receive = {&lt;br /&gt;    case msg: Message =&gt; { /* ... */}&lt;br /&gt;    case _            =&gt; { /* ... */}&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Actors can also trigger message exchanges with external systems i.e. produce to Camel endpoints.&lt;br /&gt;&lt;pre class="brush:scala"&gt;&lt;br /&gt;import se.scalablesolutions.akka.actor.Actor&lt;br /&gt;import se.scalablesolutions.akka.camel.Producer&lt;br /&gt;&lt;br /&gt;class MyActor extends Actor with Producer {&lt;br /&gt;  def endpointUri = "jms:queue:example"&lt;br /&gt;  protected def receive = produce&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In the above example, any message sent to this actor will be added (produced) to the &lt;span style="font-family:courier new;"&gt;example&lt;/span&gt; JMS queue. Producer actors may choose from the same set of Camel components as Consumer actors do.&lt;br /&gt;&lt;br /&gt;The number of Camel components is constantly increasing. Akka's Camel module can support these in a plug-and-play manner. Just add them to your application's classpath, define a component-specific endpoint URI and use it to exchange messages over the component-specific protocols or APIs. This is possible because Camel components bind protocol-specific message formats to a Camel-specific &lt;a href="https://svn.apache.org/repos/asf/camel/tags/camel-2.2.0/camel-core/src/main/java/org/apache/camel/Message.java"&gt;normalized message format&lt;/a&gt;. The normalized message format hides protocol-specific details from Akka and makes it therefore very easy to support a large number of protocols through a uniform Camel component interface. Akka's Camel module further converts mutable Camel messages into &lt;a href="http://github.com/jboner/akka/blob/v0.8/akka-camel/src/main/scala/Message.scala#L17"&gt;immutable representations&lt;/a&gt; which are used by &lt;span style="font-family:courier new;"&gt;Consumer&lt;/span&gt; and &lt;span style="font-family:courier new;"&gt;Producer&lt;/span&gt; actors for pattern matching, transformation, serialization or storage, for example.&lt;br /&gt;&lt;h4&gt;Highly-scalable eHealth integration solutions with Akka&lt;/h4&gt;One goal I had in mind when implementing the Akka Camel module was to have a basis for building highly-scalable eHealth integration solutions. For eHealth information systems it is becoming increasingly important to support standard interfaces as specified by &lt;a href="http://www.ihe.net/"&gt;IHE&lt;/a&gt;. Financial support from governments strongly depends on eHealth standard compliance.&lt;br /&gt;&lt;br /&gt;Building blocks for implementing standard-compliant eHealth applications are provided by the &lt;a href="http://gforge.openehealth.org/gf/project/ipf/"&gt;Open eHealth Integration Platform&lt;/a&gt; (IPF). IPF is a mature open source integration platform, based on Apache Camel. It provides, among others, extensive support for IHE actor interfaces. These interfaces are based on Apache Camel's component technology. Therefore, it's a one-liner to expose an Akka actor through an IHE compliant interface. The following example implements the server-side interface of the &lt;a href="http://www.ihe.net/Technical_Framework/upload/IHE_ITI_TF_Supplement_XDS-2.pdf"&gt;IHE XDS&lt;/a&gt; &lt;span style="font-style: italic;"&gt;Registry Stored Query&lt;/span&gt; (XDS-ITI18) transaction.&lt;br /&gt;&lt;pre class="brush:scala"&gt;&lt;br /&gt;class RSQService extends Actor with Consumer {&lt;br /&gt;  def endpointUri = "xds-iti18:RSQService"&lt;br /&gt;&lt;br /&gt;  def receive = {&lt;br /&gt;    case msg: Message =&gt; { /* ... */}&lt;br /&gt;    case _            =&gt; { /* ... */}&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In IHE, a message exchange between two participants is called a transaction. Here, the IPF &lt;a href="http://repo.openehealth.org/confluence/display/ipf2/IHE+support"&gt;xds-iti18 component&lt;/a&gt; is used to implement the server-side interface of the XDS ITI18 transaction. This allows any XDS-ITI18-comaptible client to communicate with the actor over an IHE standard protocol using ebXML/SOAP/HTTP (as defined in the XDS specification). The implementor of the &lt;span style="font-family:courier new;"&gt;receive&lt;/span&gt; method, however, doesn't need to care about all the low-level protocol details (which are scary if you take a closer look). The body of the received message is a high-level object graph containing XDS-ITI18-specific transaction data.&lt;br /&gt;&lt;br /&gt;A high-level programming model for implementing eHealth standards is only one of several reasons why I consider Akka as a powerful technical basis for building scalable and fault-tolerant eHealth information systems and integration solutions. Akka's support for NoSQL datastores could further be used for implementing scalabale persistence layers in eHealth applications. Over the next weeks I'm going to explore this field in more detail and will keep you updated with further blog posts on that topic.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2708349453904691513-8004463190423350163?l=krasserm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://krasserm.blogspot.com/feeds/8004463190423350163/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://krasserm.blogspot.com/2010/04/akka-features-for-application.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/8004463190423350163'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/8004463190423350163'/><link rel='alternate' type='text/html' href='http://krasserm.blogspot.com/2010/04/akka-features-for-application.html' title='Akka features for application integration'/><author><name>Martin Krasser</name><uri>http://www.blogger.com/profile/11765963540395771125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://4.bp.blogspot.com/_LrEpKPgi9gI/TI-WeznHzsI/AAAAAAAAACM/FO3hdlxwrdI/S220/Bild006a.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2708349453904691513.post-8149418263548558099</id><published>2010-02-07T13:02:00.006+01:00</published><updated>2011-04-13T20:27:21.496+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ClientLogin'/><category scheme='http://www.blogger.com/atom/ns#' term='Google App Engine'/><category scheme='http://www.blogger.com/atom/ns#' term='camel'/><category scheme='http://www.blogger.com/atom/ns#' term='gae'/><title type='text'>Accessing a security-enabled Google App Engine service with Apache Camel</title><content type='html'>In a &lt;a href="http://krasserm.blogspot.com/2010/01/accessing-security-enabled-google-app.html"&gt;previous post&lt;/a&gt; I've described the low-level details for programmatic login to a Google App Engine service from a Java client. Things are getting much easier when using &lt;a href="http://camel.apache.org/"&gt;Apache Camel&lt;/a&gt;. The recently committed &lt;a href="http://camel.apache.org/glogin.html"&gt;&lt;span style="font-family:courier new;"&gt;glogin&lt;/span&gt;&lt;/a&gt; component makes it trivial to login to a remotely deployed Google App Engine service as well as to a local &lt;a href="http://code.google.com/appengine/docs/java/tools/devserver.html"&gt;development server&lt;/a&gt;. In the following example, an application-specific authorization cookie is obtained with the &lt;span style="font-family:courier new;"&gt;glogin&lt;/span&gt; component. It authorizes a client application to access &lt;a href="http://camelcloud.appspot.com/"&gt;http://camelcloud.appspot.com&lt;/a&gt; on Google App Engine.&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;import org.apache.camel.Exchange;&lt;br /&gt;import org.apache.camel.ProducerTemplate;&lt;br /&gt;import static org.apache.camel.component.gae.login.GLoginBinding.*;&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;ProducerTemplate template = ...&lt;br /&gt;&lt;br /&gt;Exchange result = template.request(&lt;br /&gt;"glogin://camelcloud.appspot.com"&lt;br /&gt;  + "?userName=replaceme@gmail.com"&lt;br /&gt;  + "&amp;amp;password=replaceme", null);&lt;br /&gt;String cookie = result.getOut().getHeader(&lt;br /&gt;  GLOGIN_COOKIE, String.class));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Please note that the password is only sent to the &lt;a href="http://code.google.com/intl/de-DE/apis/accounts/"&gt;Google Accounts API&lt;/a&gt; for authentication. It is never sent to Google App Engine or included into any URL. The obtained authorization cookie is valid for 24 hours and needs to be sent with subsequent requests to the GAE application. If inclusion of user credentials in an endpoint URI is not an option, username and password can also be dynamically set (per request) using Camel message headers:&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;import org.apache.camel.Exchange;&lt;br /&gt;import org.apache.camel.ProducerTemplate;&lt;br /&gt;import static org.apache.camel.component.gae.login.GLoginBinding.*;&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;ProducerTemplate template = ...&lt;br /&gt;&lt;br /&gt;Exchange result = template.request(&lt;br /&gt;"glogin://camelcloud.appspot.com", new Processor() {&lt;br /&gt;  public void process(Exchange exchange) {&lt;br /&gt;  exchange.getIn().setHeader(&lt;br /&gt;    GLOGIN_USER_NAME, "replaceme@gmail.com");&lt;br /&gt;  exchange.getIn().setHeader(&lt;br /&gt;    GLOGIN_PASSWORD, "replaceme");&lt;br /&gt;  }&lt;br /&gt;});&lt;br /&gt;String cookie = result.getOut().getHeader(&lt;br /&gt;  GLOGIN_COOKIE, String.class));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;To login to a local development server, the &lt;span style="font-family:courier new;"&gt;devMode&lt;/span&gt; parameter in the endpoint URI must be set to &lt;span style="font-family:courier new;"&gt;true&lt;/span&gt;.&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;import org.apache.camel.Exchange;&lt;br /&gt;import org.apache.camel.ProducerTemplate;&lt;br /&gt;import static org.apache.camel.component.gae.login.GLoginBinding.*;&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;ProducerTemplate template = ...&lt;br /&gt;&lt;br /&gt;Exchange result = template.request(&lt;br /&gt;"glogin://localhost:8888"&lt;br /&gt;   + "?userName=test@example.org"&lt;br /&gt;   + "&amp;amp;devMode=true", null);&lt;br /&gt;String cookie = result.getOut().getHeader(&lt;br /&gt;  GLOGIN_COOKIE, String.class));&lt;br /&gt;&lt;/pre&gt;The glogin component is part of the &lt;a href="http://camel.apache.org/gae.html"&gt;Camel Components for Google App Engine&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2708349453904691513-8149418263548558099?l=krasserm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://krasserm.blogspot.com/feeds/8149418263548558099/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://krasserm.blogspot.com/2010/02/accessing-security-enabled-google-app.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/8149418263548558099'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/8149418263548558099'/><link rel='alternate' type='text/html' href='http://krasserm.blogspot.com/2010/02/accessing-security-enabled-google-app.html' title='Accessing a security-enabled Google App Engine service with Apache Camel'/><author><name>Martin Krasser</name><uri>http://www.blogger.com/profile/11765963540395771125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://4.bp.blogspot.com/_LrEpKPgi9gI/TI-WeznHzsI/AAAAAAAAACM/FO3hdlxwrdI/S220/Bild006a.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2708349453904691513.post-744325696375085123</id><published>2010-02-07T11:48:00.007+01:00</published><updated>2010-02-07T15:59:45.561+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Google App Engine'/><category scheme='http://www.blogger.com/atom/ns#' term='camel'/><category scheme='http://www.blogger.com/atom/ns#' term='oauth'/><category scheme='http://www.blogger.com/atom/ns#' term='gae'/><title type='text'>Add OAuth to your web application with Apache Camel</title><content type='html'>&lt;a href="http://oauth.net/"&gt;OAuth&lt;/a&gt; is an open protocol to allow secure API authorization from desktop and web applications. Google, for example, already &lt;a href="http://code.google.com/intl/de-DE/apis/accounts/docs/OAuth.html"&gt;supports OAuth&lt;/a&gt; for authorizing 3rd-party applications to access Google services on behalf of a user.&lt;br /&gt;&lt;br /&gt;Recently, I added the &lt;a style="font-family: courier new;" href="http://camel.apache.org/gauth.html"&gt;gauth&lt;/a&gt; component to Apache Camel. You can use it to implement OAuth consumer functionality for any web application with only a few lines of code. &lt;span style="font-family:courier new;"&gt;gauth&lt;/span&gt; endpoints take care of exchanging authorization and access tokens between a web application and an OAuth service provider. At the moment, the &lt;span style="font-family:courier new;"&gt;gauth&lt;/span&gt; component can be used to interact with Google's OAuth services, later versions will support other OAuth providers as well.&lt;br /&gt;&lt;br /&gt;From a user's perspective, an example OAuth scenario might look as follows:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The user logs into a web application that uses the &lt;a href="http://code.google.com/intl/de-DE/apis/calendar/"&gt;Google Calendar API&lt;/a&gt;, for example.&lt;/li&gt;&lt;li&gt;To authorize access, the user is redirected to a Google Accounts authorization page where access for the requesting web application can be granted or denied.&lt;/li&gt;&lt;li&gt;After granting access the user is redirected back to the web application and the web application can now access the user's calendar data.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The user can revoke access at any time within Google Accounts.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;To implement that scenario with Apache Camel, two routes are needed. The first route obtains an unauthorized request token from Google and then redirects the user to the Google Accounts authorization page:&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;String encodedCallback = URLEncoder.encode(&lt;br /&gt; "https://example.org/handler", "UTF-8");&lt;br /&gt;String encodedScope = URLEncoder.encode(&lt;br /&gt; "http://www.google.com/calendar/feeds/", "UTF-8");&lt;br /&gt;&lt;br /&gt;from("jetty:http://0.0.0.0:8080/authorize")&lt;br /&gt;.to("gauth://authorize"&lt;br /&gt; + "?callback=" + encodedCallback&lt;br /&gt; + "&amp;amp;scope=" + encodedScope);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In this example, the authorization request is triggered by the user by sending a GET request to &lt;span style="font-family: courier new;"&gt;http://example.org/authorize&lt;/span&gt; (e.g. by clicking a link in the browser). The &lt;span style="font-family: courier new;"&gt;gauth://authorize&lt;/span&gt; endpoint then obtains an unauthorized request token from Google. The &lt;span style="font-family: courier new;"&gt;scope&lt;/span&gt; parameter in the endpoint URI defines which Google service the web application wants to access. After having obtained the token, the endpoint generates a redirect response (302) which redirects the user to the Google Accounts authorization page. After granting access, the user is redirected back to the web application (&lt;span style="font-family: courier new;"&gt;callback&lt;/span&gt; parameter). The callback now contains an authorized request token that must finally be upgraded to an access token. Handling the callback and upgrading to an access token is done in the second route.&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;from("jetty:https://example.org/handler")&lt;br /&gt;.to("gauth://upgrade")&lt;br /&gt;.to(new StoreTokenProcessor())&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The &lt;a style="font-family: courier new;" href="http://camel.apache.org/jetty.html"&gt;jetty&lt;/a&gt; endpoint receives the callback from Google. The &lt;span style="font-family: courier new;"&gt;gauth://upgrade&lt;/span&gt; endpoint takes the authorized request token from the callback and upgrades it to an access token. The route finally stores the long-lived access token for the current user. The next time the user logs into the web application, the access token is already available and the application can continue to access the user's Google Calendar data without needing further user interaction. The user can invalidate the access token at any time within Google Accounts.&lt;br /&gt;&lt;br /&gt;Only these two routes are needed to integrate with Google's OAuth provider services. The routes can perfectly co-exist with any other web application framework. Whereas the web framework provides the basis for web application-specific functionality, the OAuth service provider integration is done with Apache Camel. This approach allows for a clean separation of integration logic from application or domain logic.&lt;br /&gt;&lt;br /&gt;For handling OAuth requests, web applications can also use other components than Camel's &lt;span style="font-family: courier new;"&gt;jetty&lt;/span&gt; component, such as the &lt;a style="font-family: courier new;" href="http://camel.apache.org/servlet.html"&gt;servlet&lt;/a&gt; component. For adding OAuth to Google App Engine applications, the &lt;span style="font-family: courier new;"&gt;jetty&lt;/span&gt; component needs to be replaced with Camel's &lt;a style="font-family: courier new;" href="http://camel.apache.org/ghttp.html"&gt;ghttp&lt;/a&gt; component. Here's an example:&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;String encodedCallback = URLEncoder.encode(&lt;br /&gt; "https://camelcloud.appspot.com/handler", "UTF-8");&lt;br /&gt;String encodedScope = URLEncoder.encode(&lt;br /&gt; "http://www.google.com/calendar/feeds/", "UTF-8");&lt;br /&gt;&lt;br /&gt;from("ghttp:///authorize")&lt;br /&gt;.to("gauth://authorize"&lt;br /&gt; + "?callback=" + encodedCallback&lt;br /&gt; + "&amp;amp;scope=" + encodedScope);&lt;br /&gt;&lt;br /&gt;from("ghttp:///handler")&lt;br /&gt;.to("gauth://upgrade")&lt;br /&gt;.to(new StoreTokenProcessor())&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The following figure gives an overview how the OAuth sequence of interactions relate to the &lt;span style="font-family: courier new;"&gt;gauth://authorize&lt;/span&gt; and &lt;span style="font-family: courier new;"&gt;gauth://upgrade&lt;/span&gt; endpoints.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_LrEpKPgi9gI/S27KM_bJBEI/AAAAAAAAABc/lPaeq_kszF8/s1600-h/gauth.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 224px;" src="http://1.bp.blogspot.com/_LrEpKPgi9gI/S27KM_bJBEI/AAAAAAAAABc/lPaeq_kszF8/s400/gauth.png" alt="" id="BLOGGER_PHOTO_ID_5435504124815279170" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Accessing a Google service with an access token (step 9) is application-specific and not covered by the &lt;span style="font-family: courier new;"&gt;gauth&lt;/span&gt; component. To get access to a user's Google Calendar data with an access token, one could use the GData client library. The &lt;a style="font-family: courier new;" href="http://camel.apache.org/gauth.html"&gt;gauth&lt;/a&gt; component documentation contains an example.&lt;br /&gt;&lt;br /&gt;The &lt;span style="font-family: courier new;"&gt;gauth&lt;/span&gt; component is the first step towards a broader support of security standards such as &lt;a href="http://oauth.net/"&gt;OAuth&lt;/a&gt; and &lt;a href="http://openid.net/"&gt;OpenID&lt;/a&gt; in Apache Camel. I'm currently thinking of the following extensions&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A Camel OpenID component&lt;/li&gt;&lt;li&gt;A Camel OpenID/OAuth hybrid component&lt;/li&gt;&lt;li&gt;Support OAuth providers other than Google&lt;/li&gt;&lt;/ul&gt;The &lt;span style="font-family: courier new;"&gt;gauth&lt;/span&gt; component is currently part of the Camel 2.3 development snapshot (&lt;a href="https://svn.apache.org/repos/asf/camel/trunk/"&gt;sources&lt;/a&gt;).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2708349453904691513-744325696375085123?l=krasserm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://krasserm.blogspot.com/feeds/744325696375085123/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://krasserm.blogspot.com/2010/02/add-oauth-to-your-web-application-with.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/744325696375085123'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/744325696375085123'/><link rel='alternate' type='text/html' href='http://krasserm.blogspot.com/2010/02/add-oauth-to-your-web-application-with.html' title='Add OAuth to your web application with Apache Camel'/><author><name>Martin Krasser</name><uri>http://www.blogger.com/profile/11765963540395771125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://4.bp.blogspot.com/_LrEpKPgi9gI/TI-WeznHzsI/AAAAAAAAACM/FO3hdlxwrdI/S220/Bild006a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_LrEpKPgi9gI/S27KM_bJBEI/AAAAAAAAABc/lPaeq_kszF8/s72-c/gauth.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2708349453904691513.post-8947014629148726623</id><published>2010-01-14T16:23:00.012+01:00</published><updated>2011-04-13T20:32:06.286+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ClientLogin'/><category scheme='http://www.blogger.com/atom/ns#' term='Google App Engine'/><category scheme='http://www.blogger.com/atom/ns#' term='gae'/><title type='text'>Accessing a security-enabled Google App Engine service from a Java client</title><content type='html'>After a rather long search on Google pages and forums I could only find fragmented information how to programmatically access a Google App Engine service that requires users to authenticate. In this blog post I'm going to summarize my findings for a Java client application.&lt;br /&gt;&lt;br /&gt;With programmatic access I mean that the user doesn't need to enter username and password into a login form created by Google but rather into an installed client application and the client coordinates the authentication and authorization process programmatically. The mechanism used here is the &lt;a href="http://code.google.com/apis/accounts/docs/AuthForInstalledApps.html"&gt;ClientLogin for installed applications&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The first step is to obtain an authentication token from the &lt;a href="http://code.google.com/apis/accounts/"&gt;Google Accounts API&lt;/a&gt;. The easiest way to do that is with the &lt;a href="http://code.google.com/p/gdata-java-client/"&gt;GData client library for Java&lt;/a&gt;.&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;import java.net.URLEncoder;&lt;br /&gt;&lt;br /&gt;import com.google.gdata.client.GoogleAuthTokenFactory;&lt;br /&gt;import com.google.gdata.util.AuthenticationException;&lt;br /&gt;&lt;br /&gt;public class AuthExample {&lt;br /&gt;&lt;br /&gt;  public static void main(String[] args) throws Exception {&lt;br /&gt;&lt;br /&gt;    String username = "myusername@gmail.com";&lt;br /&gt;    String password = "mypassword";&lt;br /&gt;    String serviceName = "ah";&lt;br /&gt;&lt;br /&gt;    GoogleAuthTokenFactory factory = new GoogleAuthTokenFactory(serviceName, "", null);&lt;br /&gt;    // Obtain authentication token from Google Accounts&lt;br /&gt;    String token = factory.getAuthToken(username, password, null, null, serviceName, "");&lt;br /&gt;&lt;br /&gt;    ...&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;One has to provide username an password and the name of the Google service that should be accessed. For Google App Engine the service name is always &lt;span style="font-style: italic;"&gt;ah&lt;/span&gt;, regardless of the name of the deployed application. The next step is to do a login at Google App Engine. The login URL is &lt;span style="font-family:courier new;"&gt;https://example.appspot.com/_ah/login?continue=https%3A%2F%2Fexample.appspot.com%2Fexample&amp;amp;auth=DQAAAJc...qNUA8&lt;/span&gt;. The &lt;span style="font-family:courier new;"&gt;continue&lt;/span&gt; query parameter instructs the login service where to rederict after successful login. In this example the redirect goes to &lt;span style="font-family:courier new;"&gt;https://example.appspot.com/example&lt;/span&gt;. The &lt;span style="font-family:courier new;"&gt;auth&lt;/span&gt; query parameter contains the authentication token obtained before.&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;import org.apache.http.HttpResponse;&lt;br /&gt;import org.apache.http.client.HttpClient;&lt;br /&gt;import org.apache.http.client.methods.HttpGet;&lt;br /&gt;import org.apache.http.impl.client.DefaultHttpClient;&lt;br /&gt;&lt;br /&gt;public class AuthExample {&lt;br /&gt;&lt;br /&gt;  public static void main(String[] args) throws Exception {&lt;br /&gt;    ...&lt;br /&gt;&lt;br /&gt;    String token = ...&lt;br /&gt;    String serviceUrl = "https://example.appspot.com/example";&lt;br /&gt;    String loginUrl = "https://example.appspot.com/_ah/login?continue=" +&lt;br /&gt;    URLEncoder.encode(serviceUrl, "UTF-8") + "&amp;amp;auth=" + token;&lt;br /&gt;&lt;br /&gt;    HttpClient httpclient = new DefaultHttpClient();&lt;br /&gt;    HttpGet httpget = new HttpGet(loginUrl);&lt;br /&gt;    HttpResponse response = httpclient.execute(httpget);&lt;br /&gt;    // process response&lt;br /&gt;    // ...&lt;br /&gt;&lt;br /&gt;    httpclient.getConnectionManager().shutdown();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;When the login service sends a redirect after successful login, it also returns a cookie that allows the client to finally access the protected App Engine service at &lt;span style="font-family:courier new;"&gt;https://example.appspot.com/example&lt;/span&gt;. The redirect and cookie handling is done by the &lt;span style="font-family:courier new;"&gt;httpclient&lt;/span&gt; automatically. For the duration of the session the protected App Engine service can be accessed with that cookie.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Update:&lt;/span&gt; If the service expects POST requests instead of GET requests then an automated redirect is not an option. In this case, redirect must be disabled for the for the &lt;span style="font-family:courier new;"&gt;httpclient&lt;/span&gt; and a POST request to the &lt;span style="font-family:courier new;"&gt;serviceUrl&lt;/span&gt; must be created manually. Also, the authorization cookie must be set explicitly.&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;import org.apache.http.Header;&lt;br /&gt;import org.apache.http.HttpResponse;&lt;br /&gt;import org.apache.http.client.HttpClient;&lt;br /&gt;import org.apache.http.client.methods.HttpGet;&lt;br /&gt;import org.apache.http.client.methods.HttpPost;&lt;br /&gt;import org.apache.http.client.params.ClientPNames;&lt;br /&gt;import org.apache.http.impl.client.DefaultHttpClient;&lt;br /&gt;&lt;br /&gt;public class AuthExample {&lt;br /&gt;&lt;br /&gt;  public static void main(String[] args) throws Exception {&lt;br /&gt;    ...&lt;br /&gt;&lt;br /&gt;    String token = ...&lt;br /&gt;    String loginUrl = "https://example.appspot.com/_ah/login?auth=" + token;&lt;br /&gt;    String serviceUrl = "https://example.appspot.com/example";&lt;br /&gt;&lt;br /&gt;    HttpClient httpclient = new DefaultHttpClient();&lt;br /&gt;    httpclient.getParams().setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, false);&lt;br /&gt;    HttpGet httpget = new HttpGet(loginUrl);&lt;br /&gt;    HttpResponse response = httpclient.execute(httpget);&lt;br /&gt;    // Get cookie returned from login service&lt;br /&gt;    Header[] headers = response.getHeaders("Set-Cookie");&lt;br /&gt;    httpclient.getConnectionManager().shutdown();   &lt;br /&gt;&lt;br /&gt;    httpclient = new DefaultHttpClient();&lt;br /&gt;    HttpPost httppost = new HttpPost(serviceUrl);&lt;br /&gt;    // set cookie returned by login service&lt;br /&gt;    for (Header header : headers) {&lt;br /&gt;      httppost.addHeader("Cookie", header.getValue());&lt;br /&gt;    }&lt;br /&gt;    // set request entity body&lt;br /&gt;    // ...&lt;br /&gt;&lt;br /&gt;    response = httpclient.execute(httppost);&lt;br /&gt;    // process response&lt;br /&gt;    // ...&lt;br /&gt;&lt;br /&gt;    httpclient.getConnectionManager().shutdown();   &lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;Update:&lt;/span&gt; Login to a local development server. To get access to a security-enabled application on the local development server there's no need for getting an authentication token. Instead, POST an email address and a redirect URL to &lt;span style="font-family:courier new;"&gt;http://localhost:&amp;lt;port&amp;gt;/_ah/login&lt;/span&gt; and the server returns an authorization cookie. Here's an example:&lt;br /&gt;&lt;pre class="brush:java"&gt;HttpClient httpClient = new DefaultHttpClient();&lt;br /&gt;httpClient.getParams().setBooleanParameter(&lt;br /&gt;  ClientPNames.HANDLE_REDIRECTS, false);&lt;br /&gt;// POST login data to GAE SDK dev server&lt;br /&gt;HttpPost httpPost = new HttpPost(&lt;br /&gt;  "http://localhost:8888/_ah/login");&lt;br /&gt;httpPost.setHeader("Content-Type",&lt;br /&gt;  "application/x-www-form-urlencoded");&lt;br /&gt;String email = URLEncoder.encode(&lt;br /&gt;  "test@example.com", "UTF-8");&lt;br /&gt;String redirectUrl = URLEncoder.encode(&lt;br /&gt;  "http://localhost:8888", "UTF-8");&lt;br /&gt;httpPost.setEntity(new StringEntity(&lt;br /&gt;  "email=" + email + "&amp;amp;continue=" + redirectUrl));&lt;br /&gt;HttpResponse response = httpClient.execute(httpPost);&lt;br /&gt;// Extract authorization cookie from response&lt;br /&gt;String cookie = response.getFirstHeader("Set-Cookie").getValue();&lt;br /&gt;httpClient.getConnectionManager().shutdown();&lt;br /&gt;// Create a new client and access the secured&lt;br /&gt;// service with the authorization cookie&lt;br /&gt;httpClient = new DefaultHttpClient();&lt;br /&gt;HttpGet httpget = new HttpGet("http://localhost:8888");&lt;br /&gt;httpget.addHeader("Cookie", cookie);&lt;br /&gt;response = httpClient.execute(httpget);&lt;br /&gt;System.out.println(IOUtils.toString(response.getEntity().getContent()));&lt;br /&gt;httpClient.getConnectionManager().shutdown();&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2708349453904691513-8947014629148726623?l=krasserm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://krasserm.blogspot.com/feeds/8947014629148726623/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://krasserm.blogspot.com/2010/01/accessing-security-enabled-google-app.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/8947014629148726623'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/8947014629148726623'/><link rel='alternate' type='text/html' href='http://krasserm.blogspot.com/2010/01/accessing-security-enabled-google-app.html' title='Accessing a security-enabled Google App Engine service from a Java client'/><author><name>Martin Krasser</name><uri>http://www.blogger.com/profile/11765963540395771125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://4.bp.blogspot.com/_LrEpKPgi9gI/TI-WeznHzsI/AAAAAAAAACM/FO3hdlxwrdI/S220/Bild006a.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2708349453904691513.post-5073953703794168217</id><published>2009-12-12T08:52:00.006+01:00</published><updated>2011-04-13T20:17:01.306+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='REST'/><category scheme='http://www.blogger.com/atom/ns#' term='restlet'/><category scheme='http://www.blogger.com/atom/ns#' term='jax-rs'/><category scheme='http://www.blogger.com/atom/ns#' term='jersey'/><category scheme='http://www.blogger.com/atom/ns#' term='grails'/><category scheme='http://www.blogger.com/atom/ns#' term='JSR 311'/><title type='text'>New features in grails-jaxrs 0.3</title><content type='html'>In this blog post I present some new features of the recently released grails-jaxrs 0.3 plugin. A complete list of new features is available in the &lt;a href="http://code.google.com/p/grails-jaxrs/wiki/ReleaseNotes_0_3"&gt;release notes&lt;/a&gt;. A feature overview and links to the complete documentation is on the &lt;a href="http://code.google.com/p/grails-jaxrs/"&gt;plugin home page&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;grails-jaxrs is a Grails plugin that supports the development of RESTful web services based on the &lt;a href="http://jcp.org/en/jsr/detail?id=311"&gt;Java API for RESTful Web Services&lt;/a&gt; (JSR 311: JAX-RS). It is targeted at developers who want to structure the web service layer of an application in a JSR 311 compatible way but still want to continue to use Grails' powerful features such as GORM, automated XML and JSON marshalling, Grails services, Grails filters and so on. This plugin is an alternative to Grails' built-in mechanism for implementing RESTful web services.&lt;br /&gt;&lt;br /&gt;The following example shows how to do content negotiation for Grails domain objects. Grails domain classes like&lt;br /&gt;&lt;pre class="brush:groovy"&gt;&lt;br /&gt;class Person {&lt;br /&gt;  String firstName&lt;br /&gt;  String lastName&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;can now be used in JAX-RS resource methods directly (e.g. &lt;span style="font-family: courier new;"&gt;Person&lt;/span&gt; parameter in the &lt;span style="font-family: courier new;"&gt;create&lt;/span&gt; method):&lt;br /&gt;&lt;pre class="brush:groovy"&gt;&lt;br /&gt;import static javax.ws.rs.core.UriBuilder.fromPath&lt;br /&gt;&lt;br /&gt;import javax.ws.rs.Consumes&lt;br /&gt;import javax.ws.rs.Path&lt;br /&gt;import javax.ws.rs.Produces&lt;br /&gt;import javax.ws.rs.POST&lt;br /&gt;import javax.ws.rs.core.Response&lt;br /&gt;&lt;br /&gt;@Path('/api/person')&lt;br /&gt;@Consumes(['application/xml','application/json'])&lt;br /&gt;@Produces(['application/xml','application/json'])&lt;br /&gt;class PersonCollectionResource {&lt;br /&gt;&lt;br /&gt;  @POST&lt;br /&gt;  Response create(Person person) {&lt;br /&gt;      person.save() // use GORM&lt;br /&gt;      URI uri = fromPath(person.id as String).build()&lt;br /&gt;      Response.created(uri).entity(person).build()&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // ...&lt;br /&gt;       &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Content negotiation and conversion between domain objects and their XML or JSON representations is done by &lt;a href="http://code.google.com/p/grails-jaxrs/wiki/AdvancedFeatures#Domain_object_providers"&gt;domain object providers&lt;/a&gt;. There's no need any more for application code to deal with representation formats directly.&lt;br /&gt;&lt;br /&gt;The &lt;span style="font-family: courier new;"&gt;PersonCollectionResource.create&lt;/span&gt; method handles POST requests for creating new Person objects in the database. The method uses &lt;a href="http://grails.org/doc/1.1.2/guide/5.%20Object%20Relational%20Mapping%20%28GORM%29.html"&gt;GORM&lt;/a&gt; to persist the domain object. Clients can send either XML or JSON representations for POSTing person data (see &lt;span style="font-family: courier new;"&gt;Content-Type&lt;/span&gt; header):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;POST /hello/api/person HTTP/1.1&lt;br /&gt;Content-Type: application/xml&lt;br /&gt;Accept: application/xml&lt;br /&gt;Host: localhost:8080&lt;br /&gt;Content-Length: 78&lt;br /&gt;&lt;br /&gt;&amp;lt;person&amp;gt;&lt;br /&gt;&amp;lt;firstname&amp;gt;Sam&amp;lt;/firstname&amp;gt;&lt;br /&gt;&amp;lt;lastname&amp;gt;Hill&amp;lt;/lastname&amp;gt;&lt;br /&gt;&amp;lt;/person&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;or&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;POST /hello/api/person HTTP/1.1&lt;br /&gt;Content-Type: application/json&lt;br /&gt;Accept: application/json&lt;br /&gt;Host: localhost:8080&lt;br /&gt;Content-Length: 58&lt;br /&gt;&lt;br /&gt;{"class":"Person","firstName":"Fabien","lastName":"Barel"}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In either case, the plugin will convert it to a &lt;span style="font-family: courier new;"&gt;Person&lt;/span&gt; object, as required by the &lt;span style="font-family: courier new;"&gt;person &lt;/span&gt;parameter. For creating a response the method uses the JAX-RS API. It first creates a URI for the response &lt;span style="font-family: courier new;"&gt;Location&lt;/span&gt; header and uses the &lt;span style="font-family: courier new;"&gt;Response&lt;/span&gt; builder to set the status code to 201 (&lt;span style="font-family: courier new;"&gt;created&lt;/span&gt;) and the response entity. Note that the method itself doesn't create an XML or JSON representation of the response domain object. This is again done by a domain object provider which uses the &lt;span style="font-family: courier new;"&gt;Accept&lt;/span&gt; request header to determine the response representation format. The responses to the above POST requests are:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;HTTP/1.1 201 Created&lt;br /&gt;Content-Type: application/xml&lt;br /&gt;Location: http://localhost:8080/hello/api/person/1&lt;br /&gt;Transfer-Encoding: chunked&lt;br /&gt;Server: Jetty(6.1.14)&lt;br /&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;person id="1"&amp;gt;&lt;br /&gt;&amp;lt;firstname&amp;gt;Sam&amp;lt;/firstname&amp;gt;&lt;br /&gt;&amp;lt;lastname&amp;gt;Hill&amp;lt;/lastname&amp;gt;&lt;br /&gt;&amp;lt;/person&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;and&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;HTTP/1.1 201 Created&lt;br /&gt;Content-Type: application/json&lt;br /&gt;Location: http://localhost:8080/hello/api/person/2&lt;br /&gt;Transfer-Encoding: chunked&lt;br /&gt;Server: Jetty(6.1.14)&lt;br /&gt;&lt;br /&gt;{"class":"Person","id":"2","firstName":"Fabien","lastName":"Barel"}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The &lt;span style="font-family: courier new;"&gt;PersonCollectionResource.create&lt;/span&gt; method is even more verbose than necessary. It could equally be written as&lt;br /&gt;&lt;pre class="brush:groovy"&gt;&lt;br /&gt;import static org.grails.jaxrs.response.Responses.*&lt;br /&gt;&lt;br /&gt;@Path('/api/person')&lt;br /&gt;@Consumes(['application/xml','application/json'])&lt;br /&gt;@Produces(['application/xml','application/json'])&lt;br /&gt;class PersonCollectionResource {&lt;br /&gt;&lt;br /&gt;  @POST&lt;br /&gt;  Response create(Person person) {&lt;br /&gt;      created person.save()&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // ...&lt;br /&gt;       &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;using helper methods (a mini-DSL) from &lt;span style="font-family: courier new;"&gt;org.grails.jaxrs.response.Responses&lt;/span&gt;. That's exactly the code that is generated when using &lt;a href="http://code.google.com/p/grails-jaxrs/wiki/GettingStarted#Scaffolding"&gt;scaffolding&lt;/a&gt; for the &lt;span style="font-family: courier new;"&gt;Person&lt;/span&gt; domain class i.e.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;grails generate-resources person&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;With the grails-jaxrs scaffolding feature, one can generate RESTful service interface for domain objects supporting the HTTP methods POST, GET, PUT and DELETE. A scaffolding example is given in the &lt;a href="http://code.google.com/p/grails-jaxrs/wiki/GettingStarted#Scaffolding"&gt;Scaffolding&lt;/a&gt; section of the grails-jaxrs documentation, a walk through the generated code is in the &lt;a href="http://code.google.com/p/grails-jaxrs/wiki/AdvancedFeatures#Using_GORM"&gt;Using GORM&lt;/a&gt; section.&lt;br /&gt;&lt;br /&gt;By default, grails-jaxrs uses Grail's XML and JSON converters for converting between domain objects and their XML or JSON representations. Applications can easily customize this conversion logic as explained in the &lt;a href="http://code.google.com/p/grails-jaxrs/wiki/AdvancedFeatures#Custom_providers"&gt;Custom entity providers&lt;/a&gt; section.&lt;br /&gt;&lt;br /&gt;Besides usage of GORM, grails-jaxrs also supports &lt;a href="http://code.google.com/p/grails-jaxrs/wiki/AdvancedFeatures#Service_injection"&gt;auto-injection of Grails services&lt;/a&gt; into JAX-RS resource and provider classes or usage of &lt;a href="http://code.google.com/p/grails-jaxrs/wiki/AdvancedFeatures#Applying_filters"&gt;Grails filters&lt;/a&gt;, to mention a few. With version 0.3 the included JAX-RS implementations have been upgraded to their latest versions: Jersey 1.1.4.1 and Restlet 2.0-M6.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2708349453904691513-5073953703794168217?l=krasserm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://krasserm.blogspot.com/feeds/5073953703794168217/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://krasserm.blogspot.com/2009/12/new-features-in-grails-jaxrs-03.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/5073953703794168217'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/5073953703794168217'/><link rel='alternate' type='text/html' href='http://krasserm.blogspot.com/2009/12/new-features-in-grails-jaxrs-03.html' title='New features in grails-jaxrs 0.3'/><author><name>Martin Krasser</name><uri>http://www.blogger.com/profile/11765963540395771125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://4.bp.blogspot.com/_LrEpKPgi9gI/TI-WeznHzsI/AAAAAAAAACM/FO3hdlxwrdI/S220/Bild006a.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2708349453904691513.post-6549960399310244598</id><published>2009-11-17T06:27:00.002+01:00</published><updated>2009-11-17T06:39:32.075+01:00</updated><title type='text'>Camel components for Google App Engine</title><content type='html'>The upcoming Apache Camel version 2.1 will include &lt;a href="http://cwiki.apache.org/confluence/display/CAMEL/GAE"&gt;components for connecting to the cloud computing services of Google App Engine&lt;/a&gt;. At the moment the following three components are available.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a style="font-family: courier new;" href="http://cwiki.apache.org/confluence/display/CAMEL/ghttp"&gt;ghttp&lt;/a&gt;: Provides connectivity to the GAE &lt;a href="http://code.google.com/appengine/docs/java/urlfetch/" rel="nofollow"&gt;URL fetch service&lt;/a&gt; but can also be used to receive messages from servlets&lt;/li&gt;&lt;li&gt;&lt;a style="font-family: courier new;" href="http://cwiki.apache.org/confluence/display/CAMEL/gtask"&gt;gtask&lt;/a&gt;: Supports asynchronous message processing on GAE by using the &lt;a href="http://code.google.com/appengine/docs/java/taskqueue/" rel="nofollow"&gt;task queueing service&lt;/a&gt; as message queue.  &lt;/li&gt;&lt;li&gt;&lt;a style="font-family: courier new;" href="http://cwiki.apache.org/confluence/display/CAMEL/gmail"&gt;gmail&lt;/a&gt;: Supports sending of emails via the GAE &lt;a href="http://code.google.com/appengine/docs/java/mail/" rel="nofollow"&gt;mail service&lt;/a&gt;. Receiving mails is not supported yet but will be added later.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Camel components for the other Google App Engine cloud computing services such as Memcache service, XMPP service, Images service, Datastore Service and the Authentication service are planned.&lt;br /&gt;&lt;br /&gt;There's also a &lt;a href="http://cwiki.apache.org/confluence/display/CAMEL/Tutorial+for+Camel+on+Google+App+Engine"&gt;tutorial&lt;/a&gt; that explains how to develop a non-trivial Camel GAE application using the Camel components for GAE.&lt;br /&gt;&lt;br /&gt;From a conceptual point of view, connecting to cloud computing services via Camel components introduces an abstraction-layer that decouples Camel applications from provider-specific cloud service interfaces. Supporting several cloud computing environments in Camel can significantly reduce the burden of migrating Camel applications from one provider to another. The Camel components for Google App Engine are a first step into this direction.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2708349453904691513-6549960399310244598?l=krasserm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://krasserm.blogspot.com/feeds/6549960399310244598/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://krasserm.blogspot.com/2009/11/camel-components-for-google-app-engine.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/6549960399310244598'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/6549960399310244598'/><link rel='alternate' type='text/html' href='http://krasserm.blogspot.com/2009/11/camel-components-for-google-app-engine.html' title='Camel components for Google App Engine'/><author><name>Martin Krasser</name><uri>http://www.blogger.com/profile/11765963540395771125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://4.bp.blogspot.com/_LrEpKPgi9gI/TI-WeznHzsI/AAAAAAAAACM/FO3hdlxwrdI/S220/Bild006a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2708349453904691513.post-3237541088942203934</id><published>2009-10-18T09:32:00.007+02:00</published><updated>2011-04-13T20:19:11.195+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='camel'/><category scheme='http://www.blogger.com/atom/ns#' term='gae'/><title type='text'>First steps with Apache Camel on Google App Engine</title><content type='html'>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&lt;br /&gt;&lt;ul&gt;&lt;li&gt;make Camel deployments on GAE easier and to&lt;/li&gt;&lt;li&gt;allow Camel applications access GAE services via Camel components&lt;/li&gt;&lt;/ul&gt;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:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;camel-core&lt;/li&gt;&lt;li&gt;camel-spring&lt;/li&gt;&lt;li&gt;camel-servlet&lt;/li&gt;&lt;li&gt;camel-http&lt;/li&gt;&lt;/ul&gt;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.&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;package example;&lt;br /&gt;&lt;br /&gt;import org.apache.camel.builder.RouteBuilder;&lt;br /&gt;&lt;br /&gt;public class ExampleRoute extends RouteBuilder {&lt;br /&gt;&lt;br /&gt;  @Override&lt;br /&gt;  public void configure() throws Exception {&lt;br /&gt;     from("servlet:/test")&lt;br /&gt;     .convertBodyTo(String.class)&lt;br /&gt;     .transform(constant("Hello ").append(body()));&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;For processing HTTP requests, I created my own servlet class and extended the &lt;span style=";font-family:courier new;font-size:85%;"  &gt;CamelHttpTransportServlet&lt;/span&gt; from the camel-servlet component.&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;package example;&lt;br /&gt;&lt;br /&gt;import org.apache.camel.component.servlet.CamelHttpTransportServlet;&lt;br /&gt;import org.apache.camel.management.JmxSystemPropertyKeys;&lt;br /&gt;&lt;br /&gt;public class ExampleServlet extends CamelHttpTransportServlet {&lt;br /&gt;&lt;br /&gt; static {&lt;br /&gt;     System.setProperty(JmxSystemPropertyKeys.DISABLED, "true");&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;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 &lt;span style=";font-family:courier new;font-size:85%;"  &gt;CamelHttpTransportServlet&lt;/span&gt;. Configuring the servlet in the &lt;span style=";font-family:courier new;font-size:85%;"  &gt;web.xml&lt;/span&gt; was done as follows.&lt;br /&gt;&lt;pre class="brush:xml"&gt;&lt;br /&gt;&amp;lt;servlet&amp;gt;&lt;br /&gt;&amp;lt;servlet-name&amp;gt;CamelServlet&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;&amp;lt;servlet-class&amp;gt;example.ExampleServlet&amp;lt;/servlet-class&amp;gt;&lt;br /&gt;&amp;lt;init-param&amp;gt;&lt;br /&gt;   &amp;lt;param-name&amp;gt;contextConfigLocation&amp;lt;/param-name&amp;gt;&lt;br /&gt;   &amp;lt;param-value&amp;gt;context.xml&amp;lt;/param-value&amp;gt;&lt;br /&gt;&amp;lt;/init-param&amp;gt;&lt;br /&gt;&amp;lt;/servlet&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;servlet-mapping&amp;gt;&lt;br /&gt;&amp;lt;servlet-name&amp;gt;CamelServlet&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;&amp;lt;url-pattern&amp;gt;/camel/*&amp;lt;/url-pattern&amp;gt;&lt;br /&gt;&amp;lt;/servlet-mapping&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The servlet &lt;span style=";font-family:courier new;font-size:85%;"  &gt;init-param&lt;/span&gt; points to the Spring application context that configures the route builder and the Camel context:&lt;br /&gt;&lt;pre class="brush:xml"&gt;&lt;br /&gt;&amp;lt;beans xmlns="http://www.springframework.org/schema/beans"&lt;br /&gt;  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt;  xsi:schemaLocation="&lt;br /&gt;http://www.springframework.org/schema/beans&lt;br /&gt;http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;bean id="camelContext"&lt;br /&gt;   class="org.apache.camel.spring.CamelContextFactoryBean"&amp;gt;&lt;br /&gt;   &amp;lt;property name="builderRefs"&amp;gt;&lt;br /&gt;       &amp;lt;list&amp;gt;&lt;br /&gt;           &amp;lt;ref bean="routeBuilderRef"/&amp;gt;&lt;br /&gt;       &amp;lt;/list&amp;gt;&lt;br /&gt;   &amp;lt;/property&amp;gt;&lt;br /&gt;&amp;lt;/bean&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;bean id="routeBuilderRef"&lt;br /&gt;   class="org.apache.camel.model.RouteBuilderDefinition"&amp;gt;&lt;br /&gt;   &amp;lt;constructor-arg value="routeBuilder" /&amp;gt;&lt;br /&gt;&amp;lt;/bean&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;bean id="routeBuilder"&lt;br /&gt;   class="example.ExampleRoute"&amp;gt;&lt;br /&gt;&amp;lt;/bean&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/beans&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;A severe limitation is that one cannot use the Camel-specific configuration XML schema from the &lt;span style=";font-family:courier new;font-size:85%;"  &gt;http://camel.apache.org/schema/spring&lt;/span&gt; namespace for configuring the Camel context. The problem is that the &lt;span style=";font-family:courier new;font-size:85%;"  &gt;CamelNamespaceHandler&lt;/span&gt; uses JAXB to parse bean definitions which isn't supported by GAE either. One has to fallback to plain old &lt;span style=";font-family:courier new;font-size:85%;"  &gt;&amp;lt;bean&amp;gt;&lt;/span&gt; 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.&lt;br /&gt;&lt;br /&gt;Another JAXB-releated problem arises with Camel's Spring DSL. It is also processed with JAXB and therefore cannot be used on GAE.&lt;br /&gt;&lt;br /&gt;Going completely without Spring leads to another problem. In this case the &lt;span style=";font-family:courier new;font-size:85%;"  &gt;CamelContext&lt;/span&gt; uses a &lt;span style=";font-family:courier new;font-size:85%;"  &gt;JndiRegistry&lt;/span&gt; by default that depends on &lt;span style=";font-family:courier new;font-size:85%;"  &gt;javax.naming.InitialContext&lt;/span&gt;. This class isn't on the JRE whitelist either. Writing a simple Map-based implementation of &lt;span style=";font-family:courier new;font-size:85%;"  &gt;org.apache.camel.impl.Registry&lt;/span&gt; and configuring the &lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;CamelContext&lt;/span&gt;&lt;/span&gt; with it does the trick.&lt;br /&gt;&lt;br /&gt;The last obstacle to get the sample application running was to replace the Camel's &lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;UuidGenerator&lt;/span&gt;&lt;/span&gt; with another one that uses &lt;span style=";font-family:courier new;font-size:85%;"  &gt;java.util.UUID&lt;/span&gt; from the JRE. Camel's original &lt;span style=";font-family:courier new;font-size:85%;"  &gt;UuidGenerator&lt;/span&gt; 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).&lt;br /&gt;&lt;br /&gt;After deploying the application to GAE and POSTing a request containing "Martin" to &lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;http://&amp;lt;appname&amp;gt;.appspot.com/camel/test&lt;/span&gt;&lt;/span&gt; I was able to send myself greetings. In the URL, &lt;span style=";font-family:courier new;font-size:85%;"  &gt;&amp;lt;appname&amp;gt;&lt;/span&gt; must of course be replaced with the name of an existing application.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2708349453904691513-3237541088942203934?l=krasserm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://krasserm.blogspot.com/feeds/3237541088942203934/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://krasserm.blogspot.com/2009/10/first-steps-with-apache-camel-on-google.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/3237541088942203934'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/3237541088942203934'/><link rel='alternate' type='text/html' href='http://krasserm.blogspot.com/2009/10/first-steps-with-apache-camel-on-google.html' title='First steps with Apache Camel on Google App Engine'/><author><name>Martin Krasser</name><uri>http://www.blogger.com/profile/11765963540395771125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://4.bp.blogspot.com/_LrEpKPgi9gI/TI-WeznHzsI/AAAAAAAAACM/FO3hdlxwrdI/S220/Bild006a.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2708349453904691513.post-3612572997412727879</id><published>2009-10-14T15:00:00.003+02:00</published><updated>2009-10-14T15:13:53.870+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cda'/><category scheme='http://www.blogger.com/atom/ns#' term='IPF'/><category scheme='http://www.blogger.com/atom/ns#' term='ihe'/><category scheme='http://www.blogger.com/atom/ns#' term='camel'/><category scheme='http://www.blogger.com/atom/ns#' term='ccd'/><title type='text'>IPF 2.0 milestone 2 and IPF Tools milestones released</title><content type='html'>I'm pleased to announce the following milestone releases from the &lt;a href="http://repo.openehealth.org/confluence/display/ipf2/Home"&gt;IPF core&lt;/a&gt; project and the &lt;a href="http://repo.openehealth.org/confluence/display/ipftools/Home"&gt;IPF Tools&lt;/a&gt; project.&lt;br /&gt;&lt;br /&gt;IPF 2.0 milestone 2 (&lt;a href="http://repo.openehealth.org/confluence/display/ipf2/IPF+2.0-m2"&gt;release notes&lt;/a&gt;)&lt;br /&gt;IPF Tools&lt;br /&gt;- IPF Runtime 2.0 milestone 2 (&lt;a href="http://repo.openehealth.org/confluence/display/ipftools/IPF+Runtime+2.0.0.m2"&gt;release notes&lt;/a&gt;)&lt;br /&gt;- IPF Manager 2.0 milestone 2 (&lt;a href="http://repo.openehealth.org/confluence/display/ipftools/IPF+Manager+2.0.0.m2"&gt;release notes&lt;/a&gt;)&lt;br /&gt;- IPF IDE 1.0 milestone 2 (&lt;a href="http://repo.openehealth.org/confluence/display/ipftools/IPF+IDE+1.0.0.m2#"&gt;release notes&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;IPF 2.0 milestone 2&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This release is feature-equivalent to &lt;a href="http://repo.openehealth.org/confluence/display/ipf/IPF+1.7.0"&gt;IPF 1.7.0&lt;/a&gt; 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. &lt;b&gt;Please note that IPF 2.0 is not backwards-compatible to IPF 1.x&lt;/b&gt;. This is mainly due to non-backwards compatible API changes in Camel 2.0. It is therefore important to carefully read the &lt;a href="http://camel.apache.org/camel-200-release.html"&gt;Camel 2.0.0 release notes&lt;/a&gt; as well as the &lt;a href="http://repo.openehealth.org/confluence/display/ipf2/IPF+2.0-m2#IPF2.0-m2-Upgradenotes"&gt;IPF 2.0-m2 upgrade notes&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;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 &lt;a href="http://gforge.openehealth.org/gf/project/ipf/tracker/"&gt;IPF issue tracker&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Other changes compared to IPF 1.7.0 are:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The platform manager has been moved to the IPF Tools project.&lt;/li&gt;&lt;li&gt;The IPF OSGi distributable (IPF runtime) and the IPF OSGi documentation have been moved to the IPF Tools project.&lt;/li&gt;&lt;li&gt;The HL7-independent parts of the mapping service have been factored out into a new commons-map component.&lt;/li&gt;&lt;li&gt;The IPF 2.0 documentation has been forked from the IPF 1.7 documentation and revised.&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:130%;"&gt;&lt;br /&gt;IPF Runtime 2.0 milestone 2&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;br /&gt;IPF Manager 2.0 milestone 2&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;br /&gt;IPF IDE 1.0 milestone 2&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2708349453904691513-3612572997412727879?l=krasserm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://krasserm.blogspot.com/feeds/3612572997412727879/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://krasserm.blogspot.com/2009/10/ipf-20-milestone-2-and-ipf-tools.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/3612572997412727879'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/3612572997412727879'/><link rel='alternate' type='text/html' href='http://krasserm.blogspot.com/2009/10/ipf-20-milestone-2-and-ipf-tools.html' title='IPF 2.0 milestone 2 and IPF Tools milestones released'/><author><name>Martin Krasser</name><uri>http://www.blogger.com/profile/11765963540395771125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://4.bp.blogspot.com/_LrEpKPgi9gI/TI-WeznHzsI/AAAAAAAAACM/FO3hdlxwrdI/S220/Bild006a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2708349453904691513.post-6970374852082002100</id><published>2009-10-07T11:09:00.003+02:00</published><updated>2009-10-07T11:25:17.862+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cda'/><category scheme='http://www.blogger.com/atom/ns#' term='IPF'/><category scheme='http://www.blogger.com/atom/ns#' term='ihe'/><category scheme='http://www.blogger.com/atom/ns#' term='camel'/><category scheme='http://www.blogger.com/atom/ns#' term='ccd'/><title type='text'>IPF 1.7.0 released</title><content type='html'>I'm pleased to announce the release of &lt;a href="http://repo.openehealth.org/confluence/display/ipf/Home"&gt;IPF 1.7.0&lt;/a&gt;. The main focus of this release was support for clinical standards, in particular the &lt;a href="http://repo.openehealth.org/confluence/display/ipf/IHE+support"&gt;IHE profiles&lt;/a&gt;&lt;a href="http://repo.openehealth.org/confluence/display/ipf/IHE+support"&gt; XDS.a, XDS.b, PIX, PDQ&lt;/a&gt; and &lt;a href="http://repo.openehealth.org/confluence/display/ipf/CDA+support"&gt;support for the clinical document architecture (CDA) and the Continuity of Care Document (CCD) content profile&lt;/a&gt;. The release notes are &lt;a href="http://repo.openehealth.org/confluence/display/ipf/IPF+1.7.0"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;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&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;from('xds-iti18:myIti18Service')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.to('xds-iti18://somehost:8080/myWebApp/services/myIti18Service')&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;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 &lt;a href="http://repo.openehealth.org/confluence/display/ipf/IHE+support#IHEsupport-Quickreference"&gt;IHE quick reference&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;Here's an excerpt of new IPF 1.7.0 features added since 1.6.0&lt;br /&gt;&lt;br /&gt;* &lt;a href="http://repo.openehealth.org/confluence/display/ipf/IHE+support"&gt;IHE support&lt;/a&gt;&lt;br /&gt;** IHE XDS.a+b transactions (ITI 14-18, 41-43)&lt;br /&gt;** IHE PIX transactions (ITI 8-10)&lt;br /&gt;** IHE PDQ transactions (ITI 21-22)&lt;br /&gt;** IHE ATNA for all the above transactions&lt;br /&gt;* &lt;a href="http://repo.openehealth.org/confluence/display/ipf/CDA+support"&gt;CDA support&lt;/a&gt;&lt;br /&gt;** Generic CDA support&lt;br /&gt;** CCD profile support&lt;br /&gt;* Advanced XML processing&lt;br /&gt;** &lt;a href="http://repo.openehealth.org/confluence/display/ipf/Core+features#Corefeatures-TransmogrifierImpls"&gt;Caching XSLT transmogrifier&lt;/a&gt;&lt;br /&gt;** &lt;a href="http://repo.openehealth.org/confluence/display/ipf/Core+features#Corefeatures-Validator"&gt;Schematron validator&lt;/a&gt;&lt;br /&gt;* &lt;a href="http://repo.openehealth.org/confluence/display/ipf/XDS+repository"&gt;Detailed XDS tutorial&lt;/a&gt;&lt;br /&gt;* &lt;a href="http://repo.openehealth.org/confluence/display/ipf/Performance+measurement"&gt;Performance measurement support&lt;/a&gt;&lt;br /&gt;* &lt;a href="http://repo.openehealth.org/confluence/display/ipf/Flow+removal"&gt;Scheduled flow management database cleanup&lt;/a&gt;&lt;br /&gt;* ...&lt;br /&gt;&lt;br /&gt;IPF 1.7.0 is based on Camel 1.6. In parallel, a Camel 2.0-based version is developed on the &lt;a href="http://repo.openehealth.org/confluence/display/ipf2/Home"&gt;IPF 2.0&lt;/a&gt; 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).&lt;br /&gt;&lt;br /&gt;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 &lt;a href="http://gforge.openehealth.org/gf/project/ipf-tools/"&gt;developed&lt;/a&gt; and documented in a separate &lt;a href="http://repo.openehealth.org/confluence/display/ipftools/Home"&gt;IPF Tools&lt;/a&gt; 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.&lt;br /&gt;&lt;br /&gt;Many thanks to the whole development team and contributors for their excellent and high-quality work!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2708349453904691513-6970374852082002100?l=krasserm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://krasserm.blogspot.com/feeds/6970374852082002100/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://krasserm.blogspot.com/2009/10/ipf-170-released.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/6970374852082002100'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/6970374852082002100'/><link rel='alternate' type='text/html' href='http://krasserm.blogspot.com/2009/10/ipf-170-released.html' title='IPF 1.7.0 released'/><author><name>Martin Krasser</name><uri>http://www.blogger.com/profile/11765963540395771125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://4.bp.blogspot.com/_LrEpKPgi9gI/TI-WeznHzsI/AAAAAAAAACM/FO3hdlxwrdI/S220/Bild006a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2708349453904691513.post-1159900974353850344</id><published>2009-09-23T07:29:00.006+02:00</published><updated>2009-09-23T08:00:18.670+02:00</updated><title type='text'>New release of JSR 311 plugin for Grails</title><content type='html'>It's about two weeks ago that the latest version (0.2) of the &lt;a href="http://code.google.com/p/grails-jaxrs/"&gt;JSR 311 plugin for Grails&lt;/a&gt; (grails-jaxrs) has been released. In contrast to the &lt;a href="http://krasserm.blogspot.com/2009/07/jsr-311-plugin-for-grails.html"&gt;first release&lt;/a&gt; (0.1) , which was mainly a proof-of-concept, this new release focused, among other things, on a closer Grails integration. In particular&lt;br /&gt;&lt;ul&gt;&lt;li&gt;JAX-RS classes like &lt;a href="http://code.google.com/p/grails-jaxrs/wiki/GettingStarted#Create_a_resource"&gt;resource classes&lt;/a&gt; and &lt;a href="http://code.google.com/p/grails-jaxrs/wiki/AdvancedFeatures#Entity_providers"&gt;entity providers&lt;/a&gt; are now auto-detected by the plugin. There's no need any more to add them to the Spring application context manually.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;JAX-RS classes managed by the plugin can be changed at runtime in development mode. Code changes are detected by the plugin and reloaded in the same way as Grails controllers or services are.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Services and other Spring beans are &lt;a href="http://code.google.com/p/grails-jaxrs/wiki/AdvancedFeatures#Service_injection"&gt;auto-injected by-name&lt;/a&gt; into JAX-RS resources and providers.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;The plugin also extends Grails' command-line interface for &lt;a href="http://code.google.com/p/grails-jaxrs/wiki/GettingStarted#Create_a_resource"&gt;creating JAX-RS resources from scratch&lt;/a&gt; as well as&lt;a href="http://code.google.com/p/grails-jaxrs/wiki/AdvancedFeatures#Scaffolding"&gt; generating JAX-RS resources from existing domain objects&lt;/a&gt; (scaffolding). With scaffolding RESTful service interfaces can be auto-generated for individual domain objects (still early-access).&lt;/li&gt;&lt;/ul&gt;Antoher enhancement in this version is support for &lt;a href="http://code.google.com/p/grails-jaxrs/wiki/AdvancedFeatures#Google_App_Engine"&gt;deployments on the Google App Engine&lt;/a&gt; (GAE). This required to support &lt;a href="http://www.restlet.org/"&gt;Restlet&lt;/a&gt; as JAX-RS implementation in addition to &lt;a href="http://jersey.dev.java.net/"&gt;Jersey&lt;/a&gt;. In contrast to Jersey, Restlet can be deployed to GAE and since version 2.0-m4 &lt;a href="http://restlet.tigris.org/issues/show_bug.cgi?id=818"&gt;its JAX-RS extension as well&lt;/a&gt;. For a running &lt;a href="http://code.google.com/p/grails-jaxrs/wiki/AdvancedFeatures#Google_App_Engine"&gt;example&lt;/a&gt; go to &lt;a href="http://grails-jaxrs.appspot.com/test?name=World"&gt;http://grails-jaxrs.appspot.com/test?name=World&lt;/a&gt;. Please note that initializing Grails applications on GAE can take very long (up tp 30 seconds) at the moment. Subsequent requests are served much faster, of course.&lt;br /&gt;&lt;br /&gt;Also the documentation has been and extended and completely revised. The easiest way to get started with the plugin is the &lt;a href="http://code.google.com/p/grails-jaxrs/wiki/GettingStarted"&gt;Getting Started&lt;/a&gt; guide.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2708349453904691513-1159900974353850344?l=krasserm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://krasserm.blogspot.com/feeds/1159900974353850344/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://krasserm.blogspot.com/2009/09/its-about-two-weeks-ago-that-latest.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/1159900974353850344'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/1159900974353850344'/><link rel='alternate' type='text/html' href='http://krasserm.blogspot.com/2009/09/its-about-two-weeks-ago-that-latest.html' title='New release of JSR 311 plugin for Grails'/><author><name>Martin Krasser</name><uri>http://www.blogger.com/profile/11765963540395771125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://4.bp.blogspot.com/_LrEpKPgi9gI/TI-WeznHzsI/AAAAAAAAACM/FO3hdlxwrdI/S220/Bild006a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2708349453904691513.post-893486487085392643</id><published>2009-07-08T10:45:00.005+02:00</published><updated>2011-04-13T20:20:40.844+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='REST'/><category scheme='http://www.blogger.com/atom/ns#' term='jersey'/><category scheme='http://www.blogger.com/atom/ns#' term='grails'/><category scheme='http://www.blogger.com/atom/ns#' term='jaxrs'/><category scheme='http://www.blogger.com/atom/ns#' term='JSR 311'/><title type='text'>JSR 311 plugin for Grails</title><content type='html'>Project homepage: &lt;a href="http://code.google.com/p/grails-jaxrs/"&gt;grails-jaxrs&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Recently, I wanted to make a full two-weeks mountain bike tour through the Alps but bad weather on a few days caused me to make detours on the less rocky roads of &lt;a href="http://jcp.org/en/jsr/detail?id=311"&gt;JSR 311&lt;/a&gt; (JAX-RS: The Java API for RESTful Web Services). I took the chance reading the spec, did some hacking with &lt;a href="https://jersey.dev.java.net/"&gt;Jersey&lt;/a&gt; and I must really say I like to work with it. I liked it so much that I started to use it inside &lt;a href="http://www.grails.org/"&gt;Grails&lt;/a&gt; to combine it with features such as &lt;a href="http://grails.org/doc/1.1.1/guide/5.%20Object%20Relational%20Mapping%20%28GORM%29.html"&gt;GORM&lt;/a&gt; and &lt;a href="http://grails.org/doc/1.1.1/guide/6.%20The%20Web%20Layer.html#6.1.7%20XML%20and%20JSON%20Responses"&gt;XML and JSON marshalling&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;From my experiments I factored out what I think is reusable into a Grails plugin named &lt;a href="http://code.google.com/p/grails-jaxrs/"&gt;grails-jaxrs&lt;/a&gt; and made it open source. The plugin takes care of initializing Jersey inside a Grails application, implements a controller that does the dispatch to Jersey and provides some Grails-specific entity provider implementations.&lt;br /&gt;&lt;br /&gt;Here's a very simple example of a resource class that represents a collection of notes and that makes use of Grails object relational mapping (GORM) and XML marshaling:&lt;br /&gt;&lt;pre class="brush:groovy"&gt;&lt;br /&gt;import grails.converters.*&lt;br /&gt;&lt;br /&gt;import javax.ws.rs.Consumes&lt;br /&gt;import javax.ws.rs.GET&lt;br /&gt;import javax.ws.rs.Path&lt;br /&gt;import javax.ws.rs.PathParam&lt;br /&gt;import javax.ws.rs.POST&lt;br /&gt;import javax.ws.rs.Produces&lt;br /&gt;import javax.ws.rs.core.Response&lt;br /&gt;import javax.ws.rs.core.UriBuilder&lt;br /&gt;&lt;br /&gt;@Path('/notes')&lt;br /&gt;class NotesResource {&lt;br /&gt;&lt;br /&gt;   @POST&lt;br /&gt;   @Consumes('text/plain')&lt;br /&gt;   @Produces('text/xml')&lt;br /&gt;   Response addNote(String text) {&lt;br /&gt;&lt;br /&gt;       // Create new Note object and store save it to DB&lt;br /&gt;       def note = new Note(text:text).save()&lt;br /&gt;     &lt;br /&gt;       // Construct the URI for the newly created note&lt;br /&gt;       URI uri = UriBuilder.fromPath(note.id as String).build()&lt;br /&gt;     &lt;br /&gt;       // Return an XML representation of the note object&lt;br /&gt;       // along with a Location response header with the URI&lt;br /&gt;       Response.created(uri).entity(note as XML).build()&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   @GET&lt;br /&gt;   @Produces('text/xml')&lt;br /&gt;   Response getNotes() {&lt;br /&gt;&lt;br /&gt;       // Find all notes in the database and return&lt;br /&gt;       // an XML representation of the note list&lt;br /&gt;       Response.ok(Note.findAll() as XML).build()&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;A note is an object that contains some text. Notes are instances of the &lt;span style="font-family:courier new;"&gt;Note&lt;/span&gt; Grails domain class. A collection of notes are made available through a RESTful service interface using the above &lt;span style="font-family:courier new;"&gt;NotesResource&lt;/span&gt; class and the &lt;a href="http://code.google.com/p/grails-jaxrs/"&gt;grails-jaxrs&lt;/a&gt; plugin. A POST to &lt;span style="font-family:courier new;"&gt;http://host:port/notes/&lt;/span&gt; creates a new note. A GET to &lt;span style="font-family:courier new;"&gt;http://host:port/notes&lt;/span&gt; returns an XML repsresentation of all existing notes in the database. For more details refer to the &lt;a href="http://code.google.com/p/grails-jaxrs/wiki/GettingStarted"&gt;getting started tutorial&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2708349453904691513-893486487085392643?l=krasserm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://krasserm.blogspot.com/feeds/893486487085392643/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://krasserm.blogspot.com/2009/07/jsr-311-plugin-for-grails.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/893486487085392643'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/893486487085392643'/><link rel='alternate' type='text/html' href='http://krasserm.blogspot.com/2009/07/jsr-311-plugin-for-grails.html' title='JSR 311 plugin for Grails'/><author><name>Martin Krasser</name><uri>http://www.blogger.com/profile/11765963540395771125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://4.bp.blogspot.com/_LrEpKPgi9gI/TI-WeznHzsI/AAAAAAAAACM/FO3hdlxwrdI/S220/Bild006a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2708349453904691513.post-5233494456521446629</id><published>2009-05-24T10:43:00.003+02:00</published><updated>2009-05-24T11:14:19.062+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='IPF'/><title type='text'>Moving towards IPF 1.7</title><content type='html'>Work on the next &lt;a href="http://gforge.openehealth.org/gf/project/ipf/"&gt;IPF&lt;/a&gt; release is in progress and focuses on&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Components for implementing &lt;a href="http://www.ihe.net/"&gt;IHE&lt;/a&gt; actor interfaces (XDS.a, XDS.b, PIX, PDQ). Implementing IHE actor interfaces will be as simple as using other Camel components for communication (e.g. the HTTP component). IPF IHE components represent transactions in &lt;a href="http://www.ihe.net/profiles/index.cfm"&gt;IHE profiles&lt;/a&gt;. For example, to create a web service for the server-side of the ITI-41 transaction (provide and register document set) from the XDS.b profile just write &lt;span style="font-family:courier new;"&gt;from('xdsb-iti41:service1')&lt;/span&gt; in your route definition. &lt;span style="font-family:courier new;"&gt;xdsb-iti41&lt;/span&gt; is the name of the component, &lt;span style="font-family:courier new;"&gt;service1&lt;/span&gt; the endpoint name. The rest of the route has to deal with connecting to (proprietary) backend systems that implement the corresponding actor functionality (document registry/repository). For more detailed information refer to &lt;a href="http://architects.dzone.com/articles/introduction-open-ehealth"&gt;this article&lt;/a&gt; (section &lt;a href="http://architects.dzone.com/articles/introduction-open-ehealth?page=0,3"&gt;Outlook&lt;/a&gt;).  &lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;DSL (Groovy builder) for creating &lt;a href="http://en.wikipedia.org/wiki/Clinical_Document_Architecture"&gt;CDA&lt;/a&gt; documents. This DSL supports the creation of structurally correct CDA documents by enforcing CDA-relevant schema definitions but without dealing with low-level XML details. See also &lt;a href="http://architects.dzone.com/articles/introduction-open-ehealth?page=0,3"&gt;outlook on IPF's CDA support&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Extension of OSGi support. Not all features of IPF have been fully &lt;a href="http://repo.openehealth.org/confluence/display/ipf/OSGi+support"&gt;OSGi-enabled&lt;/a&gt; with release 1.6, like the large binary support or the event infrastructure. This will be fixed with IPF 1.7. You'll also be able to use the new IHE components on OSGi platforms. We also plan to extend existing Camel components to make use of standard OSGi services such as the HTTP service.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Better IDE (Eclipse) integration, especially for developing IPF OSGi applications. This includes application development and packaging with Eclipse PDE tools and providing an Eclipse update site for downloading the IPF runtime. Code completion for DSL extensions is currently under discussion.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Performance testing framework. DSL extensions to performance-measure IPF applications including calculation and reporting of message processing statistics during load tests. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;In parallel we will also create a SVN branch for experimenting with Camel 2.0 milestone releases. I'll let you know about our upgrade/migration experiences in a separate blog post.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2708349453904691513-5233494456521446629?l=krasserm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://krasserm.blogspot.com/feeds/5233494456521446629/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://krasserm.blogspot.com/2009/05/moving-towards-ipf-17.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/5233494456521446629'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/5233494456521446629'/><link rel='alternate' type='text/html' href='http://krasserm.blogspot.com/2009/05/moving-towards-ipf-17.html' title='Moving towards IPF 1.7'/><author><name>Martin Krasser</name><uri>http://www.blogger.com/profile/11765963540395771125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://4.bp.blogspot.com/_LrEpKPgi9gI/TI-WeznHzsI/AAAAAAAAACM/FO3hdlxwrdI/S220/Bild006a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2708349453904691513.post-8058158128843406402</id><published>2009-04-13T17:55:00.001+02:00</published><updated>2009-04-13T18:01:33.335+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='IPF'/><title type='text'>Open eHealth Integration Platform 1.6.0 released</title><content type='html'>Last week we've released the&lt;a href="http://gforge.openehealth.org/gf/project/ipf/"&gt; Open eHealth Integration Platform&lt;/a&gt; (IPF) version 1.6.0. IPF is an extension of the &lt;a href="http://camel.apache.org/"&gt;Apache Camel&lt;/a&gt; routing and mediation engine. It has an application programming layer based on the &lt;a href="http://groovy.codehaus.org/"&gt;Groovy&lt;/a&gt; programming language and comes with comprehensive support for message processing and connecting systems in the eHealth domain. Please see the &lt;a href="http://repo.openehealth.org/confluence/display/ipf/IPF+1.6.0"&gt;release notes&lt;/a&gt; for further details.&lt;br /&gt;&lt;br /&gt;Give it a try! We welcome your feedback!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2708349453904691513-8058158128843406402?l=krasserm.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://krasserm.blogspot.com/feeds/8058158128843406402/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://krasserm.blogspot.com/2009/04/open-ehealth-integration-platform-160.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/8058158128843406402'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2708349453904691513/posts/default/8058158128843406402'/><link rel='alternate' type='text/html' href='http://krasserm.blogspot.com/2009/04/open-ehealth-integration-platform-160.html' title='Open eHealth Integration Platform 1.6.0 released'/><author><name>Martin Krasser</name><uri>http://www.blogger.com/profile/11765963540395771125</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='30' height='32' src='http://4.bp.blogspot.com/_LrEpKPgi9gI/TI-WeznHzsI/AAAAAAAAACM/FO3hdlxwrdI/S220/Bild006a.jpg'/></author><thr:total>0</thr:total></entry></feed>
