You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by ss...@apache.org on 2008/09/06 03:27:31 UTC
svn commit: r692601 - in /openjpa/branches/0.9.7-r547073:
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/
openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/sql/
openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/excepti...
Author: ssegu
Date: Fri Sep 5 18:27:31 2008
New Revision: 692601
URL: http://svn.apache.org/viewvc?rev=692601&view=rev
Log:
OPENJPA-458: Amplified SQL Exception processing. Introduced a new sql-error-state-codes.xml to specify database specific error code for different types of Store exceptions. This helps to narrow SQL exception to a specific errors which bubble up to user application.
Added:
openjpa/branches/0.9.7-r547073/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLErrorCodeReader.java
- copied, changed from r668814, openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLErrorCodeReader.java
openjpa/branches/0.9.7-r547073/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/sql/sql-error-state-codes.xml
- copied unchanged from r668814, openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/sql/sql-error-state-codes.xml
Modified:
openjpa/branches/0.9.7-r547073/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
openjpa/branches/0.9.7-r547073/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DerbyDictionary.java
openjpa/branches/0.9.7-r547073/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLExceptions.java
openjpa/branches/0.9.7-r547073/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/exception/PObject.java
openjpa/branches/0.9.7-r547073/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/exception/TestException.java
openjpa/branches/0.9.7-r547073/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java
Modified: openjpa/branches/0.9.7-r547073/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
URL: http://svn.apache.org/viewvc/openjpa/branches/0.9.7-r547073/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java?rev=692601&r1=692600&r2=692601&view=diff
==============================================================================
--- openjpa/branches/0.9.7-r547073/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java (original)
+++ openjpa/branches/0.9.7-r547073/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java Fri Sep 5 18:27:31 2008
@@ -51,6 +51,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
@@ -93,7 +94,12 @@
import org.apache.openjpa.meta.FieldMetaData;
import org.apache.openjpa.meta.JavaTypes;
import org.apache.openjpa.util.GeneralException;
+import org.apache.openjpa.util.LockException;
+import org.apache.openjpa.util.ObjectExistsException;
+import org.apache.openjpa.util.ObjectNotFoundException;
import org.apache.openjpa.util.OpenJPAException;
+import org.apache.openjpa.util.OptimisticException;
+import org.apache.openjpa.util.ReferentialIntegrityException;
import org.apache.openjpa.util.Serialization;
import org.apache.openjpa.util.StoreException;
import org.apache.openjpa.util.UnsupportedException;
@@ -143,16 +149,6 @@
private static final String ZERO_TIMESTAMP_STR =
"'" + new Timestamp(0) + "'";
- public static final List EMPTY_STRING_LIST = Arrays.asList(new String[]{});
- public static final List[] SQL_STATE_CODES =
- {EMPTY_STRING_LIST, // 0: Default
- Arrays.asList(new String[]{"41000"}), // 1: LOCK
- EMPTY_STRING_LIST, // 2: OBJECT_NOT_FOUND
- EMPTY_STRING_LIST, // 3: OPTIMISTIC
- Arrays.asList(new String[]{"23000"}), // 4: REFERENTIAL_INTEGRITY
- EMPTY_STRING_LIST // 5: OBJECT_EXISTS
- };
-
private static final Localizer _loc = Localizer.forPackage
(DBDictionary.class);
@@ -323,6 +319,8 @@
private Method _setString = null;
private Method _setCharStream = null;
+ public final Map sqlStateCodes = new HashMap();
+
public DBDictionary() {
fixedSizeTypeNameSet.addAll(Arrays.asList(new String[]{
"BIGINT", "BIT", "BLOB", "CLOB", "DATE", "DECIMAL", "DISTINCT",
@@ -3727,8 +3725,32 @@
// if user has unset sequence sql, null it out so we know sequences
// aren't supported
nextSequenceQuery = StringUtils.trimToNull(nextSequenceQuery);
- }
+ // initialize the error codes
+ SQLErrorCodeReader codeReader = new SQLErrorCodeReader();
+ String rsrc = "sql-error-state-codes.xml";
+ InputStream stream = getClass().getResourceAsStream(rsrc);
+ String dictionaryClassName = getClass().getName();
+ if (stream == null) { // User supplied dictionary but no error codes xml
+ stream = DBDictionary.class.getResourceAsStream(rsrc); // use default
+ dictionaryClassName = getClass().getSuperclass().getName();
+ }
+ codeReader.parse(stream, dictionaryClassName, this);
+ }
+
+ public void addErrorCode(Integer errorType, String errorCode) {
+ if (errorCode == null || errorCode.trim().length() == 0)
+ return;
+ Set codes = (Set) sqlStateCodes.get(errorType);
+ if (codes == null) {
+ codes = new HashSet();
+ codes.add(errorCode.trim());
+ sqlStateCodes.put(errorType, codes);
+ } else {
+ codes.add(errorCode.trim());
+ }
+ }
+
//////////////////////////////////////
// ConnectionDecorator implementation
//////////////////////////////////////
@@ -3737,7 +3759,7 @@
* Decorate the given connection if needed. Some databases require special
* handling for JDBC bugs. This implementation issues any
* {@link #initializationSQL} that has been set for the dictionary but
- * does not decoreate the connection.
+ * does not decorate the connection.
*/
public Connection decorate(Connection conn)
throws SQLException {
@@ -3788,7 +3810,7 @@
public OpenJPAException newStoreException(String msg, SQLException[] causes,
Object failed) {
if (causes != null && causes.length > 0) {
- OpenJPAException ret = SQLExceptions.narrow(msg, causes[0], this);
+ OpenJPAException ret = narrow(msg, causes[0]);
ret.setFailedObject(failed).setNestedThrowables(causes);
return ret;
}
@@ -3797,24 +3819,35 @@
}
/**
- * Gets the list of String, each represents an error that can help
- * to narrow down a SQL exception to specific type of StoreException.<br>
- * For example, error code <code>"23000"</code> represents referential
- * integrity violation and hence can be narrowed down to
- * {@link ReferentialIntegrityException} rather than more general
- * {@link StoreException}.<br>
- * JDBC Drivers are not uniform in return values of SQLState for the same
- * error and hence each database specific Dictionary can specialize.<br>
- *
- *
- * @return an <em>unmodifiable</em> list of Strings representing supposedly
- * uniform SQL States for a given type of StoreException.
- * Default behavior is to return an empty list.
- */
- public List/*<String>*/ getSQLStates(int exceptionType) {
- if (exceptionType>=0 && exceptionType<SQL_STATE_CODES.length)
- return SQL_STATE_CODES[exceptionType];
- return EMPTY_STRING_LIST;
+ * Gets the subtype of StoreException by matching the given SQLException's
+ * error state code to the list of error codes supplied by the dictionary.
+ * Returns -1 if no matching code can be found.
+ */
+ OpenJPAException narrow(String msg, SQLException ex) {
+ String errorState = ex.getSQLState();
+ int errorType = StoreException.GENERAL;
+ for (Iterator iter = sqlStateCodes.keySet().iterator(); iter.hasNext(); ) {
+ Integer type = (Integer) iter.next();
+ Set erroStates = (Set) sqlStateCodes.get(type);
+ if (erroStates != null && erroStates.contains(errorState)) {
+ errorType = type.intValue();
+ break;
+ }
+ }
+ switch (errorType) {
+ case StoreException.LOCK:
+ return new LockException(msg);
+ case StoreException.OBJECT_EXISTS:
+ return new ObjectExistsException(msg);
+ case StoreException.OBJECT_NOT_FOUND:
+ return new ObjectNotFoundException(msg);
+ case StoreException.OPTIMISTIC:
+ return new OptimisticException(msg);
+ case StoreException.REFERENTIAL_INTEGRITY:
+ return new ReferentialIntegrityException(msg);
+ default:
+ return new StoreException(msg);
+ }
}
/**
Modified: openjpa/branches/0.9.7-r547073/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DerbyDictionary.java
URL: http://svn.apache.org/viewvc/openjpa/branches/0.9.7-r547073/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DerbyDictionary.java?rev=692601&r1=692600&r2=692601&view=diff
==============================================================================
--- openjpa/branches/0.9.7-r547073/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DerbyDictionary.java (original)
+++ openjpa/branches/0.9.7-r547073/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DerbyDictionary.java Fri Sep 5 18:27:31 2008
@@ -98,26 +98,4 @@
}
}
}
-
- /**
- * Adds extra SQLState code that Derby JDBC Driver uses. In JDBC 4.0,
- * SQLState will follow either XOPEN or SQL 2003 convention. A compliant
- * driver can be queries via DatabaseMetaData.getSQLStateType() to detect
- * the convention type.<br>
- * This method is overwritten to highlight that a) the SQL State is ideally
- * uniform across JDBC Drivers but not practically and b) the overwritten
- * method must crate a new list to return as the super classes list is
- * unmodifable.
- */
- public List getSQLStates(int exceptionType) {
- List original = super.getSQLStates(exceptionType);
- if (exceptionType == StoreException.LOCK) {
- // Can not add new codes to unmodifable list of the super class
- List newStates = new ArrayList(original);
- newStates.add("40XL1");
- return newStates;
- }
- return original;
- }
-
}
Copied: openjpa/branches/0.9.7-r547073/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLErrorCodeReader.java (from r668814, openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLErrorCodeReader.java)
URL: http://svn.apache.org/viewvc/openjpa/branches/0.9.7-r547073/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLErrorCodeReader.java?p2=openjpa/branches/0.9.7-r547073/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLErrorCodeReader.java&p1=openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLErrorCodeReader.java&r1=668814&r2=692601&rev=692601&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLErrorCodeReader.java (original)
+++ openjpa/branches/0.9.7-r547073/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLErrorCodeReader.java Fri Sep 5 18:27:31 2008
@@ -1,3 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
package org.apache.openjpa.jdbc.sql;
import java.io.IOException;
@@ -32,24 +50,25 @@
public class SQLErrorCodeReader {
private Log log = null;
public static final String ERROR_CODE_DELIMITER = ",";
- public static final Map<String, Integer> storeErrorTypes =
- new HashMap<String, Integer>();
+ public static final Map storeErrorTypes = new HashMap();
static {
- storeErrorTypes.put("lock", StoreException.LOCK);
- storeErrorTypes.put("object-exists", StoreException.OBJECT_EXISTS);
- storeErrorTypes
- .put("object-not-found", StoreException.OBJECT_NOT_FOUND);
- storeErrorTypes.put("optimistic", StoreException.OPTIMISTIC);
+ storeErrorTypes.put("lock", new Integer(StoreException.LOCK));
+ storeErrorTypes.put("object-exists",
+ new Integer(StoreException.OBJECT_EXISTS));
+ storeErrorTypes.put("object-not-found",
+ new Integer(StoreException.OBJECT_NOT_FOUND));
+ storeErrorTypes.put("optimistic",
+ new Integer(StoreException.OPTIMISTIC));
storeErrorTypes.put("referential-integrity",
- StoreException.REFERENTIAL_INTEGRITY);
+ new Integer(StoreException.REFERENTIAL_INTEGRITY));
}
private static final Localizer _loc =
Localizer.forPackage(SQLErrorCodeReader.class);
- public List<String> getDictionaries(InputStream in) {
- List<String> result = new ArrayList<String>();
+ public List getDictionaries(InputStream in) {
+ List result = new ArrayList();
DocumentBuilder builder = XMLFactory.getDOMParser(false, false);
try {
Document doc = builder.parse(in);
@@ -124,9 +143,10 @@
String errorCodes = child.getTextContent();
if (!StringUtils.isEmpty(errorCodes)) {
String[] codes = errorCodes.split(ERROR_CODE_DELIMITER);
- for (String code : codes) {
- dict.addErrorCode(storeErrorTypes.get(errorType),
- code.trim());
+ for (int k = 0; k < codes.length; k++ ) {
+ dict.addErrorCode(
+ (Integer) storeErrorTypes.get(errorType),
+ codes[k].trim());
}
}
}
Modified: openjpa/branches/0.9.7-r547073/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLExceptions.java
URL: http://svn.apache.org/viewvc/openjpa/branches/0.9.7-r547073/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLExceptions.java?rev=692601&r1=692600&r2=692601&view=diff
==============================================================================
--- openjpa/branches/0.9.7-r547073/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLExceptions.java (original)
+++ openjpa/branches/0.9.7-r547073/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLExceptions.java Fri Sep 5 18:27:31 2008
@@ -117,32 +117,4 @@
}
return (SQLException[]) errs.toArray(new SQLException[errs.size()]);
}
-
- /**
- * Narrows the given SQLException to a specific type of
- * {@link StoreException#getSubtype() StoreException} by analyzing the
- * SQLState code supplied by SQLException. Each database-specific
- * {@link DBDictionary dictionary} can supply a set of error codes that will
- * map to a specific specific type of StoreException via
- * {@link DBDictionary#getSQLStates(int) getSQLStates()} method.
- * The default behavior is to return generic {@link StoreException
- * StoreException}.
- */
- public static OpenJPAException narrow(String msg, SQLException se,
- DBDictionary dict) {
- String e = se.getSQLState();
- if (dict.getSQLStates(StoreException.LOCK).contains(e))
- return new LockException(msg);
- else if (dict.getSQLStates(StoreException.OBJECT_EXISTS).contains(e))
- return new ObjectExistsException(msg);
- else if (dict.getSQLStates(StoreException.OBJECT_NOT_FOUND).contains(e))
- return new ObjectNotFoundException(msg);
- else if (dict.getSQLStates(StoreException.OPTIMISTIC).contains(e))
- return new OptimisticException(msg);
- else if (dict.getSQLStates(StoreException.REFERENTIAL_INTEGRITY)
- .contains(e))
- return new ReferentialIntegrityException(msg);
- else
- return new StoreException(msg);
- }
}
Modified: openjpa/branches/0.9.7-r547073/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/exception/PObject.java
URL: http://svn.apache.org/viewvc/openjpa/branches/0.9.7-r547073/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/exception/PObject.java?rev=692601&r1=692600&r2=692601&view=diff
==============================================================================
--- openjpa/branches/0.9.7-r547073/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/exception/PObject.java (original)
+++ openjpa/branches/0.9.7-r547073/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/exception/PObject.java Fri Sep 5 18:27:31 2008
@@ -33,7 +33,6 @@
@Entity
public class PObject {
@Id
- @GeneratedValue
private long id;
private String name;
@Version
@@ -47,6 +46,10 @@
this.name = name;
}
+ public void setId(long id) {
+ this.id = id;
+ }
+
public long getId() {
return id;
}
Modified: openjpa/branches/0.9.7-r547073/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/exception/TestException.java
URL: http://svn.apache.org/viewvc/openjpa/branches/0.9.7-r547073/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/exception/TestException.java?rev=692601&r1=692600&r2=692601&view=diff
==============================================================================
--- openjpa/branches/0.9.7-r547073/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/exception/TestException.java (original)
+++ openjpa/branches/0.9.7-r547073/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/exception/TestException.java Fri Sep 5 18:27:31 2008
@@ -18,17 +18,32 @@
*/
package org.apache.openjpa.persistence.exception;
+import java.io.InputStream;
import java.sql.SQLException;
+import java.util.List;
+import javax.persistence.EntityExistsException;
import javax.persistence.EntityManager;
+import javax.persistence.EntityNotFoundException;
import javax.persistence.OptimisticLockException;
+import javax.persistence.TransactionRequiredException;
+
+import org.apache.openjpa.jdbc.sql.DBDictionary;
+import org.apache.openjpa.jdbc.sql.SQLErrorCodeReader;
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
/**
* Tests proper JPA exceptions are raised by the implementation.
+ * Actual runtime type of the raised exception is a subclass of JPA-defined
+ * exception.
+ * The raised exception may nest the expected exception.
+ *
+ * @author Pinaki Poddar
*/
public class TestException extends SingleEMFTestCase {
- public void setUp() {
+ private static long ID_COUNTER = System.currentTimeMillis();
+
+ public void setUp() {
super.setUp(PObject.class);
}
@@ -36,16 +51,17 @@
* Tests that when Optimistic transaction consistency is violated, the
* exception thrown is an instance of javax.persistence.OptimisticException.
*/
- public void testThrowsJPADefinedOptimisticException() {
+ public void testThrowsOptimisticException() {
EntityManager em1 = emf.createEntityManager();
EntityManager em2 = emf.createEntityManager();
assertNotEquals(em1, em2);
em1.getTransaction().begin();
PObject pc = new PObject();
+ long id = ++ID_COUNTER;
+ pc.setId(id);
em1.persist(pc);
em1.getTransaction().commit();
- Object id = pc.getId();
em1.clear();
em1.getTransaction().begin();
@@ -61,47 +77,121 @@
try {
pc2.setName("Modified in TXN2");
em2.flush();
- fail("Expected optimistic exception on flush");
+ fail("Expected " + OptimisticLockException.class);
} catch (Throwable t) {
- if (!isExpectedException(t, OptimisticLockException.class)) {
- print(t);
- fail(t.getCause().getClass() + " is not " +
- OptimisticLockException.class);
- }
+ assertException(t, OptimisticLockException.class);
}
em1.getTransaction().commit();
try {
em2.getTransaction().commit();
- fail("Expected optimistic exception on commit");
+ fail("Expected " + OptimisticLockException.class);
+ } catch (Throwable t) {
+ assertException(t, OptimisticLockException.class);
+ }
+ }
+
+ public void testThrowsEntityExistsException() {
+ EntityManager em = emf.createEntityManager();
+
+ em.getTransaction().begin();
+ PObject pc = new PObject();
+ long id = ++ID_COUNTER;
+ pc.setId(id);
+ em.persist(pc);
+ em.getTransaction().commit();
+ em.clear();
+
+ em.getTransaction().begin();
+ PObject pc2 = new PObject();
+ pc2.setId(id);
+ em.persist(pc2);
+ try {
+ em.getTransaction().commit();
+ fail("Expected " + EntityExistsException.class);
+ } catch (Throwable t) {
+ assertException(t, EntityExistsException.class);
+ }
+ }
+
+ public void testThrowsEntityNotFoundException() {
+ EntityManager em = emf.createEntityManager();
+
+ em.getTransaction().begin();
+ PObject pc = new PObject();
+ long id = ++ID_COUNTER;
+ pc.setId(id);
+ em.persist(pc);
+ em.getTransaction().commit();
+
+ EntityManager em2 = emf.createEntityManager();
+ em2.getTransaction().begin();
+ PObject pc2 = em2.find(PObject.class, id);
+ assertNotNull(pc2);
+ em2.remove(pc2);
+ em2.getTransaction().commit();
+
+ try {
+ em.refresh(pc);
+ fail("Expected " + EntityNotFoundException.class);
} catch (Throwable t) {
- if (!isExpectedException(t, OptimisticLockException.class)) {
- print(t);
- fail(t.getCause().getClass() + " is not " +
- OptimisticLockException.class);
+ assertException(t, EntityNotFoundException.class);
+ }
+ }
+
+ public void testErrorCodeConfigurationHasAllKnownDictionaries() {
+ SQLErrorCodeReader reader = new SQLErrorCodeReader();
+ InputStream in = DBDictionary.class.getResourceAsStream
+ ("sql-error-state-codes.xml");
+ assertNotNull(in);
+ List<String> names = reader.getDictionaries(in);
+ assertTrue(names.size()>=18);
+ for (String name:names) {
+ try {
+ Class.forName(name, false, Thread.currentThread()
+ .getContextClassLoader());
+ } catch (Throwable t) {
+ fail("DB dictionary " + name + " can not be loaded");
+ t.printStackTrace();
}
}
}
+ /**
+ * Asserts that the given expected type of the exception is equal to or a
+ * subclass of the given throwable or any of its nested exception.
+ * Otherwise fails assertion and prints the given throwable and its nested
+ * exception on the console.
+ */
+ void assertException(Throwable t, Class expectedType) {
+ if (!isExpectedException(t, expectedType)) {
+ t.printStackTrace();
+ print(t, 0);
+ fail(t + " or its cause is not instanceof " + expectedType);
+ }
+ }
+
+ /**
+ * Affirms if the given expected type of the exception is equal to or a
+ * subclass of the given throwable or any of its nested exception.
+ */
boolean isExpectedException(Throwable t, Class expectedType) {
- if (t == null) return false;
+ if (t == null)
+ return false;
if (expectedType.isAssignableFrom(t.getClass()))
return true;
- if (t.getCause()==t) return false;
return isExpectedException(t.getCause(), expectedType);
}
- void print(Throwable t) {
- print(t, 0);
- }
-
void print(Throwable t, int tab) {
if (t == null) return;
for (int i=0; i<tab*4;i++) System.out.print(" ");
String sqlState = (t instanceof SQLException) ?
- "(SQLState=" + ((SQLException)t).getSQLState() + ":" + t.getMessage() + ")":"";
+ "(SQLState=" + ((SQLException)t).getSQLState() + ":"
+ + t.getMessage() + ")" : "";
System.out.println(t.getClass().getName() + sqlState);
- if (t.getCause()==t) return;
+ if (t.getCause() == t)
+ return;
print(t.getCause(), tab+1);
}
}
Modified: openjpa/branches/0.9.7-r547073/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java
URL: http://svn.apache.org/viewvc/openjpa/branches/0.9.7-r547073/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java?rev=692601&r1=692600&r2=692601&view=diff
==============================================================================
--- openjpa/branches/0.9.7-r547073/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java (original)
+++ openjpa/branches/0.9.7-r547073/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java Fri Sep 5 18:27:31 2008
@@ -22,7 +22,10 @@
import org.apache.openjpa.kernel.Broker;
import org.apache.openjpa.util.Exceptions;
+import org.apache.openjpa.util.ObjectExistsException;
+import org.apache.openjpa.util.ObjectNotFoundException;
import org.apache.openjpa.util.OpenJPAException;
+import org.apache.openjpa.util.OptimisticException;
import org.apache.openjpa.util.RuntimeExceptionTranslator;
import org.apache.openjpa.util.StoreException;
import org.apache.openjpa.util.UserException;
@@ -64,7 +67,7 @@
try {
throwing = true;
if (em.isOpen() && em.isActive())
- em.setRollbackOnly(re);
+ em.setRollbackOnly(ex);
} finally {
// handle re-entrancy
throwing = false;
@@ -139,24 +142,26 @@
*/
private static Throwable translateStoreException(OpenJPAException ke) {
Exception e;
- switch (ke.getSubtype()) {
- case StoreException.OBJECT_NOT_FOUND:
+ Throwable cause = (ke.getNestedThrowables() != null
+ && ke.getNestedThrowables().length == 1)
+ ? ke.getNestedThrowables()[0] : null;
+ if (ke.getSubtype() == StoreException.OBJECT_NOT_FOUND
+ || cause instanceof ObjectNotFoundException) {
e = new org.apache.openjpa.persistence.EntityNotFoundException
(ke.getMessage(), getNestedThrowables(ke),
getFailedObject(ke), ke.isFatal());
- break;
- case StoreException.OPTIMISTIC:
- case StoreException.LOCK:
- e = new org.apache.openjpa.persistence.OptimisticLockException
+ } else if (ke.getSubtype() == StoreException.OPTIMISTIC
+ || ke.getSubtype() == StoreException.LOCK
+ || cause instanceof OptimisticException) {
+ e = new org.apache.openjpa.persistence.OptimisticLockException
(ke.getMessage(), getNestedThrowables(ke),
getFailedObject(ke), ke.isFatal());
- break;
- case StoreException.OBJECT_EXISTS:
+ } else if (ke.getSubtype() == StoreException.OBJECT_EXISTS
+ || cause instanceof ObjectExistsException) {
e = new org.apache.openjpa.persistence.EntityExistsException
(ke.getMessage(), getNestedThrowables(ke),
getFailedObject(ke), ke.isFatal());
- break;
- default:
+ } else {
e = new org.apache.openjpa.persistence.PersistenceException
(ke.getMessage(), getNestedThrowables(ke),
getFailedObject(ke), ke.isFatal());