How do I access the Project from other classes?


#1

I wonder what the best practice is for accessing the Project from within other classes within a custom plugin (written in Java)?

If I for example have this domain structure in build.gradle for configuring something (each block is its own Java-class):

app {
    env {
        server {
            tomcat {
            }
        }
    }
}

Inside server (corresponding Java-class that is) I have:

public void tomcat(Action<Tomcat> configure) {
    configure.execute(tomcat);
}

Let’s say that I want to access Project.getVersion(), Project.file() or something else from the Project instance, how would I go about doing that inside my Tomcat-class?

I’ve seen others solving this by inheritance, storing the Project instance as a protected member in (in this example) the App-class, then subclassing App and thus getting access to it further down in the hierarchy.

I’ve also seen people having a ProjectWrapper-class and storing the Project as static member along with a static method for retrieving it from within other classes.

What would be the recommended way of getting a the Project instance from classes where you don’t have direct access to it?


(uklance) #2

storing the Project as static member along with a static method for retrieving it from within other classes.

Statics are evil, don’t do this. You’ll need to pass the Project instance wherever you need it. Both plugins and tasks have a reference to the Project instance so you’ll need to pass it downstream where required (eg dependency injection).

Every time you think of making a static mutable variable, slap yourself on the face… and think again :smile:

Also, avoid inheritance and instead embrace composition

Eg:

public class App {
   public App(Project project) { ... } 
   public Project getProject() { ... } 
} 
public class Env {
   public Env(App app) { ... } 
   public App getApp() { ... } 
} 
public class Server {
   public Server(Env env) { ... } 
   public Env getEnv() { ... } 
} 
// etc

#3

Thanks for your input.

I’m actually passing the Project instance around already, but since the places where it is needed are increasing it seems, I wanted some input on how it could (or should) be done more elegantly.

I would like to see an example of this in the official docs.


(uklance) #4

I’ve added the skeleton for what could become a “rich data model” above.

I guess it’s a choice of style. I feel that you are choosing a “rich data model” rather than an “anemic data model” (see here)

The bulk of the gradle plugins I’ve seen use an anemic model where there’s no logic in the model itself. It’s just a holder for configuration that is executed later (eg in a task). So an anemic model won’t need a reference to the project etc.

Perhaps you could save yourself the hassle by using an anemic data model instead.


#5

I haven’t thought about it in those terms. But yes, I guess my approach is toward the rich model.

You’ve given me something to think about. Thanks.


(Schalk Cronjé) #6

Pretty bad idea. With extensions classes it is worthwhile adding the Project instance as a normal private field. You can then decide how you want the delegation of the inner closure to be able to access it.


(uklance) #7

Yes… Once more for the record

Every time you think of making a static mutable variable, slap yourself on the face… and think again