I have a Java web application running under Apache Tomcat (8.0.21.0). Its function is to monitor various external processes and display alerts and periodic updated statuses in a browser. The main HTTP request handler is simple enough.
public class MyApplication extends HttpServlet
{
.
.
.
public void doPost (HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
processRequest (request, response);
}
public void doGet (HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
processRequest (request, response);
}
private static void processRequest (HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
String strOption = request.getParameter ("option");
int nOption = Integer.parseInt (strOption);
response.setContentType ("text/html");
PrintWriter out = response.getWriter ();
outputPage (out, nOption);
}
private void outputPage (PrintWriter out, int nOption)
{
out.println ("<!DOCTYPE html>");
out.println ("<html>");
out.println ("<head>");
switch (nOption)
{
// title, style and <body> content depend on option passed in request
.
.
.
}
out.println ("</body>);
out.println ("</html>");
}
}
However, the application also includes a TCP Listener and socket, to receive IoT (Internet of Things) messages:
public class MyTCPconnection extends Thread
{
public Socket clientSocket; // socket created by listener
private String url = "[local host address and servlet name]";
.
.
.
public void run ()
{
int RC = 400; // default value = "Bad Request"
try
{
// get bytes from remote process
int receiveBufferSize = clientSocket.getReceiveBufferSize ();
byte[] receiveBuffer = new byte[receiveBufferSize];
int bytesRead = TCPreceive (clientSocket, receiveBuffer); // not shown
if (bytesRead != -1 && bytesRead != 0)
{
String strOption = getOption (receiveBuffer); // not shown
}
HttpPost httpPost = new HttpPost (url);
httpPost.setHeader ("Accept", "text/html,application/xhtml+xml,application/xml");
httpPost.setHeader ("Content-Type", "application/x-www-form-urlencoded");
List<NameValuePair> requestParams = new ArrayList<NameValuePair>();
reqestParams.add (new BasicNameValuePair ("option", value));
CloseableHttpClient httpClient = HttpClients.createDefault ();
CloseableHttpResponse response = httpClient.execute (httpPost);
RC = response.getStatusLine().getStatusCode();
String responseBody = EntityUtils.toString (response.getEntity ());
system.out.println (responseBody);
}
catch (UnknownHostException e)
{
RC = 404;
}
catch (IOException e)
{
RC = 400;
}
TCPsend (clientSocket, RC); // reply to remote process, not shown
}
}
Take for granted that MyTCPconnection.run () generates a valid HTTP request body and submits a POST request to the main application. The problem I have encountered is that, where the POST is made from a web browser (IExplorer, Firefox etc), the application outputs a web page in the browser, but on receiving the POST request from the internal MyTCPconnection instance, it outputs nothing to any browser. Instead, it redirects the entire output to the responseBody.
I thought at first that I merely needed to save the HttpServletResponse and PrintWriter variables from a request from the browser, and pass the saved PrintWriter instance to the function outputPage. However, when I logged these, the results were:
Request from browser:
HttpServletResponse response = org.apache.catalina.connector.ResponseFacade#3e1d266b
PrintWriter out = org.apache.catalina.connector.CoyoteWriter#6bc55aa8
Request from MyTCPconnection.run ():
HttpServletResponse response = org.apache.catalina.connector.ResponseFacade#3e1d266b
PrintWriter out = org.apache.catalina.connector.CoyoteWriter#6bc55aa8
Any hints or hlp would be appreciated
Related
I want to do a form POST request to the url,in case of valid response callback URL should be called(or hit) else should be redirected to another page of the same application.
Eg : While doing online payment, when we click on pay on any site,it is redirected to our mentioned url,if the user ain't logged in, user is redirected to login page.
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Error error = null;
String jNo=request.getParameter("jNo");
String emailId=request.getParameter("emailId");
String mobileNo=request.getParameter("mobileNo");
String callBackUrl=request.getParameter("url");
HttpResponse httpRespnse=null;
try {
Client client = ClientBuilder.newClient();
WebTarget webTarget = client.target("https://localhost:8080/abc/xyz.aspx");
Invocation.Builder builder1 = webTarget.request(MediaType.APPLICATION_FORM_URLENCODED);
Form form = new Form();
form.param("jNo", jNo);
form.param("emailId", emailId);
form.param("url", callBackUrl);
form.param("mobileNo", mobileNo");
Response response1 = null;
response1 = builder1.post(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED));
String responseXml = response1.readEntity(String.class);
//PrintWriter out=new PrintWriter();
System.out.println(response1.getStatus());
} catch (Exception e) {
logger.error("Issue in Request" + e);
System.out.println(e.getMessage());
e.printStackTrace();
error = aadharProcess.getErrorMsg(Constants.ERR_CODE_INTERNAL_ERROR);
}
}
In a Java HttpServlet, is it possible to request data from another local service using the original request's header information without necessarily forwarding?
For example, I have FooBar.java:
// Handles the url at /foo/bar and can be accessed at http://localhost/foo/bar
public class FooBar extends HttpServlet
{
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
Object data = ... // 1. Retrieve data at http://localhost/foo/baz utilizing the current request's header
Object newData = doSomething(data); // 2. Process the data
response.getWriter().write(newData.toString); // 3. Return the processed data
}
private Object doSomething(Object data)
{
// Perform some business logic
}
}
Step 1 is the issue here. The purpose of this is that I want to be able to perform some sort of logic on the data before returning it in full, but don't necessarily have access do make the changes on the handler at /foo/baz do to the propriety nature of things.
You can use this answer of me to create a HTTP Request: send get request
In addition, it may be necessary to copy the request header with some care:
private static final Set forbiddenCopyHeaders = new HashSet<>(Arrays.asList(new String[]{
"connection"
, "transfer-encoding"
, "content-length" // POST kann zu Status 500 führen, wenn die content-length kopiert wird
, "via"
, "x-forwarded-for"
, "x-forwarded-host"
, "x-forwarded-server"
}));
private void copyRequestHeaders(HttpServletRequest customerRequest, HttpRequestBase internRequest) throws
HttpException
{
Enumeration<String> headerNames = customerRequest.getHeaderNames();
String connectionHeader = customerRequest.getHeader("connection");
while (headerNames.hasMoreElements())
{
String headerName = headerNames.nextElement();
boolean copyAllowed = !forbiddenCopyHeaders.contains(headerName.toLowerCase()) &&
!StringUtils.containsIgnoreCase(connectionHeader, headerName);
if (copyAllowed)
{
Enumeration<String> values = customerRequest.getHeaders(headerName);
while (values.hasMoreElements())
{
internRequest.addHeader(headerName, values.nextElement());
}
}
}
setProxySpecificRequestHeaders(customerRequest, internRequest);
}
private void setProxySpecificRequestHeaders(HttpServletRequest customerRequest,
HttpRequestBase internRequest) throws HttpException
{
String serverHostName = "doorman";
try
{
serverHostName = InetAddress.getLocalHost().getHostName();
}
catch (UnknownHostException e)
{
logger.error("Couldn't get the hostname needed for headers x-forwarded-server and Via", e);
}
String originalVia = customerRequest.getHeader("via");
StringBuilder via = new StringBuilder("");
if (originalVia != null)
{
if (originalVia.contains(serverHostName))
{
logger.error("This proxy has already handled the Request, will abort.");
throw new HttpException("Request has a cyclic dependency on this proxy.");
}
else
{
via.append(originalVia).append(", ");
}
}
via.append(customerRequest.getProtocol()).append(" ").append(serverHostName);
internRequest.addHeader("via", via.toString());
internRequest.addHeader("x-forwarded-for", customerRequest.getRemoteAddr());
internRequest.addHeader("x-forwarded-host", customerRequest.getServerName());
internRequest.addHeader("x-forwarded-server", serverHostName);
internRequest.addHeader("accept-encoding", "");
}
Using HttpURLConnection and altering the header to include a property from the original request, I was able to get a BufferedReader from the HTTP request:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
// Step 1
String serverName = request.getLocalName();
String contextPath = request.getContextPath();
URL url = new URL("https://" + serverName + contextPath + "/baz");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Key Header", request.getHeader("Key Header"));
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
// Step 2
... // Do something with the data from the reader
// Step 3
... // Write the data back using the response
}
I am designing a very simple chat application which uses the long polling to communicate between users. I am using a servlet to store the AsyncContexts in a Hashmap. When userA sends a message to userB the servlet gets the corresponding AsyncContext from the HashMap and pushes the data to the client.
The code that I am using is given below-:
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.setContentType("application/json");
if ("getAll".equals(request.getParameter("op"))) {
String friend = request.getParameter("for");
String jsonMessages = getChatMessagesForUser((String)request.getSession()
.getAttribute("id"),friend);
PrintWriter writer = response.getWriter();
writer.println(jsonMessages);
writer.flush();
return;
}
else if ("getFrnd".equals(request.getParameter("op"))) {
String jsonFrndList = getFriends((String)request.getSession()
.getAttribute("id"));
PrintWriter writer = response.getWriter();
writer.println(jsonFrndList);
writer.flush();
return;
}
final AsyncContext asyncContext = request.startAsync(request, response);
asyncContext.setTimeout(30 * 60 * 1000);
asyncContext.addListener(new AsyncListener() {
#Override
public void onTimeout(AsyncEvent event) throws IOException {
AsyncContext ctx = event.getAsyncContext();
PrintWriter writer = ctx.getResponse().getWriter();
ChatMessage directive = new ChatMessage();
directive.setType('D');
directive.setMessage("Keep-Alive");
writer.println(gson.toJson(directive));
writer.flush();
contexts.remove(ctx);
ctx.complete();
}
#Override
public void onStartAsync(AsyncEvent event) throws IOException {
// TODO Auto-generated method stub
}
#Override
public void onError(AsyncEvent event) throws IOException {
AsyncContext ctx = event.getAsyncContext();
PrintWriter writer = ctx.getResponse().getWriter();
ChatMessage directive = new ChatMessage();
directive.setType('D');
directive.setMessage("Keep-Alive");
writer.println(gson.toJson(directive));
writer.flush();
contexts.remove(ctx);
ctx.complete();
}
#Override
public void onComplete(AsyncEvent event) throws IOException {
// TODO Auto-generated method stub
}
});
String id = (String) request.getSession().getAttribute("id");
if(!contexts.containsKey(id)) {
contexts.put(id, asyncContext);
}
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.setContentType("application/json");
String receiver = request.getParameter("name");
String sender = (String) request.getSession().getAttribute("id");
String message = request.getParameter("message");
System.out.println(receiver + " " + message);
ChatMessage chatMessage = new ChatMessage();
chatMessage.setType('M');
chatMessage.setReceiver(receiver);
chatMessage.setSender(sender);
chatMessage.setMessage(message);
chatMessage.setImage(false);
if(contexts.containsKey(receiver)) {
AsyncContext recieverContext = (AsyncContext) contexts.remove(receiver);
System.out.println("Connections Open:" + contexts.size());
PrintWriter writer = recieverContext.getResponse().getWriter();
writer.println(gson.toJson(chatMessage));
System.out.println("Message transmitted:" +
gson.toJson(chatMessage));
writer.flush();
recieverContext.complete();
}
try {
System.out.println("Trying to add to database");
ChatDAO.addToChat(chatMessage);
} catch (SQLException e) {
System.err.println(e);
}
}
Let me explain what is happening-:
User A sends the initial GET request to the servlet.
The servlet starts an AsyncContext and adds it to the HashMap.
User B does the same thing.
User A sends a message to User B by posting to the servlet(doPost).
The servlet gets the AsyncContext of user B from the hashmap. Pushes the message from User A and call complete() on it.
User B immediately reconnects to the servlet by doing another GET (doGet).
The obvious problem of this is that when multiple people try to chat with one single person. For example-: If User B and User C try to chat with User A a race condition arises.
It may happen they both post a message to user A at the same time, depending on whose message is processed first the connection to user A will be closed. And hence if a chat message arrives before the recipient reconnects the message will be discarded.
What I need is that if the servlet is unable to find an async context for a particular user then it will wait for sometime and then after waiting if it does not still find it only then will it discard the message.
Can I write something like -:
synchronized(contexts) {
wait(100);
}
You might be better off separating the storage of messages from the async contexts so that the messages can be stored even if there is not a context for the recipient. The next time the recipient sends the get request it would find a message waiting and return it straight away.
If you are concerned about stale undelivered messages then you could have a single thread that checks periodically for messages over a certain age and returns them to the sender. It could also just destroy old return to sender messages
I have to write a controller in my project using servlets. I've done it before but I've never worked with AngularJS, so I did it via request.setAttribute() and request.getParameter() and put Java code inside of a JSP page. But now frontend developer used AngularJS and I have to return him a JSON object. And I have no idea how to do it. Here's the code of abTestCtrl.js:
app.controller("abTestCtrl", function($scope, $location, $http) {
$scope.title = "no title";
$scope.description = "no description";
$scope.getParam = $location.search()['id'];
if($scope.getParam === undefined)$scope.getParam = 0;
//$scope.getParam=2;
//path: localhost8080/UIUM.../servlet-name.java
//with two ids
//web.xml: serverlet mapping for the path
if($scope.getParam==='0'||$scope.getParam === 0){
var saveButton = document.getElementById("saveButton");
saveButton.classList.remove("hidden");
}
else{
$http.get('http://localhost:8080/UIUM_IMT4003/ABTestController', {command:'getTestCaseInfo', testcaseID:$scope.getParam}).
success(function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
console.log('request succesful');
console.log(data);
console.log(status);
console.log(headers);
console.log(config);
}).
error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
console.log('request not succesful');
});
}
and my processRequest() code from the servlet:
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, SQLException, ClassNotFoundException {
response.setStatus(HttpServletResponse.SC_OK);
response.setContentType("application/json; charset=UTF-8");
//PrintWriter printout = response.getWriter();
JSONObject jObject = null;
RequestDispatcher view = null;
TestcaseRepository testcaseRepo = new TestcaseRepository();
String command = request.getParameter("command");
if(command == null)
{
view = request.getRequestDispatcher("/testcases.jsp");
view.forward(request, response);
}
if(command.equals("getTestCaseInfo")){
String testcaseId = request.getParameter("testcaseID");
Testcase testcase = testcaseRepo.getTestcaseById(testcaseId);
jObject = new JSONObject();
jObject.put("id", testcaseId);
jObject.put("title", testcase.getTestcaseName());
jObject.put("testscenario", testcase.getTestcaseDescription());
// printout.print(jObject);
// printout.flush();
jObject.write(response.getWriter());
}
Can you please help me to process this request and finally return this poor JSON!
BTW, Servlet doesn't recognize command parameter. It gets null. But there is such parameter in AngularJS function.
Try using the javax.json.JsonObject as follow:
JsonObject jo=Json.createObjectBuilder()
.add("id", testcaseId)
.add("title", testcase.getTestcaseName())
.add("testscenario", testcase.getTestcaseDescription()).build();
Then set the response content type to json and send your json object in the response:
response.setContentType("application/json");// set content to json
PrintWriter out = response.getWriter();
out.print(jo);
out.flush();
I want to add logging to my Servlet, so I've created Filter which should display request and go to the Servlet. But unfortunately I've encoutered exception:
java.lang.IllegalStateException: getReader() has already been called for this request
at org.apache.catalina.connector.Request.getInputStream(Request.java:948)
at org.apache.catalina.connector.RequestFacade.getInputStream(RequestFacade.java:338)
at com.noelios.restlet.ext.servlet.ServletCall.getRequestEntityStream(ServletCall.java:190)
So to fix this problem I've found solution with Wrapper, but it doesn't work. What else can I use/change in code? Any ideas?
[MyHttpServletRequestWrapper]
public class MyHttpServletRequestWrapper extends HttpServletRequestWrapper
{
public MyHttpServletRequestWrapper(HttpServletRequest request)
{
super(request);
}
private String getBodyAsString()
{
StringBuffer buff = new StringBuffer();
buff.append(" BODY_DATA START [ ");
char[] charArr = new char[getContentLength()];
try
{
BufferedReader reader = new BufferedReader(getReader());
reader.read(charArr, 0, charArr.length);
reader.close();
}
catch (IOException e)
{
e.printStackTrace();
}
buff.append(charArr);
buff.append(" ] BODY_DATA END ");
return buff.toString();
}
public String toString()
{
return getBodyAsString();
}
}
[MyFilter]
public class MyFilterimplements Filter
{
#Override
public void init(FilterConfig filterConfig) throws ServletException
{
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
final HttpServletResponse httpServletResponse = (HttpServletResponse) response;
final HttpServletRequestWrapper requestWrapper = new MyHttpServletRequestWrapper(httpServletRequest);
final String requestBody = requestWrapper.toString();
chain.doFilter(request, response);
}
}
Looks like the restlet framework has called getRequestEntityStream() on the Request object which in turn calls getInputStream(), so calling getReader() on the request throws IllegalStateException. The Servlet API documentation for getReader() and getInputStream() says:
public java.io.BufferedReader getReader()
...
...
Throws:
java.lang.IllegalStateException - if getInputStream() method has been called on this request
public ServletInputStream getInputStream()
...
...
Throws:
java.lang.IllegalStateException - if the getReader() method has already been called for this request
From the documentation it seems that we cannot call both getReader() and getInputStream() on the Request object. I suggest you use getInputStream() rather than getReader() in your wrapper.
Use ContentCachingRequestWrapper class. Wrap HttpServletRequest in thi will resolve issue
Sample : if you want to convert your "HttpServletRequest servletRequest" you can do some thing like
import org.springframework.web.util.ContentCachingRequestWrapper;
ContentCachingRequestWrapper request = new ContentCachingRequestWrapper(servletRequest);
Hope it helps!!!
As far as I can tell servlets are fundamentally broken in this regard. You can try and work around this problem as outlined here but that causes other mysterious problems when other things try and work with it.
Effectively he suggests cloning the request, reading the body and then in the the cloned class overriding the getReader and getInputStream methods to return the stuff already retrieved.
The code I ended up with was this:
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
//this class stops reading the request payload twice causing an exception
public class WrappedRequest extends HttpServletRequestWrapper
{
private String _body;
private HttpServletRequest _request;
public WrappedRequest(HttpServletRequest request) throws IOException
{
super(request);
_request = request;
_body = "";
try (BufferedReader bufferedReader = request.getReader())
{
String line;
while ((line = bufferedReader.readLine()) != null)
_body += line;
}
}
#Override
public ServletInputStream getInputStream() throws IOException
{
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(_body.getBytes());
return new ServletInputStream()
{
public int read() throws IOException
{
return byteArrayInputStream.read();
}
};
}
#Override
public BufferedReader getReader() throws IOException
{
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
}
Anyway this appeared to be working fine until we realised that uploading a file from the browser wasn't working. I bisected through the changes and discovered this was the culprit.
Some people in the comments in that article say you need to override methods to do with parameters but don't explain how to do this.
As a result I checked to see if there was any difference in the two requests. However after cloning the request it had identical sets of parameters (both original request + cloned had none) aswell as an identical set of headers.
However in some manner the request was being effected and screwing up the understanding of the request further down the line - in my case causing a bizaare error in a library (extdirectspring) where something was trying to read the contents as Json. Taking out the code that read the body in the filter made it work again.
My calling code looked like this:
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException
{
HttpServletRequest properRequest = ((HttpServletRequest)request);
String pathInfo = properRequest.getPathInfo();
String target = "";
if(pathInfo == null)
pathInfo = "";
if(pathInfo.equals("/router"))
{
//note this is because servlet requests hate you!
//if you read their contents more than once then they throw an exception so we need to do some madness
//to make this not the case
WrappedRequest wrappedRequest = new WrappedRequest(properRequest);
target = ParseExtDirectTargetFrom(wrappedRequest);
request = wrappedRequest;
}
boolean callingSpecialResetMethod = pathInfo.equals("/resetErrorState") || target.equals("resetErrorState");
if(_errorHandler.IsRejectingRequests() && !callingSpecialResetMethod)
return;
try {
filterChain.doFilter(request, response);
}
catch (Exception exception) {
((HttpServletResponse) response).sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "ERROR");
_errorHandler.NotifyOf(exception);
}
}
I've ommitted the contents of ParseExtDirectTargetFrom but it calls getReader().
In my case the filter was working for all other requests but the strange behaviour in this case made me realise something wasn't quite right and what I was trying to do (implement sensible exception handling behaviour for tests) wasn't worth potentially breaking random future requests (as I couldn't figure out what had caused the request to become broken).
Also it's worth noting that the broken code is unavoidable - I assumed it might be something from spring but ServletRequest goes all the way up - thats all you get even if you were making a servlet from scratch by subclassing HttpServlet
My recommendation would be this - don't read the request body in a filter. You'll be opening up a can of worms that will cause strange problems later on.
The main problem is that you can't read the input both as binary stream and character stream, not even if the one is called in a filter and the other in the servlet.
Well, maybe this is something quite obvious, but I want to share with you this code that work OK for me. In a Spring boot project with JWT, for request of client, was necesary save all requests with their responses in a database table, and the same time authorize the access to consume the resources. Off Course i use getReader() for get request body, but i was obtain java.lang.IllegalStateException...
#Slf4j
#Component
#RequiredArgsConstructor
public class CustomAuthorizationFilter extends OncePerRequestFilter {
private final AuthorizationService authorizationService;
private String requestBody;
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) {
HttpRequestDto requestDto = new HttpRequestDto();
try {
if (RequestMethod.POST.name().equalsIgnoreCase(request.getMethod()) && requestBody != null) { //This line and validation is useful for me [requestBody != null]
requestBody = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
}
//Do all JWT control
requestDto.setRequestURI(request.getRequestURI());
requestDto.setMethod(request.getMethod());
requestDto.setBody(requestBody);
}catch (IOException ie) {
responseError(_3001, response, ie);
} finally {
try {
ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);
filterChain.doFilter(request, responseWrapper);
saveResponse(responseWrapper, requestDto);
} catch (ServletException | IOException se) {
responseError(_3002, response, se);
}
}
}
private void saveResponse(ContentCachingResponseWrapper responseWrapper, HttpRequestDto requestDto) {
try {
HttpResponseDto responseDto = new HttpResponseDto();
responseDto.setStatus(responseWrapper.getStatus());
byte[] responseArray = responseWrapper.getContentAsByteArray();
String responseBody = new String(responseArray, responseWrapper.getCharacterEncoding());
responseDto.setBody(responseBody);
responseWrapper.copyBodyToResponse();
authorizationService.seveInDatabase(requestDto, responseDto);
} catch (Exception e) {
log.error("Error ServletException | IOException in CustomAuthorizationFilter.saveResponse", e);
}
}
private void responseError(LogCode code, HttpServletResponse response, Exception e) {
try {
Map<String, Object> error = new HashMap<>();
error.put("log", LogUtil.getLog(code));
error.put("message", e.getMessage());
response.setContentType(APPLICATION_JSON_VALUE);
new ObjectMapper().writeValue(response.getOutputStream(), error);
e.printStackTrace();
} catch (IOException ie) {
log.error("Error IOException in HttpLoggingFilter.responseError:", ie);
}
}
public String getRequestBody() {
return requestBody;
}
public void setRequestBody(String requestBody) {
this.requestBody = requestBody;
}
}
So my solution was use getter and setter methods of de local attribute requestBody, for validate if this is or not null and does not call again getReader() method because save in memory when set value. This worked perfect for me. Regards.