Groovy allows a quoted function identifier such as
def "my cool method"()
{
"foo"
}
but I can't find this in the specification. Is it a groovy feature or maybe some lib relies on quotes being used in identifiers? Or is it an omission in the official doc?
It is an integral part of Groovy to be able to do this. If it is missing in the documentation, then it is a documentation bug at most. Basically the same as written at http://groovy-lang.org/syntax.html#_quoted_identifiers is also valid for function names.
Related
I'm building a route which calls a groovy script whose path is dynamically computed and, if the script can't be found, defaults to a generic, static script:
.doTry()
.toD("language://groovy:resource:classpath:scripts/${exchangeProperty.consumerType}ResponseHandler.groovy")
.doCatch(FileNotFoundException.class)
.script().groovy("resource:classpath:scripts/defaultResponseHandler.groovy")
.end()
The problem is that the exchange property consumerType is not resolved since the uri string parameter of toD is evaluated using groovy and not simple.
MultipleCompilationErrorsException -> startup failed:
Script_09b4150584d9e2c979353feee06897b5.groovy: 1: Unexpected input: 'scripts/${exchangeProperty.consumerType}' # line 1, column 20.
resource:classpath:scripts/${exchangeProperty.consumerType}ResponseHandler.groovy
^
1 error
How can I obtain the desired behavior?
According to the error shown there, it seems Camel is not able to resolve the string you provided in the toD().
By default, the expression you pass to a dynamic to is evaluated as Simple language but, as described in To Dynamic Camel documentation, you can specify other languages for the dynamic evaluation.
In your case, you are trying to evaluate the endpoint with groovy language but then you're using Simple language to substitute a piece of the name of the script.
One solution I've found (yet not the best) would be to specify the language for the interpretation of the string as simple and then use language:groovy to specify the endpoint that will need to be called.
You could write something like this:
.doTry()
.toD("language:simple:language://groovy:resource:classpath:scripts/${exchangeProperty.consumerType}ResponseHandler.groovy")
.doCatch(FileNotFoundException.class)
.script().groovy("resource:classpath:scripts/defaultResponseHandler.groovy")
.end()
It seems to work, but I hope someone else comes up with a better solution.
I found this in Groovy Syntax documentation at 4.6.1. Special cases:
As slashy strings were mostly designed to make regexp easier so a few
things that are errors in GStrings like $() or $5 will work with
slashy strings.
What $() syntax means? give some usage examples please
I also found it at Define the Contract Locally in the Repository of the Fraud Detection Service:
body([ // (4)
"client.id": $(regex('[0-9]{10}')),
loanAmount : 99999
])
but I don't understand what $() means when used with regex('[0-9]{10}').
It means nothing (or what you make of it). There are two places, you
are addressing, but they have nothing to do with each other.
The docs just mention this as "you can use slashy strings to write
things, that would give you an error with a GString" - the same is true
for just using '-Strings.
E.g.
"hello $()"
Gives this error:
unknown recognition error type: groovyjarjarantlr4.v4.runtime.LexerNoViableAltException
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
/tmp/x.groovy: 1: token recognition error at: '(' # line 1, column 9.
"hello $()"
The parser either wants a { or any char, that is a valid first char
for a variable (neither ( nor 5 is).
The other place you encountered $() (in Spring cloud contract), this
is just a function with the name $.
Form the docs 8. Contract DSL:
You can set the properties inside the body either with the value method or, if you use the Groovy map notation, with $()
So this is just a function, with a very short name.
E.g. you can try this yourself:
void $(x) { println x }
$("Hello")
We would like to understand a couple of legacy job-dsl scripts but don't know what "slash operator" means in this context (as it cant be division):
def command = (shells.first() / command)
We have tried to look it up in several Groovy books but only found the trivial solution that it means 'division'.
It's an XML Node operation, to return a sub-node of a XML node, or create it if it doesn't exist. Probably the command node under the first of your shells nodes here.
Groovy allows operator overloading, so it is the same "division" operator, just redefined somewhat. This is common (but also controversial) in other languages allowing operator overloading, but does allow for richer DSLs.
Having had a quick look at (an old copy of) the JobDSL source, it seems that they're doing it using a class NodeEnhancement, notably this JavaDoc:
/**
Add div and leftShift operators to Node.
div - Will return the first child that matches name, and if it doesn't exists, it creates
...
**/
My question is regarding the property count in the matcher class in groovy. Following is an example:
import java.util.regex.Matcher
def p= /[a-z]*/
Matcher m= "abc" =~ p
println m.count
As you can see, Groovy actually uses the Matcher class in Java. According to javadoc, Matcher doesn't have any count property. We have to use loops to count manually in Java development for pattern matching. How can groovy do this? Is it documented somewhere?
Thanks,
A good start for this is Groovy Backstage and especially Groovy Method Invocation. Basically the classes get a metaClass augmented with a common set of tools (e.g. DefaultGroovyMethods (see below) for Object). On method invocation, groovy takes this into account for "what is there". count for Matcher is already some more special case, something much more common used on Object is e.g. println.
If you are interested only in the functionality itself you can check the GDK. E.g. for Matcher.getCount().
If you are interested how it is actually implemented, then a good start is always DefaultGroovyMethods or the descendants of DefaultGroovyMethodsSupport in general. So following this for Matcher.getCount() leeds to https://github.com/groovy/groovy-core/blob/master/src/main/org/codehaus/groovy/runtime/StringGroovyMethods.java#L1508.
For DSL purposes I want to detect methods defined like:
def "methodName"() {}
or
def "This is another method name"() {}
Is there any way to do that using reflection?
This information is not available at runtime. Even with an AST transformation, you would not be able to figure out that the method was defined using a string.
For this, you would have to write your own AntlrParserPlugin and use it using a custom CompilerConfiguration. Then in methodDef from AntlrParserPlugin, when the name of the method is parsed, you could check that the character before the name is a double quote. If a double quote is found, then add a custom annotation to the generated MethodNode, so that the information is available at runtime...