I am debugging my application, I have added exception.getMessage() in logger, but exception.getMessage() prints Null, but , when I debug I could see my Exception String in exception object's detailed message, how can I get the exception message that is coming as detailed message? Note - getMessage returns Null.
P.S - I am not using PrintStackTrace or stacktraceElement, my logger should return the string from exception.getmessage(), that is the requirement.
From comment:
DBException dbExe = new DBException(sqlExe);
DBException objDbEx = (DBException) ExceptionUtil.populateSuperException(dbExe, strTraceMesg, ConstantsIF.SEVERE_LEVEL, false, null, null, null);
throw objDbEx;
public static SuperException populateSuperException (SuperException exSuperException, String strTraceMsg, char chTraceLevel, ) {
if (strTraceMsg != null) {
switch (chTraceLevel) {
case Con.IN:
case Con.S:
//log
}
}
return exSuperException;
}
You can print out the full stack trace:
exception.printStackTrace();
Try:
switch (chTraceLevel) {
case Con.IN:
case Con.S:
String msg = exSuperException.getCause().getMessage();
// LOG msg
}
That is pretty strange. The message that you see with debugging is usually created through Throwable#toString and that calls getLocalizedMessage() internally.
So if the exception does have a message, then it should be returned through getMessage() and be part of the toString() result.
An exception/throwable does not need to have a detailed message. Please double check, if you've created your exceptions with a message.
After making your code readable: your DBException is created without a message, so dbExe.getMessage() will return null. Either look the the cause or add a message while creating:
DBException dbExe = new DBException(sqlExe.toString(), sqlExe);// just an example
You are creating your exception object without any message (you're only specifying the chained exception):
DBException dbExe = new DBException(sqlExe);
hence calling dbExe.getMessage() may (correctly) return null (with the details depending on what your constructor does in this situation). The reason you can see a message in the stacktrace, incidentally, is because the generation of the stacktrace recurses to the underlying exception, and sqlExe.getMessage() will be what you're seeing.
The solution is simply to provide a message as well as the underlying exception when constructing your exception. The general wisdom is that this should reflect the level at which the exception is thrown, so perhaps something like the following:
DBException dbExe = new DBException("Unable to persist widgets", sqlExe);
If your unspecified "requirement about the existing code flow" means that you need the actual database exception to be the message in dbExe, you could construct this like the following:
DBException dbExe = new DBException(sqlExe.getMessage(), sqlExe);
though on the whole that duplication of the message isn't very nice, and the former option is the more "correct" one.
From the discussion in the comments, it is my conclusion that the root cause of your problem is in the implementation of the DBException constructor or its hierarchy. For a valid reason or not, I think it's not calling the exception class hierarchy (e.g. super(reason);) and therefore, you are not getting the expected behaviour from the call to dbException.getMessage(). Note that a call to new Exception(anotherException) will always populate the field backing the getMessage() call in the base Throwable class through this call chain: (only relevant bits shown)
public Throwable(Throwable cause) {
...
detailMessage = (cause==null ? null : cause.toString());
...
}
public String toString() {
...
String message = getLocalizedMessage();
...
}
public String getLocalizedMessage() {
return getMessage();
}
Check the implementation of DBException as the root cause of the problem discussed.
Related
With a code like this
public static void main(String[] args) {
Exception one = new Exception("my cause");
System.out.println("A) " + one.getMessage());
System.out.println();
Exception two = new Exception(one);
System.out.println("B) " + two.getMessage());
System.out.println("C) " + two.getCause().getMessage());
System.out.println();
Exception three = new Exception("my message", one);
System.out.println("D) " + three.getMessage());
System.out.println("E) " + three.getCause().getMessage());
System.out.println();
Exception fourth = new Exception(null, one);
System.out.println("F) " + fourth.getMessage());
System.out.println("G) " + fourth.getCause().getMessage());
}
The output is this one
A) my cause
B) java.lang.Exception: my cause
C) my cause
D) my message
E) my cause
F) null
G) my cause
See the difference between B and F
In both cases I did NOT provided a message, but the difference is that in the B case the null value is not forced.
It seems that for the B case, when a message is not specified, the getMessage() method provides the format
className: cause.getMessage()
But I would except to have a null value (as is for the F case).
Is there a way to get null value (like F) if I call the getMessage on an Exception that has been created providing only the cause and not the message?
Take a look at Exception's JavaDoc. For the constructor that takes only a Throwable:
Constructs a new exception with the specified cause and a detail message of (cause==null ? null : cause.toString()) (which typically contains the class and detail message of cause). This constructor is useful for exceptions that are little more than wrappers for other throwables (for example, PrivilegedActionException).
So, in your B case, since the cause is not null, you get the value of cause.toString() as the container exception's message.
If that constructor was used to create the exception, then by the time you catch the exception, it's too late - it already has a detail message as specified above. You can't get the "null" as the detail message is not null. You can compare it to the cause's toString() and deduce that it should have been null, but that's a kludge and theoretically, the cause's message could change over time and be different at the time of the catch.
Basing on #RealSkeptic reply I created a method like this
public static String getMessageOrNull(Throwable t) {
String message = t.getMessage();
if (t.getCause() != null && message.equals(t.getCause().toString())) {
message = null;
}
return message;
}
It may not be the best approach but for my case works just fine.
You could simply build it the same way, hiding it in a static method :
public static Exception getException(Throwable cause){
return new Exception(null, cause);
}
Or you define your own class that will use the Exception(String, Throwable) constructor like
public MyExceptoin extends Exception{
public MyException(Throwable cause){
super(null, cause);
}
}
This would be simpler to use later.
I've some modules, each containing some models what I want to parse from persisted file(s).
When I read a file I don't know which module will be able to parse it, that's why I try to parse it with my first module's parser. If that fails I try with the parser of the second module and continue that until I've tried all my parsers.
The parsers can give back information in form of multiple exceptions (different subtypes of Exception class) or the parsed model object (different subtypes of a ModelBase class).
If none of the parsers succeed I want to wrap all of given exceptions into one big Exception, throw it and catch it somewhere in my application code (in form of a new big exception), where I can handle the problem (e.g. show all the parsing problems and stacktraces to the user, handle them somehow etc.).
My pseudocode:
ModelBase getModelOrBigException(File file)
throws MyBigException {
List<Exception> exceptions = new ArrayList<>();
for (Module module : myModules){
try {
ModelBase model = module.parse(file);
return model;
}
catch (ParsingException1 p1) { exceptions.add(p1); }
catch (ParsingException2 p2) { exceptions.add(p2); }
}
throw new MyBigException(exceptions);
}
I want to call the code
void openFilesHandler(){
//... selecting file
try {
process(getModelOrBigException(file));
} catch (MyBigException e) {
// process the sub-exceptions or show them to user or print stacktraces of all sub-exceptions or show sub-exceptions by type etc
}
}
Obviously if I catch MyBigException I won't be able to call methods like getStackTrace(), getMessage(), getLocalizedMessage() on them by default, only if I implement my exception class similar to this:
class MyBigException extends Exception {
public MyBigException(Exception e1, Exception e2, ..., Exception eN){
super(e1, e2, ..., eN); // This is not possible, only one argument is acceptable
}
}
or to this:
class MyBigException extends Exception {
List<Exception> exceptions = new ArrayList<>();
public MyBigException(List<Exception> exceptions){
super(exceptions); // This is not possible, list or array of exceptions is not allowed here
}
}
Questions:
How should I create a new type of Exception, which can store multiple exceptions with support of the original Exception class's methods?
When I do this:
myBigException.printStackTrace();
or this:
myBigException.getMessage();
I want to print/get all stacktraces of all stored exceptions.
Should I pass all given exceptions to super() method?
Is there any better way to do the parsing solution better than the solution above?
I want to print/get all stacktraces of all stored exceptions. Should I
pass all given exceptions to super() method?
If you wanted to print all stacktraces or exception messages, you are almost there and you need add few more bits as explained below:
(1) Inside MyBigException, create a constructor MyBigException(List<Exception> exceptions, String exeptionMessage) and call super(exeptionMessage);
(2) override printStackTrace() in your MyBigException and iterateover the List<Exception> and call printStackTrace() on each exception object.
You can refer the below code on the same:
MyBigException class:
public class MyBigException extends Exception {
private List<Exception> exceptions = new ArrayList<>();
public MyBigException(List<Exception> exceptions, String exeptionMessages){
//call super and pass message
super(exeptionMessages);
this.exceptions = exceptions;
}
public void printStackTrace() {
for(Exception exception : exceptions) {
exception.printStackTrace();
}
}
}
getModelOrBigException() code:
ModelBase getModelOrBigException(File file)
throws MyBigException {
List<Exception> exceptions = new ArrayList<>();
//Capture exception messages as well using StringBuilder
StringBuilder exceptioMessages = new StringBuilder();
for (Module module : myModules){
try {
ModelBase model = module.parse(file);
return model;
}
catch (ParsingException1 p1) {
exceptions.add(p1);
exceptioMessages.append("YOUR MESSAGE FOR ParsingException1;");
}
catch (ParsingException2 p2) {
exceptions.add(p2);
exceptioMessages.append("YOUR MESSAGE FOR ParsingException2;");
}
}
throw new MyBigException(exceptions, exceptioMessages.toString());
}
Two options come to my mind.
suppressing the given exceptions using addSuppressed. You can then retrieve it again later using getSuppressed(). This is also the mechanism which is used on try-with-resources-statements throwing exceptions. This way the stack trace of your myBigException also shows the suppressed ones automatically.
add an accessor method to your exception classes internal list so you can access it from outside, e.g. getExceptions(). Here however you need to handle the stack trace of each exception yourself. You can overwrite the printStackTrace(*) methods, but that seems overhead to me.
It mainly depends on what you want to achieve (or what is more appropriate) and how you want to access the exceptions later on.
You may also want to supply your own printStackTraces() method in the second case or overwrite the getMessage()-method in both cases to supply a message that is more appropriate.
You can't have many exceptions as the cause of your BigException. One exception is thrown and it goes up the stack until you handle it. You could add it to a causality relation chain, and that's why Exception's constructor accepts another exception as the cause of this exception.
But in your case, you are throwing the BigException after many parsing exceptions have been thrown and already handled (by adding them to a list).
So your first exception in the chain is actually BigException. If I were you, I would just have a getter for the list of parsing exceptions and work with that list, i.e. to inform the user, log the list etc.
I've a method similar to the one bellow, where I want to return a private variable of one class only and only if, some conditions are verified. Otherwise I want to exit the method without return anything. I've tried something like the code bellow but I'm afraid that returning null is not a good idea. Are there any way to exit a method like the break keyword works for cycles?
private Classxpto classxpto;
public Classxpto getclassxpto(String abc, Date asd){
String curr_abc= classxpto.getabc();
Date curr_asd= classxpto.getasd();
if("my conditions"){
//dont return classxpto
return null;
}else if("my other conditions"){
classxpto.setabc(abc);
classxpto.setasd(asd);
return classxpto;
}
return null;
}
You can either return null (or some default Classxpto instance) or throw an exception. Throwing an exception is the only way to exit a method having a non-void return type without returning anything.
You cannot return "nothing" from a method unless it is declared as a void method. (And in that case, you can only return "nothing"!)
The Java Language Specification says this in ยง14.17:
A return statement with an Expression must be contained in one of the following, or a compile-time error occurs:
A method that is declared to return a value
....
If you have no value to return, then your choices are either to pick some value that means (to your application) "no value", or throw an exception.
The value null is often used to signify "no value", but you can use other things ... depending on the declared return type.
Throwing an exception would a bad whay to deal with this, unless "no result" is truly an exceptional outcome. Using exceptions and exception handling for normal flow control is a considered to be bad design in Java, and is liable to lead to serious performance problems.
It is also theoretically possible to terminate the JVM by calling System.exit(...), or write the method so that it runs forever or goes to sleep forever. However these are most likely "undesirable" behaviours.
You can always throw the Exception
if(conditionNotMet){
throw new YourCustomException();
}
then Handle it in whichever way you want !!!!
A method either return nothing (void), or something (including null), but can throw an Exception.
You have to think about how clients of the class will use the method. An exception really mean that the no return case should not occur in normal conditions.
Assuming the method is in a Foo class:
public class Foo {
private ClassXPto classXPto;
public ClassXPto getClassXPto() {...}
// other Foo stuff
}
In the client code:
Returning null
Foo foo; // initialized somewhere
ClassXPto x = foo.getClassXPto("abc", new Date());
if (x != null) {
// do something with x
}
Throwing/catching an exception
Foo foo; // initialized somewhere
try {
ClassXPto x = foo.getClassXPto("abc", new Date());
// do something with x
}
catch (WhatEverExceptionYouChoose e) {
// process the exception
}
Propagating an exception
Foo foo; // initialized somewhere
ClassXPto x = foo.getClassXPto("abc", new Date());
// do something with x. This point will be reached only
// if there is no exception thrown by getClassXPto()
If your method is designed in such a way that the return parameter is optional, you could use the new Optional mechanisms in Java 8.
Instead of returning null you would return Optional.empty().
For more information visit https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html
I have a method:
public void SomeDataMethod() throws BadDataException {
try {
// do something
} catch(IOException e) {
throw new BadDataException("Bad data",e);
} finally {
// do something regardless of above
}
}
And now for example some code will invoke this method, and I want to see all failures which happened in this method,
so how can I do it by using initCause()? Or maybe is there any other way to do this? And if I use initCause():
1) will I get all exceptions which were catch or the last one?
2) and What form do I get them / it?**
When you call an Excepion Constructor with the throwable attached, like you have the e as part of the new BadDataException("Bad data",e); then the result is effectively the same as:
BadDataException bde = new BadDataException("Bad data");
bde.initCause(e);
This is to keep compatibility with earlier Java versions which did not have the initCause concept.
Not all exceptions support adding the cause as part of the constructor, and for those exceptions you can initCause it.
note that you can only initCause an exception once, and initializing it with 'null' cannot later be changed:
BadDataException bde = new BadDataException("Bad data", null);
// this will fail.....
bde.initCause(e);
To get the cause of an exception, you call... getCause(). In this case, this method will return the IOException that you wrapped inside your BadDataException. It can't return more that one exception, since you can only wrap one exception.
I am trying to implement some validation on Enum types in wink for jaxb/jackson.
I have an enum which takes some values. I want to allow a null, i.e. not set it in xml/json, but I also want to check for invalid values and give an error.
I found that by default jaxb/wink just returns a null if I supply a value not in the enum, so I tried using a setter to allow validation of the input. Using Level.valueOf(newLevel) to try and convert the supplied string to a value throws an exception and gives me a stack trace and http error.
This is ok, but what I really want is a custom exception so that I can have some control over the marshalling of the error response. I tried throwing one but it gets swallowed by (I think) wink.
enum Level {BASIC, ADVANCED};
#XmlAttribute
public void setLevel(String newLevel) throws MyException {
if (newNodeLevel != null) {
try {
this.level = Level.valueOf(newLevel);
} catch (IllegalArgumentException e) {
throw new MyException("level invalid");
}
}
}
Other than using a Throwable rather than an Exception, is there any way I can achieve this?