在 SpringSource dm Server 中部署 GWT 应用程序 - 第 2 部分

工程 | Ben Corrie | 2008 年 11 月 24 日 | ...

介绍

这是描述在 SpringSource dm Server™ 中构建和部署 GWT 应用程序的分步方法的系列博客中的第二篇。第一篇博客介绍了从 GWT 示例应用程序创建简单 WAR 文件的过程。下一篇博客将介绍如何将我们在 第 1 部分 中创建的 WAR 文件转换为 “共享库” WAR。这意味着我们将把应用程序的 GWT 依赖项外部化到一个 OSGi 捆绑包中,以便它可以被任意数量的 GWT 应用程序共享。您可以将其视为用 GWT 远程处理功能扩展我们的 dm Server。

第 1 部分 中所述,我在这第二篇博客文章中没有使用 Spring 框架,而是专注于 SpringSource dm Server™SpringSource Tool Suite 来部署“纯”GWT。

另请参阅 第 1 部分 以了解 GWT StockWatcher 示例和我正在使用的软件的背景信息。

快速回顾

第 1 部分 中,我们从头开始将 GWT StockWatcher 示例应用程序构建为一个 Eclipse 项目,然后将代码生成到一个动态 Web 项目中,然后将其部署到 dm Server 中。最后,我们将动态 Web 项目导出到 WAR 文件中,并在 STS 之外部署它。

这里描述的分步方法将基于我们在 第 1 部分 中所做的工作,而不是重新开始。我们在 第 1 部分 中所做的唯一要改变的事情是移除对gwt-servlet.jar库的显式依赖。

步骤 1:将我们的 GWT 依赖项转换为 OSGi 捆绑包

首先,再补充一点背景知识。“共享库”方法的整个概念是使用 OSGi 捆绑包之间的显式导入和导出,在 dm Server 中创建依赖项映射。对于像我们的 StockWatcher 示例这样的小型 WAR,这大多只是一个有趣的学术练习。然而,鉴于许多商业 Web 项目以大型 WAR 文件形式发布,这些文件包含数十甚至数百个依赖 jar 文件,将这些依赖项分解为可共享资源不仅从占用空间的角度来看有意义,而且还大大减少了应用程序的打包、版本控制和维护的痛苦。

好消息是,创建这些依赖项的大部分工作已经为您完成。SpringSource 企业捆绑包存储库 包含大多数常用库的“捆绑”版本。但是,在撰写本文时,我们的 GWT 依赖项就是一个您必须将其转换为捆绑包的库示例……

诊断 OSGi uses 冲突

工程 | Rob Harrop | 2008 年 11 月 22 日 | ...

Glyn 在他最近的博客文章中介绍了 OSGi “uses” 指令。在这篇博客中,我想更深入地探讨 uses 约束违规的原因,并提供一些诊断应用程序中 uses 问题的技巧。

对于大多数示例,我将使用原始的 Equinox 而不是 dm Server。原因在于 uses 约束并非 dm Server 特有,而是与所有 OSGi 用户相关。在这篇博客的最后,我将演示 dm Server 中内置的一些智能约束失败诊断。

依赖约束不匹配

uses 违规最常见的原因是一个或多个依赖约束不匹配。举个例子,考虑下面的三个清单

Manifest-Version: 1.0
Bundle-Name: Spring Bundle
Bundle-ManifestVersion: 2
Bundle-SymbolicName: spring
Bundle-Version: 2.5.5
Export-Package: spring.orm.hibernate;version="2.5.5";uses:="eclipselink"
Import-Package: eclipselink;version="[1.0, 2.0)"

Manifest-Version: 1.0
Bundle-Name: EclipseLink 1 Bundle
Bundle-ManifestVersion: 2
Bundle-SymbolicName: eclipselink
Bundle-Version: 1
Export-Package: eclipselink;version="1.0.0"

Manifest-Version: 1.0
Bundle-Name: EclipseLink 2 Bundle
Bundle-ManifestVersion: 2
Bundle-SymbolicName: eclipselink
Bundle-Version: 2
Export-Package: eclipselink;version="2.0.0"

这里您可以看到一个 spring 捆绑包和两个 eclipselink 捆绑包。显然,这些不是真正的捆绑包。spring 捆绑包导入了范围为 [1.0, 2.0)eclipselink 包。显然,只有 eclipselink_1 捆绑包可以满足此约束。现在,考虑来自两个不同应用程序的这些清单

Manifest-Version: 1.0
Bundle-Name: App1 Bundle
Bundle-ManifestVersion: 2
Bundle-SymbolicName: app1
Bundle-Version: 1.0.0
Import-Package: spring.orm.hibernate,eclipselink;version="[1.0, 1.0]"

Manifest-Version: 1.0
Bundle-Name: App2 Bundle
Bundle-ManifestVersion: 2
Bundle-SymbolicName: app2
Bundle-Version: 1.0.0
Import-Package: spring.orm.hibernate,eclipselink;version="[2.0, 2.0]"

这里我们可以看到 app1 导入了范围 [1.0, 1.0] 的 eclipselinkapp2 导入了范围 [2.0, 2.0]eclipselink。如果我将这些捆绑包安装到 Equinox 中,然后尝试启动应用程序捆绑包,控制台会显示类似以下内容

id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.4.0.v20080605-1900
2       RESOLVED    spring_2.5.5
3       RESOLVED    eclipselink_1.0.0
4       RESOLVED    eclipselink_2.0.0
5       ACTIVE      app1_1.0.0
6       INSTALLED   app2_1.0.0

这里我们可以看到 springeclipselink 捆绑包都已解析。app1 捆绑包已启动,但 app2 捆绑包无法启动。要找出原因,我们可以使用 diag 命令

osgi> diag app2
file:/Users/robharrop/dev/resdiag/uses/app2/bin [6]
  Package uses conflict: Import-Package: spring.orm.hibernate; version="0.0.0"

这里我们可以看到 app2 捆绑包无法解析,因为它导入的 spring.orm.hibernate 存在包 uses 冲突。这意味着 app2 中对 spring.orm.hibernate 的导入无法满足,因为它的其他导入之一与可能提供 spring.orm.hibernate 的捆绑包(在本例中是 spring 捆绑包)上的 uses 约束发生冲突。

诊断此问题的第一步是找出 spring.orm.hibernate 捆绑包的可能提供者。从我们的用例中我们知道唯一可能的提供者是 spring 捆绑包,但如果您不知道提供者,可以使用 packages 命令找到它们

osgi> packages spring.orm.hibernate
spring.orm.hibernate; version="2.5.5"<file:/Users/robharrop/dev/resdiag/uses/spring/bin [2]>
  file:/Users/robharrop/dev/resdiag/uses/app1/bin [5] imports

这表明 spring.orm.hibernate 包由捆绑包 2 导出。有了这些知识,我们可以找出捆绑包 2spring.orm.hibernate 包的 uses 指令中列出的包

osgi> headers 2
Bundle headers:
 Bundle-ManifestVersion = 2
 Bundle-Name = Spring Bundle
 Bundle-SymbolicName = spring
 Bundle-Version = 2.5.5
 Export-Package = spring.orm.hibernate;version="2.5.5";uses:="eclipselink"
 Import-Package = eclipselink;version="[1.0, 2.0)"
 Manifest-Version = 1.0

这里我们可以看到 uses 中唯一的包是 eclipselink 包,所以它一定是罪魁祸首。确实,我们可以看到 Spring 捆绑包需要范围为 [1.0, 2.0)eclipselink,而 app2 需要范围为 [2.0, 2.0]eclipselink - 这两个范围是互斥的,这意味着 app2 无法spring 捆绑包连接到相同版本的 eclipselink

uses 列表很长的情况下,您可以通过找出列出的哪些包具有多个供应商来缩小可能的违规范围。必须始终有多个供应商才能看到 uses 约束违规。

版本不匹配并非依赖约束不匹配的唯一原因。约束可能由于属性以及版本而不匹配。

安装顺序问题

如果我们回到之前的示例,并更改 spring 捆绑包的清单,使其能够接受版本 2.0 的 eclipselink 包,并放宽 app1 的范围,使其能够接受 1.0 以上的任何版本,我们应该能够解决这个问题

Manifest-Version: 1.0
Bundle-Name: Spring Bundle
Bundle-ManifestVersion: 2
Bundle-SymbolicName: spring
Bundle-Version: 2.5.5
Export-Package: spring.orm.hibernate;version="2.5.5";uses:="eclipselink"
Import-Package: eclipselink;version="[1.0, 2.0]"

Manifest-Version: 1.0
Bundle-Name: App1 Bundle
Bundle-ManifestVersion: 2
Bundle-SymbolicName: app1
Bundle-Version: 1.0.0
Import-Package: spring.orm.hibernate,eclipselink;version="1.0"

安装捆绑包并启动应用程序捆绑包表明这种改变产生了很大的不同

id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.4.0.v20080605-1900
1       RESOLVED    spring_2.5.5
2       RESOLVED    eclipselink_1.0.0
3       RESOLVED    eclipselink_2.0.0
4       ACTIVE      app1_1.0.0
5       ACTIVE      app2_1.0.0

现在两个应用程序捆绑包都可以启动。不幸的是,还有一个更微妙的问题等待着我们。根据安装顺序,这组捆绑包可能仍然无法一起运行。为了说明这一点,让我们将 springeclipselink_1app1 作为一次事务安装,并启动 app1

id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.4.0.v20080605-1900
1       RESOLVED    spring_2.5.5
2       RESOLVED    eclipselink_1.0.0
3       ACTIVE      app1_1.0.0

现在,让我们安装 eclipselink_2app2

id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.4.0.v20080605-1900
1       RESOLVED    spring_2.5.5
2       RESOLVED    eclipselink_1.0.0
3       ACTIVE      app1_1.0.0
4       RESOLVED    eclipselink_2.0.0
5       INSTALLED   app2_1.0.0

app2 捆绑包无法启动。diag 的输出告诉我们原因

osgi> diag app2
file:/Users/robharrop/dev/resdiag/uses/app2/bin [5]
  Package uses conflict: Import-Package: spring.orm.hibernate; version="0.0.0"

uses 约束又回来了。运行上一节中确定的诊断步骤将无济于事,因为没有依赖约束不匹配——我们知道这一点,因为第一次这些捆绑包解析得很好。

这里的问题是解析顺序。捆绑包分两个不同的块安装和解析。第一个块包括 springeclipselink_1app1,第二个块包括 eclipselink_2app2。当第一个块被解析(由于启动 app1 捆绑包)时,spring 捆绑包会将其对 eclipselink 包的导入连接到 eclipselink_1 捆绑包。这可以通过控制台确认

osgi> bundle app1
file:/Users/robharrop/dev/resdiag/uses/app1/bin [3]
  Id=3, Status=ACTIVE      Data Root=/opt/springsource-dm-server-1.0.0.RELEASE/lib/configuration/org.eclipse.osgi/bundles/3/data
  No registered services.
  No services in use.
  No exported packages
  Imported packages
    spring.orm.hibernate; version="2.5.5"<file:/Users/robharrop/dev/resdiag/uses/spring/bin [1]>
    eclipselink; version="1.0.0"<file:/Users/robharrop/dev/resdiag/uses/eclipselink1/bin [2]>
  No fragment bundles
  Named class space
    app1; bundle-version="1.0.0"[provided]
  No required bundles

请注意,导入的包部分显示 eclipselink 版本 1.0.0 是从 eclipselink_1 捆绑包导入的。当第二个块安装时,app2 捆绑包无法解析,因为它需要版本 2.0.0eclipselink,但 spring 已经连接到版本 1.0.0eclipselink。当所有捆绑包作为一个块安装和解析时,OSGi 解析器将尝试满足所有约束,包括确保 spring.orm.hibernate 上的 uses 约束能够满足。

要解决此问题,我们无需更改我们的捆绑包。相反,我们可以将捆绑包重新安装到一个块中,或者我们可以触发对 spring 捆绑包的刷新——实际上是要求 OSGi 重新运行解析过程。现在 eclipselink_2 捆绑包已安装,我们可以预期会有不同的结果

osgi> refresh spring

osgi> ss

Framework is launched.

id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.4.0.v20080605-1900
1       RESOLVED    spring_2.5.5
2       RESOLVED    eclipselink_1.0.0
3       ACTIVE      app1_1.0.0
4       RESOLVED    eclipselink_2.0.0
5       ACTIVE      app2_1.0.0

osgi> bundle spring
file:/Users/robharrop/dev/resdiag/uses/spring/bin [1]
  Id=1, Status=RESOLVED    Data Root=/opt/springsource-dm-server-1.0.0.RELEASE/lib/configuration/org.eclipse.osgi/bundles/1/data
  No registered services.
  No services in use.
  Exported packages
    spring.orm.hibernate; version="2.5.5"[exported]
  Imported packages
    eclipselink; version="2.0.0"<file:/Users/robharrop/dev/resdiag/uses/eclipselink2/bin [4]>
  No fragment bundles
  Named class space
    spring; bundle-version="2.5.5"[provided]
  No required bundles

请注意,刷新 spring 导致 app2 捆绑包解析。springeclipselink 包的连接已更改,由 eclipselink_2 捆绑包中版本 2.0.0 的导出满足。

dm Server 中的 Uses 约束

当您在 dm Server 中遇到 uses 约束违规时,我们已经尝试为您执行一些分析步骤,特别是识别可能不匹配的依赖约束

Could not satisfy constraints for bundle 'app2' at version '1.0.0'.
 Cannot resolve: app2
  Resolver report:
    Bundle: app2_1.0.0 - Uses Conflict: Import-Package: spring.orm.hibernate; version="0.0.0"
      Possible Supplier: spring_2.5.5 - Export-Package: spring.orm.hibernate; version="2.5.5"
        Possible Conflicts: eclipselink

Uses 约束在企业库中很常见,手动诊断失败可能是一个真正的噩梦。特别是,当导出的包在其 uses 子句中列出 10 个或更多包时,确定可能的冲突可能非常耗时。因此,自动化诊断是必须的,我希望不断改进 dm Server 中的诊断代码,以便处理常见错误变得微不足道。

在下一个版本中,我们计划将诊断工具直接内置到我们的 dm Server Eclipse 工具中,这样大部分问题将由 dm Server 自动诊断。

SpringSource Banner下的首个Grails发布

工程 | Graeme Rocher | 2008 年 11 月 14 日 | ...

我很高兴地宣布,这是自SpringSource收购G2One以来,Grails的首个发布。Grails 1.0.4包含一系列改进以及底层Grails关键库的升级,可从Grails下载页面下载。更具体地说,Grails 1.0.4集成了大约一周前发布的最新的Spring 2.5.6版本

除了改进之外,此版本还有几个有趣的新功能。第一个是添加了一个更好地支持 GORM 中的 Hibernate 用户类型定义的映射的功能。您现在可以映射自定义用户类型……

对抗复杂性的更多武器:SpringSource收购Groovy/Grails领导者

工程 | Rod Johnson | 2008年11月11日 | ...

我很高兴地宣布,SpringSource已收购G2One,该公司是GrailsGroovy的幕后推手。

为什么?

我因为许多原因对这笔交易感到兴奋。

Grails与Spring和SpringSource技术非常契合。Grails建立在Spring之上。它提供了另一种采用Spring的方式,Spring是企业Java的事实标准组件模型。Spring(和Java)的所有强大功能都隐藏在每个基于Grails的应用程序的表面之下——这是Grails能够扩展到企业级应用的关键原因,也是对Spring强大和灵活性的验证。

与 Spring 一样,Grails 是一项简化开发人员生活并提高他们生产力的技术。正如我们的新标语 对抗 Java 复杂性的武器 所反映的那样,简化一直是我们公司和技术人员的核心……

Spring for .NET 1.2.0 发布

发布 | Mark Pollack | 2008年11月10日 | ...

我们很高兴地宣布 Spring for .NET 1.2.0 现已可用。

下载 | 支持 | 文档| 社区

此版本包含以下主要新功能

  • WCF 集成 - 使用依赖注入配置 WCF 服务。将 AOP 通知应用于 WCF 服务。
  • MSMQ 集成 - MSMQ 辅助类,可提高您开发消息应用程序的效率。提供与 Spring 事务管理功能的集成。
  • Apache ActiveMQ 集成 - 辅助类,可提高您使用 ActiveMQ/NMS 开发消息应用程序的效率
  • Quartz 集成 - 使用依赖注入配置 Quartz 作业、调度器、触发器。用于实现 Quartz 作业的便捷类。
  • AOP- 新的基于继承的 AOP 代理生成
  • 支持 NHibernate 2.0.1。
此版本包含自 1.1.2 版本以来大约 100 项错误修复和增强功能。

有关更多详细信息,请参阅变更日志

祝您使用愉快!

Spring JavaConfig 1.0.0.M4 发布

发布 | Chris Beams | 2008 年 11 月 07 日 | ...

亲爱的Spring社区,
我们很高兴地宣布 Spring JavaConfig 1.0.0.M4 现已可用。
下载 | 参考文档 | API 文档

主要亮点

  • @AnnotationDrivenTx - 支持声明式事务管理
  • @AnnotationDrivenConfig - 支持 @Autowired、@Resource 等。
  • @ComponentScan - 直接从 JavaConfig 扫描 @Component 类
  • @AspectJAutoProxy - 一等支持 @Aspect bean
  • @MBeanExport - 一等支持导出 JMX MBean
  • 完整的 PetClinic 示例现已随分发版提供,演示了 JavaConfig 的使用
  • 改进了对 @ExternalValue 和 @PropertiesValueSource 的外部化值支持
  • @ImportXml - 从 JavaConfig 引导 Spring XML bean 定义
  • 改进的错误处理
  • ...以及数十个其他已解决的问题


请试用此里程碑版本,并通过 Spring JavaConfig 论坛问题跟踪器提供您的反馈。有关更多信息,请访问Spring JavaConfig 主页

Chris Beams
Spring JavaConfig 负责人

在 SpringSource dm Server 中部署 GWT 应用程序 - 第 1 部分

工程 | Ben Corrie | 2008 年 11 月 07 日 | ...

介绍

这将是 3 篇系列博客,描述在 SpringSource dm Server™ 中构建和部署 GWT 应用程序的分步方法。博客的重点如下:
  1. 使用 SpringSource Tool Suite 从头开始构建并以 WAR 文件形式将 GWT StockWatcher 示例应用程序部署到 dm Server 中。
  2. 使用 “共享库” 方法部署:如何从 WAR 中移除 GWT 依赖项并将其作为 OSGi 捆绑包部署到 dm Server 中。
  3. 使用 “共享服务” 方法部署:我们将单个 WAR 文件转换为 OSGi 服务,这些服务可以被其他应用程序共享并热插拔。
值得注意的是,我在前两篇博客中都没有使用 Spring 框架。Spring 和 GWT 之间的集成本身就是一个主题,我想尽量让每篇博客都尽可能集中。在第三篇博客中,我将展示如何使用 Spring 发布和消费 OSGi 服务,以及这如何与 GWT 集成。

背景

这篇博客将采取实用的分步方法来构建 此处 描述的 GWT StockWatcher 示例。Google 教程将引导您完成使用 RPC 从头开始构建 GWT 示例所需的步骤。我将逐页引用教程,并讨论各种方法的优缺点。

这篇博客假设您已安装 SpringSource Tool Suite 1.1.1(我使用的是 Eclipse 3.4 版本)、  dm Server 1.0.0GWT 1.5。它还假设您对 Java 编程有很好的理解,并且对 Javascript 和 Ajax 有基本的了解。

为了演示中使用的路径,我在/Users/bcorrie/gwt/workspace创建了一个新的 Eclipse 工作区。我已在下方包含了可以下载的压缩项目,其中包含一个我定义的GWT_ROOT_INSTALL变量。要使用我的项目,当您导入它们时,请导航到“Preferences”->“Java”->“Build Path”->“Classpath Variables”并定义您自己的GWT_ROOT_INSTALL

获取 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,助您加速进步。

了解更多

获得支持

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件,只需一份简单的订阅。

了解更多

即将举行的活动

查看 Spring 社区所有即将举行的活动。

查看所有