Tiven Wang
Wang Tiven February 23, 2017
425 favorite favorites
bookmark bookmark
share share

The project codes for this article can be downloaded from Github.

The Java Persistence API (JPA) provides Java developers with an object/relational mapping facility for managing relational data in Java applications.

EclipseLink is comprehensive open-source Java persistence solution addressing relational, XML, and database web services. HCP advise to use the EclipseLink to present JPA implementation.

Note that EclipseLink versions as of 2.5 contain the SAP HANA database platform.

Dependencies

<!-- Required for compilation and required at runtime (additional web application libraries) -->
<dependency>
  <groupId>com.sap.security.core.server</groupId>
  <artifactId>csi</artifactId>
  <version>1.0.1</version>
  <scope>system</scope>
  <systemPath>${basedir}/src/main/webapp/WEB-INF/lib/com.sap.security.core.server.csi_1.0.1.jar</systemPath>
</dependency>
<dependency>
  <groupId>org.eclipse.persistence</groupId>
  <artifactId>javax.persistence</artifactId>
  <version>2.1.0</version>
</dependency>
<dependency>
  <groupId>org.eclipse.persistence</groupId>
  <artifactId>eclipselink</artifactId>
  <version>2.5.1</version>
</dependency>

Create JPA Entity

package com.sap.c4c.wechat.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQuery;

@Entity
@NamedQuery(name = "AllCustomers", query = "select c from Customer c")
public class Customer {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    public Long id;
    public String firstName;
    public String lastName;

    public Customer() {}

    public Customer(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    @Override
    public String toString() {
        return String.format(
                "Customer[id=%d, firstName='%s', lastName='%s']",
                id, firstName, lastName);
    }

}

JPA Configurations

Persistence Unit

Create the persistence unit configuration file persistence.xml in position src/main/resources/META-INF/persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<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="persistence-with-jpa" transaction-type="RESOURCE_LOCAL">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <class>com.sap.c4c.wechat.model.Customer</class>
        <properties>
            <property name="eclipselink.ddl-generation" value="create-tables" />
            <property name="eclipselink.logging.level" value="SEVERE" />
        </properties>
    </persistence-unit>
</persistence>

JNDI Lookup Data Source

Add the data source for JNDI lookup in web file src/main/webapp/WEB-INF/web.xml

<!-- Declare the JNDI lookup of the default data source -->
<resource-ref>
    <res-ref-name>jdbc/DefaultDB</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
</resource-ref>

Use in Servlet

Override the init method in http servlet class to create an entity manager factory for creating entity manager.

private DataSource ds;
private EntityManagerFactory emf;

/** {@inheritDoc} */
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public void init() throws ServletException {
  Connection connection = null;
  try {
    InitialContext ctx = new InitialContext();
    ds = (DataSource) ctx.lookup("java:comp/env/jdbc/DefaultDB");

    Map properties = new HashMap();
    properties.put(PersistenceUnitProperties.NON_JTA_DATASOURCE, ds);
    emf = Persistence.createEntityManagerFactory("persistence-with-jpa", properties);
  } catch (NamingException e) {
    throw new ServletException(e);
  }
}

For get method in servlet class

EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(customer);
em.getTransaction().commit();
/** {@inheritDoc} */
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
  try {
    // Extract name of person to be added from request
    String firstName = request.getParameter("FirstName");
    String lastName = request.getParameter("LastName");

    // ADD PERSON IF NAME IS NOT NULL/EMPTY
    EntityManager em = emf.createEntityManager();
    try {
      if (firstName != null && lastName != null && !firstName.trim().isEmpty()
          && !lastName.trim().isEmpty()) {
        Customer customer = new Customer(firstName, lastName);
        em.getTransaction().begin();
        em.persist(customer);
        em.getTransaction().commit();
      }
    } finally {
      em.close();
    }
  } catch (Exception e) {
    response.getWriter().println("Persistence operation failed with reason: " + e.getMessage());
  }
}

Test Locally

Open DB Tunnel

SAP HANA Cloud Platform Console Client enables development, deployment and configuration of an application outside the Eclipse IDE as well as continuous integration and automation tasks. The tool is part of the SDK. You can find it in the tools folder of your SDK location.

So you can use a database tunnel to connect to a remote database instance through a secure connection. To open a tunnel, use the open-db-tunnel command in console client in HCP SDK.

For example :

set HTTP_PROXY_HOST=proxy
set HTTP_PROXY_PORT=8080
set HTTPS_PROXY_HOST=proxy
set HTTPS_PROXY_PORT=8080
set HTTP_NON_PROXY_HOSTS="localhost"
neo open-db-tunnel -h int.sap.hana.ondemand.com -u cxxxxxx -a ixxxxxxsapdev --id hcpwechat

If you have to configure proxy settings, specify them using the environment variables.

If the tunnel is opened successfully, the remote database instance can be used as a local database connection.

Local Context Resource

The Context element represents a web application, which is run within a particular virtual host. Each web application is based on a Web Application Archive (WAR) file, or a corresponding directory containing the corresponding unpacked contents, as described in the Servlet Specification (version 2.2 or later).

You can declare the characteristics of the resource to be returned for JNDI lookups of <resource-ref> and <resource-env-ref> elements in the web application deployment descriptor.

You can define the context file at src/test/resources/context.xml as

<Context >
  <Resource name="jdbc/DefaultDB"
        global="jdbc/DefaultDB"
        auth="Container"
        type="javax.sql.DataSource"
        driverClassName="com.sap.db.jdbc.Driver"
        url="jdbc:sap://localhost:30015/"
        username="<db_user>"
        password="<password>"

        maxActive="100"
        maxIdle="20"
        minIdle="5"
        maxWait="10000"/>
</Context>

Maven Configurations and Tomcat7 Plugin

In order to define com.sap.db.jdbc.Driver as the driver class name, you need add the SAP HANA jdbc Java package as a dependency in pom.xml:

<dependency>
  <groupId>com.sap.db.jdbc</groupId>
  <artifactId>ngdbc</artifactId>
  <version>1.96.0</version>
  <scope>system</scope>
  <systemPath>${sap.cloud.sdk.path}/repository/.archive/lib/ngdbc.jar</systemPath>
</dependency>

You also need to add the context.xml file in maven tomcat7 plugin configuration:

<plugin>
  <groupId>org.apache.tomcat.maven</groupId>
  <artifactId>tomcat7-maven-plugin</artifactId>
  <version>2.0</version>
  <configuration>
    <contextFile>${project.basedir}/src/test/resources/context.xml</contextFile>
  </configuration>
</plugin>

Run Locally

Execute mvn tomcat plugin goal mvn tomcat7:run then access the web application through http://localhost:8080/wechat/message

Similar Posts

Comments

Back to Top