I need to set up an Eclipse project with an additional builder that enhances the Java bytecode produced by an earlier builder (ideally Eclipse's own). I managed to get this builder to run and enhance the Eclipse Java builder output properly but seconds later Eclipse re-runs its Java builder and resets the bytecode back. It does not rerun my enhancement builder.
My setup
- Imported as a "Gradle project" into Eclipse 2019-12 (with Buildship).
- Added manually (and automated with Gradle) a custom Ant builder (that ends up calling Gradle) to enhance the code that Eclipse Java builder produces in bin/main, in place. This builder is set to run on Manual Build and Auto Build and not After a "Clean" or During a "Clean".
- By default the above ends up having three builders, top-to-bottom: 1. Gradle Project Builder, 2. Java Builder and 3. my bytecode enhancement builder (yes, it is listed last).
Alternatives I tried
- Some combinations of setting my builder to run after/during a "Clean" as well without success. Not sure what exact events these relate to, really.
- Had the builder refresh the project after ... and also not - did not help.
Try to remove the Java Builder using the following bit in Gradle script (didn't work - it comes back on its own):
eclipse { project { file { whenMerged { projectFile -> projectFile.buildCommands.removeAll { it.name == 'org.eclipse.jdt.core.javabuilder' } } } } }
Tried disabling the Java builder manually and have my bytecode enhancement builder also build the files itself (using Gradle). This stores the following file
org.eclipse.jdt.core.javabuilder.launch
file with the following content ... but upon restart the builder is re-enabled:<?xml version="1.0" encoding="UTF-8" standalone="no"?> <launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType"> <booleanAttribute key="org.eclipse.ui.externaltools.ATTR_BUILDER_ENABLED" value="false"/> <stringAttribute key="org.eclipse.ui.externaltools.ATTR_DISABLED_BUILDER" value="org.eclipse.jdt.core.javabuilder"/> <mapAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS"/> <booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/> </launchConfiguration>
I tried (and failed) to find if there is some workspace file (as opposed to project file) being changed (as well) to disable the Java builder.
Questions
- What is the "proper" way to set up Eclipse for post-compilation bytecode enhancement?
- What causes Eclipse to re-run previous builders without re-running mine?
- Is there a way to fix (1)?
- How to reliably disable the Java builder?
Can anyone help? Thanks!
UPDATE Additional details I added 12 builders and made them all append output to the same log file to research. The 12 extra builders are just informational - 4 before the Java Builder, 4 between the Java and the enhancement builder and 4 after the enhancement builder. Each of the 12 run in only one of the four conditions (hence 3x4). They are arranged as follows:
- Gradle Project Builder
- 1a-after-clean (runs only After a "Clean")
- 1b-manual (runs only During manual builds)
- 1c-auto (runs only During auto builds)
- 1d-during-clean (runs only During a "Clean")
- Java Builder
- 2a-after-clean (runs only After a "Clean")
- 2b-manual (runs only During manual builds)
- 2c-auto (runs only During auto builds)
- 2d-during-clean (runs only During a "Clean")
- Bytecode Enhancement Builder
- 3a-after-clean (runs only After a "Clean")
- 3b-manual (runs only During manual builds)
- 3c-auto (runs only During auto builds)
- 3d-during-clean (runs only During a "Clean")
Each of the 12 informational builders writes time, its name and the size of a chosen test class. Unenhanced it is 46243 bytes long. When enhanced it becomes 53338 bytes long.
Here's the log after running "Clean" on this project alone ("Build automatically" is enabled):
20:19:19
1d-during-clean
-rw-r--r-- 1 Learner ...\... 46243 3 Mar 20:10 Test.class
20:19:19
2d-during-clean
-rw-r--r-- 1 Learner ...\... 46243 3 Mar 20:10 Test.class
20:19:20
1c-auto
-rw-r--r-- 1 Learner ...\... 46243 3 Mar 20:10 Test.class
20:19:27
2c-auto
-rw-r--r-- 1 Learner ...\... 46243 3 Mar 20:19 Test.class
Buildfile: /.../some-ant.xml
run-gradle:
[echo] Running Gradle: --parallel :...:enhanceEclipseBytecode
...
[java] > Task :...:enhanceBytecode
[java] Enhanced class: ...Test in ...
...
[java] Enhanced 205 classes.
[java] > Task :...:enhanceEclipseBytecode
[java] BUILD SUCCESSFUL in 15s
[java] 2 actionable tasks: 2 executed
BUILD SUCCESSFUL
Total time: 15 seconds
20:19:44
1c-auto
-rw-r--r-- 1 Learner ...\... 53338 3 Mar 20:19 Test.class
20:19:46
1c-auto
-rw-r--r-- 1 Learner ...\... 46243 3 Mar 20:19 Test.class
20:19:46
2c-auto
-rw-r--r-- 1 Learner ...\... 46243 3 Mar 20:19 Test.class
20:19:46
3b-manual
-rw-r--r-- 1 Learner ...\... 46243 3 Mar 20:19 Test.class
20:19:46
3c-auto
-rw-r--r-- 1 Learner ...\... 46243 3 Mar 20:19 Test.class
20:19:46
3d-during-clean
-rw-r--r-- 1 Learner ...\... 46243 3 Mar 20:19 Test.class
20:19:57
1c-auto
-rw-r--r-- 1 Learner ...\... 46243 3 Mar 20:19 Test.class
20:19:57
2c-auto
-rw-r--r-- 1 Learner ...\... 46243 3 Mar 20:19 Test.class
20:19:57
3b-manual
-rw-r--r-- 1 Learner ...\... 46243 3 Mar 20:19 Test.class
20:19:57
3c-auto
-rw-r--r-- 1 Learner ...\... 46243 3 Mar 20:19 Test.class
20:19:57
3d-during-clean
-rw-r--r-- 1 Learner ...\... 46243 3 Mar 20:19 Test.class
UPDATE 2: Minimum example to reproduce
- Create a folder - name it what you wish.
In that folder create build.grade file with the following content:
buildscript { repositories { mavenCentral() } dependencies { classpath 'org.hibernate:hibernate-gradle-plugin:5.4.2.Final' } } plugins { id 'java' id 'eclipse' } apply plugin: 'org.hibernate.orm' repositories { mavenCentral() } dependencies { implementation 'org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Final' } hibernate { sourceSets = [ project.sourceSets.main ] enhance { enableLazyInitialization = true; enableDirtyTracking = true; enableAssociationManagement = false; enableExtendedEnhancement = false; } }
Create a src/main/java/learner/TestEntity.java in there too as follows:
package learner; import javax.persistence.*; @Entity public class TestEntity { @Id @Column(name = "id", nullable = false, updatable = false) private Long id = null; @Column(name = "name", columnDefinition = "TEXT") private String name = null; public Long getId() { return id; } public void setId(final Long id) { this.id = id; } public String getName() { return name; } public void setName(final String name) { this.name = name; } }
Execute
gradle compileJava
. Open the resultingbuild/classes/java/main/learner/TestEntity.class
binary in an ASCII or hex viewer and observe stuff like$$_hibernate_write_name
in there.- Import this project into Eclipse (say 2019-12) as a Gradle project and build it. Open the resulting
bin/main/learner/TestEntity.class
and observe none of that.