Troubleshooting Java Persistence API (JPA) applications
Use this information to find various known problems with JPA applications.
- Review messages that are related to transactions.
Under certain conditions, a message similar to the following might be logged:
Unable to execute {0} on a WebSphere managed transaction. WebSphere does not support direct manipulation of managed transactions.
This error is probably caused by a data source not configured correctly as <non-jta-data-source>. See the information center topic on how to configure a data source to be used as a <non-jta-data-source>.
- Troubleshoot classes that have not been enhanced by run time.
It is difficult to diagnose these situations. Sometimes we can trace the problem back to a lack of OpenJPA enhancement of entity classes. Examples of these situations might be detecting when entities are not "persistence capable". Look for a message similar to the following in the log:
This configuration disallows runtime optimization, but the following listed types were not enhanced at build time or at class load time with a javaagent: "{0}".
This message indicates that the expected runtime enhancement did not take place on the listed entity types. In most cases, this is just a build time failure and the PCEnhancer needs to be run on the listed classes. It can also indicate a more involved problem, especially if we are expecting the container classloader transform to do the entity enhancement.
- Troubleshoot issues with closed cursors.
The following is an exception from DB2 in the log org.apache.openjpa.persistence.PersistenceException:
[ibm][db2][jcc][10120][10898] Invalid operation: result set is closed can be a WAS configuration problem. By default, the application server configures the resultSetHoldability custom property with a value of 2 (CLOSE_CURSORS_AT_COMMIT). This property causes DB2 to close its resultSet/cursor at transaction boundaries. Despite DB2's default resultSetHoldability value of 1 (HOLD_CURSORS_OVER_COMMIT), the appserver retains the default value of 2 to avoid breaking compatibilities with previous releases of the appserver. We can change the default if the need arises.
If this is an XA datasource, define a new custom property on the datasource where property_name = downgradeHoldCursorsUnderXa and boolean value = true.
Avoid trouble: In V 7.0, if a DB2 XA Data source is used, the following configuration are required to overcome the "result set closed" problem:
- Apply DB2 V8.1 FP17 for APAR IZ18070 or V 9 FP4 for APAR IZ18072.
- Add custom property name="downgradeHoldCursorsUnderXa", value="true" and type="java.lang.Boolean"
- Add custom property name="resultSetHoldability", value="1", and type="java.lang.Integer"
- Avoid multi-threaded EntityManager usage. If we experience an exception with the following message text, we might be accidentally allowing the usage of an EntityManager across multiple threads.
Per the JPA specification, EntityManagers are meant to be used by a single thread. We might receive an exception message that is similar to the following (in this context, brokers and EntityManagers are essentially the same thing):
Multiple concurrent threads attempted to access a single broker. By default brokers are not thread safe; if we require and/or intend a broker to be accessed by more than one thread, set the openjpa.Multithreaded property to true to override the default behavior. There are some ways to address this issue:
- As documented in this exception text, an easy workaround to the situation is to tell OpenJPA that we are requiring multi-threaded access to the EntityManagers through the openjpa.Multithreaded property. This can introduce unnecessary overhead if multi-threaded access occurs not intentional.
- Best practice: Utilize the get-use-close pattern when using application-managed (extended) persistence contexts. Remember to close the EntityManager before leaving the method that used the EntityManager. Leaving the EntityManager open can accidentally allow other threads to use the same EntityManager instance at the same time
- Change the application to use container-managed persistence contexts by injecting the EntityManager instance through the @PersistenceContext annotation, if the model for the application is amenable to this change. Essentially, this enforces the get-use-close pattern by allowing the container to do the management.
- Be aware of versioning conditions if we are using optimistic locking. In the JPA architecture, the persistence provider uses the version property to perform optimistic locking and concurrency semantics for a persisting entity. For example:
@Entity public class VedTimestampEntity { @Id private int id; @Version private java.sql.Timestamp version; .... }The provider updates the versioned property to a new value when an entity is written to the database. During an entity merge operation, the persistence provider examines this versioned property to determine if the entity that is being merged is a stale copy of the entity. If the operation failed due to the stale versioning condition, an OptimisticLockException will be thrown. The versioned property can be one of these types:
- int
- Integer
- short
- Short
- long
- Long
- Timestamp.
Avoid trouble: If we use the Timestamp type for the versioned property, the application needs to be aware of behavior that can be exhibited due from the implementation precision used for creating the Timestamp object. The typical implementation uses System.currentTimeMills(), and the time precision of this method is platform specific. For example, the precision is approximately 15ms for 32-bit Windows and 2ms for z/OS. If an entity is persisted, and the entity is then fetched and updated in a separate persistence context that is within the precision window of the platform, the persistence provider will not be able to detect the optimistic locking and concurrent condition. As a result, an OptimisticLockException may not be thrown and data integrity could be compromised.
- Troubleshoot database constraint violations when working with entities.
The JPA providers included with WAS use a constraint update manager to determine the order of SQL requests to the database based on each entity's configuration. This update manager may rearrange the order of SQL requests to the database. This alleviates an application from knowing the order of entity manager operations required to perform its business logic and optimizes database performance using underlying batching support.
Since the JPA provider does not assume that there are implied database constraints for relationships between entities, if there are constraints in the database (for example, a foreign key constraint) the JPA provider may not issue SQL statements in the desired order. Under these conditions, the following or similar exception may be observed:
com.ibm.db2.jcc.b.SqlException: DB2 SQL error: SQLCODE: -530, SQLSTATE: 23503, SQLERRMC: xxxxxxThere are some ways to address this issue:
- The JPA provider can be configured to read constraint information from the database and apply to the update manager at runtime by adding the following configuration property to the persistence unit.
<property name="openjpa.jdbc.SchemaFactory" value="native(ForeignKeys=true)" />- The application can enhanced entity to use @ForeignKey annotation to indicate to the JPA provider which relationships have foreign key constraints.
public class Person { @ManyToOne @ForeignKey private Address address; .... }- The application can take on the responsibility of ordering the SQL statements by adding the following configuration property to the persistence unit.
<property name="openjpa.jdbc.UpdateManager" value="operation-order" />With this configuration option present, the JPA provider will execute the SQL statements in the same order as the entity operations were requested. The application must be aware of any interdependencies between entities.
- Remove the constraints from the database.
- Troubleshoot using the OpenJPA MappingTool ANT task.
The MappingTool ANT task provided by OpenJPA uses a temporary classloader to load the JDBC driver classes. This temporary classloader may have trouble loading some JDBC drivers such as DB2.
When you run the MappingTool ANT task, you could see something similar to the following error: [mappingtool] java.lang.UnsatisfiedLinkError: com/ibm/jvm/Trace.initTrace([Ljava/lang/String;[Ljava/lang/String;)V [mappingtool] at com.ibm.jvm.Trace.initializeTrace(Trace.java:94) [mappingtool] at com.ibm.jvm.Trace.<clinit>(Trace.java:59) [mappingtool] at java.lang.J9VMInternals.initializeImpl(Native Method) [mappingtool] at java.lang.J9VMInternals.initialize(J9VMInternals.java:200) [mappingtool] at java.lang.Class.forNameImpl(Native Method) [mappingtool] at java.lang.Class.forName(Class.java:136) [mappingtool] at com.ibm.db2.jcc.a.o.n(o.java:577) [mappingtool] at com.ibm.db2.jcc.a.o.<clinit>(o.java:329)
In order to use the mapping tool, we can disable the temporary classloader by adding the tmpClassLoader=false argument to the ANT task. Two example ANT scripts follow :
This example will exhibit the problem:
<taskdef name="mapping" classname="org.apache.openjpa.jdbc.ant.MappingToolTask" classpathref="jpa.cp"/> . . . <target name="map.broken"> <mapping> <!-- this will exhibit the problem --> . . . </mapping> </target>This example will prevent the problem:
<taskdef name="mapping" classname="org.apache.openjpa.jdbc.ant.MappingToolTask" classpathref="jpa.cp"/> . . . <target name="map.fixed"> <mapping tmpClassLoader="false"> <!-- this will work --> . . . </mapping> </target>- Impact of DataCache on inconsistent domain models
When an application persists an inconsistent domain model and later retrieves the entities in a separate persistence context, the retrieved entities will differ depending on whether DataCache is active or not.
For example, consider bi-directional, one-to-one relationship between two entities mapped by a single foreign key column in the database. It is possible for an application to set the relation fields in the entities inconsistently. When such inconsistent values are mapped to the database, the database records become consistent only because a single foreign key column expresses the bi-directional relationships DataCache is active, however, then DataCache captures the inconsistent in-memory entity states. Therefore, when an application persists a pair of entities related in a bi-directional relation but their relation fields are set to inconsistent values and later retrieves the entities in a different persistence context, the bi-directional relationship either remains inconsistent or becomes consistent depending on whether DataCache is used or not.
When multiple fields are mapped to the same column but set to different values is another example where an inconsistent entity state is persisted but retrieved as consistent in a separate persistence context. In this case, the introduction of DataCache will also cause an entity realized in a separate persistence context to retain different and inconsistent values while without a DataCache, an entity will hold the same value for both the fields.
The best practice is to avoid populating the application domain model inconsistently. It is also possible to configure openjpa.InverseManager property to detect certain inconsistencies such as bi-directional relationship.
Logging with the Java Persistence API (JPA) and the appserver
Troubleshooting Java Persistence API (JPA) deadlocks and transaction time-outs
wsjpaversion
Related tasks
Task overview: Storing and retrieving persistent data with the Java Persistence API (JPA)