java - 使用声明性服务的 OSGi+Pax-Web 中的 GWT 问题

标签 java gwt osgi declarative-services pax-web

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

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

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

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

加载序列化描述符时,GWT 从本地上下文加载序列化策略文件。 就我而言,它尝试解析如下资源:/ctx/ctx/62394587E47773FB1594FF.gwt.rpc 该资源由 GWT 编译器创建并放置在: /war/ctx/ctx/资源...

之前,使用标准 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

最佳答案

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

在 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( list :Webapp-Context + web.xml)部署它。在此部署中,servlet 报告: [getContextPath]->[/ctx]

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

在本例中,servlet 报告: [getContextPath]->[]

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

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

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

PS:继 Pax-web 的 Achim Nierbeck 之后,OSGi 规范正在不断发展以管理 app-ctx 问题: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

关于java - 使用声明性服务的 OSGi+Pax-Web 中的 GWT 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11136105/

相关文章:

serialization - 当我使用 ArrayList 时,如何防止 GWT 尝试包含每个可序列化的类

java - View 和演示者之间的 MVP 和包循环

java - OSGi 片段何时附加到主机?

osgi - 从 Java 访问 Karaf cfg 文件中的属性?

javascript - 要在很长的区域、 Canvas 上渲染多个对象?

java - 如何从代码启动和使用 Apache Felix?

java - 用另一个按钮替换一个按钮

Java 等价于 Python 的 format()

java - 双循环链表的大小

java - 没有数组名称的 JSONArray(地震示例)