0

I cannot access exploits property in domain class - Scenario , from my java class - MatchScenario , located in Grails src folder.

Already tried :

  1. Explicit methods : I have tried explicitly creating the get;set; but I get stackOverflow error since the setExploits() is called infinitely by itself for some reason.

  2. Service to return the exploit field, Though the service was created, it's never called on my fork-debug integration testing, so tests hangs with no exception

compilation error ->

Error:(59, 44) java: cannot find symbol
symbol:   variable exploits
location: variable scenario of type core.Scenario

Java class, error on the inner loop ->

public class MatchScenario implements Callable{
    private static final Logger LOG = Logger.getLogger(MatchScenario.class.getCanonicalName());

    private List<Scenario> scenarioList

    @Override
    public List<Scenario> call() throws Exception {
        LOG.debug( "***********************    schedule matcher called *****************************" );
        if (scenarioList==null) {
            LOG.debug("scenarioList not initialized ");
            return null;
        }
        List<Scenario> scenarioAvailable = new ArrayList<Scenario>();
        for (Scenario scenario : scenarioList){
            for (Exploit exploit : scenario.exploits){
                //println 'exploit -> '+exploit
                if (!match( exploit.getExpression() ) ){
                    break;
                }
            }
            //happens only when  all scenario are available ( no break issued )
            scenarioAvailable.add(scenario);
        }

        return scenarioAvailable;
    }

    private boolean match(String expression) {
        return true;
    }
}

Scenario domain object ->

package core

class Scenario {
    String name

    static belongsTo = [ Exploit ]

    static hasMany = [ exploits : Exploit ]

    static constraints = {
        name nullable: false , maxSize: 32
    }
}

1 Answer 1

1

You're confusing fields and properties. When you declare a property in a Groovy class, e.g. String name, the Groovy compiler converts that to a private field and adds a getter and a setter (unless you already defined one or both of them - it won't overwrite), in this case something like

private String name
public void setName(String name) { this.name = name }
public String getName() { return name }

It only does this if there's no scope modifier, so public String name and protected String name would both stay as defined.

One benefit of this is that you can later add logic to the getter and/or setter to modify the value, do some validation checks or computations, etc., and in Groovy you would still read and write to the name property since property access always calls the underlying setters and getters, and since properties like this are a Groovy-only thing that Java can't access, you would have been calling the setter and getter from Java all along, so you wouldn't need to recompile the Java classes that used the class.

Declaring a hasMany like yours creates an exploits property, effectively

Set<Exploit> exploits

and that property (added by a Grails AST transformation) is likewise converted to a private field with a getter and setter. So to get this working from Java, use the getter:

for (Exploit exploit : scenario.getExploits()) {
Sign up to request clarification or add additional context in comments.

4 Comments

This didn't work as i stated in 1,it still gives the similar error - > Error:(60, 40) java: cannot find symbol symbol: method getExploits() location: variable scenario of type core.Scenario. I think it's better to edit your response so the answer will be on top,at least for me.
I will also note , that sometimes after removing the line and compiling, and then returning it , it does compile and run .I use intelliJ 14.0.1 with grails 2.5, I cannot pin-point the exact trigger for it to compile or give compilation error , but it seems like some anomaly.
I think I've seen this before, and it seems like a timing issue. If the Java class gets compiled before the Groovy class (in particular before the AST has made its changes) then the Java class won't be able to see the getExploits method. Although it's rarely a good idea to do so (not a problem really, just clutter), you should be able to get it working by adding in Set<Exploit> exploits to the domain class. It's the same thing that GORM will add, but should be there early enough that it's visible.
WORKS!! great , i will look to enforce a better compilation ordering in someway

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.