This article is the first in a series of three tutorials that cover the following topics:

  1. JPA2 in SAP NetWeaver
  2. Building server-side database-backed OData services in SAP NetWeaver with JPA2
  3. Building server-side database-backed OData services in SAP NetWeaver with JPA1

Introduction

The SAP NetWeaver AS Java provides a JPA2-compliant container from version 7.5 SP03 onwards according to the SAP NetWeaver 7.5 SP03 release notes. A rough outline for the necessary steps to make use of this new feature is given in the SAP help.

The bad news about the new feature is that NetWeaver only provides the container while the SAP JPA provider is not capable of JPA2. Therefore, we need to supply NetWeaver and our JEE applications with our own provider. We decided to use Hibernate ORM for this purpose, as it is the most widely used OR mapper in the JEE world.

In this tutorial, we will demonstrate how to develop JEE applications for SAP NetWeaver that use JPA2 with Hibernate as the provider implementation. Generally, it should be possible to use other providers such as, for example EclipseLink, however we did not test this and therefore cannot guarantee that other providers will work.

Prerequisites

We strongly advise using the latest version of SAP NetWeaver AS Java, which is 7.5 SP06 at the time of writing this article, for reasons that we will discuss in the following pitfalls.

The latest stable Hibernate version that supports JPA 2.0 is Hibernate 4.2.21.Final. Download the hibernate-core artifact and all dependencies for this version, including the sources for Hibernate 4.2.21, as we will need these later. The following artifacts are required:

  • antlr-2.7.7.jar
  • dom4j-1.6.1.jar
  • hibernate-commons-annotations-4.0.2.Final.jar
  • hibernate-core-4.2.21.Final.jar
  • hibernate-entitymanager-4.2.21.Final.jar
  • javassist-3.18.1-GA.jar
  • jboss-logging-3.1.0.GA.jar
  • jboss-transaction-api_1.1_spec-1.0.1.Final.jar

Pitfall:

Ensure that you use Javassist version 3.18.1-GA or higher. This is necessary to provide compatibility for Java SE 8 (which SAP NetWeaver 7.5 supports) in your application. Otherwise, Hibernate will not work with Java 8 applications!

Pitfall:

Do not include the JPA-API artifact (“hibernate-jpa-2.0-api-1.0.1.Final.jar”)! Initially we tested JPA2 in SAP NetWeaver 7.5 SP03 and included the JPA-API-JAR as NetWeaver did not provide its own artifact for the API. However, somewhere between SP03 and SP06, SAP decided to include its own artifact of the JPA API with their application server as one would expect. If you include your own JPA-API-JAR with the later versions of NetWeaver 7.5, a deploy-time exception will be raised stating that an API mismatch was detected, even if you deploy the very same JAR that NetWeaver ships! This means that if you include your own API-JAR with NW 7.5 SP03 (where it is required) and you decide to migrate to later service packs, your application deployment will break!

Hibernate and NetWeaver Transactions

Hibernate provides support for a large number of JEE application servers regarding the Java Transaction API (JTA), in the sense that it includes components that provide container-specific JNDI-lookups of the TransactionManager and UserTransaction, which are essential for JPA2. Unfortunately SAP NetWeaver is not among those application servers supported by Hibernate. Furthermore, it is not possible to ship a suitable component for SAP NetWeaver with your application as the Hibernate JPA provider will be at the top end of the classloader chain, which means that it cannot search for classes „lower“ in the classloading chain. Hence, the only way of making Hibernate compatible with SAP NetWeaver is compiling your own version of the hibernate-core artifact with said class. We have submitted this change to Hibernate so that users of future versions will be able to make use of this out-of-the-box. If you get in touch with us, we will provide you with our own version of this artifact. We will still outline the necessary steps to generate your own artifact. Note that as of Hibernate 4, the TransactionManagerLookup-mechanism was replaced by JTA platform constructs.

In the sources for hibernate-core, navigate to the following package: org.hibernate.engine.transaction.jta.platform.internal

Create a new class SAPNetWeaverJtaPlatform:

/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
 * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
 */

package org.hibernate.engine.transaction.jta.platform.internal;

import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction;

/**
 * {@link org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform} implementation for SAP NetWeaver
 *
 * @author Lukas Pradel
 */

public class SapNetWeaverJtaPlatform extends AbstractJtaPlatform {

    public static final String TM_NAME = "TransactionManager";

    public static final String UT_NAME = "UserTransaction";

    @Override
    protected TransactionManager locateTransactionManager() {

        return (TransactionManager) jndiService().locate(TM_NAME);
    }

    @Override
    protected UserTransaction locateUserTransaction() {

        return (UserTransaction) jndiService().locate(UT_NAME);
    }
}

Modify the class StrategySelectorBuilder at line 318 to include the following:

addJtaPlatforms(
    strategySelector,
    SapNetWeaverJtaPlatform.class,
    "SapNetWeaver",
    "org.hibernate.service.jta.platform.internal.SapNetWeaverJtaPlatform"
);

Finally, replace the original hibernate-core-4.2.21.Final.jar with your freshly compiled one.

Pitfall:

You must compile Hibernate 4.2.21 with JDK 6 as the remaining artifacts in Hibernate 4.2.21 were compiled using Java 6 as well.

Installing Hibernate as JPA provider

Follow the steps listed in SAP help:

  • Put all hibernate artifacts (excluding the JPA-API-JAR) into a directory <hibernate-dir>
  • Connect to NetWeaver using telnet <netweaver-host> 50008
  • add orpersistence
  • deploy_provider <hibernate-dir> -vendor org.hibernate -name hibernate4221

Configuring your application

Open the file application-j2ee-engine.xml in the META-INF directory of your EAR DC and add the following reference:

<reference reference-type="hard">
  <reference-target provider-name="org.hibernate" target-type="library">hibernate4221</reference-target>
</reference>

Note that the provider-name is the same as the vendor specified in the previous section and the value of the reference-target property is the name specified in the previous section.

Next, edit the persistence.xml file of your EJB DC and make it a JPA2 persistence-file:

<persistence version="2.0"
	xmlns="http://java.sun.com/xml/ns/persistence"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="pu-name">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>YOUR_DATA_SOURCE</jta-data-source>
        <properties>
            <property name="com.sap.jpa.container.packaging.pu.root.strategy.jpa10" value="true"/>
            <property name="com.sap.jpa.container.packaging.referenced.jars.strategy.jpa10" value="true"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
            <property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.SapNetWeaverJtaPlatform" />
            <property name="hibernate.hbm2ddl.auto" value="validate" />
            <property name="hibernate.connection.autocommit" value="false" />
            <property name="hibernate.validator.autoregister_listeners"
                value="false" />
            <property name="hibernate.validator.apply_to_ddl" value="false" />
            <property name="hibernate.default_schema" value="DEFAULT_SCHEMA"/>
        </properties>
</persistence-unit>
</persistence>

Note the important parts:

  • The provider attribute which sets the Hibernate provider
  • The SAP-specific properties that ensure JPA2-compatibility and
  • The transaction.jta.platform property which references the class we added to Hibernate.

In this example we used an Oracle DB. You will have to modify the related properties for your specific project setting.

 

Congratulations, you are now ready to deploy your first JPA2 application to SAP NetWeaver!

Compiling JPA2 applications in NWDS

By default, JEE DCs in NWDS depend on engine.jee5.facade. Naturally, this includes the JPA 1 API which makes it impossible to compile an application that uses JPA2-specific annotations such as for example the orphanRemoval attribute in OneToMany annotations.

We solved this issue by removing the engine.jee5.facade dependency and adding a dependency to an external library DC that includes only the JEE6 API (javaee-api-6.0.jar). Obviously, you can only use JPA2 related classes and annotations and not for example EJB 3.1 annotations such as @Singleton or you will experience exceptions at deploytime.

Conclusion

We successfully deployed and tested JPA2 applications with this setup in SAP NetWeaver 7.5 SP06 and hope that this tutorial enables you to develop JPA2 applications for SAP NetWeaver.

If you are experiencing problems, need assistance, or would like to see a minimal sample project, do not hesitate to contact us via SAP Community or by commenting on this article.

In the next article of this series, we will demonstrate how to use JPA2 to develop OData services with Apache Olingo with minimal boilerplate code.

To report this post you need to login first.

Be the first to leave a comment

You must be Logged on to comment or reply to a post.

Leave a Reply