Tuomas Toivonen
Tuomas Toivonen

Reputation: 23522

How to use other servlets service in another servlet?

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

Answers (1)

Suraj
Suraj

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

Related Questions