作者:Reza Rahman  文章来源:www.theserverside.com

In the first three articles of this series, I covered optional interfaces for Session beans, Singleton beans, EJB Timer Service enhancements, simplified packaging, asynchronous Session bean invocation and EJB Lite. By popular demand, in this article I will cover WebBeans/EJB 3.1 integration. Remember, none of this has been finalized yet. All of this is really just a peek into the inner workings of the JCP so that you have a chance to provide feedback.

WebBeans and EJB: Together Forever

WebBeans is one of the most exciting JSRs being developed in the Java EE 6 timeframe. The basic value proposition of WebBeans is actually pretty intuitive. If you have developed an application or two using JSF and EJB 3.0, you may have noticed that the JSF backing bean layer is usually pretty thin. In fact, even though you can easily inject EJBs into backing beans using the @EJB annotation, it’s not too far off to classify backing beans as glue-code. WebBeans eliminates this glue-code by allowing you to directly use EJBs as JSF backing beans. We’ll see how great this actually looks in a second.

In addition to effectively integrating the JSF and EJB programming models, WebBeans also adds a number of very cool features including robust annotation-driven DI, further ease-of-use for using the Java EE interceptor model as well as sensible component context management for web applications. This last feature I won’t talk about in great detail since it is requires more of a JSF focus than an EJB focus, but I’ll cover the rest.

WebBeans is largely inspired by JBoss Seam as well as Google Guice. The JSR is being led by Gavin King and Bob Lee is part of the expert group. My guess is that the core Seam code is going to be the basis for the major WebBeans pluggable implementation although it looks like many application servers like Caucho Resin will provide their own implementation as well.

EJBs as JSF Backing Beans

Let’s see what WebBeans is all about by re-factoring an example from EJB 3 in Action. The first substantial Session bean example in EJB 3 in Action is used for adding a bid. The session bean uses JPA to save a Bid entity into the database. Here is how the session bean and the entity would look like in a WebBeans environment:

  1. @Component
  2. @Stateless
  3. @Named("placeBid")
  4. public class PlaceBidBean {
  5. @PersistenceContext
  6. private EntityManager entityManager;
  7. @In
  8. private Bid bid;
  9. public void addBid() {
  10. entityManager.persist(bid);
  11. }
  12. }
  13. @Component
  14. @Entity
  15. @Named("bid")
  16. public class Bid {
  17. private Long bidId;
  18. private String bidder;
  19. private String item;
  20. private Double bidPrice;
  21. @Id
  22. @GeneratedValue
  23. public Long getBidId() {
  24. return bidId;
  25. }
  26. public void setBidId(Long bidId) {
  27. this.bidId = bidId;
  28. }
  29. public String getBidder() {
  30. return bidder;
  31. }
  32. public void setBidder(String bidder) {
  33. this.bidder = bidder;
  34. }
  35. public String getItem() {
  36. return item;
  37. }
  38. public void setItem(String item) {
  39. this.item = item;
  40. }
  41. public Double getBidPrice() {
  42. return bidPrice;
  43. }
  44. public void setBidPrice(Double bidPrice) {
  45. this.bidPrice = bidPrice;
  46. }
  47. }

@Component @Stateless @Named("placeBid") public class PlaceBidBean { @PersistenceContext private EntityManager entityManager; @In private Bid bid; public void addBid() { entityManager.persist(bid); } } @Component @Entity @Named("bid") public class Bid { private Long bidId; private String bidder; private String item; private Double bidPrice; @Id @GeneratedValue public Long getBidId() { return bidId; } public void setBidId(Long bidId) { this.bidId = bidId; } public String getBidder() { return bidder; } public void setBidder(String bidder) { this.bidder = bidder; } public String getItem() { return item; } public void setItem(String item) { this.item = item; } public Double getBidPrice() { return bidPrice; } public void setBidPrice(Double bidPrice) { this.bidPrice = bidPrice; } }

The @Component annotation on both the PlaceBidBean stateless session bean and the Bid JPA entity registers these components with the WebBeans container. @Named annotation assigns names to the components that the WebBeans container knows them by. These names are then used in JSF pages to refer to the components. The @In annotation on the bid instance variable injects a Bid entity into the session bean. It’ll be clearer how this works when you look at the JSP code below that uses the WebBeans components. Figure 1 depicts how the page actually looks like to the bidder adding the bid.

  1. <html>
  2. ...
  3. <body>
  4. <f:view>
  5. ...
  6. <h:form>
  7. <table>
  8. <tr>
  9. <td>Bidder</td>
  10. <td><h:inputText value="#{bid.bidder}"/></td>
  11. </tr>
  12. <tr>
  13. <td>Item</td>
  14. <td><h:inputText value="#{bid.item}"/></td>
  15. </tr>
  16. <tr>
  17. <td>Bid Amount</td>
  18. <td><h:inputText value="#{bid.bidPrice}"/></td>
  19. </tr>
  20. </table>
  21. ...
  22. <h:commandButton type="submit" value="Add Bid"
  23. action="#{placeBid.addBid}"/>
  24. ...
  25. </h:form>
  26. ...
  27. </f:view>
  28. </body>
  29. </html>

<html> ... <body> <f:view> ... <h:form> <table> <tr> <td>Bidder</td> <td><h:inputText value="#{bid.bidder}"/></td> </tr> <tr> <td>Item</td> <td><h:inputText value="#{bid.item}"/></td> </tr> <tr> <td>Bid Amount</td> <td><h:inputText value="#{bid.bidPrice}"/></td> </tr> </table> ... <h:commandButton type="submit" value="Add Bid" action="#{placeBid.addBid}"/> ... </h:form> ... </f:view> </body> </html>

Figure 1: Add Bid Page

As you can see, the bidder, item and bid amount fields in the JSP are bound to the corresponding properties of the Bid entity through EL. The names “bid" and “placeBid" in the EL match the values of the @Named annotation placed on the components. When WebBeans first encounters the bean name corresponding to the Bid entity, it creates a new instance of the entity behind the scenes and places it in the underlying page request context. Notice also that the PlaceBidBean.addBid method is bound as the action listener for the button to add the bid. When the button is clicked and the underlying form is submitted, WebBeans binds the values of the form fields to the Bid entity properties. It then injects the populated entity into the bid instance variable of the PlaceBidBean session bean because of the @In annotation. Unlike the Bid entity, the EJB is looked up from JNDI and placed into the request context. When the addBid method is invoked to handle the button click, the EJB uses the JPA entity manager to save the injected entity. Other than the request context, WebBeans also understands the application, session and very innovative “conversation" contexts. For details of these contexts, check out the WebBeans draft specification.

The appeal of the WebBeans programming model in the code above really cannot be understated. WebBeans unifies JSF, EJB and JPA in a way that makes Java EE really feel like one seamlessly integrated platform that just works out of the box and minimizes boilerplate code, much like what you might be used to while working with frameworks like Ruby on Rails. What do you think? Do you think this is compelling? Can you see any pitfalls to this model?

WebBeans Dependency Injection

A large majority of enterprise application components are either service components, DAOs or domain model components. While JPA is ideal for implementing domain model components, service and DAO components are good candidates for EJB. This is because EJBs are transactional and thread-safe by default (a lot of people seem to have the misconception that EJBs are remote-enabled by default as well; this is not true). EJB is even more of an obvious component model if you might use declarative services for security, remoting, web services, messaging, scheduling or asynchronous processing. These services are at our fingertips in the form of decorating an EJB with an annotation or two as needed.

However, there are some components in an application that simply don’t need declarative services, don’t need to be transaction-aware and don’t need implicit thread-safety guarantees. Good examples of such components are utilities or helper components. Because EJB 3.0 did not support dependency injection for non-managed components, it was not possible to use DI for such components without making them EJBs. WebBeans dependency injection solves these problems because the @Component annotation can be applied to any POJO, not just EJBs and JPA entities. Just as the @In annotation was used to inject the Bid entity into the PlaceBidBean stateless session bean, WebBeans can also inject plain components into EJBs.

Let’s take a look at a quick example. Let’s assume that the bid amount entered by the user is rounded up to two decimal places using a utility class before the bid is saved. This can be done as follows:

@Component   public class MathUtil {       ...       public static double round(double value, int decimalPlaces) {           BigDecimal converter = new BigDecimal(Double.toString(value));           converter = converter.setScale(decimalPlaces,                BigDecimal.ROUND_HALF_UP);           return converter.doubleValue();       }       ...   }   @Component   @Stateless   @Named("placeBid")   public class PlaceBidBean {       @PersistenceContext       private EntityManager entityManager;         @In         private Bid bid;         @In         private MathUtil mathUtil;           public void addBid() {             bid.setBidPrice(mathUtil.round(bid.getBidPrice(), 2));               entityManager.persist(bid);       }   }  

@Component public class MathUtil { ... public static double round(double value, int decimalPlaces) { BigDecimal converter = new BigDecimal(Double.toString(value)); converter = converter.setScale(decimalPlaces, BigDecimal.ROUND_HALF_UP); return converter.doubleValue(); } ... } @Component @Stateless @Named("placeBid") public class PlaceBidBean { @PersistenceContext private EntityManager entityManager; @In private Bid bid; @In private MathUtil mathUtil; public void addBid() { bid.setBidPrice(mathUtil.round(bid.getBidPrice(), 2)); entityManager.persist(bid); } }

In this case, a new instance of MathUtil will be created and injected into the EJB as needed. Although plain WebBeans components cannot directly use EJB declarative services, they can use DI themselves, as well as life-cycle callbacks ( @PostConstruct/ @PreDestroy) and interceptors.

The @In and @Component annotations are really just the tip of the ice-berg. WebBeans brings a whole host of other DI features into Java EE, including Guice style producer methods and binding annotations. Note that all EJB types including message driven beans can use WebBeans features.

WebBeans Interceptor Enhancements

Another major WebBeans feature very relevant to EJB is a very cool extension to the existing interceptor model. You can currently apply interceptors to EJBs using the @Interceptor and @Interceptors annotations. While this structure is both pretty easy to understand and intuitive, it is not very flexible. WebBeans introduces a little more flexibility to interceptors without making things more complex by introducing an annotation-based indirection. The easiest way to understanding this is though code. Let’s assume that we want to apply an auditing interceptor to the PlaceBidBean EJB. This is how we could do it:

  1. @InterceptorBindingType
  2. @Target({TYPE, METHOD})
  3. @Retention(RUNTIME)
  4. public @interface Audited {}
  5. @Audited @Interceptor
  6. public class AuditInterceptor {
  7. @AroundInvoke
  8. public Object audit(InvocationContext context) throws Exception {
  9. System.out.println("Entering: "
  10. + context.getMethod().getName());
  11. System.out.println("  with args: "
  12. + context.getParameters());
  13. return context.proceed();
  14. }
  15. }
  16. @Component
  17. @Stateless
  18. @Named("placeBid")
  19. public class PlaceBidBean {
  20. @PersistenceContext
  21. private EntityManager entityManager;
  22. @In
  23. private Bid bid;
  24. @Audited
  25. public void addBid() {
  26. entityManager.persist(bid);
  27. }
  28. }

@InterceptorBindingType @Target({TYPE, METHOD}) @Retention(RUNTIME) public @interface Audited {} @Audited @Interceptor public class AuditInterceptor { @AroundInvoke public Object audit(InvocationContext context) throws Exception { System.out.println("Entering: " + context.getMethod().getName()); System.out.println(" with args: " + context.getParameters()); return context.proceed(); } } @Component @Stateless @Named("placeBid") public class PlaceBidBean { @PersistenceContext private EntityManager entityManager; @In private Bid bid; @Audited public void addBid() { entityManager.persist(bid); } }

The @InterceptorBindingType annotation on the @Audited annotation is used to declare the fact that it is to be bound to an interceptor. Unlike the EJB 3.0 interceptor model, WebBeans uses the @Interceptor annotation to bind one or more annotations to a given interceptor. So the @Audited and @Interceptor annotations placed on AuditInterceptor means that the @Audited annotation placed on a component or method binds it to the interceptor. As a result, when the placeBid method is invoked, the AuditInterceptor is triggered and the audit method executes.

In addition to adding a level of indirection and flexibility, I think this extension really improves code readability. What do you think? Should this extension be adopted into the EJB specification itself or be applied to Java EE as a whole?

Still in the Works

Activity on the expert groups had understandably slowed down a bit due to JavaOne. However, things are picking back up strongly again. There are still a number of very interesting topics that are being actively discussed:

  1. The standardization of JNDI mappings is being simultaneously discussed in the Java EE 6 and EJB 3.1 expert groups. Looks like some very neat things will happen very soon in this area.
  2. Support for using EJB 3.1 in Java SE environments (e.g. unit tests) is still in the works. The fact that Embedded GlassFish has followed the OpenEJB, EasyBeans and Embedded JBoss path is a strong indication to me that this is solidly on track.
  3. A great extensibility mechanism proposal is being discussed in the Java EE 6 expert group. Looks like this might eventually end up in the EJB expert group as well. If this goes through, it will be a breeze to add non-standard third party declarative, annotation-based services to Java EE.

What are your thoughts on these features? If you think they are important, voice your opinion by emailing the expert groups. The EJB 3.1 expert group email address is jsr-318-comments@jcp.org while the WebBeans expert group email address is jsr-299-comments@jcp.org. Feel free to copy me at reza@rahmannet.net. In the meanwhile, I’ll keep you informed as things settle down on the remaining features in the next and possibly last article in this series.

References

  1. JSR 316: Java EE 6, http://jcp.org/en/jsr/detail?id=316.
  2. JSR 318: Enterprise JavaBeans 3.1, http://jcp.org/en/jsr/detail?id=318.
  3. JSR 299: Web Beans, http://jcp.org/en/jsr/detail?id=299.
  4. Seam, http://www.seamframework.org.
  5. Google Guice, http://code.google.com/p/google-guice/.

转载于:https://www.cnblogs.com/lanzhi/archive/2009/02/01/6469621.html

New features in EJB3.1 (Part 4)相关推荐

  1. jee6 学习笔记 5 - Struggling with JSF2 binding GET params

    这题目可能有点儿吓人,但却是实事求是. 我们看看JSF2有哪些方法来获取HTTP GET parameters: 1. use of new JSF tag "f:viewParam&quo ...

  2. EJB3.0开发环境的搭建

    EJB Container的介绍 SUN公司正式推出了EJB的规范之后,在众多的公司和开发者中引起了非常大的反响.标志着用Java开发企业级应用系统将变的非常easy.很多公司都已经推出了或正打算EJ ...

  3. Jboss EJB3.0实例教程

    Jboss EJB3.0实例教程 第一章 前言............................................................................. ...

  4. Jboss EJB3.0 实例教程

    第一章 前言.............................................................................................. ...

  5. PyTorch加载模型model.load_state_dict()问题,Unexpected key(s) in state_dict: “module.features..,Expected .

    希望将训练好的模型加载到新的网络上.如上面题目所描述的,PyTorch在加载之前保存的模型参数的时候,遇到了问题. Unexpected key(s) in state_dict: "mod ...

  6. OpenCV中的SURF(Speeded-Up Robust Features 加速鲁棒特征)

    OpenCV中的SURF(加速健壮功能) 1. 效果图 2. 原理 2.1 为什么SURF比SIFT快? 2.3 怎样获取SIFT与SURF? 3. 源码 参考 上一篇博客介绍了用于关键点检测和描述的 ...

  7. OpenCV中的快速特征检测——FAST(Features from Accelerated Segment Test)

    OpenCV中的快速特征检测--FAST(Features from Accelerated Segment Test) 1. 效果图 2. 源码 参考 OpenCV中的尺度不变特征变换(SIFT S ...

  8. keras系列︱图像多分类训练与利用bottleneck features进行微调(三)

    引自:http://blog.csdn.net/sinat_26917383/article/details/72861152 中文文档:http://keras-cn.readthedocs.io/ ...

  9. EJB3.1 JBoss7.1 Eclipse3.7

    为什么80%的码农都做不了架构师?>>>    EJB3.1 JBoss7.1 Eclipse3.7 ------Hello World 一.环境配置: JDK:正常配置 Eclip ...

  10. PPF(Point Pair Features)原理及实战技巧

    简介 基于Point Pair Features(PPF)的6D姿态估计方法PPF,Drost et al., 2010(https://ieeexplore.ieee.org/document/5 ...

最新文章

  1. 运维-系统架构师经验总结:
  2. php 类 init,基于initPHP的框架介绍
  3. python for in list
  4. HDU - 1251 统计难题(字典树)
  5. QT简介及QT环境搭建
  6. UVA-1623 Enter The Dragon (贪心)
  7. SOS宣布与融合子公司成立一家合资企业,专注区块链资产和加密货币等业务
  8. 夸大 iPhone 防水功能?苹果遭起诉,曾已被罚 1200 万美元
  9. 我的第一个Python随笔
  10. 自定义对象和json互转
  11. 使用阿里云code和git管理项目
  12. 2018服务器cpu性能天梯图,哪里看CPU性能排行榜?2018年CPU天梯图最新版(高清)...
  13. 形容词和指示代词-this、that、thses、those_31
  14. 学习逆向知识之用于游戏外挂的实现.第三讲,通过游戏外挂.分析红色警戒金钱基址.以及确定基址小技巧....
  15. php tsrmg,php内核分析(二)-ZTS和zend_try
  16. java周总结1106
  17. 《重装系统》Windows纯净装机+常用工具(最简单易懂教程)--菜鸟小回
  18. 汇报:阳光事业在阳光下进行
  19. 牛市来了,直接买币不就OK了,干嘛非要上矿机?
  20. Python Selenium 字节校招实习岗筛选

热门文章

  1. Aiseesoft HEIC Converter如何在Mac上将HEIC转换为JPG/JPEG或PNG?
  2. 函数对象、对象、原型
  3. 洛谷3004 [USACO10DEC]宝箱Treasure Chest
  4. 【03】创建型-原型模式
  5. 数据库练习集1--读书笔记
  6. Illustrator 教程,如何在 Illustrator 中添加文本段落?
  7. 苹果Mac好用的图片编辑工具:Acorn 再升级
  8. 磁盘已满,如何从 Mac 中删除大文件?
  9. EaseUS Data Recovery Wizard 如何在Mac上恢复已删除文件?
  10. 如何在macOS中关闭优化电池充电功能?