Discuss project

How to Install Hibernate 5.4.5/JPA 2.2 in AEM 6.4.4

Authors: Svetlana Suvorova, Alexander Markov

Softwerke experts share their own experience of Hibernate 5.4.5 deployment in Adobe Experience Manager 6.4.4 (further AEM) and database connection setup like MySQL according to JPA 2.2. This task is not trivial as, for instance, there is not enough information on this topic on the Web. We hope this article will be useful if you are struggling with Hibernate/JPA integration in AEM.

Contents

1. Technical Requirements

To install Hibernate 5.4.5 you will need preinstalled:

  • Java 8
  • Adobe Experience Manager 6.4.4
  • Maven 3

2. Hibernate 5.4.5 Installation in AEM 6.4.4

Screenshot below shows all modules needed for successful Hibernate ORM operation in OSGi (Apache Felix). Each module is installed in AEM as a separate bundle. All required OSGi dependencies for Hibernate are listed in Appendix 1.

If all dependencies are successfully installed and activated, hibernate-osgi bundle provides javax.persistence.spi.PersistenceProvider service which can be injected in your application to interact with your database.

Installation of the required Hibernate dependencies can be done in different ways in AEM.

  1. Classic approach is based on the package installation with Maven. All required bundles are embedded into a zip package with com.day.jcr.vault:content-package-maven-plugin and then installed in AEM via Package Manager. Example of POM.xml for Hibernate installation as a zip content package is located in Appendix 2.

  1. Another approach installs all bundles in predefined order with org.apache.sling:sling-maven-plugin called by Apache Maven Invoker API. Example of POM.xml and HibernateInstall.java for such installation can be found in Appendix 3.

3. Maven Application Dependencies

Example of Maven dependencies to enable Hibernate/JPA/MySQL integration in AEM:

<dependencies>
    ...
    <!-- Hibernate dependencies -->
    <dependency>
        <groupId>javax.persistence</groupId>
        <artifactId>javax.persistence-api</artifactId>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-osgi</artifactId>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>com.day.commons</groupId>
        <artifactId>day.commons.datasource.poolservice</artifactId>
    </dependency>
</dependencies>

4. JPA/JDBC Properties Setup in AEM

Persistence properties for Hibernate ORM are loaded in two steps.

4.1. Loading of JPA persistence.xml

Path to persistence.xml is set in the bundle manifest configuration <Meta-Persistence> tag.

<build>
    <plugins>
         <plugin>
            <groupId>org.apache.felix</groupId>
            <artifactId>maven-bundle-plugin</artifactId>
            <extensions>true</extensions>
            <configuration>
                <instructions>
                    <Import-Package>
    	                 javax.persistence;version="2.2.0",
                         org.hibernate.proxy,
                         javassist.util.proxy,
                         *
                    </Import-Package>
                    <Meta-Persistence>META-INF/persistence.xml</Meta-Persistence>
                    ...
                </instructions>
            </configuration>
        </plugin>
    <plugins>
</build>

Required parameters:

  • name – title of the persistence-unit;
  • transaction-type – is set to RESOURCE_LOCAL as unmanaged JPA access is used to communicate with database via EntityManagerFactory;
  • class – list of Entity classes;
  • exclude-unlisted-classes = false so that Hibernate manages all Entity classes not defined in persistence.xml.
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2"
             xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
    http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
    <persistence-unit name="softwerke-hibernate" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <class>com.softwerke.integration.jpa.entity.EntityClassName</class>
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
    </persistence-unit>
</persistence>

4.2. Loading of JDBC properties with AEM OSGi configuration

To make Hibernate/JPA properties manageable in runtime create OSGi configuration with corresponding JDBC connection properties needed to communicate with a database like MySQL:

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
          jcr:primaryType="sling:OsgiConfig"
          hibernate.dialect="org.hibernate.dialect.MySQLDialect"
          hibernate.connection.driver_class="com.mysql.jdbc.Driver"
          hibernate.connection.url="jdbc:mysql//…"
          hibernate.show_sql="false"
          hibernate.format_sql="true"
          hibernate.connection.username="user"
          hibernate.connection.password="password"/>

5. AEM-Database Interaction via javax.persistence.EntityManager

Here is an example of a simple JPA transaction with Hibernate/JPA properties loaded from AEM OSGi configuration jpaEntityManagerConfiguration:

BundleContext context = thisBundle.getBundleContext();
ServiceReference serviceReference = context.getServiceReference(PersistenceProvider.class.getName());
PersistenceProvider persistenceProvider = (PersistenceProvider) context.getService(serviceReference);
entityManagerFactory = persistenceProvider.createEntityManagerFactory("softwerke-hibernate",
    JpaPersistenceProperties.getProperties(jpaEntityManagerConfiguration));
EntityManager entityManager = entityManagerFactory.createEntityManager();
EntityTransaction transaction = entityManager.getTransaction();
// SQL queries, transactions…

Appendix 1. Hibernate 5.4.5 OSGi dependencies for AEM 6.4.4

Show table of Hibernate 5.4.5 OSGi dependencies
# Dependency group and artifact name Version Parent dependency Bundle
1 org.hibernate » hibernate-osgi 5.4.5.Final   hibernate-osgi-5.4.5.Final.jar
2 javax.interceptor »javax.interceptor-api 1.2 hibernate-osgi
cdi-api
javax.interceptor-api-1.2.2.jarcdi-api-1.2.jar
3 net.bytebuddy » byte-buddy 1.9.11 hibernate-osgi
org.osgi.core
byte-buddy-1.9.11.jar
4 org.hibernate » hibernate-core 5.4.5.Final hibernate-osgi hibernate-core-5.4.5.Final.jar
5 org.jboss.logging » jboss-logging 3.3.2.Final hibernate-osgi
hibernate-commons-annotations
org.osgi.core
jboss-logging-3.3.2.Final.jar
  org.osgi » org.osgi.core 6.0.0   Provided by AEM
  org.osgi » org.osgi.compendium 5.0.0   Provided by AEM
6 antlr » antlr 2.7.7 org.osgi.core org.apache.servicemix.bundles.antlr-2.7.7_5.jar
7 com.fasterxml » classmate 1.3.4 org.osgi.core classmate-1.3.4.jar
8 javax.activation » javax.activation-api 1.2.0 org.osgi.core
jaxb-runtime
jaxb-api
javax.activation-api-1.2.0.jar
9 javax.persistence » javax.persistence-api 2.2 org.osgi.core javax.persistence-api-2.2.jar
10 javax.xml.bind » jaxb-api 2.3.1 org.osgi.core
jaxb-runtime
jaxb-api-2.3.1.jar
11 org.dom4j » dom4j 2.1.1 org.osgi.core org.apache.servicemix.bundles.dom4j-2.1.1_1.jar
12 javax.activation » activation 1.1 jaxb-runtime
javax.activation-api
javax.activation-1.2.0.jar
13 javax.enterprise » cdi-api 1.2 jboss-transaction-api_1.2_spec cdi-api-1.2.jar
14 org.jboss.spec.javax.interceptor » jboss-interceptors-api_1.2_spec 1.0.1.Final jboss-transaction-api_1.2_spec jboss-interceptors-api_1.2_spec-1.0.1.Final.jar
15 javax.el » javax.el-api 3.0.0 cdi-api javax.el-api-2.2.5.jar
16 javax.inject » javax.inject 1 cdi-api org.apache.servicemix.bundles.javax-inject-1_2.jar
17 org.glassfish.jaxb » jaxb-runtime 2.3.1 org.osgi.core org.apache.servicemix.bundles.jaxb-runtime-2.3.1_1.jar
18 org.hibernate.common » hibernate-commons-annotations 5.1.0.Final org.osgi.core hibernate-commons-annotations-5.1.0.Final.jar
19 org.javassist » javassist 3.24.0-GA org.osgi.core javassist-3.24.0-GA.jar
20 org.jboss » jandex 2.0.5.Final org.osgi.core jandex-2.0.5.Final.jar
21 org.jboss.spec.javax.transaction » jboss-transaction-api_1.2_spec 1.1.1.Final org.osgi.core jboss-transaction-api_1.2_spec-1.1.1.Final.jar
22 com.sun.istack » istack-commons-runtime 3.0.7 jaxb-runtime istack-commons-runtime-3.0.7.jar
23 com.sun.xml.fastinfoset » FastInfoset 1.2.15 jaxb-runtime FastInfoset-1.2.16.jar
  org.glassfish.jaxb » txw2 2.3.1 jaxb-runtime Embedded in org.apache.servicemix.bundles.jaxb-runtime-2.3.1_1.jar

Appendix 2. How to Install Hibernate 5.4.5 in AEM 6.4.4 with content-package-maven-plugin

Below is a part of POM.xml with Maven profile for classic application installation in AEM 6.4.4 Package Manager as a zip-package with content-package-maven-plugin.

Show Maven profile for Hibernate 5.4.5 package installation in AEM 6.4.4
<profiles>
    <profile>
        <id>installHibernate</id>
        <activation>
            <activeByDefault>false</activeByDefault>
        </activation>
        <build>
            <plugins>
                <plugin>
                    <groupId>com.day.jcr.vault</groupId>
                    <artifactId>content-package-maven-plugin</artifactId>
                    <extensions>true</extensions>
                    <configuration>
                        <embeddedTarget>/apps/hibernate/install</embeddedTarget>
                        <embeddeds>
                            <embedded>
                                <groupId>org.apache.servicemix.bundles</groupId>
                                <artifactId>org.apache.servicemix.bundles.antlr</artifactId>
                            </embedded>
                            <embedded>
                                <groupId>com.fasterxml</groupId>
                                <artifactId>classmate</artifactId>
                            </embedded>
                            <embedded>
                                <groupId>com.sun.activation</groupId>
                                <artifactId>javax.activation</artifactId>
                            </embedded>
                            <embedded>
                                <groupId>javax.activation</groupId>
                                <artifactId>javax.activation-api</artifactId>
                            </embedded>
                            <embedded>
                                <groupId>javax.persistence</groupId>
                                <artifactId>javax.persistence-api</artifactId>
                            </embedded>
                            <embedded>
                                <groupId>javax.xml.bind</groupId>
                                <artifactId>jaxb-api</artifactId>
                            </embedded>
                            <embedded>
                                <groupId>net.bytebuddy</groupId>
                                <artifactId>byte-buddy</artifactId>
                            </embedded>
                            <embedded>
                                <groupId>org.apache.servicemix.bundles</groupId>
                                <artifactId>org.apache.servicemix.bundles.dom4j</artifactId>
                            </embedded>
                            <embedded>
                                <groupId>com.sun.istack</groupId>
                                <artifactId>istack-commons-runtime</artifactId>
                            </embedded>
                            <embedded>
                                <groupId>com.sun.xml.fastinfoset</groupId>
                                <artifactId>FastInfoset</artifactId>
                            </embedded>
                            <embedded>
                                <groupId>org.apache.servicemix.bundles</groupId>
                                <artifactId>org.apache.servicemix.bundles.jaxb-runtime</artifactId>
                            </embedded>
                            <embedded>
                                <groupId>org.javassist</groupId>
                                <artifactId>javassist</artifactId>
                            </embedded>
                            <embedded>
                                <groupId>org.jboss.logging</groupId>
                                <artifactId>jboss-logging</artifactId>
                            </embedded>
                            <embedded>
                                <groupId>org.hibernate.common</groupId>
                                <artifactId>hibernate-commons-annotations</artifactId>
                            </embedded>
                            <embedded>
                                <groupId>org.jboss</groupId>
                                <artifactId>jandex</artifactId>
                            </embedded>
                            <embedded>
                                <groupId>javax.el</groupId>
                                <artifactId>javax.el-api</artifactId>
                            </embedded>
                            <embedded>
                                <groupId>org.apache.servicemix.bundles</groupId>
                                <artifactId>org.apache.servicemix.bundles.javax-inject</artifactId>
                            </embedded>
                            <embedded>
                                <groupId>javax.interceptor</groupId>
                                <artifactId>javax.interceptor-api</artifactId>
                            </embedded>
                            <embedded>
                                <groupId>javax.enterprise</groupId>
                                <artifactId>cdi-api</artifactId>
                            </embedded>
                            <embedded>
                                <groupId>org.jboss.spec.javax.interceptor</groupId>
                                <artifactId>jboss-interceptors-api_1.2_spec</artifactId>
                            </embedded>
                            <embedded>
                                <groupId>org.jboss.spec.javax.transaction</groupId>
                                <artifactId>jboss-transaction-api_1.2_spec</artifactId>
                            </embedded>
                            <embedded>
                                <groupId>mysql</groupId>
                                <artifactId>mysql-connector-java</artifactId>
                            </embedded>
                            <embedded>
                                <groupId>org.hibernate</groupId>
                                <artifactId>hibernate-core</artifactId>
                            </embedded>
                            <embedded>
                                <groupId>org.hibernate</groupId>
                                <artifactId>hibernate-osgi</artifactId>
                            </embedded>
                        </embeddeds>
                    </configuration>
                    <executions>
                        <execution>
                            <id>install-package-hibernate</id>
                            <goals>
                                <goal>install</goal>
                            </goals>
                            <configuration>
                                <targetURL>http://${aem.host}:${aem.port}/crx/packmgr/service.jsp</targetURL>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

<!-- ====================================================================== -->
<!-- D E P E N D E N C I E S                                                -->
<!-- ====================================================================== -->
<dependencies>
    <dependency>
        <groupId>org.apache.servicemix.bundles</groupId>
        <artifactId>org.apache.servicemix.bundles.antlr</artifactId>
        <version>2.7.7_5</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml</groupId>
        <artifactId>classmate</artifactId>
        <version>1.3.4</version>
    </dependency>
    <dependency>
        <groupId>com.sun.activation</groupId>
        <artifactId>javax.activation</artifactId>
        <version>1.2.0</version>
    </dependency>
    <dependency>
        <groupId>javax.activation</groupId>
        <artifactId>javax.activation-api</artifactId>
        <version>1.2.0</version>
    </dependency>
    <dependency>
        <groupId>javax.persistence</groupId>
        <artifactId>javax.persistence-api</artifactId>
        <version>2.2</version>
    </dependency>
    <dependency>
        <groupId>javax.xml.bind</groupId>
        <artifactId>jaxb-api</artifactId>
        <version>2.3.1</version>
    </dependency>
    <dependency>
        <groupId>net.bytebuddy</groupId>
        <artifactId>byte-buddy</artifactId>
        <version>1.9.11</version>
    </dependency>
    <dependency>
        <groupId>org.apache.servicemix.bundles</groupId>
        <artifactId>org.apache.servicemix.bundles.dom4j</artifactId>
        <version>2.1.1_1</version>
    </dependency>
    <dependency>
        <groupId>com.sun.istack</groupId>
        <artifactId>istack-commons-runtime</artifactId>
        <version>3.0.7</version>
    </dependency>
    <dependency>
        <groupId>com.sun.xml.fastinfoset</groupId>
        <artifactId>FastInfoset</artifactId>
        <version>1.2.16</version>
    </dependency>
    <dependency>
        <groupId>org.apache.servicemix.bundles</groupId>
        <artifactId>org.apache.servicemix.bundles.jaxb-runtime</artifactId>
        <version>2.3.1_1</version>
    </dependency>
    <dependency>
        <groupId>org.javassist</groupId>
        <artifactId>javassist</artifactId>
        <version>3.24.0-GA</version>
    </dependency>
    <dependency>
        <groupId>org.jboss.logging</groupId>
        <artifactId>jboss-logging</artifactId>
        <version>3.3.2.Final</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate.common</groupId>
        <artifactId>hibernate-commons-annotations</artifactId>
        <version>5.1.0.Final</version>
    </dependency>
    <dependency>
        <groupId>org.jboss</groupId>
        <artifactId>jandex</artifactId>
        <version>2.0.5.Final</version>
    </dependency>
    <dependency>
        <groupId>javax.el</groupId>
        <artifactId>javax.el-api</artifactId>
        <version>2.2.5</version>
    </dependency>
    <dependency>
        <groupId>org.apache.servicemix.bundles</groupId>
        <artifactId>org.apache.servicemix.bundles.javax-inject</artifactId>
        <version>1_2</version>
    </dependency>
    <dependency>
        <groupId>javax.interceptor</groupId>
        <artifactId>javax.interceptor-api</artifactId>
        <version>1.2.2</version>
    </dependency>
    <dependency>
        <groupId>javax.enterprise</groupId>
        <artifactId>cdi-api</artifactId>
        <version>1.2</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.jboss.spec.javax.interceptor</groupId>
        <artifactId>jboss-interceptors-api_1.2_spec</artifactId>
        <version>1.0.1.Final</version>
    </dependency>
    <dependency>
        <groupId>org.jboss.spec.javax.transaction</groupId>
        <artifactId>jboss-transaction-api_1.2_spec</artifactId>
        <version>1.1.1.Final</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-osgi</artifactId>
    </dependency>
    <dependency>
        <groupId>com.adobe.aem</groupId>
        <artifactId>uber-jar</artifactId>
        <classifier>apis</classifier>
    </dependency>
    <dependency>
        <groupId>javax.jcr</groupId>
        <artifactId>jcr</artifactId>
    </dependency>
</dependencies>

Appendix 3. How to Install Hibernate 5.4.5 in AEM 6.4.4 with sling-maven-plugin and Maven Invoker API

Below is a part of POM.xml with Maven profile for application installation in AEM 6.4.4 Felix Console as separate bundles with sling-maven-plugin called from Java code.

Show Maven profile for Hibernate 5.4.5 OSGi bundles installation in AEM 6.4.4
<profiles>
    <profile>
        <id>installHibernate</id>
        <activation>
            <activeByDefault>false</activeByDefault>
        </activation>

        <dependencies>
            <dependency>
                <groupId>rg</groupId>
                <artifactId>com.softwerke.jpa.hibernate.bundles</artifactId>
                <version>1.0-SNAPSHOT</version>
                <scope>import</scope>
                <type>pom</type>
            </dependency>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-dependency-plugin</artifactId>
                    <executions>
                        <execution>
                            <id>copy</id>
                            <phase>package</phase>
                            <goals>
                                <goal>copy-dependencies</goal>
                            </goals>
                            <configuration>
                                <outputDirectory>
                                    ${basedir}/src/main/content/jcr_root/apps/hibernate/install/
                                </outputDirectory>
                                <includeArtifactIds>
                                    org.apache.servicemix.bundles.antlr,
                                    classmate,
                                    javax.activation,
                                    javax.activation-api,
                                    javax.persistence-api,
                                    jaxb-api,
                                    byte-buddy,
                                    org.apache.servicemix.bundles.dom4j,
                                    istack-commons-runtime,
                                    FastInfoset,
                                    org.apache.servicemix.bundles.jaxb-runtime,
                                    javassist,
                                    jboss-logging,
                                    hibernate-commons-annotations,
                                    jandex,
                                    javax.el-api,
                                    org.apache.servicemix.bundles.javax-inject,
                                    javax.interceptor-api,
                                    cdi-api,
                                    jboss-interceptors-api_1.2_spec,
                                    jboss-transaction-api_1.2_spec,
                                    mysql-connector-java,
                                    hibernate-core,
                                    hibernate-osgi
                                </includeArtifactIds>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>exec-maven-plugin</artifactId>
                    <version>1.6.0</version>
                    <executions>
                        <execution>
                            <phase>install</phase>
                            <goals>
                                <goal>java</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <mainClass>com.softwerke.build.utils.HibernateInstaller</mainClass>
                        <classpathScope>compile</classpathScope>
                        <arguments>
                            <!-- Path to load Hibernate OSGi dependencies from -->
                            <argument>${basedir}/src/main/content/jcr_root/apps/hibernate/install</argument>
                            <!-- Path to XML file with a list of Hibernate bundles -->
                            <argument>${basedir}/src/main/content/META-INF/resources/hibernate-bundles.xml</argument>
                            <!-- User login to install bundle in AEM -->
                            <argument>${sling.user}</argument>
                            <!-- User password to install bundle in AEM -->
                            <argument>${sling.password}</argument>
                            <!-- Path to AEM Felix Console -->
                            <argument>http://${aem.host}:${aem.port}/system/console</argument>
                        </arguments>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

Here is an example of the bundle installation with Apache Maven Invoker API. Bundles are listed in the provided hibernate-bundles.xml file in <bundle> tags:

<bundles>
    <!-- Hibernate dependencies -->
    <bundle>byte-buddy-1.9.11.jar</bundle>
    ...
</bundles>

Path to XML file is set via second parameter of the exec-maven-plugin configuration.

Show Java code for Hibernate 5.4.5 installation with Maven Invoker API
public class HibernateInstaller {
    public static void main(String[] args) throws Exception {
        String bundleFolder,
               xmlFilePath,
               slingUser,
               slingPassword,
               url;
        if (args != null && args.length == 5) {
            bundleFolder = args[0];
            xmlFilePath = args[1];
            slingUser = args[2];
            slingPassword = args[3];
            url = args[4];
        } else {
            throw new Exception("Can't execute Hibernate install!\nPlease specify five arguments.");
        }

        StringBuilder mvnCmd = new StringBuilder();
        mvnCmd.append("org.apache.sling:sling-maven-plugin:2.4.2:install-file");
        mvnCmd.append(" -Dsling.user=" + slingUser);
        mvnCmd.append(" -Dsling.password=" + slingPassword);
        mvnCmd.append(" -Dsling.url=" + url);
        mvnCmd.append(" -Dsling.deploy.method=WebConsole");
        mvnCmd.append(" -Dsling.file=");
        mvnCmd.append(bundleFolder);
        mvnCmd.append("/");

        // Read XML file with a list of the Hibernate OSGi dependencies (bundles)
        File file = new File(xmlFilePath);
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
        Document document = documentBuilder.parse(file);
        NodeList bundlesList = document.getElementsByTagName("bundle");

        final InvocationRequest invocationRequest = new DefaultInvocationRequest();
        // invocationRequest.setDebug(true);
        final Invoker invoker = new DefaultInvoker();

        for (int i = 0; i < bundlesList.getLength(); i++) {
            String goal = mvnCmd.toString() + bundlesList.item(i).getTextContent();
            installBundle(invocationRequest, invoker, goal);
        }
    }

    private static void installBundle(InvocationRequest invocationRequest, Invoker invoker, String goal)
            throws MavenInvocationException, CommandLineException {
        invocationRequest.setGoals(Collections.singletonList(goal));
        final InvocationResult invocationResult = invoker.execute(invocationRequest);
        if (invocationResult.getExitCode() != 0) {
            String msg = "Invocation Exception";
            if (invocationResult.getExecutionException() != null) {
                msg = invocationResult.getExecutionException().getMessage();
            }
            throw new CommandLineException(msg);
        }
    }
}