This post shows how to create Singleton Session Bean. And will cover following topics.
1. Create Singleton Session Bean
2. Initializing and Ordering Singleton Session Bean
3. Counter Example with Hit Count
Template.xhtml:
BeanTest.xhtml:
TestBean.java
1. Create Singleton Session Bean
2. Initializing and Ordering Singleton Session Bean
3. Counter Example with Hit Count
1. Create Singleton Session Bean
The javax.ejb.Singleton annotation is used to specify that the enterprise bean implementation class is a singleton session bean:
@Singleton
public class SingletonBean { ... }
public class SingletonBean { ... }
In this example, A web application named Counter is created with JSF2 framework. Ad all
beans are created in this application.
2. Initializing and Ordering Singleton Session Bean
Sinbleton Session bean are initialized by 2 ways:
-- EJB container (Weblogic, GlassFish, JBOSS etc) initializes the bean before 1st request comes to that client. In this way, the container will decide when the bean will initialize.
-- Another way is eager initialization. Here the class is annotated with javax.ejb.Startup annotation. The bean is initialized upon application startup. The following is the example of eager initialization.
-- Another way is eager initialization. Here the class is annotated with javax.ejb.Startup annotation. The bean is initialized upon application startup. The following is the example of eager initialization.
@Startup
@Singleton
public class StatusBean {
@PostConstruct
private void init()
{
System.out.println("StatusBean initialized...");
}
}
@Singleton
public class StatusBean {
@PostConstruct
private void init()
{
System.out.println("StatusBean initialized...");
}
}
When the container startup after deployment the project containing the bean, the part of the server console output are as follows: (Here I use GlassFish Server)
Info: WEB0671: Loading application [Counter] at [/Counter]
Info: Counter was successfully deployed in 1,755 milliseconds.
Info: keepstate options resolved to true, saving appId 96493622293626880 for application Counter.
Info: EJB5181:Portable JNDI names for EJB StatusBean: [java:global/Counter/StatusBean!test.ejb.StatusBean, java:global/Counter/StatusBean]
Info: StatusBean initialized...
Info: Initializing Mojarra 2.1.6 (SNAPSHOT 20111206) for context '/Counter'
Info: WEB0671: Loading application [Counter] at [/Counter]
Info: Counter was successfully deployed in 3,495 milliseconds.
Info: Counter was successfully deployed in 1,755 milliseconds.
Info: keepstate options resolved to true, saving appId 96493622293626880 for application Counter.
Info: EJB5181:Portable JNDI names for EJB StatusBean: [java:global/Counter/StatusBean!test.ejb.StatusBean, java:global/Counter/StatusBean]
Info: StatusBean initialized...
Info: Initializing Mojarra 2.1.6 (SNAPSHOT 20111206) for context '/Counter'
Info: WEB0671: Loading application [Counter] at [/Counter]
Info: Counter was successfully deployed in 3,495 milliseconds.
Sometimes multiple singleton session beans are used to initialize data for an application and therefore need to be initialized in a specific order. The javax.ejb.DependsOn annotation to declare the startup dependencies. The @DependsOn annotation can take multiple session beans name as string but there order not necessarily depends on the listing order.
To illustrate ordering of singleton session bean, I use 3 singleton session beans: PrimaryBean, SecondaryBean, TertiaryBean.
PrimaryBean is a normal singleton session bean. It has @PostConstruct annotation method and getHit() business method. There is nothing special to this bean.
@Singleton
public class PrimaryBean {
private String name="PrimaryBean";
private int hit = 0;
@PostConstruct
private void init()
{
System.out.println(name + " initialized...");
}
public int getHit() {
hit++;
return hit;
}
}
public class PrimaryBean {
private String name="PrimaryBean";
private int hit = 0;
@PostConstruct
private void init()
{
System.out.println(name + " initialized...");
}
public int getHit() {
hit++;
return hit;
}
}
The following is SecondaryBean. It uses eager initialization by using @Startup annotation. @DependsOn annotation tells that PrimaryBean will be initialized first before SecondaryBean initialized and SecondaryBean will be initialized during application startup.
@Startup
@Singleton
@DependsOn("PrimaryBean")
public class SecondaryBean {
private String name="SecondaryBean";
private int hit = 0;
@PostConstruct
private void init()
{
System.out.println(name + " initialized...");
}
public int getHit() {
hit++;
return hit;
}
}
@Singleton
@DependsOn("PrimaryBean")
public class SecondaryBean {
private String name="SecondaryBean";
private int hit = 0;
@PostConstruct
private void init()
{
System.out.println(name + " initialized...");
}
public int getHit() {
hit++;
return hit;
}
}
The following is TertiaryBean and it'll be initialized upon injection or 1st request come to the bean. The DependsOn annotation defines that PrimaryBean and SecondaryBean must be initialized before this bean. And order is not like listing their names. In this example, SecondayBean depends on PrimaryBean, so the order of initialization as follows: PrimaryBean, SecondaryBean, TertiaryBean. Here 1st two beans are initialized during application startup.
@Singleton
@DependsOn({"PrimaryBean", "SecondaryBean"})
public class TertiaryBean {
private String name = "TertiaryBean";
private int hit = 0;
@PostConstruct
private void init()
{
System.out.println(name + " initialized...");
}
public int getHit() {
hit++;
return hit;
}
}
@DependsOn({"PrimaryBean", "SecondaryBean"})
public class TertiaryBean {
private String name = "TertiaryBean";
private int hit = 0;
@PostConstruct
private void init()
{
System.out.println(name + " initialized...");
}
public int getHit() {
hit++;
return hit;
}
}
After deployment and startup the server, the part of the server console output are as follows:
Info: EJB5181:Portable JNDI names for EJB PrimaryBean: [java:global/Counter/PrimaryBean!test.ejb.PrimaryBean, java:global/Counter/PrimaryBean]
Info: EJB5181:Portable JNDI names for EJB SecondaryBean: [java:global/Counter/SecondaryBean!test.ejb.SecondaryBean, java:global/Counter/SecondaryBean]
Info: EJB5181:Portable JNDI names for EJB TertiaryBean: [java:global/Counter/TertiaryBean!test.ejb.TertiaryBean, java:global/Counter/TertiaryBean]
Info: EJB5181:Portable JNDI names for EJB StatusBean: [java:global/Counter/StatusBean!test.ejb.StatusBean, java:global/Counter/StatusBean]
Info: PrimaryBean initialized...
Info: SecondaryBean initialized...
Info: StatusBean initialized...
Info: Initializing Mojarra 2.1.6 (SNAPSHOT 20111206) for context '/Counter'
Info: WEB0671: Loading application [Counter] at [/Counter]
Info: Counter was successfully deployed in 3,139 milliseconds.
Info: EJB5181:Portable JNDI names for EJB SecondaryBean: [java:global/Counter/SecondaryBean!test.ejb.SecondaryBean, java:global/Counter/SecondaryBean]
Info: EJB5181:Portable JNDI names for EJB TertiaryBean: [java:global/Counter/TertiaryBean!test.ejb.TertiaryBean, java:global/Counter/TertiaryBean]
Info: EJB5181:Portable JNDI names for EJB StatusBean: [java:global/Counter/StatusBean!test.ejb.StatusBean, java:global/Counter/StatusBean]
Info: PrimaryBean initialized...
Info: SecondaryBean initialized...
Info: StatusBean initialized...
Info: Initializing Mojarra 2.1.6 (SNAPSHOT 20111206) for context '/Counter'
Info: WEB0671: Loading application [Counter] at [/Counter]
Info: Counter was successfully deployed in 3,139 milliseconds.
Here TertiaryBean is not initialized because it has no @Startup annotation.
3. Counter Example with Hit Count
Now I'll test these 3 beans - PrimaryBean, SecondaryBean, TertiaryBean by calling getHit() methods of the particular bean. The count of the specific bean will be exist during the whole application life. Therefore i've created Facelets XHTML Template.xhtml and it's client BeanTest.xhtml which has 3 buttons to call 3 beans getHit() methods. The JSF manged bean TestBean.java is used by BeanTest.xhtml. TestBean.java references the beans through dependency injection. The output is as follows:Template.xhtml:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link href="./resources/css/default.css" rel="stylesheet" type="text/css" />
<link href="./resources/css/cssLayout.css" rel="stylesheet" type="text/css" />
<title>Counter - A singleton Session Bean Example.</title>
</h:head>
<h:body>
<div id="top" class="top">
<ui:insert name="top">Top</ui:insert>
</div>
<div id="content" class="center_content">
<ui:insert name="content">Content</ui:insert>
</div>
</h:body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link href="./resources/css/default.css" rel="stylesheet" type="text/css" />
<link href="./resources/css/cssLayout.css" rel="stylesheet" type="text/css" />
<title>Counter - A singleton Session Bean Example.</title>
</h:head>
<h:body>
<div id="top" class="top">
<ui:insert name="top">Top</ui:insert>
</div>
<div id="content" class="center_content">
<ui:insert name="content">Content</ui:insert>
</div>
</h:body>
</html>
BeanTest.xhtml:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html">
<body>
<ui:composition template="./Template.xhtml">
<ui:define name="top">
Test Singleton Bean
</ui:define>
<ui:define name="content">
<h:form>
<h:panelGrid columns="1">
<h:panelGroup>
<h:commandButton value="Test Primary Bean" action="#{testBean.PrimaryBean()}"/>
<h:commandButton value="Test Seconday Bean" action="#{testBean.SecondaryBean()}"/>
<h:commandButton value="Test Tertiary Bean" action="#{testBean.TertiaryBean()}"/>
</h:panelGroup>
<h:outputText value="#{testBean.message}"/>
</h:panelGrid>
</h:form>
</ui:define>
</ui:composition>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html">
<body>
<ui:composition template="./Template.xhtml">
<ui:define name="top">
Test Singleton Bean
</ui:define>
<ui:define name="content">
<h:form>
<h:panelGrid columns="1">
<h:panelGroup>
<h:commandButton value="Test Primary Bean" action="#{testBean.PrimaryBean()}"/>
<h:commandButton value="Test Seconday Bean" action="#{testBean.SecondaryBean()}"/>
<h:commandButton value="Test Tertiary Bean" action="#{testBean.TertiaryBean()}"/>
</h:panelGroup>
<h:outputText value="#{testBean.message}"/>
</h:panelGrid>
</h:form>
</ui:define>
</ui:composition>
</body>
</html>
TestBean.java
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.request;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import test.ejb.PrimaryBean;
import test.ejb.SecondaryBean;
import test.ejb.TertiaryBean;
/**
*
* @author Dell
*/
@ManagedBean
@RequestScoped
public class TestBean {
@EJB
private TertiaryBean tBean;
@EJB
private PrimaryBean pBean;
@EJB
private SecondaryBean sBean;
private String message;
/** Creates a new instance of TestBean */
public TestBean() {
}
public void PrimaryBean()
{
message = "Primary Bean Clicked: " + pBean.getHit() + " times.";
}
public void SecondaryBean()
{
message = "Secondary Bean Clicked: " + sBean.getHit() + " times.";
}
public void TertiaryBean()
{
message = "Tertiary Bean Clicked: " + tBean.getHit() + " times.";
}
public String getMessage() {
return message;
}
}
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.request;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import test.ejb.PrimaryBean;
import test.ejb.SecondaryBean;
import test.ejb.TertiaryBean;
/**
*
* @author Dell
*/
@ManagedBean
@RequestScoped
public class TestBean {
@EJB
private TertiaryBean tBean;
@EJB
private PrimaryBean pBean;
@EJB
private SecondaryBean sBean;
private String message;
/** Creates a new instance of TestBean */
public TestBean() {
}
public void PrimaryBean()
{
message = "Primary Bean Clicked: " + pBean.getHit() + " times.";
}
public void SecondaryBean()
{
message = "Secondary Bean Clicked: " + sBean.getHit() + " times.";
}
public void TertiaryBean()
{
message = "Tertiary Bean Clicked: " + tBean.getHit() + " times.";
}
public String getMessage() {
return message;
}
}
No comments:
Post a Comment