Showing posts with label camel. Show all posts
Showing posts with label camel. Show all posts

Monday, July 25, 2011

Grails, Camel and Hibernate session

It's been a while since I thought about manually opening Hibernate sessions to do some work on the database. The usual thing is simply to call one of the GORM methods like get() or save() and have the framework tackle all the bits and pieces regarding low-level Hibernate usage for me.

From time to time however it is important to have a high-level understanding of what's going on behind the scenes. One example of that is saving entities in services utilized as part of Camel routes. But let's start from the beginning...

In Grails opening Hibernate session is handled by a Spring class called OpenSessionInViewFilter. This is a filter that opens a Hibernate session before anything else is happening and closes it after the processing is done. With this filter in place a Hibernate session is available throughout the whole request cycle.

When doing processing in Camel we're in a separate thread completely outside the normal Grails request processing so there's nothing there to open the Hibernate session for us. As a side note one needs to remember that the same happens in pretty much every case where a separate thread is fired to do some processing. In all those cases Hibernate session is not available.

But I still want to use GORM in those places! How can I open a session manually?

Well, that's the easiest thing ever. GORM-managed entities expose a method called withNewSession that takes a closure with one parameter (the newly created session) and life is good again.
To make this more common I'll give you two other examples of such a method: withTransaction and withSession. The first one fires of a new transaction and closes it after the processing is done and the second one is kind of a utility that allows you to access the currently active Hibernate session if you find yourself in need doing so.

I hope this will save someone some time :)

Friday, July 22, 2011

Grails, routing plugin and GORM

I's been brought to my attention today that it is possible that Camel routes start sooner than some of the other services in Grails (GORM in particular). This leads to issues like missing methods in domain classes. To get around this problem you can do as follows:

In your route definition add the .noAutoStartup() part like this:
from('direct:foo').routeId('myRoute').noAutoStartup()....
In BootStrap.groovy's init closure add the following code:
import org.codehaus.groovy.grails.web.context.*
[...]
def ctx = ServletContextHolder.servletContext.getAttribute(GrailsApplicationAttributes.APPLICATION_CONTEXT)
ctx.camelContext.startRoute('myRoute')
This will give you the possibility to start and even stop a route anytime you want.

You can read more on this topic on fusesource.com.

I hope this will help someone :)

Tuesday, July 19, 2011

Grails routing 1.1.3 released!

I'm happy to announce the immediate availability of the routing and routing-jms plugins. The major theme for this release is hot reloading of Camel inner-workings when service classes are changed.

So.. well... it works. For the most part at least. It wasn't easy but let's examine the changes and new capabilities one step at a time.

Apache Camel.

In Apache Camel there's no obvious way to force the routes to re-get the bean from Spring context. An endpoint caches an instance of BeanProcessor that's created with ConstantBeanInfo instance and that's pretty much it.
Thankfully the BeanProcessor instance is not final and is lazy initialized so if you force it to be null by calling setProcessor(null) the next time the endpoint is called it needs to re-create the processor and all is good. It's a pity no one thought of a "forceReinitialize" method in Camel but this way works too.

Grails.

In Grails it is pretty much standard that you are allowed to overwrite the existing instance of a service class with a new implementation. This mechanism is sort of baked in into the core.
However when reloading services that are marked as transactional there's some AOP going on with cglib and caching that I couldn't quite crack so those kind of services when reloaded will produce an exception that says "SomeService cannot be cast to SomeService" or something of this sort. I'll have to get back to it some day and figure out if this is a general problem with Grails or if it is something I'm missing in my onChange handler. For now if you need your method to participate in transaction you'll have to manually call the withTransaction { } helper.

Bottom line.

The bottom line is that you finally can use the routing plugin to do normal Grails development and it should catch you with no surprise (other than the transactional services...). Go and give it a shot. Let me know if it works for you!

Happy Cameling!

Grails routing plugin - report from the battlefield

Just wanted to let you all know that I've resumed work on improving the routing plugin for Grails. There's already version 1.1.2 that introduces a new method added to controllers, services and (if Quartz plugin is installed) jobs that allows you to send messages with headers.

The next task however isn't simple and will take some time. It's the long standing problem with Camel routes that target beans that are reloaded.

Will see where this will lead me.

Saturday, January 8, 2011

Grails, Camel and adding routes at runtime

Since it's been of some interest on the net to figure out how to add routes at runtime to Camel provided by the grails-routing plugin here's an example of how it might be implemented:
import org.apache.camel.builder.*
import org.apache.camel.model.*

class HomeController {
// 1
def camelContext

def index = {
// 2
println camelContext.routes.size()
// 3
if (camelContext.routes.size() == 0)
// 4
camelContext.addRouteDefinitions(
new MyRouteBuilder().routeDefinitions
)
render text: camelContext.routes.size().toString(), contentType: "text/plain"
}

def send = {
// 5
sendMessage("seda:input", "Hello, world! from dynamically added rotue")
render text: "sent", contentType: "text/plain"
}
}

// 6
class MyRouteBuilder extends RouteBuilder {
// need to override this to make RouteBuilder inheritance happy
void configure() { 
} 

// generate a new route
List getRouteDefinitions() {
[ from("seda:input").to("stream:out") ]
}
}

1 - Make the CamelContext instance available


the def camelContext makes the bean of class CamelContext available for us in this controller

2 - Debugging


For debugging purposes we're printing out to console how many routes are defined. The first time it will print 0 as there are no routes defined yet.

3 - Check if the route has already been added


We don't want to add the same route over and over again, right? :)

4 - Adding a new route


Using an instance of MyRouteBuilder get a new route definition and stuff it into the current set of routes.

5 - The send action


In this action we'll test the newly created route to see if it works

As you can see the only odd thing is that MyRouteBuilder doesn't do anything in configure since it's not required. We're inheriting from RouteBuilder only to have access to specific DSL methods (like the from one in this example).

To try it out make sure you have no other routes defined in your application, fire up the /home/index and note the number of routes printed out to console and displayed on the page. The first one should read 0 and the second one (since it's evaluated after the new route has been added) should read 1.
Then navigate to /home/send and observe in console a nice message received on seda:input and forwarded to stream:out

EDIT on 21 January 2012

There's a better way of doing this sort of things that works with all kind of routes:
def index = {
    if (camelContext.routes.size() == 0) {
        camelContext.addRoutes(new RouteBuilder() {
            @Override void configure() {
                from("seda:input")
                    .filter({ it.in.body.contains('from') })
                    .to("stream:out")
            }
        });
    }
    render text: camelContext.routes.size().toString(), contentType: "text/plain"
}


Hope this will help :)

Tuesday, December 14, 2010

Grails Routing plugin released!

Hi all,

Today I've released the first version of grails-routing plugin. It's a modernized version of the original grails-camel plugin by Chris Navta with some extras included.

First of all, if you plan to target Apache Camel 1.6.x this plugin is no good for you as it works only with 2.4.0. It's been ages since 1.6 was released and the original author did not express interest in providing an update.

Secondly there are 2 exciting features included:

- integration with grails-quartz plugin to allow jobs to send messages
- integration with Ivy to download all the necessary dependencies

As I am not leaving my audience without ready-to-use examples (by definition) you'll also find 3 of those:

- basic usage example
- Quartz plugin integration example
- ActiveMQ usage example

I hope it'll serve you well!