Does groovy provide an include mechanism?
Asked Answered
R

7

7

We are searching for an include mechanism for groovy scripts to have space for cross-cutting-concerns.

In my example we have, web service endpoints as groovy scripts and want to log to our web service protocol. for that we use our implicit object (getting from our framework) to create the logging statement.

But this is boilerplate code if we code this in every web service endpoint.

We are searching for something like include() in php, that includes other groovy scripts, are there any ideas how to do this?

Resistive answered 12/8, 2009 at 7:24 Comment(0)
P
1

Since you already mentioned “cross-cutting-concerns” I’d say that you need to intercept your webservice calls AOP style (not an include mechanism).

Grails is completely integrated with Spring framework, so this makes for a good option for exploiting Spring AOP features. Take a look at this chapter from grails official guide: http://grails.org/doc/latest/guide/14.%20Grails%20and%20Spring.html and search for word AOP.

Maybe there is a purely groovy way of doing AOP, but I'd go with grails and spring.

Proteus answered 12/8, 2009 at 17:39 Comment(0)
D
10

Groovy treats its files as objects (think of it as of automatic wrapping). And it makes all .groovy files within the java classpath available as classes. So if you have the file util.groovy, that contains something like this inside:

def static AuxMethod() {
    return "Hello World"
}

To call it from another file you just write:

println util.AuxMethod()

That's it. Again, just make sure that your util.groovy file is in the classpath.

Derril answered 2/12, 2010 at 14:55 Comment(3)
I suspect that only works if your groovy scripts are object oriented classes. With regular functional scripts, probably doesn't work?Sharolynsharon
The example only works, at least from Windows, if the util.groovy script is renamed with capitalization Util.groovy, and the reference correspondingly changed to 'println Util.AuxMethod()'Franci
Follow-up to my previous comment. This applies to UNIX also. Does not work until I rename "util" to "Util". Also, most experience Java+Groovy developers would write the method declaration to conform with Java conventions: static def auxMethod. I.e. "static" before the type name and all methods begin with lower-case (see e.g. tons of static methods in java.util.Collections).Franci
F
2

To invoke script u.groovy from the current script, passing along the original arguments to the u.groovy, run

run(new File('u.groovy'), args)

Obviously, you could also send any String arguments that you want to:

run(new File('u.groovy'),
        ['one', new File('two.text').absolutePath] as String[])
Franci answered 20/10, 2011 at 16:24 Comment(0)
G
1

Look at the evaluate(File) function:

 Object evaluate(File file) 

http://groovy.codehaus.org/api/groovy/lang/Script.html

Glucoside answered 12/8, 2009 at 7:30 Comment(2)
Useless if you don't explain how to make or get a Script object, because that class is abstract.Franci
Generally the code that would be calling this is compiled to an instance of an anonymous Script subclass.Lathing
P
1

Since you already mentioned “cross-cutting-concerns” I’d say that you need to intercept your webservice calls AOP style (not an include mechanism).

Grails is completely integrated with Spring framework, so this makes for a good option for exploiting Spring AOP features. Take a look at this chapter from grails official guide: http://grails.org/doc/latest/guide/14.%20Grails%20and%20Spring.html and search for word AOP.

Maybe there is a purely groovy way of doing AOP, but I'd go with grails and spring.

Proteus answered 12/8, 2009 at 17:39 Comment(0)
A
1

I did some research on this for a Domain Specific Language I was creating. There are three possibilities:

  1. Create your classes as inheriting a parent groovy class. Put your shared code in the base class.

  2. Use the ScriptBaseClass see http://groovy.codehaus.org/Embedding+Groovy . This is a class upon which all of your scripts will be created.

  3. Use the import static methods capability. Note that you can do this inside the java container (see http://mrhaki.blogspot.com/2011/06/groovy-goodness-add-imports.html ).

All of these work great. My preference is the ScriptBaseClass. This works best if the common code is Groovy (the ScriptBaseClass must be a groovy class. It can not be a java class.)

Of course, with all of these items, you will still need to actually call the common method in your groovy code. For example:

doCommonStuff();
.
. do the rest of it here
.

That's not too awful, I don't think. Certainly about the same as adding some sort of #include pre-processor statement.

And finally, all of this assumes that you have access to the java program which is calling your Groovy code. If that's not the case, you can still use the static imports. It's just one extra line of code.

import static com.mycompany.mycode.doCommonStuff
doCommonStuf()
.
. do the rest of it here
.
Antigorite answered 22/1, 2012 at 16:40 Comment(0)
H
0

I created a preprocessor for my scripts. It searchs for a specific include pattern, here is a example:

public final class IncludePreprocessor {

    @FunctionalInterface
    public interface IncludeLoader {

        InputStream load(String include) throws IOException;

    }

    private static final Pattern INCLUDE_PATTERN = Pattern.compile("include\\s+(.+)$");

    private final IncludeLoader includeLoader;

    public IncludePreprocessor(IncludeLoader includeLoader) {
        this.includeLoader = includeLoader;
    }

    public boolean preprocess(InputStream mainScript, Writer outputScript) throws IOException {
        boolean preprocessed = false;
        try (Scanner sc = new Scanner(mainScript)) {
            while (sc.hasNextLine()) {
                String line = sc.nextLine();

                Matcher m = INCLUDE_PATTERN.matcher(line);
                if (m.matches()) {
                    outputScript.append("//").append(line).append(System.lineSeparator());

                    String include = m.group(1);
                    try (InputStream in = includeLoader.load(include)) {
                        StringWriter sw = new StringWriter();
                        preprocess(in, sw);
                        outputScript.append(sw.toString()).append(System.lineSeparator());
                        preprocessed = true;
                    }
                    outputScript.append("//").append(line).append(" [EOF]").append(System.lineSeparator());
                } else {
                    outputScript.append(line).append(System.lineSeparator());
                }
            }
        }

        return preprocessed;
    }
}

And how to use it:

//common.groovy
def sum(a,b) {
   a + b
}

// main.groovy
include common.groovy
sum(1,2)


// Demo.java
public class Demo {
    public static void main(String[] args) {
        IncludePreprocessor ip = new IncludePreprocessor(include -> new FileInputStream("./" + include));
        
        StringWriter sw = new StringWriter();
        ip.preprocess(new FileInputStream("./main.groovy", sw));
        System.out.println(sw.toString());
    }
}
Herring answered 29/7, 2020 at 19:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.