From 01ae9ac56e87c0f48d1cc48b6f5c8ebf353782c1 Mon Sep 17 00:00:00 2001 From: Aron Roberts Date: Thu, 29 Nov 2012 18:23:47 -0800 Subject: [PATCH] CSPACE-5506: Return a new Exception message and corresponding custom HTTP status code if a Nuxeo transaction times out or otherwise fails. Some of these Exceptions may result in transaction rollbacks, and can more generally leave data involved in the transaction in an unexpected state. --- .../AbstractCollectionSpaceResourceImpl.java | 6 ++ .../common/document/TransactionException.java | 87 +++++++++++++++++++ .../nuxeo/client/java/DocHandlerBase.java | 2 +- .../client/java/DocumentModelHandler.java | 2 +- .../java/RemoteDocumentModelHandlerImpl.java | 2 +- .../client/java/RepositoryJavaClientImpl.java | 81 ++++++++++++----- 6 files changed, 154 insertions(+), 26 deletions(-) create mode 100644 services/common/src/main/java/org/collectionspace/services/common/document/TransactionException.java diff --git a/services/common/src/main/java/org/collectionspace/services/common/AbstractCollectionSpaceResourceImpl.java b/services/common/src/main/java/org/collectionspace/services/common/AbstractCollectionSpaceResourceImpl.java index d7d533585..c85a1b8bb 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/AbstractCollectionSpaceResourceImpl.java +++ b/services/common/src/main/java/org/collectionspace/services/common/AbstractCollectionSpaceResourceImpl.java @@ -40,6 +40,7 @@ import org.collectionspace.services.common.document.BadRequestException; import org.collectionspace.services.common.document.DocumentException; import org.collectionspace.services.common.document.DocumentHandler; import org.collectionspace.services.common.document.DocumentNotFoundException; +import org.collectionspace.services.common.document.TransactionException; import org.collectionspace.services.common.repository.RepositoryClient; import org.collectionspace.services.common.repository.RepositoryClientFactory; import org.collectionspace.services.common.security.UnauthorizedException; @@ -448,6 +449,11 @@ public abstract class AbstractCollectionSpaceResourceImpl logException = false; response = Response.status(Response.Status.NOT_FOUND).entity(serviceMsg + " on " + getClass().getName() + " csid=" + csid).type("text/plain").build(); result = new WebApplicationException(response); + + } else if (e instanceof TransactionException) { + int code = ((TransactionException) e).getErrorCode(); + response = Response.status(code).entity(e.getMessage()).type("text/plain").build(); + result = new WebApplicationException(response); } else if (e instanceof BadRequestException) { int code = ((BadRequestException) e).getErrorCode(); diff --git a/services/common/src/main/java/org/collectionspace/services/common/document/TransactionException.java b/services/common/src/main/java/org/collectionspace/services/common/document/TransactionException.java new file mode 100644 index 000000000..2f49eb0af --- /dev/null +++ b/services/common/src/main/java/org/collectionspace/services/common/document/TransactionException.java @@ -0,0 +1,87 @@ +/** + * This document is a part of the source code and related artifacts + * for CollectionSpace, an open source collections management system + * for museums and related institutions: + + * http://www.collectionspace.org + * http://wiki.collectionspace.org + + * Copyright 2009 University of California at Berkeley + + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + + * You may obtain a copy of the ECL 2.0 License at + + * https://source.collectionspace.org/collection-space/LICENSE.txt + */ +package org.collectionspace.services.common.document; + +/** + * TransactionException + * + */ +public class TransactionException extends DocumentException { + + // Custom HTTP status code, per the extensibility offered via RFC-2616 + // e.g. http://tools.ietf.org/html/rfc2616#section-6.1.1 + final public static int HTTP_CODE = 590; + + final static String TRANSACTION_FAILED_MSG = + "A transaction failed, whether due to exceeding a timeout value or some other cause. Please contact your system administrator."; + + /** + * Creates a new instance of TransactionException without detail message. + */ + public TransactionException() { + super(TRANSACTION_FAILED_MSG); + setErrorCode(HTTP_CODE); + } + + /** + * Constructs an instance of TransactionException with the specified detail message. + * @param msg the detail message. + */ + public TransactionException(String msg) { + super(msg); + setErrorCode(HTTP_CODE); + } + + /** + * Constructs a new exception with the specified detail message and + * cause.

Note that the detail message associated with + * cause is not automatically incorporated in + * this exception's detail message. + * + * @param message the detail message (which is saved for later retrieval + * by the {@link #getMessage()} method). + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A null value is + * permitted, and indicates that the cause is nonexistent or + * unknown.) + * @since 1.4 + */ + public TransactionException(String message, Throwable cause) { + super(message, cause); + setErrorCode(HTTP_CODE); + } + + /** + * Constructs a new exception with the specified cause and a detail + * message of (cause==null ? null : cause.toString()) (which + * typically contains the class and detail message of cause). + * This constructor is useful for exceptions that are little more than + * wrappers for other throwables (for example, {@link + * java.security.PrivilegedActionException}). + * + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A null value is + * permitted, and indicates that the cause is nonexistent or + * unknown.) + * @since 1.4 + */ + public TransactionException(Throwable cause) { + super(TRANSACTION_FAILED_MSG, cause); + setErrorCode(HTTP_CODE); + } +} diff --git a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/DocHandlerBase.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/DocHandlerBase.java index 1064fa4a8..175c209b3 100644 --- a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/DocHandlerBase.java +++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/DocHandlerBase.java @@ -278,7 +278,7 @@ public abstract class DocHandlerBase extends RemoteDocumentModelHandlerImpl * @throws PropertyException the property exception */ abstract public AuthorityRefList getAuthorityRefs(String csid, - List authRefsInfo) throws PropertyException; + List authRefsInfo) throws PropertyException, Exception; /* * Subclasses should override this method if they need to customize their refname generation diff --git a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RemoteDocumentModelHandlerImpl.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RemoteDocumentModelHandlerImpl.java index 7fd63f622..a3416934a 100644 --- a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RemoteDocumentModelHandlerImpl.java +++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RemoteDocumentModelHandlerImpl.java @@ -592,7 +592,7 @@ public abstract class RemoteDocumentModelHandlerImpl @Override public AuthorityRefList getAuthorityRefs( String csid, - List authRefsInfo) throws PropertyException { + List authRefsInfo) throws PropertyException, Exception { AuthorityRefList authRefList = new AuthorityRefList(); AbstractCommonList commonList = (AbstractCommonList) authRefList; diff --git a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java index 154c429a5..628bf3213 100644 --- a/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java +++ b/services/common/src/main/java/org/collectionspace/services/nuxeo/client/java/RepositoryJavaClientImpl.java @@ -47,6 +47,7 @@ import org.collectionspace.services.common.document.DocumentNotFoundException; import org.collectionspace.services.common.document.DocumentHandler.Action; import org.collectionspace.services.common.document.DocumentWrapper; import org.collectionspace.services.common.document.DocumentWrapperImpl; +import org.collectionspace.services.common.document.TransactionException; import org.nuxeo.common.utils.IdUtils; import org.nuxeo.ecm.core.api.ClientException; @@ -59,6 +60,7 @@ import org.nuxeo.ecm.core.api.DocumentRef; import org.nuxeo.ecm.core.api.IdRef; import org.nuxeo.ecm.core.api.PathRef; import org.nuxeo.ecm.core.api.repository.RepositoryInstance; +import org.nuxeo.runtime.transaction.TransactionRuntimeException; // // CSPACE-5036 - How to make CMISQL queries from Nuxeo @@ -129,12 +131,14 @@ public class RepositoryJavaClientImpl implements RepositoryClient getDoc( ServiceContext ctx, - String csid) throws DocumentNotFoundException, DocumentException { + String csid) throws DocumentNotFoundException, TransactionException, DocumentException { RepositoryInstance repoSession = null; DocumentWrapper wrapDoc = null; @@ -411,13 +422,16 @@ public class RepositoryJavaClientImpl implements RepositoryClient findDoc( ServiceContext ctx, String whereClause) - throws DocumentNotFoundException, DocumentException { + throws DocumentNotFoundException, TransactionException, DocumentException { RepositoryInstance repoSession = null; DocumentWrapper wrapDoc = null; @@ -441,14 +455,18 @@ public class RepositoryJavaClientImpl implements RepositoryClient ctx, String whereClause) - throws DocumentNotFoundException, DocumentException { + throws DocumentNotFoundException, TransactionException, DocumentException { String csid = null; boolean releaseSession = false; try { @@ -584,7 +602,10 @@ public class RepositoryJavaClientImpl implements RepositoryClient findDocs( @@ -592,7 +613,7 @@ public class RepositoryJavaClientImpl implements RepositoryClient docTypes, String whereClause, int pageSize, int pageNum, boolean computeTotal) - throws DocumentNotFoundException, DocumentException { + throws DocumentNotFoundException, TransactionException, DocumentException { RepositoryInstance repoSession = null; DocumentWrapper wrapDoc = null; @@ -625,7 +646,7 @@ public class RepositoryJavaClientImpl implements RepositoryClient csidList, DocumentHandler handler) - throws DocumentNotFoundException, DocumentException { + throws DocumentNotFoundException, TransactionException, DocumentException { if (handler == null) { throw new IllegalArgumentException( "RepositoryJavaClient.getAll: handler is missing"); @@ -670,11 +691,13 @@ public class RepositoryJavaClientImpl implements RepositoryClient wrappedDoc) throws ClientException { @@ -812,11 +835,12 @@ public class RepositoryJavaClientImpl implements RepositoryClient