3

我正在迁移在 OSGi (Equinox) 和 Pax-web 上运行的现有 GWT 应用程序,以使用声明式服务而不是程序化服务跟踪器。

我在 Equinox 中使用 Pax-Web。PAX-WEB War 扩展器可以毫无问题地加载基于 WAR 的 GWT 应用程序,但在这种操作方式中您不能拥有声明式服务。

我成功地从战争中重构了所有 servlet,并将它们转换为声明性 OSGi 服务 ( <provide interface="javax.servlet.Servlet"/>)。这样我就摆脱了 servlet 中所有凌乱的 ServiceTracker 代码和特定的 OSGi 依赖项。我进一步复制了所有其他 web.xml 功能,以使用[1]上的信息注册过滤器、提供静态内容和欢迎页面

此时,它通常应该可以工作,但我遇到了 PAX-WEB 和 GWT 尝试加载其资源的方式的问题:

在加载序列化描述符时,GWT 从本地上下文加载序列化策略文件。在我的例子中,它尝试解析这样的资源:/ctx/ctx/62394587E47773FB1594FF.gwt.rpc 此资源由 GWT 编译器创建并放置在:/war/ctx/ctx/resource...

以前,使用标准 wab 映射 ( Webapp-Context: /ctx, Webapp-Root: /war) gwt 会正确找到它的资源。现在我正在使用程序化资源映射:

DefaultResourceMapping resourceMapping = new DefaultResourceMapping();
resourceMapping.setAlias( "/ctx" );
resourceMapping.setPath( "/war" );

GWT 无法加载资源并产生以下错误:

2012-06-20 12:46:36.283:INFO:/:AbcProxy: ERROR: The serialization policy file '/ctx/ctx/600000000000000773FB1594FF.gwt.rpc' was not found; did you forget to include it in this deployment?
2012-06-20 12:46:36.283:INFO:/:AbcProxy: WARNING: Failed to get the SerializationPolicy '600000000000000773FB1594FF' for module 'https://localhost:8443/ctx/ctx/'; a legacy, 1.3.3 compatible, serialization policy will be used.  You may experience SerializationExceptions as a result.

[注意最后一句应该是“你会因此而遇到大量的序列化问题”]

我已经跟踪到 HttpServiceContext 加载资源并将路径解释为文件而不是相对于编程 Web 上下文的 url 的问题:

getting resource: [/mx/mx/6ECAD5B3A6F908CE17E47773FB1594FF.gwt.rpc]
HttpServiceContext | not a URL or invalid URL: [/ctx/ctx/600000000000000773FB1594FF.gwt.rpc], treating as a file path
DefaultHttpContext | Searching bundle [bundle] for resource [/ctx/ctx/600000000000000773FB1594FF.gwt.rpc]

这显然失败了,因为此资源位于捆绑文件系统中的 /war/ctx/ctx/ 下。这似乎与错误 PAXWEB-314 [2] 有关,其实现是将相对路径转换为文件路径:

// IMPROVEMENT start PAXWEB-314
257              try {
258                  resource = new URL(path);
 259                  LOG.debug( "resource: [" + path + "] is already a URL, returning" );
 260                  return resource;
261              }
262                  catch (MalformedURLException e) {
 263                        // do nothing, simply log
264                      LOG.debug( "not a URL or invalid URL: [" + path + "], treating as a file path" );
 265              }
266              // IMPROVEMENT end PAXWEB-314

有没有办法解决这个问题?有人使用 GWT 和 PAX-WEB 使用 OSGi DS 而不是 WAB?一种可能的方法是将 GWT 编译器生成的 /war/ctx 复制回 /ctx,但我想在进入 hack 方向之前找到一个不错的解决方案。

有任何想法吗?

1 - https://github.com/ops4j/org.ops4j.pax.web/blob/master/samples/whiteboard/src/main/java/org/ops4j/pax/web/extender/samples/whiteboard/internal/ Activator.java [2] - http://team.ops4j.org/browse/PAXWEB-314

4

1 回答 1

0

我做了一些进一步的挖掘。

在 GWT 上,这是负责加载这些策略文件的相关代码:[1]

protected SerializationPolicy doGetSerializationPolicy(
      HttpServletRequest request, String moduleBaseURL, String strongName) {
    // The request can tell you the path of the web app relative to the
    // container root.
    String contextPath = request.getContextPath();
    String modulePath = null;
    if (moduleBaseURL != null) {
      try {
        modulePath = new URL(moduleBaseURL).getPath();
      } catch (MalformedURLException ex) {
        // log the information, we will default
        log("Malformed moduleBaseURL: " + moduleBaseURL, ex);
      }
    }
...

在这种情况下,我怀疑 contextPath 是潜在的候选嫌疑人。为了测试这个理论,我部署了一个简单的 servlet 来转储它的上下文。我使用 WAB(清单:Webapp-Context + web.xml)部署它。在此部署中,servlet 报告:[getContextPath]->[/ctx]

然后,使用包含资源映射的编程激活器将部署更改为 OSGi-ds。DefaultResourceMapping resourceMapping = new DefaultResourceMapping(); resourceMapping.setAlias("/ctx"); resourceMapping.setPath("/war");

在这种情况下,servlet 报告:[getContextPath]->[]

转换为 gwt 问题 --> 当 gwt 与 WAB 一起部署时,它在 /ctx/app 中找到它的配置,当我使用编程资源映射时,它正在查看 /app,因此找不到它的资源。

底线:在 PAX-WEB 中,Webapp-Context 不等同于别名。别名不会像 Webapp-Context 那样填充 ContextPath。

针对这种情况,当前唯一的解决方法是让构建将 GWT 生成的文件向下复制一层(消除应用程序上下文路径)

PS: Following Achim Nierbeck from Pax-web, the OSGi spec is evolving to manage the app-ctx issue: http://wiki.osgi.org/wiki/WebExperience

[1] http://code.google.com/p/google-web-toolkit/source/browse/trunk/user/src/com/google/gwt/user/server/rpc/RemoteServiceServlet.java?spec=svn5045&r=5045

于 2012-10-17T14:23:42.897 回答