A Singleton Session Bean Example: counter (original) (raw)
2. Using the Tutorial Examples
3. Getting Started with Web Applications
4. JavaServer Faces Technology
7. Using JavaServer Faces Technology in Web Pages
8. Using Converters, Listeners, and Validators
9. Developing with JavaServer Faces Technology
10. JavaServer Faces Technology: Advanced Concepts
11. Using Ajax with JavaServer Faces Technology
12. Composite Components: Advanced Topics and Example
13. Creating Custom UI Components and Other Custom Objects
14. Configuring JavaServer Faces Applications
16. Uploading Files with Java Servlet Technology
17. Internationalizing and Localizing Web Applications
18. Introduction to Web Services
19. Building Web Services with JAX-WS
20. Building RESTful Web Services with JAX-RS
21. JAX-RS: Advanced Topics and Example
23. Getting Started with Enterprise Beans
24. Running the Enterprise Bean Examples
To Run the cart Example Using NetBeans IDE
To Run the cart Example Using Ant
A Web Service Example: helloservice
The Web Service Endpoint Implementation Class
Stateless Session Bean Implementation Class
Running the helloservice Example
To Build, Package, and Deploy the helloservice Example Using NetBeans IDE
To Build, Package, and Deploy the helloservice Example Using Ant
To Test the Service without a Client
Creating Calendar-Based Timer Expressions
Specifying Multiple Values in Calendar Expressions
Running the timersession Example
To Run the timersession Example Using NetBeans IDE
To Build, Package, and Deploy the timersession Example Using Ant
25. A Message-Driven Bean Example
26. Using the Embedded Enterprise Bean Container
27. Using Asynchronous Method Invocation in Session Beans
Part V Contexts and Dependency Injection for the Java EE Platform
28. Introduction to Contexts and Dependency Injection for the Java EE Platform
29. Running the Basic Contexts and Dependency Injection Examples
30. Contexts and Dependency Injection for the Java EE Platform: Advanced Topics
31. Running the Advanced Contexts and Dependency Injection Examples
32. Introduction to the Java Persistence API
33. Running the Persistence Examples
34. The Java Persistence Query Language
35. Using the Criteria API to Create Queries
36. Creating and Using String-Based Criteria Queries
37. Controlling Concurrent Access to Entity Data with Locking
38. Using a Second-Level Cache with Java Persistence API Applications
39. Introduction to Security in the Java EE Platform
40. Getting Started Securing Web Applications
41. Getting Started Securing Enterprise Applications
42. Java EE Security: Advanced Topics
Part VIII Java EE Supporting Technologies
43. Introduction to Java EE Supporting Technologies
45. Resources and Resource Adapters
46. The Resource Adapter Example
47. Java Message Service Concepts
48. Java Message Service Examples
49. Bean Validation: Advanced Topics
50. Using Java EE Interceptors
51. Duke's Bookstore Case Study Example
52. Duke's Tutoring Case Study Example
53. Duke's Forest Case Study Example
The counter example demonstrates how to create a singleton session bean.
Creating a 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 { ... }
Initializing Singleton Session Beans
The EJB container is responsible for determining when to initialize a singleton session bean instance unless the singleton session bean implementation class is annotated with thejavax.ejb.Startup annotation. In this case, sometimes called eager initialization, the EJB container must initialize the singleton session bean upon application startup. The singleton session bean is initialized before the EJB container delivers client requests to any enterprise beans in the application. This allows the singleton session bean to perform, for example, application startup tasks.
The following singleton session bean stores the status of an application and is eagerly initialized:
@Startup @Singleton public class StatusBean { private String status;
@PostConstruct void init { status = "Ready"; } ... }
Sometimes multiple singleton session beans are used to initialize data for an application and therefore must be initialized in a specific order. In these cases, use the javax.ejb.DependsOn annotation to declare the startup dependencies of the singleton session bean. The @DependsOn annotation’s value attribute is one or more strings that specify the name of the target singleton session bean. If more than one dependent singleton bean is specified in @DependsOn, the order in which they are listed is not necessarily the order in which the EJB container will initialize the target singleton session beans.
The following singleton session bean, PrimaryBean, should be started up first:
@Singleton public class PrimaryBean { ... }
SecondaryBean depends on PrimaryBean:
@Singleton @DependsOn("PrimaryBean") public class SecondaryBean { ... }
This guarantees that the EJB container will initialize PrimaryBean before SecondaryBean.
The following singleton session bean, TertiaryBean, depends on PrimaryBean and SecondaryBean:
@Singleton @DependsOn({"PrimaryBean", "SecondaryBean"}) public class TertiaryBean { ... }
SecondaryBean explicitly requires PrimaryBean to be initialized before it is initialized, through its own @DependsOn annotation. In this case, the EJB container will first initializePrimaryBean, then SecondaryBean, and finally TertiaryBean.
If, however, SecondaryBean did not explicitly depend on PrimaryBean, the EJB container may initialize either PrimaryBean or SecondaryBean first. That is, the EJB container could initialize the singletons in the following order: SecondaryBean, PrimaryBean, TertiaryBean.
Managing Concurrent Access in a Singleton Session Bean
Singleton session beans are designed for concurrent access, situations in which many clients need to access a single instance of a session bean at the same time. A singleton’s client needs only a reference to a singleton in order to invoke any business methods exposed by the singleton and doesn’t need to worry about any other clients that may be simultaneously invoking business methods on the same singleton.
When creating a singleton session bean, concurrent access to the singleton’s business methods can be controlled in two ways: container-managed concurrency and bean-managed concurrency.
The javax.ejb.ConcurrencyManagement annotation is used to specify container-managed or bean-managed concurrency for the singleton. With @ConcurrencyManagement, a type attribute must be set to either javax.ejb.ConcurrencyManagementType.CONTAINER or javax.ejb.ConcurrencyManagementType.BEAN. If no @ConcurrencyManagement annotation is present on the singleton implementation class, the EJB container default of container-managed concurrency is used.
Container-Managed Concurrency
If a singleton uses container-managed concurrency, the EJB container controls client access to the business methods of the singleton. The javax.ejb.Lock annotation and a javax.ejb.LockType type are used to specify the access level of the singleton’s business methods or @Timeoutmethods. The LockType enumerated types are READ and WRITE.
Annotate a singleton’s business or timeout method with @Lock(LockType.READ) if the method can be concurrently accessed, or shared, with many clients. Annotate the business or timeout method with @Lock(LockType.WRITE) if the singleton session bean should be locked to other clients while a client is calling that method. Typically, the @Lock(LockType.WRITE)annotation is used when clients are modifying the state of the singleton.
Annotating a singleton class with @Lock specifies that all the business methods and any timeout methods of the singleton will use the specified lock type unless they explicitly set the lock type with a method-level @Lock annotation. If no@Lock annotation is present on the singleton class, the default lock type, @Lock(LockType.WRITE), is applied to all business and timeout methods.
The following example shows how to use the @ConcurrencyManagement, @Lock(LockType.READ), and @Lock(LockType.WRITE)annotations for a singleton that uses container-managed concurrency.
Although by default, singletons use container-managed concurrency, the @ConcurrencyManagement(CONTAINER) annotation may be added at the class level of the singleton to explicitly set the concurrency management type:
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER) @Singleton public class ExampleSingletonBean { private String state;
@Lock(LockType.READ) public String getState() { return state; }
@Lock(LockType.WRITE) public void setState(String newState) { state = newState; } }
The getState method can be accessed by many clients at the same time because it is annotated with @Lock(LockType.READ). When the setState method is called, however, all the methods in ExampleSingletonBean will be locked to other clients because setStateis annotated with @Lock(LockType.WRITE). This prevents two clients from attempting to simultaneously change thestate variable of ExampleSingletonBean.
The getData and getStatus methods in the following singleton are of type READ, and the setStatus method is of type WRITE:
@Singleton @Lock(LockType.READ) public class SharedSingletonBean { private String data; private String status;
public String getData() { return data; }
public String getStatus() { return status; }
@Lock(LockType.WRITE) public void setStatus(String newStatus) { status = newStatus; } }
If a method is of locking type WRITE, client access to all the singleton’s methods is blocked until the current client finishes its method call or an access timeout occurs. When an access timeout occurs, the EJB container throws a javax.ejb.ConcurrentAccessTimeoutException. The javax.ejb.AccessTimeout annotation is used to specify the number of milliseconds before an access timeout occurs. If added at the class level of a singleton, @AccessTimeout specifies the access timeout value for all methods in the singleton unless a method explicitly overrides the default with its own @AccessTimeout annotation.
The @AccessTimeout annotation can be applied to both @Lock(LockType.READ) and @Lock(LockType.WRITE) methods. The@AccessTimeout annotation has one required element, value, and one optional element, unit. By default, the value is specified in milliseconds. To change the value unit, setunit to one of the java.util.concurrent.TimeUnit constants: NANOSECONDS, MICROSECONDS, MILLISECONDS, or SECONDS.
The following singleton has a default access timeout value of 120,000 milliseconds, or 2 minutes. The doTediousOperation method overrides the default access timeout and sets the value to 360,000 milliseconds, or 6 minutes.
@Singleton @AccessTimeout(value=120000) public class StatusSingletonBean { private String status;
@Lock(LockType.WRITE) public void setStatus(String new Status) { status = newStatus; }
@Lock(LockType.WRITE) @AccessTimeout(value=360000) public void doTediousOperation { ... } }
The following singleton has a default access timeout value of 60 seconds, specified using the TimeUnit.SECONDS constant:
@Singleton @AccessTimeout(value=60, timeUnit=SECONDS) public class StatusSingletonBean { ... }
Bean-Managed Concurrency
Singletons that use bean-managed concurrency allow full concurrent access to all the business and timeout methods in the singleton. The developer of the singleton is responsible for ensuring that the state of the singleton is synchronized across all clients. Developers who create singletons with bean-managed concurrency are allowed to use the Java programming language synchronization primitives, such as synchronization and volatile, to prevent errors during concurrent access.
Add a @ConcurrencyManagement annotation with the type set to ConcurrencyManagementType.BEAN at the class level of the singleton to specify bean-managed concurrency:
@ConcurrencyManagement(ConcurrencyManagementType.BEAN) @Singleton public class AnotherSingletonBean { ... }
Handling Errors in a Singleton Session Bean
If a singleton session bean encounters an error when initialized by the EJB container, that singleton instance will be destroyed.
Unlike other enterprise beans, once a singleton session bean instance is initialized, it is not destroyed if the singleton’s business or lifecycle methods cause system exceptions. This ensures that the same singleton instance is used throughout the application lifecycle.
The Architecture of the counter Example
The counter example consists of a singleton session bean, CounterBean, and a JavaServer Faces Facelets web front end.
CounterBean is a simple singleton with one method, getHits, that returns an integer representing the number of times a web page has been accessed. Here is the code of CounterBean:
package counter.ejb;
import javax.ejb.Singleton;
/**
CounterBean is a simple singleton session bean that records the number
of hits to a web page. */ @Singleton public class CounterBean { private int hits = 1;
// Increment and return the number of hits public int getHits() { return hits++; }
}
The @Singleton annotation marks CounterBean as a singleton session bean. CounterBean uses a local, no-interface view.
CounterBean uses the EJB container’s default metadata values for singletons to simplify the coding of the singleton implementation class. There is no @ConcurrencyManagement annotation on the class, so the default of container-managed concurrency access is applied. There is no @Lockannotation on the class or business method, so the default of @Lock(WRITE) is applied to the only business method, getHits.
The following version of CounterBean is functionally equivalent to the preceding version:
package counter.ejb;
import javax.ejb.Singleton; import javax.ejb.ConcurrencyManagement; import static javax.ejb.ConcurrencyManagementType.CONTAINER; import javax.ejb.Lock; import javax.ejb.LockType.WRITE;
/**
CounterBean is a simple singleton session bean that records the number
of hits to a web page. */ @Singleton @ConcurrencyManagement(CONTAINER) public class CounterBean { private int hits = 1;
// Increment and return the number of hits @Lock(WRITE) public int getHits() { return hits++; }
}
The web front end of counter consists of a JavaServer Faces managed bean,Count.java, that is used by the Facelets XHTML files template.xhtml and template-client.xhtml. TheCount JavaServer Faces managed bean obtains a reference to CounterBean through dependency injection. Countdefines a hitCount JavaBeans property. When the getHitCount getter method is called from the XHTML files, CounterBean’s getHits method is called to return the current number of page hits.
Here’s the Count managed bean class:
@ManagedBean @SessionScoped public class Count { @EJB private CounterBean counterBean;
private int hitCount;
public Count() {
this.hitCount = 0;
}
public int getHitCount() {
hitCount = counterBean.getHits();
return hitCount;
}
public void setHitCount(int newHits) {
this.hitCount = newHits;
}
}
The template.xhtml and template-client.xhtml files are used to render a Facelets view that displays the number of hits to that view. The template-client.xhtml file uses an expression language statement, #{count.hitCount}, to access the hitCount property of the Count managed bean. Here is the content of template-client.xhtml:
This text above will not be displayed.
<ui:composition template="/template.xhtml">
This text will not be displayed.
<ui:define name="title">
This page has been accessed **#{count.hitCount}** time(s).
</ui:define>
This text will also not be displayed.
<ui:define name="body">
Hooray!
</ui:define>
This text will not be displayed.
</ui:composition>
This text below will also not be displayed.
</body>
Running the counter Example
You can use either NetBeans IDE or Ant to build, package, deploy, and run the counter example.
To Run the counter Example Using NetBeans IDE
- From the File menu, choose Open Project.
- In the Open Project dialog, navigate to:
tut-install/examples/ejb/ - Select the counter folder.
- Select the Open as Main Project check box.
- Click Open Project.
- In the Projects tab, right-click the counter project and select Run.
A web browser will open the URL http://localhost:8080/counter, which displays the number of hits. - Click the browser’s Refresh button to see the hit count increment.
To Run the counter Example Using Ant
- In a terminal window, go to:
tut-install/examples/ejb/counter/ - Type the following command:
ant all
This will build and deploy counter to your GlassFish Server instance. - In a web browser, type the following URL:
http://localhost:8080/counter - Click the browser’s Refresh button to see the hit count increment.
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. Legal Notices