I am trying to catch exceptions generated while executing some methods in a list.
I have created a different POJO class extending throwable class.
public class ErrorDetails extends Throwable implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private Exception errorDescription;
public Exception getErrorDescription() {
return errorDescription;
}
public void setErrorDescription(Exception errorDescription) {
this.errorDescription = errorDescription;
}
But still I cannot capture the exception in this manner.
private List<ErrorDetails> hello=new ArrayList<ErrorDetails>();
catch (Exception e) {
hello.add(e);
ErrorDetails is one specific type of Throwable. If you declare a list of ErrorDetails you can't add exceptions or errors in it. Change your code to use a list of Exception instead:
List<Exception> hello = new ...
I don't see a point to have your ErrorDetails class but in case you want to keep it, remove "extends Throwable" or replace it with something else. Throwable is meant to be a parent class only for Exception and Error.
Related
From a single method trowing two different custom exceptions based on the condition. While creating a custom exception passing two things one is an error message and another one is error code as a string. But I'm unable to get the error based on the error code. getting an error while calling processErrorCodes() method. Could anyone please help me in fixing this.
// BackgroundException is a custom EXCEPTION
public class BackgroundException extends Exception {
private static final long serialVersionUID = 4664456874499611218L;
private String errorCode="Unknown_Exception";
public BackgroundException(String message, String errorCode){
super(message);
this.errorCode=errorCode;
}
public String getErrorCode(){
return this.errorCode;
}
}
// Similarly I have InvalidException custom exception
public class MyExceptionTest {
public void methodTest(){
String policyId =null;
String policyNotification = null;
String policyStatus = null;
try {
if(policyNotification !=null) {
if(policyStatus!=null) {
if(policyId!=null) {
}
else{
throw new InvalidException("Policy ID Is Null","POLICY_ID");
}
}else{
throw new BackgroundException("Policy Status Is Null","POLICY_STATUS");
}
}
else{
throw new BackgroundException("Policy Notification Is Null","POLICY_NOTIFICATION");
}
} catch (BackgroundException | InvalidException e ) {
// TODO Auto-generated catch block
try {
processErrorCodes(e);
} catch (MyExcep e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.getMessage();
}
}
private static void processErrorCodes(Exception e) throws BackgroundException,InvalidException {
switch(e.getErrorCode()){
case "POLICY_NOTIFICATION":
System.out.println(e.getMessage());
throw e;
case "POLICY_ID":
System.out.println(e.getMessage());
throw e;
case "POLICY_STATUS":
System.out.println(e.getMessage());
throw e;
default:
System.out.println("Unknown exception occured, lets log it for further debugging."+e.getMessage());
e.printStackTrace();
}
}
public static void main(String[] args) {
MyExceptionTest mt = new MyExceptionTest();
mt.methodTest();
}
}
I just want to handle those exceptions based on the error code.
You need a common superclass for all your custom exceptions, let say MessageCodeException, extending Exception and the accept this super class type as a parameter inside of your processErrorCodes method
public abstract class MessageCodeException extends Exception {
public abstract String getCode();
// you can have a same abstract method for message
}
public class BackgroundException extends MessageCodeException {
// ...
}
public class InvalidException extends MessageCodeException {
// ...
}
//and now the process method will look like
private static void processErrorCodes(Exception e) throws ... {
// ...
}
That's abvious that for current implementation you cannot access code field, because Exception class interface does not provide anything like this
BTW it seems to be very bad idea to create Exception driven business validation logic. Wouldn't it be better to create some kind of ValidationResult object with list (lists) of errors/warning/successes and to process such validation result at the end? The purpose of the Exception existence is not to control application flow, but to force user to provide some support for critical situations (or to handle somehow unexpected situations with RuntimeException)
I have around 20 to 30 different types of different Exceptions all extending Exception class in Java.
one example is:
public class NoHandlerFoundException extends Exception {
private static final long serialVersionUID = -9079454849611061074L;
public NoHandlerFoundException() {
super();
}
public NoHandlerFoundException(final String message) {
super(message);
}
}
Other example is:
public class ResourceNotFoundException extends Exception{
private static final long serialVersionUID = -9079454849611061074L;
public ResourceNotFoundException() {
super();
}
public ResourceNotFoundException(final String message) {
super(message);
}
}
and many more.
As you can see most of the code is repeated and then I use ControllerAdvice like (I know code in ControllerAdvice argument exception class should be proper):
#ExceptionHandler({NoHandlerFoundException.class, ResourceNotFoundException.class})
#ResponseStatus(value = HttpStatus.NOT_FOUND)
public #ResponseBody ExceptionResponse handleResourceNotFound(final NoHandlerFoundException exception,
final HttpServletRequest request) {
ExceptionResponse error = new ExceptionResponse();
error.setErrorMessage(exception.getMessage());
error.callerURL(request.getRequestURI());
return error;
}
So I want to know if we have any way in which I can optimize above exceptions and not write individual classes doing almost same job n times of times but still want to differentiate between them.
Thank you.
You can use below approach to reduce code redundancy.
#ExceptionHandler(value = {NoHandlerFoundException.class, ResourceNotFoundException.class})
protected ResponseEntity handleInvalidDataException(RuntimeException exception, WebRequest request) {
ExceptionResponse error = new ExceptionResponse();
error.setErrorMessage(exception.getMessage());
error.callerURL(request.getRequestURI());
return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
}
I'm designing a Java exception handling mechanism for a 2 component system {front-end, back-end}. The back-end will generate exceptions by using Exception classes for different error conditions. Front-end has to map those exception classes to a customer visible error code. This list of Exception classes can be pretty big and may continue to increase in size. What is the best way to map those Exception classes to customer visible error codes?
I could create a Map<Class, Integer> MAP_EX_CLASS_TO_ERROR_CODE and keep it updated, but is it the right/scalable way to map exceptions?
------- Edits after receiving initial set of answers, see Comments below ----
I want to represent similar types of exceptions, or exceptions that demand similar handling with one exception class. For e.g. UserExceptions can be:
RESOURCE_NAME_TOO_LONG
RESOURCE_NOT_FOUND
RESOURCE_NOT_OWNED
...
and InternalExceptions can be:
SERVER_UNAVAILABLE
REQUEST_TIMEOUT
...
If I make an enum for all these error codes, then is it still useful to implement the grouping? I wanted to do the grouping instead of defining one single class for checked exceptions because it'll force me to pay attention to the catch-ing of exceptions every time I add a new line of code that throws a different checked exception than existing code.
for e.g.
public enum ECodes {
RESOURCE_NAME_TOO_LONG(/*number*/0, UserException.class),
RESOURCE_NOT_FOUND(1, UserException.class),
RESOURCE_NOT_OWNED(2, UserException.class),
SERVER_UNAVAILABLE(3, InternalException.class),
REQUEST_TIMEOUT(4, InternalException.class);
// constructor and stuff
}
public class Prot1ExceptionMapper {
static Map<Ecode, /*CustomerCode*/Integer> MAP_EX_CLASS_TO_ERROR_CODE = new HashMap<>();
static {
MAP_EX_CLASS_TO_ERROR_CODE.add(Ecode.RESOURCE_NAME_TOO_LONG, PROT1_CUSTOMER_CODE1);
// Other mappings here
}
public static Integer map(Ecode ecode) {
// Lookup ecode
}
}
public class Prot2ExceptionMapper {
static Map<Ecode, /*CustomerCode*/Integer> MAP_EX_CLASS_TO_ERROR_CODE = new HashMap<>();
static {
MAP_EX_CLASS_TO_ERROR_CODE.add(Ecode.RESOURCE_NAME_TOO_LONG, PROT2_CUSTOMER_CODE1);
// Other mappings here
}
public static Integer map(Ecode ecode) {
// Lookup ecode
}
}
public class UserException extends Exception {
public UserException(ECodes ecode, String message) {
assert ecode.class == UserException.class;
}
}
public class InternalException extends Exception {
public InternalException(ECodes ecode, String message) {
assert ecode.class == UserException.class;
}
}
class DummyClass {
public void doFirstJob() throws UserException {}
public void doSecondJob() throws InternalException {}
}
class Protocol1MainClass {
public static void main(final String[] args) {
try {
doFirstJob();
doSecondJob();
} catch (UserException e1) {
// Do UserException specific stuff
throw Prot1ExceptionMapper.map(e1);
} catch (InternalException e2) {
// Do InternalException specific stuff
throw Prot1ExceptionMapper.map(e2);
}
I created an exception :
public class PkDeleteException extends java.lang.Exception {
private static final long serialVersionUID = 1L;
public PkDeleteException(String msg) {
super(msg);
}
}
Now I threw it in the catch block of some code :
import com.ambre.pta.utils.PkDeleteException;
public class AdminRole {
#Autowired
private Environment env;
#Autowired
private RoleDAO roleDao;
public void del(#RequestParam String id) {
try {
roleDao.delete(id);
} catch (org.hibernate.exception.ConstraintViolationException e) {
Role role = roleDao.get(id);
String errMsg = env.getProperty("admin.list.profils.err.suppr");
errMsg = errMsg.replace("%s", role.getRole_lib());
throw new PkDeleteException(errMsg);
}
}
}
But I got an error Unhandled exception type PkDeleteException !
There are suggested solutions proposed by Eclipse but I do not want to follow them ! So why is there this error ?
In general or for most of the scenarios, you never create a custom exception by extending java.lang.Exception class directly, rather you need to extend java.lang.RuntimeException class (or it's subtypes, which is even more preferable).
As your current PkDeleteException is checked Exception, you need to declare that in your method signature using throws clause (option-2, not preferable) or the best practice is to convert it into unchecked Exception (option-1) like below:
Option(1) - Use unchecked Exception (Preferable):
public class PkDeleteException extends RuntimeExcetion {
private static final long serialVersionUID = 1L;
public PkDeleteException(String msg) {
super(msg);
}
}
Option(2): Change your method signature
from
public void del(#RequestParam String id)
to
public void del(#RequestParam String id) throws PkDeleteException
I suggest you to have a look at here
Your del method should throw PkDeleteException.
Your method should be like follow
public void del(#RequestParam String id) throws PkDeleteException {
try {
roleDao.delete(id);
} catch (org.hibernate.exception.ConstraintViolationException e) {
Role role = roleDao.get(id);
String errMsg = env.getProperty("admin.list.profils.err.suppr");
errMsg = errMsg.replace("%s", role.getRole_lib());
throw new PkDeleteException(errMsg);
}
}
I am new to this, trying to achieve reading some docs but its not working, please bear with me.
I have created a UserNotFoundMapper using ExceptionMappers like this:
public class UserNotFoundMapper implements ExceptionMapper<UserNotFoundException> {
#Override
public Response toResponse(UserNotFoundException ex) {
return Response.status(404).entity(ex.getMessage()).type("text/plain").build();
}
}
This in my service:
#GET
#Path("/user")
public Response getUser(#QueryParam("id") String id) throws UserNotFoundException{
//Some user validation code with DB hit, if not found then
throw new UserNotFoundException();
}
The UserNotFoundException is an User-Defined Exception.
I tried this:
public class UserNotFoundException extends Exception {
//SOME block of code
}
But when I invoke the service, the UserDefinedExceptionMapper is not getting invoked. It seems I might be missing something in the UserDefinedException. How to define this exception then?
Please let me know how to define the UserNotFoundException.
You need to annotate your exception mapper with #Provider, otherwise it will never get registered with the JAX-RS runtime.
#Provider
public class UserNotFoundMapper implements
ExceptionMapper<UserNotFoundException> {
#Override
public Response toResponse(UserNotFoundException ex) {
return Response.status(404).entity(ex.getMessage()).type("text/plain")
.build();
}
}
What I usually do when creating APIs is create my own exception that extends from RuntimeException so I don't necessarily have to catch my exception.
Here's an example:
NOTE: I'm using JAX-RS with Jersey
First: create my own Exception that extends from RuntimeException.
public class ExceptionName extends RuntimeException {
private int code;
private String message;
public int getCode(){
return code;
}
public String getMessage(){
return message;
}
public ExceptionName(int code, String message) {
this.code = code;
this.message = message;
}
}
Also implement a ExceptionMapper
#Provider
public class ExceptionName implements ExceptionMapper<ExceptionName>{
#Override
public Response toResponse(ExceptionName exception) {
return Response.status(exception.getCode()).entity(exception.getMessage()).build();
}
}
And every time that I want to throw an exception I just do it like this anywhere, the exception mapper will take care of returning a response to the client consuming the API
throw new ExceptionName(500,"there was an error with something here");
One small remark , try to Use Response.Status.NOT_FOUND rather than using 404 etc. Code will be more readable and less prone to typos , the same goes for "text/plain". Below is the code that will handle exception as you mentioned.
Oh and one more thing remember to annotate your method #Produces(MediaType.TEXT_PLAIN) in your interface
public class UserNotFoundException extends Exception {
//...
}
public class UserServiceImpl implements UserService {
#Override
public Response getUser(#QueryParam("id") String id) {
final Response response;
try{
// call user method
//if everything is ok
response = Response.status(Response.Status.OK).entity(whateverYouWant).type(MediaType.TEXT_PLAIN).build();
} catch(UserNotFoundException ex) {
response = new UserNotFoundMapper().toResponse(ex);
}
return response;
}
}
In client slide you can check
public static boolean isUserExists(final Response serverResp) {
return serverResp != null && serverResp.getStatus() == Response.Status.NOT_FOUND.getStatusCode();
}