How to deal with wrong ids of resource in REST API? - java

I have the following method in my service layer.
public void delete(int candidateId) {
candidateRepository.delete(candidateId);
}
Pretty basic, now this method is used by the web layer which RESTful architecure is applied.
The URL that will trigger this method is:
DELETE /candidates/{id}
How should I deal with wrong ids given by the clients that use the REST API in the service layer? I know the HTTP response would be 4xx but how should I communicate that the id is invalid between the service and web layer?
Should I use a unchecked exception since this is a condition that my application is unable to recover from? The fault barrier (Spring exception handler) will deal with it.
Or should this be a checked exception since it is possible that clients give wrong ids?
I am using the latest Spring technology if that matter

If it is possible that clients give wrong ids, then they will give wrong ids. And this is a condition that your application should be able to recover from.
I would return a checked exception for this. But introducing a checked exceptions can sometimes mean changes throughout different layers of the application, because, for example, the signatures of many methods would need to be changed to add the "throws" clause (breaking OCP). In case that gets overcomplicated some people (like in Robert C. Martin's "Clean Code") recommend using unchecked exceptions. I would say it's up to you what to return as long as the exception has a meaningful description.

Firstly, you need to decide how your REST API will handle exceptions. There are multiple, equally valid solutions to this.
When designing an API, you pretty much have to assume that whatever can go wrong, will go wrong. Client applications will pass incorrect parameters, use incorrect formats, etc.; your application should expect this, and handle it gracefully.
Using exceptions to communicate business logic is not particularly readable, and may have performance implications. It really doesn't scale beyond very simple cases - imagine that the business logic for "delete" might need to include failures for "record not found", "record has dependent relationships", "record protected", "record archived" etc.
Instead, I would design the application to pass explicit status information back and forth, and translate this into whatever RESTful error handling you use.

Related

Can ResponseEntity be used outside of Controllers in Spring?

I have the following question. I find myself in using ResponseEntity inside a RestController in Spring whenever I want to manipulate the HTTP response coming back from my controller.
Let's say now that the outcome of this response depends indeed on what happens on the business layer below. Let's say this layer makes an http call, if it goes right I forward back above a positive message, instead I forward a negative message.
My controller now receives a message, but it would be nice to analyze whetever what happened down below was successful or not. So, can I return from the business level a ResponseEntity and mark it already as 400 or 200 (depending on what happens down there) or there is another better practice?
Sure you can. Technically ResponseEntity is a class like any other, you can return an instance of it from any layer.
The question you should ask yourself though, is this a good practise to return object of that class from a method that suppose to perform some business logic? For me it does not feel right. You introduce layers to separate concerns. Your domain layer should be totally agnostic of off communication protocol your application offer.
If you design domain layer right you'll know what went wrong based on thrown exception. Then you'll also know which HTTP status you should return.
This violates the concept of separation of layers: It is the controller's only job, and only the controller's job, to translate between the language of HTTP and your application's internal language (API). What if, in the future, you want to change how your HTTP API works but support multiple versions at the same time?
Instead, this is exactly what exceptions are for: Throw a sensible exception from your business methods. I frequently create subclasses of exception types such as IllegalStateException to represent application-specific errors, and sometimes I use the existing exception classes directly.

Is it good practice to raise an exception on "bad requests" in an http API - in contradiction to (Java) best practice

Normally I try to use exceptions only for "exceptional" conditions ("Effective Java ", Issue 69). My personal interpretation is:
if I hit a condition in a specific part in code (normally a method or constructor) where I can't give a meaningful answer or outcome anymore I throw an exception and whoever called the piece of code has to handle it.
In the special case of HTTP endpoints I can always give a meaningful answer - a response with a status code.
Handling bad requests thus belongs to normal program flow of endpoint methods and should not raise new exception.
E.g. an endpoint that returns a resource should just return 404 in case the resource is not found. In my opinion it would be bad practice to raise a "SomethingNotFoundExcetion" (that could be handled by an error handler and create 404 response)
My question is: It is bad practice to use Spring Boot's error handling mechanism for bad requests (4xy) that relies on exceptions to create specific HTTP responses. (It is really fine for all uncovered errors yielding 500)
(I am just writing a review of code and I am not sure if I should suggest to not use error handler for "normal" API interaction)
Answer/Comment to current answers
It seems that the most of you missed the important part of my reasoning:
(citing Effective Java, Item 69):
Use exceptions only for exceptional
conditions ...
this reasoning:
• Because exceptions are designed for exceptional circumstances, there is little
incentive for JVM implementors to make them as fast as explicit tests.
• Placing code inside a try-catch block inhibits certain optimizations that
JVM implementations might otherwise perform.
The main point for me is:
A well-designed API
must not force its clients to use exceptions for ordinary control flow.
Especially in case of rest API. It should be easy to use any API in a way to avoid exceptions at all. This means for me. No correct (defined e.g. in Open API) usage of a Rest API should raise an exception.
To put another point: The standard for SOAP (another http based API stuff) forbids to use "SOAP fault" for correct (defined by WSDL) requests.
For me raising exception in remote APIs on not exceptional cases are even worse then in classic API (via dependency).
It depends on your project, it's really a matter of opinion/architectural decision. I'd say either-or.
The advantage of using specific Exceptions and then using a Spring handler to map them is that it removes the tedious construction of responses with the correct code from the actual application logic code (it's not dissimilar from aspects in that respect): just throw the correct exception and be done with it.
OTOH, the distance to the error handling code means that 1. if something doesn't work, it may be difficult to track down the issue 2. you need to know what exceptions to throw, and that is not immediately obvious and needs to be documented well.
It is not a bad practice, but a matter of architectural decision. It could be good to have an error handler that will produce a 4xx response and will do some additional error handling work, such as logging, and/or sending a notification by mail or queue or (like in my project) write errors in the table so they could be reviewed by user using GUI component of an application and may be even edited and re-submitted if it makes sense. It also unifies the error handling to a single code (code re-use). But if you really just need to send a 4xx response and nothing else, then its OK not raise exception and just do it in your code. Raising exception is expensive performance-wise and shouldn't be done just for the sake of raising exception alone. But in this particular case my opinion is to use Exception/Spring boot Error handling mechanism

Exception versus return code in DAO pattern

After reading a lot about the abusive use of exceptions in Java and how you should let an exception bubble up through the different layers of an application, I've come to a point where I don't know what I am supposed to do with the potential errors my application can have.
Basically, I have a webservice which uses the DAO pattern to access data in my database. All of the database actions can throw a SQLException.
As of today, I'm using a try catch to catch the SQLException and then thow a specific defined exception called ExceptionDAO that will be handle by the webservice to return a correct message to the users (a mobile application) of my webservice.
After reading a lot about how exception should be exceptional and should not be used in control flow, I've come up with a mixed understanding of what I should do to handle any errors:
Use return codes for anything that is likely to happen (e.g. username already exists) and therefore, to comply with the DAO pattern, pass my business objects as parameters instead. I could also use a specific pair which would return the code + the business object instead. The webservice would then use the return code to display a specific message.
Use checked exceptions for anything that I can't predict will happen and let them bubble up to the webservice to handle and return a message to the users. (e.g. SQLException that I can't predict : connection aborted)
Let unchecked exceptions bubble up aswell and display a sort of 404 error in this case.
I also had a look at the null pattern but I don't think it suits this particular situation really well.
I'm also concerned to not give too much information to the users, but rather useful and straight to the point information. Indeed, the messages returned by the webservice will be used by a mobile application to then display a message to the end-user.
I hope that I was clear enough about the problem I'm having, and I'm looking forward to your answers !
Return codes are suitable for C, which lacks exception handling among its features. For Java, please use exceptions, either checked or runtime, that's a matter of taste.
Personally, I hate checked exceptions, because they pollute my method signatures with information of border cases that might never occur. But maybe you want to be strict with the contract of your classes, even for such exceptional cases. If that's your case, then use checked exceptions. Otherwise, let your method signatures in peace and throw a runtime exception whenever you detect an exceptional case (such as an entity not found, entity already exists, etc).
Please note that ExceptionDAO is not a happy name. It appears to be a dao that handles exceptions. Maybe something like PersistenceException would be better.
Apart from that naming detail, I think your approach is on the right way, though not ideal. Ideally, you wouldn't need to do a try/catch for SQLExceptions inside every method that calls methods from your DAOs (or inside every method of your DAOs). Instead, a persistence exception translation mechanism would be much better. Spring, for instance, comes with one by default. Spring accomplishes this by proxying every DAO, and by letting its proxies perform a try/catch around every method invocation. Then, specific SQLExceptions with specific SQL error codes are translated to Spring's own DataAccessException hierarchy. So, in the upper layers, you would end up with a specific DataAccessException, but you wouldn't need to do a try/catch inside every method.
If you are already using Spring, then you have nothing to do, but if you aren't using it and have either many DAOs or many methods that might throw SQLExceptions, and all your DAOs implement an interface, then it might be worth the effort to implement a proxy that intercepts all the methods of your DAOs and performs a try/catch around them. Then, in this interceptor's catch block, you'd throw your ExceptionDAO (please rename it!) with a message that would depend on the original SQLException (and maybe on its SQL error code, too).
This approach has the advantage that you could handle all persistence exceptions in a single point of your program.
This very same concept could be applied to your web layer as well. Instead of letting every method of your endpoints handle your ExceptionDAO (don't forget to rename it!), you could create a proxy that intercepts every method call and perform a try/catch around it. You could then extract the message from the exception and send it in the response (or whatever you find suitable to do with it). Again, this is all based in Spring, this time, in Spring MVC Exception Handling mechanism. Here you could also handle unexpected exceptions, i.e. RuntimeExceptions and provide an appropriate message to your users.
The advantage, again, would be that you could handle all the exceptions that reached your web layer in a single point of your program.
Please see Proxy javadocs and this tutorial for further reference on Java's proxies.
I think you are missing an important option, which is the observer pattern.
In your DAO you can have this:
public interface OnExceptionInteractionListener {
public void onExceptionInteraction(String exceptionMessage);
}
I would have the DAO be something like:
public SomeDAO(OnExceptionInteractionListener listener, ...) {
}
and I would instantiate the DAO as
SomeDAO s = new SomeDAO(new OnExceptionInteractionListener() {
public void onExceptionInteraction(String exceptionMessage) {
}
}, ...);
So, if there is an exception caught then call the listener in the DAO and the next level up will handle it.
This is better performance than throwing exceptions, and better than return codes.
For more on this you can look at this answer, for other examples: https://stackoverflow.com/a/18585099/67566
I haven't tried it but I expect that lambda expressions would be useful for this also, if you are using Java8.
Return codes are very old-school. Ideally, you should do your insert in some sort of transaction that checks:
Lock username inserts
Is this username available?
3a. If so, insert and unlock
3b. If not, unlock and inform user
If that's not possible, then a return object wrapping the result if it was created successfully and response Enum with potential outcomes.

Java Throwing exceptions vs returning response in catch

I know a lot has been discussed around exception handling, however I need some advice specific to my situation.
I am currently working on a Spring MVC application with Controller->Services->DAO layers. The service classes catch mainly two kinds of exceptions HibernateException and IOException.
HibernateException because service needs to perform rollback if a transaction did not succeed and IOException since it is an unchecked exception and needs to be caught or thrown and I prefer the first option.
Now what would be a better way of handling these further up in the stack :
Should I rethrow these exceptions to the controller and in the
ExceptionHandler of the controller send a HTTP error-code 500
Or in the catch block create the normal JSON response object, setting status=failure and the appropriate error message and return this to the Controller?
Exception Handling convensions:
There is a saying that, best way of handling Exception is not to handle it!
For Spring's convention of controller<->service<->dao layers, Exception handling mechanism is known as Bubble up. Any exception occurs in the dao or service layer, you should pop it up to the controller layer (by adding throws XXXException in dao and service layer's method signature, is the most common way). Only controller layer should handle Exceptions.
Here is a nice tutorial of how you can handle exceptions for REST with spring.
Send HTTP Status code 500 or JSON object with status:
Sounds like you are writing API with Spring MVC. Look, when you are writing API's you should follow the proper conventions. It is Globally accepted that for internal server errors you send HTTP response with code 500, that means internal server errors.
There are number of causes for what you should not send JSON response in this case. One of the main cause is the implicit assumption of your API client. That is HTTP response with code 200 with a JSON object means every thing went normal. And thus the client side business logic may reflect that assumption which is wrong eventually.
Here you can see some API error code conventions for some well-known organizations:
twitter
LinkedIn
Facebook Graph API
I assume that you have not come so far yet as to create a client and therefor can pick 100% for yourself.
If so I would also recommend to use 1, for the main reason that using the correct status codes can go a long way in your API, as well as it's a very easy solution to your problem. You can write some neat code for your error handling.
Another major reason why you should use your first point is because you can easily re-use the error handling for other APIs, resources or webapps.
For example an enum with all your errors, and what status code you consider them to be, and you can also include what log level you want them to be.
public enum ExceptionMapping {
IllegalArgumentException(IllegalArgumentException.class, 400, LogLevel.ERROR),
If your goal is to build a neat API for unknown clients I would recommend reading more about REST level 3 (http://martinfowler.com/articles/richardsonMaturityModel.html) where you includes hypermedia links to create an API which allows the client to "browse" your full API. It's more work for the client since they have to be smarter but it can provide you with very nice features such as breaking a large part of your API without the client even noticing.

Handling web service error codes (in addition to general soapfaultexceptions)

I am currently adding functionality to a JSF/Richfaces application and we are now integrating with external web services.
Actions done with the services include: get user, get account, update user, update account, create user, create account.
These services, along with the unexpected soapfaultexceptions, can return error codes in their response types. Mainly for failures along the lines of: login already exists, password doesn't meet criteria, account number already exists, and no user found.
The calls are like so: BackingBean > Manager Level Class (mainly a pass through) > Web Service Client (makes the actual WS call). For the GET actions, the ID (username or account number) is passed down and the Account or User object is passed back up. The Updates pass around User/Account objects, same with the Creates.
What would be the best way to get these errors back up to the backingbean so I can handle them via the UI?
Of course I could check for error codes in the response, throw an exception and keep throwing it to the backing bean where I would handle it there.
I could implement a Result type that would hold an Error Type and POJO/DTO that I was populating from the service.
One of my colleagues recommended I use the decorator to decorate my USER or ACCOUNT objects with validators that I would also need to create. Basically I suppose my decorator would just hold custom Error types and the Validate() would just check to see if (List!= null && !(Size>0)). Correct?
What are your thoughts on the proposed methods? #1 is the easiest, #2 seems to be more elegant and still simple, #3 is the "toughest" to me since I've never used the decorator pattern. However, #3 seems to be the most elegant while also being the most time consuming to implement.
Let me know if you need any more clarification.
Thanks, SO!
It's always best to limit programatically using exceptions(When to throw an exception).
First ask yourself is this an exceptional situation? In your case it isn't its just a validation error. Exceptions come with a cost, and there is no guarantee that you will be able to catch the exception further down the chain.
Both 2/3 are similar solutions in the fact you are just trying to return additional information back to the controller.
Option 3, could be considered cleaner, but if you have access to the user/account classes, you could always add an additional property to the class that could contain validation errors.
A good example of this pattern is ActiveRecord within ruby, same type of model. You call save on a model object, if an error occurs it populates an error property.
Throw a custom exception or one of a set of custom exceptions and handle it at the higher level. This is my preferred way of handling it versus status codes in Java where everything is pass by value, and frees up a return variable for other purposes.
In regards to "keep throwing it," don't catch and re-throw at each level, but only catch at the level where you can do something about it, ie. the backing bean / UI in this case.

Categories