First off, I'm an experienced programmer, but have very little familiarity with Java. I have about two years of experience with it, eight years ago.
I'm getting a NullPointerException in the following code:
public static void handle(HttpServletRequest request,HttpServletResponse response)throws IOException,ServletException {
Response gfexResponse = null;
try {
ActionFactory actionFactory = ActionFactory.getInstance();
String requestURL = request.getRequestURI();
String actionId = actionFactory.getActionId(requestURL);
IAction action = actionFactory.createAction(actionId);
ActionEvent event = new ActionEvent(request, 0, actionId);
gfexResponse = action.execute(event);
} catch (Exception ex) {
gfexResponse = new Response();
gfexResponse.setError(ex.getMessage());
gfexResponse.setOutcome(IViewConstants.ERROR);
} finally {
if(request.getParameter("loginId") != null){
request.setAttribute("loginId", request.getParameter("loginId"));
}
if(gfexResponse.getMessage()!= null){
request.setAttribute("message", gfexResponse.getMessage());
}
if(gfexResponse.getError()!= null){
request.setAttribute("error", gfexResponse.getError());
}
if (gfexResponse.getContentType() != null) {
response.setContentType(gfexResponse.getContentType());
OutputStream outputStream = response.getOutputStream();
outputStream.write(gfexResponse.getOutputData());
outputStream.flush();
outputStream.close();
}
if(gfexResponse.getOutcome() != null){
RequestDispatcher dispatcher = request.getRequestDispatcher(gfexResponse.getOutcome());
dispatcher.forward(request, response);
}
}
}
Here's the StackTrace:
[6/18/13 17:10:04:518 GMT] 00000023 ServletWrappe E SRVE0068E: Uncaught exception thrown in one of the service methods of the servlet: GfexServlet. Exception thrown : java.lang.NullPointerException
at com.svl.gfex.handlers.RequestHandler.handle(RequestHandler.java:44)
at com.svl.gfex.servlets.GfexServlet.processRequest(GfexServlet.java:43)
at com.svl.gfex.servlets.GfexServlet.doPost(GfexServlet.java:39)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:763)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:966)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:907)
at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:118)
at com.ibm.ws.webcontainer.filter.WebAppFilterChain._doFilter(WebAppFilterChain.java:87)
at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:701)
at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:646)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:475)
at com.ibm.ws.wswebcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:463)
at com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:3129)
at com.ibm.ws.webcontainer.webapp.WebGroup.handleRequest(WebGroup.java:238)
at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:811)
at com.ibm.ws.wswebcontainer.WebContainer.handleRequest(WebContainer.java:1433)
at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:93)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:465)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewInformation(HttpInboundLink.java:394)
at com.ibm.ws.http.channel.inbound.impl.HttpICLReadCallback.complete(HttpICLReadCallback.java:102)
at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:152)
at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:213)
at com.ibm.io.async.AbstractAsyncFuture.fireCompletionActions(AbstractAsyncFuture.java:195)
at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:136)
at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:194)
at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:741)
at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:863)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1510)
The stacktrace points to this line:
if(gfexResponse.getMessage()!= null){ <-------- this line
request.setAttribute("message", gfexResponse.getMessage());
}
This code was being maintained by an offshore contractor, but the company laid off all the contractors. For my sins, I was given the job of fixing it.
If anyone can help me figure out why I'm getting this error, I would appreciate it.
That error indicates that the gfexResponse object itself is null (i.e. action.execute(event) is returning null in the code above, and no exception is being thrown)
Your basic outline is this:
public static void handle(HttpServletRequest request,HttpServletResponse response)throws IOException,ServletException {
Response gfexResponse = null;
try {
//Try to get your gfexResponse
} catch (Exception ex) {
//Provide a default gfexResponse
} finally {
//Do some stuff with gfexResponse
}
}
This is bad practice: you're attempting to use exception handling for flow control. Further, you assume that the method you use to get gfexResponse will throw an exception if it fails, which clearly it does not. (Some simple debugging/tracing will reveal this directly.)
What you should be doing is the following:
public static void handle(HttpServletRequest request,HttpServletResponse response)throws IOException,ServletException {
Response gfexResponse = null;
try {
//Try to get your gfexResponse
//Make sure you got your response object and throw SomeAppropriateException if not
//Do some stuff with gfexResponse
} catch (SomeAppropriateException e) {
//properly handle this case
} catch (Exception ex) {
//properly handle the general case that something else failed (But you should try to be more specific)
} finally {
//remove any resources that might not be properly cleaned up if an exception is thrown.
}
}
Are you sure that gfexResponse is getting an actual value from action.execute(event); (in the try {})? I'd guess that action.execute(event); is returning null.
To solve the immediate pain - your action.execute(event); call is likely returning null. However, this can be mitigated in several ways:
Null checking, or
Turning the try-catch block into its own separate method call, to return Response.
From there, the finally block becomes the main focus of your method, and you can check for null without having to worry about finally.
Actually problem lies at the line gfexResponse = action.execute(event);
only chance in the below line to get NPE here is gfexResponse is null
if(gfexResponse.getMessage()!= null){ <-------- this line
change it to
if(gfexResponse!=null && gfexResponse.getMessage()!= null){ <-------- this line
Related
I have a program in which I want to throw one of 4 exceptions that I define.
I get an HTTP response and according its error code I want to throw the exceptions:
Here is an example:
public List<Map<String, Object>> getData(String product) {
try {
Response<DataGeneralResponse> response = dataApi.dataGet(product).execute();
if (!response.isSuccessful()) {
log.error(String.format("Failed to get data for product [%s] error [%s]",
product,
Util.getErrorMsg(response)));
}
DataGeneralResponse body = response.body();
return body != null ? body.getData(): null;
} catch (Exception e) {
log.error(String.format("Failed to get data for product [%s] error[%s]",
product,
Util.getErrorMsg(response)));
}
return null;
}
So I need to to something like that in Util:
public void handleResponse(Response<DataGeneralResponse> response) throws CustomException {
switch (response.code()) {
case 500: throw new FirstCustomException(");
break;
case 404: throw new SecondCustomException(");
break;
default: throw new UnknownCustomException(");
}
}
But when I try to remove the catch clause I get unhandled IOException error on the execute method and on the getErrorMsg method.
Can someone help please?
I get unhandled IOException error on the execute method and on the getErrorMsg method.
This indicates that you have a method, which is trying to throw a checked exception, which is not surrounded by a try catch clause. By Java language standard all methods, which throw checked exceptions must do one of the two ..
Be surrounded by a try-catch block which catches the relevant exception
Declare that they throw the relevant exception by using the throws keyword
You can use one of the methods above to deal with error you are getting.
If this does not completely solve your problem, please add a comment below and I'll respond.
I am trying to throw a timeout exception in the code below. I tried a simple condition but it's not the proper way.
My question is how can I distinct the timeout exception from SOAPException?
URL endpoint = new URL(null,
urlStr,
new URLStreamHandler() {
// The url is the parent of this stream handler, so must create clone
protected URLConnection openConnection(URL url) throws IOException {
URL cloneURL = new URL(url.toString());
HttpURLConnection cloneURLConnection = (HttpURLConnection) cloneURL.openConnection();
// TimeOut settings
cloneURLConnection.setConnectTimeout(10000);
cloneURLConnection.setReadTimeout(10000);
return cloneURLConnection;
}
});
try {
response = connection.call(request, endpoint);
} catch (SOAPException soapEx) {
if(soapEx.getMessage().contains("Message send failed")) {
throw new TimeoutExpirationException();
} else {
throw soapEx;
}
}
The following lines are from open jdk source code of call method. In the code they are only catching with Exception (also with chaining? comment). I don't think there is other way unless Oracle jdk handles this differently.
You can still try something like if(soapEx.getCause() instanceof SomeTimeoutException) (not sure if this will work)
try {
SOAPMessage response = post(message, (URL)endPoint);
return response;
} catch (Exception ex) {
// TBD -- chaining?
throw new SOAPExceptionImpl(ex);
}
If you want to check the source code HttpSoapConnection
After some hours of testing I found the proper way to distict the SOAPException from Timeout related exceptions. So the solution is to take the parent cause field of the exception and check if it's an instance of SocketTimeoutException.
try {
response = connection.call(request, endpoint);
} catch (SOAPException soapEx) {
if(soapEx.getCause().getCause() instanceof SocketTimeoutException) {
throw new TimeoutExpirationException(); //custom exception
} else {
throw soapEx;
}
}
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");
}
From the server Code (in an HttpServlet) I'm throwing an exception if the file is too large:
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
...
// Check if the blob has correct size, otherwise delete it
final BlobInfo blobInfo = new BlobInfoFactory().loadBlobInfo(blobKey);
long size = blobInfo.getSize();
if(size > 0 && size <= BasicConstants.maxImageSize){
res.sendRedirect("/download?blob-key=" + blobKey.getKeyString());
} else { // size not allowed
bs.delete(blobKey);
throw new RuntimeException(BasicConstants.fileTooLarge);
}
From the client code I'm missing to successfully catch the exception with this snippet:
try {
uploadForm.submit(); // send file to BlobStore, where the doPost method is executed
} catch (Exception ex) {
GWT.log(ex.toString());
}
However, from this other client code snippet I'm somehow detecting when the exception was thrown with an ugly workaround that I don't trust at all:
uploadForm.addSubmitCompleteHandler(new FormPanel.SubmitCompleteHandler() {
#Override
public void onSubmitComplete(SubmitCompleteEvent event) {
// This is what gets the result back - the content-type *must* be
// text-html
String imageUrl =event.getResults();
// This ugly workaround apparently manages to detect when the server threw the exception
if (imageUrl.length() == 0) { // file is too large
uploadFooter.setText(BasicConstants.fileTooLarge);
} else { // file was successfully uploaded
...
}
The Development Mode view in Eclipse reports an error of type "uncaught exception", which suggests that I'm really doing a bad job at detecting it.
Can anyone tell me how to properly catch the exception, and if the workaround I'm using makes any sense?
Thanks!
Your first attempt
try {
uploadForm.submit(); // send file to BlobStore, where the doPost method is executed
} catch (Exception ex) {
GWT.log(ex.toString());
}
doesn't work, because submit() doesn't wait until the browser receives the response (it's an asynchronous call).
uploadForm.addSubmitCompleteHandler(new FormPanel.SubmitCompleteHandler() {
#Override
public void onSubmitComplete(SubmitCompleteEvent event) {
...
Here you actually receive the response from the server. But it's a form submission, not a GWT-RPC call, so the result is just plain text, not GWT Java Objects.
When you throw a RuntimeException in a Servlet, the server will simply send a response with an error code (probably '500', but ideally use the "Network" tab in Firebug or Chrome Developer Tools to see the actual response and response code.) So in the success case you'll get the URL, otherwise the response is empty.
Possible solution
You can catch Exceptions on the server side, and send better descriptions explicitly:
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
try {
...
if (...) {
throw new MyTooLargeException();
} else {
...
res.getWriter().write("ok " + ...);
}
} catch (MyTooLargeException e) {
res.getWriter().write("upload_size_exceeded"); // just an example string
// (use your own)
res.sendError(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE);
}
}
Then, on the client, check for
"upload_size_exceeded".equals(event.getResults()).
so i am using a filter to catch servlet exception (because we are using a mix of jsf/plain servlets)
when catching the ServletException and calling printstacktrace most of the information is lost.
the "true" root exception seems to be hidden behind the "funny" expression
((ServletException) e.getRootCause().getCause()).getRootCause().getCause().getCause().getCause()
this is clearly not the way to do it.
is the an easy way to print the "full" information of such an exception.
can someone explain me why the exception is wrapped this way?
Take a look at the ExceptionUtils class from commons-lang. It contains several useful methods for printing the entire chain of exceptions.
after i had a look at ExceptionUtils, this solved the problem!
final StringWriter stacktrace = new StringWriter();
ExceptionUtils.printRootCauseStackTrace(throwable,new PrintWriter(stacktrace));
msg.append(stacktrace.getBuffer());
this prints out the full stacktrace with every piece of information that is relevant.
That is called exception chaining. By wrapping an exception in a different exception you can let exceptions bubble up the stack without having your main application classes to worry about some low-level exceptions.
Example:
public void doStuff() throws StuffException {
try {
doDatabaseStuff();
} catch (DatabaseException de1) {
throw new StuffException("Could not do stuff in the database.", de1);
}
}
This way your application only has to handle StuffException but it can get to the underlying DatabaseException if it really needs to.
To get to the bottom-most (and all other) exception(s) of an exception you caught you can iterator over its root causes:
...
} catch (SomeException se1) {
Throwable t = se1;
logger.log(Level.WARNING, "Top exception", se1);
while (t.getCause() != null) {
t = t.getCause();
logger.log(Level.WARNING, "Nested exception", t);
}
// now t contains the root cause
}
Exception chaining for ServletException is tricky. Depending on the web server implementation and web development framework in use, at runtime the chain may use cause and/or rootCause. This link explains it very well. To complicate things, I've seen exceptions where the cause points to the exception itself.
Here's a recursive method we have used that covers all bases for ServletExceptions:
public static Throwable getDeepCause(Throwable ex) {
if (ex == null) {
return ex;
}
Throwable cause;
if (ex instanceof ServletException) {
cause = ((ServletException) ex).getRootCause();
if (cause == null) {
cause = ex.getCause();
}
} else {
cause = ex.getCause();
}
if (cause != null && cause != ex) {
return getDeepCause(cause);
} else {
// stop condition - reached the end of the exception chain
return ex;
}
}