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.
Related
I am bit confused, whether I should validate the data returned from the remote call to another Microserivce Or should I rely on the contract between these Microservice.
I know putting extra checks will not hurt anyone but I would like to know what's the right approach?
in theory, you don't even know how the data you get back from a microservices is created since you only know the interface (API) and what it is returning.
By that, you should take the data response of this API as given.
Sure, additional validation may not harm in the first place.
But consider a case where some business-logic got changed which lead to a change in one of the services. Could be a simple thing like adapting the definition of a KPI leading to a different response (datawise, not structurewise) from the microservice.
Your validation would fail too as false-positive. You would need to adapt your validation for basically nothing.
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.
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.
I'm using spring-mvc and my controllers mostly contain too much logic. When 3 - 5 service beans constitutes the business process and they are called in one handler, then there is some validation included and it results in a few if-else conditions with positive or negative response.
One possible solution is having a facade that contains all references to service beans and common interface of their methods. This makes it simpler, it can also constitute exception boundary in the MVC pattern, but still, the business process has some logic and validation and it is still dealt with in the handler method.
Should I create something like this? :
BusinessProcess {
processOrder() {
serviceBeanA.call();
result = serviceBeanB.call();
validator.validate(result); // throw exception
serviceBeanC.call(result);
}
}
and use only BusinessProcess bean in my handlers ? Catching exceptions or return value would say what's wrong and what to include into the response. Otherwise content of processOrder method would be in handler.
Is it correct way ? How is this pattern called if so.
Most likely you should do as you suggest if I understood correctly. I don't think there's a name for this "pattern" nor needs to be. Since you seem uncertain, here's why I think you are thinking about the right thing.
Processing orders is an logical abstraction your handler is interested in. How the OrderProcessorBean (or BusinessProcessImpl) actually accomplishes this is an implementation detail and hidden from the handler/controller.
Not having such bean you may write a method processOrder in some controller and the controller has dependencies and references to service beans dealing with the details of processing orders. As you noticed this is not good design.
It also seems proper that the processing code lets exceptions fly out and is not bothered how they are handled by the caller. Perhaps a transaction is rolled back and perhaps some HTML containing error messages gets serviced to the end user, but the code (business logic) responsible for processing orders should not know that there are such things as Spring MVC or HTML.
Although I have tagged this as a java/spring question it can be easily asked of any mvc framework with stateless controllers. I know rails uses simple stateless controllers for instance so perhaps you guys know how to best solve this problem. I can best describe the problem with java/spring mvc which is the implementation - forgive the java jargon.
The issue
We are having trouble coming up with a satisfactory way of performing stateless-to-stateful handover in spring mvc.
In essence given a structure like:
Model: Unit
With the states: withdrawn, available, unavailable
And the operations: getOutline() and getHelp()
Controller: UnitController
with operations: displayOutline() and displayHelp()
We need a way to check the state of the unit before we execute the operation displayOutline() (because the unit itself may be withdrawn and so the user should be forwarded to a withdrawn page).
We have tried to do this a number of ways including:
The dead simple way (any language)
All methods in the controller that require an ‘available’ state unit call a method isAvailable() in the first line of its implementation. Obviously there lots of replication here, it reeks.
The AOP way (Java specific)
An #Around advice can be created called UnitAccess which does the check and reroutes the control flow (i.e. instead of calling proceed() which would invoke the underlying method it calls another method on the controller). This seems like a hack and not really what AOP if for, it does remove the replication but adds complexity and reduces transparency.
An Interceptor (Provided by servlet architecture but probably doable in other frameworks)
Which checks the unit state and essentially changes the actual URL call. Again this does not seem right. We don’t like the idea of invoking model logic before getting to a controller.
We have thought about
Command Pattern
Creating a command pattern structure which (with the use of inheritance) can return a withdrawn view or valid displayOutline view. As the execute method will perform the checks in a super()call and the specific logic inside the concrete commands. Ie creating a object structure like
DisplayOutlineCommand extends UnitCommand
public void execute(){
super();
// must be ok, perform getOutline()
}
And finally, using a custom Exception
Calling getAvailableUnit() on a service level object which will do the checks for availability, etc before returning the unit. If the unit is withdrawn then it will throw a UnitWithdrawnException which could be caught by the servlet and handled by returning an appropriate view. Were still not convinced. We are also not hot on the idea of using an exception for normal flow control.
Are we missing something? Is there an easy way to do this under spring/another stateless controller framework?
Maybe I'm missing the point, but why should a user come to the controller if the Unit is withdrawn?
I would argue it is best to ensure that normally pages don't link to a controller that require the Unit to be 'OK', if that Unit is not 'OK'.
If the state of the Unit changes between the time the referring page is rendered and the actual call comes in to the controller (it is not longer 'OK'), then the use of an exception to handle that event seems perfectly fine to me (like having an exception when an optimistic locking error occurs).
Perhaps you haven't described the whole problem, but why not put the check in displayOutline() itself? perhaps route to a displayOutlineOrHelp() method, which looks essentially like
ModelAndView displayOutlineOrHelp(...) {
Unit unit = ... //code to get the unit the request refers to
return unit.isAvailable() ? displayOutline(...) : displayHelp(...);
}