| At line 1 added 43 lines |
| RunnableInvoker is a really prime RSF [OLI], whose entire code looks as follows: |
|
| {{{ |
| public interface RunnableInvoker { |
| public void invokeRunnable(Runnable torun); |
| } |
| }}} |
|
| RunnableInvoker abstracts the work of executing a work unit - an existing package of work is supplied as a standard JDK {{Runnable}} which is then invoked on the stack frame of the implementor, possibly surrounded by pre-, post-, or bracketing logic. |
|
| This idea will be familiar to aficionados of [AOP], since it is really an equivalent (although a massively more "environmentally friendly" equivalent) of an AOP "execute around" advice. In [Chapter 6|http://www.springframework.org/docs/reference/aop.html] of the Spring manual, you can see examples of Spring AOP in action, in particular the "MethodInterceptor" type. Since RSF lives in a request-scope IoC world, the need to express arbitrary "kitchen-sink" interception with support for arbitrary parameters is much lower - rather than pass these values into the wrapping bean as arguments, it is far cleaner for it to fetch them itself as request-scope dependencies. |
|
| Here is an example illustrating this point from the RSF [LogonTest] sample: |
|
| {{{ |
| public class SecurityWrapper implements RunnableInvoker { |
| private ViewParameters viewparams; |
| private LogonBean logonbean; |
|
| public void setViewParameters(ViewParameters viewparams) { |
| this.viewparams = viewparams; |
| } |
|
| public void setLogonBean(LogonBean logonbean) { |
| this.logonbean = logonbean; |
| } |
|
| public void invokeRunnable(Runnable towrap) { |
| if (logonbean.name == null |
| && !(LogonProducer.VIEW_ID.equals(viewparams.viewID))) { |
| throw new SecurityException("Cannot view page " + viewparams.viewID |
| + " while not logged on"); |
| } |
| towrap.run(); |
| } |
| } |
| }}} |
|
| As we can see, all the inner context for the wrapper is injected in via the request-scope dependencies ViewParameters and LogonBean, and we can keep our clean "nullary interface" to the wrapper itself. |
|
| Ruby fans will also recognise the {{towrap.run();}} call as the equivalent of a zero-args {{yield}} call. What in Java requires a lot of reflective and AOP sweat (although in RSF, a bit less sweat), is simply part of the language in Ruby, with its powerful support for code-block arguments and "continuation" programming style. |
|
| RunnableInvoker replaced the slightly more verbose equivalent [RunnableWrapper] as of RSF 0.7. |