Revision 4 as of 2014-01-27 01:56:33

Clear message
Locked History Actions

GWT/ReverseProxy

リバースプロキシ問題

通常、gwtアプリをwarファイルとしてtomcatに配備し、apacheと連携させ、ユーザ側にはapache側にアクセスさせることと思われる。 その際、例えばgwtアプリのコンテキストパスがfoobarであるのに、apache側ではルートとしてアクセスさせるような以下のような設定を行うと、

<Location />
 ProxyPass ajp://localhost:8009/foobar/
</Location>

以下のようなエラーが発生する。

Apr 5, 2012 2:37:43 PM org.apache.catalina.core.ApplicationContext log
INFO: Key[type=com.gwtplatform.dispatch.server.guice.DispatchServiceImpl, annotation=[none]]: ERROR: The module path requested, /foobar/, is not in the same web application as this servlet, /foobar.  Your module may not be properly configured or your client and server code maybe out of date.
Apr 5, 2012 2:37:43 PM org.apache.catalina.core.ApplicationContext log
INFO: Key[type=com.gwtplatform.dispatch.server.guice.DispatchServiceImpl, annotation=[none]]: WARNING: Failed to get the SerializationPolicy 'BFA4FE22E9D21F283BBB8900278EB97B' for module 'http://****/foobar/'; a legacy, 1.3.3 compatible, serialization policy will be used.  You may experience SerializationExceptions as a result.
Apr 5, 2012 2:37:43 PM org.apache.catalina.core.ApplicationContext log
SEVERE: Key[type=com.gwtplatform.dispatch.server.guice.DispatchServiceImpl, annotation=[none]]: An IncompatibleRemoteServiceException was thrown while processing this call.
com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException: Type '***' was not assignable to 'com.google.gwt.user.client.rpc.IsSerializable' and did not have a custom field serializer. For security purposes, this type will not be deserialized.
        at com.google.gwt.user.server.rpc.RPC.decodeRequest(RPC.java:315)
        at com.google.gwt.user.server.rpc.RemoteServiceServlet.processCall(RemoteServiceServlet.java:206)
        at com.google.gwt.user.server.rpc.RemoteServiceServlet.processPost(RemoteServiceServlet.java:248)

apache側でルートコンテキストとしてアクセスさせたい場合は、tomcat側でもルートコンテキストとして配備しなければならないらしい。

答えはこのあたりにありそう

解決策

上記のリンクに含まれない、もっと単純な解決策があった。これで一応は動作するが、あらゆる場面で正常かどうかは不明。 対象はGWT 2.5.1 + GWTP 0.7で、GWTPのDispatchServiceImplを置き換えるものだが、これはRemoteServiceServletを継承しているので、生のRemoteServiceServletの場合にも適用可能と思われる。

import java.net.*;
import java.util.logging.*;

import javax.servlet.http.*;

import com.google.gwt.user.server.rpc.*;
import com.google.inject.*;
import com.gwtplatform.dispatch.server.*;
import com.gwtplatform.dispatch.server.guice.*;

@Singleton
public class MyDispatchServiceImpl extends DispatchServiceImpl {
  private static final long serialVersionUID = 1L;
  
  @Inject
  public MyDispatchServiceImpl(Logger logger, Dispatch dispatch,
      RequestProvider requestProvider) {
    super(logger, dispatch, requestProvider);
  }

  @Override
  protected SerializationPolicy doGetSerializationPolicy(
      HttpServletRequest request, String moduleBaseURL, String strongName) {
    
    URL url;
    try {
      url = new URL(moduleBaseURL);
    } catch (Exception ex) {
      throw new RuntimeException(ex);
    }
    String path = url.getPath();
    String host = moduleBaseURL.substring(0, moduleBaseURL.length() - path.length());
    
    return super.doGetSerializationPolicy(
      request, 
      host + request.getContextPath()  + path, 
      strongName
    );    
  }
}