DZone
Java Zone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
  • Refcardz
  • Trend Reports
  • Webinars
  • Zones
  • |
    • Agile
    • AI
    • Big Data
    • Cloud
    • Database
    • DevOps
    • Integration
    • IoT
    • Java
    • Microservices
    • Open Source
    • Performance
    • Security
    • Web Dev
DZone > Java Zone > How to do Cross-Domain GWT RPC With a ProxyServlet

How to do Cross-Domain GWT RPC With a ProxyServlet

Matt Raible user avatar by
Matt Raible
·
Aug. 06, 09 · Java Zone · Interview
Like (0)
Save
Tweet
13.40K Views

Join the DZone community and get the full member experience.

Join For Free

Last week, I started working on a new project using GWT. On my last project, we used GWT HTTP Calls and my new project is using RPC. We'll likely migrate to a JSON backend eventually, but in the meantime, I wanted to be able to develop in hosted mode (localhost:8888) and call services on another host (localhost:8080), where the services are running in a JSF/Spring webapp.

At first, I thought it'd be easy thanks to the handy-dandy ProxyServlet I mentioned in Implementing OAuth with GWT. However, when I tried to hook it in and use it, I saw the following error in my server-side logs.

java.lang.NullPointerException
at javax.servlet.GenericServlet.getServletName(GenericServlet.java:322)
at javax.servlet.GenericServlet.log(GenericServlet.java:277)
at com.google.gwt.user.server.rpc.RemoteServiceServlet.doGetSerializationPolicy(RemoteServiceServlet.java:219)
at com.google.gwt.user.server.rpc.RemoteServiceServlet.getSerializationPolicy(RemoteServiceServlet.java:117)
at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.prepareToRead(ServerSerializationStreamReader.java:429)
at com.google.gwt.user.server.rpc.RPC.decodeRequest(RPC.java:234)

Looking at RemoteServiceServlet.java:219, there's a logging call that fails for some reason (at least in my application).

/*
* Check that the module path must be in the same web app as the servlet
* itself. If you need to implement a scheme different than this, override
* this method.
*/
if (modulePath == null || !modulePath.startsWith(contextPath)) {
String message = "ERROR: The module path requested, "
+ modulePath
+ ", is not in the same web application as this servlet, "
+ contextPath
+ ". Your module may not be properly configured or your client and server code maybe out of date.";
log(message, null);
}

In the above code, you might notice that GWT is checking to make sure the client is hosted in the same application as the server. After I figured this out, it was pretty easy to modify my ProxyServlet to trick GWT RPC into thinking the client was in the same web application. In the ProxyServlet's handleContentPost method, I added the following code to replace "localhost:8888/" with "localhost:8080/services/" (in the content of the post to the server). 

if (contentType.startsWith("text/x-gwt-rpc")) {
String clientHost = httpServletRequest.getLocalName();
if (clientHost.equals("127.0.0.1")) {
clientHost = "localhost";
}

int clientPort = httpServletRequest.getLocalPort();
String clientUrl = clientHost + ((clientPort != 80) ? ":" +
clientPort : "");
String serverUrl = stringProxyHost + ((intProxyPort != 80) ? ":" +
intProxyPort : "") + httpServletRequest.getServletPath();
postContent = postContent.replace(clientUrl , serverUrl);
}

After manipulating the posted content, I was successfully able to use GWT RPC cross-domain.

Woo hoo!

For your convenience, the full handleContentPost() method is listed below.

private void handleContentPost(PostMethod postMethodProxyRequest, 
HttpServletRequest httpServletRequest)
throws IOException, ServletException {
StringBuilder content = new StringBuilder();
BufferedReader reader = httpServletRequest.getReader();
for (;;) {
String line = reader.readLine();
if (line == null) break;
content.append(line);
}

String contentType = httpServletRequest.getContentType();
String postContent = content.toString();

if (contentType.startsWith("text/x-gwt-rpc")) {
String clientHost = httpServletRequest.getLocalName();
if (clientHost.equals("127.0.0.1")) {
clientHost = "localhost";
}

int clientPort = httpServletRequest.getLocalPort();
String clientUrl = clientHost + ((clientPort != 80) ? ":" +
clientPort : "");
String serverUrl = stringProxyHost + ((intProxyPort != 80) ? ":" +
intProxyPort : "") + httpServletRequest.getServletPath();
postContent = postContent.replace(clientUrl , serverUrl);
}

String encoding = httpServletRequest.getCharacterEncoding();
debug("POST Content Type: " + contentType + " Encoding: " + encoding,
"Content: " + postContent);
StringRequestEntity entity;
try {
entity = new StringRequestEntity(postContent, contentType, encoding);
} catch (UnsupportedEncodingException e) {
throw new ServletException(e);
}
// Set the proxy request POST data
postMethodProxyRequest.setRequestEntity(entity);
}

From http://raibledesigns.com/rd/entry/how_to_do_cross_domain 

application Web Service Host (Unix) Hook security POST (HTTP) JSON authentication

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Role of Development Team in an Agile Environment
  • Applying Kappa Architecture to Make Data Available Where It Matters
  • Maven Tutorial: Nice and Easy [Video]
  • How to Test JavaScript Code in a Browser

Comments

Java Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • MVB Program
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends:

DZone.com is powered by 

AnswerHub logo