I have the following classes:
BusinessException.java (Is the main exception class that needs to catch the exception and throw it)
public class BusinessException
extends Exception
{
private BusinessExceptionInfo faultInfo
public BusinessException(String message, BusinessExceptionInfo faultInfo) {
super(message);
this.faultInfo = faultInfo;
}
public BusinessException(String message, BusinessExceptionInfo faultInfo, Throwable cause) {
super(message, cause);
this.faultInfo = faultInfo;
}
public BusinessExceptionInfo getFaultInfo() {
return faultInfo;
}
}
BusinessExceptionInfo.java
public class BusinessException {
protected ExceptionResponse exceptionResponse;
protected String message;
// getters and setters for these properties
}
ExceptionResponse.java (This class holds the exception messages and stack trace. This class needs to populated with the values coming from exception)
public class ExceptionResponse {
protected String exceptionClass;
protected String exceptionMessage;
protected List<ErrorResponseItem> errorResponseItems;
protected String stackTrace;
// getters and setters for these properties
}
ErrorResponseItem.java
public class ErrorResponseItem {
protected String defaultErrorDescription;
protected List<String> descriptionVariables;
protected String errorCode;
protected SourceSystemFault sourceSystemFault;
// getter and setter methods
}
// SourceSystemFault.java
public class SourceSystemFault {
protected List<String> calloutParameters;
protected String errorCode;
protected String errorDescription;
protected String operationName;
protected String serviceName;
protected String system;
}
MyClass.java (My class is where in I need to check and throw it. How can I pass the exception message, stack trace to ExceptionResponse from this class?)
Can any one share an example of similar issue. This will be helpful. I got to work with these file to handle exceptions in my project.
public MyResponse myMethod(MyRequest req)
throws BusinessException {
}
How can I catch and throw the BusinessException. I am a newbie and need help.
Related
I am getting list of products from DB using REST Webservice Call & checking if products are NULL or NOT.
IF there are no products i need to throw an exception in POSTMAN.
Can anyone throw some light on how to show exception messages in postman?
Code:
public class ABC extends BusinessException
{
public ABC(final String message)
{
super(message);
}
public ABC(final String message, final Throwable cause)
{
super(message, cause);
}
}
you can directly use WebApplicationException from jax-rs to throw the exception
For Example:
if(products==null){
throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND).entity("products does not exist.").build());
}
If you have your custom exception then you can extends WebApplicationException
public class BusinessException extends WebApplicationException {
public BusinessException(Response.Status status, String message) {
super(Response.status(status)
.entity(message).type(MediaType.TEXT_PLAIN).build());
}
}
throw from your code
if(products==null){
throw new BusinessException(Response.Status.NOT_FOUND,"products does not exist.");
}
you can use error response object to display clean way
public class ErrorResponse {
private int status;
private String message;
ErrorResponse(int status,String message){
this.status = status;
this.message = message;
}
//setters and getters here
}
create ErrorResponse object while throwing the exception
public class BusinessException extends WebApplicationException {
public BusinessException(Response.Status status, String message) {
super(Response.status(status)
.entity(new ErrorResponse(status.getStatusCode(),message)).type(MediaType.APPLICATION_JSON).build());
}
}
In postman it will display like below
{
status:404,
message:"products does not exist."
}
I have enum like this:
public enum Email{
WELCOME,
LOGIN
}
EmailService has following method signature:
public void sendEmail(String from, String subject, String[] to, Map<String, String> props, String templateFileName)
I want to have API like this:
Email.WELCOME.send(from, subject, to, welcomeProp1, welcomeProp2....)
Email.LOGIN.send(from, subject, to, loginProp1, loginProp2....)
To acheve this I tried to add specific methods to enum fields:
public enum Email{
WELCOME{
public void send(String param1,String param2,String param3,String param4){
....
}
},
LOGIN{
public void send(String anotherParam1,String anotherParam2,String anotherParam3){
....
}
}
}
But I found out that I could not invoke this methods outside of enum. To acheve it I need to create abstract method and override in each enum value. But problem that signature of these methods are different and it is impossible to do it.
Any ideas?
You can use polymorphism for in such case. First of all, define some interface, for instance:
public interface Message {
}
Then you should add an abstract method to the enum:
public abstract void send(Message message);
After that, create two child classes - the first one is for WELCOME and the second one is for LOGIN:
class WelcomeMessage implements Message {
private String param1;
private String param2;
private String param3;
private String param4;
// constructor, getters
}
class LoginMessage implements Message {
private String anotherParam1;
private String anotherParam2;
private String anotherParam3;
// constructor, getters
}
Then add implementations of send() method:
public enum Email {
WELCOME {
public void send(Message message) {
WelcomeMessage wm = (WelcomeMessage) message;
....
}
},
LOGIN {
public void send(Message message) {
LoginMessage lm = (LoginMessage) message;
....
}
}
}
UPD.
#gstackoverflow mentioned that it's possible to invoke methods with "incorrect" implementation. I guess I know how to prevent this.
public enum Email {
WELCOME {
protected void sendInternal(Message message) {
WelcomeMessage wm = (WelcomeMessage) message;
....
}
protected Class<? extends Message> getSupportedClass() {
return WelcomeMessage.class;
}
},
LOGIN {
protected void sendInternal(Message message) {
LoginMessage lm = (LoginMessage) message;
....
}
protected Class<? extends Message> getSupportedClass() {
return LoginMessage;
}
};
public static void send(Message message) {
for (Email email : values()) {
if (email.getSupportedClass().equals(message.getClass()) {
email.sendInternal(message);
}
}
}
protected abstract void sendInternal(Message message);
protected abstract Class<? extends Message> getSupportedClass();
}
One solution is to make all the methods take exactly the same object, they just use different parameters from it.
class EmailDetails {
String param1;
String param2;
String param3;
String param4;
String anotherParam1;
String anotherParam2;
String anotherParam3;
}
public enum Email {
WELCOME {
public void send(EmailDetails details) {
System.out.println("Welcome!!");
}
},
LOGIN {
public void send(EmailDetails details) {
System.out.println("Log in!!");
}
};
public abstract void send(EmailDetails details);
}
public void test(String[] args) {
Email.WELCOME.send(new EmailDetails());
Email.LOGIN.send(new EmailDetails());
}
You will generally find that many of the fields are common to all uses.
I have created a new exception class in my Dropwizard service that extends BadRequestException.
public class CustomBadRequestException extends BadRequestException {
private static final long serialVersionUID = 1L;
private List<ValidationFailureDto> validationFailures;
public CustomBadRequestException() {
super();
}
public CustomBadRequestException(final List<ValidationFailureDto> validationFailures) {
super();
this.validationFailures = validationFailures;
}
#ApiModelProperty(value = "List of validationFailures")
public List<ValidationFailureDto> getValidationFailures() {
return validationFailures;
}
}
When I throw that exception at first I was only getting back the deserialised BadRequestException, minus the additional property (validationFailures)
{
code: "400",
message: "Bad request"
}
This is because Dropwizard's internals have a default exception mapper that allows Jetty/Jackson to understand domain exceptions and how to send the appropriate HTTP response.
To overcome this you can implement your own ExceptionMapper class and register it with Dropwizard.
public class CustomBadRequestExceptionMapper implements ExceptionMapper<SamplePackOrderBadRequestException> {
/**
* Allows jackson to deserialise custom exceptions and its properties to JSON response
*
* #param exception exception
* #return response object
*/
#Override
public Response toResponse(final SamplePackOrderBadRequestException exception) {
if (exception instanceof SamplePackOrderBadRequestException) {
SamplePackOrderBadRequestException samplePackOrderBadRequestException
= (SamplePackOrderBadRequestException) exception;
return Response
.status(400)
.entity(samplePackOrderBadRequestException)
.build();
}
return Response.status(400).build();
}
}
However this issue with this is that it deserializes super (Throwable), so you get every single inherited property added in the response which I do not want.
To combat this I tried adding Jackson annotations like so:
#JsonIgnoreProperties(value = "stackTrace")
This is not an optimal solution as there are several properties other than stackTrace that I will need to ignore.
So to summarise, how can I get Dropwizard to properly deserialize my CustomException class without all the additional clutter that I do not need?
I think the easier option is to transform exception to a Error bean and return it as shown below.
public class CustomBadRequestExceptionMapper implements ExceptionMapper<SamplePackOrderBadRequestException> {
#Override
public Response toResponse(final SamplePackOrderBadRequestException exception) {
if (exception instanceof SamplePackOrderBadRequestException) {
SamplePackOrderBadRequestException ex
= (SamplePackOrderBadRequestException) exception;
return Response
.status(400)
.entity(new ErrorBean(400,ex.getMessage,ex.getgetValidationFailures()))
.build();
}
return Response.status(400).build();
}
}
And ErrorBean.java
public static class ErrorBean{
private int code;
private String message;
private List<ValidationFailureDto> failures;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public List<ValidationFailureDto> getFailures() {
return failures;
}
public void setFailures(List<ValidationFailureDto> failures) {
this.failures = failures;
}
}
I have successfully implemented a custom exception using below code
CarNotFoundException.Java
public class CarNotFoundException extends Exception
{
private static final long serialVersionUID = 1L;
public CarNotFoundException(String msg) {
super(msg);
}
}
Car.Java
public static CarProvider getInstanceByProvider(String provider) throws CarNotFoundException {
if(!provider.equals(Constants.BMW || Constants.B||Constants.C{
throw new CarNotFoundException("Car Not Found");
}
return carProvider;
}
CarTest.java
try
{
carProvider = Car.getInstanceByProvider(provider);
} catch (CarNotFoundException e) {
e.printstacktrace();
}
What I want to do ?
Instead of e.printStackTrace(); when I calle.getMessage(),
I get nothing(blank).
How I can make custom e.getMessage() ?
Edit : I got my answer, I missed System.out.println()
Thanks for helping..!
Override getMessage() method in your custom exception
public class CarNotFoundException extends Exception
{
private static final long serialVersionUID = 1L;
public String message;
public CarNotFoundException(String msg) {
this.message = msg;
}
// Overrides Exception's getMessage()
#Override
public String getMessage(){
return message;
}
}
I'm trying to serialize a custom Exception in Java using writeValueAsString() method from Jackson library. I intend to send it by HTTP to another machine. This is working partialy because not all fields are included in JSON after serialize. The top level exception Throwable implements Serializable interface, and also has some constructors that add info about what is to be serialized. I suppose the truth is somewhere here. Please help with some advices. Here is my custom exception code:
import java.io.Serializable;
public class MyException extends RuntimeException{
private static String type = null;
private static String severity = null;
// somewhere on google I red that should use setters to make serialize work
public static void setType(String type) {
MyException.type = type;
}
public static void setSeverity(String severity) {
MyException.severity = severity;
}
public MyException(String message) {
super(message);
}
}
somewhere in code I use:
MyException exc = new MyException("Here goes my exception.");
MyException.setType(exc.getClass().getSimpleName());
MyException.setSeverity("Major");
throw exc;
and in other place I have:
ObjectMapper mapper = new ObjectMapper();
try {
responseBuilder.entity(mapper.writeValueAsString(MyException) );
}
catch (JsonGenerationException e) {e.printStackTrace(); }
catch (JsonMappingException e) {e.printStackTrace(); }
catch (IOException e) { e.printStackTrace(); }
The result JSON object is:
{"cause":null,"message":"Here goes my exception.","localizedMessage":"Here goes my exception.","stackTrace":[{...a usual stack trace...}]}
Here I also expect to see my type and severity fields.
I made type and severity non-static, and it seems to be working fine. I used the following code, and I see both type and severity in the serialized output.
public class MyException extends RuntimeException
{
private String type = null;
private String severity = null;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getSeverity() {
return severity;
}
public void setSeverity(String severity) {
this.severity = severity;
}
public MyException(String message) {
super(message);
}
}
... and
MyException exc = new MyException("Here goes my exception.");
exc.setType(exc.getClass().getSimpleName());
exc.setSeverity("Major");
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writeValueAsString(exc));
Hope this helps!