Java Platform, Enterprise Edition with WebSphere Application Server and DB2
When dealing with a database, Java enterprise programs in the past used the JDBC driver APIs either for dynamic SQL or for static SQL (SQLJ) directly. As an alternative, the usage of Container-Managed Persistence (CMP) was specified and implemented in almost all Java enterprise servers, such as WebSphere Application Server. DB2 for z/OS and WebSphere: The Perfect Couple, SG24-6319 describes this situation and gives multiple examples of how to write DB2 applications with dynamic JDBC, SQLJ, and EJB (CMP).
This chapter gives a database administrator (DBA) enough background information so that the DBA can assess what is behind the newer Java enterprise concepts. For the Java programmer, this chapter provides samples that could serve as a starting point to working with DB2 on z/OS from inside and outside of managed application server environments.
This chapter covers the following topics:
7.1 Java Platform, Enterprise Edition with WebSphere Application Server and DB2
The Java programming environment on z/OS is established. Both Java stand-alone applications and Java Platform, Enterprise Edition applications inside WebSphere Application Server are used. DB2 is their prime persistent storage.
The first generation of Java applications commonly uses driver-specific JDBC statements for dynamic SQL or, following a more traditional development path, static SQLJ in a similar way to how you include SQL into COBOL programs. Because the driver is associated to a particular database and has database-specific statements, your code is tied to that database.
However, to fulfill driver-specific requirements is a violation of one of the primary goals of Java: portability. Although SQL is standardized among different systems and databases, raw JDBC programming error handling, for example, remains database specific. In addition, with raw JDBC or SQLJ programming, boilerplate code must be written to make Java objects work with the information from the database. You must fill the class attributes for every database field with separate statements. The JDBC API is not designed to store Java objects directly into relational databases.
The EJB 2.0 specification was a trial run to hide all the platform-specific details and delegate the arduous task of mapping the database information in Java objects to a standardized application server. Container-managed persistence (CMP) EJBs help the programmer by supporting automatic transaction handling and security services.
EJBs were not well received by the Java community for numerous reasons, mostly to do with the shortcomings of the specifications. Unit tests of EJB entities are nearly impossible because EJBs need an enterprise container to run in. The mapping of the state of Java objects to a relational representation is insufficient in the EJB model. It misses important aspects of object-oriented programming, such as inheritance.
Other approaches were more successful than the EJB 2.0 persistency specification, which is part of Java 2 Enterprise Edition 1.4. Hibernate, iBATIS, and EclipseLink are examples of successful persistency frameworks that often are used in enterprise applications instead of the EJBs that are offered by standard Java Platform, Enterprise Edition application servers.
Things have changed since the advent of Java Platform, Enterprise Edition 5, though. This Enterprise Java specification now includes the Java Persistence API (JPA). JPA 1.0 is part of Java Platform, Enterprise Edition 5, and JPA 2.0 is part of Java Platform, Enterprise Edition 6. The concepts that made Hibernate and the other persistency frameworks successful are now included in the Java enterprise standard. EJB Container-managed persistence (CMP) beans are replaced by JPA entity beans. EJBs now provide transaction support only; they do not provide persistency any more.
JPA was defined within the Java EE specification for Enterprise JavaBeans (EJB) 3.0. With JPA 2.0, the JPA specification is defined separately in Java Specification Request (JSR) 317: Java Persistence API, Version 2.0.
WebSphere Application Server V8.5 conforms to Java Platform, Enterprise Edition 6 and supports JPA 2.0. The JPA implementation inside WebSphere Application Server is based on the Apache OpenJPA project. Although you can use this implementation directly in WebSphere Application Server, the WebSphere Application Server default is to use the JPA for WebSphere Application Server persistence provider. There are some enhancements in the WebSphere Application Server version of the JPA provider over the original Apache version. The support of pureQuery client optimization is one example.
7.2 Implementation version of JPA inside WebSphere Application Server
You can see the version of both implementations by running wsjpaversion, as shown in Example 7-1.
Example 7-1 The wsjpaversion command
C:ProgrammeibmWebSphereAppServerin>wsjpaversion.bat
WSJPA 2.2.1-SNAPSHOT
Versions-ID: WSJPA-2.2.1-SNAPSHOT-r1119:2559
Überarbeitung der WebSphere-JPA-Unterversion: 1119:2559
 
OpenJPA 2.2.1-SNAPSHOT
Versions-ID: openjpa-2.2.1-SNAPSHOT-r422266:1325904
Überarbeitung der Apache-Unterversion: 422266:1325904
 
os.name: Windows Vista
os.version: 6.0
os.arch: x86
 
java.version: 1.6.0
java.vendor: IBM Corporation
 
java.class.path:
C:Program FilesibmWebSphereAppServerdevJavaEEj2ee.jar
C:Program FilesibmWebSphereAppServerpluginscom.ibm.ws.jpa.jar
C:Program FilesibmWebSphereAppServerpluginscom.ibm.ws.prereq.commons-collections.jar
C:Program FilesIBMWebSphere Studio Workload SimulatorjsoapiwlJSoap.jar
Strictly speaking, JPA is every thing that you need for persistence for new projects. JPA is now considered the standard approach for Object to Relational Mapping (ORM) and can replace all the preceding ORM frameworks.
7.2.1 The goals of the Java Persistence API
The goal of JPA is to enable the Java programmer to handle only the main constituents of his program: Java objects. In a program, all the objects that are used are related in some way, and make up an object model. The object model reflects real objects of a business or other things the program should deal with. From a developer’s point of view, the application logic and the object model is what matters.
In addition, there is the relational model, which is based on tables. Their correlation to each other is mathematically verified and optimized in a normalization process. Special skills are necessary to accomplish this task. It requires a deep knowledge of the database and its organization to accomplish this task effectively. Table design and definition are normally not a task the Java developer wants to deal with. It does not directly solve his problem. Both models must be coordinated with each other and mapped.
To leave the Java programmer free to work with his object model, the task of mapping his model to the relational model is delegated to the JPA infrastructure. Ideally, the Java programmer does not have to know which database is used and how the data in this database is dealt with.
JPA implementations allow simple Java classes or Plain Old Java Objects (POJOs) to be persisted. A POJO is considered a simple Java class because there is nothing that it depends on (not even on the code that makes nearly automatic persistence possible). To add the persistence behavior, Java annotations are added to the Java class. Java annotations do not change the program logic of the class but only give information to runtime environments that need this information. Only JPA uses javax.persistence.* annotations. Otherwise, runtime annotations are ignored. Thus, the Java class remains a POJO.
Conversely, the EJB 2 CMP specification requires classes to implement interfaces or methods that makes the class dependent on other classes or a server run time.
Because JPA has no dependencies on other containers, run times, or servers, it can be used as a stand-alone POJO persistence layer or it can be integrated in to any Java EE compliant container and many other lightweight frameworks.
This situation cannot be reached in more complex situations. In practice, the Java programmer and the DBA must communicate with each other and adjust their respective models. In many cases, most parts of the data exist, even for new applications or applications that are supposed to be migrated to JPA. Most companies have their data organized in to databases. Here, the Java programmer must follow the structure of existing tables because they are used by other programs as well and cannot easily be changed for the new one. JPA entities must be designed according to the relational data. This is called a bottom-up ORM approach. To accomplish this task, JPA gives you a rich set of annotations (or the XML equivalent) that allows you to customize each part of the mapping.
JPA entity customizing
Whether you must connect to an existing database or must follow strict database naming conventions, you can customize your JPA entities in many ways. You could start with your data model, which includes the database schema, and then work upwards to your entity classes. The wsreversemapping tool can help with this approach. It is used to perform reverse (bottom-up) mappings of database tables to entities. The generated Java files from the wsreversemapping tool might require some editing before they can be used in an application. Also, generated files do not contain annotations. Annotations can be added manually.
The JPA solution for WebSphere Application Server provides several tools that help with developing JPA applications. Combining these tools with IBM Rational Application Developer or IBM Data Studio provides a solid development environment for either Java EE or Java SE applications. IBM Rational Application Developer or IBM Data Studio include GUI tools to insert annotations, a customized persistence.xml file editor, a database explorer, and
other features.
The customization of the ORM involves the following areas:
Elementary mapping rules
 – Table name or names of additional tables to be used to map an entity
 – Single key column or composite keys for that entity
 – Rules for generating the key value
 – Attribute data types and table column characteristics
Relationship mapping rules
 – Collections of Java types and their representation in tables (through foreign key or
join tables)
 – Unidirectional and bidirectional mapping
 – One-to-one, one-to-many, many-to-one, many-to-many mapping
Inheritance mapping
 – Single-table-per-class hierarchy strategy
 – Joined-subclass strategy
 – Table-per-concrete-class strategy
You can see from the volume of options that you need much experience and a good knowledge of theory and background of the mapping patterns to successfully work with ORM.
Automatic database schema generation
If the new application does not have to work with legacy data and can start from scratch, you can go the opposite way: the top-down approach. In that approach, the domain model dictates the relational schema. If you are using a top-down mapping of the object model to the relational model, you develop the entity classes first and then use the OpenJPA functionality to generate the database tables that are based on the entity classes. The wsmapping tool helps with this approach. You can use the wsmapping tool to create database tables. As an alternative, by specifying the buildSchema parameter to the openjpa.jdbc.SynchronizeMappings of your persistence.xml property, the mapping tool provides the default mapping that matches the database schema automatically during the run of your application. You are not required to run the batch mapping tool if the default mapping satisfies the necessary database schema.
Most persistence providers, including OpenJPA, allow you to generate the database automatically from the entities. Automatic table creation by JPA does not need a great deal of configuration, though. JPA follows a configuration-by-exception mapping strategy. Nearly everything is taken from the existing definitions in the Java class.
However, sticking to the defaults and relying only on the automatic generation of the database tables might lead to problems in more complex situations. The generated relational model should be reviewed because a normalized schema with too many tables might be the result. Bad performance could be a consequence, and maintenance might become
more difficult.
Entity handling with the Entity Manager
The Entity Manager is the unit through which your program works with JPA. Entity manipulation, such as persist, read, change, and delete actions, are done by invoking methods on the entity manager. For create, read, update, and delete operations of simple entities, JPA provides the Java Persistence Query Language (JPQL). JPQL is syntactically similar to SQL, but is object-oriented rather than table-oriented. More complex tasks can use commands that the database provides natively. JPQL uses SQL and resembles raw
JDBC coding.
The Entity Manager can deal with four types of commands:
Dynamic query
A string with JPQL statements is given as an argument to the Entity Manager for execution. The string can be a simple select or a more complex query by using joins and other selection criteria. It also can be an update or delete statement that is given to the createQuery method. Example 7-2 is an example in which an array of employee objects are returned. The query selects Java objects and not table rows with JPQL.
Example 7-2 Example of a dynamic JPA query
em = emf.createEntityManager();
TypedQuery<Employee> query1 = em.createQuery(
"Select d from Employee d", Employee.class);
Static query
This query must not be confused with static SQL. It still translates to dynamic SQL in the JDBC driver. Static here means that the query is already coded at build time and inspected by the JPA run time before the program actually uses it. It can have variable parameters. Query templates can be statically declared by using the NamedQuery annotation, as shown in Example 7-3. They are coded in the same Java source as the class they deal with. Many NamedQuery templates are a sort of table with statements that are prepared for later use by other parts of the program.
Example 7-3 Example of a static JPA query
Declared in the entity class:
@NamedQuery(name="DeleteEmpAThiele", query="DELETE FROM Employee e " +
"where e.lastname = 'Thiele'")
Use in a different class:
Query delete1 = em.createNamedQuery("DeleteEmpAThiele");
delete1.executeUpdate();
Native query
Similar to the JDBC method prepareStatement(), a SQL string is given as a parameter with optional arguments. In addition, the second parameter says that the result list is expected to be of the type Magazine, as shown in Example 7-4.
Example 7-4 Example of a native SQL query in JPA
Query query = em.createNativeQuery("SELECT ISBN, TITLE, PRICE, "
+ "VERS FROM MAG WHERE PRICE > ?1 AND PRICE < ?2", Magazine.class);
query.setParameter(1, 5d);
query.setParameter(2, 10d);
List<Magazine> results = (List<Magazine>) query.getResultList();
Stored procedure call
A stored procedure is similar to a native query. OpenJPA supports stored procedure invocations as SQL queries. OpenJPA assumes any SQL that does not begin with the SELECT keyword (ignoring case) is a stored procedure call, and starts it as such at the JDBC level. See Example 7-5.
Example 7-5 Example call of a stored procedure
Query query = em.createNativeQuery("CALL MY_STOREDPROCEDURE(?)");
query.setParameter(1, arg1);
query.executeUpdate());
You can use native queries and stored procedure calls in cases where the JPA defaults are not enough and a generated table model does not fit your demands. The usage of JPA native queries can help you migrate raw JDBC applications to JPA or help you avoid raw JDBC in cases where the JPA defaults lead to problems. Generated SQL sometimes cannot use the full potential that the database normally provides. With native queries, you are able to use the database power inside JPA.
7.2.2 OpenJPA and JDBC interaction
OpenJPA interacts with the database by using the normal Java DataBase Connectivity (JDBC) APIs that are provided by the driver. OpenJPA uses the configuration of the JDBC driver that is in place through the definition of a data source or other properties unless the JPA provider is told to set specific configuration properties. In these cases, JPA calls the respective JDBC API for reconfiguration. Great care should be taken to not interfere with the configuration of the data source in an application server.
OpenJPA Entity Manager handles all the communication that is needed with the JDBC driver, for example, when the JDBC driver is requested to provide a connection to the database.
OpenJPA obtains JDBC connections on an as needed basis and releases them as fast as possible. A connection is made for each query. The connection is closed and given back to the pool. The connection is open only during a data store transaction or if a JDBC ResultSet is still active.
All this is transparent to the programmer and the Java program and normally this is the best behavior. In rare cases, you can configure OpenJPA's usage of JDBC connections through the openjpa.ConnectionRetainMode configuration property.
7.2.3 Agile JPA development with a WebSphere Application Server embeddable EJB container and DB2
Agile development has become the prevailing paradigm for nearly every enterprise Java project today. The development of every new Java production class starts by writing a test driver for that class. Test drivers are normally written as JUnit tests. Unit tests are integrated in development tools, such as IBM Rational Application Developer for WebSphere, Eclipse, Ant, or Maven. The number of unit tests grows as your application grows. A test for a new class normally includes all the tests for previously developed classes. This ensures that the new class does not interfere with the rest of the application.
The developer runs unit tests often, for example, once a minute or after even minor changes of a class. This ensures that the application remains in a consistent state.
The tests run inside a Java stand-alone test-driven environment. They must provide every service that the test depends on. Often, these services are configured as part of the test environment itself. For example, many databases and their JDBC driver are written in Java and can be included in to the application class path of the test run. Similar to the concept of the embeddable EJB container, these databases are embeddable databases. They start in the same JVM with the application and define their databases and tables at run time. Often, they are defined as in-memory databases. They and their contents vanish after the test run. One advantage is that every programmer has his own database; no coordination with other programmers is necessary. The database is reset to a known state for each test. The Apache Derby embeddable JDBC driver has such a capability. DB2 does not have an
embeddable database.
The downside of dynamic databases is that you must define the database infrastructure and the test data for every run on your own. There are tools that help in that situation. JPA can generate the required tables automatically based on the definition of the Java classes. In addition, DbUnit (http://www.dbunit.org) is a JUnit extension that puts your database into a known state between test runs. It can be used for in-memory databases and for normal data stores. Provided that the Java programmer has sufficient access rights, the Java programmer can use DbUnit to reset the DB2 test database.
Problems with test runs arise when the Java class under test requires special services that are only provided in a full-blown Java Platform, Enterprise Edition server. Examples are security, transaction, or persistency services, which normally cannot be included in the tests. As a circumvention, these services are delegated to serve as mock-ups of objects that typically return hardcoded values from method invocations.
The Spring Container (http://www.springsource.org) addresses this and other problems. Spring in combination with Hibernate (http://www.hibernate.org) became a strong competitor to Java Platform, Enterprise Edition servers such as WebSphere
Application Server.
The EJB 3.1 specification now includes an JSE-friendly embeddable container that is ideally suitable for agile Java development. As of WebSphere Application Server V8.0, this embeddable container is available. It does have some limitations, but can speed up development in a Java Platform, Enterprise Edition environment.
The WebSphere Application Server embeddable EJB container is a container for enterprise beans that does not require a Java Platform, Enterprise Edition server to run. The EJB programming model and the EJB container services are now available for Java Platform, Standard Edition (Java SE) servers.
The EJB container can be used for the following functions:
EJB unit testing: Developers can test their enterprise beans without needing a full server installation of WebSphere Application Server in their development environment. It is an ideal environment for quickly developing and testing applications that might eventually run in the application server. It starts within seconds and is sufficiently configurable for the main tasks for applications that do not need a full Java Platform, Enterprise Edition server.
Embedding enterprise beans in Java SE applications, for example, in batch applications, if the client that uses the EJBs is in the same JVM as the embeddable container.
Embeddable EJB container functions
According to the Enterprise JavaBeans (EJB) 3.1 specification, all embeddable EJB containers that vendors use must at least implement the EJB Lite subset of EJB functionality. It includes the following items:
Local (and no-interface) session beans with synchronous methods only, which include stateless, stateful, and singleton bean types
Declarative and programmatic security
Interceptors
Support for annotations or XML deployment descriptors and the ejb-jar.xml file
Java Persistence Architecture (JPA) 2.0
WebSphere Application Server 8.5 adds the following features to that EJB Lite subset:
 – Java Database Connectivity (JDBC) data source configuration, usage, and dependency injection.
 – Bean validation: To use bean validation with the embeddable EJB container, the javax.validation classes must exist in the class path. This can be achieved by including com.ibm.ws.jpa.thinclient_8.0.0.jar in the class path.
Here are the limitations when you use the embeddable container:
Inbound RMI/IIOP calls are not supported, which means that all EJB clients must exist within the same Java virtual machine (JVM) as the embeddable container.
Message driven beans (MDB) are not supported.
The embeddable container cannot be clustered for high availability.
Embeddable EJB container configuration
Because the embeddable EJB container runs inside your application or your unit test as a separate container, the configuration is different from the normal WebSphere configuration. It relies on a file named embeddable.properties in the current work directory or a property file that the Java system property com.ibm.websphere.embeddable.configFileName points to.
In this file, you define data sources, as shown in Example 7-6. The example shows two data sources that are bound to the JNDI-namespace under the names jdbc/TxDSz and jdbc/NoTxDSz at container startup.
Example 7-6 DB2 data source definitions for the WebSphere embeddable EJB container
# JPA Transactional data source definition
DataSource.db2_1.name=jdbc/TxDSz
DataSource.db2_1.className=com.ibm.db2.jcc.DB2XADataSource
DataSource.db2_1.driverType=4
DataSource.db2_1.databaseName=DB0Z
DataSource.db2_1.serverName=d0zg.itso.ibm.com
DataSource.db2_1.portNumber=39000
DataSource.db2_1.user=DB2R1
DataSource.db2_1.password=db2r1pw
 
# JPA non-Transactional data source definition
DataSource.db2_2.name=jdbc/NoTxDSz
DataSource.db2_2.className=com.ibm.db2.jcc.DB2DataSource
DataSource.db2_2.driverType=4
DataSource.db2_2.databaseName=DB0Z
DataSource.db2_2.serverName=d0zg.itso.ibm.com
DataSource.db2_2.portNumber=39000
DataSource.db2_2.user=DB2R1
DataSource.db2_2.password=db2r1pw
DataSource.db2_2.transactional=false
For a JPA application, it is preferred practice to define both data sources to allow the full JPA functionality, such as automatic entity identity generation. This is done in the no-transactional data source.
The number of configuration parameters are limited compared to the number of configuration options you have with WebSphere Application Server. The following WebSphere Information Center contains a list of all data source definitions:
There is no configuration option for the current schema; it must be defined by an persistence.xml property statement:
<property name="openjpa.jdbc.Schema" value="DSN81010" />
A short Java Platform, Enterprise Edition example
In this section, a short example shows the usage of the database definition that is shown in Example 7-6 on page 345 in a Java Platform, Enterprise Edition application. It is a basic program that serves only as a starting point for Java Platform, Enterprise Edition -based applications with DB2. The application deals with the EMPLOYEE table in the SAMPLE database of DB2. The SAMPLE database on z/OS is slightly different from the one on Linux UNIX, and Windows. On z/OS, we define an alias of EMPLOYEE for the table DSN81010.EMP to be able to run the example on both databases. The table EMPLOYEE exists without alias on DB2 for Linux, UNIX, and Windows.
The Java equivalent of the EMPLOYEE table is the Java class Employee, as shown in Example 7-7.
The server and JPA run time knows at class load time that this class corresponds to the database table EMPLOYEE because it is annotated with the @Entity tag. By default, the Java names for the class and the fields are directly taken by the JPA run time as names for use with the database. In addition, the source file defines a @NamedQuery for later use by other parts of the application.
Example 7-7 The Employee class
package com.ibm.itso.entities;
 
import java.io.Serializable;
import javax.persistence.*;
import java.math.BigDecimal;
import java.util.Date;
 
@Entity
@NamedQuery(name="DeleteEmpAThiele", query="DELETE FROM Employee e
where e.lastname = 'Thiele'")
 
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
 
@Id
private String empno;
@Temporal( TemporalType.DATE)
private Date birthdate;
private BigDecimal bonus;
private BigDecimal comm;
private short edlevel;
private String firstnme;
@Temporal( TemporalType.DATE)
private Date hiredate;
private String job;
private String lastname;
private String midinit;
private String phoneno;
private BigDecimal salary;
private String sex;
private String workdept;
public Employee() {
}
 
public String getEmpno() {
return this.empno;
}
.... more getters and setters .......
 
}
The application shows how Java Platform, Enterprise Edition components, such as transactional EJBs and JPA entities, can be included in agile development.
For that reason, the application is called from a JUnit test inside IBM Data Studio. Test1 does a SELECT on the EMPLOYEE table and checks whether all 42 Employee objects are returned in the result list. Test2 does an INSERT of a new Employee into the table and checks afterward that the number of table rows has increased to 43. Test 3 deletes the added row and checks the correct number of rows afterward. The tests that are shown in Example 7-8 do not belong to the application, and are only for development.
Example 7-8 JUnit test driver
package tests;
 
import static org.junit.Assert.assertEquals;
 
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import ibm.itso.ejbs.EmpBean;
import java.util.List;
 
import javax.ejb.embeddable.EJBContainer;
import javax.naming.NamingException;
 
import com.ibm.itso.entities.Employee;
 
public class TestEmpBean {
 
EJBContainer ec = null;
Employee Emp1 = null;
EmpBean EmpBean = null;
 
@Before
public void initEmbeddableContainerAndTestData() throws NamingException {
 
// Create the embeddable container
ec = EJBContainer.createEJBContainer();
// Use the container context to look up the EmpBean
EmpBean = (EmpBean) ec.getContext().lookup(
"java:global/bin/EmpBean!ibm.itso.ejbs.EmpBean");
// Create some test data
Emp1 = new Employee();
Emp1.setFirstnme("Andreas");
Emp1.setLastname("Thiele");
Emp1.setMidinit("A");
Emp1.setEmpno("999999");
Emp1.setWorkdept("A00");
}
 
@Test
public void testNumberOfEmployeeRows() {
 
// Query Employee table and verify it has 42 rows
List<Employee> Emps = EmpBean.getEmployeeResultList();
assertEquals(42, Emps.size());
}
 
@Test
public void insertNewEmployeeBean() {
 
try {
EmpBean.persistNewEmployee(Emp1);
}
catch (Exception e) {
System.out.println("Exception persisting Employee: " +e);
}
// Number of rows has increased to 43
List<Employee> Emps = EmpBean.getEmployeeResultList();
assertEquals(43, Emps.size());
}
 
//@Ignore
@Test
public void deleteInsertedEmpAgain() {
 
try {
EmpBean.deleteInsertedEmpAgain();
}
catch (Exception e) {
System.out.println("Exception deleting Employee: " +e);
}
// Number of rows should be 42 again
List<Employee> Emps = EmpBean.getEmployeeResultList();
assertEquals(42, Emps.size());
}
@After
public void shutDown() {
ec.close();
 
}
}
The JUnit tests use a stateless session EJB, EmpBean, that is part of the application.
As you can see in Example 7-9, the EJB consists of three transactional methods for SELECT, INSERT, and DELETE for JPA entity objects that are mapped to the EMPLOYEE table. The work with the database is done by the javax.persistence.EntityManager by using the persistence unit EmpPU. No JDBC statement is used to do the work, and no column name used. Even a table name is not given. All this is derived by the JPA container at run time from the Java class that the entity manager is asked to deal with, for example, em.persist(employee);.
In the EJB, only resource references that must be mapped to real names inside the server are used.
Example 7-9 Sample session EJB for SELECT, INSERT, and DELETE of a JPA entity
package ibm.itso.ejbs;
 
import static javax.ejb.TransactionAttributeType.SUPPORTS;
import static javax.ejb.TransactionAttributeType.REQUIRED;
 
import java.util.List;
 
import javax.annotation.Resource;
import javax.annotation.Resources;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.sql.DataSource;
 
import com.ibm.itso.entities.Employee;
 
@Resources({ @Resource(name = "jdbc/TxDSref", type = DataSource.class),
@Resource(name = "jdbc/NoTxDSref", type = DataSource.class) })
 
@Stateless
public class EmpBean {
 
@PersistenceContext(unitName = "EmpPU")
private EntityManager em;
 
@TransactionAttribute(SUPPORTS)
public List<Employee> getEmployeeResultList() {
 
TypedQuery<Employee> query1 = em.createQuery(
"Select d from Employee d", Employee.class);
return query1.getResultList();
}
 
@TransactionAttribute(REQUIRED)
public void persistNewEmployee(Employee employee) {
em.persist(employee);
}
 
@TransactionAttribute(REQUIRED)
public void deleteInsertedEmpAgain() {
Query delete1 = em.createNamedQuery("DeleteEmpAThiele");
delete1.executeUpdate();
}
}
The persistence unit is defined in a short persistence.xml file, as shown in Example 7-10. It shows a transaction-type=”JTA”, declaring that everything is handled within the server. This is different from a persistence-unit with transaction-type="RESOURCE_LOCAL", where all the database connection definitions must be made. Only resource references are used, so the file remains portable.
Example 7-10 Persistence.xml of the sample program
<?xml version="1.0"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="EmpPU" transaction-type="JTA">
<jta-data-source>java:comp/env/jdbc/TxDSref</jta-data-source>
<non-jta-data-source>java:comp/env/jdbc/NoTxDSref</non-jta-data-source>
<class>com.ibm.itso.entities.Employee</class>
<properties>
<property name="openjpa.Log" value="DefaultLevel=INFO" />
<property name="openjpa.jdbc.Schema" value="DSN81010" />
</properties>
</persistence-unit>
</persistence>
The references are resolved in the definition of the container definition file embeddable.properties. For every EJB that uses database resources, a Bean<bean_name>.ResourceRef.BindingName.jdbc statement must be included. This definition is then assigned to a bean by the container after an EJB is found.
At start, the container looks for enterprise beans in the class path, that is, it looks for Java classes that are annotated, for example, with the @Stateless annotation. The EJBs found are then further examined for resource references. They are declared in the EJBs by annotations like @Resource(name = "jdbc/TxDSref", type = DataSource.class), which are resource references.
Resource references must be bound to names in the servers namespace at deployment time. The name in @Resource(name = "jdbc/TxDSref" resolves to java:comp/env/jdbc/TxDSref, as any resource reference would be named in Java. This reference is likewise defined in the persistence.xml file for the JPA container.
Because there is no deployment in this case, the relationship between the resource reference and the real JNDI name for the resource in the server must be defined in the embeddable containers definition file. The following example shows how to accomplish this task:
Bean.#bin#EmpBean.ResourceRef.BindingName.jdbc/TxDSref=jdbc/TxDSz
The bean named EmpBean in the /bin directory uses a resource reference named jdbc/TxDSref that resolves to the servers JNDI name jdbc/TxDSz.
The beans must be registered in the namespace as well so that they can be looked up by clients, such as the TestEmpBean.java JUnit test driver. The embeddable container does this task, like any other Java Platform, Enterprise Edition application server, in the java.global namespace. The name under which the bean can be found is the following one:
java:global/bin/EmpBean!ibm.itso.ejbs.EmpBean
The name ibm.itso.ejbs.EmpBean is the fully qualified class name of the class in the class path and /bin/EmpBean is the location where it can be found. /bin in this case is the output folder for compiled classes in the current directory (the project directory in Rational Application Developer). Alternatively, this can be the name of a JAR file containing @Stateless annotated classes (without the .jar in the name), which then is taken as the EJB
module name.
To run the unit test, the project must have the following JAR files in its class path. Some of the JAR files can be found in a WebSphere Application Server installation. You can get one, for example, if you augment IBM Data Studio with the WebSphere Application Server test environment, as described in Appendix C, “Setting up a WebSphere Application Server test environment on IBM Data Studio” on page 523.
com.ibm.ws.ejb.embeddableContainer_8.5.0.jar
com.ibm.ws.jpa.thinclient_8.5.0.jar
db2jcc_license_cu.jar or db2jcc_license_cisuz.jar for connections to DB2 for z/OS
db2jcc4.jar
Run TestEmpBean.java as a JUnit test, which creates a run configuration that must be updated afterward because you must specify a Java agent in your Java system properties to enhance the JPA entities. For the TestEmpBean JUnit test run, click Run 
Run Configurations.
An example of how to do this task for JUnit tests is shown in Figure 6-14 on page 325. For the run with the embeddable EJB container, use the following statement:
-javaagent:"C:ProgrammeibmWebSphereAppServer untimescom.ibm.ws.jpa.thinclient_8.5.0.jar
Run TestEmpBean.java as a JUnit test a second time. This time you should see the green bar for a successful test, as shown in Figure 7-1.
Figure 7-1 Insert and delete a table row with embeddable EJB container - successful test
Despite your success, you might see the following error message during the unit test:
NMSV0307E: A Java: URL name was used, but Naming was not configured to handle Java: URL names. The likely cause is a user in error attempting to specify a Java: URL name in a non-J2EE client or server environment. Throwing ConfigurationException.
This error message is explained at the following web page:
Why JPA enhancement
You do not need to be concerned about enhancement if you deploy an application into a Java EE 5 compliant application server, such as WebSphere Application Server, because it enhances your entities automatically at run time. Thus, enhancement can be an issue only for Java stand-alone applications, such as with JUnit testing.
What is enhancement? If a Java class is annotated as a JPA entity (@Entity), then all its non-transient fields are traced by the JPA run time. Changing a field marks it as dirty, which means it must be persisted. Similar monitoring occurs with variables that are annotated with FetchType.LAZY, where a special access strategy must be prepared. The class does this work by “enhancing” the setters of applicable fields with newly generated Java code. This can be done at build time by using the org.apache.openjpa.ant.PCEnhancerTask utility. It is more common to change the entity at class load time dynamically through a Java agent.
The concept of Java agents was introduced in JDK5 and works by specifying a JAR file with the agent class in the -javaagent keyword at JRE start time. The META-INF/MANIFEST.MF file of this JAR file has the Premain-Class keyword, which specifies the agent class.
The agent is intercepted in front of your main method. It can configure the runtime environment before your application runs. The agent can then manipulate the class loaders to add JPA code to your classes.
Java agents for JPA enhancement are provided by both the openjpa-2.2.0.jar and com.ibm.ws.jpa.thinclient_8.5.0.jar files, which can be found in the runtimes directory of WebSphere Application Server.
If you run the application in WebSphere Application Server, you can obtain a small performance benefit if you can enhance your entities when you build the application. The application does not attempt to enhance entities that are already enhanced.Enhance the entity classes by using the JPA enhancer tool, wsenhancer, which can be found in the bin directory of WebSphere Application Server.
On a Windows development system where all your entity classes are in the build directory, the command to enhance all the entities on the class path looks like Example 7-11.
Example 7-11 wsenhancer command
C:myprojectcd build
C:myprojectuild>%profile_root%inwsenhancer.bat
Summary
With WebSphere Application Server, embeddable EJB container agile Java EE development becomes feasible.
7.2.4 Use of alternative JPA persistence providers
The default persistence provider in WebSphere Application Server is the JPA for the WebSphere Application Server persistence provider that is implemented in the com.ibm.websphere.persistence.PersistenceProviderImpl class. Alternatively, the Apache OpenJPA persistence provider can be used. These two providers are built into the server and installed automatically during the server installation.
Although they are built from the Apache OpenJPA persistence provider, the JPA for WebSphere Application Server persistence provider contains the following enhancements and differences:
Static SQL support using the DB2 pureQuery feature.
Access intent support.
Enhanced tracing support.
Version ID generation.
WebSphere product-specific commands and scripts.
Translated message files.
Check in-memory caches for lazily loaded many-to-one or one-to-one relationships. Setting the wsjpa.BrokerImpl property to true specifies that the JPA implementation attempts to load lazy fields from memory at run time if the foreign key data for the lazy fields are available.
If no JPA provider is configured in the <provider> element of the persistence.xml file within an Enterprise JavaBeans (EJB) module, the default JPA provider that is configured for this server is used. The product is packaged with the JPA for WebSphere Application Server persistence provider that is defined as the default provider. However, it is possible to override this default and specify a different default through the administrative console, as shown in Figure 7-2. To do so, click Application servers, select your server, and click Container Services  Default Java Persistence API settings.
Figure 7-2 Specify an alternative default persistence provider
Depending on your requirements, you can embed the implementation classes of an alternative persistence provider inside an application, or place the persistence provider into a shared library.
7.2.5 Usage of Non-JTA data sources
Some JPA entity features require that a non-JTA data source be specified. An example of this is automatic entity identity generation. Ensure that a non-JTA data source is configured to match your application needs. A non-transactional data source must be defined in WebSphere Application Server for that purpose. To accomplish this task, click Data sources, click your data source, click WebSphere Application Server data source properties, and select the Non-transactional datasource check box, as shown in Figure 7-3.
The application server does not enlist the connections from this data source in global or local transactions. Non-JPA applications must explicitly call setAutoCommit(false) on the connection if they want to start a local transaction on the connection, and they must commit or roll back the transaction that they started.
Figure 7-3 Non-transactional data source
7.2.6 Data source resource definition in applications
In support of the Java Enterprise Edition (Java EE) 6 specification, applications can define data sources in annotations or in the deployment descriptor, as shown in Example 7-12.
Example 7-12 Data source definition with Java annotations
@DataSourceDefinition(
name = "java:comp/env/jdbc/db2",
className = "com.ibm.db2.jcc.DB2DataSource",
databaseName = "SAMPLEDB",
serverName = "localhost",
portNumber = 50000,
properties = { "driverType=4" },
user = "user1",
password = "pwd1"
)
7.2.7 Definition of the IBM DB2 Driver in WebSphere Application Server V8.5 Liberty Profile
The Liberty profile is a new dynamic profile of WebSphere Application Server V8.5 that provisions only the features that are required by the applications. For example, if an application requires a servlet engine, a Liberty profile can be configured to start only the WebSphere Application Server kernel, the HTTP transport, and the web container. This improves the server start time and results in a small footprint because it does not use the full Java Enterprise Edition stack. Furthermore, if the application needs additional features such as database connectivity, the Liberty profile configuration can be dynamically modified to include the JDBC feature without the needing a server restart.
The name of the product suggests that the server might be just another profile of the WebSphere Application Server product. This is misleading. The Liberty Profile is a new product that is different from WebSphere Application Server. For example, you do not need the Profile Management Tool (PMT) to create a new server. The code may be shared in many cases with the normal application server, but the packaging is different. In addition to the binary files, which have only a less than 50 MB footprint, you need just one XML file to configure a server.
This section cannot show all the details of that server. You can find a detailed description of the Liberty Profile in WebSphere Application Server V8.5 Administration and Configuration Guide, SG24-8056. Here, we focus on the definition of the IBM Data Server Driver for JDBC and SQLJ driver and the way to configure a data source.
To run the sample application db2_jpa_web, you must define the WebSphere Application Server Liberty Profile server.xml file as shown in Example 7-13.
Example 7-13 Server and data source definitions for Liberty Profile
<server description="ITSO DB2R1">
 
<!-- Enable features -->
<featureManager>
<feature>jsp-2.2</feature>
<feature>jsf-2.0</feature>
<feature>localConnector-1.0</feature>
<feature>jpa-2.0</feature>
<feature>jdbc-4.0</feature>
</featureManager>
 
<httpEndpoint host="localhost"
httpPort="9080"
httpsPort="9443"
id="defaultHttpEndpoint"/>
 
<jdbcDriver id="DB2T4" libraryRef="DB2T4LibRef"/>
<library id="DB2T4LibRef">
<fileset dir="C:/aps/IBM/SQLLIB/java/"
includes="db2jcc4.jar db2jcc_license_cu.jar"/>
</library>
<dataSource beginTranForResultSetScrollingAPIs="false"
connectionSharing="MatchCurrentState"
id="sample_ds"
isolationLevel="TRANSACTION_READ_COMMITTED"
jdbcDriverRef="DB2T4" jndiName="jdbc/sample"
statementCacheSize="20">
<connectionManager
agedTimeout="30m"
connectionTimeout="10s"
maxPoolSize="20"
minPoolSize="5"/>
<properties.db2.jcc databaseName="DB0Z"
driverType="4"
password="db2r1pw"
portNumber="39000"
serverName="d0zg.itso.ibm.com"
currentSchema="DSN81010"
user="db2r1"/>
</dataSource>
 
<applicationMonitor updateTrigger="mbean"/>
</server>
To run the WebSphere Application Server Liberty Profile, you can either install a single server run time or you can augment IBM Data Studio with the WebSphere Application Server test environment, as described in Appendix C, “Setting up a WebSphere Application Server test environment on IBM Data Studio” on page 523, which describes how to install the Liberty Profile in IBM Data Studio. For more information about the data source definition, see the Information Center found at the following website:
7.2.8 LOB streaming
JPA 2 with DB2 supports LOB streaming. Large amounts of data can be streamed into and out of persistent fields without ever holding that data in memory.
To use LOB streaming, either annotate a java.io.InputStream or a java.io.Reader property with an @Persistent annotation, as shown in Example 7-14.
Example 7-14 LOB streaming
@Entity
public class Employee {
...
@Persistent
private InputStream photoStream;
There is a known issue with LOB data streaming and DB2 for very large streams. You might have to switch progressive streaming off. For more information, see 7.4, “Known issues with OpenJPA 2.2 and DB2” on page 359.
7.2.9 XML JPA column mapping
DB2 is one of only a few databases that support XML column types, XPath queries, and indexes over these columns. As of DB2 9, mapping of an entity property that is mapped to an XML column is supported by OpenJPA.
With WebSphere Application Server V8.5, column mapping is no longer a server extension feature, but is provided directly by OpenJPA. Therefore, you can find information regarding XML mapping in the Apache OpenJPA documentation directly at the following website:
Here is an example of this feature. As always with JPA, the process is about mapping Java objects to database columns. In the case of mapping to an XML column, the standard mapping routine cannot be used. Instead, you must specify a third-party mapping tool, which is done by annotating the field containing the JAXB object that is persisted as XML with a strategy handler, as shown in Example 7-15.
The handler knows how to deal with Java Architecture for XML Binding (JAXB) annotations. With JAXB, a Java object can be marshalled or unmarshalled to an XML structure as defined by JAXB annotations. This is analogous to what JPA does with database objects.
Example 7-15 Applying a third-party XML mapping tool using JPA annotations
...
@Persistent
@Strategy("org.apache.openjpa.jdbc.meta.strats.XMLValueHandler")
@Persistence(fetch=FetchType.LAZY)
private MyXMLObject xmlObject;
...
A sample Java object that is converted to its XML equivalent and is included in the JPA entity that is shown in Example 7-15 looks like Example 7-16.
Example 7-16 Sample JAXB object to be included into a JPA entity
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
....
public class MyXMLObject {
@XmlElement(name = "field1", required = true)
protected String field1;
@XmlElement(name = "list1", required = true)
protected List<String> list1;
.....
The XML structure is built by JAXB and then persisted by JPA. The JAXB JAR files must be on the application class path (jaxb-api.jar, jaxb-impl.jar, jsr173_1.0_api.jar, or the equivalent).
For more information about how WebSphere Application Server is involved in this process, see the following website:
7.3 Preferred practices of Java Platform, Enterprise Edition and DB2
This section provides samples of Preferred practices of Java Platform, Enterprise Edition
and DB2.
7.3.1 Using resource references
Even today, many classes use data sources directly instead of resource references. Theoretically, there are two ways of direct access:
1. Connection attributes are defined in the DriverManager.getConnection() properties and virtually hardcoded. This is an oversimplification for demonstration purposes.
2. The application class uses a managed data source but specifies its JNDI name in the server directly. No reference is used.
Coding infrastructure information in the Java code is a breach of the separation of concerns (SoC) principle and prevents portability. Although this works in many cases, it can lead to some problems in others.
Section 6.6, “JDBC applications in managed environments” on page 326 provides details about resource references.
The application server requires the usage of resource references for the following reasons:
If application code looks up a data source directly in the JNDI naming space, every connection that is maintained by that data source inherits the properties that are defined in the application. Then, you create the potential for numerous exceptions if you configure the data source to maintain shared connections among multiple applications. For example, an application that requires a different connection configuration might attempt to access that particular data source, resulting in application failure.
It relieves the programmer from having to know the name of the data source or connection factory at the target application server.
You can set the default isolation level for a data source through resource references. With no resource reference, you get the default for the JDBC driver that you use.
7.3.2 Providing a JDBC driver in your application libraries
You should not provide a JDBC driver in your application libraries.
For a large Java Platform, Enterprise Edition project, it is normal that the application is built several times a day from a central repository. Hundreds and even thousands of program artifacts are checked out and combined in several deployable archives like .ear, .jar, and .war files. This process mostly is done by specialized builder programs such as Maven.
This process normally must be done for several environments, such as unit tests, integration environments, or quality assurance systems. Some might have predefined database connections, and some might not. Unit tests normally run unmanaged, so they must provide their own database connectivity. In these cases, you need the JDBC driver in your /lib directory, but in production you must not have it there, as wrong packaging can easily occur.
There are problems when these “forgotten” drivers interfere with the installed driver in the application server. This is especially the case when your application is deployed with the class loading policy parent last. Parent last means that everything in your application is loaded before the classes in the application server.
This has the same effect as a STEPLIB in your JCL. Every program in the STEPLIB overcomes the one that the system provides, which is not wanted behavior in a production environment.
7.3.3 Resetting the database for each test run
During the development of the application, every developer should have one set of database test data to prevent data corruption. To obtain this set, setting up the database infrastructure with many schemata.
You should always avoid creating tests that depends on the results of preceding tests. The entire database might not need to be reinitialized, but the parts you use should be.
7.3.4 Optimizing generated SQL from persistence frameworks
Persistence frameworks such as JPA or Hibernate by default do not use DB2 capabilities fully because they produce simple but not always performant SQL. If you want to see how JPA functions, enable a WebSphere Application Server trace by running the following string:
/F MZSR015,TRACEJAVA='JPA=all: openjpa=all: SystemErr=all: SystemOut=all: com.ibm.pq=all'
You see all the generated dynamic SQL statements. You can see how a change of the JPA class annotations is reflected in the SQL. If the results are not satisfactory, you might have to use native queries where you have full control over the SQL.
Reset the trace by running the following string:
/F MZSR015,TRACEINIT
7.4 Known issues with OpenJPA 2.2 and DB2
The OpenJPA 2.2. Reference Guide reports some known issues with DB2. Here are the known issues that result from a connection to DB2 for z/OS:
Floats and doubles might lose their precision when stored.
Empty char values are stored as NULL.
Fields of type BLOB and CLOB are limited to 1M. This number can be increased by extending DB2Dictionary.
The usage of DB2 on z/OS with the IBM Data Server driver requires the DESCSTAT subsystem parameter value to be set to 'YES'. If this parameter is set to 'NO', the mapping tool fails with a persistence exception that has this error
“Invalid parameter: Unknown column name TABLE_SCHEM"
After changing the value of DESCSTAT, DB2 metadata tables must be re-created by running the DSNTIJMS job.
When using LOBs with persistent attributes of a streaming data type (for example, java.io.InputStream) in the case of a very large LOB, the DB2 Data Server driver automatically uses progressive streaming to retrieve the LOB data. If you get an LobClosedException, you might have to set the following string:
fullyMaterializeLobData=true;progressiveStreaming=NO
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset