Delete Mapping Exception in Spring Data - java

Hello i would like to throw an exception in case the user enters an id that is not existing in the system.
This is my mapping
#DeleteMapping("/drugs/{neo4jId}")
public void deleteDrug(#PathVariable Long neo4jId) {
drugsRep.deleteById(neo4jId);
}
what would you suggest?
* I dont want to handle it only in my Frontend

You can try something like this:
if (drugsRep.existsById(neo4jId)) {
throw new EntityNotFoundExceptionById("Invlaid Id was provided");
}
drugsRep.deleteById(neo4jId);
If you define a custom exception you can map it to appropriate http status.
#ResponseStatus(HttpStatus.NOT_FOUND)
public class EntityNotFoundExceptionById extends RuntimeException {
public EntityNotFoundExceptionById(String message) {
super(message);
}
}

Good morning, in this case you can check if user exists.
In Spring-mongodb have one function when you extends the MongoRepository with the name of existsById. So take a look in the documentation, maybe your repository have this function too.
And, when you use this function you can throw one exception. Like the code
if(!repository.existsById(id)){
throw new NotFoundException();
}
repository.deleteById(id);

Related

Spring Webflux - Proper way to throw checked custom exception (not RuntimeException)

May I ask what is the proper way to throw checked custom exception in Spring webflux please?
I would like to insist, it is about checked custom exception, like MyException.java, not something like RuntimeException, and it is about throwing exception, not handling exception.
I tried the following :
#Controller
#SpringBootApplication
public class QuestionHowToThrowException {
public static void main(String[] args) {
SpringApplication.run(QuestionHowToThrowException.class);
}
#PostMapping(path = "/question", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public Mono<ResponseEntity<QuestionResponse>> question(#RequestBody QuestionRequest questionRequest) {
Mono<FirstStep> firstStepMono = WebClient.create().post().uri("http://firstWebService:8111/getFirstStep")
.body(questionRequest.getThing(), String.class).retrieve().bodyToMono(FirstStep.class);
Mono<SecondStep> secondStepMono = firstStepMono.map(oneFirstStep -> getSecondStepFromFirstStepAfterCheck(oneFirstStep));
return secondStepMono.map(oneSecondStep -> ResponseEntity.ok(new QuestionResponse(oneSecondStep.getSecondThing())));
}
private SecondStep getSecondStepFromFirstStepAfterCheck(FirstStep firstStep) throws MyException {
if (firstStep.getThingNeedsToCheckCanThrowException().equals("exception")) {
throw new MyException("exception");
} else {
return new SecondStep(firstStep.getThingNeedsToCheckCanThrowException() + "good");
}
}
public class QuestionRequest {
private String thing;
public String getThing() {
return thing;
}
}
public class QuestionResponse {
private String response;
public QuestionResponse(String response) {
this.response = response;
}
}
public class FirstStep {
private String thingNeedsToCheckCanThrowException;
public String getThingNeedsToCheckCanThrowException() {
return thingNeedsToCheckCanThrowException;
}
}
public class SecondStep {
private String secondThing;
public SecondStep(String secondThing) {
this.secondThing = secondThing;
}
public String getSecondThing() {
return secondThing;
}
}
}
This is not possible, since there in an unhandled exception in getSecondStepFromFirstStepAfterCheck method.
If I throw and propagate, private SecondStep getSecondStepFromFirstStepAfterCheck(FirstStep firstStep) throws MyException the lambda caller method is not happy.
What is the cleanest and proper way to throw custom exception in webflux please?
Thank you
Reading through your sample code, it looks like you are trying to introduce some error handling with on your Mono.
You can create an unchecked exception by extending the RuntimeException class. If you want a checked exception that enforces handling, you can simply extend Exception.
public class MyException extends RuntimeException {
public MyException(String msg) {
super(s);
}
}
The cleanest way to throw an exception with the Reactor project is really just to throw it. There are error handling functions that allow you to provide different flows to certain error cases.
The good news is you have several options that provides some flow control for error handling.
Project Reactor provides several of these methods on the Mono object.
doOnError(),onErrorContinue(),onErrorReturn(),onErrorStop(),onErrorMap()
I am not entirely sure what you are trying to achieve with the following sample code.
return Mono.error(new MyException("exception"));
} else {
return Mono.just(new SecondStep(firstStep.getThingNeedsToCheckCanThrowException() + "good"));
But this looks like a good case for a onErrorMap() since it looks like you are trying to translate some exception here
return Mono.just(new SecondStep(firstStep.getThingNeedsToCheckCanThrowException() + "good")
.onErrorMap(e -> "translated result");
For our applications, we have our custom base exception extend from RuntimeException. We then have standard exception handling that looks for our custom exception for special handling before returning results back to the end user. This allows us to use normal throws mechanics since we want all exceptions thrown to ripple up the top level of the call.
For performance concerns webflux and reactive are slightly lower performance on a per call basis especially for calls that don't need to do any parallelization. However once load is put onto the system it tends to become more performant primarily related to garbage collection. Overhead from the difference between map and flatMap should be negligible at best.

How to handle errors in a Spring-MVC project without if else?

I can’t understand how to handle the following error:
In the class CustomerService I delete the customer by id, and if such an id does not exist, then an error must be thrown! How can you do without an if else construct?
CustomerService:
// Delete customer
public void deleteCustomer(Long id){
Customer customer = customerRepository.getByIdAndUserRole(id, "customer");
customerRepository.delete(customer);
}
CustomerController:
// DELETE MAPPING
//
// Delete customer with ID
#DeleteMapping("/customers/{id}")
void deleteCustomer(#PathVariable Long id) {
customerService.deleteCustomer(id);
}
Try to use Controller Advice. Whenever a exception occur it will directly handled by the handler. No if/else or try/catch blocks will be required.
1) Create a class CustomerControllerHandler, annotate with #ControllerAdvice.
2) Now create methods with arguments having the type of Exception.
3) The methods will return the JSON/POJO/void you want.
4) Annotate the methods with #ExceptionHandler(Exception.class) and
#ResponseStatus(HttpStatus.BAD_REQUEST),
#ControllerAdvice
public class CustomerControllerHandler {
#ExceptionHandler(Exception.class)
#ResponseStatus(HttpStatus.BAD_REQUEST)
public void processException(Exception ex) {
}
}
You can try using this instead. It's the deleteById method for a CrudRepository (hope you're using that) and it throws IllegalArgumentException if it can't find a customer.
I assumed that with "error" you meant "exception" and then in the controller you can surround with a try-catch block like that:
try{
customerService.deleteCustomer(id);
} catch (IllegalArgumentException e) {
log.error("No customer id exists!", e);
// if you have no logger, then use System.out.println() at least
}
If you wanted instead to return an error to the caller, then change the data type from void to HttpResponse<String> and when catching an exception you can return HttpResponse<>("No customer exists with that id!", HTTP.BAD_REQUEST). Now the caller will get a 400 - bad request.
A nicer approach would be to catch the exception in the service itself and return a boolean to the controller (true if customer is deleted and false if couldn't delete / couldn't find one).
if you want to throw error then you will have to check a condition, that is there will be an if statement, but not necessarily an else is needed.
For instance, you can check response of delete and throw error according to below one.
if (deleteCount == 0) {
//throw error here
}

Best practices for exception in my DAO layer

I'm working on my dao layer implementation and I'm confused about the exception handling part. I have many solution to throw exception so what is the best solution to handle exception in dao layer :
This is my code :
My DAO Interface :
#Repository
#Transactional
public interface GnqstRepository<T,V> {
public T save(T t);
public void delete(V v)throws GnqstRepositoryNotFoundException;
public T update(T t);
public T find(V v)throws GnqstRepositoryNotFoundException;
public List<T> findAll();
}
And this is my this an implementation for an entity :
public class EnqueteurRepository implements GnqstRepository<Enqueteur, Long> {
#PersistenceContext(name="gnst")
private EntityManager em ;
private static final Logger logger = Logger.getLogger(EnqueteurRepository.class);
#Override
public Enqueteur find(Long v)throws GnqstRepositoryNotFoundException {
Enqueteur enqueteur = em.find(Enqueteur.class,v);
if(enqueteur!= null){
logger.info("EnqueteurRepository : l'enqueteur avec l'ID : "+v+" a été trouvé avec succès.");
return enqueteur;
}
else{
throw new GnqstRepositoryNotFoundException("L'identifiant entré ne ressemble pas à un ID enqueteur valide.");
}
}
}
Here I create a checked exception my question is there best way than this to throw an exception to the next layer in case for example the find method do not find an entity ?
My objectif is that the user in IHM when click in button find for search in case of no result found then a message should show in IHM in my case I throw exception with a message throught dao layer,business layer to presentation layer my question is who is the best throw an exception or return null to the presentation layer then check an return message to the user ?Thank in advance
There are no hard and fast rules regarding exception handling, but these are my recommendations:
You have to ask yourself what the users of your repository would like to do when they do a lookup with a missing id.
If they want to take immediate action - for instance use a fallback repo - I would simply return a value representing "miss", such as null or Optional.empty().
If you want the error to propagate several layers up your application and maybe render a 404 or abort the running program, I would use an exception.
If you don't want to handle exceptions from different repositories differently, I would just stick with the standard EntityNotFoundException. If you do want to handle them differently I would introduce my own RuntimeExceptions.
Checked exceptions are quite rarely used today. They exist in the borderland between returning values representing failures and throwing exceptions. I believe that the consensus in the community is that they sound like a good idea but are bad in practice. So I would avoid them.
What's wrong with javax.persistence.EntityNotFoundException? This is a matter of debate, but if I were you I would keep close to JPA and avoid adding custom exceptions. I would also avoid changing the behaviour. In JPA the find method returns null if an entity is missing. Users of your find method may find it confusing to get an exception instead. I would return null or rename the method to findRequired.
I din't it's better to throw the Exception in the next layer. And you could simply return an Optional on this method:
public class EnqueteurRepository implements GnqstRepository<Enqueteur, Long> {
#PersistenceContext(name="gnst")
private EntityManager em ;
#Override
public Optional<Enqueteur> find(Long v) {
return Optional.ofNullable(em.find(Enqueteur.class,v));
}
}
And then, could throw a custom exception in the next layer.
void methodCallingDao() {
Optional<Enqueteur> enqueteur = enqueteurRepository.find(new Long(1));
if(!enqueteur.isPresent()) {
throw new RuntimeException("Error retrieving enqueteur");
}
}

Global Exception Handling in Jersey & Spring?

I am developing the RESTful webservices using Jersey & Spring 3.2 along with Open CMIS.
I am not using MVC pattern of Spring and it's just Spring IOC & Jersey SpringServlet, the controller class is something like below code
#GET
#Path("/{objId:.+}")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public statusMsg addObject(#PathParam("objId") String objId{
return repoService.addObject(objId);
}
In the repoService I am performing the business logic to add the object using CMIS, my question is that I am catching around 5 exceptions related to CMIS then the base exception i.e Exception but for every service method I have to repeat it which I don't want to do.
I was searching on Google and found that #ControllerAdvice is the best solution for such problem wheer you can define all the checked & unchecked exceptions and wherever remove all the try catch blocks from the application. But it only work with MVC pattern.
Question 1: Is there a way I can use this in above Jersey-Spring framework?
After more reserach I found that Jersey provides ExceptionMapper to handle customized exception but I want to catch more CMIS exception or default Exception or IO Exception etc.
Question 2: How can I do it with ExceptionMapper?
Question 3: Am I on the correct approach or do you suggest any better approach to handle such issues.
Thanks in advance.
I use jersey2.11 with Tomcat and almost exception handle with ExceptionMapper.
(In domain logic, only DB rollback process use try-catch code.)
I think ExceptionMapper with #Provider automatically choose correct ExceptionMapper. So I suppose this function is satisfied with "I want to catch more CMIS exception or default Exception or IO Exception etc."
This code is my handling ExceptionMapper design code.
1.Some Jersey Root Resource Class
#GET
#Produces("application/json")
public String getUser(#NotNull #QueryParam("id") String id,
#NotNull #QueryParam("token") String token) throws Exception { // This level throws exceptions handled by ExceptionMapper
someComplexMethod(id, token); // possible throw Exception, IOException or other exceptions.
return CLICHED_MESSAGE;
}
2.ExceptionMapper package. com.yourdomain.exceptionmapper
AbstractExceptionMapper.java (All ExceptionMapper class extends this Abstract class)
public abstract class AbstractExceptionMapper {
private static Logger logger = LogManager.getLogger(); // Example log4j2.
protected Response errorResponse(int status, ResponseEntity responseEntity) {
return customizeResponse(status, responseEntity);
}
protected Response errorResponse(int status, ResponseEntity responseEntity, Throwable t) {
logger.catching(t); // logging stack trace.
return customizeResponse(status, responseEntity);
}
private Response customizeResponse(int status, ResponseEntity responseEntity) {
return Response.status(status).entity(responseEntity).build();
}
}
ExceptionMapper.java (At least this mapper can catch any exception which is not define specify exception mapper.)
#Provider
public class ExceptionMapper extends AbstractExceptionMapper implements
javax.ws.rs.ext.ExceptionMapper<Exception> {
#Override
public Response toResponse(Exception e) {
// ResponseEntity class's Member Integer code, String message, Object data. For response format.
ResponseEntity re = new ResponseEntity(Code.ERROR_MISC);
return this.errorResponse(HttpStatus.INTERNAL_SERVER_ERROR_500, re, e);
}
}
WebApplicationExceptionMapper.java (Specify WebApplicationException)
#Provider
public class WebApplicationExceptionMapper extends AbstractExceptionMapper implements
ExceptionMapper<WebApplicationException> {
#Override
public Response toResponse(WebApplicationException e) {
ResponseEntity re = new ResponseEntity(Code.ERROR_WEB_APPLICATION);
return this.errorResponse(e.getResponse().getStatus(), re, e);
}
}
ConstraintViolationExceptionMapper.java (Specify Hibernate Validator ConstraintViolationException)
#Provider
public class ConstraintViolationExceptionMapper extends AbstractExceptionMapper implements
ExceptionMapper<ConstraintViolationException> {
#Override
public Response toResponse(ConstraintViolationException e) {
ResponseEntity re = new ResponseEntity(Code.ERROR_CONSTRAINT_VIOLATION);
List<Map<String, ?>> data = new ArrayList<>();
Map<String, String> errorMap;
for (final ConstraintViolation<?> error : e.getConstraintViolations()) {
errorMap = new HashMap<>();
errorMap.put("attribute", error.getPropertyPath().toString());
errorMap.put("message", error.getMessage());
data.add(errorMap);
}
re.setData(data);
return this.errorResponse(HttpStatus.INTERNAL_SERVER_ERROR_500, re, e);
}
}
.. and other specify exception can create ExceptionMapper classes.
In my experience, Exception Mapper is high level idea for focus to domain logic. It could drive out boring scattered try-catch block code from domain logic.
So I hope that you feel the "Yes i am" at Question 3 to resolve the problem at your environment.
you have not used try catch and throw anywhere across the application.
My code design use throws at method like this and this make to manage by ExceptionMapper classes.
public String getUser(#NotNull #QueryParam("id") String id,
#NotNull #QueryParam("token") String token) throws Exception
So in above approach I have created just 1 class for all the exceptions which I could expect and for any unknown exception the base Exception will be there to catch.
Now wherever in my application if any exception occurs it comes to the CentralControllerException and appropriate response with http status code is sent back.
Q.2. Do you foresee any issue in above approach.
I think if simple project or never update/modify project (project lifecycle short time), your one class exception mapper approach ok.
But ... i never take this approach. Simply, if need to manage more exception, this method become big and complex, and hard to read and maintain becoming.
In my policy, OOP should use pleomorphism strategy any level code(class plan, DI plan) and this approach some part aim to drive out if/switch block in code. And this idea make each method short code and simple, clear to "domain logic" and code become to resistant to modify.
So i create implements ExceptionMapper and delegate to DI which ExceptionMapper class manage to exception.
(So DI manage replace your single class If block manage which exception handling, this is typically refactoring approach similar Extract xxx http://refactoring.com/catalog/extractClass.html.
In our discussion case, single class and one method too busy, so extract each ExceptionMapper class approaching and DI call suitable class & method strategy.)
Btw, system processing result is same at present point. But if need to reduce future development cost ,should not took approach one class exception handling plan. Because if give up simply code and refactor status, project code is dead faster.
This is my idea and why this.
regards.
thanks for your reply. I can see you have created multiple classes based on the exception type and behaviour.
Q1. In your services method are you throwing any exception like
public void addObject(String objId) throws WebApplicationException{
}
or you have not used try catch and throw anywhere across the application.
Actually, I have tried something where in my web application I am not using try, catch and throws anywhere and in my CentralControllerException I have mentioned like below:
public class CentralControllerHandler implements ExceptionMapper<Exception> {
#Override
#Produces(MediaType.APPLICATION_JSON)
public Response toResponse(Exception ex) {
if(ex instanceof CmisContentAlreadyExistsException){
log.error(ex);
// send Response status as 400
}
if(ex instanceof IOException){
log.error(ex);
// send Response status as 400
}
return Response;
}
}
So in above approach I have created just 1 class for all the exceptions which I could expect and for any unknown exception the base Exception will be there to catch.
Now wherever in my application if any exception occurs it comes to the CentralControllerException and appropriate response with http status code is sent back.
Q.2. Do you foresee any issue in above approach.

Implementation for user defined Exception

I have been searching online and researching in some books, but the examples given are limited and I still have some doubts in user-defined exception.
Using the following codes as an example:
//Conventional way of writing user-defined exception
class IdException extends Exception
{
public IdException(String s)
{
super(s);
}
}
class Product
{
String id = new String();
public Product(String _id) throws IdException
{
id = _id;
//Check format of id
if (id.length() < 5)
throw(new IdException(_id));
}
}
It seems that the conventional way of writing a user-defined exception is almost always the same. In the constructor of the user-defined exception, we always call super(msg). This triggers a question in me: If most exceptions are implemented this way, what difference are there between all these exceptions?
For example, I can have multiple user-defined exceptions, but all seems to do the same thing without any differences. (There is no implementation in these exceptions, what makes them work?)
Example:
class IdException extends Exception
{
public IdException(String s)
{
super(s);
}
}
class NameException extends Exception
{
public NameException(String s)
{
super(s);
}
}
class ItemException extends Exception
{
public ItemException(String s)
{
super(s);
}
}
QUE: So shouldn't we (for example) implement the checking of id inside the exception class? If not all exception classes just seem to do the same thing (or not doing anything).
Example of implementing the check in an Exception:
class IdException extends Exception {
public IdException(String s)
{
super(s);
//Can we either place the if-statements here to check format of id ?
}
//Or here ?
}
Ideally you should not implement your business logic inside Exception. Exception tells information about exceptional behaviour, And in Custom Exception you can customise that information.
Find the best practice to write Custom Exception.
We have so many Exceptions already defined in java. All do the same thing : to notify user about the problem in code.
Now suppose we have only one Exception, then How we can what error occurs when the exception is thrown. After all, name matters a lot.
To take your example Exceptions, I would create a more elaborate message by formatting the data provided:
public IdException(String id, String detail) {
super(String.format("The id \"%s\" is invalid: %s", id, detail));
}
throw new IdException(_id, "Id too short.");
This way there is no real logic in the IdException class other than providing the given value (id) and a detail message together in the e.getMessage() String so debugging and logging is easy to read and the code itself is also straightforward:
There is something wrong with the Id _id, namely it is too short. Thus we throw it back at the caller.
Also, when you throw different types of Exceptions in a code, it allows caller code to handle each Exception type differently:
try {
getItem(id, name);
} catch (IdException ex) {
fail(ex.getMessage()); // "The Id is bogus, I don't know what you want from me."
} catch (NameException ex) {
warn(ex.getMessage()); // "The name doesn't match the Id, but here's the Item for that Id anyways"
} catch (ItemException ex) {
fail("Duh! I reported to the dev, something happened");
emailToAdmin(ex.getMessage()); // "The Item has some inconsistent data in the DB"
}
class MyException extends Exception{
int x;
MyException(int y) {
x=y;
}
public String toString(){
return ("Exception Number = "+x) ;
}
}
public class JavaException{
public static void main(String args[]){
try{
throw new MyException(45);
}
catch(MyException e){
System.out.println(e) ;
}
}
}
output: Exception Number = 45

Categories