Обсудить проект

Как установить Hibernate 5.4.5/JPA 2.2 в AEM 6.4.4

Специалисты Softwerke делятся опытом установки Hibernate 5.4.5 в Adobe Experience Manager 6.4.4 (далее AEM) и настройки взаимодействия с базой данной типа MySQL в соответствии с JPA 2.2. Задача не является тривиальной, в частности потому что в сети крайне мало информации по данной теме. Мы надеемся, что эта статья будет полезна тем, кто столкнулся с проблемой интеграции Hibernate/JPA в AEM.

Содержание

1. Технические требования

Для установки Hibernate 5.4.5 требуются заранее развернутые:

  • Java 8
  • Adobe Experience Manager 6.4.4
  • Maven 3

2. Установка Hibernate 5.4.5 в AEM 6.4.4

Ниже представлены все модули, от которых зависит успешная работа Hibernate ORM в OSGi (Apache Felix). Каждый модуль устанавливается как отдельный независимый bundle. Все необходимые OSGi зависимости для Hibernate перечислены в таблице.

В случае успешной установки и активации всех перечисленных зависимостей hibernate-osgi bundle предоставляет сервис javax.persistence.spi.PersistenceProvider, который может быть импортирован в приложение для взаимодействия с базой данных.

Установка требуемых зависимостей в AEM может быть выполнена различными способами.

  1. Стандартным способом с помощью Maven сборки и установки пакета. Все необходимые bundles включаются в пакет (embedded) с помощью com.day.jcr.vault:content-package-maven-plugin. Пример POM.xml файла, выполняющего такую установку, находится в Приложении 2.

  1. Непосредственно установкой всех bundles с помощью org.apache.sling:sling-maven-plugin в порядке их зависимостей. Пример POM.xml файла для выполнения установки и пример HibernateInstall.java, в котором с помощью Apache Maven Invoker API выполняется вызов sling-maven-plugin для установки bundles, находятся в Приложении 3.

3. Установка Maven зависимостей для приложения

Пример требуемых Maven зависимостей для организации взаимодействия AEM и MySQL через Hibernate/JPA:

<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 параметров

Загрузка persistence properties для организации работы с Hibernate ORM выполняется в 2 этапа.

4.1. Загрузка JPA параметров из persistence.xml

Сначала загружаются JPA параметры из файла persistence.xml, путь к которому указывается в bundle manifest configuration тэге <Meta-Persistence>.

<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>

Основные параметры, которые необходимо указать:

  • name – название persistence-unit;
  • transaction-type — тип транзакций, значение этого параметра устанавливается в RESOURCE_LOCAL, т.к. на проекте используется unmanaged JPA доступ для работы с базой данных с помощью EntityManagerFactory;
  • class — список используемых Entity классов;
  • exclude-unlisted-classes = false указывает Hibernate выполнять управление всеми Entity классами, не указанными в 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. Загрузка JDBC параметров из AEM OSGi конфигурации

На этом этапе из созданной OSGi конфигурации загружаются JDBC connection properties, необходимые для организации взаимодействия с базой данных, например, 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. Взаимодействие с базой данных через EntityManager

Ниже приведен пример создания JPA транзакции в контексте AEM:

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…

Приложение 1. Таблица Hibernate зависимостей

Показать таблицу Hibernate OSGi зависимостей
# 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

Приложение 2. Установка Hibernate 5.4.5 в AEM 6.4.4 отдельным пакетом

Ниже представлена часть POM.xml с Maven профилем для классической установки приложения в AEM 6.4.4 Package Manager в виде zip-пакета с помощью content-package-maven-plugin.

Показать код Maven профиля для установки пакета с Hibernate 5.4.5 в 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>

Приложение 3. Установка Hibernate 5.4.5 в AEM 6.4.4 с помощью sling-maven-plugin и Maven Invoker API

Ниже представлена часть POM.xml с Maven профилем для установки приложения в AEM 6.4.4 Felix Console в виде отдельных bundles с помощью sling-maven-plugin, вызываемого из Java кода.

Показать код Maven профиля для установки отдельных Hibernate OSGi bundles в 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>

Ниже приведен пример установки bundles с использованием Apache Maven Invoker API. Список bundles для установки содержится в XML файле в тэгах <bundle>:

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

Путь к XML файлу передается в качестве второго параметра в конфигурации exec-maven-plugin.

Показать Java код для установки Hibernate с помощью 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);
        }
    }
}