简体   繁体   English

除了EAR和EJB之外,我从Java EE应用服务器获得了什么,而我没有像Tomcat那样进入servlet容器?

[英]Besides EAR and EJB, what do I get from a Java EE app server that I don't get in a servlet container like Tomcat?

We use Tomcat to host our WAR based applications. 我们使用Tomcat来托管基于WAR的应用程序。 We are servlet container compliant J2EE applications with the exception of org.apache.catalina.authenticator.SingleSignOn. 我们是与servlet容器兼容的J2EE应用程序,但org.apache.catalina.authenticator.SingleSignOn除外。

We are being asked to move to a commercial Java EE application server. 我们被要求迁移到商业Java EE应用服务器。

  1. The first downside to changing that I see is the cost. 改变我看到的第一个缺点是成本。 No matter what the charges for the application server, Tomcat is free. 无论应用服务器的收费是多少,Tomcat都是免费的。
  2. Second is the complexity. 其次是复杂性。 We don't use either EJB nor EAR features (of course not, we can't), and have not missed them. 我们不使用EJB或EAR功能(当然不是,我们不能),并且没有错过它们。

What then are the benefits I'm not seeing? 那么我没有看到的好处是什么?

What are the drawbacks that I haven't mentioned? 我没有提到的缺点是什么?


Mentioned were... 提到的是......

  1. JTA - Java Transaction API - We control transaction via database stored procedures. JTA - Java Transaction API - 我们通过数据库存储过程控制事务。
  2. JPA - Java Persistence API - We use JDBC and again stored procedures to persist. JPA - Java持久性API - 我们使用JDBC和再次存储过程来持久化。
  3. JMS - Java Message Service - We use XML over HTTP for messaging. JMS - Java消息服务 - 我们使用XML over HTTP进行消息传递。

This is good, please more! 这很好,请多多!

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. 当我们以Java EE 6为目标开始将Apache Tomcat认证为Apache TomEE时 ,为了最终传递Java EE 6 TCK,我们必须填补一些空白。

Not a complete list, but some highlights that might not be obvious even with the existing answers. 不是一个完整的列表,但有些亮点即使有现有答案也可能不明显。

No TransactionManager 没有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: 在任何Web组件(servlet,过滤器,监听器,jsf托管bean)中,您应该能够像这样注入UserTransaction

  • @Resource UserTransaction transaction;

You should be able use the javax.transaction.UserTransaction to create transactions. 您应该能够使用javax.transaction.UserTransaction来创建事务。 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: 例如,如果在servlet中启动事务,则:

  • Update the database 更新数据库
  • Fire a JMS message to a topic or queue 将JMS消息发送到主题或队列
  • Create a Timer to do work at some later point 创建一个Timer,以便稍后进行工作

.. and then one of those things fails or you simply choose to call rollback() on the UserTransaction , then all of those things are undone. ..然后其中一个失败或你只是选择在UserTransaction上调用rollback() ,然后撤消所有这些事情。

No Connection Pooling 没有连接池

To be very clear there are two kinds of connection pooling: 要非常清楚,有两种连接池:

  • Transactionally aware connection pooling 事务感知连接池
  • Non-Transactionally aware 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. Java EE规范并不严格要求连接池,但是如果您有连接池,它应该是事务感知的,否则您将丢失事务管理。

What this means is basically: 这意味着什么基本上:

  • Everyone in the same transaction should have the same connection from the pool 同一事务中的每个人都应该从池中具有相同的连接
  • The connection should not be returned to the pool until the transaction completes (commit or rollback) regardless if someone called close() or any other method on the DataSource . 在事务完成(提交或回滚)之前,不管是否有人在DataSource上调用close()或任何其他方法,都不应将连接返回到池。

A common library used in Tomcat for connection pooling is commons-dbcp. 在Tomcat中用于连接池的公共库是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. 我们也希望在TomEE中使用它,但是它不支持事务感知连接池,所以我们实际上将这个功能添加到commons-dbcp(yay,Apache)中,并且它是commons-dbc 1.4版本。

Note, that adding commons-dbcp to Tomcat is still not enough to get transactional connection pooling. 注意,将commons-dbcp添加到Tomcat仍然不足以获得事务连接池。 You still need the transaction manager and you still need the container to do the plumbing of registering connections with the TransactionManager via Synchronization objects. 您仍然需要事务管理器,您仍然需要容器来执行通过Synchronization对象注册与TransactionManager连接的管道。

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. 在Java EE 7中,有人谈到添加标准方法来加密数据库密码,并将它们与应用程序打包在一个安全文件或外部存储中。 This will be one more feature that Tomcat will not support. 这将是Tomcat不支持的另一项功能。

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. Web服务安全性,JAX-RS SecurityContext,EJB安全性,JAAS登录和JAAC都是安全概念,即使您单独添加像CXF,OpenEJB等库,默认情况下也不会在Tomcat中“连接”。

These APIs are all of course suppose to work together in a Java EE server. 当然,这些API都假定在Java EE服务器中协同工作。 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 Tomcat Realm implementations to drive their "Java EE" security. 我们必须做很多工作才能让所有这些合作并在Tomcat Realm API之上进行,以便人们可以使用所有现有的Tomcat Realm实现来驱动他们的“Java EE”安全性。 It's really still Tomcat security, it's just very well integrated. 它仍然是Tomcat的安全性,它只是非常好地集成。

JPA Integration JPA集成

Yes, you can drop a JPA provider into a .war file and use it without Tomcat's help. 是的,您可以将JPA提供程序放入.war文件中,并在没有Tomcat帮助的情况下使用它。 With this approach you will not get: 使用这种方法你不会得到:

  • @PersistenceUnit EntityManagerFactory injection/lookup @PersistenceUnit EntityManagerFactory注入/查找
  • @PersistenceContext EntityManager injection/lookup @PersistenceContext EntityManager注入/查找
  • An EntityManager hooked up to a transactional aware connection pool EntityManager连接到事务感知连接池
  • JTA-Managed EntityManager support JTA管理的EntityManager支持
  • Extended persistence contexts 扩展的持久化上下文

JTA-Managed EntityManager basically mean that two objects in the same transaction that wish to use an EntityManager will both see the same EntityManager and there is no need to explicitly pass the EntityManager around. JTA-Managed EntityManager基本上意味着同一事务中希望使用EntityManager两个对象都将看到相同的EntityManager并且不需要显式传递EntityManager 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. 很简单,你从容器中获得的EntityManager是假的。 It's a wrapper. 这是一个包装。 When you use it, it looks in the current transaction for the real EntityManager and delegates the call to that EntityManager . 当您使用它时,它会在当前事务中查找真实的EntityManager并将调用委托给该EntityManager This is the reason for the mysterious EntityManager.getDelegate() method, so users can get the real EntityManager if they want and make use of any non-standard APIs. 这就是神秘的EntityManager.getDelegate()方法的原因,因此用户可以在需要时使用真正的 EntityManager并使用任何非标准API。 Do so with great care of course and never keep a reference to the delegate EntityManager or you will have a serious memory leak. 当然,这样做非常谨慎,并且永远不会保留对委托EntityManager的引用,否则您将发生严重的内存泄漏。 The delegate EntityManager will normally be flushed, closed, cleaned up and discarded when a transaction completes. 通常在事务完成时刷新,关闭,清理和丢弃委托EntityManager If you're still holding onto a reference, you will prevent garbage collection of that EntityManager and possibly all the data it holds. 如果您仍然持有引用,则将阻止该EntityManager垃圾收集以及它可能包含的所有数据。

  • It's always safe to hold a reference to a EntityManager you got from the container 保持对从容器中获取的EntityManager的引用始终是安全的
  • Its not safe to hold a reference to EntityManager.getDelegate() 保持对EntityManager.getDelegate()的引用是不安全的
  • Be very careful holding a reference to an EntityManager you created yourself via an EntityManagerFactory -- you are 100% responsible for its management. 要非常小心抱着一个参考EntityManager您通过创建自己EntityManagerFactory -你是100%负责其管理。

CDI Integration CDI集成

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. 我不想过度简化CDI,但我发现它有点太大了很多人都没有认真看待 - 对于很多人而言,这是“某一天”的名单:)所以这里只是一些亮点我认为一个“网络人”会想知道。

You know all the putting and getting you do in a typical webapp? 你知道所有的推杆和让你在一个典型的网络应用程序吗? Pulling things in and out of HttpSession all day? 整天把东西拉进HttpSession Using String for the key and continuously casting objects you get from the HttpSession . 使用String作为键并连续地从HttpSession获取对象。 You've probably go utility code to do that for you. 您可能会使用实用程序代码为您执行此操作。

CDI has this utility code too, it's called @SessionScoped . CDI也有这个实用程序代码,它被称为@SessionScoped Any object annotated with @SessionScoped gets put and tracked in the HttpSession for you. 任何使用@SessionScoped注释的对象都会在HttpSession为您进行放置和跟踪。 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 the EntitityManager . 您只需通过@Inject FooObject请求将对象注入到Servlet中,CDI容器将以我描述EntitityManager的事务跟踪的方式跟踪“真实”FooObject实例。 Abracadabra, now you can delete a bunch of code :) Abracadabra,现在你可以删除一堆代码:)

Doing any getAttribute and setAttribute on HttpServletRequest ? HttpServletRequest上执行任何getAttributesetAttribute Well, you can delete that too with @RequestScoped in the same way. 好吧,你也可以用@RequestScoped以同样的方式删除它。

And of course there is @ApplicationScoped to eliminate the getAttribute and setAttribute calls you might be doing on ServletContext 当然还有@ApplicationScoped来消除你可能在ServletContext上做的getAttributesetAttribute调用

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). 为了使事情变得更酷,任何像这样跟踪的对象都可以实现一个@PostConstruct ,它在创建bean时被调用,而@PreDestroy方法在所述“范围”完成时被通知(会话完成,请求结束,该应用程序正在关闭)。

CDI can do a lot more, but that's enough to make anyone want to re-write an old webapp. CDI可以做更多,但这足以让任何人想重新编写一个旧的webapp。

Some picky things 一些挑剔的事情

There are some things added in Java EE 6 that are in Tomcats wheelhouse that were not added. Java EE 6中添加了一些在Tomcats驾驶室中未添加的东西。 They don't require big explanations, but did account for a large chunk of the "filling in the gaps". 他们不需要大的解释,但确实占了“填补空白”的很大一部分。

  • Support for @DataSourceDefinition 支持@DataSourceDefinition
  • Support for Global JNDI ( java:global , java:app , java:module ) 支持全局JNDI( java:globaljava:appjava:module
  • Enum injection via @Resource MyEnum myEnum and Enum注射来自@Resource MyEnum myEnum
  • Class injection via @Resource Class myPluggableClass and 通过@Resource Class myPluggableClass和类注入
  • Support for @Resource(lookup="foo") 支持@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" 小点,但以可移植的方式在应用程序中定义DataSource ,在webapps之间共享JNDI条目,并且具有简单的权力来说“看起来这个并注入它”是非常有用的。

Conclusion 结论

As mentioned, not a complete list. 如上所述,不是一个完整的清单。 No mention of EJB, JMS, JAX-RS, JAX-WS, JSF, Bean Validation and other useful things. 没有提到EJB,JMS,JAX-RS,JAX-WS,JSF,Bean Validation和其他有用的东西。 But at least some idea of the things often overlooked when people talk about what Tomcat is and is not. 但是,当人们谈论Tomcat是什么和不是什么时,至少对事物的一些想法经常被忽视。

Also be aware that what you might have thought of as "Java EE" might not match the actual definition. 另请注意,您可能认为“Java EE”可能与实际定义不匹配。 With the Web Profile, Java EE has shrank. 使用Web Profile,Java EE已经缩减。 This was deliberately to address "Java EE is too heavy and I don't need all that". 这是故意解决“Java EE太重而且我不需要所有这些”。

If you cut EJB out of the Web Profile, here's what you have left: 如果您将EJB从Web配置文件中删除,那么这就是您剩下的内容:

  • Java Servlets Java Servlets
  • Java ServerPages (JSP) Java ServerPages(JSP)
  • Java ServerFaces (JSF) Java ServerFaces(JSF)
  • Java Transaction API (JTA) Java Transaction API(JTA)
  • Java Persistence API (JPA) Java持久性API(JPA)
  • Java Contexts and Dependency Injection (CDI) Java上下文和依赖注入(CDI)
  • Bean Validation Bean验证

It's a pretty darn useful stack. 这是一个非常有用的堆栈。

Unless you want EJB proper, you don't need a full stack J2EE server (commercial or not). 除非您需要适当的EJB,否则您不需要完整的堆栈J2EE服务器(商用或非商用)。

You can have most J2EE features (such as JTA, JPA, JMS, JSF) with no full stack J2EE server. 您可以拥有大多数J2EE功能(例如JTA,JPA,JMS,JSF),而没有完整的堆栈J2EE服务器。 The only benefit of a full stack j2ee is that the container will manage all these on your behalf declaratively. 完整堆栈j2ee的唯一好处是容器将以声明方式代表您管理所有这些。 With the advent of EJB3, if you need container managed services, using one is a good thing. 随着EJB3的出现,如果您需要容器管理服务,使用一个是件好事。

You can also have no cost full stack server such as Glasfish, Geronimo or JBoss. 您也可以没有成本的完整堆栈服务器,如Glasfish,Geronimo或JBoss。

You can also run embedded j2ee container managed services with embedded Glasfish for example, right inside Tomcat. 您也可以使用嵌入式Glasfish运行嵌入式j2ee容器托管服务,例如,在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. 如果要使用会话bean,消息bean,为您精心管理的计时器bean,您可能需要EJB容器,即使使用群集和故障转移也是如此。

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! 其中一些EJB容器可能很好地使用嵌入式Tomcat作为其Web服务器,因此给出了什么!

Some managers just like to pay for things. 有些经理喜欢为事情买单。 Ask them to consider a city shelter donation or just go for BEA. 让他们考虑一个城市住房捐赠或只是去BEA。

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. 如果要求您迁移到商业J2EE服务器,原因可能与J2EE堆栈无关,而是出于非技术考虑。

One thing that you do get with a commercial J2EE offering that you don't get with Tomcat is technical support. 使用Tomcat无法获得的商业J2EE产品可以获得的一件事就是技术支持。

This may not be a consideration for you, depending on the service levels your web applications are supposed to meet. 这可能不是您的考虑因素,具体取决于您的Web应用程序应满足的服务级别。 Can your applications be down while you try and figure out a problem with Tomcat, or will that be a major problem? 当您尝试找出Tomcat的问题时,您的应用程序是否可以关闭,或者这是一个主要问题?

Cost isn't necessarily a downside as there a few free J2EE servers, eg JBoss and Glassfish. 成本不一定是一个缺点,因为有一些免费的J2EE服务器,例如JBoss和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. 您的问题假定(J2EE = Servlet + EJB + EAR)因此,如果您不使用EJB或EAR,那么使用Servlet容器之外没有任何意义。 This is simply not the case, J2EE includes a lot more than this. 事实并非如此,J2EE包含的内容远不止这些。 Examples include: 例子包括:

  • JTA - Java transaction API JTA - Java事务API
  • JPA - Java persistence API JPA - Java持久性API
  • JMS - Java messaging specification JMS - Java消息传递规范
  • JSF - technology for constructing user interfaces out of components JSF - 用于构建组件之外的用户界面的技术

Cheers, Donal 干杯,唐纳德

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). 事实上,由于提供了大量的包和库,因此无法将EJB容器提供给现有的servlet容器(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. 总而言之,现代EJB容器非常好用,并且预先集成了所有这些服务,如果你想要它们,它们在某种程度上更容易使用。 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. 由于免费的EJB容器的质量,很难想象购买一个有用的东西,特别是考虑到你目前没有真正的需求。

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). Glassfish非常容易上手且非常好,并且应该轻松地按照你的WAR(或者进行非常小的调整)。

As a rule when it comes between running Tomcat vs an EJB container the question is really why NOT use one? 作为规则,当运行Tomcat与EJB容器之间时,问题是为什么不使用它? 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. 专门针对Glassfish,我发现它比Tomcat更容易使用,它的主要区别在于它可以拥有比Tomcat更大的内存占用(特别是对于小型应用程序),但在大型应用程序中你甚至不会注意到。 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. 它为我提供了所有这些不错功能的单一来源,而无需为第三方选项抓取网络。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM