Troubleshooting JPA applications
Use this information to find various known problems with Java Persistence API (JPA) applications.
- Review messages related to transactions.
Under certain conditions, a message like 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 that is not configured correctly as <non-jta-data-source>.
- Troubleshoot classes that have not been enhanced by run time.
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 like 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 Java agent: "{0}"
This message indicates that the expected runtime enhancement did not take place on the listed entity types. In most cases, this error is just a build time failure and the PCEnhancer must be run on the listed classes. It can also indicate a more involved problem, especially if the container class loader transform is expected to do the entity enhancement.
- Troubleshoot issues with closed cursors.
The following is a DB2 exception located 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 the DB2 default resultSetHoldability value of 1 (HOLD_CURSORS_OVER_COMMIT), the application server retains the default value of 2 to avoid breaking compatibilities with previous releases of the application server. We can change the default.
If this data source is an XA data source, define a new custom property on the data source where property_name = downgradeHoldCursorsUnderXa and boolean value = true.
Avoid trouble: In Version 8.0, if a DB2 XA data source is used, the following configuration are required to overcome the result set closed problem:
gotcha
- Use DB2 Version 9.1 FP4 (for APAR IZ18072) or a later version.
- 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 an exception occurs with the following message text, you might be accidentally supporting 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 like 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 you require and 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:
Best practice: Use 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 cause other threads to use the same EntityManager instance at the same time and might consume system resources.bprac
- Change the application to use container-managed persistence contexts by injecting the EntityManager instance through the @PersistenceContext annotation, if the programming model for the application is amenable to this change. Essentially, this enforces the get-use-close pattern by supporting the container to do the management.
- As documented in this exception text, a quick workaround is to configure OpenJPA to require multi-threaded access to the EntityManagers in the openjpa.Multithreaded property. Enable this property can introduce unnecessary overhead.
Avoid trouble: Instance variables for servlets are automatically shared by all instances of the servlet. Using the @PersistenceContext annotation on a servlet instance variable can unintentionally result in multi-threaded access to the same EntityManager. In addition, any EntityManagers injected in this manner are not cleaned up by the container until the application is stopped. For servlets, it is a better choice to use the @PersistenceUnit annotation to inject an EntityManagerFactory. gotcha
- If we are using optimistic locking, be aware of version conditions. 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 VersionedTimestampEntity { @Id private int id; @Version private java.sql.Timestamp version; .... }
The provider updates the version 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 version condition, an OptimisticLockException occurs. The version property can be one of these types:
- int
- Integer
- short
- Short
- long
- Long
- Timestamp.
Avoid trouble: If we use the Timestamp type for the version property, the application must be aware of behavior that can be exhibited due from the implementation precision used for creating the Timestamp object. The typical implementation uses the System.currentTimeMills method. The time precision of this method is platform-specific. For example, the precision is 15 ms for 32 - bit Windows and 2 ms for z/OS .gotcha 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 cannot detect the optimistic locking and concurrent condition. As a result, an OptimisticLockException might not be thrown and data integrity is compromised.
- Troubleshoot database constraint violations when working with entities.
The JPA providers included with WebSphere Application Server use a constraint update manager to determine the order of SQL requests to the database based on each entity configuration. This update manager can 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 might not issue SQL statements in the wanted order. Under these conditions, the following or similar exception might occur:
com.ibm.db2.jcc.b.SqlException: DB2 SQL error: SQLCODE: -530, SQLSTATE: 23503, SQLERRMC: xxxxxx
There 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 run time 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 starts the SQL statements in the same order as the entity operations were requested. The application must be aware of any interdependencies between entities.
Avoid trouble: Even though you might be inclined to use a combination of these properties, you should only use the one the best fits the situation. If we have a situation where you think you do need to use a combination of these properties, be aware that using both the openjpa.jdbc.UpdateManager and openjpa.jdbc.SchemaFactory properties might not result in the SQL request ordering required to fix the exception. The operation-order setting for the openjpa.jdbc.UpdateManager property indicates to the JPA provider we want SQL requests performed in the order they are specified within an application. Even if specified the openjpa.jdbc.SchemaFactory property, along with the openjpa.jdbc.UpdateManager command, the JPA provider honors the SQL request order specified in an application instead of automatically ordering SQL requests to honor a detected constraint, such as a Foreign Key constraint. Whenever the openjpa.jdbc.UpdateManager property is specified, it is the responsibility of the application developer to ensure that the SQL requests are specified in the proper order within an application.gotcha
- Remove the constraints from the database.
- Troubleshoot using the OpenJPA MappingTool ANT task.
The MappingTool ANT task provided by OpenJPA uses a temporary class loader to load the JDBC driver classes. This temporary class loader might have trouble loading some JDBC drivers such as DB2.
When you run the MappingTool ANT task, you see an error similar to the following: [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)
To use the mapping tool, we can disable the temporary class loader by adding the tmpClassLoader=false argument to the ANT task. Two example ANT scripts follow:
This example exhibits the problem:
<taskdef name="mapping" classname="org.apache.openjpa.jdbc.ant.MappingToolTask" classpathref="jpa.cp"/> . . . <target name="map.broken"> <mapping> <!-- this exhibits the problem --> . . . </mapping> </target>This example prevents 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 are different depending on if the DataCache is active or not.
For example, consider bidirectional, 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 bidirectional 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 bidirectional relation but their relation fields are set to inconsistent values and later retrieves the entities in a different persistence context, the bidirectional relationship either remains inconsistent or becomes consistent depending on if the DataCache is used.
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 also causes an entity realized in a separate persistence context to retain different and inconsistent values while without a DataCache, an entity holds the same value for both the fields.
Best practice: Avoid populating the application domain model inconsistently. It is also possible to configure openjpa.InverseManager property to detect certain inconsistencies such as bidirectional relationship.bprac
- Troubleshoot problems with the MappingTool and @ForeignKey annotation with Sybase.
The OpenJPA mapping tool is unable to create ForeignKey constraints when used with Sybase Adaptive Server. As a result, the foreign key constraints must be created manually.
- Troubleshoot the DB2 Optimâ„¢ pureQuery Runtime configuration options.
If we are using DB2 Optim pureQuery Runtime with the WAS JPA provider, set the following property in the persistence.xml file:
<property name="openjpa.Compatibility" value="StrictIdentityValues=true"/>
If we must set a different compatibility option, for example ReloadOnDetach=false, specify both options as parameters of the same property statement in the persistence.xml file. For example :
<property name="openjpa.Compatibility" value="StrictIdentityValues=true,ReloadOnDetach=false"/>
The OpenJPA compatibility property does not remove proxy types that OpenJPA generates for certain data types, especially date types such as GregorianCalendar. This omission can cause problems with deserialization. If a deserialization problem occurs, an error message, similar to the following message, is issued:gotcha
Error Message is:org.codehaus.jackson.map.JsonMappingException: Can not construct instance of org.apache.openjpa.util.java$util$GregorianCalendar$proxy, problem: no suitable creator method found at [Source: org.apache.http.conn.EofSensorInputStream@d83fbd5; line: 1, column: 4094]
- Troubleshoot issues with time related type attributes in an entity when we are using a database with DB2 for z/OS. If an entity has a time related type attribute, and the corresponding mapped column that is targeted to the database is not compatible, the following exception might be observed under certain situations:
org.apache.openjpa.lib.jdbc.ReportingSQLException: THE DATE, TIME, OR TIMESTAMP VALUE 1 IS INVALID. SQLCODE=-18x, SQLSTATE=22007
You might see this exception if:
- Your database is running DB2 for z/OS.
- We are using a named query and access the database with native SQL.
- The native query uses the time related field as an SQL parameter, but the query is not compatible with the column definition for the database table. See the Supported data conversions topic in the DB2 9.7 Information Center for more information on compatibility.
To resolve this issue, we can instruct the DB2 server to relax the conversion rule. Set the deferPrepares property to false in the database connection or in the data source.
Subtopics
- Logging applications with JPA
Logging supports viewing, tracing, and troubleshooting the runtime behavior of an application. Java Persistence API (JPA) provides a flexible logging system that is integrated with the application server to assist you in troubleshooting problems.
- Troubleshooting JPA deadlocks and transaction timeouts
Database deadlocks and transaction timeouts are the result of contention between two or more clients attempting to access the same database resource. Deadlock is a special case where a circular blocking condition between two or more clients, each blocked by the others, but no one can proceed. Usually these phenomena are not programming errors. They are caused by business logic accessing database resources in a complex and inter-depending fashions.
Related tasks
Task overview: Storing and retrieving persistent data with the JPA API Associate persistence providers and data sources wsjpaversion command
Apache OpenJPA User Guide
IBM Optim pureQuery Runtime