Saturday, April 28, 2012

A Proxy EJB - Servlet for AJAX GET and POST requests


The below class is an EJB that can resolve AJAX GET/POST requests. As you know, AJAX cannot directly access absolute URLs. But, AJAX can "forward" its request to a proxy component, as a servlet (the “gate” to EJB), and that component can access the final resource, instead of AJAX, and return the response to AJAX. The below EJB/Servlet solution accepts GET/POST requests.

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.annotation.Resource;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.RolesAllowed;
import javax.ejb.Stateless;
import javax.ejb.LocalBean;
import javax.ejb.SessionContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.codec.binary.Base64;

@Stateless
@LocalBean
@DeclareRoles({"some_role_1", "some_role_2"})
public class AJAXGETPOSTBean {

  @Resource
  private SessionContext ctx;

  /**
   * Forward GET AJAX request
   */
  @RolesAllowed({"some_role_1", "some_role_2"})
public int getAjaxRequest(HttpServletRequest request, HttpServletResponse response)
  throws Exception {

    String line = "";
    URL new_url = null;
    HttpURLConnection httpURLConnection = null;
    InputStream inputStream = null;
    BufferedReader bufferedReader = null;
    OutputStream outputStream = null;
    PrintWriter out = null;

    String url = request.getParameter("url");

    try {
      if((ctx.isCallerInRole("some_role_1"))||(ctx.isCallerInRole("some_role_2"))){
        if (url.indexOf("http") != -1) {
          out = response.getWriter();

         //sometimes you need to modify the request machine!
         //after you add the new machine URL, you need to paste the rest of request
         //you can use the substring method to identify the remaining URL that is 
         //pasted to the new machine                  
         String local_url = "http://localhost:8080/" + 
                 url.substring(url.indexOf("${paste_this}"));
          url = local_url;

          new_url = new URL(url);

          httpURLConnection = (HttpURLConnection) (new_url.openConnection());
          httpURLConnection.setDoOutput(true);
          httpURLConnection.setDoInput(true);
          httpURLConnection.setRequestMethod(request.getMethod());
          httpURLConnection.setRequestProperty("Content-Type", 
                                          "application/x-www-form-urlencoded");
          httpURLConnection.setUseCaches(false);

          inputStream = request.getInputStream();
          outputStream = httpURLConnection.getOutputStream();

          final int length = 200;
          byte[] bytes = new byte[length];
          int bytesRead = 0;
          while ((bytesRead = inputStream.read(bytes, 0, length)) > 0) {
            outputStream.write(bytes, 0, bytesRead);
          }

          outputStream.flush();
          outputStream.close();
          inputStream.close();

          response.setContentType(httpURLConnection.getContentType());

          inputStream = httpURLConnection.getInputStream();
          bufferedReader = new BufferedReader(new InputStreamReader(inputStream));

          while ((line = bufferedReader.readLine()) != null) {
            out.println(line);
          }

          if (out != null) {
            out.close();
          }
          if (bufferedReader != null) {
            bufferedReader.close();
          }
          if (outputStream != null) {
            outputStream.flush();
            outputStream.close();
          }
          if (inputStream != null) {
            inputStream.close();
          }
          return 1;
        }
      }
      return 0;

    } catch (Exception e) {
      if (out != null) {
        out.close();
      }
      if (bufferedReader != null) {
        bufferedReader.close();
      }
      if (outputStream != null) {
        outputStream.flush();
        outputStream.close();
      }
      if (inputStream != null) {
        inputStream.close();
      }

      throw e;
    } finally {
      if (out != null) {
        out.close();
      }
      if (bufferedReader != null) {
        bufferedReader.close();
      }
      if (outputStream != null) {
        outputStream.flush();
        outputStream.close();
      }
      if (inputStream != null) {
        inputStream.close();
      }
    }
  }

  /**
   * Forward POST AJAX request
   */
  @RolesAllowed("some_role_1")
public int postAjaxRequest(HttpServletRequest request,HttpServletResponse response)
   throws Exception {

    final int length = 1;
    URL new_url = null;
    String requestString = "";
    HttpURLConnection httpURLConnection = null;
    InputStream inputStream = null;
    PrintWriter xmlOut = null;

    String url = request.getParameter("url");

    try {
    //sometimes you need to modify the request machine!
    //after you add the new machine URL, you need to paste the rest of request
    //you can use the substring method to identify the remaining URL that is pasted
    //to the new machine                  
      String local_url = "http://localhost:8080/" + 
             url.substring(url.indexOf("${paste_this}"));
      url = local_url;

      if (ctx.isCallerInRole("some_role_1")) {
        inputStream = request.getInputStream();

        int bytesRead = 0;
        byte[] bytes = new byte[length];
        while ((bytesRead = inputStream.read(bytes, 0, length)) > 0) {
          String value = new String(bytes);
          requestString = requestString + value;
        }

        //if the machine appears in the request query also, you need to modify it 
        //accordingly     
        requestString.replace("original_ip:original_port", 
                      "new_ip(localhost):new_port(8080)");

        inputStream.close();

        response.setContentType("application/xml");

        new_url = new URL(url);
        httpURLConnection = (HttpURLConnection) new_url.openConnection();
        httpURLConnection.setAllowUserInteraction(false);

        httpURLConnection.setRequestMethod("POST");
        httpURLConnection.setRequestProperty("Content-Type", "application/xml");

        httpURLConnection.setDoOutput(true);
        httpURLConnection.setDoInput(true);
        httpURLConnection.setUseCaches(false);

        String authHeader = request.getHeader("Authorization");
        String username = request.getParameter("username");

        if ((username != null) && !username.trim().equals("")) {
          String password = request.getParameter("password");
          String up = username + ":" + password;
          byte[] encoded = Base64.encodeBase64(up.getBytes());
          authHeader = "Basic " + new String(encoded);
        }

        if (authHeader != null) {
          httpURLConnection.setRequestProperty("Authorization", authHeader);
        }

        xmlOut = new PrintWriter(httpURLConnection.getOutputStream());
        xmlOut.write(requestString);
        xmlOut.flush();
        xmlOut.close();

        if (httpURLConnection.getResponseCode() >= 400) {
          return 0;
        } else {
          response.setContentType(httpURLConnection.getContentType());
          response.setHeader("Content-disposition",
                  httpURLConnection.getHeaderField("Content-disposition"));

          int chunk;
          OutputStream output = response.getOutputStream();
          InputStream input = httpURLConnection.getInputStream();

          while ((chunk = input.read()) != -1) {
            output.write(chunk);
          }

          input.close();
          output.close();
        }

        if (inputStream != null) {
          inputStream.close();
        }
        if (xmlOut != null) {
          xmlOut.close();
        }

        return 1;
      }
      return 0;
    } catch (Exception e) {
      if (inputStream != null) {
        inputStream.close();
      }
      if (xmlOut != null) {
        xmlOut.close();
      }
      throw e;
    } finally {
      if (inputStream != null) {
        inputStream.close();
      }
      if (xmlOut != null) {
        xmlOut.close();
      }
    }
  }
}

Now, the servlet that take advantage of this EJB is:

import ejb_package_here;

import java.io.IOException;
import javax.annotation.security.RolesAllowed;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name = "AJAXGETPOSTServlet", urlPatterns = {"/AJAXGETPOSTServlet"})
public class AJAXGETPOSTServlet extends HttpServlet {

  @EJB
  private AJAXGETPOSTBean ajaxBean;

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
    try {
      ajaxBean.getAjaxRequest(request, response);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  @Override
  //@RolesAllowed("memberRole")
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
    try {
      ajaxBean.postAjaxRequest(request, response);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  @Override
  public String getServletInfo() {
    return "Short description";
  }
}

No comments:

Post a Comment