除了 EAR 和 EJB 之外,我还可以从 Java EE 应用服务器获得哪些在 Tomcat 等 servlet 容器中无法获得的内容?
我们使用 Tomcat 来托管基于 WAR 的应用程序。 我们是 servlet 容器兼容的 J2EE 应用程序,但 org.apache.catalina.authenticator.SingleSignOn 除外。
我们被要求迁移到商业 Java EE 应用服务器。
- 改变这一点的第一个缺点 我看到的是成本。 无论 申请费用 服务器,Tomcat是免费的。
- 其次是复杂性。 我们不 使用 EJB 或 EAR 功能( 当然不是,我们不能),并且没有错过他们。
那么我没有看到的好处是什么?
还有哪些我没有提到的缺点?
提到的是...
- JTA - Java Transaction API - 我们 通过数据库控制事务 存储过程。
- JPA - Java 持久性 API - 我们使用 JDBC 和存储过程 坚持。
- JMS - Java 消息服务 - 我们使用 XML over HTTP 用于消息传递。
这个不错,请多多指点!
We use Tomcat to host our WAR based applications. We are servlet container compliant J2EE applications with the exception of org.apache.catalina.authenticator.SingleSignOn.
We are being asked to move to a commercial Java EE application server.
- The first downside to changing that
I see is the cost. No matter what
the charges for the application
server, Tomcat is free. - Second is the complexity. We don't
use either EJB nor EAR features (of
course not, we can't), and have not missed them.
What then are the benefits I'm not seeing?
What are the drawbacks that I haven't mentioned?
Mentioned were...
- JTA - Java Transaction API - We
control transaction via database
stored procedures. - JPA - Java Persistence API - We use
JDBC and again stored procedures to
persist. - JMS - Java Message Service - We use
XML over HTTP for messaging.
This is good, please more!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
当我们设定 Java EE 6 认证 Apache Tomcat 为 Apache TomEE 的目标时,以下是我们遇到的一些差距填写才能最终通过Java EE 6 TCK。
不是完整的列表,但有些亮点即使在现有答案中也可能并不明显。
TransactionManager
任何经过认证的服务器都绝对不需要 事务管理。 在任何 Web 组件(servlet、过滤器、侦听器、jsf 托管 bean)中,您应该能够像这样注入
UserTransaction
:@Resource UserTransaction transaction;
您应该能够使用
javax.transaction.UserTransaction
创建事务。 您在该事务范围内接触的所有资源都应该注册到该事务中。 这包括但不限于以下对象:javax.sql.DataSource
javax.persistence.EntityManager
javax.jms.ConnectionFactory
javax.jms.TopicConnectionFactory
javax.ejb.TimerService
例如,如果在 servlet 中启动事务,则
.. 然后其中一件事失败,或者您只需选择在
上调用
,那么所有这些事情都被撤消了。rollback()
UserTransaction无连接池
需要明确的是,有两种连接池:
Java EE 规范并不严格要求连接池,但是如果您有连接池,它应该是事务感知的,或者您将失去您的交易管理。
这基本上意味着:
close()
或DataSource
上的任何其他方法。Tomcat 中用于连接池的通用库是 commons-dbcp。 我们也想在 TomEE 中使用它,但是它不支持事务感知连接池,因此我们实际上将该功能添加到 commons-dbcp(是的,Apache)中,并且从 commons-dbc 版本 1.4 开始它就存在了。
请注意,将 commons-dbcp 添加到 Tomcat 仍然不足以获得事务连接池。 您仍然需要事务管理器,并且仍然需要容器通过
Synchronization
对象来完成注册与TransactionManager
的连接的工作。在 Java EE 7 中,有人讨论添加一种标准方法来加密数据库密码并将其与应用程序一起打包在安全文件或外部存储中。 这将是 Tomcat 不支持的又一项功能。
无安全集成
WebServices 安全、JAX-RS SecurityContext、EJB 安全、JAAS 登录和 JAAC 都是安全概念,默认情况下,即使您单独添加 CXF、OpenEJB 等库,这些概念也不会“挂接到”Tomcat 中。
这些 API 都是当然假设在 Java EE 服务器中一起工作。 我们需要做大量的工作来让所有这些合作并在 Tomcat Realm API 之上完成,以便人们可以使用所有现有的 Tomcat Realm code> 实现来驱动其“Java EE”安全性。 它实际上仍然是 Tomcat 安全性,只是集成得非常好。
JPA 集成 是
的,您可以将 JPA 提供程序放入 .war 文件中并在没有 Tomcat 帮助的情况下使用它。 使用这种方法,您将不会获得:
@PersistenceUnit EntityManagerFactory
注入/查找@PersistenceContext EntityManager
注入/查找EntityManager
池JTA 管理的 EntityManager 基本上意味着同一事务中希望使用 EntityManager 的两个对象将两者都看到相同的
EntityManager
,并且无需显式传递EntityManager
。 所有这些“传递”都是由容器为你完成的。这是如何实现的? 很简单,您从容器中获取的 EntityManager 是假的。 这是一个包装纸。 当您使用它时,它会在当前事务中查找真正的 EntityManager 并将调用委托给该 EntityManager。 这就是神秘的
EntityManager.getDelegate()
方法的原因,因此用户可以根据需要获取真实 EntityManager,并使用任何非标准 API。 当然,这样做时要非常小心,并且永远不要保留对委托EntityManager
的引用,否则您将遇到严重的内存泄漏。 当事务完成时,委托EntityManager
通常会被刷新、关闭、清理和丢弃。 如果您仍然保留引用,则将阻止对该 EntityManager 及其可能包含的所有数据进行垃圾收集。EntityManagerFactory
创建了自己的EntityManager
——您对其管理负有 100% 的责任。CDI 集成
我不想过度简化 CDI,但我发现它有点太大了,很多人都没有认真看一下——它在很多人的“有一天”清单上:) 所以这里只是几个我认为“网络人”会想了解的重点内容。
您知道在典型的网络应用程序中所做的所有操作吗? 整天从
HttpSession
中提取内容? 使用String
作为键并连续转换从HttpSession
获取的对象。 您可能已经使用实用程序代码来为您做到这一点。CDI 也有这个实用程序代码,称为
@SessionScoped
。 任何用@SessionScoped
注解的对象都会被放入HttpSession
中并为您进行跟踪。 您只需通过 @Inject FooObject 请求将对象注入到 Servlet 中,CDI 容器就会以我描述的 EntityManager 事务跟踪相同的方式跟踪“真实”FooObject 实例。 /代码>。 Abracadabra,现在你可以删除一堆代码了:)在
HttpServletRequest
上执行任何getAttribute
和setAttribute
吗? 好吧,您也可以使用@RequestScoped
以相同的方式删除它。当然,还有 @ApplicationScoped 来消除您可能在 ServletContext 上执行的 getAttribute 和 setAttribute
调用更酷的是,像这样跟踪的任何对象都可以实现一个 @PostConstruct ,该方法在创建 bean 时被调用,并且一个
@PreDestroy
方法在所述“范围”被指定时得到通知完成(会话完成,请求结束,应用程序正在关闭)。CDI 可以做更多事情,但这足以让任何人想要重写旧的 Web 应用程序。
一些挑剔的东西
Java EE 6 中添加了一些 Tomcat 驾驶室中未添加的东西。 它们不需要太多的解释,但确实占了“填补空白”的很大一部分。
@DataSourceDefinition
java:global
、java:app
、java:module
)@Resource MyEnum myEnum
进行注入,@Resource Class myPluggableClass
进行类注入,并@Resource(lookup="foo")
要点, 方式在应用程序中定义 DataSource、在 Web 应用程序之间共享 JNDI 条目以及具有简单的能力说“查找这个东西并注入它”可能非常有用
。
但以可移植的 不是完整的列表。 没有提到EJB、JMS、JAX-RS、JAX-WS、JSF、Bean Validation 和其他有用的东西。 但是,当人们谈论 Tomcat 是什么和不是什么时,至少有一些经常被忽视的事情。
另请注意,您可能认为的“Java EE”可能与实际定义不匹配。 随着 Web Profile 的出现,Java EE 已经萎缩了。 这是故意解决“Java EE 太重而我不需要所有这些”的问题。
如果您将 EJB 从 Web Profile 中删除,那么您还剩下以下内容:
这是一个非常有用的堆栈。
When we set out with the goal to Java EE 6 certify Apache Tomcat as Apache TomEE, here are some of the gaps we had to fill in order to finally pass the Java EE 6 TCK.
Not a complete list, but some highlights that might not be obvious even with the existing answers.
No TransactionManager
Transaction Management is definitely required for any certified server. In any web component (servlet, filter, listener, jsf managed bean) you should be able to get a
UserTransaction
injected like so:@Resource UserTransaction transaction;
You should be able use the
javax.transaction.UserTransaction
to create transactions. All the resources you touch in the scope of that transaction should all be enrolled in that transaction. This includes, but is not limited to, the following objects:javax.sql.DataSource
javax.persistence.EntityManager
javax.jms.ConnectionFactory
javax.jms.QueueConnectionFactory
javax.jms.TopicConnectionFactory
javax.ejb.TimerService
For example, if in a servlet you start a transaction then:
.. and then one of those things fails or you simply choose to call
rollback()
on theUserTransaction
, then all of those things are undone.No Connection Pooling
To be very clear there are two kinds of connection pooling:
The Java EE specs do not strictly require connection pooling, however if you have connection pooling, it should be transaction aware or you will lose your transaction management.
What this means is basically:
close()
or any other method on theDataSource
.A common library used in Tomcat for connection pooling is commons-dbcp. We wanted to also use this in TomEE, however it did not support transaction-aware connection pooling, so we actually added that functionality into commons-dbcp (yay, Apache) and it is there as of commons-dbc version 1.4.
Note, that adding commons-dbcp to Tomcat is still not enough to get transactional connection pooling. You still need the transaction manager and you still need the container to do the plumbing of registering connections with the
TransactionManager
viaSynchronization
objects.In Java EE 7 there's talk of adding a standard way to encrypt DB passwords and package them with the application in a secure file or external storage. This will be one more feature that Tomcat will not support.
No Security Integration
WebServices security, JAX-RS SecurityContext, EJB security, JAAS login and JAAC are all security concepts that by default are not "hooked up" in Tomcat even if you individually add libraries like CXF, OpenEJB, etc.
These APIs are all of course suppose to work together in a Java EE server. There was quite a bit of work we had to do to get all these to cooperate and to do it on top of the Tomcat
Realm
API so that people could use all the existing TomcatRealm
implementations to drive their "Java EE" security. It's really still Tomcat security, it's just very well integrated.JPA Integration
Yes, you can drop a JPA provider into a .war file and use it without Tomcat's help. With this approach you will not get:
@PersistenceUnit EntityManagerFactory
injection/lookup@PersistenceContext EntityManager
injection/lookupEntityManager
hooked up to a transactional aware connection poolEntityManager
supportJTA-Managed
EntityManager
basically mean that two objects in the same transaction that wish to use anEntityManager
will both see the sameEntityManager
and there is no need to explicitly pass theEntityManager
around. All this "passing" is done for you by the container.How is this achieved? Simple, the
EntityManager
you got from the container is a fake. It's a wrapper. When you use it, it looks in the current transaction for the realEntityManager
and delegates the call to thatEntityManager
. This is the reason for the mysteriousEntityManager.getDelegate()
method, so users can get the real EntityManager if they want and make use of any non-standard APIs. Do so with great care of course and never keep a reference to the delegateEntityManager
or you will have a serious memory leak. The delegateEntityManager
will normally be flushed, closed, cleaned up and discarded when a transaction completes. If you're still holding onto a reference, you will prevent garbage collection of thatEntityManager
and possibly all the data it holds.EntityManager
you got from the containerEntityManager.getDelegate()
EntityManager
you created yourself via anEntityManagerFactory
-- you are 100% responsible for its management.CDI Integration
I don't want to over simplify CDI, but I find it is a little too big and many people have not take a serious look -- it's on the "someday" list for many people :) So here is just a couple highlights that I think a "web guy" would want to know about.
You know all the putting and getting you do in a typical webapp? Pulling things in and out of
HttpSession
all day? UsingString
for the key and continuously casting objects you get from theHttpSession
. You've probably go utility code to do that for you.CDI has this utility code too, it's called
@SessionScoped
. Any object annotated with@SessionScoped
gets put and tracked in theHttpSession
for you. You just request the object to be injected into your Servlet via@Inject FooObject
and the CDI container will track the "real" FooObject instance in the same way I described the transactional tracking of theEntitityManager
. Abracadabra, now you can delete a bunch of code :)Doing any
getAttribute
andsetAttribute
onHttpServletRequest
? Well, you can delete that too with@RequestScoped
in the same way.And of course there is
@ApplicationScoped
to eliminate thegetAttribute
andsetAttribute
calls you might be doing onServletContext
To make things even cooler, any object tracked like this can implement a
@PostConstruct
which gets invoked when the bean gets created and a@PreDestroy
method to be notified when said "scope" is finished (the session is done, the request is over, the app is shutting down).CDI can do a lot more, but that's enough to make anyone want to re-write an old webapp.
Some picky things
There are some things added in Java EE 6 that are in Tomcats wheelhouse that were not added. They don't require big explanations, but did account for a large chunk of the "filling in the gaps".
@DataSourceDefinition
java:global
,java:app
,java:module
)@Resource MyEnum myEnum
and@Resource Class myPluggableClass
and@Resource(lookup="foo")
Minor points, but it can be incredibly useful to define
DataSource
in the app in a portable way, share JNDI entries between webapps, and have the simple power to say "look this thing up and inject it"Conclusion
As mentioned, not a complete list. No mention of EJB, JMS, JAX-RS, JAX-WS, JSF, Bean Validation and other useful things. But at least some idea of the things often overlooked when people talk about what Tomcat is and is not.
Also be aware that what you might have thought of as "Java EE" might not match the actual definition. With the Web Profile, Java EE has shrank. This was deliberately to address "Java EE is too heavy and I don't need all that".
If you cut EJB out of the Web Profile, here's what you have left:
It's a pretty darn useful stack.
除非您想要正确的 EJB,否则您不需要全栈 J2EE 服务器(商业或非商业)。
您无需全栈 J2EE 服务器即可拥有大多数 J2EE 功能(例如 JTA、JPA、JMS、JSF)。 全栈 j2ee 的唯一好处是容器将以声明方式代表您管理所有这些。 随着 EJB3 的出现,如果您需要容器托管服务,那么使用容器管理服务是一件好事。
您还可以免费拥有全栈服务器,例如 Glasfish、Geronimo 或 JBoss。
您还可以使用嵌入式 Glasfish(例如,在 Tomcat 内部)运行嵌入式 j2ee 容器托管服务。
如果您想要使用为您良好管理的会话 bean、消息 bean、计时器 bean,甚至使用集群和故障转移,您可能需要 EJB 容器。
我建议管理层根据功能需求考虑升级。 其中一些 EJB 容器可能只是使用嵌入式 Tomcat 作为其 Web 服务器,所以有什么!
有些经理就是喜欢花钱买东西。 请他们考虑捐赠城市庇护所,或者直接去找 BEA。
Unless you want EJB proper, you don't need a full stack J2EE server (commercial or not).
You can have most J2EE features (such as JTA, JPA, JMS, JSF) with no full stack J2EE server. The only benefit of a full stack j2ee is that the container will manage all these on your behalf declaratively. With the advent of EJB3, if you need container managed services, using one is a good thing.
You can also have no cost full stack server such as Glasfish, Geronimo or JBoss.
You can also run embedded j2ee container managed services with embedded Glasfish for example, right inside Tomcat.
You may want an EJB container if you want to use session beans, message beans, timer beans nicely managed for you, even with clustering and fail over.
I would suggest to the management to consider upgrades based on feature need. Some of these EJB containers might just well use embedded Tomcat as their webserver so what gives!
Some managers just like to pay for things. Ask them to consider a city shelter donation or just go for BEA.
如果您被要求迁移到商业 J2EE 服务器,原因可能与 J2EE 堆栈无关,而是出于非技术考虑。
通过商业 J2EE 产品可以获得但通过 Tomcat 无法获得的一件事是技术支持。
这可能不是您考虑的因素,具体取决于您的 Web 应用程序应该满足的服务级别。 当您尝试找出 Tomcat 的问题时,您的应用程序是否会停机,或者这会成为一个主要问题吗?
If you are being asked to move to a commercial J2EE server, the reasons may have nothing to do with the J2EE stack but with non-technical considerations.
One thing that you do get with a commercial J2EE offering that you don't get with Tomcat is technical support.
This may not be a consideration for you, depending on the service levels your web applications are supposed to meet. Can your applications be down while you try and figure out a problem with Tomcat, or will that be a major problem?
成本不一定是一个缺点,因为有一些免费的 J2EE 服务器,例如 JBoss 和 Glassfish。
您的问题假设 (J2EE = Servlet + EJB + EAR),因此,如果您不使用 EJB 或 EAR,那么使用 Servlet 容器以外的任何东西都没有意义。 事实并非如此,J2EE 包含的内容远不止这些。 示例包括:
干杯,
多纳尔
Cost isn't necessarily a downside as there a few free J2EE servers, e.g. JBoss and Glassfish.
Your question assumes that (J2EE = Servlet + EJB + EAR) and therefore, there's no point in using anything more than a Servlet container if you're not using EJB or EAR. This is simply not the case, J2EE includes a lot more than this. Examples include:
Cheers,
Donal
事实上,由于有大量可用的包和库,EJB 容器提供的几乎所有功能都可以添加到现代 servlet 容器(如 Tomcat)中。 因此,如果您想要其中任何功能,您可以“按菜单点菜”获得它们,可以说,成本就是将该功能集成到您的应用程序中的过程。
如果您现在没有“缺少”任何这些功能,那么从实际角度来看,您可能不需要它们。
总而言之,现代 EJB 容器确实非常好,并且预先集成了所有这些服务,这使得它们在某种程度上更易于使用(如果您需要的话)。 有时,某个功能在附近且方便就足以让人们探索它在应用程序中的潜力,而不是将功能的集成过程视为采用的障碍。
考虑到免费 EJB 容器的质量,真的很难想象购买一个容器会有什么用处,特别是考虑到您目前对它没有真正的需求。
不过,我确实鼓励您实际购买一个并试用它并探索该平台。 Glassfish 非常容易上手并且非常好,并且应该可以轻松地按原样使用您的 WAR(或进行非常小的调整)。
作为一项规则,当涉及到运行 Tomcat 与 EJB 容器之间时,问题实际上是为什么不使用一个容器呢? 特别针对 Glassfish,我发现它比 Tomcat 更容易使用,它的主要区别是它的内存占用比 Tomcat 稍大(特别是对于小型应用程序),但在大型应用程序上您甚至不会注意到。 对我来说,内存打击并不是什么大问题,但对其他人来说,这可能是一个问题。
它为我提供了所有这些出色功能的单一来源,而无需爬行网络寻找第三方选项。
In truth, with the vast array of packages and libraries available, there's little an EJB container provides that can't be added to a modern servlet container (ala Tomcat). So, if you ever wanted any of those features, you can get them "ala carte" so to speak with the cost being the process of integrating that feature in to your app.
If you're not "missing" any of these features now, then from a practical standpoint, you probably don't need them.
That all said, the modern EJB containers are really nice, and come with all of those services pre-integrated, making them, somewhat, easier to use should you ever want them. Sometimes having the feature nearby and handy is enough to make someone explore it for its potential in their application, versus seeing the integration process of a feature as a hurdle to adoption.
With the quality of the free EJB containers, it's really hard to imagine how buying one can be at all useful, especially given that you have no real demand for one at the moment.
However, I do encourage you to actually get one and play around with it and explore the platform. Glassfish is very easy to get started with and very good, and should easily take your WARs as is (or with very minor tweaks).
As a rule when it comes between running Tomcat vs an EJB container the question is really why NOT use one? Speaking specifically for Glassfish, I find it easier to use than Tomcat, and It's primary difference is that it can have a moderately larger memory footprint (particularly for a small application) than Tomcat, but on a large application you won't even notice that. For me, the memory hit isn't a big deal, for others it may be an issue.
And it gives me a single source of all this nice functionality without having to crawl the net for a 3rd party option.