Fast development with Gradle in Eclipse. Is it possible?

Francois, just to make sure: by Project A in your example you mean the application project, right? And by Project B you mean the library project, right? So the settings.gradle file will be located in the application project. Because as I said it is the applications that will depend on the library, not the other way around.

Could you confirm this for me please?

Yup, here A is the application
And B the library, since I wrote a compilation dependency on B, in project A.

As I said, I would report my findings after trying it out. And the result is that unfortunatelly it didn’t work as expected. I see that everytime I make a change in the library project and run the application project, the library project jar is generated (I see it is generated in the ‘libs’ dir).

I’ll show some of my files below for you to see if there’s something wrong or if I missed something. The ‘desenvolvimento’ project is the library project and the ‘teste’ project is the application project (sorry because the names are in Portuguese, but I think that the names doesn’t matter in this case).

build.gradle (library)

apply plugin: 'java'

sourceCompatibility = 1.8

repositories
{
	mavenCentral()
}

dependencies
{
	compile 'org.hibernate:hibernate-entitymanager:5.0.0.Final'
	compile 'org.hibernate:hibernate-validator:5.2.1.Final'
	compile 'org.slf4j:slf4j-api:1.7.12'
}

build.gradle (application)

apply plugin: 'application'
apply plugin: 'eclipse'

sourceCompatibility = 1.8
mainClassName = 'br.desenvolvimento.teste.iu.Teste'

repositories
{
	mavenCentral()
}

dependencies
{
	compile 'org.hibernate:hibernate-entitymanager:5.0.0.Final'
	compile 'org.hibernate:hibernate-validator:5.2.1.Final'
	compile 'org.slf4j:slf4j-api:1.7.12'
	compile project(':desenvolvimento')

	runtime 'javax.el:javax.el-api:3.0.0'
	runtime 'ch.qos.logback:logback-classic:1.1.3'
	runtime 'org.postgresql:postgresql:9.4-1201-jdbc41'
	
	testCompile 'org.testng:testng:6.9.6'
}

test
{
	useTestNG
	{
		suites 'src/test/resources/padrao.xml',
			'src/test/resources/personalizado.xml'
	}
}

jar
{
	manifest
	{
		attributes 'Specification-Title': 'Sistema',
                   'Description': 'Sistema Teste'
	}
}

settings.gradle (application)

include 'desenvolvimento'
project(':desenvolvimento').projectDir = new File('../../desenvolvimento/desenvolvimento')

entry generated in the .classpath file after running the eclipse task in the application project:

<classpathentry kind="src" path="/desenvolvimento"/>

Is there anything left to be done to achieve what I want?

Well, isn’t it what you want?
You can develop your application, and see instantaneously the changes you make in the library, since it’s a project dependency in your Eclipse .classpath file from your application project.
Of course, the library classpath file must as well contains source entries (e.g. It can be generated by the eclipse gradle plug-in as well) if you want that your modification on the library project can be seen in the application project.

Gradle is “just” used here to generate the .classpath files of your projects.
Of course it generates as well libraries for both projects, but that’s not relevant for you right now, during development.

Could you explain again what is wrong with this approach, regarding your initial request ?

This is very nice. I really wanted this as I didn’t have it before when the projects were independent projects. But the real point, the real issue is not this (explained below).

My initial request was this:

Before using Gradle, I was using only Eclipse to build and run my application. I didn’t use any other build tool.

So, when I made some change to a source file in the library project and saved the file to disk, the Eclipse Java Builder kicks in and compiles only that file. Then when I run my application project in Eclipse (the application project depends on the library project), Eclipse runs my application very fast because it doesn’t generate the library jar file (the thing that Gradle is doing here). Am I being clear here? Eclipse just do all the magic assembling the classpath and classload thing in memory and runs my application as if I was executing it outside it, running it from the application jar file using the library jar file. Do you get what I mean?

I want to achive the same thing with Gradle while I’m in development stage. Later, when I want (when I’m about to go to production), I want to instruct Gradle to finally generate the library jar file and application jar file.

This feature is a very nice feature of Eclipse. It saves us a lot of time in development. I think that any build tool can’t have less than any IDE. If I can’t accomplish this with Gradle, my only option will be to come back to raw Eclipse do develop my library and application. All those milliseconds and seconds generating a jar file without necessity every time I make a little change and want to see it will make me waste a lot of time. It is definitely a no-no.

So you want to completely get rid of your IDE, and mimic the Eclipse builder behavior, using just Gradle on the command line?

The closest thing I can think of is [gradle continuous build] (https://docs.gradle.org/current/userguide/continuous_build.html)

Maybe my English is really very bad. Nowhere I said that I want to get rid of Eclipse and use Gradle on the command line simulating Eclipse behavior.

I want to keep developing in Eclipse using Gradle, but I want Gradle to behave like Eclipse regarding the feature I mentioned. I think that I didn’t explain it so bad in my last post.

If someone understood what I want I just want you to tell me: no, you can’t do this with Gradle or yes, you can do this with Gradle, here’s how. Simple like this.

No, you cannot do this with Gradle. I think given your description, the best option is to go back to raw Eclipse development.

Thanks for the direct answer.

Does Gradle (or Buildship) have any plan to support it in the future as a request for enhancement?

I’m not aware of any plans at Gradle to mimic Eclipse’s way of building projects.
The one thing that will come in the future is composite builds, i.e. building across disjunct projects.

Just to emphasize a last thing: I didn’t suggest anywhere that the point of this topic started by me was to find a way for Gradle to mimic Eclipse’s way of building projects. I wouldn’t be so naive. If so, what about IntelliJ, Netbeans, etc? This meaning can’t be assigned to my topic.

What I suggested was a way that, to save development time, independent of any IDE, while someone is working in development stage (maybe that only in Java SE applications, I don’t know), was not necessary to Gradle generate the jar file(s). The developer could be working in this mode, let’s call it this way, until he thinks it is the time to package and deploy its artifacts. That would save a lot of time in development (as we have today using IDEs in Java SE applications).

Thank you for listing.

Hi Marcos,
i had a similar challenge migrating legacy projects to be built by gradle, without having too much impact on the development workflow.
What finally worked for me, was using this kind of hack to adjust the generated eclipse classpath to have a reference to the class folder of the library project, compiled by the eclipse compiler.
This way, launching the project A from eclipse would pick up the latest changes done in sources of library B without any gradling.
From what i can tell, this binary reference is the only thing you are missing to achieve what you want.
Since my main project was a web project, this is how the generated CP entry had to look like:

<classpathentry kind="lib" path="/library-b/bin" exported="null" sourcepath="/library-b">
	<attributes>
		<attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/classes"/>
	</attributes>
</classpathentry>

Whether or not you are willing to go this hacky road is up to you ;-]

Thank you. I’ll test this next week and report if it solves the problem.

I also have utility projects and clients of them, that are built and published separately.
But where I want to do fast and seamless development on them at the same time in eclipse.

My solution has been a flag in the client project build file.
When set, the normal dependency to the utility project is disabled, and the eclipse-plugin is used to add an eclipse project reference to the utility project.

Works a charm.

i can post an example, when I’m at work on Monday if you like.

Yes, I really would like to see your solution.

It would be nice if there was a stardard way in Gradle to configure it to be .class oriented when we want instead of only .jar oriented. Then this discussion would be needless.

Who generates it? Eclipse itself or gradle build runned by you in command line? I think eclipse alone cannot do this. If you create build files from your post and run gradle eclipse it will generate .classpath file (maybe some other files needed for raw eclipse build without gradle). Then you can use your eclipse installation as usual without gradle. And no jar files will be generated until you run gradle build or something similar. So you achieve really what you want - fast development in eclise without gradle. But with possibility of building your projects from command line and deploy when you want.

Maybe I am wrong? I really doesn’t understand what problem you experience. Maybe I not understand your workflow process?

The script below uses an external prebuilt dependency (dk.jyskebank.tooling.infra:infra-base) when useWorkspaceBase is false.

When true, it rewrites Eclipse’s .classpath file to reference the project (jb.jbit.im.tools.base.java) directly in the workspace (not its .classpath folder - the project).

I hope it makes sense.

Cheers,
Jesper

apply plugin: "eclipse"

ext {
  useWorkspaceBase = false
}

dependencies {
  if (!useWorkspaceBase) {
    compile "dk.jyskebank.tooling.infra:infra-base:1.0.0"
  }
}

eclipse {
  classpath {
    if (useWorkspaceBase) {
      file {
        withXml {
          def node = it.asNode()
          node.appendNode('classpathentry', [kind: 'src', path: '/jb.jbit.im.tools.base.java', exported: true])
        }
      }
    }
  }
}

I decided to abandon Gradle for Java SE development. I will only use it in Java EE development where artifacts like .jar, .war and .ear really need to be generated for the server in order to run the application.

Gradle is a nice tool, no doubt about that, but it is certainly not tailored for the use case of this topic. Eclipse does a better job alone.

Thanks to Jasper and conf for the help. The hacks didn’t work for me and unfortunately I don’t have the time to delay my work anymore to try to find out why.

Again, only my suggestion: I think that Gradle should consider an easier way to achieve this in the future. I’m not the only one that wants this feature.

This is going to be fixed by the composite build feature we plan to release with Buildship 1.1

This is really what I call very good news. I’ll certainly give it a try. With this feature Gradle is becoming even more complete and sophisticated. Thank you for implementing this.