我正在实施一项JavaEE任务,我在接受采访时获得了这项任务。
我有一些EJB的先前经验,但没有任何与JMS和MDB相关的经验。所以这是我通过众多例子找到的:
topic
/ queue
,jms
activationConfig
属性,而在Sun教程中则不是。这可能只是JBoss,但由于它经过认证可以实现规范,因此规范似乎并未指定这些内容。所有涉嫌携带的东西都消失了。
所以我想知道 - 为什么声称JavaEE是可移植的,你可以把它放在另一个应用程序服务器上然后神奇地运行,如果这些非常基本的东西看起来根本不可移植的话。 / p>
P.S。抱歉咆哮,但我想我可能会做错/做错,所以说出你的意见。
答案 0 :(得分:8)
Java EE,就像(几乎?)任何标准一样,是实施者努力宣传坚持但绝望不想坚持的东西。
考虑一下这个问题:红帽如何赚钱?通过放弃或出售它们?如果您编写的代码可以轻松地转移到另一个Java EE应用程序服务器,这将干扰他们从您那里赚钱。对此的解决方案是微软的“拥抱和扩展”技术,该技术归功于微软,但实际上自第一个标准出版以来一直是商业软件供应商的首选工具。
如果您将严格粘贴到代码中的Java EE API,那么JBoss(或Geronimo(或JonAS(或...)))将运行它以及任何其他兼容的应用程序服务器特定于服务器的部署描述符中唯一需要的更改。这是拥抱阶段。
每个服务器 - 特别是商业用户(如JBoss)! - 也倾向于在API中添加额外的东西以“简化”。 (公平地说,这些通常会使事情变得更容易。)开发人员 - 特别是那些不熟悉标准API的人 - 经常陷入依赖这些额外API的陷阱而不以任何方式包装它们,从而允许这些扩展淹没他们的代码,如果你想改变平台,他们很难删除。这是延长阶段。
从软件历史中的任何一点命名标准,你会发现人们拥抱和扩展(当人们谈论“致命的拥抱”时,我必须强行将我的想法从供应商锁定问题转移到适当的术语)。您还会发现最终用户(开发人员或其他人)不满意。 Java EE与这方面的任何其他技术没有什么不同。
然后你考虑一下大多数规格的措辞是多么糟糕......
答案 1 :(得分:2)
乔尔说“all non-trivial abstractions are, to some degree, leaky。”我发现这非常适用于JavaEE。考虑JMS异常可能是一些瞬态,例如完整队列。这是一个典型的快速生产者/慢消费者问题,理想情况下,生产者将减少以匹配消费者的速度。但是错误也可能是致命的,例如授权失败。在第一种情况下,重试最终会成功(通常),而在第二种情况下,在人类介入修复授权失败之前,任何重试次数都无济于事。
那么你在便携式程序中做了什么来解决这个问题呢?一种方法是将每个JMS异常视为致命异常。关闭所有对象并重新初始化程序。有点像用大锤杀死苍蝇但非常便携。或者,您可以检查JMS异常以查看它是暂时性还是致命错误并采取适当的措施。这样效率要高得多,但由于JMS异常是提供者特定的,因此难以移植。我的一些客户采用了编写特定于供应商的垫片的方法,这些垫片捕获JMS异常并使用它们与供应商相关的东西,以便代码可以“可移植”(想想:软件相当于硬件抽象层)。
当然,这只是异常处理。全面存在类似问题。考虑重新连接细节。某些传输会导致应用程序或容器的连接失败。有些人将其隐藏起来,认为代码不需要知道这一点。但实际情况是,如果网络永久停机,几乎所有消息传递应用程序都需要提供警报或日志条目。如果网络出现故障,您不希望应用程序永远挂起,对吗?因此,即使是在提供透明重新连接的传输上运行的应用程序,也需要对连接失败进行编码。传输提供程序的特定功能和行为将通过JMS的抽象而泄漏。
为了我的钱,JavaEE使技能可以跨运输提供商移植。应用程序需要充分了解底层传输提供程序,以处理浮出水面的抽象。在某种程度上,您可以避免泄漏,应用程序是可移植的,但不能再进一步。
答案 2 :(得分:1)
这只是一个部分答案,但Java EE 6,更确切地说是EJB 3.1,最后指定Portable Global JNDI Names。在Java EE 6之前,JNDI命名没有标准化,每个应用服务器供应商都在使用its own rules,这对于可移植性(一种供应商锁定)确实不好。因此,在J2EE 1.4世界中,如果您希望简化企业应用程序的可移植性,则必须实现各种策略,通常在ServiceLocator
类中。在Java EE 5中引入依赖注入减少了对查找的需求,并以某种方式“改进”了可移植性,但仍然没有标准用于何时需要JNDI查找并且仍需要多语言ServiceLocator
。
答案 3 :(得分:0)
核心EE应用程序可以不变地运行。外部配置是应用程序服务器特定的。