Reputation: 23522
I need to forward/craft request to another servlet from other servlet's service method manually. This servlet which calls another servlet, should extract the data from other servlet's response and send it's own response to client. How to achieve this kind of functionality?
Client <-----> Servlet1 <-----> Servlet2
I know it's bad design, but due the circumstances we have to introduce the functionality of Servlet2 to Servlet1
Upvotes: 0
Views: 807
Reputation: 1705
you need to use HttpServletResponseWrapper and override its getOutputStream Method.
CustomHttpServletResponseWrapper
and CustomServletOutputStream
are implementation for this.
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
public class CustomHttpServletResponseWrapper extends HttpServletResponseWrapper {
private ServletOutputStream outputStream;
private PrintWriter writer;
private CustomServletOutputStream os;
public CustomHttpServletResponseWrapper(HttpServletResponse response) throws IOException {
super(response);
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
if (writer != null) {
throw new IllegalStateException("getWriter() has already been called on this response.");
}
if (outputStream == null) {
outputStream = getResponse().getOutputStream();
os = new CustomServletOutputStream(outputStream);
}
return os;
}
@Override
public PrintWriter getWriter() throws IOException {
if (outputStream != null) {
throw new IllegalStateException("getOutputStream() has already been called on this response.");
}
if (writer == null) {
os = new CustomServletOutputStream(getResponse().getOutputStream());
writer = new PrintWriter(new OutputStreamWriter(os, getResponse().getCharacterEncoding()), true);
}
return writer;
}
@Override
public void flushBuffer() throws IOException {
if (writer != null) {
writer.flush();
} else if (outputStream != null) {
os.flush();
}
}
public byte[] getContent() {
if (os != null) {
return os.getContent();
} else {
return new byte[0];
}
}
}
customServletOutputStream.java
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
public class CustomServletOutputStream extends ServletOutputStream {
private OutputStream outputStream;
private ByteArrayOutputStream content;
public CustomServletOutputStream(OutputStream outputStream) {
this.outputStream = outputStream;
this.content = new ByteArrayOutputStream(1024);
}
@Override
public void write(int b) throws IOException {
outputStream.write(b);
content.write(b);
}
public byte[] getContent() {
return content.toByteArray();
}
@Override
public boolean isReady() {
// TODO Auto-generated method stub
return false;
}
@Override
public void setWriteListener(WriteListener writeListener) {
// TODO Auto-generated method stub
}
}
your Main class:
use RequestDespetcher.include()
to redirect request to s2 and pass CustomHttpServletResponseWrapper
.
@ResponseBody
@RequestMapping("/s1")
public String s1(HttpServletRequest req, HttpServletResponse res) throws Exception{
RequestDispatcher rd = req.getRequestDispatcher("/oauth2/s2");
CustomHttpServletResponseWrapper wrappedResponse = new CustomHttpServletResponseWrapper(res);
rd.include(req, wrappedResponse);
wrappedResponse.flushBuffer();
byte[] result = wrappedResponse.getContent();
System.out.println("result of servlet 2 "+new String(result));
// here you got the result of servlet 2. manipulate it as you want.
return new String(result);
}
@ResponseBody
@RequestMapping("/s2")
public String s2(HttpServletRequest req, HttpServletResponse res){
return "hello from s2";
}
Upvotes: 1