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
Related
I have a simple try catch method that returns an exception as String
public class Program {
try {
someFunction()
} catch (Exception e){
// i need to get the code and message as strings
}
}
these are some examples of the exceptions I can get:
You have got the error. [ErrorCode: 400 XYZ]
You have got the error. [ErrorCode: 404 XYZ]
You got error which has no errorCode
and these are the error codes I want for each of these exceptions:
INVALID_TEMPLATE
REQUEST_REJECTED
NO_ERROR_CODE
I tried a few things and this is what I came up with
public class Program {
try {
someFunction(x);
} catch (Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
String message = sw.toString();
Matcher m = Pattern.compile(".*:\\s+(.*)\\s+\\[ErrorCode: (\\d+)").matcher(message);
if (m.find()) {
String errorMessage = m.group(1); // You have got the error.
String errorCode = m.group(2); // 400
// Here I want to fetch the error Category based on the errorCode
String errorCategory = XYZ.errorCategory(errorCode);
`//Based on`
the errorCode, errorCategory of INVALID_TEMPLATE which is an enum must be returned
SomeOtherFunc(errorCategory, errorMessage);
}
}
public class XYZ {
private static final Map < String, String > errorMap = new HashMap < > ();
public void populateErrorMap() {
errorMap.put("400", INVALID_TEMPLATE(400, 400));
errorMap.put("404", REQUEST_REJECTED(404, 404));
}
}
public static String errorCategory(String errorCode) {
return errorMap.get(errorCode);
}
Is this optimal or is there a better solution?
Also this is still unable to handle the exception in case there is no error code (should return NO_ERROR_CODE).
How can I archive that?
In real life there are two audiences:
the log handler with a configurable log level (ERROR) and logging (in English) with much info;
the end user with an localized translated message, also with parameters.
The first property is that you probably want a message as format String with Object... parameters. Probably should use MessageFormat.
Sensible would be to support typed parameters.
/** Type-checkable Message Definition. */
public record MessageDef(String format, Class<?>... parameterTypes) {
public void checkFormat() {
... check actual parameters with parameterTypes.length
}
public void checkUsage(Object[] args) {
... check parameter types
}
}
One could make an enum for the error categories. However enums are more suitable for closed domains with a fixed set of values. Extending values in future means that you have created a needless common bottleneck for source version control and so on.
An error is more like an open domain. However if you number them with error codes, an enum gives a nice overview.
The only advantage of error codes is the internationalisation. An Hungarian error message can be easily retrieved.
Then, if you rethrow check exceptions as RuntimeException, like IllegalArgumentException or you own custom ones, you might not want parallel classes: run-time exceptions and categories.
All-in-all I would advise an enum:
public enum MessageType {
INVALID_TEMPLATE(400, Level.ERROR,
new MessageDef("You have got the error in {0}.", String.class)),
...
REQUEST_REJECTED(200, Level.INFO,
new MessageDef("Done."));
public final int code;
public final Level level;
public final MessageDef def;
MessageType(int code, Level level, MessageDef def) {
this.code = code;
this.level = level;
this.def = def;
}
}
One small remark: such little discussion points in the beginning of a project sometimes might be better postponed to a fast refactoring after having written sufficient code. Here an enum might not fit, you might have much re-throwing of exceptions. A premature decision is not needed. And might hamper fast productivity.
Especially as you probably need not mark the code places, you most likely call the same show-error dialog.
I am not sure if I understood your issue properly
If you want to transform your exception code to a custom category this looks shorter:
public class Program {
Map<Integer, String> errorMap = new HashMap<Integer, String>();
errorMap.put(400, "INVALID_TEMPLATE");
errorMap.put(404, "REQUEST_REJECTED");
try {
someFunction (x) ;
} catch (Exception e ) {
SomeOtherFunction(errorMap.get(e.getStatusCode()),errorMessage);
}
}
Otherwise, you could add multiple catches for each exception type if you want to call different functions.
try {
someFunction (x) ;
} catch (IllegalArgumentException e ) {
// do this if exception 1
callThisFunction1()
} catch (IndexOutOfBoundsException e ) {
// do this if exception 2
callThisFunction2()
} catch(ExceptionType3 | Exceptiontype4 ex) {
// do this if exception 3 or 4
callThisFunction3()
}
Also please try to write down your questions better, like give it a proper order.
1)your input
2)your desired output
3)your code
4)the issue
Thank you...
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.
I am writing a unit test for my below code
public class Class1 {
protected void execute(String a, String b) {
try{
process(a,b);
}
catch(Exception E){
Class2.write(e,Class1.class.getSimpleName())
}
}
private void process(String a, String b) {
validate(a,b);
// Doing some processing on a and b values
}
private void validate (String a, String b) {
if(a==null || a.isEmpty() || b==null || b.isEmpty())
throw new IllegalArgumentException("Input value cannot be null or empty");
}
}
For the above code, I am trying to write a UT which covers the exception use case. Below is my UT code,
#Test
public void test1(){
try {
PowerMockito.mockStatic(Class2.class);
PowerMockito.when(Class2.class, "write", Mockito.anyObject(), Mockito.anyString())
.thenCallRealMethod();
Class1 class1 = new Class1();
Class2.write(new IllegalArgumentException("Input value cannot be null or empty"),Class1.class.getSimpleClassName());
PowerMockito.verifyStatic(Class2.class, VerificationModeFactory.times(1));
class1.execute(Mockito.anyString(),Mockito.anyString());
} catch (Exception e) {
e.printStackTrace();
Assert.fail(e.getMessage());
}
}
I am getting the below exception when I execute the above test
Argument(s) are different! Wanted:
Class2.write{
java.lang.IllegalArgumentException:Input value cannot be null or empty,
Class1
}
Actual invocation has different arguments:
Class2.write{
java.lang.IllegalArgumentException:Input value cannot be null or empty,
Class1
}
Can someone please help me on resolving this issue?
I really appreciate your help and time
Thanks in Advance
Your Problem:
IllegalArgumentException does not use the string message for equality. It would be safer to test the string message or the class type. I would prefer that the test detect the type rather than the message, as the string message should not be used for control flow, it is an implementation detail.
System.out.println(Objects.equals(
new IllegalArgumentException(),
new IllegalArgumentException()));
// false
System.out.println(Objects.equals(
new IllegalArgumentException().getClass(),
new IllegalArgumentException().getClass()));
// true
So to mock this I would use matchers:
any(IllegalArgumentException.class), eq(Class1.class.getSimpleName())
Issues with your design:
I'm going to end with an argument against how this code is structured, being that it is not built around dependency injection. Rather than calling the static method Class2::write, you could be calling an instance method.
For example, create the interface:
public interface Writer {
void write(Exception e, String source);
}
You can now refactor the class to provide two ctors, one that accepts any writer, and one that defaults to Class2.
public class Class1 {
private final Writer writer;
public Class1() {
this(Class2::write);
}
public Class1(Writer writer) {
this.writer = writer;
}
protected void execute(String a, String b) {
try {
process(a,b);
}
catch (Exception E) {
writer.write(e, Class1.class.getSimpleName());
}
}
...
}
Using this strategy you can now simply create an instance mock of Writer. This avoids having to mock as static method which changes the bytecode of your application, and also make your class more flexible as it can support many different writer implementations now. Anything that is modifying the bytecode of the application should be used very sparingly, such as replacing static method calls, does not truly validate the runtime execution of your code.
In my opinion, the majority of the PowerMockito/PowerMock only help verify code which was not built with testability / flexibility in mind. You shouldn't need to use anything outside of the Mockito/EasyMock tool-set for well structured code. There are some exceptions but the tool-set should be used very sparingly.
public class ExampleNullPointer {
public static void main(String[] args) {
try {
getEmployee().getDept().getLocation().getContactPerson();
} catch (NullPointerException e) {
e.printStackTrace();
}
}
}
Output
java.lang.NullPointerException
at com.india.test.ExampleNullPointer.main(ExampleNullPointer.java:7)
Looking at above code and its output, when java throws java.lang.NullPointerException, is there anyway we can wrap this NullPointerException to show additional information, like which Object is null, or some info about its parent object, such as the parent object's name attributes?
I am mainly looking for parent object's attribute values, for example Dept is null so if I can log Employee's primary key or Employee's name by overriding toString() method.
Is there anyway I can generically make changes to get these information, so that whenever program throws NullPointerException I get these additional information which will help me easily identify the issue and the data which are causing the issue?
The NullPointerException should not be a part of normal application logic. It's thrown only to find bugs in your code. If you write getEmployee().getDept().getLocation().getContactPerson(), you should be absolutely sure that employee, dept, location exist. Thus you can modify your methods like this:
public Employee getEmployee() {
if(employee == null) {
// some business-level exception
throw new EmployeeAbsentException(this.toString());
}
return employee;
}
// in Employee class
public Dept getDept() {
if(dept == null) {
throw new EmployeeHasNoDeptException(this);
}
return dept;
}
And so on. Of course you should have your own system of business-logic exceptions. You may reuse the same exception class or create several ones (probably subclassing some abstract BusinessLogicException). This way you can easily distinguish what's happening and display the corresponding messages to the user or log them to investigate bugs.
If you want to be able to check whether Employee exists without catching exceptions, add another method like this:
public boolean hasEmployee() {
return employee != null;
}
I have enum say ErrorCodes that
public enum ErrorCodes {
INVALID_LOGIN(100),
INVALID_PASSWORD(101),
SESSION_EXPIRED(102) ...;
private int errorCode;
private ErrorCodes(int error){
this.errorCode = error;
} //setter and getter and other codes
}
now I check my exception error codes with this error codes. I don't want to write if this do this, if this do this. How I can solve this problem (writing 10+ if blocks)
Is there any design patter to that situation ?
Thanks
Either you do it with a if-statement or a switch, or you just implement the logic in question into the ErrorCode somehow.
In an OO fashion it all depends on how you want the application or system react to the error code. Lets say you just want it to output somekind of dialog:
public doSomethingWithError() {
ErrorCodes e = getError();
// the source of error, or originator, returns the enum
switch(e) {
case ErrorCodes.INVALID_LOGIN:
prompt('Invalid Login');
case ErrorCodes.INVALID_PASSWORD:
prompt('Invalid password');
// and so on
}
}
We could instead create an ErrorHandler class that does this instead:
// We'll implement this using OO instead
public doSomethingWithError() {
ErrorHandler e = getError();
// the originator now returns an ErrorHandler object instead
e.handleMessage();
}
// We will need the following abstract class:
public abstract class ErrorHandler {
// Lets say we have a prompter class that prompts the message
private Prompter prompter = new Prompter();
public final void handleMessage() {
String message = this.getMessage();
prompter.prompt(message);
}
// This needs to be implemented in subclasses because
// handleMessage() method is using it.
public abstract String getMessage();
}
// And you'll have the following implementations, e.g.
// for invalid logins:
public final class InvalidLoginHandler() {
public final String getMessage() {
return "Invalid login";
}
}
// E.g. for invalid password:
public final class InvalidPasswordHandler() {
public final String getMessage() {
return "Invalid password";
}
}
The former solution is easy to implement, but becomes difficult to maintain as the code grows larger. The latter solution is more complex, (aka. Template Method pattern following the Open-Closed Principle) but enables you to add more methods into the ErrorHandler when you need it (such as restoring resources or whatever). You can also implement this with the Strategy pattern.
You won't get away completely with the conditional statements, but in the latter the conditional is pushed to the part of the code where the error is originated. That way you won't have double maintenance on conditional statements both at the originator and the error handling code.
EDIT:
See this answer by Michael Borgwardt and this answer by oksayt for how to implement methods on Java Enums if you want to do that instead.
Java enums are very powerful and allow per-instance method implementations:
public enum ErrorCode {
INVALID_LOGIN {
public void handleError() {
// do something
}
},
INVALID_PASSWORD {
public void handleError() {
// do something else
}
},
SESSION_EXPIRED {
public void handleError() {
// do something else again
}
};
public abstract void handleError();
}
Then you can simply call errorCode.handleError();. However, it is questionable whether an ErrorCode enum is really the right place for that logic.
As pointed out by Spoike, using polymorphism to pick the right error handling method is an option. This approach basically defers the 10+ if blocks to the JVM's virtual method lookup, by defining a class hierarchy.
But before going for a full-blown class hierarchy, also consider using enum methods. This option works well if what you plan to do in each case is fairly similar.
For example, if you want to return a different error message for each ErrorCode, you can simply do this:
// Note singular name for enum
public enum ErrorCode {
INVALID_LOGIN(100, "Your login is invalid"),
INVALID_PASSWORD(101, "Your password is invalid"),
SESSION_EXPIRED(102, "Your session has expired");
private final int code;
private final String
private ErrorCode(int code, String message){
this.code = code;
this.message = message;
}
public String getMessage() {
return message;
}
}
Then your error handling code becomes just:
ErrorCode errorCode = getErrorCode();
prompt(errorCode.getMessage());
One drawback of this approach is that if you want to add additional cases, you'll need to modify the enum itself, whereas with a class hierarchy you can add new cases without modifying existing code.
I believe the best you can do is implementing the strategy pattern. This way you won't have to change existing classes when adding new enums but will still be able to extend them. (Open-Closed-Principle).
Search for Strategy Pattern and Open Closed Principle.
You can create a map of error codes(Integer) against enum types
Edit
In this solution, once the map is prepared, you can look up an error code in the map and thus will not require if..else look ups.
E.g.
Map<Integer, ErrorCodes> errorMap = new HashMap<Integer, ErrorCodes>();
for (ErrorCodes error : ErrorCodes.values()) {
errorMap.put(error.getCode(), error);
}
Now when you want to check an error code coming from your aplpication, all you need to do is,
ErrorCodes error = errorMap.get(erro_code_from_application);
Thus removing the need for all the if..else.
You just need to set up the map in a way that adding error codes doesn't require changes in other code. Preparation of the map is one time activity and can be linked to a database, property file etc during the initialization of your application
In my opinion there is nothing wrong with ErrorCodes as enums and a switch statement to dispatch error handling. Enums and switch fit together really well.
However, maybe you find the following insteresting (kind of over-design), see an Example
or "Double dispatching" on Wikipedia.
Assumed requirements:
Error-handling should be encapsulated in an own class
Error-handling should be replacable
Type safety: Whenever an error is added, you are forced to add error handling at each error-handler implementation. It is not possible to "forget" an error in one (of maybe many) switch statments.
The code:
//Inteface for type-safe error handler
interface ErrorHandler {
void handleInvalidLoginError(InvalidLoginError error);
void handleInvalidPasswordError(InvalidLoginError error);
//One method must be added for each kind error. No chance to "forget" one.
}
//The error hierachy
public class AbstractError(Exception) {
private int code;
abstract public void handle(ErrorHandler);
}
public class InvalidLoginError(AbstractError) {
private String additionalStuff;
public void handle(ErrorHandler handler) {
handler.handleInvalidLoginError(this);
}
public String getAdditionalStuff();
}
public class InvalidPasswordError(AbstractError) {
private int code;
public void handle(ErrorHandler handler) {
handler.handleInvalidPasswordError(this);
}
}
//Test class
public class Test {
public void test() {
//Create an error handler instance.
ErrorHandler handler = new LoggingErrorHandler();
try {
doSomething();//throws AbstractError
}
catch (AbstractError e) {
e.handle(handler);
}
}
}