JavaEE真的是可移植的吗?

JavaEE真的是可移植的吗?,java,jakarta-ee,ejb-3.0,jms,Java,Jakarta Ee,Ejb 3.0,Jms,我正在执行一个JavaEE任务,我是在一次面试中得到的 我以前有一些EJB方面的经验,但与JMS和MDB无关。下面是我从众多的例子中发现的: 应用程序服务器将其主题和队列绑定到不同的JNDI名称,例如topic/queue,jms JBoss上需要activationConfig属性,而在Sun教程中则不是 启动我的应用程序后,jboss警告我我的主题没有绑定(实际上没有绑定——我没有绑定,但我希望它会自动绑定——事实上,在JBoss4.0的一个例子中,自动绑定似乎确实发生了)。建议的解决方案

我正在执行一个JavaEE任务,我是在一次面试中得到的

我以前有一些EJB方面的经验,但与JMS和MDB无关。下面是我从众多的例子中发现的:

  • 应用程序服务器将其主题和队列绑定到不同的JNDI名称,例如
    topic
    /
    queue
    jms
  • JBoss上需要
    activationConfig
    属性,而在Sun教程中则不是
  • 启动我的应用程序后,jboss警告我我的主题没有绑定(实际上没有绑定——我没有绑定,但我希望它会自动绑定——事实上,在JBoss4.0的一个例子中,自动绑定似乎确实发生了)。建议的解决方案是将其映射到一些jboss文件中,甚至使用jboss特定的注释
这可能只是JBoss,但由于它经过认证可以实现规范,因此规范似乎没有指定这些内容。在那里,所有所谓的便携性都消失了

所以我想知道——为什么有人说JavaEE是可移植的,你可以把它部署到另一个应用服务器上,然后它神奇地运行,如果这些极其基本的东西看起来根本不可移植的话


顺便说一句,很抱歉这么说,但我想我可能做错了什么,所以请陈述你的观点。

核心EE应用程序可以不加修改地运行。外部配置是特定于应用程序服务器的

javaee,就像(几乎?)任何标准一样,是实现者努力宣传遵守的东西,但却拼命不想遵守

考虑这个问题:红帽如何赚钱?送东西还是卖东西?如果您编写的代码可以轻松地传输到另一个JavaEE应用程序服务器,这将妨碍他们从您那里赚钱。解决这个问题的方法是值得尊敬的“拥抱并扩展”技术,这项技术被认为是微软的,但实际上,自从第一个标准发布以来,它一直是商业软件供应商的首选工具

如果您严格遵守代码中的JavaEEAPI,那么JBoss(或Geronimo(或JonAS(或…))将与任何其他兼容的应用程序服务器一起运行,只需要在特定于服务器的部署描述符中进行更改。这是拥抱阶段

每台服务器——特别是商业服务器(比如JBoss)—还倾向于向API添加额外的内容以“使事情变得更简单”。(公平地说,这些通常会让事情变得更简单。)开发人员——特别是那些不熟悉标准API的人——经常陷入依赖这些额外API而不以任何方式包装它们的陷阱,因此,如果您希望更改平台,允许这些扩展淹没他们的代码,以至于很难删除它们。这是延伸阶段

从软件历史的任何一点上命名一个标准,你都会发现人们在拥抱和扩展(以至于当人们谈论“致命拥抱”时,我不得不强行将我的想法从供应商锁定问题转移到正确的术语上)。您还将发现最终用户(开发人员或其他人员)爱上了它。JavaEE在这方面与任何其他技术都没有区别


然后考虑到大多数规范的措辞有多糟糕,这只是一个部分答案,但JavaEE6,更准确地说是EJB3.1,最终指定了它。在JavaEE6之前,JNDI命名并没有标准化,每个应用服务器供应商都在使用,这对可移植性(一种供应商锁定)确实是有害的。因此,在J2EE1.4世界中,如果您想简化企业应用程序的可移植性,就必须实现各种策略,通常是在
ServiceLocator
类中。在JavaEE5中引入依赖注入减少了对查找的需求,并以某种方式“改进”了可移植性,但仍然没有关于何时需要JNDI查找以及何时仍然需要polyglot的标准。

Joel说,“我发现这非常适用于JavaEE。考虑JMS异常可能是暂时性的,例如完整队列。这是一个典型的快速生产者/慢速消费者问题,理想情况下生产者会降低油门以匹配消费者的速度。但该错误也可能是致命的,例如授权失败。在第一种情况下,重试最终会成功(通常),而在第二种情况下,在人工干预修复授权失败之前,再多的重试都没有帮助

那么你在你的便携程序中做了什么来解决这个问题呢?一种方法是将每个JMS异常视为致命异常。关闭所有对象并重新初始化程序。有点像用大锤打死苍蝇,但非常轻便。或者,您可以检查JMS异常,看看它是暂时的还是致命的错误,并采取适当的措施。这更有效,但由于JMS异常是特定于提供者的,因此很难移植。我的一些客户已经采取了编写特定于供应商的垫片的方法,这些垫片捕捉JMS异常,并对其执行适合供应商的操作,以便代码可以“可移植”(想想:硬件抽象层的软件等效物)

当然,这只是异常处理。类似的问题普遍存在。考虑重新连接细节。某些传输导致与应用程序或容器的连接失败。有些人将其隐藏起来,认为代码不需要知道这一点。但现实情况是,如果网络永久关闭,几乎所有消息传递应用程序都需要提供警报或日志条目。如果网络出现故障,你不会希望应用程序永远挂起,对吧?因此,最终,即使是在提供透明重新连接的传输上运行的应用程序,也需要编写连接故障代码。传输提供商的特定功能和行为将