SpringOne Americas 2008 的幻灯片和演示
正如我向参加我会议的听众承诺的那样,这是关于我的 dm Server 和并发会话的内容。
dm Server 介绍
本次演示的幻灯片和演示代码已附在我的上一篇文章中:《SpringSource dm Server 入门》。
在会议期间,我遇到了来自 Spring by Example 的 David Winterfeldt,他向我推荐了他很棒的 dm Server 教程。
正如我向参加我会议的听众承诺的那样,这是关于我的 dm Server 和并发会话的内容。
本次演示的幻灯片和演示代码已附在我的上一篇文章中:《SpringSource dm Server 入门》。
在会议期间,我遇到了来自 Spring by Example 的 David Winterfeldt,他向我推荐了他很棒的 dm Server 教程。
我很高兴地宣布,Spring Framework 3.0 M1 终于可以下载了!
本版本包含多项重大变更,包括 3.0 主要主题的开始,例如 EL 和 REST 支持
以及各种细微增强。
请注意,Spring Framework 3.0 需要 Java 5 或更高版本以及 J2EE 1.4 或更高版本。我们将 Java 6 和 Java EE 5 作为主要的平台级别进行构建 - 但请放心,我们将保留与支持 Java 5 的 J2EE 1.4 服务器(如 WebLogic 9 和 WebSphere 6.1)的兼容性。
我们还移除/弃用了一些过时的类。更多信息…
我们刚刚在本周于 SpringOne Americas 会议上发布了一款名为 SpringSource tc Server 的新产品。SpringSource tc Server 是一个基于 Apache Tomcat 的企业级 Web 应用服务器。
尽管 SpringSource 并非首家围绕 Apache Tomcat 构建产品的公司(WebSphere Community Edition 和 JBoss 都将 Tomcat 版本嵌入到其 J2EE 应用服务器中,并且 JBoss Web 2.1.1 的开发者版本也嵌入了 Tomcat),但 tc Server 的独特性在于它保留了 Tomcat servlet/JSP 编程模型。为 Tomcat 编写的应用可以 100% 可移植到…
OSGi Alliance 决定通过在公共注册表中列出供应商特定的 manifest 头部来容纳它们。目的是避免供应商之间以及供应商与 OSGi 自身头部之间的冲突。
注册表目前包含 OSGi 自身的头部、SpringSource dm Server 引入的头部以及 bnd 工具使用的两个头部。
正如在第 1 部分中提到的,我在第二篇博客文章中没有使用 Spring Framework,而是专注于 SpringSource dm Server™ 和 SpringSource Tool Suite 来部署“纯”GWT。
有关 GWT StockWatcher 示例的背景信息以及我正在使用的软件,请参阅第 1 部分。
此处描述的循序渐进的方法将基于我们在第 1 部分中所做的工作,而不是重新开始。我们在第 1 部分中所做的唯一现在要改变的事情是移除对以下项的显式依赖:gwt-servlet.jar库。
好消息是,创建这些依赖项的大部分工作已经为你完成。SpringSource 企业 Bundle 仓库包含大多数常用库的“bundle 化”版本。然而,在撰写本文时,我们的 GWT 依赖项就是一个您需要自己将其转换为 bundle 的库示例…
在他最近的博客文章中,Glyn 介绍了 OSGi 的“uses”指令。在这篇博客中,我想深入探讨 uses 约束违规的原因,并提供一些诊断应用中 uses 问题的技巧。
在大多数示例中,我将使用原生的 Equinox 而不是 dm Server。这是因为 uses 约束并非 dm Server 特有,而是与所有 OSGi 用户相关。在这篇博客的末尾,我将演示 dm Server 内置的一些智能约束失败诊断功能。
uses 违规最常见的原因是一个或多个依赖约束之间的不匹配。下面是三个 manifest 示例:
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 bundle 和两个 eclipselink bundle。显然,这些不是真实的 bundle。spring bundle 导入了版本范围为 [1.0, 2.0) 的 eclipselink 包。很明显,只有 eclipselink_1 bundle 可以满足此约束。现在,考虑以下来自两个不同应用的 manifest:
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] 的 eclipselink,app2 导入了版本范围为 [2.0, 2.0] 的 eclipselink。如果我将这些 bundle 安装到 Equinox 中,然后尝试启动 app bundle,控制台会显示如下内容:
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
这里我们可以看到 spring 和 eclipselink bundle 都已解析。app1 bundle 已经启动,但 app2 bundle 无法启动。要找出原因,我们可以使用 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 bundle 无法解析,因为它导入的 spring.orm.hibernate 包存在 uses 冲突。这意味着 app2 对 spring.orm.hibernate 的导入无法满足,因为它的另一个导入与可能提供 spring.orm.hibernate 的 bundle(在本例中是 spring bundle)上的 uses 约束发生冲突。
诊断这个问题的第一步是找出 spring.orm.hibernate bundle 的可能提供者。根据我们的用例,我们知道唯一可能的提供者是 spring bundle,但如果您不知道提供者,可以使用 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 包由 bundle 2 导出。了解这一点后,我们可以找出 bundle 2 中 spring.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 bundle 需要版本范围为 [1.0, 2.0) 的 eclipselink,而 app2 需要版本范围为 [2.0, 2.0] 的 eclipselink - 这两个范围是互斥的,这意味着 app2 无法与 spring bundle 连线到相同版本的 eclipselink。
如果 uses 列表很长,您可以通过找出列出的哪些包具有多个提供者来缩小可能的违规范围。要出现 uses 约束违规,必须始终存在不止一个提供者。
版本不匹配不是导致依赖约束不匹配的唯一原因。约束不匹配也可能是由于属性以及版本造成的。
如果我们回到之前的例子,修改 spring bundle 的 manifest,使其能够接受 eclipselink 包的 2.0 版本,并放宽 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"
安装 bundle 并启动 app bundle 表明这一变化带来了很大的不同:
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
现在两个 app bundle 都可以启动了。不幸的是,还有一个更微妙的问题等待着我们。取决于安装顺序,这组 bundle 可能仍然无法一起运行。为了说明这一点,让我们将 spring、eclipselink_1 和 app1 作为一次事务安装,并启动 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_2 和 app2:
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 bundle 无法启动。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 约束问题又回来了。按照上一节中确定的诊断步骤在这里不起作用,因为没有依赖约束不匹配——我们知道这一点是因为第一次这些 bundle 解析得很顺利。
这里的问题是解析顺序。这些 bundle 是分两个独立的批次安装和解析的。第一个批次包含 spring、eclipselink_1 和 app1,第二个批次包含 eclipselink_2 和 app2。当第一个批次被解析时(由于启动了 app1 bundle),spring bundle 对 eclipselink 包的导入被连接到 eclipselink_1 bundle。这可以通过控制台确认:
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 bundle 导入的。安装第二个批次时,app2 bundle 无法解析,因为它需要版本为 2.0.0 的 eclipselink,而 spring 已经连接到版本为 1.0.0 的 eclipselink。当所有 bundle 作为一次性安装并解析时,OSGi 解析器将尝试满足所有约束,包括确保 spring.orm.hibernate 上的 uses 约束得到满足。
要解决这个问题,我们不需要更改我们的 bundle。相反,我们可以选择一次性重新安装所有 bundle,或者我们可以对 spring bundle 触发刷新——这实际上是要求 OSGi 重新运行解析过程。现在 eclipselink_2 bundle 已经安装,我们可以期待一个不同的结果:
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 bundle 解析。在 spring 中对 eclipselink 包的连接已更改为由 eclipselink_2 bundle 中导出的 2.0.0 版本来满足。
当您在 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 收购 G2One 以来的首个 Grails 版本发布。Grails 1.0.4 包含多项改进以及对支撑 Grails 的关键库的升级,可以从 Grails 下载页面下载。更具体地说,Grails 1.0.4 集成了大约一周前发布的最新 Spring 2.5.6 版本。
除了改进之外,此版本中还有几个有趣的新功能。第一个是添加了一项新功能,可以更好地支持 GORM 中 Hibernate 用户类型定义的映射。您现在可以映射自定义用户类型…
我很高兴地宣布,SpringSource 已经收购了 G2One,这家公司是 Grails 和 Groovy 的幕后推手。
Grails 与 Spring 和 SpringSource 技术非常契合。Grails 构建在 Spring 之上。它提供了另一种采用 Spring 的途径,Spring 是企业 Java 的事实标准组件模型。Spring(和 Java)的所有强大能力都隐藏在每个基于 Grails 的应用的表面之下——这是 Grails 能够扩展到企业应用的关键原因,也是 Spring 强大和灵活性的证明。
与 Spring 一样,Grails 是一项简化开发者工作并提高生产力的技术。正如我们的新标语,应对 Java 复杂性之战的武器,所反映的那样,简化始终是我们作为一家公司和技术人员工作的核心…
本博客假设您已安装 SpringSource Tool Suite 1.1.1(我使用的是 Eclipse 3.4 版本)、dm Server 1.0.0 和 GWT 1.5。它还假设您对 Java 编程有很好的理解,并对 Javascript 和 Ajax 有基本了解。
为了演示中使用的路径,我在以下位置创建了一个新的 Eclipse 工作区:/Users/bcorrie/gwt/workspace。我包含了一些可以在下面下载的压缩项目,其中包含一个GWT_ROOT_INSTALL我定义的变量。要使用我的项目,导入后请导航到“Preferences” -> “Java” -> “Build Path” -> “Classpath Variables” 并定义您自己的GWT_ROOT_INSTALL…