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
- 2. Hibernate 5.4.5 Installation in AEM 6.4.4
- 3. Maven Application Dependencies
- 4. JPA/JDBC Properties Setup in AEM
- 5. AEM-Database Interaction via javax.persistence.EntityManager
- Appendix 1. Hibernate 5.4.5 OSGi dependencies for AEM 6.4.4
- Appendix 2. How to Install Hibernate 5.4.5 in AEM 6.4.4 with content-package-maven-plugin
- Appendix 3. How to Install Hibernate 5.4.5 in AEM 6.4.4 with sling-maven-plugin and Maven Invoker API
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.
- 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.
- 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 toRESOURCE_LOCAL
as unmanaged JPA access is used to communicate with database viaEntityManagerFactory
;class
– list of Entity classes;exclude-unlisted-classes = false
so that Hibernate manages all Entity classes not defined inpersistence.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);
}
}
}