リバースプロキシ問題
通常、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 ); } }
別の問題
上記の措置を施しても、なおエラーが発生する場合がある。
com.google.gwt.user.client.rpc.SerializationException: Type '[Ljp.xxx.yyy.zzz.AAAA;' 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 serialized.: instance = [Ljp.xxx.yyy.zzz.AAAA;@1bca390a at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serialize(ServerSerializationStreamWriter.java:667) at com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamWriter.writeObject(AbstractSerializationStreamWriter.java:126) at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter$ValueWriter$8.write(ServerSerializationStreamWriter.java:153) at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serializeValue(ServerSerializationStreamWriter.java:587) at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serializeClass(ServerSerializationStreamWriter.java:757) at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serializeImpl(ServerSerializationStreamWriter.java:796) at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serialize(ServerSerializationStreamWriter.java:669) at com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamWriter.writeObject(AbstractSerializationStreamWriter.java:126) at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter$ValueWriter$8.write(ServerSerializationStreamWriter.java:153) at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serializeValue(ServerSerializationStreamWriter.java:587)
答えはこのあたりか