views:

193

answers:

4

I have an interceptor for catching Exceptions and sending emails of this exceptions.

All my struts actions extend CoreController which implements SerlvetRequestAware.

In mail service class then I have:

CoreController cc = (CoreController)invocation.getAction();
HttpServletRequest request = cc.getRequest();

I want to insert request body to email, if exists. Like so:

StringWriter msg = new StringWriter();
msg.write("Requested URI: " + request.getRequestURI()+NEW_LINE);
msg.write("Requested Query String: " + request.getQueryString()+NEW_LINE);
msg.write("Request method: "+request.getMethod()+NEW_LINE);
try {
 if (request.getReader() != null) {
  msg.write("Request body: "+ request.getReader().readLine()+NEW_LINE);
  request.getReader().close();
 }
} catch (IOException e) {
    e.printStrackTrace();
} catch(IllegalStateException e) {
    e.printStrackTrace();
}

Now it always throws an IllegalStateException, when reader is not null. How could I "revert" reader or how any other way to read the request body?

EDIT Exception: getInputStream() has already been called for this request

+2  A: 

Perhaps you should try using the request's InputStream rather than its Reader if you receive an IllegalStateException:

BufferedReader bufferedReader;
try {
    bufferedReader = request.getReader();
} catch (IllegalStateException e) {
    InputStream inputStream = request.getInputStream();

    // As per BalusC's comment:
    String charsetName = request.getCharacterEncoding();
    if (charsetName == null) {
        charsetName = "UTF-8";
    }

    InputStreamReader inputStreamReader = new InputStreamReader(inputStream, charsetName);
    bufferedReader = new BufferedReader(inputStreamReader);
}

bufferedReader.readLine();
Adam Paynter
If the IllegalArgumentException is indeed caused by calling the Reader instead of InputStream and the topicstarter'd go for this solution, please keep character encoding in mind. Preferably construct InputStreamReader with the charset as obtained from request.getCharacterEncoding(), otherwise you will get into trouble with "unicode".
BalusC
I tried this, but the value is null (but I am sending it in a request body).
Trick
@Trick: If it is null, use UTF-8.
BalusC
Thanks for the afford, i tried this in the first attempt, but it was still null... Any other idea? :)
Trick
@Trick: The value returned by `getCharacterEncoding()` is supposedly specified in the `Content-Type` HTTP header. For example: `Content-Type: text/plain;charset=UTF-8`
Adam Paynter
A: 

The manual says:

Throws: IllegalStateException if getInputStream has been called on this same request.

Christian Strempfer
Are you sure it may be called only once? I could be wrong, but I thought `getInputStream()` could be called multiple times and that `getReader()` could be called multiple times, just no combination of the two...
Adam Paynter
You're right, I was a little sloppy. I'll remove that sentence, but it looks like the explanation helped the questioner.
Christian Strempfer
+1  A: 

You will get that exception if someone else has already read the request body or if the other kind of reader (in your case the InputStream) has been opened by someone.

My guess is that this happens in the code which parses the request. So at this stage, you can't read the request body anymore. Instead, you should check the field which contains the exception. Your struts config must contain this code somewhere:

<exception
  key="exception"
  path="/UserExists.jsp"
  type="java.lang.Exception"/>

This means you can find the exception in the request attribute exception.

Aaron Digulla
I don't understand this. I am doing only REST calls, so I don't have any jsp files to forward it there. I get the exception through an interceptor.
Trick
A: 

If you want to read the request body more than once, you could add a Filter that wraps the original HttpServletRequest inside a custom implementation that supports multiple reads (e.g. by storing the request body into a byte array and creating a new ByteArrayInputStream for each call).

Note: Wrapping HttpServletRequest and HttpServletResponse isn't uncommon (see for instance Jetty's GzipFilter, especially its GZIPResponseWrapper class). You should do this carefully though as changing (the behavior of) the request object might affect other filters or servlets.

sfussenegger