I'm trying to write a job scheduling system in GWT that maintains an array of exceptions (Class<? extends Exception>[] exceptions), that might be resolved by retrying the job. For this, if the scheduler catches an exception, I need to see if this exception matches one of the classes in the array. So, I would like to have a function like this:
boolean offerRetry(Exception exception) {
for (Class<? extends Exception> e: exceptions)
if (e.isInstance(exception)) return true;
return false;
}
Unfortunately Class.isInstance(...) isn't available in GWT.
Is there a good work-around for this? My current best guess is something like this:
public static boolean isInstance(Class<?> clazz, Object o) {
if ((clazz==null) || (o==null)) return false;
if (clazz.isInterface()) throw new UnsupportedOperationException();
Class<?> oClazz = o.getClass();
while (oClazz!=null) {
if (oClazz.equals(clazz)) return true;
oClazz = oClazz.getSuperclass();
}
return false;
}
Unfortunately, this approach does not support testing against interfaces, and I don't have any idea how to fix that either as Class.getInterfaces() is also not available. But would this approach at least work the same way as Java's Class.isInstance in all other cases, excluding interfaces? Specifically, if I look at GWT's source for Class.java, the getSuperclass() method contains a check of isClassMetadataEnabled(), which might return false (but I don't know in which cases), as it contains a comment saying "This body may be replaced by the compiler".
Or is there a better way entirely to do this?
I use following code:
public static <T> boolean isInstanceOf(Class<T> type, Object object) {
try {
T objectAsType = (T) object;
} catch (ClassCastException exception) {
return false;
}
return true;
}
Maybe something like this would help:
boolean offerRetry(Exception exception) {
try{
throw exception;
} catch (SpecException se) {
return true;
} catch (SpecException1 se1) {
return true;
...
} catch (Exception e) {
return false;
}
}
It depends on how you construct the array of exceptions. If the java 7 stuff works properly then you could put all exceptions in one catch:
boolean offerRetry(Exception exception) {
try{
throw exception;
} catch (SpecException | SpecException1 | ... se) {
return true;
} catch (Exception e) {
return false;
}
}
Related
So I recently asked the question of how to handle Dropbox API Exceptions here. I learned that I would have to parse the DBXEception into its subclasses which there are many of. Now Thinking about this I am wondering what would be the best way to go about handling this.
Currently I plan on using instanceof and checking like this if I want the program to try again it will return true and the program will try again maybe with a exponential backoff with server request
public boolean parseDBX(DbxException e)
{
if(e instanceof AccessErrorException) {//handle Error
}else if (e instanceof DbxApiException) {//handle Error
}etc
}
It would be called in a catch block like this
for(int i =0;;i++) {
try {
ListFolderResult result = client.files().listFolder("/Saves/"+prefName);
while (true) {
for (Metadata metadata : result.getEntries()) {
System.out.println(metadata.getPathLower());
//metadata.
}
if (!result.getHasMore()) {
break;
}
result = client.files().listFolderContinue(result.getCursor());
}
} catch (ListFolderErrorException e) {
createDefFolder();
} catch (DbxException e) {
if(codeHandler.parse(e)&&i<10) {
continue;
}else {
log.write("Error 5332490: a problem was encountered while trying to check for the root file"+e.getMessage());
throw new IOException();
}
}
}
So My Question is there a way to use a switch statement instead(From what I have found the answer is no), and if not, is there a better way to handle checking for the type of exception.
The best approach is to avoid "parsing" the exception at all by catching exceptions of the appropriate type:
try {
...
} catch (AccessErrorException aee) {
...
} catch (DbxApiException dae) {
...
}
In cases when this is not desirable you could associate your own integer ID with each exception type, put it in a Map, and use it in your parse method to distinguish among subtypes in a switch:
static Map<Class,Integer> parseId = new HashMap<>();
static {
parseId.put(AccessErrorException.class, 1);
parseId.put(DbxApiException.class, 2);
...
}
...
public void parseDBX(DbxException e) {
Integer id = parseId.get(e.getClass());
if (id != null) {
switch (id.intValue()) {
...
}
}
}
I have a Java EE application with dozens of web services using the same pattern:
public Response myWebService1() {
try {
// do something different depending on the web service called
} catch (MyCustomException e1) {
return Response.status(409).build();
} catch (UnauthorizedException e2) {
return Response.status(401).build();
} catch (Exception e3) {
return Response.status(500).build();
}
}
Is that possible to factorize this piece of code?
If this is a JAX-RS environment, see Tunaki's answer, handling this is specifically catered for and wonderfully simple.
If not:
You can have a functional interface accepting a function that can throw exceptions and returns a Response:
#FunctionalInterface
public interface Responder {
Response handleRequest() throws Exception;
}
(As Dici points out, you could make that a generic ThrowingSupplier or similar, since you're allowing it to throw Exception.)
Then have a helper method accepting an instance of it:
private static Response respond(Responder responder) {
try {
return responder.handleRequest();
} catch (MyCustomException e1) {
return Response.status(409).build();
} catch (UnauthorizedException e2) {
return Response.status(401).build();
} catch (Exception e3) {
return Response.status(500).build();
}
}
...and use it via a lambda:
public Response myWebService1() {
return respond(() -> {
// Do stuff here, return a Response or throw / allow throws on error
});
}
Since this is in a JAX-RS context, there is a much better way, that does not rely on catching a lot of different exceptions: use an ExceptionMapper. This is a built-in mechanism of JAX-RS 1.0 that translates an exception type into a proper Response object to send to the client.
In your case, you could have the following classes defined once in your application:
#Provider
public class UnauthorizedExceptionMapper implements ExceptionMapper<UnauthorizedException> {
public Response toResponse(UnauthorizedException e) {
return Response.status(401).build();
}
}
#Provider
public class MyCustomExceptionMapper implements ExceptionMapper<MyCustomException> {
public Response toResponse(MyCustomException e) {
return Response.status(409).build();
}
}
#Provider
public class CatchAllExceptionMapper implements ExceptionMapper<Exception> {
public Response toResponse(Exception e) {
return Response.status(500).build();
}
}
The #Provider annotation tells the JAX-RS runtime to discover this class when scanning. This makes sure that, wherever in your code, if a MyCustomException is thrown (and not explicitly catched), a 409 response will be returned. The code in your application would simply become:
public Response myWebService1() {
// do something, and don't catch anything; just care about the happy path
}
The exception hierarchy is correctly taken into account. If the application code throws a MyCustomExceptionMapper, JAX-RS will look for an exception mapper registered with that type, and will go up the super class if it can't find one: this way, there can be a catch-all exception mapper handling every other case.
If all methods handle exceptions the same way, you can extract the exception handling to an external method :
public static Response exceptionHandler (Exception exc)
{
if (exc instanceof MyCustomException) {
return Response.status(409).build();
} else if (exc instanceof UnauthorizedException) {
return Response.status(401).build();
} else {
return Response.status(500).build();
}
}
public Response myWebService1() {
try {
// do something different depending on the web service called
} catch (Exception exc) {
return exceptionHandler(exc);
}
}
Sure, that is possible. We have a solution that looks like:
} catch (Exception exception) {
exceptionConverter.convertAndThrow(exception);
}
to unify re-throwing of exceptions based on the exception caught.
So that exception converter is the one central place where we "switch" over the exception type and do what needs to be done. Of course, the central element here is: all your classes need the exact same handling for the incoming exceptions.
We even go one step further and allow a wild mix of potential "input causes", but we also have extensive unit tests to ensure that the conversion always gives the expected result.
Please note: my answer is just about refactoring those "catch" cascade. You can still turn to TJs solution; but keep in mind: that approach adds a certain bit of complexity by introducing that Runnable aspect.
#T.J.Crowder's response is perfect. But for those who can't use Java 8, this is how to implement it with earlier version of Java:
The Responder interface:
public interface Responder {
Response handleRequest() throws Exception;
}
The helper method:
private static Response respond(Responder responder) {
try {
return responder.handleRequest();
} catch (MyCustomException e1) {
return Response.status(409).build();
} catch (UnauthorizedException e2) {
return Response.status(401).build();
} catch (Exception e3) {
return Response.status(500).build();
}
}
With an anonymous class instead of a lambda expression:
Response response = respond(new Responder() {
#Override
public Response handleRequest() throws Exception {
...
return Response.ok().build();
}
});
public WHATTOWRITEHERE test()
{
try
{
transaction.begin();
code which may trigger exception
transaction.commit();
return true;
}
catch (javax.script.ScriptException ex)
{
transaction.rollback();
return ex.getMessage();
}
}
the code above intend to do something, if its OK then return true if not (error happened), this error message string should be returned. It do possible with Php but not with Java
EDIT: expection cant go outside, it has to be handled right here.
You can't return multiple types but you can redesign so you don't have to. Some possibilities:
Don't return an error message. Throw or rethrow an exception instead and let the caller handle it.
Create some class that can encapsulate a success and error state and all related info, return an instance of that.
I recommend option 1. You're already handling an exception, you can see its use for it error handling. No reason to stop it in its tracks there, handle any local cleanup then keep it going up to the caller.
Some hastily constructed examples now that I'm back at a keyboard, intended only to illustrate concepts, not to be exhaustive or necessarily used verbatim:
Cleanup then rethrow:
public boolean test () throws javax.script.ScriptException {
try {
transaction.begin();
...
transaction.commit();
return true;
} catch (javax.script.ScriptException ex) {
transaction.rollback();
throw ex;
}
}
Clean up then rethrow a different exception type if needed:
public boolean test () throws MyGreatException {
try {
transaction.begin();
...
transaction.commit();
return true;
} catch (javax.script.ScriptException ex) {
transaction.rollback();
throw new MyGreatException(ex);
}
}
Return an object that provides status information (this is just a quick example of the general idea):
public class TransactionResult {
private final boolean failed;
private final String reason;
/** Construct a result that represents a successful transaction. */
public TransactionResult () {
failed = false;
reason = null;
}
/** Construct a result that represents a failed transaction with a reason. */
public TransactionResult (String failedReason) {
failed = true;
reason = failedReason;
}
public boolean isFailed () {
return failed;
}
public String getReason () {
return reason;
}
}
And then:
public TransactionResult test () {
TransactionResult result;
try {
transaction.begin();
...
transaction.commit();
result = new TransactionResult();
} catch (javax.script.ScriptException ex) {
transaction.rollback();
result = new TransactionResult(ex.getMessage());
}
return result;
}
Etc.
Don't return anything. Just re-throw the original exception after you roll-back.
public void test()
{
try
{
transaction.begin();
code which may trigger exception
transaction.commit();
}
catch (javax.script.ScriptException ex)
{
transaction.rollback();
throw ex; // re-throw the original exception
}
}
If you insist, you can return Object. In that case, true will be autoboxed to Boolean.TRUE. It’s certainly not recommended, and it will give the caller some extra trouble figuring out whether the returned object is a String or a Boolean. To make matters worse, the caller has no guarantee that return types are limited to the mentioned two, but should also take into account that it could be yet another class.
Better options depend on the situation, so I probably cannot tell you what’s best. A couple of ideas spring to mind, but please don’t use uncritically: (1) Return String, and return null instead of true on success. (2) Design your own return class; for instance, it may hold both a boolean and a message string.
UGLY Workaround but if you really want to do this you can always define a Helper class which wraps status and Error Message, but I would prefer #JsonC's approach.
// Helper class
class Pair<First,Second>{
private First first;
private Second second;
Pair(First first,Second second){
this.first = first;
this.second = second;
}
public First getFirst(){ return this.first; }
public First getSecond(){ return this.second; }
}
// Function returning two types
public Pair<boolean,String> returnSomething(){
try {
return new Pair<boolean,String>(true,null);
}catch(Exception e){
return new Pair<boolean,String>(false,e.getMessage());
}
}
// Calling this method would look like this
Pair<String,boolean> result = returnSomething();
// Retrieve status
boolean status = result.getFirst();
// Retrieve error message (This is null if an exception was caught!)
String errorMessage = result.getSecond();
Exceptions can't go outside, it has to be handled here.
I must say this restriction can only make the interface more difficult to use. Assume you want to return something for the caller to check whether an exception happened in this method, while the caller can ignore the returned value no matter what. So I guess you want to give the caller some flexibility: that he/she doesn't need to bother with the final result if possible. But with the exception approach the caller can still do that, with empty (not recommended) catch clauses.
Exception is the best approach here. Unless "outside" is an environment where exceptions are not supported. Then you have no choice but to come up with something like Try in Scala.
In your case, exceptions should probably be used, not hidden. It's not a result but an error. Learn how to do exception handling in transactions!
Functional programming fanboys will advocate a Monad-like structure, as you can find in the Optional<T> API of Java 8.
I.e. you could return Optional<String> and leave it unset on success (if you do not have a return false and a return true).
For clarity it would be better to build something like this instead with custom classes:
interface Result {}
class BooleanResult implements Result {
boolean result;
public boolean getResult() { return result; }
}
class ErrorResult implements Result {
Exception cause;
public Exception getCause() { return cause; }
}
You could emulate Optional with null values (if you have only one boolean result). On success, return null. Non-null values indicate errors.
String perform() {
try{
...
return null; // No error
} except(Exception e) { // bad code style
return e.getMessage(); // Pray this is never null
}
}
String err = perform();
if (err != null) { throw up; }
Similar APIs are fairly common in old C libraries. Any return value except 0 is an error code. On success, the results are written to a pointer provided at the method call.
You could use Object.
public Object perform() {...}
Object o = perform();
if (o instanceof Boolean) { ...
This is 1980s programming style. This is what PHP does, so it actually is possible in Java! It's just bad because it is no lpnger type safe. This is the worst choice.
I suugest your try 1., 3., 2., 4., 5. in this preference. Or better, only consider the options 1 and 3 at all.
As for option 1. you really should learn how to use try-with-resources. Your transaction is a resource.
When done right, your code will look like this:
try(Transaction a = connection.newTransaction()) {
doSomethingThatMayFail(a);
a.commit();
} // No except here, let try handle this properly
Java will call a.close() even if an exception occurs. Then it will throw the exception upwards. Sour transaction class should have code like this to take care of the rollback:
public void close() {
if (!committed) rollback();
}
This is the most elegant and shortest and safe-to-use approach, as Java ensures close() is called. Throw the Exception, then properly handle it. The code snipped you showed above is an anti-pattern, and known to be very error prone.
If you are using Java 8 you could return an Optional<String>. Then if the code succeeds you return an empty Optional and if there is a failure you return an optional wrapping the failure message.
I would like to annotate some of my test cases with KnownFault - which would do pretty much what expectedException does plus some magic using YouTrack's REST API. I would also like to have an IntermittentFailure attribute which would mean that I'm aware that the test might occasionally fail with [exception] [message] but I wouldn't want this to block the rest of my build chain.
After some research I found that my test class should implement IHookable, then I could have something like this:
#Override
public void run(IHookCallBack callBack, ITestResult result) {
callBack.runTestMethod(result);
if (result.getThrowable().getCause() instanceof IllegalArgumentException){
System.out.println("This is expected.");
result.setThrowable(null);
}
else{
System.out.println("Unexpected exception");
}
}
The problem with this is the actual implementation of invokeHookable:
final Throwable[] error = new Throwable[1];
IHookCallBack callback = new IHookCallBack() {
#Override
public void runTestMethod(ITestResult tr) {
try {
invokeMethod(thisMethod, testInstance, parameters);
} catch (Throwable t) {
error[0] = t;
tr.setThrowable(t); // make Throwable available to IHookable
}
}
#Override
public Object[] getParameters() {
return parameters;
}
};
hookable.run(callback, testResult);
if (error[0] != null) {
throw error[0];
}
Unfortunately that last line means that my test case is going to throw an exception no matter what as the error array is completely out of my hands in the run method.
So, what would be the proper way of intercepting an exception and handling it the way I want to?
What you are trying to do is really interesting. You should try to propose changes on https://github.com/cbeust/testng/pull/
But maybe IHookable is not the best listener you can use. Did you try IInvokedMethodListener?
void afterInvocation(IInvokedMethod method, ITestResult result) {
if (result.getThrowable().getCause() instanceof IllegalArgumentException) {
System.out.println("This is expected.");
result.setThrowable(null);
result.setStatus(SUCCESS); // If you want to change the status
} else {
System.out.println("Unexpected exception");
}
}
I'm implementing an Iterator and in order to deal with the Exceptions I'm using the following pattern: The actual work is done in the private hasNextPriv() method whereas the hasNext() method deals with the Exceptions. The reason for doing it this way is because I don't want to litter hasNextPriv() with try-catch blocks.
#Override
public boolean hasNext()
{
try {
return hasNextPriv();
} catch (XMLStreamException e) {
e.printStackTrace();
try {
reader.close();
} catch (XMLStreamException e1) {
e1.printStackTrace();
}
}
return false;
}
Questions:
Is there a better way to do this?
What would be a good name for the private method hasNextPriv()?
Another way to handle exceptions would be to extract each part that throws exception in a small pure function that properly handles each exception. And then construct final result composing those functions.
Optional<Resource> open() {
try{
//...
return Optional.of(resource);
} catch {
//....
return Optional.empty();
}
}
Optional<Value> read(Resource resource) {
try{
//...
return Optional.of(resource.value);
} catch {
//....
return Optional.empty();
}
}
boolean hasNext() {
open().flatMap(this::read).isPresent();
}
There is no need to return Optional everywhere. Usually there is some dummy value like in Null Object Pattern
Another pattern is to wrap a function execution in object that produces either result or error value. In library javaslang it looks like
return Try.of(this::hasNextPriv)
.recover(x -> Match(x).of(
Case(instanceOf(Exception_1.class), /*handle exception*/),
Case(instanceOf(Exception_2.class), ...)))
.getOrElse(false);
Try object is similar to java 8 Optional but instead of holding present value or missing value Try contains value of either success or failure.
Regarding naming hasNextPriv in your case there is specific domain of data structure. Probably you could come up with more specific name like hasMoreNodes or notEmpty etc.