5
0
mirror of https://github.com/apache/sqoop.git synced 2025-05-09 21:01:20 +08:00

SQOOP-1426: Sqoop2: ThrowableBean should correct reconstruct SqoopException

This commit is contained in:
Jarek Jarcec Cecho 2014-08-11 17:40:04 -07:00 committed by Abraham Elmahrek
parent cf448a2291
commit 199d342df7
3 changed files with 89 additions and 30 deletions

View File

@ -28,28 +28,37 @@
public class SqoopException extends RuntimeException {
private final ErrorCode code;
private final String originalMessage;
public SqoopException(ErrorCode code) {
super(code.getCode() + ":" + code.getMessage());
this.code = code;
originalMessage = null;
}
public SqoopException(ErrorCode code, String extraInfo) {
super(code.getCode() + ":" + code.getMessage() + " - " + extraInfo);
this.code = code;
originalMessage = extraInfo;
}
public SqoopException(ErrorCode code, Throwable cause) {
super(code.getCode() + ":" + code.getMessage(), cause);
this.code = code;
originalMessage = null;
}
public SqoopException(ErrorCode code, String extraInfo, Throwable cause) {
super(code.getCode() + ":" + code.getMessage() + " - " + extraInfo, cause);
this.code = code;
originalMessage = extraInfo;
}
public ErrorCode getErrorCode() {
return code;
}
public String getOriginalMessage() {
return originalMessage;
}
}

View File

@ -17,6 +17,7 @@
*/
package org.apache.sqoop.json;
import org.apache.sqoop.common.SqoopException;
import org.apache.sqoop.utils.ClassUtils;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
@ -36,6 +37,8 @@ public class ThrowableBean implements JsonBean {
public static final String FILE = "file";
public static final String LINE = "line";
public static final String CAUSE = "cause";
public static final String ERROR_CODE = "error-code";
public static final String ERROR_CODE_CLASS = "error-code-class";
private Throwable throwable;
@ -60,6 +63,14 @@ public JSONObject extract(boolean skipSensitive) {
result.put(MESSAGE, throwable.getMessage());
result.put(CLASS, throwable.getClass().getName());
if(throwable instanceof SqoopException ) {
SqoopException sqoopException = (SqoopException) throwable;
result.put(ERROR_CODE, sqoopException.getErrorCode().getCode());
result.put(ERROR_CODE_CLASS, sqoopException.getErrorCode().getClass().getName());
// Override message with the original message
result.put(MESSAGE, sqoopException.getOriginalMessage());
}
JSONArray st = new JSONArray();
for(StackTraceElement element : throwable.getStackTrace()) {
JSONObject obj = new JSONObject();
@ -91,11 +102,25 @@ public void restore(JSONObject jsonObject) {
message = "";
}
// Let's firstly try to instantiate same class that was originally on remote
// side. Fallback to generic Throwable in case that this particular
// exception is not known to this JVM (for example during server-client
// exchange).
throwable = (Throwable) ClassUtils.instantiate(exceptionClass, message);
// Special handling for SqoopException as we need to transfer ERROR_CODE from the other side
if(jsonObject.containsKey(ERROR_CODE_CLASS)) {
Class e = ClassUtils.loadClass((String) jsonObject.get(ERROR_CODE_CLASS));
// Only if the error code class is known to this JVM, let's instantiate the real SqoopException
if( e != null) {
String errorCode = (String) jsonObject.get(ERROR_CODE);
Enum enumValue = Enum.valueOf(e, errorCode);
throwable = (Throwable) ClassUtils.instantiate(exceptionClass, enumValue, message);
}
}
// Let's try to instantiate same class that was originally on remote side.
if(throwable == null) {
throwable = (Throwable) ClassUtils.instantiate(exceptionClass, message);
}
// Fallback to generic Throwable in case that this particular exception is not known
// to this JVM (for example during server-client exchange).
if(throwable == null) {
throwable = new Throwable(message);
}

View File

@ -17,35 +17,60 @@
*/
package org.apache.sqoop.json;
import junit.framework.TestCase;
import org.apache.sqoop.common.SqoopException;
import org.apache.sqoop.json.util.SerializationError;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
/**
*
*/
public class TestThrowableBean extends TestCase {
// public void testSerialization() {
// Throwable ex = new RuntimeException("A");
// ex.initCause(new Exception("B"));
//
// // Serialize it to JSON object
// ThrowableBean bean = new ThrowableBean(ex);
// JSONObject json = bean.extract(false);
//
// // "Move" it across network in text form
// String string = json.toJSONString();
//
// // Retrieved transferred object
// JSONObject retrievedJson = (JSONObject) JSONValue.parse(string);
// ThrowableBean retrievedBean = new ThrowableBean();
// retrievedBean.restore(retrievedJson);
// Throwable retrieved = retrievedBean.getThrowable();
//
// assertEquals("A", retrieved.getMessage());
// assertEquals(RuntimeException.class, retrieved.getClass());
// assertEquals("B", retrieved.getCause().getMessage());
// assertEquals(Exception.class, retrieved.getCause().getClass());
// assertNull(retrieved.getCause().getCause());
// }
public class TestThrowableBean {
@Test
public void testSerialization() {
Throwable ex = new RuntimeException("A");
ex.initCause(new Exception("B"));
Throwable retrieved = transfer(ex);
assertEquals("A", retrieved.getMessage());
assertEquals(RuntimeException.class, retrieved.getClass());
assertEquals("B", retrieved.getCause().getMessage());
assertEquals(Exception.class, retrieved.getCause().getClass());
assertNull(retrieved.getCause().getCause());
}
@Test
public void testSqoopException() {
SqoopException ex = new SqoopException(SerializationError.SERIALIZATION_001, "Secret");
Throwable retrieved = transfer(ex);
assertNotNull(retrieved);
assertEquals(SqoopException.class, retrieved.getClass());
SqoopException sqoopRetrieved = (SqoopException) retrieved;
assertEquals(SerializationError.class, sqoopRetrieved.getErrorCode().getClass());
assertEquals(SerializationError.SERIALIZATION_001, sqoopRetrieved.getErrorCode());
assertEquals("SERIALIZATION_001:Attempt to pass a non-map object to MAP type. - Secret", sqoopRetrieved.getMessage());
}
public Throwable transfer(Throwable source) {
// Serialize it to JSON object
ThrowableBean bean = new ThrowableBean(source);
JSONObject json = bean.extract(false);
// "Move" it across network in text form
String string = json.toJSONString();
// Retrieved transferred object
JSONObject retrievedJson = (JSONObject) JSONValue.parse(string);
ThrowableBean retrievedBean = new ThrowableBean();
retrievedBean.restore(retrievedJson);
return retrievedBean.getThrowable();
}
}