groovy-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Alain Stalder <astal...@span.ch>
Subject Re: [ANN] Jexler 2.0.0 / A somewhat unexpected Grengine use case
Date Wed, 20 May 2015 13:21:00 GMT
FYI, while porting Jexler from Java to Groovy I found a use
case for Grengine (http://grengine.ch/) that might be interesting
to some - not for running the Jexler Groovy scripts as services,
for that I use a normal GroovyClassLoader - but for scheduling
something using Quartz (http://quartz-scheduler.org).

The interface for a Job to schedule in Quarz is a bit strange,
maybe not without good reasons, but anyway: you have to
implement the Job interface with a class that has a no args
constructor and has a "void execute(def context)" method.
That makes it difficult to give the method some useful context
because only serializable objects can be provided there.

Instead I did this:

class SomeUtil {

     private static final Grengine gren = new Grengine()

     private static final String runnableWrappingJobScript = """\
         import groovy.transform.CompileStatic
         import org.quartz.*
         @CompileStatic
         class RunnableWrappingJob implements Job {
            public static Runnable runnable
           RunnableWrappingJob() {}
           void execute(JobExecutionContext context) throws 
JobExecutionException {
              runnable.run()
           }
         }
         """.stripIndent()

     static {
         gren.load(runnableWrappingJobScript)
     }

     static Class newJobClassForRunnable(Runnable runnable) {
         Class jobClass = (Class)gren.load(gren.newDetachedLoader(), 
runnableWrappingJobScript)
         jobClass.getDeclaredField('runnable').set(null, runnable)
         return jobClass
     }

}

This way, I can simply pass anything that implements runnable:

The way Grengine is used, each time someone requests a new Job class
for a given runnable, Grengine uses the already compiled bytecode and
loads the class from a new ClassLoader, and then via reflection the *static*
variable "runnable" is set...

(I you don't mind to compile each time, you could of course also use a
GroovyClassLoader here or redirect output to a class file and add that
to a second GroovyClassLoader, with a little more complexity).

In any case, since the solution with Grengine is quite lean, it might be
useful in other similar cases...?

Alain

On 20.05.15 15:05, Alain Stalder wrote:
> I wrote when announcing Jexler 1.0.6 a week ago:
> > "Jexler is a simple relaxed Java 7 framework for
> > starting/stopping Groovy scripts as services and
> > enabling them to react to events of their choice."
>
> Well, not any more! Now it's written 100% in Groovy:
>
> 2.0.0 (2015-05-20)
> * Jexler is now written in Groovy (unit tests with Spock),
>   no longer Java 7 (and JUnit).
> * Scheduling is now based on Quartz, no longer on Cron4j,
>   which allows now to schedule at shorter intervals
>   (seconds instead of minutes).
> * Various small changes and simplifications, which should
>   almost always have no effect on existing jexler scripts.
>
> Porting Jexler from Java to Groovy has been a lot of fun,
> things just got simpler...*
>
> Spock especially is fantastic, thanks for making it!
>
> Fascinating... ;)
>
> Alain
>
> * I am using Intellj IDEA - at least a year ago Groovy support
> in Eclipse was not good enough (yet?) so that I had cancelled
> a similar attempt back then... :(

PS: http://www.jexler.net/


Mime
View raw message