In the logging part of the project I working for, I try to optimize the error messages that are shown in log management. Logging error messages is coded like this:
String errorMessage =" Problem with server "+"\n"+t.getMessage();
_logger.fatal(errorMessage);
Where t is a Throwable object and _logger is a Logger object, which is related to the log4j framework.
What I wonder is, what changes if I use _logger.fatal(errorMessage, t); instead of _logger.fatal(errorMessage);? If there is a major difference between them, Which one will be better to use?
Edit: I've just realised I copied "fatal" example instead of "error". However my question is same for fatal, too.
Practically all Java logging framework (alas, we have plenty of those...) support putting a Throwable as the last parameter.
This will result in a stack trace being logged, which can be extremely useful in diagnosing and fixing the problem.
I'd only ever not give the exception to the logger if the cause of the exception is really well established and printing the exception is just unnecessary noise. For example here:
try {
int port = Integer.parseInt(input);
// do something with the port
} catch (NumberFormatException e) {
logger.error("'{}' is not a valid port number: {}", input, e.toString);
}
Another case is when the exception is being re-thrown (and something else will eventually log it with more detail).
But not with a "Problem with server" (and at FATAL level no less). That looks like you want to get as much info as you can get.
Also note that in those cases, e.toString() is usually better than e.getMessage() because it also includes the name of the exception in addition to its message (which may be empty).
Related
I'm in the process of updating from picocli 3.9.6 to 4.2.0, and I'm running into an issue when replacing old deprecated calls with the new versions.
In my original version, I had a code block like this:
try {
return commandLine.parseWithHandlers(
new RunLast().useOut(ps),
new ExceptionHandler(),
args);
}
catch(Exception e) {
// handle exceptions
}
The ExceptionHandler handles both parameter and execution exceptions -- both are rethrown, but parameter exceptions get the help text added to the exception text. The catch would get hit in cases where, e.g., a command was given bad args. The catch would ensure the error was printed in the UI.
I attempted to update it like this:
try {
commandLine.setOut(pw);
ExceptionHandler handler = new ExceptionHandler();
commandLine.setExecutionExceptionHandler(handler);
commandLine.setParameterExceptionHandler(handler);
commandLine.execute(args);
return commandLine.getExecutionResult();
}
catch(Exception e) {
// handle exceptions
}
With this new version, exceptions are thrown as before, but they are no longer caught by the catch block after being rethrown by the ExceptionHandler. How can I catch these exceptions?
One of the changes in picocli 4.x is the new execution framework. The user manual has a section on migration that may be useful.
By design, the CommandLine::execute method never throws an exception. So there is no need to surround the call to CommandLine::execute with a try/catch block (unless you need to catch an Error or Throwable).
Instead, you can optionally specify custom exception handlers, like you already do in your example. These exception handlers is where you can show an error message to the users. (Perhaps a combination of what was in the previous ExceptionHandler and the logic that previously was in the catch block.)
The ParameterExceptionHandler is invoked when the user provided invalid input. The default handler shows an error message, may suggest alternative spellings for options or subcommands that look like a typo, and finally displays the usage help message. The Handling Errors section of the user manual has an example ShortErrorMessageHandler that may be useful when the usage help message is so long that it obscures the error message.
The ExecutionExceptionHandler is invoked when the business logic throws an exception. The default handler just rethrows the exception, which results in a stack trace being printed. The Business Logic Exceptions section of the user manual shows an alternative.
It sounds like you need a custom ExecutionExceptionHandler that prints a stack trace followed by the usage help message.
I am using the jSerialComm library to communicate to and from the SerialPort. I have written a SerialDataListener to read the bytes with an overridden serialEvent method that looks like this:
#Override
public void serialEvent(SerialPortEvent event) {
if (event.getEventType() != SerialPort.LISTENING_EVENT_DATA_AVAILABLE) return;
int numBytesAvailable = serialPort.bytesAvailable();
if (numBytesAvailable < 0) {
logger.error("Port is not open.. returning without any action");
return;
}
byte[] newData = new byte[numBytesAvailable];
int readData = serialPort.readBytes(newData, numBytesAvailable);
for (int i = 0; i < numBytesAvailable; i++) {
byte b = newData[i];
logger.info("Starting new response");
response = new Response();
response.addByte(b);
}
}
Now, if I do receive data and the subsequent code gets into a NUllPointerException somehow (one example being that the response's constructor is invoked and throws an NPE), then the SerialPort has been programmed inside the library's SerialPort class to
stop listening and
Swallow the exception
As a consequence of 1 and 2, no more data arriving on the SerialPort can be processed. There is neither an exposed API to see if the listener is stopped and restart it. I can neither take any action like reopening the SerialPort.
Here is that piece of code:
//Line 895 of the class SerialPort) (from dependency: com.fazecast:jSerialComm:1.3.11).
while (isListening && isOpened) { try { waitForSerialEvent(); } catch (NullPointerException e) { isListening = false; } }
Here are the questions:
Why was the exception swallowed and listening stopped inside the library? Are there any design reasons?
The SerialPort class itself is final and hence writing my own implementation of the class to replace the swallow is out of question. How do I proceed? Apart from this issue, jSerialComm appears to satisfy most other use cases decently well, so I may not migrate from it anytime soon.
One way is to catch it myself and do the handling. But I do not want to do it unless the answer for Q1 is clear. I have tried to investigate but not found any practical reasons for disabling the listening and not announcing the exception.
Why just a NPE, other exceptions could arise too. So then at least, I will have to handle the exceptions myself. Is this approach of my own handlers correct then?
TIA
Rahul
1) Why was the exception swallowed and listening stopped inside the library? Are there any design reasons?
You would need to ask the author of the code.
However, it does seem to be intentional, since the waitForSerialEvent is declared as throws NullPointerException.
If I were you, I would dig deeper into where the NPEs are thrown and why. Modify the code to print a stacktrace instead of just squashing the exception entirely. It could be a "hack" workaround, or there could be a legitimate reason for doing this.
If we make the assumption that the client's listener code could throw an NPE, then in my view it is a mistake for the event thread to assume that all NPEs can be squashed.
But looking at the code, I can also see places where NPE's are being thrown deliberately to (apparently) signal there is an error; e.g. in the read methods in SerialPortInputStream. So it is not clear to me that the NPEs should be squashed at all.
2) The SerialPort class itself is final and hence writing my own implementation of the class to replace the swallow is out of question. How do I proceed?
The code is on GitHub, so you could fork the repository, develop a patch and submit a pull request.
4) Why just a NPE, other exceptions could arise too. So then at least, I will have to handle the exceptions myself. Is this approach of my own handlers correct then?
Good question.
But really, all of these questions are best addressed to the author of the code. He does seem to respond to questions posted as issues ... if they are pertinent.
By all means I know the following is not possible, but it is occurring in one of our production environments:
SETUP
ESAPI 2.01
Main servlet filter setting and removing a current request thread local object:
try {
ESAPI.httpUtilities().setCurrentHTTP(request, response);
// filter logic ...
} catch (Exception e) {
LOG.error(Logger.SECURITY_FAILURE, "Error in ESAPI "
+ "security filter: " + e.getMessage(), e);
request.setAttribute("message", e.getMessage());
} finally {
ESAPI.clearCurrent();
}
all requests pass through this filter, and ESAPI.currentRequest() is used throughout the system.
Path A (http://server/path_a/)
goes through until it reaches method_a, this method is not accessible from path_b
Path B (http://server/path_b)
goes through until it reaches method_b, not accessible from path_a
Both of these paths go through the servlet filter (mapping "/*")
One of our error mails that I received suggests that path_a is throwing an error, which in turn initiates the error mail, in the mail code, the current request (via ESAPI.currentRequest()) is enumerated for request info.
PROBLEM
In the error mail, request info from path_a correlates with stacktrace info from method_b, to me this seems impossible as both run in separate threads.
QUESTION
How is this possible? I cannot re-create this locally, are their certain precautions I have to take other than setting and clearing the ThreadLocal? Can this be a problem with tomcat setup? I'm lost.
PS: code from the question has been simplified as the code base is to large for an example
Reading ESAPI code https://code.google.com/p/owasp-esapi-java/source/browse/trunk/src/main/java/org/owasp/esapi/reference/DefaultHTTPUtilities.java there are some questionable practices regarding thread local.
The biggest problem I'd say is it uses InheritableThreadLocal. If thread A spawns a thread B, B will inherit A's thread local value; however, when A then clears the thread local, it doesn't affect B, so B's inherited value will stay. ESAPI probably shouldn't use InheritableThreadLocal.
I can't say how this may produce the problem you see, without knowing more about threads in your app.
I am using GWT. if any server side exception is generated, we are sending an email with error details(have used log4j SMTPAppender). Based on the line number, we can fix the issue..
My scenario is, if any exception is generated in the client package code, as of now, we are giving generic message saying "Some Exception has Occured". But is it possible to display error stack trace along with the exception cause and line number? my code is as below:
GWT.setUncaughtExceptionHandler(new
GWT.UncaughtExceptionHandler() {
public void onUncaughtException(Throwable e) {
Window.alert("Some Exception has Occured");
}
});
I dont think it is possible as client package is converted into Javascript in web mode. Please suggest me if there is any approach to display exception cause and line number where it has occured.
You can read this page
Basically, you have to use JUL to do your logging, and it's client logging : firebug, JS console, etc... You may do some smarter things with the RemoteLogging but i can't help you on that.
The main problem is that log4j is not supported. Maybe with a bridge between JUL and log4j you will be able to achieve everything you want
I would recommend using gwt-log:
Project Page
gwt-log has support for an 'UncaughtExceptionHandler' and a RemoteLogger to send messages/exception to the server.
in gwt-log, you can also turn on the "emulated stack", which is exactly what you want to do:
Wiki Page - Emulated Stack
please note however that this adds a LOT of code to the compiled JS-script
I have an Axis2 web service which throws different detail messages in the fault response to signal problems in the call.
At some point, due to server errors (others than the ones treated by the web service), in the fault detail string I get the full stacktrace of what happened. I do not want the client to see the stack trace, so (as a catch all errors) I want to output a simple "Server error" message with no stacktrace, no nothing.
What is the simplest way of intercepting fault responses and changing the fault message. Are modules the only way of (complicated) doing this?
Or, is there a configuration in Axis2 that says not to display stacktrace in fault?
Thanks!
I once had a similar problem. Not sure if there is some config to turn off the stacktrace showing, at least none that I could find at that moment (that would have been the best solution). Instead, I opted for a quick and dirty approach, mostly due to lack of time.
What I did was to provide Axis2 with the detail of the fault myself. The Axis2 servlet has a method called handleFault which deals with generating the fault. More exactly (deeper in the call) the MessageContextBuilder.createFaultEnvelope method is used to construct the fault element.
Having the stacktrace in the detail is the default behavior, but there are ways to specify your custom detail. One way is to use the the AxisFault's detail field in which you can add an OMElement (refer to AXIOM) to be placed into the fault. So you do something like:
public class MyServlet extends AxisServlet {
...
public void handleFault(MessageContext msgContext, OutputStream out, AxisFault e) {
OMFactory factory = OMAbstractFactory.getOMFactory();
OMElement detail = factory.createElement(...);
e.setDetail(detail);
// now let axis do its thing with the new improved AxisFault
super.handleFault(msgContext, out, e);
}
}
Now, instead of the exception stacktrace, your detail will be added instead.
Axis2 uses Apache commons logging and the AxisFault messages that you are seeing are generated by code in Axis2 that looks similar to:
try {
executeMethod(httpClient, msgContext, url, getMethod);
handleResponse(msgContext, getMethod);
} catch (IOException e) {
log.info("Unable to sendViaGet to url[" + url + "]", e);
throw AxisFault.makeFault(e);
} finally {
cleanup(msgContext, getMethod);
}
[This code segment comes from org.apache.axis2.transport.http.HTTPSender]
So refer to apache commons logging user guide for instructions on how to set the logging levels and destination of the messages.
Hope this helps.
Can you not just catch the AxisFault
try {
// do stuff
} catch (AxisFault f) {
log.error("Encountered error doing stuff", f);
throw new IOException("Server error");
}