当我们着手将Java EE 6认证Apache Tomcat为Apache TomEE时,以下是为了最终通过Java EE 6 TCK而必须填补的一些空白。
不是一个完整的列表,而是一些亮点,即使有现有的答案也可能不明显。
无事务管理器
任何经过认证的服务器都绝对需要事务管理。在任何Web组件(servlet,filter,listener,jsf托管bean)中,你应该能够像这样注入:UserTransaction
@Resource UserTransaction transaction;
您应该能够使用 来创建交易记录。您在该事务范围内涉及的所有资源都应在该事务中注册。这包括但不限于以下对象:javax.transaction.UserTransaction
javax.sql.DataSource
javax.persistence.EntityManager
javax.jms.ConnectionFactory
javax.jms.QueueConnectionFactory
javax.jms.TopicConnectionFactory
javax.ejb.TimerService
例如,如果在 servlet 中启动事务,则:
- 更新数据库
- 向主题或队列触发 JMS 消息
- 创建计时器以在以后的某个时间点执行工作
..然后其中一件事情失败了,或者你只是选择调用,那么所有这些事情都被撤消了。rollback()
UserTransaction
无连接池
需要明确说明的是,有两种类型的连接池:
Java EE 规范并不严格要求连接池,但是如果您有连接池,它应该是事务感知的,否则您将失去事务管理。
这基本上意味着:
- 同一事务中的每个人都应具有来自池的相同连接
- 在事务完成(提交或回滚)之前,不应将连接返回到池中,无论是否调用了 某人或 上的任何其他方法。
close()
DataSource
Tomcat 中用于连接池的一个常见库是 commons-dbcp。我们也想在TomEE中使用它,但是它不支持事务感知连接池,所以我们实际上将该功能添加到commons-dbcp(yay,Apache)中,并且它从commons-dbc版本1.4开始就存在。
请注意,将 commons-dbcp 添加到 Tomcat 仍然不足以获得事务性连接池。您仍然需要事务管理器,并且仍然需要容器来执行与 via 对象注册连接的管道。TransactionManager
Synchronization
在 Java EE 7 中,有关于添加一种标准方法来加密数据库密码,并将它们与应用程序一起打包在安全文件或外部存储器中。这将是Tomcat不支持的另一个功能。
无安全集成
WebServices Security、JAX-RS SecurityContext、EJB Security、JAAS login 和 JAAC 都是在 Tomcat 中默认不“挂接”的安全概念,即使您单独添加 CXF、OpenEJB 等库也是如此。
当然,这些 API 都假定在 Java EE 服务器中协同工作。我们必须做很多工作才能让所有这些合作,并在Tomcat API之上做到这一点,以便人们可以使用所有现有的Tomcat实现来驱动他们的“Java EE”安全性。它实际上仍然是Tomcat的安全性,它只是很好地集成在一起。Realm
Realm
联合保护区集成
是的,您可以将 JPA 提供程序拖放到 .war 文件中,并在没有 Tomcat 帮助的情况下使用它。使用这种方法,您将无法获得:
-
@PersistenceUnit EntityManagerFactory
注入/查找
-
@PersistenceContext EntityManager
注入/查找
- 连接到事务感知连接池的
EntityManager
- JTA 托管支持
EntityManager
- 扩展的持久性上下文
JTA-Managed基本上意味着同一事务中希望使用一个的两个对象都将看到相同的内容,并且不需要显式传递。所有这些“传递”都是由容器为您完成的。EntityManager
EntityManager
EntityManager
EntityManager
这是如何实现的?很简单,你从容器中得到的是假的。它是一个包装器。使用它时,它会在当前事务中查找 real,并将调用委托给该 。这就是神秘方法的原因,因此用户可以根据需要获得真正的EntityManager,并使用任何非标准API。当然,这样做要非常小心,永远不要保留对委托的引用,否则您将遇到严重的内存泄漏。事务完成时,委托通常将被刷新、关闭、清理和丢弃。如果您仍然保留引用,则可以防止对该引用进行垃圾回收,并可能阻止对它所包含的所有数据进行垃圾回收。EntityManager
EntityManager
EntityManager
EntityManager.getDelegate()
EntityManager
EntityManager
EntityManager
- 始终可以安全地保存对从容器中获取的引用
EntityManager
- 它不安全地持有引用
EntityManager.getDelegate()
- 要非常小心地持有你自己通过一个 - 你100%负责它的管理。
EntityManager
EntityManagerFactory
CDI 集成
我不想过度简化CDI,但我发现它有点太大了,很多人都没有认真看过 - 它在“有一天”的名单上,很多人:)所以这里只是一些亮点,我认为一个“网络人”会想知道。
您知道在典型的Web应用程序中进行的所有放置和操作吗?整天把东西拉进拉出?用于从 中获得的关键和连续转换对象。您可能已经使用实用程序代码来为您执行此操作。HttpSession
String
HttpSession
CDI也有这个实用程序代码,它被称为。任何带有注释的对象都会被放入并跟踪到 中。您只需请求通过将对象注入到您的 Servlet 中,CDI 容器将以与我描述的 事务跟踪相同的方式跟踪 “真正的”FooObject 实例。Abracadabra,现在你可以删除一堆代码:)@SessionScoped
@SessionScoped
HttpSession
@Inject FooObject
EntitityManager
做任何和上 ?好吧,您也可以以相同的方式删除它。getAttribute
setAttribute
HttpServletRequest
@RequestScoped
当然,还有消除您可能正在做的和电话@ApplicationScoped
getAttribute
setAttribute
ServletContext
为了使事情变得更酷,任何像这样跟踪的对象都可以实现一个在创建bean时调用的,并在所述“scope”完成时通知一个方法(会话已完成,请求结束,应用程序关闭)。@PostConstruct
@PreDestroy
CDI可以做得更多,但这足以让任何人都想重写一个旧的Web应用程序。
一些挑剔的事情
Java EE 6 中添加了一些在 Tomcats 驾驶室中没有添加的内容。它们不需要大的解释,但确实占了“填补空白”的很大一部分。
- 支持
@DataSourceDefinition
- 支持全局 JNDI (, 、
java:global
java:app
java:module
)
- 通过和
@Resource MyEnum myEnum
- 通过 和 进行类注入
@Resource Class myPluggableClass
- 支持
@Resource(lookup="foo")
次要的一点,但是在应用程序中以可移植的方式进行定义,在Web应用程序之间共享JNDI条目,并具有简单的功能来表示“查找此内容并注入它”,这可能非常有用。DataSource
结论
如前所述,不是一个完整的列表。没有提到EJB,JMS,JAX-RS,JAX-WS,JSF,Bean Validation和其他有用的东西。但至少对人们谈论雄猫是什么和不是什么时经常被忽视的事情有一些想法。
另请注意,您可能认为的“Java EE”可能与实际定义不符。随着Web Profile的出现,Java EE已经萎缩。这是故意解决“Java EE太重了,我不需要所有这些”。
如果您从 Web 配置文件中删除 EJB,那么您将留下以下内容:
- Java Servlets
- Java ServerPages (JSP)
- Java ServerFaces (JSF)
- Java Transaction API (JTA)
- Java Persistence API (JPA)
- Java Contexts and Dependency Injection (CDI)
- 豆类验证
这是一个非常有用的堆栈。