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:
parent
cf448a2291
commit
199d342df7
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user