JavaEE真的是可移植的吗?

3

我正在实现一项在面试中给我的JavaEE任务。

我之前有一些EJB的经验,但与JMS和MDB无关。所以这是我通过众多例子发现的:

  • 应用服务器将它们的主题和队列绑定到不同的JNDI名称上 - 例如topic/queuejms
  • 在JBoss上需要activationConfig属性,在Sun教程中则不需要。
  • 在启动应用程序后,jboss会警告我我的主题没有绑定(实际上并没有 - 我没有绑定它,但我希望它自动绑定 - 实际上,在JBoss 4.0的一个示例中自动绑定似乎确实发生了)。建议的解决方案是在某些jboss文件中映射它,甚至使用特定于jboss的注释。

这可能仅适用于JBoss,但由于它已获得规范认证,因此规范似乎没有指定这些内容。这里所有所谓的可移植性都消失了。

所以我想知道 - 如果这些非常基本的事情看起来根本不可移植,如何声称JavaEE是可移植的,并且您可以将一个ear部署到另一个应用程序服务器上,它就会自动运行。

P.S. 对不起发牢骚,但我认为我可能做错了/得到了什么,所以请给出您的意见。

4个回答

7

Java EE,像(几乎?)任何标准一样,是实现者努力宣传遵从但却不愿意遵从的东西。

考虑这个问题:Red hat 如何赚钱?通过赠送还是销售?如果您编写的代码可以轻松转移到另一个 Java EE 应用服务器,则会干扰他们从您身上赚钱。解决这个问题的方法是备受尊崇的“拥抱和扩展”技术,这被认为是 Microsoft 的工具,但实际上自第一个标准发布以来,商业软件供应商一直使用它。

如果您在代码中严格遵循 Java EE API,则 JBoss(或 Geronimo(或 JonAS(或...)))将与任何其他符合规范的应用服务器一样运行它,唯一需要更改的是特定于服务器的部署描述符。这是拥抱阶段。

每个服务器 - 特别是商业服务器(如 JBoss)! - 也倾向于向 API 添加额外的内容以“使事情变得更容易”。 (公平地说,这些通常确实使事情变得更容易。)开发人员 - 尤其是那些不熟悉标准 API 的人 - 经常会陷入依赖这些额外 API 的陷阱,而不进行任何包装,从而允许这些扩展淹没他们的代码,以至于如果您希望更改平台,则很难将它们删除。这是扩展阶段。

从软件历史的任何时候命名一个标准,您会发现人们拥抱和扩展(到了人们谈论“致命拥抱”时,我必须强制自己将思维从供应商锁定问题转移到正确的术语上)。您还会发现最终用户(开发人员或其他人)会上当。在这方面,Java EE 与任何其他技术没有区别。

然后考虑大多数规范写得有多糟糕...


2
实际上,能够摆脱它的能力可能是坚持下去的很好理由 :) - Thorbjørn Ravn Andersen
1
然而,你也会遇到一些人甚至没有完成标准,但他们仍然扩展了它。 - L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳
嗯,是的。 这些让我更恼火,甚至比那些拥抱和扩展的人还要让我生气。 - JUST MY correct OPINION

2
乔尔说:“所有非平凡的抽象在某种程度上都是有漏洞的。”我发现这对JavaEE非常适用。考虑到JMS异常可能是一些短暂的问题,比如队列已满。这是一个典型的快速生产者/慢速消费者问题,理想情况下,生产者会减速以匹配消费者的速度。但错误也可能是致命的,比如授权失败。在第一种情况下,重试最终会成功(通常),而在第二种情况下,除非人类介入修复授权失败,否则无论重试多少次都没有帮助。
在您的便携程序中,您采取了什么措施来解决这个问题?一种方法是将每个JMS异常视为致命错误。关闭所有对象并重新初始化程序。有点像用大锤子杀苍蝇,但非常便携。或者,您可以检查JMS异常是否为瞬态或致命错误,并采取适当的措施。这样效率更高,但由于JMS异常是特定于提供者的,因此几乎不具备可移植性。我的一些客户采取了编写特定于供应商的包装器的方法,捕获JMS异常并对其进行供应商特定的处理,以便代码可以“可移植”(想象一下:硬件抽象层的软件等效物)。
当然,这只是异常处理。类似的问题存在于各个领域。考虑重新连接详细信息。某些传输将连接失败上升到应用程序或容器。有些则将其隐藏起来,认为代码不需要知道这一点。但现实情况是,几乎所有的消息应用程序都需要在网络永久故障时提供警报或日志条目。如果网络失败,您肯定不希望应用程序永远挂起,对吧?因此,即使在提供透明重新连接的传输上运行的应用程序,最终也需要为连接故障编写代码。传输提供程序的特定功能和行为将泄漏到JMS的抽象层中。
依我之见,JavaEE使得技能在不同的传输提供商之间具有可移植性。应用程序需要足够了解底层传输提供商,以处理浮出表面的抽象。只要你能避免泄漏,应用程序就是可移植的,但没有更进一步的可能。

“更具可移植性的技能”这一点加1分。历史上,任何标准的主要好处都是因为没有人真正遵守标准。 - JUST MY correct OPINION

1

这只是一个部分答案,但Java EE 6,更确切地说是EJB 3.1,最终指定了可移植全局JNDI名称。在Java EE 6之前,JNDI命名没有标准化,每个应用服务器供应商都使用自己的规则,这对于可移植性来说确实很糟糕(一种供应商锁定)。因此,在J2EE 1.4世界中,如果您想要简化企业应用程序的可移植性,就必须实现各种策略,通常在您的ServiceLocator类中。在Java EE 5中引入依赖注入减少了查找的需求,并在某种程度上“改善”了可移植性,但仍然没有标准来确定何时需要JNDI查找,因此仍需要多语言ServiceLocator


0

核心EE应用程序可以保持不变。外部配置与应用服务器有关。


正如我所指出的,这是非常基础的核心JavaEE - 一个MDB和一个EJB正在向主题发送消息。 - Bozho
基本上,如果您在应用程序服务器上有一个字符串变量,则可以在 JNDI 中外部指定其值,或在应用程序特定的配置文件中指定。除非在规范中明确指定,否则任何“可以在哪里找到此内容”的字符串都是这样的值。 - Thorbjørn Ravn Andersen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接