Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 2e64a07

Browse files
committed
HHH-19519: Document breaking changes in new Hibernate Maven Plugin
- Rename 'HibernateEnhancerMojo' to 'EnhancerMojo' - Rename 'HibernateEnhancerMojoTest' to 'EnhancerMojoTest' - Add integration test 'HibernateEnhancerMojoTestIT' to test the different configuration options - Make sure that the enhancer is not doing anything if all the enablement parameters are false Signed-off-by: Koen Aers <koen.aers@gmail.com>
1 parent 6ebf347 commit 2e64a07

File tree

8 files changed

+597
-114
lines changed

8 files changed

+597
-114
lines changed

‎tooling/hibernate-maven-plugin/hibernate-maven-plugin.gradle

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,33 @@ plugins {
1212

1313
description = 'Maven plugin to integrate aspects of Hibernate into your build.'
1414

15+
sourceSets {
16+
intTest {
17+
compileClasspath += sourceSets.main.output
18+
runtimeClasspath += sourceSets.main.output
19+
}
20+
}
21+
22+
configurations {
23+
intTestImplementation.extendsFrom implementation
24+
intTestRuntimeOnly.extendsFrom runtimeOnly
25+
}
26+
1527
dependencies {
1628
implementation project( ":hibernate-core" )
1729

18-
implementation "org.apache.maven:maven-plugin-api:3.6.3"
30+
implementation "org.apache.maven:maven-plugin-api:3.9.11"
1931
implementation "org.apache.maven:maven-project:2.2.1"
2032
implementation "org.apache.maven.shared:file-management:3.1.0"
2133

22-
compileOnly "org.apache.maven.plugin-tools:maven-plugin-annotations:3.6.0"
34+
compileOnly "org.apache.maven.plugin-tools:maven-plugin-tools-annotations:3.15.1"
35+
36+
intTestImplementation 'org.junit.jupiter:junit-jupiter:5.13.4'
37+
intTestImplementation 'org.apache.maven:maven-embedder:3.9.11'
38+
intTestRuntimeOnly 'org.junit.platform:junit-platform-launcher'
39+
intTestRuntimeOnly 'ch.qos.logback:logback-classic:1.5.18'
40+
intTestRuntimeOnly 'org.apache.maven:maven-compat:3.9.11'
41+
2342
}
2443

2544
def releasePrepareTask = tasks.register("releasePrepare") {
@@ -37,6 +56,25 @@ tasks.register("preVerifyRelease") {
3756
dependsOn releasePrepareTask
3857
}
3958

59+
tasks.register('integrationTest', Test) {
60+
description = 'Runs integration tests.'
61+
group = 'verification'
62+
63+
testClassesDirs = sourceSets.intTest.output.classesDirs
64+
classpath = sourceSets.intTest.runtimeClasspath
65+
shouldRunAfter test
66+
67+
useJUnitPlatform()
68+
69+
testLogging {
70+
events "passed"
71+
}
72+
}
73+
74+
tasks.forbiddenApisIntTest {
75+
enabled = false
76+
}
77+
4078
var publishingExtension = project.getExtensions().getByType(PublishingExtension) as PublishingExtension
4179
publishingExtension.publications.named("publishedArtifacts") {
4280
from components.java
@@ -64,3 +102,11 @@ publishingExtension.publications.named("publishedArtifacts") {
64102
}
65103
}
66104

105+
integrationTest {
106+
environment "hibernateVersion", project.version
107+
}
108+
109+
integrationTest.dependsOn rootProject.childProjects.'hibernate-core'.tasks.publishToMavenLocal
110+
integrationTest.dependsOn publishToMavenLocal
111+
check.dependsOn integrationTest
112+
Lines changed: 321 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,321 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.orm.tooling.maven;
6+
7+
import static org.junit.jupiter.api.Assertions.assertTrue;
8+
import static org.junit.jupiter.api.Assertions.assertFalse;
9+
10+
import org.apache.maven.cli.MavenCli;
11+
import org.hibernate.bytecode.enhance.spi.EnhancementInfo;
12+
import org.junit.jupiter.api.BeforeEach;
13+
import org.junit.jupiter.api.Test;
14+
import org.junit.jupiter.api.io.TempDir;
15+
16+
import java.io.File;
17+
import java.lang.reflect.Field;
18+
import java.lang.reflect.Method;
19+
import java.net.URL;
20+
import java.net.URLClassLoader;
21+
import java.nio.file.Files;
22+
import java.util.List;
23+
24+
public class EnhancerMojoTestIT {
25+
26+
public static final String MVN_HOME = "maven.multiModuleProjectDirectory";
27+
28+
@TempDir
29+
File projectDir;
30+
31+
private MavenCli mavenCli;
32+
33+
@BeforeEach
34+
public void beforeEach() throws Exception {
35+
copyJavFiles();
36+
System.setProperty(MVN_HOME, projectDir.getAbsolutePath());
37+
mavenCli = new MavenCli();
38+
}
39+
40+
@Test
41+
public void testEnhancementDefault() throws Exception {
42+
// The default configuration for the enhance goal are as follows:
43+
// enableLazyInitialization = 'true'
44+
// enableDirtyTracking = 'true'
45+
// enableAssociationManagement = 'false'
46+
// enableExtendedEnhancement = 'false'
47+
// classesDirectory = 'target/classes'
48+
String configurationElement = "<configuration/>\n";
49+
preparePomXml(configurationElement);
50+
executeCompileGoal();
51+
executeEnhanceGoal();
52+
// Both Bar and Baz should be enhanced
53+
assertTrue(isEnhanced( "Bar" ));
54+
assertTrue(isEnhanced( "Baz" ));
55+
// Both Bar and Baz contain the method '$$_hibernate_getInterceptor'
56+
// because of the default setting of 'enableLazyInitialization'
57+
assertTrue( methodIsPresentInClass("$$_hibernate_getInterceptor", "Bar"));
58+
assertTrue( methodIsPresentInClass("$$_hibernate_getInterceptor", "Baz"));
59+
// Both Bar and Baz contain the method '$$_hibernate_hasDirtyAttributes'
60+
// because of the default setting of 'enableDirtyTracking'
61+
assertTrue( methodIsPresentInClass("$$_hibernate_hasDirtyAttributes", "Bar"));
62+
assertTrue( methodIsPresentInClass("$$_hibernate_hasDirtyAttributes", "Baz"));
63+
// Foo is not an entity and extended enhancement is not enabled so the class is not enhanced
64+
assertFalse(isEnhanced("Foo"));
65+
// Association management should not be present
66+
assertFalse(isAssociationManagementPresent());
67+
}
68+
69+
@Test
70+
public void testEnhancementFileSet() throws Exception {
71+
// Use the defaults settings for enhancement (see #testEnhancementDefault)
72+
// The files are read from the specified 'fileset' element:
73+
// - the folder specified by 'dir'
74+
// - the 'Baz.class' file is excluded
75+
String configurationElement =
76+
"<configuration>\n" +
77+
" <fileSets>\n"+
78+
" <fileset>\n" +
79+
" <directory>" + projectDir.getAbsolutePath() + "/target" + "</directory>\n" +
80+
" <excludes>\n" +
81+
" <exclude>**/Baz.class</exclude>\n" +
82+
" </excludes>\n" +
83+
" </fileset>\n" +
84+
" </fileSets>\n" +
85+
"</configuration>\n";
86+
preparePomXml(configurationElement);
87+
executeCompileGoal();
88+
executeEnhanceGoal();
89+
// Bar is enhanced
90+
assertTrue(isEnhanced( "Bar" ));
91+
// Baz is not enhanced because it was excluded from the file set
92+
assertFalse(isEnhanced( "Baz" ));
93+
// Foo is not enhanced because it is not an entity and extended enhancement was not enabled
94+
assertFalse( isEnhanced( "Foo" ) );
95+
// Association management should not be present
96+
assertFalse(isAssociationManagementPresent());
97+
}
98+
99+
@Test
100+
public void testEnhancementNoLazyInitialization() throws Exception {
101+
// Change the default setting for 'enableLazyInitialization' to 'false'
102+
// Otherwise use the settings of #testEnhancementDefault
103+
String configurationElement =
104+
"<configuration>\n" +
105+
" <enableLazyInitialization>false</enableLazyInitialization>\n"+
106+
"</configuration>\n";
107+
preparePomXml(configurationElement);
108+
executeCompileGoal();
109+
executeEnhanceGoal();
110+
// Both Bar and Baz are enhanced, Foo is not
111+
assertTrue( isEnhanced( "Bar" ));
112+
assertTrue( isEnhanced( "Baz" ));
113+
// Foo is not enhanced because it is not an entity and extended enhancement was not enabled
114+
assertFalse( isEnhanced( "Foo" ) );
115+
// but $$_hibernate_getInterceptor is not present in the enhanced classes
116+
// because of the 'false' value of 'enableLazyInitialization'
117+
assertFalse( methodIsPresentInClass("$$_hibernate_getInterceptor", "Bar"));
118+
assertFalse( methodIsPresentInClass("$$_hibernate_getInterceptor", "Baz"));
119+
// Association management should not be present
120+
assertFalse(isAssociationManagementPresent());
121+
}
122+
123+
@Test
124+
public void testEnhancementNoDirtyTracking() throws Exception {
125+
// Change the default setting for 'enableDirtyTracking' to 'false'
126+
// Otherwise use the settings of #testEnhancementDefault
127+
String configurationElement =
128+
"<configuration>\n" +
129+
" <enableDirtyTracking>false</enableDirtyTracking>\n"+
130+
"</configuration>\n";
131+
preparePomXml(configurationElement);
132+
executeCompileGoal();
133+
executeEnhanceGoal();
134+
// Both Bar and Baz should be enhanced
135+
assertTrue( isEnhanced( "Bar" ));
136+
assertTrue( isEnhanced( "Baz" ));
137+
// Foo is not enhanced because it is not an entity and extended enhancement was not enabled
138+
assertFalse( isEnhanced( "Foo" ) );
139+
// $$_hibernate_hasDirtyAttributes is not present in the enhanced classes
140+
// because of the 'false' value of 'enableLazyInitialization'
141+
assertFalse( methodIsPresentInClass("$$_hibernate_hasDirtyAttributes", "Bar"));
142+
assertFalse( methodIsPresentInClass("$$_hibernate_hasDirtyAttributes", "Baz"));
143+
// Association management should not be present
144+
assertFalse(isAssociationManagementPresent());
145+
}
146+
147+
@Test
148+
public void testEnhancementEnableAssociationManagement() throws Exception {
149+
// Change the default setting for 'enableAssociationManagement' to 'true'
150+
// Otherwise use the settings of #testEnhancementDefault
151+
String configurationElement =
152+
"<configuration>\n" +
153+
" <enableAssociationManagement>true</enableAssociationManagement>\n"+
154+
"</configuration>\n";
155+
preparePomXml(configurationElement);
156+
executeCompileGoal();
157+
executeEnhanceGoal();
158+
// Both Bar and Baz are enhanced, Foo is not
159+
assertTrue( isEnhanced( "Bar" ));
160+
assertTrue( isEnhanced( "Baz" ));
161+
assertFalse( isEnhanced( "Foo" ) );
162+
// Now verify that the association management is in place;
163+
assertTrue(isAssociationManagementPresent());
164+
}
165+
166+
@Test
167+
public void testEnhancementEnableExtendedEnhancement() throws Exception {
168+
// Change the default setting for 'enableExtendedEnhancement' to 'true'
169+
// Otherwise use the settings of #testEnhancementDefault
170+
String configurationElement =
171+
"<configuration>\n" +
172+
" <enableExtendedEnhancement>true</enableExtendedEnhancement>\n"+
173+
"</configuration>\n";
174+
preparePomXml(configurationElement);
175+
executeCompileGoal();
176+
executeEnhanceGoal();
177+
// Both Bar and Baz are enhanced because they are entities
178+
assertTrue( isEnhanced( "Bar" ));
179+
assertTrue( isEnhanced( "Baz" ));
180+
// Though Foo is not an entity, it is enhanced because of the setting of 'enableExtendedEnhancement'
181+
assertTrue( isEnhanced( "Foo" ) );
182+
// No association management is in place;
183+
assertFalse(isAssociationManagementPresent());
184+
}
185+
186+
187+
@Test
188+
public void testNoEnhancement() throws Exception {
189+
// Setting the values of all the settings to 'false' has the effect
190+
// of not executing the enhancement at all.
191+
// The setting of 'enableAssociationManagement' and 'enableExtendedEnhancement' to
192+
// false is not really needed in this case as that's what their default is
193+
String configurationElement =
194+
"<configuration>\n" +
195+
" <enableLazyInitialization>false</enableLazyInitialization>\n"+
196+
" <enableDirtyTracking>false</enableDirtyTracking>\n"+
197+
" <enableAssociationManagement>false</enableAssociationManagement>\n"+
198+
" <enableExtendedEnhancement>false</enableExtendedEnhancement>\n"+
199+
"</configuration>\n";
200+
preparePomXml(configurationElement);
201+
executeCompileGoal();
202+
executeEnhanceGoal();
203+
// None of the classes should be enhanced
204+
assertFalse( isEnhanced( "Bar" ));
205+
assertFalse( isEnhanced( "Baz" ));
206+
assertFalse( isEnhanced( "Foo" ) );
207+
// No association management is in place;
208+
assertFalse(isAssociationManagementPresent());
209+
}
210+
211+
private void executeCompileGoal() {
212+
// The class files should not exist
213+
assertFalse(fileExists("target/classes/Bar.class"));
214+
assertFalse(fileExists("target/classes/Baz.class"));
215+
assertFalse(fileExists("target/classes/Foo.class"));
216+
// Execute the 'compile' target
217+
new MavenCli().doMain(
218+
new String[]{"compile"},
219+
projectDir.getAbsolutePath(),
220+
null,
221+
null);
222+
// The class files should exist now
223+
assertTrue( fileExists( "target/classes/Bar.class" ) );
224+
assertTrue( fileExists( "target/classes/Baz.class" ) );
225+
assertTrue( fileExists( "target/classes/Foo.class" ) );
226+
}
227+
228+
private void executeEnhanceGoal() throws Exception {
229+
// The class files should not be enhanced at this point
230+
assertFalse( isEnhanced( "Bar" ));
231+
assertFalse( isEnhanced( "Baz" ));
232+
assertFalse( isEnhanced( "Foo" ));
233+
// Execute the 'enhance' target
234+
mavenCli.doMain(
235+
new String[]{"process-classes"},
236+
projectDir.getAbsolutePath(),
237+
null,
238+
null);
239+
// The results are verified in the respective tests
240+
}
241+
242+
private void preparePomXml(String configurationElement) throws Exception {
243+
URL url = getClass().getClassLoader().getResource("pom.xm_");
244+
File source = new File(url.toURI());
245+
assertFalse( fileExists( "pom.xml" ));
246+
String pomXmlContents = new String(Files.readAllBytes( source.toPath() ));
247+
pomXmlContents = pomXmlContents.replace( "@hibernate-version@", System.getenv("hibernateVersion"));
248+
pomXmlContents = pomXmlContents.replace( "@configuration@", configurationElement);
249+
File destination = new File(projectDir, "pom.xml");
250+
Files.writeString(destination.toPath(), pomXmlContents);
251+
assertTrue( fileExists( "pom.xml" ) );
252+
}
253+
254+
private void copyJavFiles() throws Exception {
255+
File srcDir = new File(projectDir, "src/main/java");
256+
srcDir.mkdirs();
257+
String[] javFileNames = {"Bar.jav_", "Baz.jav_", "Foo.jav_"};
258+
for (String javFileName : javFileNames) {
259+
copyJavFile( javFileName, srcDir );
260+
}
261+
}
262+
263+
private void copyJavFile(String javFileName, File toFolder) throws Exception {
264+
URL url = getClass().getClassLoader().getResource( javFileName );
265+
assert url != null;
266+
File source = new File(url.toURI());
267+
File destination = new File(toFolder, javFileName.replace( '_', 'a' ));
268+
assertTrue(source.exists());
269+
assertTrue(source.isFile());
270+
Files.copy(source.toPath(), destination.toPath());
271+
assertTrue(destination.exists());
272+
assertTrue(destination.isFile());
273+
}
274+
275+
private ClassLoader getTestClassLoader() throws Exception {
276+
return new URLClassLoader( new URL[] { new File(projectDir, "target/classes").toURI().toURL() } );
277+
}
278+
279+
private boolean isEnhanced(String className) throws Exception {
280+
return getTestClassLoader().loadClass( className ).isAnnotationPresent( EnhancementInfo.class );
281+
}
282+
283+
private boolean methodIsPresentInClass(String methodName, String className) throws Exception {
284+
Class<?> classToCheck = getTestClassLoader().loadClass( className );
285+
try {
286+
Object m = classToCheck.getMethod( methodName, new Class[] {} );
287+
return true;
288+
} catch (NoSuchMethodException e) {
289+
return false;
290+
}
291+
}
292+
293+
private boolean isAssociationManagementPresent() throws Exception {
294+
// Some dynamic programming
295+
ClassLoader loader = getTestClassLoader();
296+
// Obtain the class objects for 'Baz' and 'Bar'
297+
Class<?> bazClass = loader.loadClass( "Baz" );
298+
Class<?> barClass = loader.loadClass( "Bar" );
299+
// Create an instance of both 'Baz' and 'Bar'
300+
Object bazObject = bazClass.getDeclaredConstructor().newInstance();
301+
Object barObject = barClass.getDeclaredConstructor().newInstance();
302+
// Lookup the 'bars' field of class 'Baz' (an ArrayList of 'Bar' objects)
303+
Field bazBarsField = bazClass.getDeclaredField( "bars" );
304+
bazBarsField.setAccessible( true );
305+
// Obtain the 'bars' list of the 'Baz' object; it should be empty
306+
List<?> bazBarsList = (List<?>) bazBarsField.get( bazObject ); // baz.bars
307+
assertTrue(bazBarsList.isEmpty());
308+
// Lookup the 'setBaz' method of class 'Bar' and invoke it on the 'Bar' object
309+
Method barSetBazMethod = barClass.getDeclaredMethod( "setBaz", new Class[] { bazClass } );
310+
barSetBazMethod.invoke( barObject, bazObject ); // bar.setBaz(baz)
311+
// Reobtain the 'bars' list of the 'Baz' object
312+
bazBarsList = (List<?>) bazBarsField.get( bazObject );
313+
// If there is association management, the 'bars' list should contain the 'Bar' object
314+
return bazBarsList.contains( barObject ); // baz.bars.contains(bar)
315+
}
316+
317+
private boolean fileExists(String relativePath) {
318+
return new File( projectDir, relativePath ).exists();
319+
}
320+
321+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /