How to print messages in Custom Exception? - java

I'm new to exceptions and am a bit confused at getMessage() and super(customMessage). Please forgive me if it sounds rather ridiculous...
Part of my try catch code is here:
try{
sc.buyASong();
} catch (CardEmptyException e){
System.out.println("Caught error: " +e.getMessage() );
} catch (CardNotActivatedException e){
System.out.println("Caught error: " +e.getMessage() );
}
And I want to print "Caught error: Card not activated"
or "Caught error: No more songs on the card". And my custom exception is like this
class CardNotActivatedException extends Exception{
public CardNotActivatedException(){
super("Card not activated");
}
}
class CardEmptyException extends Exception{
public CardEmptyException(){
super("No more songs on the card");
}
}
But when I run it, it prints
com.example.CardNotActivatedException: Card not activated
and "Caught error: ----" is not printed out as well. Is there something that I am understanding wrongly? Because it looks like I am fundamentally wrong and I'm not quite sure where my misunderstanding is...?

Are you sure you're catching the CardEmptyException ?
Did you forget to save your code?
Anyway, I suggest you change your approach, and use a constructor method receiving a String object. You can keep a default costructor with a default message, but also use somthing like this one:
public MyCustomException(String arg0) {
super(arg0);
}
Then, whenever you call this exception, you can call passa the message you want to.

Related

How do you assert that an exception is thrown if it has already been consumed/handled/caught

Let's say I test a class method that is reliant on another method that we do not want or can not test directly, which handles a checked exception, in the following manner:
public class A {
public void process(){
if (isProcessingSuccessful()){
LOG.info("Success");
}
else {
LOG.error("Fail");
}
}
private boolean isProcessingSuccessful(){
try{
doSomeOtherStuff();
return true;
}
catch (Exception e){
return false;
}
}
}
Now, if I have a test class testing for the A#process(), like:
#Test
public void shouldFailDueToCommandGatewayError() {
A a = new A();
// setting up preconditions
//testing here
a.process();
//Now, assert exception was thrown during the course of a.process() execution, something like
exception.expect(NullPointerException.class);
// ?? how to do that?
}
TLTD: It is possible to write separate test for isProcessingSuccessful() or do something similar, but let's say that method is not accessible for testing, like it's private in a library?
Given the above constraints, is there any way to write a test in a way that ascertains the exception was thrown in the underlying method as above?
No, junit can't tell the exception was thrown, since it gets eaten by the code being tested. For you to detect what happened here you would have to check what was written to the log. Replace the appender with something that holds onto what is written to it, then the test can verify what was written to it at the end of the test.
You can't catch the exception again which have been already consumed. The only way is to catch the exception with the test method as described below.
Annote the test method that is supposed to fail with #Test and use the expected parameter for the expected exception.
#Test(expected = NullPointerException.class)
public void shouldFailDueToCommandGatewayError() {
// something that throws NullPointerException
}
#Test(expected = NullPointerException.class)
This basically says:
If this test quits with a NullPointerException then everything is as expected. Otherwise this test will fail.
#Test(expected = NullPointerException.class)
has been mentioned already. This feature came wuth JUnit 4. Before that and if you want to do want to check more than just a particular type of exception being thrown, you can do something like this:
try {
doSometing("", "");
fail("exception expected");
}
catch(IllegalArgumentException iae) {
assertEquals("check message", "parameter a must not be empty", iae.getMessage());
assertNull("check non-existance of cause", iae.getCause());
}
try {
doSometing("someval", "");
fail("exception expected");
}
catch(IllegalArgumentException iae) {
assertEquals("check message", "parameter b must not be empty", iae.getMessage());
assertNull("check non-existance of cause", iae.getCause());
}
This is particular useful if the same type of exception is thrown and you want to ensure that the "correct" exception is thrown with a given combination of parameters.

Android unreported exception IOException error

I am new to android apps development. Recently,Im writing an application which able to show public ip based on Ipify. So far, i already:
Download the required jar file and put inside libs folder
I also compile file within gradle
Then i import required class it to my class
How to use Ipify, according to its website:
import org.ipify.Ipify;
public class HelloIP {
public static void main(String[] args) throws IOException {
System.out.println(Ipify.getPublicIp());
}
}
I write the following method to be invoked from another class:
public static String getPublicIp() throws IOException{
String ip = Ipify.getPublicIp();
return ip;
}
Another Class
//Get wifi
getWifiName wifiInfo = new getWifiName();
String myIP = wifiInfo.getPublicIp();
However, i keep getting:
Error:(52, 43) error: unreported exception IOException; must be caught
or declared to be thrown
I tried to modify the code and use the following try and catch, but still got the same error.
public static String getPublicIp() throws IOException{
String myip = Ipify.getPublicIp();
try{
return myip;
}
catch (IOException e){
System.out.println("General I/O exception: " + e.getMessage());
e.printStackTrace();
}
}
Im not too good in catch and throw exception, and already spent the whole day for this.I dont have idea anymore to fix this error..T.T
public static String getPublicIp() {
try{
return Ipify.getPublicIp();
}catch (IOException e){
System.out.println("General I/O exception: " + e.getMessage());
e.printStackTrace();
}
return null;
}
In case it didn't help, clean project in your IDE. You may have some data cached and it might be a reason.
Your problem is in another class! As you have declared the method getPublicIp() to throw IOException that class is afraid of receiving the Exception and therefor requests catching it.
In Java you have two types of Exceptions. Checked and unchecked. Checked Exceptions must be caught.
In Java Exceptions are used for marking unexpected situations. For example parsing non-numeric String to a number (NumberFormatException) or calling a method on a null reference (NullPointerException). You can catch them in many ways.
Unchecked Exceptions are those which extend RunTimeException. They are used for marking unexpected states usually caused by user's input. They shouldn't cause harm and should be worked out with business logic. You don't have to catch them, but sometimes you should.
On the other hand there are Checked Exceptions which mark dangerous situations. For example the application being unable to open a file. As those situations are found dangerous, you must catch them.
try{
//some code
} catch (NumberFormatException e1) {
e.printStackTrace() //very important - handles the Exception but prints the information!
} catch (NullPointerException e2) {
e.printStackTrace();
}
or using the fact, that they all extend Exception:
try {
//somecode
} catch (Exception e) {
e.printStackTrace;
};
or since Java 7:
try {
//somecode
} catch (NullPointerException | NumberFormatException e) {
e.printStackTrace;
};

Adding conditions to my method in order to reduce user error

I have attempted to add conditions inside my add method so when the user makes a mistake like entering a new appointment with values that already exist the program will produce a error message
here is my add method
public void add(Appointment a){
appointmentList.add(a);
}
my question is how would I do get the program to produce an error message ?
I have already attempt to use try and catch.
you can use throw to throw a specific exception and handle it later to preview an error message to user.
for Example :
public void add(Appointment a){
if(a==null){
throw new IllegalArgumentException("appointement can't be null");
}
appointmentList.add(a);
}
You can also create a specific AppointementAlreadyExistException by extending RunTimeException and throw it when it is needed :
public class AppointementAlreadyExistException extends RuntimeException{
// constructors
}
and use it as follows :
public void add(Appointment a){
if(a==null){
throw new IllegalArgumentException("appointement can't be null");
}
//equals in appointement must be overrided to give correct behaviour
if(appointmentList!=null && appointmentList.contains(a)){
throw new AppointementAlreadyExistException();
}
appointmentList.add(a);
}
Now when you call this method :
// let's assume we have an Appointement a
try {
add(a)
}catch(AppointementAlreadyExistException ex){
//display the information to the user saying that appointment
}

Using specific try catch, error overrides

This is my Exception:
public class MyException extends Exception {
private String errorCode="Unknown_Exception";
public MyException(String message, String errorCode){
super(message);
this.errorCode=errorCode;
}
public String getErrorCode(){
return this.errorCode;
}
}
Now immagine the next scenario, the code is way too long to paste here:
1 I got a Presentation class made in Swing in Presentation package
2 In package calculations I made simple operations with few numbers from received database fields
3 In package connections I got the database connections
Trouble comes here:
-In presentation layer I catch all errors, like this:
try {
//here is a method called updateCombo() wich throws:
//throw new MyException(e.getMessage(),"ERROR_UPDATING_COMBO_BOX");
} catch (MyException ex) {
try {
//Here we process error code, if error is not defined, uses default errors.
processCode(ex);
} catch (MyException ex1) {
Logger.getLogger(Presentacion.class.getName()).log(Level.SEVERE, null, ex1);
}
}
processCode is a simple list with cases, like this:
private void processCode(MyException e) throws MyException {
switch (e.getErrorCode()) {
case "ERROR_UPDATING_COMBO_BOX":
lblErrorText.setText("Error updating combo.");
throw e;
case "ERROR_SELECTING_PRIMARY_KEY":
lblErrorText.setText("Error selecting PK");
throw e;
case "ERROR_OPENING_CONNECTION":
lblErrorText.setText("Error opening connection.");
throw e;
default:
lblErrorText.setText("Excepcion not defined: "+ e.getMessage());
e.printStackTrace();
}
This is the scenario, the connection fails in 3rd package and leads to this:
throw new MyException(e.getMessage(),"ERROR_OPENING_CONNECTION");
As I said, the error is thrown to the upper layer with throws clause in method header, this beeing 2nd package.
2nd package also throws a new exception to Presentation, because of failing connection:
throw new MyException(e.getMessage(),"ERROR_SELECTING_PRIMARY_KEY");
Presentation methods also throw this exception becase 2nd layer failed:
throw new MyException(e.getMessage(),"ERROR_UPDATING_COMBO_BOX");
The main problem:
Using debug i found out that the program does what it has to do. It gets to the connection layer and does this successfully:
throw new MyException(e.getMessage(),"ERROR_OPENING_CONNECTION");
But, in 2nd layer, calculations, if connection fails it throws a new exception:
throw new MyException(e.getMessage(),"ERROR_SELECTING_PRIMARY_KEY");
This is the problem:
throw new
throwing new exception overrides ERROR_OPENING_CONNECTION with ERROR_SELECTING_PRIMARY_KEY. When it gets to presentation due to its "throw new" overrides ERROR_SELECTING_PRIMARY_KEY with ERROR_UPDATING_COMBO_BOX, resulting in the final error shown in the screen:
lblErrorText.setText("Error updating combo.");
Is there any way to return to presentation once first error is caught without overriding by next errors?
Maybe I misunderstood the concept but I want to catch all possible errors because:
-If connection is OK but method in 2nd layer fails it should throw ERROR_SELECTING_PRIMARY_KEY.
-If 2nd layer (calculations) does it OK but there is error in presentation it should lead to ERROR_UPDATING_COMBO_BOX.
You can use e.getCause() which will return a Throwable and check if this cause belongs to MyException. In case it is, you can check the e.getCause() again recursively until you obtain the deepest error code in the stacktrace and perform the validation for this exception.
Here's an example:
public MyException getDeepestException(MyException e) {
Throwable t = e.getCause();
if (t instanceof MyException) {
return getDeepestException((MyException)t);
}
return e;
}
As pointed out by #RealSkeptic, in order to use this approach, you will need to add an additional constructor to your custom exception:
public MyException(String message, Throwable cause, String errorCode){
super(message, cause);
this.errorCode = errorCode;
}
And when throwing your exception, call the proper constructor:
try {
//...
} catch (SomeException e) {
throw new MyException(<a proper message should be here>, e, "ERROR_SELECTING_PRIMARY_KEY");
}
If I understand you correctly, if the exception caught by one package happens to be a MyException, you want the original MyException to be passed up, otherwise (if the exception is some other type of Exception) you want to create a new MyException.
In this case, you should have two catch clauses.
try {
// Whatever you do in the try clause
} catch ( MyException myEx ) {
throw myEx;
} catch ( Exception e ) {
throw new MyException(e.getMessage(),"ERROR_SELECTING_PRIMARY_KEY");
}

Throwing and logging Exceptions, a better way

Ultimately, i'd like to
if (badThingsHappen) {
log the issue
throw exception with description
}
The obvious redundancy here is that often exception description and the message to be logged is (often) the same.
This looks needlessly verbose
if (badThingsHappen) {
logger.error("oh no! not again!");
throw new AppException("oh no! not again!");
}
Declaring temporary String feels wrong
if (badThingsHappen) {
String m = "oh no! not again!";
logger.error(m);
throw new AppException(m);
}
Is it ok to have Exception's constructor handle the logging? Is there a better (cleaner) way?
You could use a utility method:
public class AppException extends Exception {
public static AppException logAndThrow(Logger logger, String message) throws AppException {
AppException e = new AppException(message);
// log the stack trace as well
logger.error(message, e);
throw e;
}
}
and the use it:
if (badThingsHappen) {
AppException.logAndThrow(logger, "oh no! not again!");
}
I usually prefer to log exceptions when I catch them, rather then when I throw them.
This cleans up the logs quite a bit more, and also lets the "client" code handle the exception and information output much more precisely, since the information you want to associate with the exception when logging can be dependent of context.
If you do want to log as soon as it happens, I would build the exception and log it before throwing, something like:
if(badthingshappen){
Exception e = new Exception("holy $%##");
logger.log(e);
throw e;
}
A bit verbose yes... but this is java.
Typically when working with Exceptions and logging requirements I include logging support in the Exceptions.
Exceptions typically inherit from a Base Exception class in our project and it has hooks for logging log4j or other logging utilities.
class Problem extends java.lang.Exception {
private boolean debug=false;
public Problem(String message) {
if(debug) {
logging.exception(message);
/* Maybe a stack trace? */
}
}
}
I just wrote an error-logging method myself, today (this is used to log errors if they occur in a listener method, so it's also logging the method in which the error occurred and the object in which the listener is implemented to help tracking):
protected void listenerError(String listenerMethodName, Object listener,
RuntimeException e) {
logger.error("Exception while calling " + listenerMethodName
+ " on object " + listener, e);
throw e;
}
I wrote it in the class in question (or the base class, to be exact), because you probably want to use the logger in that class (and all subclasses). Another option would be to create a utility method in a utility class (I would not write an Exception class for it), and provide the logger as parameter:
class ExceptionUtil {
public static error(Exception e, Logger logger) {
logger.error(e);
throw e;
}
}
You can, of course, provide the method and object as params for this method (or an overloaded version of it), as necessary.

Categories

Resources