Error while executing groovy script - groovy

Code is a follows:
class Book
{
private String title
Book (String theTitle)
{
title=theTitle
}
String getTitle()
{
return title
}
}
Book gina=new Book('Groovy in Action')
assert gina.getTitle()=='Groovy in Action'
assert getTitleBackwards(gina)=='noitcA ni yvoorG'
String getTitleBackwards(Book)
{
title=book.getTitle()
return title.reverse()
}
When I execute is with Ctrl+R, I get the following compilation error.
1 compilation error:
Invalid duplicate class definition of class Book : The source
Book.groovy contains at least two definitions of the class Book. One
of the classes is an explicit generated class using the class
statement, the other is a class generated from the script body based
on the file name. Solutions are to change the file name or to change
the class name. at line: 1, column: 1
Can anybody please explain me what is happening here.

Invalid duplicate class definition of class Book:
The code listing of the OP contains two parts:
The type definition of class Book
A groovy script that acts as a client of the Book type
Groovy treats your *.groovy file as either a script file or as a class definition file. A script file is a file that contains code that is not inside a class definition. When Groovy compiles a script file it implicitly creates a class to hold your code and the implicit class is given the name of the Book.groovy file.
Then, the compiler will try and create an additional class Book for the Book class defined in the groovy script, and the error occurs here because now there a actually two Book class definitions.
Compare: Blog entry with code sample for this error message
A way to define the Book class and the client script in the same file would be to rename the file, e.g. to BookApp.groovy. Caveat: if you do this, the Book type can only be referenced from within the script file, the Book type would not be found by groovy automatically, even if the *.groovy file was found on the class path.

Groovy console buffers items (sources, classes, variables) internally, second click of "run" can be different that first, I agree. Almost all interpreter windows (in any languages) has similar behaviour
has delicate differences when opening from File, pasting into window without file, in consequence can have name Book or ConsoleScript1 etc ("procedural" use of Groovy has hidden "object" background, hidden/default/generated class names from file etc)
This can be help-full by ad-hoc programming (script mode) but not always is the best for true OOP.
PS. code has few errors, too

when I ran into this error, it was because I forgot the word 'import' directly above so rather than :
import io.beapi.api.service.PrincipleService
#RestController
class UserController {
I had this:
io.beapi.api.service.PrincipleService
#RestController
class UserController {
The lack of the word import caused this issue for me. Quick easy fix (once I caught what it was) :)

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.

Groovy star import and usage of "partial" packages

To my surprise I have learned today that the following works just fine in Groovy:
import java.util.concurrent.*
def atomicBool = new atomic.AtomicBoolean(true)
i.e. after the star import, I can use a 'partial' package to refer to java.util.concurrent.atomic.AtomicBoolean.
Obviously, the same is not valid in Java:
import java.util.concurrent.*;
public class Sample {
public static void main(String[] args) {
// compiler error: 'atomic' cannot be resolved to a type
new atomic.AtomicBoolean(true);
}
}
So it seems that Groovy's idea of a package is similar to C++ (or C#) namespaces in this regard.
Question to the Groovy experts:
Is this by design or is it a (potentially unintended) side effect of the way the interpreter treats star imports?
If it is by design, can you point me to a section in the documentation or language specification where this behavior is documented? (There is no mention of this in the documentation on Star Import and neither in the language spec as far as I can tell or at least I couldn't find anything.)
Based on Groovy source code, this behavior seems to be intended. Before we dig deeper into Groovy internals you have to be aware of one thing - Groovy compiles to a bytecode that can be represented by a valid Java code. It means that Groovy code like the one form your example actually compiles to something like this (without compile static and type checked transformations):
import groovy.lang.Binding;
import groovy.lang.Script;
import java.util.concurrent.atomic.AtomicBoolean;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
import org.codehaus.groovy.runtime.callsite.CallSite;
public class test extends Script {
public test() {
CallSite[] var1 = $getCallSiteArray();
}
public test(Binding context) {
CallSite[] var2 = $getCallSiteArray();
super(context);
}
public static void main(String... args) {
CallSite[] var1 = $getCallSiteArray();
var1[0].call(InvokerHelper.class, test.class, args);
}
public Object run() {
CallSite[] var1 = $getCallSiteArray();
AtomicBoolean atomicBool = (AtomicBoolean)ScriptBytecodeAdapter.castToType(var1[1].callConstructor(AtomicBoolean.class, true), AtomicBoolean.class);
return var1[2].callCurrent(this, atomicBool);
}
}
As you can see this Java class uses full java.util.concurrent.atomic.AtomicBoolean import and this is actually what Groovy transforms your input source code to.
How does it happen?
As you may know Groovy builds Abstract Syntax Tree (AST) from the input source file and it iterates over all nodes (like expressions, variable definitions, method calls etc.) and applies transformations. Groovy uses class called ResolverVisitor that is designed to resolve types. When Groovy compiles your code it finds ConstructorCallExpression:
new atomic.AtomicBoolean(true)
It sees that the expected type of the object you are trying to create is atomic.AtomicBoolean, so ResolverVisitor starts resolving the type by calling resolveOrFail(type, cce); at line 1131.
It tries several resolving strategies that fail until it reaches method resolveFromModule at line 695. What happens here is it iterates over all star imports (single java.util.concurrent.* in your case), then it concatenates star import with the type name and it checks if qualified name created from this concatenation is a valid type class. Luckily it is in your case:
When type gets resolved, Groovy replaces initial type with this resolved valid type name in the abstract syntax tree. After this operation your input code looks more like this:
import java.util.concurrent.*
java.util.concurrent.atomic.AtomicBoolean atomicBool = new java.util.concurrent.atomic.AtomicBoolean(true)
This is what compiler gets eventually. Of course fully qualified name gets replaced with the import (this is what Java compiler does with qualified names).
Was this "feature" introduced by designed?
I can't tell you that. However we can read from the source code, that this happens on purpose and type resolving like this is implemented with intention.
Why it is not documented?
I guess no one actually recommend using imports that way. Groovy is very powerful and you are able to do many things in a many different ways, but it doesn't mean you should do so. Star imports are pretty controversial, because using star imports over explicit imports makes your code more error-prone due to possible class import conflicts. But if you want to know exact answer to this kind of questions you would have to ask Groovy language designers and core developers - they may give you straight answer without any doubts.

Add constraints to properties of Groovy class (not Grails domain class!)

How can we add some common constraints (i.e. maxLength, nullable) to a property of a Groovy class? I know we can do it at Grails domain class, but is it possible if that is a Groovy class (I use it as a DTO class for my Grails project)?
Thank you so much!
You can add constraints to command classes. If a command class is in the same .groovy file as a controller (in Groovy you can have more than one public class in each .groovy file), you don't need to do anything special for Grails to recongise it as a command class.
However, if your command class is somewhere else (e.g. under src/groovy), you need to annotate it with #Validateable and add the package name to the grails.validateable.packages parameter in Config.groovy. Here's an example of a command that's not in the same file as a controller
pacakge com.example.command
#Validateable
class Person {
Integer age
String name
static constraints = {
name(blank: false)
age(size 0..100)
}
}
Add the following to Config.groovy
grails.validateable.packages = ['com.example.command']
Command classes have a validate() method added by Grails. After this method is called, any errors will be available in the errors property (as per domain classes).
Using a grails Command Object is probably your best bet. It has constraints and validation, but no database backing. It's normally a value object that controllers use, but you could instantiate one outside of a controller without any problems.
Not sure if this is relevant to your use (I am not familiar with DTOs), but in the current version (2.3.8), you can also add Grails constraints to an abstract class, and they will be inherited by the domains that extend it. Your IDE might not like it though ;)

Kohana 3 Auto loading Models

I'm attempting to use a Model but I get a fatal error so I assume it doesn't autoload properly.
ErrorException [ Fatal Error ]: Class
'Properties_Model' not found
The offending controller line:
$properties = new Properties_Model;
The model:
class Properties_Model extends Model
{
public function __construct()
{
parent::__construct();
}
}
I also put the class in three different locations hoping one would work, all there failed.
They are:
application/classes/model
application/model
application/models
What am I missing?
Ah, I got this question emailed directly to me (via my website's contact form)!
Here is what I responded with (for the benefit of other people which may run into this problem).
The correct location of a model named
properties is
application/classes/model/properties.php
and the class definition would be as
follows
class Model_Properties extends Model { }
Think of the underscore above as the
directory separator. That is, if you
replaced the underscore with a / you
would have: 'model/properties', which
will be your file under application/classes.
To load the model from a controller,
you can use PHP's standard new
operator or do what I prefer, which is
$propertiesModel = Model::factory('Properties');
I'm not 100% why I prefer this way...
but it works for me :)
First off, The Kohana 3 fileyestem does not work like Kohana 2's!
In K2 the autoloader looks at the class name searches for the class in different folders, based on the suffix of the class.
In K3, class names are "converted" to file paths by replacing underscores with slashes.
i.e. Class Properties_Model becomes classes/properties/model.php
As you can see, using a Model suffix in this new system won't really help to group your models, so basically you prepend "Model" to the class name instead of suffixing it:
Model_Property is located in classes/model/property.php
For more information see the Kohana 3 userguide

groovy static class

What does the 'static' do in this file, sample.groovy?
static class froob {
}
The groovy code compiles fine with 'static' or without it.
There is absolutely no difference. The static in this situation is ignored.
To test, I created a groovy class and piped the output of "javap -verbose StaticTest" to a file. Then put "static" before the class def and piped that to a 2nd file. I then diffed the two files. The only differences were those unique ids that are associated with the long class ID that gets generated new for every class.
Are you referring to the static class or the static method "main" within the static class?
The keyword "static" means that allocation starts when the program begins and ends when the program ends. In other words, there's no way to programmatically create an instance of class "froob," but rather an instance is automatically create when the program beings and will exist until your program ends.
In the context of your small sample program, it is effectively meaningless. Only the "main" class needs to be static, as it needs to "exist" prior to any code within the program having been executed.
In Java, only an inner class can be static. Prior to Groovy 1.7 inner classes are prohibited, and declaring a top-level class static has no effect.
In Groovy 1.7+ I expect static inner classes to have the same semantics as they do in Java. Declaring a top-level class will likely have no effect (or be prohibited by the compiler).

Resources