diff --git a/tooling/hibernate-maven-plugin/hibernate-maven-plugin.gradle b/tooling/hibernate-maven-plugin/hibernate-maven-plugin.gradle
index 8cf198508b36..3f09b9a3c36f 100644
--- a/tooling/hibernate-maven-plugin/hibernate-maven-plugin.gradle
+++ b/tooling/hibernate-maven-plugin/hibernate-maven-plugin.gradle
@@ -12,14 +12,34 @@ plugins {
description = 'Maven plugin to integrate aspects of Hibernate into your build.'
+sourceSets {
+ intTest {
+ compileClasspath += sourceSets.main.output
+ runtimeClasspath += sourceSets.main.output
+ }
+}
+
+configurations {
+ intTestImplementation.extendsFrom implementation
+ intTestRuntimeOnly.extendsFrom runtimeOnly
+}
+
dependencies {
implementation project( ":hibernate-core" )
- implementation "org.apache.maven:maven-plugin-api:3.6.3"
+ implementation "org.apache.maven:maven-plugin-api:3.9.11"
implementation "org.apache.maven:maven-project:2.2.1"
implementation "org.apache.maven.shared:file-management:3.1.0"
- compileOnly "org.apache.maven.plugin-tools:maven-plugin-annotations:3.6.0"
+ compileOnly "org.apache.maven.plugin-tools:maven-plugin-tools-annotations:3.15.1"
+
+ intTestImplementation 'org.junit.jupiter:junit-jupiter:5.13.4'
+ intTestImplementation 'org.apache.maven:maven-embedder:3.9.11'
+ intTestRuntimeOnly 'org.junit.platform:junit-platform-launcher'
+ intTestRuntimeOnly 'ch.qos.logback:logback-classic:1.5.18'
+ intTestRuntimeOnly 'org.apache.maven:maven-compat:3.9.11'
+ intTestRuntimeOnly 'org.apache.maven.resolver:maven-resolver-transport-http:1.9.24'
+ intTestRuntimeOnly 'org.apache.maven.resolver:maven-resolver-connector-basic:1.9.24'
}
def releasePrepareTask = tasks.register("releasePrepare") {
@@ -37,6 +57,22 @@ tasks.register("preVerifyRelease") {
dependsOn releasePrepareTask
}
+tasks.register('integrationTest', Test) {
+ description = 'Runs integration tests.'
+ group = 'verification'
+
+ testClassesDirs = sourceSets.intTest.output.classesDirs
+ classpath = sourceSets.intTest.runtimeClasspath
+ shouldRunAfter test
+
+ useJUnitPlatform()
+
+}
+
+tasks.forbiddenApisIntTest {
+ enabled = false
+}
+
var publishingExtension = project.getExtensions().getByType(PublishingExtension) as PublishingExtension
publishingExtension.publications.named("publishedArtifacts") {
from components.java
@@ -64,3 +100,10 @@ publishingExtension.publications.named("publishedArtifacts") {
}
}
+integrationTest {
+ environment "hibernateVersion", project.version
+}
+
+integrationTest.dependsOn rootProject.childProjects.'hibernate-core'.tasks.publishToMavenLocal
+integrationTest.dependsOn publishToMavenLocal
+check.dependsOn integrationTest
diff --git a/tooling/hibernate-maven-plugin/src/intTest/java/org/hibernate/orm/tooling/maven/EnhancerMojoTestIT.java b/tooling/hibernate-maven-plugin/src/intTest/java/org/hibernate/orm/tooling/maven/EnhancerMojoTestIT.java
new file mode 100644
index 000000000000..14f557ff3bd7
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/java/org/hibernate/orm/tooling/maven/EnhancerMojoTestIT.java
@@ -0,0 +1,321 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * Copyright Red Hat Inc. and Hibernate Authors
+ */
+package org.hibernate.orm.tooling.maven;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+import org.apache.maven.cli.MavenCli;
+import org.hibernate.bytecode.enhance.spi.EnhancementInfo;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Files;
+import java.util.List;
+
+public class EnhancerMojoTestIT {
+
+ public static final String MVN_HOME = "maven.multiModuleProjectDirectory";
+
+ @TempDir
+ File projectDir;
+
+ private MavenCli mavenCli;
+
+ @BeforeEach
+ public void beforeEach() throws Exception {
+ copyJavFiles();
+ System.setProperty(MVN_HOME, projectDir.getAbsolutePath());
+ mavenCli = new MavenCli();
+ }
+
+ @Test
+ public void testEnhancementDefault() throws Exception {
+ // The default configuration for the enhance goal are as follows:
+ // enableLazyInitialization = 'true'
+ // enableDirtyTracking = 'true'
+ // enableAssociationManagement = 'false'
+ // enableExtendedEnhancement = 'false'
+ // classesDirectory = 'target/classes'
+ String configurationElement = "\n";
+ preparePomXml(configurationElement);
+ executeCompileGoal();
+ executeEnhanceGoal();
+ // Both Bar and Baz should be enhanced
+ assertTrue(isEnhanced( "Bar" ));
+ assertTrue(isEnhanced( "Baz" ));
+ // Both Bar and Baz contain the method '$$_hibernate_getInterceptor'
+ // because of the default setting of 'enableLazyInitialization'
+ assertTrue( methodIsPresentInClass("$$_hibernate_getInterceptor", "Bar"));
+ assertTrue( methodIsPresentInClass("$$_hibernate_getInterceptor", "Baz"));
+ // Both Bar and Baz contain the method '$$_hibernate_hasDirtyAttributes'
+ // because of the default setting of 'enableDirtyTracking'
+ assertTrue( methodIsPresentInClass("$$_hibernate_hasDirtyAttributes", "Bar"));
+ assertTrue( methodIsPresentInClass("$$_hibernate_hasDirtyAttributes", "Baz"));
+ // Foo is not an entity and extended enhancement is not enabled so the class is not enhanced
+ assertFalse(isEnhanced("Foo"));
+ // Association management should not be present
+ assertFalse(isAssociationManagementPresent());
+ }
+
+ @Test
+ public void testEnhancementFileSet() throws Exception {
+ // Use the defaults settings for enhancement (see #testEnhancementDefault)
+ // The files are read from the specified 'fileset' element:
+ // - the folder specified by 'dir'
+ // - the 'Baz.class' file is excluded
+ String configurationElement =
+ "\n" +
+ " \n"+
+ " \n" +
+ " " + projectDir.getAbsolutePath() + "/target" + "\n" +
+ " \n" +
+ " **/Baz.class\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ "\n";
+ preparePomXml(configurationElement);
+ executeCompileGoal();
+ executeEnhanceGoal();
+ // Bar is enhanced
+ assertTrue(isEnhanced( "Bar" ));
+ // Baz is not enhanced because it was excluded from the file set
+ assertFalse(isEnhanced( "Baz" ));
+ // Foo is not enhanced because it is not an entity and extended enhancement was not enabled
+ assertFalse( isEnhanced( "Foo" ) );
+ // Association management should not be present
+ assertFalse(isAssociationManagementPresent());
+ }
+
+ @Test
+ public void testEnhancementNoLazyInitialization() throws Exception {
+ // Change the default setting for 'enableLazyInitialization' to 'false'
+ // Otherwise use the settings of #testEnhancementDefault
+ String configurationElement =
+ "\n" +
+ " false\n"+
+ "\n";
+ preparePomXml(configurationElement);
+ executeCompileGoal();
+ executeEnhanceGoal();
+ // Both Bar and Baz are enhanced, Foo is not
+ assertTrue( isEnhanced( "Bar" ));
+ assertTrue( isEnhanced( "Baz" ));
+ // Foo is not enhanced because it is not an entity and extended enhancement was not enabled
+ assertFalse( isEnhanced( "Foo" ) );
+ // but $$_hibernate_getInterceptor is not present in the enhanced classes
+ // because of the 'false' value of 'enableLazyInitialization'
+ assertFalse( methodIsPresentInClass("$$_hibernate_getInterceptor", "Bar"));
+ assertFalse( methodIsPresentInClass("$$_hibernate_getInterceptor", "Baz"));
+ // Association management should not be present
+ assertFalse(isAssociationManagementPresent());
+ }
+
+ @Test
+ public void testEnhancementNoDirtyTracking() throws Exception {
+ // Change the default setting for 'enableDirtyTracking' to 'false'
+ // Otherwise use the settings of #testEnhancementDefault
+ String configurationElement =
+ "\n" +
+ " false\n"+
+ "\n";
+ preparePomXml(configurationElement);
+ executeCompileGoal();
+ executeEnhanceGoal();
+ // Both Bar and Baz should be enhanced
+ assertTrue( isEnhanced( "Bar" ));
+ assertTrue( isEnhanced( "Baz" ));
+ // Foo is not enhanced because it is not an entity and extended enhancement was not enabled
+ assertFalse( isEnhanced( "Foo" ) );
+ // $$_hibernate_hasDirtyAttributes is not present in the enhanced classes
+ // because of the 'false' value of 'enableLazyInitialization'
+ assertFalse( methodIsPresentInClass("$$_hibernate_hasDirtyAttributes", "Bar"));
+ assertFalse( methodIsPresentInClass("$$_hibernate_hasDirtyAttributes", "Baz"));
+ // Association management should not be present
+ assertFalse(isAssociationManagementPresent());
+ }
+
+ @Test
+ public void testEnhancementEnableAssociationManagement() throws Exception {
+ // Change the default setting for 'enableAssociationManagement' to 'true'
+ // Otherwise use the settings of #testEnhancementDefault
+ String configurationElement =
+ "\n" +
+ " true\n"+
+ "\n";
+ preparePomXml(configurationElement);
+ executeCompileGoal();
+ executeEnhanceGoal();
+ // Both Bar and Baz are enhanced, Foo is not
+ assertTrue( isEnhanced( "Bar" ));
+ assertTrue( isEnhanced( "Baz" ));
+ assertFalse( isEnhanced( "Foo" ) );
+ // Now verify that the association management is in place;
+ assertTrue(isAssociationManagementPresent());
+ }
+
+ @Test
+ public void testEnhancementEnableExtendedEnhancement() throws Exception {
+ // Change the default setting for 'enableExtendedEnhancement' to 'true'
+ // Otherwise use the settings of #testEnhancementDefault
+ String configurationElement =
+ "\n" +
+ " true\n"+
+ "\n";
+ preparePomXml(configurationElement);
+ executeCompileGoal();
+ executeEnhanceGoal();
+ // Both Bar and Baz are enhanced because they are entities
+ assertTrue( isEnhanced( "Bar" ));
+ assertTrue( isEnhanced( "Baz" ));
+ // Though Foo is not an entity, it is enhanced because of the setting of 'enableExtendedEnhancement'
+ assertTrue( isEnhanced( "Foo" ) );
+ // No association management is in place;
+ assertFalse(isAssociationManagementPresent());
+ }
+
+
+ @Test
+ public void testNoEnhancement() throws Exception {
+ // Setting the values of all the settings to 'false' has the effect
+ // of not executing the enhancement at all.
+ // The setting of 'enableAssociationManagement' and 'enableExtendedEnhancement' to
+ // false is not really needed in this case as that's what their default is
+ String configurationElement =
+ "\n" +
+ " false\n"+
+ " false\n"+
+ " false\n"+
+ " false\n"+
+ "\n";
+ preparePomXml(configurationElement);
+ executeCompileGoal();
+ executeEnhanceGoal();
+ // None of the classes should be enhanced
+ assertFalse( isEnhanced( "Bar" ));
+ assertFalse( isEnhanced( "Baz" ));
+ assertFalse( isEnhanced( "Foo" ) );
+ // No association management is in place;
+ assertFalse(isAssociationManagementPresent());
+ }
+
+ private void executeCompileGoal() {
+ // The class files should not exist
+ assertFalse(fileExists("target/classes/Bar.class"));
+ assertFalse(fileExists("target/classes/Baz.class"));
+ assertFalse(fileExists("target/classes/Foo.class"));
+ // Execute the 'compile' target
+ new MavenCli().doMain(
+ new String[]{"compile"},
+ projectDir.getAbsolutePath(),
+ null,
+ null);
+ // The class files should exist now
+ assertTrue( fileExists( "target/classes/Bar.class" ) );
+ assertTrue( fileExists( "target/classes/Baz.class" ) );
+ assertTrue( fileExists( "target/classes/Foo.class" ) );
+ }
+
+ private void executeEnhanceGoal() throws Exception {
+ // The class files should not be enhanced at this point
+ assertFalse( isEnhanced( "Bar" ));
+ assertFalse( isEnhanced( "Baz" ));
+ assertFalse( isEnhanced( "Foo" ));
+ // Execute the 'enhance' target
+ mavenCli.doMain(
+ new String[]{"process-classes"},
+ projectDir.getAbsolutePath(),
+ null,
+ null);
+ // The results are verified in the respective tests
+ }
+
+ private void preparePomXml(String configurationElement) throws Exception {
+ URL url = getClass().getClassLoader().getResource("pom.xm_");
+ File source = new File(url.toURI());
+ assertFalse( fileExists( "pom.xml" ));
+ String pomXmlContents = new String(Files.readAllBytes( source.toPath() ));
+ pomXmlContents = pomXmlContents.replace( "@hibernate-version@", System.getenv("hibernateVersion"));
+ pomXmlContents = pomXmlContents.replace( "@configuration@", configurationElement);
+ File destination = new File(projectDir, "pom.xml");
+ Files.writeString(destination.toPath(), pomXmlContents);
+ assertTrue( fileExists( "pom.xml" ) );
+ }
+
+ private void copyJavFiles() throws Exception {
+ File srcDir = new File(projectDir, "src/main/java");
+ srcDir.mkdirs();
+ String[] javFileNames = {"Bar.jav_", "Baz.jav_", "Foo.jav_"};
+ for (String javFileName : javFileNames) {
+ copyJavFile( javFileName, srcDir );
+ }
+ }
+
+ private void copyJavFile(String javFileName, File toFolder) throws Exception {
+ URL url = getClass().getClassLoader().getResource( javFileName );
+ assert url != null;
+ File source = new File(url.toURI());
+ File destination = new File(toFolder, javFileName.replace( '_', 'a' ));
+ assertTrue(source.exists());
+ assertTrue(source.isFile());
+ Files.copy(source.toPath(), destination.toPath());
+ assertTrue(destination.exists());
+ assertTrue(destination.isFile());
+ }
+
+ private ClassLoader getTestClassLoader() throws Exception {
+ return new URLClassLoader( new URL[] { new File(projectDir, "target/classes").toURI().toURL() } );
+ }
+
+ private boolean isEnhanced(String className) throws Exception {
+ return getTestClassLoader().loadClass( className ).isAnnotationPresent( EnhancementInfo.class );
+ }
+
+ private boolean methodIsPresentInClass(String methodName, String className) throws Exception {
+ Class> classToCheck = getTestClassLoader().loadClass( className );
+ try {
+ Object m = classToCheck.getMethod( methodName, new Class[] {} );
+ return true;
+ } catch (NoSuchMethodException e) {
+ return false;
+ }
+ }
+
+ private boolean isAssociationManagementPresent() throws Exception {
+ // Some dynamic programming
+ ClassLoader loader = getTestClassLoader();
+ // Obtain the class objects for 'Baz' and 'Bar'
+ Class> bazClass = loader.loadClass( "Baz" );
+ Class> barClass = loader.loadClass( "Bar" );
+ // Create an instance of both 'Baz' and 'Bar'
+ Object bazObject = bazClass.getDeclaredConstructor().newInstance();
+ Object barObject = barClass.getDeclaredConstructor().newInstance();
+ // Lookup the 'bars' field of class 'Baz' (an ArrayList of 'Bar' objects)
+ Field bazBarsField = bazClass.getDeclaredField( "bars" );
+ bazBarsField.setAccessible( true );
+ // Obtain the 'bars' list of the 'Baz' object; it should be empty
+ List> bazBarsList = (List>) bazBarsField.get( bazObject ); // baz.bars
+ assertTrue(bazBarsList.isEmpty());
+ // Lookup the 'setBaz' method of class 'Bar' and invoke it on the 'Bar' object
+ Method barSetBazMethod = barClass.getDeclaredMethod( "setBaz", new Class[] { bazClass } );
+ barSetBazMethod.invoke( barObject, bazObject ); // bar.setBaz(baz)
+ // Reobtain the 'bars' list of the 'Baz' object
+ bazBarsList = (List>) bazBarsField.get( bazObject );
+ // If there is association management, the 'bars' list should contain the 'Bar' object
+ return bazBarsList.contains( barObject ); // baz.bars.contains(bar)
+ }
+
+ private boolean fileExists(String relativePath) {
+ return new File( projectDir, relativePath ).exists();
+ }
+
+}
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/Bar.jav_ b/tooling/hibernate-maven-plugin/src/intTest/resources/Bar.jav_
new file mode 100644
index 000000000000..a5b7325842f7
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/Bar.jav_
@@ -0,0 +1,24 @@
+import jakarta.persistence.Entity;
+import jakarta.persistence.ManyToOne;
+
+@Entity
+public class Bar {
+
+ private String foo;
+
+ @ManyToOne
+ private Baz baz;
+
+ public String getFoo() {
+ return foo;
+ }
+
+ public void setFoo(String f) {
+ foo = f;
+ }
+
+ public Baz getBaz() { return baz; }
+
+ public void setBaz(Baz baz) { this.baz = baz; }
+
+}
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/Baz.jav_ b/tooling/hibernate-maven-plugin/src/intTest/resources/Baz.jav_
new file mode 100644
index 000000000000..5e33d11767bb
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/Baz.jav_
@@ -0,0 +1,27 @@
+import jakarta.persistence.Entity;
+import jakarta.persistence.OneToMany;
+
+import java.util.List;
+import java.util.ArrayList;
+
+@Entity
+public class Baz {
+
+ private String foo;
+
+ @OneToMany(mappedBy = "baz")
+ private List bars = new ArrayList();
+
+ String getFoo() {
+ return foo;
+ }
+
+ public void setFoo(String f) {
+ foo = f;
+ }
+
+ public void addBar(Bar bar) {
+ bars.add( bar );
+ }
+
+}
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/Foo.jav_ b/tooling/hibernate-maven-plugin/src/intTest/resources/Foo.jav_
new file mode 100644
index 000000000000..4c3df431118c
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/Foo.jav_
@@ -0,0 +1,13 @@
+public class Foo {
+
+ private Bar bar;
+
+ Bar getBar() {
+ return bar;
+ }
+
+ public void setBar(Bar b) {
+ bar = b;
+ }
+
+}
diff --git a/tooling/hibernate-maven-plugin/src/intTest/resources/pom.xm_ b/tooling/hibernate-maven-plugin/src/intTest/resources/pom.xm_
new file mode 100644
index 000000000000..6f48cc3aaa3a
--- /dev/null
+++ b/tooling/hibernate-maven-plugin/src/intTest/resources/pom.xm_
@@ -0,0 +1,39 @@
+
+
+ 4.0.0
+
+ org.hibernate.orm.tooling.maven
+ enhance-test
+ 0.0.1-SNAPSHOT
+
+
+ @hibernate-version@
+
+
+
+
+ org.hibernate.orm
+ hibernate-core
+ ${hibernate.version}
+
+
+
+
+
+
+ org.hibernate.orm
+ hibernate-maven-plugin
+ ${hibernate.version}
+
+
+ @configuration@
+
+ enhance
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tooling/hibernate-maven-plugin/src/main/java/org/hibernate/orm/tooling/maven/HibernateEnhancerMojo.java b/tooling/hibernate-maven-plugin/src/main/java/org/hibernate/orm/tooling/maven/HibernateEnhancerMojo.java
index 061af2c34be0..aa924ab9e186 100644
--- a/tooling/hibernate-maven-plugin/src/main/java/org/hibernate/orm/tooling/maven/HibernateEnhancerMojo.java
+++ b/tooling/hibernate-maven-plugin/src/main/java/org/hibernate/orm/tooling/maven/HibernateEnhancerMojo.java
@@ -33,29 +33,57 @@ public class HibernateEnhancerMojo extends AbstractMojo {
final private List sourceSet = new ArrayList();
private Enhancer enhancer;
+ /**
+ * A list of FileSets in which to look for classes to enhance.
+ * This parameter is optional but if it is specified, the 'classesDirectory' parameter is ignored.
+ */
@Parameter
private FileSet[] fileSets;
+ /**
+ * The folder in which to look for classes to enhance.
+ * This parameter is required but if the 'fileSets' parameter is specified, it will be ignored.
+ */
@Parameter(
defaultValue = "${project.build.directory}/classes",
required = true)
private File classesDirectory;
+ /**
+ * A boolean that indicates whether or not to add association management to automatically
+ * synchronize a bidirectional association when only one side is changed
+ */
@Parameter(
defaultValue = "false",
required = true)
private boolean enableAssociationManagement;
+ /**
+ * A boolean that indicates whether or not to add dirty tracking
+ * @deprecated See HHH-15641
+ */
+ @Deprecated(
+ forRemoval = true)
@Parameter(
- defaultValue = "false",
+ defaultValue = "true",
required = true)
private boolean enableDirtyTracking;
+ /**
+ * A boolean that indicates whether or not to add lazy initialization
+ * @deprecated See HHH-15641
+ */
+ @Deprecated(
+ forRemoval = true)
@Parameter(
- defaultValue = "false",
+ defaultValue = "true",
required = true)
private boolean enableLazyInitialization;
+ /**
+ * A boolean that indicates whether or not to add extended enhancement.
+ * This setting will provide bytecode enhancement, even for non-entity classes
+ */
@Parameter(
defaultValue = "false",
required = true)
@@ -64,13 +92,23 @@ public class HibernateEnhancerMojo extends AbstractMojo {
public void execute() {
getLog().debug(STARTING_EXECUTION_OF_ENHANCE_MOJO);
processParameters();
- assembleSourceSet();
- createEnhancer();
- discoverTypes();
- performEnhancement();
+ if (enhancementIsNeeded()) {
+ assembleSourceSet();
+ createEnhancer();
+ discoverTypes();
+ performEnhancement();
+ }
getLog().debug(ENDING_EXECUTION_OF_ENHANCE_MOJO);
}
+ private boolean enhancementIsNeeded() {
+ // enhancement is not needed when all the parameters are false
+ return enableAssociationManagement ||
+ enableDirtyTracking ||
+ enableLazyInitialization ||
+ enableExtendedEnhancement;
+ }
+
private void processParameters() {
if (!enableLazyInitialization) {
getLog().warn(ENABLE_LAZY_INITIALIZATION_DEPRECATED);
diff --git a/tooling/hibernate-maven-plugin/src/test/java/org/hibernate/orm/tooling/maven/HibernateEnhancerMojoTest.java b/tooling/hibernate-maven-plugin/src/test/java/org/hibernate/orm/tooling/maven/HibernateEnhancerMojoTest.java
index 93853350184d..243812245525 100644
--- a/tooling/hibernate-maven-plugin/src/test/java/org/hibernate/orm/tooling/maven/HibernateEnhancerMojoTest.java
+++ b/tooling/hibernate-maven-plugin/src/test/java/org/hibernate/orm/tooling/maven/HibernateEnhancerMojoTest.java
@@ -519,6 +519,9 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl
@Test
void testExecute() throws Exception {
+ Field enableDirtyTrackingField = HibernateEnhancerMojo.class.getDeclaredField( "enableDirtyTracking" );
+ enableDirtyTrackingField.setAccessible( true );
+ enableDirtyTrackingField.set( enhanceMojo, true );
Method executeMethod = HibernateEnhancerMojo.class.getDeclaredMethod("execute", new Class[] {});
executeMethod.setAccessible(true);
final String barSource =