Saturday, August 22, 2009

GWT RPC - How Server-side JSP Service Works

Continued from Passing Parameters in GWT RPC (Server-side)


Remember that the name of any JSP that is registered as a GWT RPC service responder must end with suffix ".gwtrpc.jsp".

Here's the reason why.

A JSP is first translated into a Java source file with a _jspService method, which always begins with this block of code
public void _jspService(
HttpServletRequest request,
HttpServletResponse response)
throws java.io.IOException, ServletException {

JspFactory _jspxFactory = null;
  PageContext pageContext = null;
  HttpSession session = null;
  ServletContext application = null;
  ServletConfig config = null;
  JspWriter out = null;
  Object page = this;
  JspWriter _jspx_out = null;
  PageContext _jspx_page_context = null;

  try {
    _jspxFactory = JspFactory.getDefaultFactory();
    response.setContentType("text/html");
    pageContext =
    _jspxFactory.getPageContext(
    this, request, response,
    null, true, 8192, true);
    _jspx_page_context = pageContext;
    application = pageContext.getServletContext();
    config = pageContext.getServletConfig();
    session = pageContext.getSession();
    out = pageContext.getOut();
    _jspx_out = out;

    ....

However, the RemoteServiceServlet class, which a GWT RPC service responder servlet should extend (in order to exploit the convenience of data serialization afforded by implementng GWT RPC interfaces), uses its own output stream and ignores/discards the response output stream. That is, the JspWriter out stream is ignored/discarded. Which causes the output of a JSP extending RemoteServiceServlet to be blank, because all the content rendering of a JSP is translated into lines of ignored output stream

out.write( .... );

Therefore, we need a way to exploit the out.write lines generated by the JSP translator, by diverting out back to the response body. So we create a class JspResponseWriter, which extends JspWriter, to over-ride the write method, so that it writes to the response body.
package org.synthful.gwt.http.servlet.server;
....
public class JspResponseWriter
 extends JspWriter
{
  ....



@Override public void write(char[] cbuf, int off, int len) throws IOException{ for (int i=off; i<off+len; i++) this.Body.append(cbuf[i]); }
.... }

Alright, now we the mice have the bell, we only need find a ribbon to tie it to the neck of the pussycat. Even with a ribbon, we still need to sneak up to the cat tie the ribbon with the bell around the cat.

Okay, notice in the translated JSP Java source is the line

out = pageContext.getOut();

So we create an extension of PageContext whose getOut method would sneak our version of JspWriter to the out variable.

And, the plot thickens. Now, we have to find a way to sneak our version of PageContext into the conspiracy to defraud Google's blindfolding of the JSP out prisoner.

Notice the translated Java source has a line
pageContext = _jspxFactory.getPageContext(....);

And your premonition is correct - we have to send in a double-agent to sneak our impersonator of the JspFactory, who would help us sneak our version of PageContext into the belly of RemoteServiceServlet.

So, here's the double-agent, JspServiceBeanable, who would undertake this mission. Notice the line JspFactory.setDefaultFactory( .... ), which is how our agent sneaks our version of JspFactory, which would sneak our version of PageContext, which would sneak our version of JspWriter, which would sneak GWT server-side prisoner, the JSP rendering output, back to the response body where it rightly belongs:
package org.synthful.gwt.http.servlet.server;
...
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

abstract public class JspServiceBeanable
  extends RemoteServiceServlet
  implements HttpJspPage
{
....

protected String doJspService( HashMap<String, String> parameters){ this.parameters = new Hashtable<String, String>(parameters); JspFactory.setDefaultFactory(new JspFactoryShunt()); this.jspFactory = JspFactory.getDefaultFactory(); try{ this._jspService( this.getThreadLocalRequest(), this.getThreadLocalResponse()); } catch (Exception e){ e.printStackTrace(); } this.jspContext.popBody(); return this.jspOut.Body.toString(); }
public class JspFactoryShunt extends JspFactory { .... @Override public PageContext getPageContext( Servlet arg0, ServletRequest arg1, ServletResponse arg2, String arg3, boolean arg4, int arg5, boolean arg6) { Class cls = arg0.getClass(); this.shuntedPageContext = this.shuntedJspFactory.getPageContext( arg0, arg1, arg2, arg3, arg4, arg5, arg6); if (!cls.getName().contains("_gwtrpc_jsp")) return this.shuntedPageContext; jspContext = new PageContextShunt(this.shuntedPageContext); return jspContext; } .... }
public class PageContextShunt extends PageContext { public PageContextShunt(PageContext ctx) { this.shuntedPageContext = ctx; } .... }
}



But, but, but ...,
JspFactory.setDefaultFactory and
JspFactory.getDefaultFactory
are static methods, and affects the whole application, not just a request, so that our version of JspFactory is thrusted into the throats of even JSPs who are not involved in this conspiracy.

We need to a way for our JspFactory impersonator to differentiate between visitors and prisoners, between JSPs not part of the crime from JSPs intent on committing this fraud. Otherwise, the output of the non-complicit JSPs would not be processed as intended thro the normal response out stream.

That is where the suffix, .gwtrpc.jsp comes in. Notice the code in the JspFactoryShunt, which returns the original shunted PageContext for JSPs whose names are without .gwtrpc.jsp.

if (!cls.getName().contains("_gwtrpc_jsp"))
  return this.shuntedPageContext;




Continue next Why Use JSP for GWT RPC Server-side Service

10 comments:

  1. Michael Kors Outlet Online was a huge success there and became very well known. The designer Kors then branched out into accessories including Michael Kors Handbags Clearance. He never lost focus on his American chic styling. Some of his most notable collections include the Michael Kors Totes, Michael Kors satchel and the Designer MK Outlet and Michael Kors Outlet Online Store.

    No one has to know that they are cheap Ray Ban Sale UK and no one will know unless you tell them. Each of the cheap designer Ray Ban Sunglasses Sale UK carries the signature brand on the lens to let you know that you do have authentic designer Cheap Ray Ban Sunglasses UK.

    tags: Cheap Oakley Sunglasses UK,MK Outlet

    ReplyDelete
  2. Ce sac cartable Michael Kors est si universel qu'il pourrait plaire à tout le monde. Dans cet article, je vais essayer de passer en revue les caractéristiques principales et les éléments qui distinguent ce sac à main des autres.

    tags:Bolsos Michael Kors Rebajas,Bolsos Michael Kors Baratos,Bolsos Michael Kors El Corte Ingles

    L’extérieur de ce fourre-tout Michael Kors est un cuir métallisé de laiton froncé et froncé. Si vous connaissez les sacs à main Michael Kors, vous savez que ce cuir sera doux et souple. Les deux grandes poignées supérieures sont attachées au sac avec quelques centimètres de chaînes dorées, puis les moitiés supérieures des bretelles présentent le même cuir couleur laiton.

    tags:Bolsos Michael Kors Baratos,Michael Kors Örhängen

    La diversité des couleurs et la taille utilisable de ce sac le rendent parfait pour un usage quotidien. Les poches intérieures ne manquent pas pour aider à garder les choses en ordre. Il y a des endroits parfaits pour votre téléphone ou votre Blackberry. Le zip top empêche les malfaiteurs de saisir votre sac dans un bar et aide également à contenir tout ce qui se trouve à l'intérieur lorsque vous courez pour créer ce train.

    tags:Windguru Longchamps,Longchamp Soldes Destockage,Pronote College Longchamp

    ReplyDelete