org.eclipse.persistence.jpa.rs.exceptions.AbstractExceptionMapper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of eclipselink Show documentation
Show all versions of eclipselink Show documentation
EclipseLink build based upon Git transaction 346465e
/*******************************************************************************
* Copyright (c) 2013, 2014 Oracle. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* gonural - initial implementation
******************************************************************************/
package org.eclipse.persistence.jpa.rs.exceptions;
import org.eclipse.persistence.exceptions.ConversionException;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.jaxb.JAXBContext;
import org.eclipse.persistence.jaxb.JAXBContextFactory;
import org.eclipse.persistence.jaxb.MarshallerProperties;
import org.eclipse.persistence.jpa.rs.DataStorage;
import org.eclipse.persistence.jpa.rs.features.ServiceVersion;
import org.eclipse.persistence.jpa.rs.util.JPARSLogger;
import org.eclipse.persistence.jpa.rs.util.StreamingOutputMarshaller;
import javax.naming.NamingException;
import javax.persistence.EntityExistsException;
import javax.persistence.EntityNotFoundException;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.OptimisticLockException;
import javax.persistence.PersistenceException;
import javax.persistence.PessimisticLockException;
import javax.persistence.QueryTimeoutException;
import javax.persistence.RollbackException;
import javax.persistence.TransactionRequiredException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import java.io.IOException;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URI;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public abstract class AbstractExceptionMapper {
@Context
private HttpHeaders headers;
@Context
UriInfo uriInfo;
private static final Map HTTP_STATUS_CODE_MAPPING =
Collections.unmodifiableMap(new HashMap() {
{
put(ClassNotFoundException.class.getName(), Status.BAD_REQUEST);
put(ConversionException.class.getName(), Status.BAD_REQUEST);
put(DatabaseException.class.getName(), Status.INTERNAL_SERVER_ERROR);
put(EntityExistsException.class.getName(), Status.CONFLICT);
put(EntityNotFoundException.class.getName(), Status.NOT_FOUND);
put(IOException.class.getName(), Status.BAD_REQUEST);
put(IllegalAccessException.class.getName(), Status.BAD_REQUEST);
put(IllegalArgumentException.class.getName(), Status.BAD_REQUEST);
put(IllegalStateException.class.getName(), Status.BAD_REQUEST);
put(InvocationTargetException.class.getName(), Status.INTERNAL_SERVER_ERROR);
put(JAXBException.class.getName(), Status.NOT_FOUND); // TODO: we might want to change this http status in v2.0
put(MalformedURLException.class.getName(), Status.BAD_REQUEST);
put(NamingException.class.getName(), Status.BAD_REQUEST);
put(NoResultException.class.getName(), Status.NOT_FOUND);
put(NoSuchMethodException.class.getName(), Status.BAD_REQUEST);
put(NonUniqueResultException.class.getName(), Status.NOT_FOUND);
put(NumberFormatException.class.getName(), Status.BAD_REQUEST);
put(OptimisticLockException.class.getName(), Status.INTERNAL_SERVER_ERROR);
put(PersistenceException.class.getName(), Status.INTERNAL_SERVER_ERROR);
put(PessimisticLockException.class.getName(), Status.INTERNAL_SERVER_ERROR);
put(QueryTimeoutException.class.getName(), Status.BAD_REQUEST);// TODO: we might want to change this http status in v2.0
put(RollbackException.class.getName(), Status.BAD_REQUEST);
put(TransactionRequiredException.class.getName(), Status.INTERNAL_SERVER_ERROR);
}
});
// An absolute URI that identifies the problem type. When dereferenced, it SHOULD provide human-readable documentation for the problem type (e.g., using HTML)."
private static final String PROBLEM_TYPE = "http://www.eclipse.org/eclipselink/documentation/";
protected Response buildResponse(JPARSException exception) {
String path = null;
exception.setHttpStatusCode(getHttpStatusCode(exception.getCause()));
if (uriInfo != null) {
URI requestURI = uriInfo.getRequestUri();
if (requestURI != null) {
path = requestURI.getPath();
}
}
if ((path != null) && (path.contains(ServiceVersion.VERSION_2_0.getCode()) || path.contains(ServiceVersion.LATEST.getCode()))) {
ErrorResponse errorResponse = new ErrorResponse(PROBLEM_TYPE, exception.getMessage(), String.valueOf(exception.getErrorCode()));
errorResponse.setRequestId((String) DataStorage.get(DataStorage.REQUEST_ID));
errorResponse.setHttpStatus(exception.getHttpStatusCode().getStatusCode());
String error = marshallErrorResponse(errorResponse, StreamingOutputMarshaller.getResponseMediaType(headers).toString());
if (error != null) {
return Response.status(exception.getHttpStatusCode()).entity(error).type(StreamingOutputMarshaller.getResponseMediaType(headers)).build();
}
}
return Response.status(exception.getHttpStatusCode()).type(StreamingOutputMarshaller.getResponseMediaType(headers)).build();
}
private static Status getHttpStatusCode(Throwable throwable) {
if (throwable != null) {
Status httpStatusCode = HTTP_STATUS_CODE_MAPPING.get(throwable.getClass().getName());
if (throwable instanceof RollbackException) {
Throwable cause = throwable.getCause();
if (cause != null) {
if (cause instanceof DatabaseException) {
// 409 Conflict ("The request could not be completed due to a conflict with the current state of the resource.")
httpStatusCode = Status.CONFLICT;
}
}
}
if (httpStatusCode != null) {
return httpStatusCode;
}
}
return Status.BAD_REQUEST;
}
private String marshallErrorResponse(ErrorResponse errorResponse, String mediaType) {
try {
JAXBContext context = (JAXBContext) JAXBContextFactory.createContext(new Class[] { ErrorResponse.class }, null);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, mediaType);
marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, Boolean.FALSE);
marshaller.setProperty(MarshallerProperties.JSON_REDUCE_ANY_ARRAYS, true);
StringWriter writer = new StringWriter();
marshaller.marshal(errorResponse, writer);
return writer.toString();
} catch (Exception ex) {
JPARSLogger.exception(ex.getMessage(), null, ex);
}
return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy