jee6 EJB- Singleton EJB

The idea of the test is to print the instance of the singleton ejb for different requests. The singleton ejb is referenced in the request scoped backing bean. 

the screen shot of the test page: 




the page: "/tst/testSingleton.xhtml" 
Java代码   收藏代码
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"   
  2.     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
  3. <html xmlns="http://www.w3.org/1999/xhtml"  
  4.     xmlns:f="http://java.sun.com/jsf/core"  
  5.     xmlns:h="http://java.sun.com/jsf/html"  
  6.     xmlns:p="http://primefaces.org/ui">  
  7.       
  8. <h:head>  
  9.     <title>Test EJB3.1 @Singleton</title>  
  10. </h:head>  
  11.   
  12. <h:body>  
  13.     <h:form>  
  14.         <p:panel header="Test EJB3.1 @Singleton" toggleable="true" style="width:60%">  
  15.             <h:panelGrid columns="1">  
  16.                 Click "Test" to see if it's the same instance:  
  17.                 <h:outputText id="out" value="#{st.message}" escape="false"/>  
  18.             </h:panelGrid>  
  19.             <p:separator/>  
  20.             <p:commandButton value="Test" action="#{st.test}" update="out"/>  
  21.             <p:spacer width="7"/>  
  22.             <p:commandButton value="Clear" actionListener="#{st.reset}" update="out"/>  
  23.         </p:panel>  
  24.     </h:form>  
  25. </h:body>  
  26. </html>  


the backing bean 
Java代码   收藏代码
  1. package com.jxee.action.test.ejb31;  
  2.   
  3. import java.io.Serializable;  
  4. import java.util.Date;  
  5. import java.util.concurrent.atomic.AtomicInteger;  
  6. import java.util.concurrent.atomic.AtomicReference;  
  7.   
  8. import javax.annotation.PostConstruct;  
  9. import javax.ejb.EJB;  
  10. import javax.faces.bean.ManagedBean;  
  11. import javax.faces.bean.RequestScoped;  
  12.   
  13. import org.apache.log4j.Logger;  
  14.   
  15. import com.jxee.ejb.test.singleton.SingletonEJB;  
  16.   
  17. @ManagedBean(name="st")  
  18. @RequestScoped  
  19. public class SingletonTestBean implements Serializable {  
  20.   
  21.   @EJB // inject the singleton ejb  
  22.   private SingletonEJB single;  
  23.     
  24.   // the message to build up and display. this is a bit over kill anyway.  
  25.   private static final AtomicReference<StringBuffer> message = new AtomicReference<StringBuffer>();  
  26.     
  27.   // this backing bean instances counter  
  28.   private static final AtomicInteger beanCount = new AtomicInteger();  
  29.     
  30.   private static final Logger log = Logger.getLogger(SingletonTestBean.class);  
  31.   
  32.     
  33.   @PostConstruct  
  34.   public void init() {  
  35.     log.debug(String.format(">>> PostConstruct: backing bean inited: %s"this));  
  36.   }  
  37.     
  38.   public String getMessage() {  
  39.     return message.get() != null ? message.get().toString() : "";  
  40.   }  
  41.   
  42.   private void buildMessge(String toappend, boolean reset) {  
  43.     StringBuffer newmsg = new StringBuffer();  
  44.     while(true) {  
  45.       StringBuffer oldmsg = message.get();  
  46.       if(!reset) {  
  47.         if(oldmsg != null) {  
  48.           newmsg.append(oldmsg);  
  49.         }  
  50.         if(toappend != null) {  
  51.           newmsg.append(toappend);  
  52.         }  
  53.       }  
  54.       if(message.compareAndSet(oldmsg, newmsg)) {  
  55.         log.debug(">>> new message appended ok");  
  56.         return;  
  57.       }  
  58.     }  
  59.   }  
  60.     
  61.   public String test() {  
  62.     StringBuffer newmsg = new StringBuffer();  
  63.     newmsg.append("----- request arrived(sec): ")  
  64.           .append(new Date().getTime()/1000)  
  65.           .append("<br/> >>> the backing bean [")  
  66.           .append(beanCount.incrementAndGet()).append("]: ").append(this)  
  67.           .append("<br/> >>> the singleton ejb: ")  
  68.           .append(this.single.getInstance())  
  69.           .append("<br/>");  
  70.     this.buildMessge(newmsg.toString(), false);  
  71.     return null;  
  72.   }  
  73.     
  74.   public void reset() {  
  75.     this.buildMessge(nulltrue);  
  76.   }  
  77. }  


the singleton ejb: 
Java代码   收藏代码
  1. package com.jxee.ejb.test.singleton;  
  2.   
  3. import javax.annotation.PostConstruct;  
  4. import javax.ejb.Singleton;  
  5.   
  6. import org.apache.log4j.Logger;  
  7.   
  8. @Singleton  
  9. public class SingletonEJB {  
  10.     
  11.   private static final Logger log = Logger.getLogger(SingletonEJB.class);  
  12.     
  13.   @PostConstruct  
  14.   public void init() {  
  15.     log.debug(">>> PostConstruct: SingletonEJB");  
  16.   }  
  17.     
  18.   public String getInstance() {  
  19.     return this.toString();  
  20.   }  
  21. }  



Now take a look at concurrency control of singleton session beans. 

The the container makes sure that singleton session bean can only instantiate once. But the @Singleton does not say anything about concurrency control. JEE 6 has annotations to address this issue: @ConcurrencyManagement and @Lock. 

@ConcurrencyManagement applies to the singleton class and has too options ConcurrencyManagementType.CONTAINER(default) and ConcurrencyManagementType.BEAN. 

When using the default, annotation @Lock(LockType.READ | LockType.WRITE) can be used to further control the access levels of shared data. 

Java代码   收藏代码
  1. package com.jxee.ejb.test.singleton;  
  2.   
  3. import javax.annotation.PostConstruct;  
  4. import javax.ejb.ConcurrencyManagement;  
  5. import javax.ejb.ConcurrencyManagementType;  
  6. import javax.ejb.Lock;  
  7. import javax.ejb.LockType;  
  8. import javax.ejb.Singleton;  
  9.   
  10. import org.apache.log4j.Logger;  
  11.   
  12.   
  13. /** 
  14.  * Test @Singleton session ejb. 
  15.  *  
  16.  * ConcurrencyManagementType.CONTAINER is the default concurrency control. 
  17.  * Under container managed concurrency control, @Lock(LockType) can be used 
  18.  * to define READ/WRITE access types. 
  19.  *  
  20.  * Alternative is ConcurrencyManagementType.BEAN. With this option, the bean 
  21.  * developer has to provide control over concurrent accesses to shared data. 
  22.  * Therefore, you can use keyword "synchronized" etc, and i guess, the classes 
  23.  * in package "java.util.concurrent". 
  24.  */  
  25. @ConcurrencyManagement(ConcurrencyManagementType.CONTAINER) // the default  
  26. @Singleton  
  27. public class SingletonEJB {  
  28.     
  29.   private static final Logger log = Logger.getLogger(SingletonEJB.class);  
  30.     
  31.   private static Integer counter = new Integer(1);  
  32.     
  33.   @PostConstruct  
  34.   public void init() {  
  35.     log.debug(">>> PostConstruct: SingletonEJB inited");  
  36.   }  
  37.     
  38.   /** 
  39.    * LockType.READ: For read-only operations. Allows simultaneous access  
  40.    * to methods designated as READ, as long as no WRITE lock is held.  
  41.    */  
  42.   @Lock(LockType.READ)  
  43.   public Integer getCounter() {  
  44.     return counter;  
  45.   }  
  46.   
  47.   /** 
  48.    * LockType.WRITE: For exclusive access to the bean instance.  
  49.    * A WRITE lock can only be acquired when no other method with  
  50.    * either a READ or WRITE lock is currently held.  
  51.    */  
  52.   @Lock(LockType.WRITE)  
  53.   public void setCounter(Integer c) {  
  54.     counter = c;  
  55.   }  
  56.     
  57.   /** 
  58.    * a convenience method 
  59.    */  
  60.   @Lock(LockType.WRITE)  
  61.   public void increment() {  
  62.     counter++;  
  63.   }  
  64.     
  65.   public String getInstance() {  
  66.     return this.toString();  
  67.   }  
  68. }  



结论: 

We can see from the result that the container instantiated different backing bean instance for each request, but the injected singleton ejb was always the same instance. So we can say that the @Singleton does its trick. 

The singleton EJB has all the ejb services available. It can be used to maintain application wide state, such as caching application static data, i suppose? 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值