I'm getting to grips with the Spark Framework and I'm trying to understand the best way of handling exceptions in a uniform way for multiple Routes.
At the moment I have a number of Routes which all handle exceptions along the lines of:
...
catch (final Exception e) {
...
response.status(418);
return e.getMessage();
}
...
This leaves a lot to be desired, mainly the exception logic is duplicated between them. I know that it can be improved by refactoring but I was wondering if there's something similar to the ExceptionHandler mechanism in Spring where you can perform an action when a particular exception is thrown, e.g.:
#ExceptionHandler(Exception.class)
public void handleException(final Exception e, final HttpServletRequest request) {
...executed for the matching exception...
}
So, is there a Spark-esque mechanism for exception handling? I've checked the documentation and come up short. If there isn't, I'll go ahead with my refactoring plans. Thanks.
You can handle exceptions like so:
get("/throwexception", (request, response) -> {
throw new NotFoundException();
});
exception(NotFoundException.class, (e, request, response) -> {
response.status(404);
response.body("Resource not found");
});
Example taken from the Spark docs.
I've been dealing with this very issue. This is what I came up with. It will need tweaking to your environment.
public class ExceptionHandler extends MustacheTemplateHandler
{
private final WrappedHandler inter;
public abstract static class WrappedHandler
{
public abstract Object handle(Request req, Response res);
}
public static ExceptionHandler wrap(String path, WrappedHandler internal)
{
return new ExceptionHandler(path, internal);
}
private ExceptionHandler(String path, WrappedHandler internal)
{
super(path);
inter = internal;
}
#Override
public Object handle(Request req, Response res)
{
try
{
return inter.handle(req, res);
}
catch (Exception e)
{
e.printStackTrace();
return new ModelAndView(e, "errors");
}
}
}
and then (using import static):
get(wrap("/download", new DownloadHandler()));
post(wrap("/upload", new UploadHandler()));
Related
Have a service method which can throw an exception
if (NOT_FOUND) {
throw new ResourceNotFoundException("Resource not found");
}
And ControllerAdvice with exceptionHandler
#ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity handleResourceNotFound(Exception ex) {
return new ResponseEntity("your-error-message");
}
So i need to pass another String as param and access it form exceptionHanlder:
if (NOT_FOUND) {
String param2 = "param2";
throw new ResourceNotFoundException("Recource not found", param2);
}
#ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<Problem> handleResourceNotFound(Exception ex) {
doomething(param2);
return new ResponseEntity({your-error-message});
}
Is there any way to do it?
Yes, as Abra said, you can create your own exception that inherits from ResourceNotFoundException, and add the other parameter there. Then in the exception handler you can get it from the exception:
This could be the class
public class CustomException extends ResourceNotFoundException {
private String otherParam;
public CustomException(String message, String otherParam) {
super(message);
this.otherParam = otherParam
{
public getOtherParam() {
return otherParam;
}
}
Then you throw it
throw new CustomException("Recource not found", param2);
Then in exception handler you can get the second param
#ExceptionHandler(CustomException.class)
public ResponseEntity<Problem> handleResourceNotFound(CustomException ex) {
doomething(ex.getOtherParam());
return new ResponseEntity(ex.getMessage());
}
i refer to the error handle tutorial (chapter 6.3) , where you see an proper usage of the Exception Handler as you did in your code snippet.
there is an interesing aspect of your approach:
Of course, we'll use the global exception handling mechanism that we discussed earlier to handle the AccessDeniedException as well:
so the purpose of your Exception Handler is to handle Exceptions of a vast variety of exceptions: global exception handling. You would not know where the exception was thrown. Therefor it makes no sense to add additional logic to your Exception handler on the Handler side.
rather than adding a backpack to the handler you should take the action on the point of existing. that would take a small archituetur change and handle there:
if (NOT_FOUND) {
String param2 = "param2";
doomething(param2);
throw new ResourceNotFoundException("Recource not found");
}
clean code - separation of concerns
if it was a general aspect of exception handling, you would have the general informatiaon already in your hands
if it is a specific aspect, then it should be handled where it happens!
Just update your advice:
#ExceptionHandler(ResourceNotFoundException.class)
// public ResponseEntity handleResourceNotFound(Exception ex) {
public ResponseEntity handleResourceNotFound(ResourceNotFoundException ex) {
// ex contains all parameters that you need
return new ResponseEntity("your-error-message");
}
Is there a way in Java/Spring with annotations to achieve the following?
For example I have a method:
public void deleteObject(Object object) {
delete(object);
}
I want to send 2 audit events: one when method starts, and second - if method finishes successfully or throws exception.
Actually, I can do it like this:
public void deleteObject(Object object) {
sendAuditEvent("Started deletion of object");
try {
delete(object);
sendAuditEvent("Finished deleting of object successfully");
} catch (Exception ex) {
sendAuditEvent("Finished deleting object with exception");
throw ex;
}
}
But I was wondering if there is a way to do it with annotations? I'd prefer to keep the auditing logic separately and not autowire any beans for sending audit events.
The only thing coming top my mind is to do something like this:
public void deleteObject(Object object) {
startedDeleting(object);
delete(object);
}
#SomeAnnotationOnStartOfMethod
public void startedDeleting(Object object) {
//do nothing
}
public void delete(Object object) {
try {
businessLogicMethodToDelete(object);
methodOnSuccess(object);
} catch (Exception ex) {
methodOnException(object);
throw ex;
}
}
#SomeAnnotationOnSuccess
public void methodOnSuccess(Object object) {
//do nothing
}
#SomeAnnotationOnFailure
public void methodOnException(Object object) {
//do nothing
}
But that looks not nice to me.
What could be a better design solution here?
What you are looking for is called Aspect-oriented programming.
The most commonly used tools to solve this kind of problems are:
AspectJ (cf. also the tutorial on Baeldung),
Spring AOP (cf. also the tutorial on Baeldung)
I'm stuck to understand why RxJava does not capture my exception and it just crashes. The exception occurs while getting the object to emit.
Here is how my code looks like:
TestService testService = new TestService();
Single.just(testService.testGetUser())
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableSingleObserver<User>() {
#Override
public void onSuccess(#NonNull User user) {
Log.d(TAG, "onSuccess(): Launching Home Activity");
Intent intent = new Intent(LoginActivity.this, HomeActivity.class);
startActivity(intent);
}
#Override
public void onError(#NonNull Throwable e) {
Log.d(TAG, "onError()");
}
});
My TestService class looks like:
public class TestService {
public User logInUser(LogInData logInData) throws RuntimeException {
Log.d(TAG, "logInUser(): Logging user in");
User user = this.guideMeAroundData.logInUser(logInData);
return user;
}
}
In my logInUser() method I'm throwing an exception if the user is not valid. This causes my whole Android app to crash.
It looks like this is not the correct way to do it. Could anybody please tell how should I handle an scenario where an exception is thrown while getting the object(s) to be emitted?
This is a very common (and baffling) misunderstanding of Java syntax and operations. The code
Single.just(testService.testGetUser())
is equivalent to
User tmp1 = testService.testGetUser();
Single.just(tmp1)
where testGetUser executes before RxJava even gets involved thus any exception it throws happens before that.
You are probably looking for the
Single.fromCallable(() -> testService.testGetUser())
or simply define the Retrofit API as Single<User> logInUser(LogInData data).
Unchecked exceptions are catched by the RxJava for the most part.
But for checked exceptions you need to provide your own try{}catch(){}
block.
One example would be -
String transform(String input) throws IOException;
Observable.just("Hello!")
.map(input -> {
try {
return transform(input);
} catch (Throwable t) {
throw Exceptions.propagate(t);
}
})
Check out this post for info, it explained very well.
http://blog.danlew.net/2015/12/08/error-handling-in-rxjava/
The Following is what I copy from Elasticsearch Official website
"The Response object, either returned by the synchronous performRequest methods or received as an argument in ResponseListener#onSuccess(Response), wraps the response object returned by the http client"
https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/_reading_responses.html
The following is Async Function in ElasticSearchService Class
public void getAsyncRequest(String endpoint, Map params, HttpEntity entity) {
restClient.performRequestAsync("GET", endpoint, params, entity, new ResponseListener() {
#Override
public void onSuccess(Response response) {
try {
LOGGER.info(EntityUtils.toString(response.getEntity()));
} catch (IOException e) {
LOGGER.error(e.getMessage());
}
}
#Override
public void onFailure(Exception e) {
LOGGER.error(e.getMessage());
}
});
}
The following is another Class.
public static void main(String[] args) {
ElasticSearchService.getAsyncRequest(endpoint, params, entity);
}
So my question is, when calling getAsyncRequestWithBody, when it is onSuccess, then it will get response Object, but how do I return it back to the caller which is static "main" function.
I didn't figure out what it means by "wraps the response object returned by the http client"
Thank you for help.
leochung
Your java code very likely exits, before the response is processed. You can use the RestClient.SyncResponseListener to wait for the response to return.
But you are basically not gaining anything from an async call in this example. If you underlying code does not support it, you can just keep using the synchronous code.
I am using a third party REST API in which every single API call is defined as throws IOException. I am wrapping the REST API in a Repository-style class. However, given the API interface, I am forced to either declare every method in my repository as throws IOException, or wrap every single call and rethrow it as a runtime exception.
Is there any clean way of wrapping the entire API to catch/rethrow as my own custom RuntimeException instead? I know I can wrap the calls using AspectJ and intercept the IOException, but my signature for the method won't change.
Are there any tricks I can use to convert an Exception to a RuntimeException?
For example:
APIWrapper interface has method:
public String getAppBuilds(String report_changed_since, String only_latest, String include_in_progress) throws IOException
In my repo, I would like to be able to call APIWrapper.getAppBuilds() without needing to catch the IOException.
The only possibility is to catch the Exception and convert it to a RuntimeException exactly as library like SpringJDBC do.
Basically something like that
public class OriginalLibrary {
public void method1() throws IOException {
...
}
}
public class LibraryWithoutException {
private OriginalLibrary original;
public LibraryWithoutException(OriginalLibrary original) {
this.original = original;
}
public void method1() {
try {
original.method1();
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
}
}
}
Note: it will be better to create a custom RuntimeException instead of using the standard class.
Or with your api:
public class APIWrapperNoException {
private APIWrapper api;
public APIWrapperNoException(APIWrapper api) {
this.api = api;
}
public String getAppBuilds(String report_changed_since,
String only_latest,
String include_in_progress) {
try {
return api.getAppBuilds(report_changed_since,
only_latest, include_in_progress);
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
}
}
}
You could use project Lombok #SneakyThrows annotation (see here). This annotation allows you to hide throws in the signature at compile time.