How to access registry from groovy DSL after inserting handlers

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

How to access registry from groovy DSL after inserting handlers

rwatts
Hi there!

We're working with ratpack 0.9.7-SNAPSHOT and are wondering the best way to render an object that has been processed after a linear, one after the other, set of handlers.

The way we currently use:

put('endpoint') {
     insert  new ThingInitializerHandler(),         // Sets up registry containing Thing
               new ThingWorkerHandler(),            // Works on Thing in the registry
               new ThingRenderHandler()             // calls render to Thing in the registry
}

I'm wondering if there's a way we can drop DisplayHandler and instead have something like:

put('endpoint') {
     insert  new ThingInitializerHandler(),        // Sets up registry containing Thing
               new ThingWorkerHandler()            // Works on Thing in the registry
     
     render json(registry.get(Thing))
}

I get an error complaining that the registry does not contain a Thing object.

How can I access Thing from the registry within the DSL?  Or have is there a better approach entirely?

Many thanks for awesome framework
Rob
Reply | Threaded
Open this post in threaded view
|

Re: How to access registry from groovy DSL after inserting handlers

Luke Daley
Administrator
Hi Robert,

Do the initializer and worker need to be handlers? They seem like candidates for services to me.

Your code is not working as you intend because the context registry is logically partitioned. It's a bit hard to mentally picture, but handlers are arranged in something like a graph, where the insert() method creates a new branch and starts travelling down it. Anything inserted into the registry from a branch is not visible to the parent branch. This is to prevent handlers being able to unintentionally affect unrelated handlers (i.e. the effects of a handler are tightly scoped).

To make a more concrete recommendation we’ll need to dig into the detail of what you are doing a bit more.
Reply | Threaded
Open this post in threaded view
|

Re: How to access registry from groovy DSL after inserting handlers

rwatts
Hi Luke,

The initialiser and worker could be services, for sure.  Although we were initially attracted to Ratpack because we could build a "pipeline" of handlers that worked on the context and added to it as it went on.  Those handlers could then be reused across other pipelines.   We construct Handlers with guava managed services to manage shared/common functionality.

What I think would be neat would be to have ratpack.groovy dsl manage all request/response HTTP and have the handlers just work on the registry.

This is one of our pipes:

put {
    insert  new CampaignInitializer(),   // Creates a "campaign" object from the request, adds to registry
    new Experimenter(experimentsApi, s3Helper), // Integrates with GA and adds links to campaign object
    new VariantRenderUploader(variantTemplater, s3Helper), // Creates HTML and uploads to s3
    new Persister(mongo), // saves campaign to mongdb
    new CampaignDisplayer() // renders campaign object
}

The Campaign object in the registry is created, worked on and added to, saved to mongo and finally rendered to request.  These handlers are re-used in different endpoints managing different workflows.

// Update: we can use inline groovy handlers by defining
put {
   insert new CampaignInitializer(),
       ...
       groovyHandler {
           render json(registry.get(Campaign)
       }
}

Although I still suspect our basic approach is not right.

Any feedback gratefully received!
Cheers, Rob
Reply | Threaded
Open this post in threaded view
|

Re: How to access registry from groovy DSL after inserting handlers

Luke Daley
Administrator
Looks like an interesting app. A couple of things…

If your first `put {}` example, you are creating new handler instances for each request. This should be avoided if possible because it often creates unnecessary objects, leading to object churn under load. You should aim to make handlers singletons. 

Once you start to get into handler composition, it’s worth looking at http://www.ratpack.io/manual/current/api/ratpack/handling/Handlers.html, which provides the building blocks of the DSL. If I understand your intent, you probably want to write something like…

import ratpack.handling.Handlers

handlers {

  handler(Handlers.path(“somePath”, Handler.chain(
    Handlers.put(),
    registry.get(CampaignInitializer),
    registry.get(Experimenter), // Integrates with GA and adds links to campaign object
    registry.get(VariantRenderUploader), // Creates HTML and uploads to s3
    registry.get(Persister), // saves campaign to mongdb
    registry.get(CampaignDisplayer) // renders campaign object
  )))
  
}

So here we are creating the handlers early (i.e. during app initialisation) and only creating one instance. We are also getting them from the chain registry (which if you are using the Groovy support is automatically backed by Guice) to allow Guice to dependency inject your handlers.

Another thing to consider is the role of the context registry vs. the request registry. 

The context registry is effectively for defining objects that represent certain handling strategies. For example: “for this part of the app, the error handler should be this”, or “for this part of the app, object of type X should be rendered like this”. Because it’s typically about strategy, it’s important to partition as mentioned in my previous post.

The request registry is about state (see that http://www.ratpack.io/manual/current/api/ratpack/http/Request.html implements http://www.ratpack.io/manual/current/api/ratpack/registry/MutableRegistry.html). 

So you probably want to be pushing your data objects into the request registry (via add()) instead of using the context registry. That should make things easier.

Reply | Threaded
Open this post in threaded view
|

Re: How to access registry from groovy DSL after inserting handlers

rwatts
Hi Luke,

Many thanks for this response, it really cleared some things up. We will implement all your suggestions.

Thanks again
Rob

On Wednesday, 30 July 2014, Luke Daley [via Ratpack Forum] <[hidden email]> wrote:
Looks like an interesting app. A couple of things…

If your first `put {}` example, you are creating new handler instances for each request. This should be avoided if possible because it often creates unnecessary objects, leading to object churn under load. You should aim to make handlers singletons. 

Once you start to get into handler composition, it’s worth looking at http://www.ratpack.io/manual/current/api/ratpack/handling/Handlers.html, which provides the building blocks of the DSL. If I understand your intent, you probably want to write something like…

import ratpack.handling.Handlers

handlers {

  handler(Handlers.path(“somePath”, Handler.chain(
    Handlers.put(),
    registry.get(CampaignInitializer),
    registry.get(Experimenter), // Integrates with GA and adds links to campaign object
    registry.get(VariantRenderUploader), // Creates HTML and uploads to s3
    registry.get(Persister), // saves campaign to mongdb
    registry.get(CampaignDisplayer) // renders campaign object
  )))
  
}

So here we are creating the handlers early (i.e. during app initialisation) and only creating one instance. We are also getting them from the chain registry (which if you are using the Groovy support is automatically backed by Guice) to allow Guice to dependency inject your handlers.

Another thing to consider is the role of the context registry vs. the request registry. 

The context registry is effectively for defining objects that represent certain handling strategies. For example: “for this part of the app, the error handler should be this”, or “for this part of the app, object of type X should be rendered like this”. Because it’s typically about strategy, it’s important to partition as mentioned in my previous post.


So you probably want to be pushing your data objects into the request registry (via add()) instead of using the context registry. That should make things easier.




If you reply to this email, your message will be added to the discussion below:
http://forum.ratpack.io/How-to-access-registry-from-groovy-DSL-after-inserting-handlers-tp558p567.html
To unsubscribe from How to access registry from groovy DSL after inserting handlers, click here.
NAML