Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(kernel): distinguish framework errors from userland errors in Java #3747

Merged
merged 27 commits into from
Sep 21, 2022
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
5586bbc
framework errors
comcalvi Sep 1, 2022
db512f8
tmp
comcalvi Sep 7, 2022
d8510a7
playback tests pass
comcalvi Sep 8, 2022
770c120
remove comment
comcalvi Sep 8, 2022
8b81f62
js exception added
comcalvi Sep 9, 2022
3c0dc76
rename
comcalvi Sep 12, 2022
3ed3b27
rename JsiiE
comcalvi Sep 12, 2022
d6975d8
need to ensure that JsErrors are thrown correctly, the writeError() m…
comcalvi Sep 12, 2022
6ed003b
playback fix
comcalvi Sep 13, 2022
428c95e
force js error from kernel host...pretty sure this is the wrong appro…
comcalvi Sep 13, 2022
8dbb87f
working userland errors
comcalvi Sep 13, 2022
3486573
remove old commment
comcalvi Sep 13, 2022
42a4f31
remove commented code
comcalvi Sep 13, 2022
a32e01d
test fix
comcalvi Sep 14, 2022
f116ddb
removed old comment
comcalvi Sep 14, 2022
feecb62
updated expected exception type to JsiiException
comcalvi Sep 14, 2022
da967df
updated type to name
comcalvi Sep 14, 2022
855085d
updated comment
comcalvi Sep 15, 2022
53aa68d
updated comment
comcalvi Sep 15, 2022
3fc61f8
final comment update
comcalvi Sep 15, 2022
dc7562c
rename JsError to JSError
comcalvi Sep 15, 2022
fb8a93f
have to delete the file to change the capitalization...why????
comcalvi Sep 15, 2022
a468d90
final rename
comcalvi Sep 15, 2022
373cae2
Made JsiiException the base error class in Java. JsiiError now repres…
comcalvi Sep 19, 2022
636516d
comment update
comcalvi Sep 19, 2022
fa5398e
review comments
comcalvi Sep 20, 2022
823b1ba
Merge branch 'main' into frameworkerrors
mergify[bot] Sep 21, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ public void exceptions() {
assertEquals(23, calc3.getValue());
boolean thrown = false;
try { calc3.add(10); }
catch (Exception e) { thrown = true; }
catch (RuntimeException e) { thrown = true; }
assertTrue(thrown);
calc3.setMaxValue(40);
calc3.add(10);
Expand Down Expand Up @@ -449,7 +449,7 @@ public java.lang.Number overrideMe(java.lang.Number mult) {
boolean thrown = false;
try {
obj.callMe();
} catch (JsiiException e) {
} catch (RuntimeException e) {
assertTrue(e.getMessage().contains( "Thrown by native code"));
thrown = true;
}
Expand Down Expand Up @@ -518,7 +518,7 @@ public String getTheProperty() {
boolean thrown = false;
try {
so.retrieveValueOfTheProperty();
} catch (Exception e) {
} catch (RuntimeException e) {
assertTrue(e.getMessage().contains("Oh no, this is bad"));
thrown = true;
}
Expand All @@ -536,7 +536,7 @@ public void setTheProperty(String value) {
boolean thrown = false;
try {
so.modifyValueOfTheProperty("Hii");
} catch (Exception e) {
} catch (RuntimeException e) {
assertTrue(e.getMessage().contains("Exception from overloaded setter"));
thrown = true;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/@jsii/java-runtime/BundledRuntime.t.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ ${resources.map(extractResource).map(indent(12)).join('\n')}

return entrypoint.toString();
} catch (final IOException ioe) {
throw new JsiiException("Unable to extract bundled @jsii/runtime library", ioe);
throw new JsiiError("Unable to extract bundled @jsii/runtime library", ioe);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public void loadModule(final JsiiModule module) {
Files.delete(tarball.getParent());
}
} catch (IOException e) {
throw new JsiiException("Unable to extract resource " + module.getBundleResourceName(), e);
throw new JsiiError("Unable to extract resource " + module.getBundleResourceName(), e);
}
}

Expand Down Expand Up @@ -226,7 +226,7 @@ public List<Callback> pendingCallbacks() {

JsonNode callbacksResp = resp.get("callbacks");
if (callbacksResp == null || !callbacksResp.isArray()) {
throw new JsiiException("Expecting a 'callbacks' key with an array in response");
throw new JsiiError("Expecting a 'callbacks' key with an array in response");
}

ArrayNode callbacksArray = (ArrayNode) callbacksResp;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ private JsiiEngine() {
*/
public void loadModule(final Class<? extends JsiiModule> moduleClass) {
if (!JsiiModule.class.isAssignableFrom(moduleClass)) {
throw new JsiiException("Invalid module class "
throw new JsiiError("Invalid module class "
+ moduleClass.getName()
+ ". It must be derived from JsiiModule");
}
Expand All @@ -173,7 +173,7 @@ public void loadModule(final Class<? extends JsiiModule> moduleClass) {
try {
module = moduleClass.getConstructor().newInstance();
} catch (IllegalAccessException | InstantiationException | InvocationTargetException | NoSuchMethodException e) {
throw new JsiiException(e);
throw new JsiiError(e);
}

if (this.loadedModules.containsKey(module.getModuleName())) {
Expand Down Expand Up @@ -270,12 +270,12 @@ public JsiiObjectRef nativeToObjRef(final Object nativeObject) {
*
* @param objRef The object reference
* @return a JsiiObject
* @throws JsiiException If the object is not found.
* @throws JsiiError If the object is not found.
*/
public Object getObject(final JsiiObjectRef objRef) {
Object obj = this.objects.get(objRef.getObjId());
if (obj == null) {
throw new JsiiException("Cannot find jsii object: " + objRef.getObjId());
throw new JsiiError("Cannot find jsii object: " + objRef.getObjId());
}
return obj;
}
Expand Down Expand Up @@ -303,24 +303,24 @@ Class<?> resolveJavaClass(final String fqn) {
}
String[] parts = fqn.split("\\.");
if (parts.length < 2) {
throw new JsiiException("Malformed FQN: " + fqn);
throw new JsiiError("Malformed FQN: " + fqn);
}

String moduleName = parts[0];

JsonNode names = this.getClient().getModuleNames(moduleName);
if (!names.has("java")) {
throw new JsiiException("No java name for module " + moduleName);
throw new JsiiError("No java name for module " + moduleName);
}

final JsiiModule module = this.loadedModules.get(moduleName);
if (module == null) {
throw new JsiiException("No loaded module is named " + moduleName);
throw new JsiiError("No loaded module is named " + moduleName);
}
try {
return module.resolveClass(fqn);
} catch (final ClassNotFoundException cfne) {
throw new JsiiException(cfne);
throw new JsiiError(cfne);
}
}

Expand All @@ -346,12 +346,12 @@ private JsiiObject createNativeProxy(final String fqn, final JsiiObjectRef objRe
ctor.setAccessible(false);
return newObj;
} catch (NoSuchMethodException e) {
throw new JsiiException("Cannot create native object of type "
throw new JsiiError("Cannot create native object of type "
+ klass.getName()
+ " without a constructor that accepts an InitializationMode argument", e);

} catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
throw new JsiiException("Unable to instantiate a new object for FQN " + fqn + ": "
throw new JsiiError("Unable to instantiate a new object for FQN " + fqn + ": "
+ e.getMessage(), e);
}
} catch (ClassNotFoundException e) {
Expand All @@ -369,7 +369,7 @@ private JsiiObject createNativeProxy(final String fqn, final JsiiObjectRef objRe
public Enum<?> findEnumValue(final String enumRef) {
int sep = enumRef.lastIndexOf('/');
if (sep == -1) {
throw new JsiiException("Malformed enum reference: " + enumRef);
throw new JsiiError("Malformed enum reference: " + enumRef);
}

String typeName = enumRef.substring(0, sep);
Expand All @@ -396,7 +396,7 @@ public void processAllPendingCallbacks() {
* Invokes a local callback and returns the result/error.
* @param callback The callback to invoke.
* @return The return value
* @throws JsiiException if the callback failed.
* @throws JsiiError if the callback failed.
*/
public JsonNode handleCallback(final Callback callback) {

Expand All @@ -408,7 +408,7 @@ public JsonNode handleCallback(final Callback callback) {
return invokeCallbackSet(callback.getSet());
}

throw new JsiiException("Unrecognized callback type: get/set/invoke");
throw new JsiiError("Unrecognized callback type: get/set/invoke");
}

/**
Expand Down Expand Up @@ -486,9 +486,9 @@ private Object invokeMethod(final Object obj, final Method method, final Object.
throw e;
}
} catch (InvocationTargetException e) {
throw new JsiiException(e.getTargetException());
throw new JsiiError(e.getTargetException());
} catch (IllegalAccessException e) {
throw new JsiiException(e);
throw new JsiiError(e);
} finally {
// revert accessibility.
method.setAccessible(accessibility);
Expand All @@ -503,7 +503,7 @@ private void processCallback(final Callback callback) {
try {
JsonNode result = handleCallback(callback);
this.getClient().completeCallback(callback, null, result);
} catch (JsiiException e) {
} catch (JsiiError e) {
this.getClient().completeCallback(callback, e.getMessage(), null);
}
}
Expand All @@ -528,15 +528,15 @@ private Method findCallbackMethod(final Class<?> klass, final String signature)
return findCallbackMethod(klass.getSuperclass(), signature);
}

throw new JsiiException("Unable to find callback method with signature: " + signature);
throw new JsiiError("Unable to find callback method with signature: " + signature);
}

/**
* Tries to locate the getter method for a property
* @param klass is the type on which the getter is to be searched for
* @param methodName is the name of the getter method
* @return the found Method
* @throws JsiiException if no such method is found
* @throws JsiiError if no such method is found
*/
private Method findCallbackGetter(final Class<?> klass, final String methodName) {
try {
Expand All @@ -549,7 +549,7 @@ private Method findCallbackGetter(final Class<?> klass, final String methodName)
// Ignored!
}
}
throw new JsiiException(nsme);
throw new JsiiError(nsme);
}
}

Expand All @@ -559,7 +559,7 @@ private Method findCallbackGetter(final Class<?> klass, final String methodName)
* @param methodName is the name of the setter method
* @param valueType is the type of the argument the setter accepts
* @return the found Method
* @throws JsiiException if no such method is found
* @throws JsiiError if no such method is found
*/
private Method findCallbackSetter(final Class<?> klass, final String methodName, final Class<?> valueType) {
try {
Expand All @@ -572,7 +572,7 @@ private Method findCallbackSetter(final Class<?> klass, final String methodName,
// Ignored!
}
}
throw new JsiiException(nsme);
throw new JsiiError(nsme);
}
}

Expand Down Expand Up @@ -731,7 +731,7 @@ static Jsii tryGetJsiiAnnotation(final Class<?> type, final boolean inherited) {
String loadModuleForClass(Class<?> nativeClass) {
final Jsii jsii = tryGetJsiiAnnotation(nativeClass, true);
if (jsii == null) {
throw new JsiiException("Unable to find @Jsii annotation for class");
throw new JsiiError("Unable to find @Jsii annotation for class");
}

this.loadModule(jsii.module());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package software.amazon.jsii;

/**
* A nonrecoverable error from the jsii runtime,
* usually the kernel.
*/
public class JsiiError extends JsiiException {
/**
* Creates an exception.
* @param message The error message
*/
JsiiError(final String message) {
super(message);
}

/**
* Creates an exception.
* @param e The error that caused this exception
*/
JsiiError(final Throwable e) {
super(e);
}

/**
* Creates an exception.
* @param message The error message
* @param e The error that caused this exception
*/
JsiiError(final String message, final Throwable e) {
super(message, e);
}
}
Original file line number Diff line number Diff line change
@@ -1,33 +1,48 @@
package software.amazon.jsii;

/**
/*
* An error raised by the jsii runtime.
*/
public final class JsiiException extends RuntimeException {
public abstract class JsiiException extends RuntimeException {
public static final long serialVersionUID = 1L;

/**
* Creates an exception.
* @param message The error message
*/
JsiiException(final String message) {
super(message);
}
public static enum Type {
JSII_FAULT("@jsii/kernel.Fault"),
RUNTIME_EXCEPTION("@jsii/kernel.RuntimeException");

/**
* Creates an exception.
* @param e The error that caused this exception
*/
JsiiException(final Throwable e) {
super(e);
}
private final String errorType;

Type(String str) {
this.errorType = str;
}

/**
* Creates an exception.
* @param message The error message
* @param e The error that caused this exception
*/
JsiiException(final String message, final Throwable e) {
super(message, e);
public String toString() {
return this.errorType;
}
}

/**
* Creates an exception.
* @param message The error message
*/
JsiiException(final String message) {
super(message);
}

/**
* Creates an exception.
* @param e The error that caused this exception
*/
JsiiException(final Throwable e) {
super(e);
}

/**
* Creates an exception.
* @param message The error message
* @param e The error that caused this exception
*/
JsiiException(final String message, final Throwable e) {
super(message, e);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ protected JsiiObject(final InitializationMode initializationMode) {
JsiiObject(@Nullable final JsiiEngine engine, final InitializationMode initializationMode) {
this.jsii$engine = JsiiEngine.getEngineFor(this, engine);
if (initializationMode != InitializationMode.JSII) {
throw new JsiiException("The only supported initialization mode is '" + InitializationMode.JSII + "'");
throw new JsiiError("The only supported initialization mode is '" + InitializationMode.JSII + "'");
}
}

Expand Down Expand Up @@ -380,11 +380,11 @@ final <T extends JsiiObject> T asInterfaceProxy(final Class<? extends T> proxyCl
constructor.setAccessible(oldAccessible);
}
} catch(final NoSuchMethodException nsme) {
throw new JsiiException("Unable to find interface proxy constructor on " + proxyClass.getCanonicalName(), nsme);
throw new JsiiError("Unable to find interface proxy constructor on " + proxyClass.getCanonicalName(), nsme);
} catch (final InvocationTargetException | InstantiationException e) {
throw new JsiiException("Unable to initialize interface proxy " + proxyClass.getCanonicalName(), e);
throw new JsiiError("Unable to initialize interface proxy " + proxyClass.getCanonicalName(), e);
} catch (final IllegalAccessException iae) {
throw new JsiiException("Unable to invoke constructor of " + proxyClass.getCanonicalName(), iae);
throw new JsiiError("Unable to invoke constructor of " + proxyClass.getCanonicalName(), iae);
}
}
@SuppressWarnings("unchecked")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public final class JsiiObjectMapper {

/**
* Similar to calling JsiiObjectMapper.INSTANCE.treeToValue, but handles a null JsonNode argument
* well, and throws JsiiException instead of JsonProcessingException.
* well, and throws JsiiError instead of JsonProcessingException.
*
* @param tree the JSON object to parse
* @param valueType the expected type value type
Expand Down Expand Up @@ -228,7 +228,7 @@ private static final class EnumSerializer extends JsonSerializer<Enum> {
public void serialize(final Enum value, final JsonGenerator gen, final SerializerProvider serializers) throws IOException {
Jsii jsii = this.tryGetJsiiAnnotation(value.getClass());
if (jsii == null) {
throw new JsiiException("Cannot serialize non-jsii enums");
throw new JsiiError("Cannot serialize non-jsii enums");
} else {
gen.writeStartObject();
gen.writeStringField(TOKEN_ENUM, jsii.fqn() + "/" + value.toString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ private JsiiObjectRef(final String objId, final Set<String> interfaces, final Js
*/
public static JsiiObjectRef parse(final JsonNode objRef) {
if (!objRef.has(TOKEN_REF)) {
throw new JsiiException("Malformed object reference. Expecting " + TOKEN_REF);
throw new JsiiError("Malformed object reference. Expecting " + TOKEN_REF);
}

return new JsiiObjectRef(objRef.get(TOKEN_REF).textValue(), objRef);
Expand Down
Loading