groovy singleton pattern - groovy

Q1. What is the best way to implement the singleton pattern using groovy? What are the other options available in groovy to support the singleton mechanism?
Any example that would be useful.
Q2. Does groovy support something like File changed listener?

Q1
You can make any class a singleton simply by adding a #Singleton annotation (since groovy v1.7.0 at least):
#Singleton
class MyClass {
}
You can then access the singleton instance with
MyClass singleton = MyClass.instance
Q2
I think you're asking if Groovy provides a listener which is called every time a file is changed? I am not aware of any such facility in Groovy. If such a class exists you're more likely to find a Java implementation (which you could use in your Groovy program).

Regarding Q2: while groovy itself doesn't provide any way to be notified on file changes, Java 7, which can be used with groovy, does.
In particular, if you want to watch for file changes on a file foo in the current directory, you can do something like this:
import java.nio.file.*
FileSystems.default.getPath(".") // dot for current directory
def watchKey = p.register(FileSystems.default.newWatchService(),
StandardWatchEventKinds.ENTRY_MODIFY)
def events = watchKey.pollEvents()
events.findAll{it.context().fileName == 'foo'}.each { event ->
println "foo was changed"
}

Related

How to declare a constructor or extends a class of a groovy script?

I am working on a shared library for Jenkins, and I want to access some utilities methods between some classes, but not all of them, thus I have established some statements:
I would like to avoid using static methods, since it does not access pipeline steps directly, and passing the pipeline instance every call would be a pain;
I would like to avoid a singleton as well, or prefixing every method call with the util class' instance;
Since it is not supposed to be shared between all classes I would like to avoid putting every method as a file on vars/ special directory, but I would like a similar behavior;
Despite extending the class would be a anti-pattern, it would be acceptable, though I would like to avoid the verbose Java syntax for declaring the class the same name as the file, once it is implicit in groovy;
This question does solve my problem partially, although there are issues with serialization, I noted that when I use checkpoint and some build is resumed from some stage, the instance loses all extra methods.
This other question would have helped me fix the serialization issue, however the author seems the have solved the root cause of his problem using a way that is not the original question titled for.
Is there a way to extends a implicit script class in groovy without using the class NameOfFile extends SomeOtherClass { put every thing inside this block } syntax? And without working with inner-class?
Or else, is there a way to declare a constructor using the script groovy syntax analogue as the previous question?
Or even, is there a way to change the serialization behavior to install the extra methods again after unserializing?
Appendix
The script syntax works more-or-less like this:
Consider the content of file src/cicd/pipeline/SomePipeline.groovy:
package cicd.pipeline
// there is no need to wrap everything inside class SomePipeline,
// since it is implicit
def method() {
// instance method, here I can access pipeline steps freely
}
def static otherMethod() {
// static method, here it is unable to access pipeline steps
// without a instance
}
#groovy.transform.Field
def field
def call() {
// if the class is used as method it will run
this.method()
SomePipeline.otherMethod() // or simply otherMethod() should work
this.field = 'foo'
println "this instance ${this.getClass().canonicalName} should be cicd.pipeline.SomePipeline"
}
// any code other than methods or variables with #Field
// annotation will be inside a implicit run method that is
// triggered likewise main method but isn't a static one
def localVar = 'foo'
println "It will not execute on constructor since it is on run: $localVar"
println "Method: ${org.codehaus.groovy.runtime.StackTraceUtils.sanitize(new Throwable()).stackTrace[0].methodName}"
println "this instance ${this.getClass().canonicalName} should be cicd.pipeline.SomePipeline"
If I was going to use the Java verbose syntax I would have to wrap almost everything inside a class SomePipeline which is implicit in groovy, this is the script syntax I want to keep.
I realised that this.getClass().superclass.canonicalName when outside Jenkins pipeline is groovy.lang.Script and when inside pipeline is org.jenkinsci.plugins.workflow.cps.CpsScript and based on this resource I was able to elaborate the following solution:
abstract class CustomScript extends org.jenkinsci.plugins.workflow.cps.CpsScript {
public CustomScript() {
// do something here, it will always execute regardless
// serialization, and before everything
}
}
#groovy.transform.BaseScript CustomScript baseScript
That is it, worked as expected! Of course you can elaborate this solution better in order to reduce repeating and avoid inner-classes, but I will leave it for your imagination.

Populate List<Callable<String>> in Groovy with Groovy objects

In What JVM-based scripting language support #WebService to create services at runtime? I was suggested to use Groovy to provide web services configured in a script read in at runtime.
To make this work with our existing infrastructure I need essentially to be able to add new entries to a List<Callable<String>> which I then can ask an executor to invokeAny upon.
The basic structure will be something like:
Groovy is embedded using GroovyScriptEngine
Initial list passed in from Java as "l" in the Binding passed in.
Groovy script defines and instantiates N objects, all implementing Callable<String> and add them to the list.
Back in Java the list is then further processed and then passed to the executor.
My initial feeble steps show that I will most likely need to use def c = { ... } as Callable<String> but then I get a ClassCastException. Reading up I see that it appears that this is a bit hard and involves closures.
What is the correct way to define and instantiate an object in Groovy which implements Callable<String>?
In Groovy 1.8 and later, groovy.lang.Closure implements Callable by default so you don't need any "as" magic., simply:
l << { "hello" }
l << { "world" }
For earlier versions of Groovy (1.6 and 1.7 certainly, not sure about "ancient" versions) you need to use as:
import java.util.concurrent.Callable
l << ({ "hello" } as Callable)

Is there any way to use groovy and java code for the same class?

I mainly program in groovy, but occasionally it's too slow. So I write a separate .java class, and put the code that needs to run faster in a java method and call that java method from my groovy code.
This causes me to end up with two separate files and two separate classes. Is there any way I could embed a java method right into the groovy file, maybe marking it with an annotation to indicate that it is java?
This is the idea behind groovy++. Marking a class or method with the #Typed annotation will cause it to use static typing instead of dynamic typing, while still retaining a lot of goodness of groovy.
While not exactly java, typed groovy++ methods generally perform about the same as java would.
More information on groovy++ is available at: https://code.google.com/p/groovypptest/wiki/Welcome
You don't need to do anything special.
Just write the Java class behind the groovy class. 99% of all Java source is valid groovy source as well.
class GroovyClass {
def a;
def doSomething(x,y) { return x*y; }
}
class JavaClass {
SomeType someVar;
public JavaClass() { /* ... */ } // some contructor
public void doit(String a, int b) {} // full typed method, that is java
}
Groovy++ is somethign completely different.
The JavaClass needs to have everything fully typed to be "Java" however your problem can be solved far easyer if you just use types in the relevant groovy methods.
class AnotherGroovyClass {
// typed
public Result someMethod(SomeArg arg1, SomeOtherArg arg2) {
}
def someVariable; // untyped
}
If you think the lack of speed comes from the dynamic nature of groovy then just use full types at the relevant points.

cast closure map to object with a private constructor in groovy

I am using groovy to create some mock classes for a test case. I am basically creating dummy objects where all the methods return null so that i can run my testcase.
I am using the following syntax:
MessageFactory.instance = ["getMessage": {a,b,c,d -> "dummy"}] as MessageFactory
So here i am trying to overwrite the singleton instance with my on fake factory object. The problem is that MessageFactory's constructor happens to be a private method. This gives me an illigal access exception when i run the code above. Is there a away i can create a proxy in groovy and overcome the private constructor issue?
If you have access to the MessageFactory, and are willing to modify it, then you use the standard dependency-injection solution, as detailed here: mock singleton
..Though it's not particularly Groovy.
Otherwise, the best workaround I've found is to override the method(s) on the singleton instance itself, like so:
#Singleton
class Test{
def method(){"Unmocked method called"}
}
def test = Test.instance
test.metaClass.method = {-> null}
test.method() // Now returns null
Naturally, as a singleton, this instance doesn't change (at least in theory)... So, overriding methods in this manner is effectively global.
Edit: Or you can use GMock, which supports constructor mocking (among other things).

Is it possible to automatically preload user classes into the groovy interpreter?

Is there any way to automatically load user classes in the groovy interpreter, the way System.out is automatically loaded (so you don't have to import System.out to use println)? I want to be able to write scripts that employ custom classes and run the scripts in the groovy interpreter without having to import all the classes all the time.
Yep, you just need to create a profile/rc file. Just create a file at ~/.groovy/groovysh.profile and put your imports in there. You'll also want to make sure that any additional classes you want to include are part of your CLASSPATH.
ex: ~/.groovy/groovysh.profile:
import org.apache.commons.lang.StringUtils
println "in groovysh.profile"
Then run groovysh and use a method from StringUtils:
% groovysh
in groovysh.profile
Groovy Shell (1.7.3, JVM: 1.6.0_20)
Type 'help' or '\h' for help.
---------------------------------------------------------------------------------------------------------------------------------
groovy:000> StringUtils.isWhitespace(" ")
===> true
groovy:000>
You can see that the import is in place (and that it also printed out the println I had in the profile. This example will only work if you've got the commons-lang jar file is in your classpath.
See the Groovy Shell page for more details.
Groovy adds some methods to Object, including methods like println and printf that you'd expect on printWriters. They implicitly use System.out. This is actually how groovy makes if feel like System.out is globally available.
If you want to import a set of classes by default, so they can be used without specifying the full package name, Ted's comment about groovysh.profile applies.
However, if you want a specific object, like System.out, global available so its methods can be called without referencing the object, then you can add some dynamic methods to Object. For example, to make the logging methods of the default global JDK logger globally available:
Object.metaClass.info = { String message ->
java.util.logging.Logger.global.info(message)
}
Object.metaClass.warning = { String message ->
java.util.logging.Logger.global.warning(message)
}
Object.metaClass.severe = { String message ->
java.util.logging.Logger.global.severe(message)
}
etc...
Once those methods are applied to the base Object metaClass, any object can call info("message") and have it logged, effectively making Logger.global available in the same way System.out is.

Resources