4

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; 
}
Andreas Dolk
  • 113,398
  • 19
  • 180
  • 268
Sridevi Laks
  • 187
  • 2
  • 7
  • 19
  • 1
    show some code (around the exception chain). If you are wrapping your exceptions and the wrapped exceptions are not retaining the message, then you would get a null. – rajasaur Jun 28 '11 at 08:38
  • Yes, I wrap the exception, but I return the same object. Please see the code below. – Sridevi Laks Jun 28 '11 at 08:43
  • does `exception.getCause().getMessage()` hold your information? – oliholz Jun 28 '11 at 08:44
  • 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; } – Sridevi Laks Jun 28 '11 at 08:49
  • Could you show some code? including the exception class being used? Is it a class you created or a standard java exception? – maasg Jun 28 '11 at 08:52
  • yes exception.getCause().getMessage() hold info "dbExe.getCause().getMessage()"= "Connection is closed." – Sridevi Laks Jun 28 '11 at 08:53
  • could you show the code of the DBException(...) constructor? (if yours) – maasg Jun 28 '11 at 09:07
  • It is [questionable whether you should log the exception message](http://stackoverflow.com/questions/7320080/should-you-report-the-message-text-of-exceptions) if the exception does not indicate a bug. And if it does indicate a bug, you *ought* to print the stack trace. – Raedwald Mar 24 '16 at 17:26

5 Answers5

4

You can print out the full stack trace:

 exception.printStackTrace();
Giann
  • 3,142
  • 3
  • 23
  • 33
0

Try:

            switch (chTraceLevel) { 
                case Con.IN: 
                case Con.S: 
                    String msg = exSuperException.getCause().getMessage();
                    // LOG msg
            } 
oliholz
  • 7,447
  • 2
  • 43
  • 82
  • 1
    yes Exception.getCause().getMessage(); this is having the message, why am not getting in Exception.getMessage()? – Sridevi Laks Jun 28 '11 at 09:01
  • @SrideviLaks, you'll find the answer here: https://stackoverflow.com/a/9017846/7022062 basically exception can be wrapped (and more than once). Provided link allows you to unwrap it to the root cause of the problem... – Dmitry Shevkoplyas Oct 13 '17 at 14:13
0

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
Andreas Dolk
  • 113,398
  • 19
  • 180
  • 268
  • Nope, I am returning, what my Exception .getMessage is giving. – Sridevi Laks Jun 28 '11 at 09:01
  • @Sridevi Laks - your're returning what `dbExe.getMessage()` is giving and *that* exception does not carry a message. Have a look at my edit and oliholz's suggestion – Andreas Dolk Jun 28 '11 at 09:05
  • Thanks all, it s working. I have to invoke the constructoror as DBException dbExe = new DBException(sqlExe.getMessage(), sqlExe); instead of DBException dbExe = new DBException(sqlExe); – Sridevi Laks Jun 28 '11 at 09:08
  • @Sridevi Laks - please have a look at the SO FAQ and use the *upvote* / *downvote* and the *accept* buttons in case you like/don't like or accept an answer. That's the SO way to say "thanks" :) – Andreas Dolk Jun 28 '11 at 09:13
  • @Andreas_D re:" your DBException is created without a message, so dbExe.getMessage() will return null." (copy of comment below): That's not quite correct. The constructor Throwable(Throwable cause) will update the message with cause.toString(). cause.toString will at least return the name of the throwable class. We are assuming that in this case DBException(Exception ex) calls super(ex), which might not be the case. Hence my request to see that code as well. – maasg Jun 28 '11 at 09:24
  • @maasg - I've looked at the [implementation](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/Throwable.java#Throwable.toString%28%29) and can't find a call to the cause's getMessage().... – Andreas Dolk Jun 28 '11 at 09:54
  • @Andreas_D I looked here: http://goo.gl/95S31 Here's the execution chain (only copied the relevant bits): Throwable(Throwable cause) { ... detailMessage = (cause==null ? null : cause.toString()); ... } String toString() { ... String message = getLocalizedMessage(); ...} String getLocalizedMessage() { return getMessage(); } – maasg Jun 28 '11 at 10:11
  • @Andreas_D I think the issue is in the specific impl of the DBException constructor. – maasg Jun 28 '11 at 10:37
  • @maasg - ah, ok, the constructor already populates the `detailedMessage` field. – Andreas Dolk Jun 28 '11 at 10:40
0

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.

Andrzej Doyle
  • 102,507
  • 33
  • 189
  • 228
  • 1
    that's not quite correct. The constructor Throwable(Throwable cause) will update the message with cause.toString(). cause.toString will *at least* return the name of the throwable class. We are assuming that in this case DBException(Exception ex) calls super(ex), which might not be the case. Hence my request to see that code as well. – maasg Jun 28 '11 at 09:15
  • @maasg Very good point, I hadn't explicitly thought about it but it does depend entirely on what the `DBException` constructor does with that single argument. In fact I was assuming that it *doesn't* call `super(ex)`, just because that's the way the cultures I've worked in have always done exceptions (i.e. if you don't specify a message, presumably you don't want one so it's better for it to be `null` than the superclass' behaviour - though that's a different argument). – Andrzej Doyle Jun 28 '11 at 09:19
  • @ Andrzej Doyle - have used the vote for thanking, thanks for the insights. @ maasg - yes even I have the same thing in mind, in this case my getMessage should have the thrwable class name - but for me it is giving null, my DBException constrcutor public DBException(Throwable throwable) { super(throwable); } – Sridevi Laks Jun 28 '11 at 11:23
  • have another point to say here I create a new custommized exception DBException dx= new DBException(sqlEX); and pass my sql exception in it, but when the sql object sits in the throwable, while debugging, i get only the following params. exception - java.sql.SQLException: detailedDesceription - Connection is closed. Connection is closed. next - null sql state - null Stack trace - null vendor code 0 – Sridevi Laks Jun 28 '11 at 11:51
  • @Sridevi - I'm not sure what your point is there. Have you tried explicitly providing a message in the constructor though? This **will** make `getMessage()` return whatever you want. – Andrzej Doyle Jun 28 '11 at 11:55
  • yes, wen I provide the error message in the constructor, I get the error details. But if i don provide, and call only the one arg constructor calling the super(Throwable) , I should atleast get the Class Name when I call getMessage right.... I get a null only. As per this detailMessage = (cause==null ? null : cause.toString()); - the getMessage should return me the class name right? – Sridevi Laks Jun 28 '11 at 12:03
  • @sridevi: Yes, if the constructor you're talking about defers all the way up to the similar `Throwable` constructor. But it really depends on what `DBException`'s superclass is, and what *its* constructors do. If you're getting `null` from `getMessage()`, then obviously the constructor isn't deferring right up the chain. – Andrzej Doyle Jun 28 '11 at 14:37
  • Thanks a lot Andrzej and maasg (Am yet to get enough reputations to vote for your answers) , your help and discussion gave me more insights and have figured out the problem. There is a DBException extends a SuperException which is another customized class that extends the Exception. we have a getMessage in our SuperException and only SuperException(String strSystemMessage, Throwable nestedException) sets the actual message in SuperException, hence using this two arg constructor , gives me the error message. – Sridevi Laks Jun 29 '11 at 06:59
0

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.

maasg
  • 37,100
  • 11
  • 88
  • 115