Sun Microsystem added the features like annotation to make the development easier and more efficient in jdk 5. The main objective to develop the annotations is to make the development easier. Annotations behaves like the meta. The literal meaning of meta data is data about data. Java also signifies this meaning. Annotations are like meta data, means you are free to add your code and can also apply them to variables, parameters, fields type declarations, methods and constructors. Metadata is also used to create the documentation to perform rudimentary compile time checking and even for tracking down the dependencies in code. XDoclet contains all these features and is widely used. Annotations provide a means of indicating about methods, classes, dependencies, incompleteness and also about the references on other methods and classes respectively. Quoting from Sun's official site, "It (annotation-based development) lets us avoid writing boilerplate code under many circumstances by enabling tools to generate it from annotations in the source code. This leads to a declarative programming style where the programmer says what should be done and tools emit the code to do it."
Annotation is the way of associating the program elements with the meta tags so that the compiler can extract program behavior to support the annotated elements to generate interdependent code when necessary.
Fundamentals of annotations
While going through the annotations you should consider two things. The first one is the"annotation" itself and second one is the "annotations types". An annotation is the meta tag, used to give some life to the code you are using. While annotation type is used to define annotations so that you can use them while creating your own custom annotations.
An annotation type definition appends an "at" @ sign at the start of the interface keyword with the annotation name. On the other hand, an annotation includes the "at" @ sign followed by the annotation type. You can also add the data within the parenthesis after the annotation name. Lets illustrate the concept more clearly by using some examples.
Defining an annotation (Annotation type)
public @interface Example {
String showSomething();
}
Annotating the code (Annotation)
Example (showSomething="Hi! How r you")
public void anymethod() {
....
}
Annotation Types: Three types of annotations types are there in java.
- Marker: Like the marker interface, marker annotations does not contain any elements except the name itself. The example given below clarifies the concept of marker interface.
Example:
public @interface Example{
}
Usage:
@Example
public void anymethod() {
------------
}
- Single-value: This type of elements provide only single value. It means that these can be represented with the data and value pair or we can use the shortcut syntax (just by using the value only within the parenthesis).
Example:
public @interface Example{
String showSomething();
}
Usage:
@Example ("Hi ! How r you")
public void anymethod(){
--------
}
- Multi-value or Full-value: These types of annotations can have multiple data members. Therefore use full value annotations to pass the values to all the data members.
Example:
public @interface Example{
String showSomething(); int num;
String name;
}
Usage:
@Example (showSomething = "Hi! How r you", num=5, name="zulfiqar" )
public void anymethod{
// code here
}
Rules defining the Annotation type: Here are some rules that one should follow while defining and using annotations types
- Start the annotation declaration starting with the symbol "at" @ following the interface keyword that should follow the annotation name.
- Method declaration should not throw any exception.
- Method declaration should not contain any parameter.
- Method using annotations should return a value, one of the types given below:
- String
- primitive
- enum
- Class
- array of the above types
Annotations: JDK 5 (Tiger) contains two types of annotations:
- Simple annotations: These types of annotations are used to annotate the code only. We can not use these types of annotations for creating the custom annotation type.
- Meta annotations: Also known as annotations of annotations are used to annotate the annotation-type declaration.
Simple annotations: JDK 5 includes three types of simple annotations.
- Override
- Depricated
- Suppresswarnings
JDK 5 (also known as Tiger) does not include many built-in annotations but it facilitates to core java to support annotation features. Now will discuss in brief each of the above simple annotation types along with examples.
Override annotation: The override annotation ensures that the annotated method is used to override the method in the super class. If the method containing this type of annotation does not override the method in the super class then the compiler will generate a compile time error.
Lets take an example and demonstrate what will happen if the annotated method does not override the method in the super class.
Example 1:
public class Override_method{
@Override
public String toString(){
return super.toString() +
"Will generate an compile time error.";
}
}
Suppose there is spell mistake in the method name such as the name is changed from toString to toStrimg. Then on compiling the code will generate the message like this:
Compiling 1 source file to D:tempNew Folder (2)
TestJavaApplication1buildclasses
D:tempNew Folder (2)TestJavaApplication1srctest
myannotationTest_Override.java:24: method does not override
a method from its superclass
@Override
1 error
BUILD FAILED (total time: 0 seconds)
Deprecated annotation: These types of annotations ensure that the compiler warns you when you use the deprecated element of the program. The example given below illustrates this concept.
Example: Lets first create the class containing the deprecated method.
public class Deprecated_method{
@Deprecated
public void showSomething() {
System.out.println("Method has been depricated'");
}
}
Now lets try to invoke this method from inside the other class:
public class Test_Deprication {
public static void main(String arg[]) throws Exception {
new Test_Deprication();
}
public Test_Deprication() {
Deprecated_method d = new Deprecated_method();
d.showSomething();
}
The method showSomething() in the above example is declared as the deprecated method. That means we can't further use this method any more. On compiling the class Depricated_method does not generate any error. While compiling the class Test_Deprication generates the message like this:
Compiling 1 source file to D:tempNew Folder
(2)TestJavaApplication1buildclasses
D:tempNew Folder
(2)TestJavaApplication1srctestmyannotation
Test_Deprication.java:27:
warning: [deprecation] showSomething() in
test.myannotation.Deprecated_method has been deprecated
d.showSomething();
1 warning
The Suppresswarning annotation: These types of annotations ensure that the compiler will shield the warning message in the annotated elements and also in all of its sub-elements. Lets take an example:
Suppose you annotate a class to suppress a warning and one of its method to suppress another warning, then both the warning will be suppressed at the method level only. Lets demonstrate it by an example:
public class Test_Depricated {
public static void main(String arg[]) throws Exception {
new TestDepricated().showSomething();
}
@SuppressWarnings({"deprecation"})
public void showSomething() {
Deprecation_method d = new Deprecation_method();
d.showSomething();
}
}
This example is suppressing the deprecation warnings that means we can't see the warnings any more.
Note: Applying annotation at most deeply nested elements is a good idea. It is better to apply annotations at the method level rather than the class to annotate a particular method.
Meta-Annotations (Annotation Types): There are four types ofm Meta annotations (or annotations of annotations) defined by the JDK 5. These are as follows:
- Target
- Retention
- Documented
- Inherited
Target annotation: Target annotation specifies the elements of a class to which annotation is to be applied. Here is the listing of the elements of the enumerated types as its value:
- @Target(ElementType.TYPE)—applicable to any element of a class.
- @Target(ElementType.FIELD)—applicable to field or property.
- @Target(ElementType.PARAMETER)—applicable to the parameters of a method.
- @Target(ElementType.LOCAL_VARIABLE)—applicable to local variables.
- @Target(ElementType.METHOD)—applicable to method level annotation.
- @Target(ElementType.CONSTRUCTOR)—applicable to constructors.
- @Target(ElementType.ANNOTATION_TYPE)—specifies that the declared type itself is an annotation type.
Here is an example that demonstrates the target annotation:
Example:
@Target(ElementType.METHOD)
public @interface Test_Element {
public String doTestElement();
}
Now lets create a class that use the Test_Element annotation:
public class Test_Annotations {
public static void main(String arg[]) {
new Test_Annotations().doTestElement();
}
@Test_Target(doTestElement="Hi ! How r you")
public void doTestElement() {
System.out.printf("Testing Target Element annotation");
}
}
The @Target(ElementType.METHOD) specifies that this type of annotation can be applied only at method level. Compiling and running the above program will work properly. Lets try to apply this type of annotation to annotate an element:
public class Test_Annotations {
@Test_Target(doTestElement="Hi! How r you")
private String str;
public static void main(String arg[]) {
new Test_Annotations().doTestElement();
}
public void doTestElement() {
System.out.printf("Testing Target Element annotation");
}
}
Here we are trying to apply @Target(ElementType.METHOD) at the field level by declaring the element private String str; after the @Test_Target(doTestElement="Hi ! How r you") statement. On compiling this code will generate an error like this:
"Test_Annotations.java":
D:R_AND_DTest_Annotationsrctestmyannotation
Test_Annotations.java:16:
annotation type not applicable to this kind of declaration at line
16, column 0
@Test_Target(doTestElement="Hi ! How r you")
^
Error in javac compilation
Retention annotation: These types of annotation specify where and how long annotation with this types are to be retained. There are three type of Retention annotations are of three types.
- RetentionPolicy.SOURCE: This type of annotation will be retained only at source level and the compiler will ignore them.
- RetentionPolicy.CLASS: This type of annotation will be retained at the compile time the virtual machine (VM) will ignore them.
- RetentionPolicy.RUNTIME: Virtual machine will retained the annotation of this type and they can be read only at run-time.
Lets demonstrate that how this type of annotations are applied by taking an example using RetentionPolicy.RUNTIME.
Example:
@Retention(RetentionPolicy.RUNTIME)
public @interface Retention_Demo {
String doRetentionDemo();
}
This example uses the annotation type @Retention(RetentionPolicy.RUNTIME) that indicates the VM will retained your Retention_Demo annotation so that it can be read effectively at run-time.
Documented annotation: This type of annotation should be documented by the javadoc tool. javadoc does not include the annotation by default. Include the annotation type information by using @Documented in the generated document. In this type of annotation all the processing is done by javadoc-like tool.
The given example demonstrates the use of the @Documented annotations.
Example:
@Documented
public @interface Documented_Demo {
String doTestDocumentedDemo();
}
Next, make changes in Test_Annotations class as follows:
public class Test_Annotations {
public static void main(String arg[]) {
new Test_Annotations().doTestRetentionDemo();
new Test_Annotations().doTestDocumentedDemo();
}
@Retention_Demo (doTestRetentionDemo="Hello retention annotation")
public void doTestRetentionDemo() {
System.out.printf("Testing 'Retention' annotation");
}
@Documented_Demo (doTestDocumentedDemo="Hello Test documentation")
public void doTestDocumentedDemo() {
System.out.printf("Testing 'Documented' annotation");
}
}
Inherited Annotation: This annotation is little bit complex. It inherits the annotated class automatically. If you specify @Inherited tag before defining a class then apply the annotation at your class and finally extend the class then the child class inherits the properties of the parent class automatically. Lets demonstrate the benefits of using the @Inherited tag by an example:
Example:
Lets first, define the annotation:
@Inherited
public @interface ParentObjectDemo {
boolean isInherited() default true;
String showSomething() default "Show anything?";
}
Now, annotate the class with our annotation:
@ParentObjectDemo
public Class ChildObjectDemo {
}
The above example shows that you do not need to define the interface methods inside the implemented class. The @Inherited tag automatically inherits the methods for you. Suppose you define the implementing class in the old-fashioned-java-style then let us see the effect of doing this:
public class ChildObjectDemo implements ParentObjectDemo {
public boolean isInherited() {
return false;
}
public String showSomething() {
return "";
}
public boolean equals(Object obj) {
return false;
}
public int hashCode() {
return 0;
}
public String toString() {
return "";
}
public Class annotationType() {
return null;
}
}
Have you seen the difference? You have to implement all the methods of the parent interface. You will have to implement the equals(), toString(), and the hashCode() methods of the Object class and also the annotation type method of the java.lang.annotation.Annotation class. You will also have to include all these methods in your class regardless of whether you are implementing all these methods or not.
Session Beans
A session bean is the enterprise bean that directly interact with the user and contains the business logic of the enterprise application. A session bean represents a single client accessing the enterprise application deployed on the server by invoking its method. An application may contain multiple sessions depending upon the number of users accessing to the application. A session bean makes an interactive session only for a single client and shields that client from complexities just by executing the business task on server side.
For example, whenever a client wants to perform any of these actions such as making a reservation or validating a credit card, a session bean should be used. The session bean decides what data is to be modified. Typically, the session bean uses an entity bean to access or modify data. They implement business logic, business rules, algorithms, and work flows. Session beans are relatively short-lived components. The EJB container may destroy a session bean if its client times out.
A session bean can neither be shared nor can persist (means its value can not be saved to the database) its value. A session bean can have only one client. As long as the client terminates, session bean associated with this client is also terminated and the data associated with this bean is also destroyed.
The above figure shows how Session Bean interacts with the clients as well as with the Entity Beans.
Session beans are divided into two parts.
- Stateless Session Beans: A stateless session bean does not maintain a conversational state with the client. When a client invokes the methods of a stateless bean, the instance of bean variables may contain a state specific to that client only for the duration of a method invocation. Once the method is finished, the client-specific state should not be retained i.e. the EJB container destroys a stateless session bean.
These types of session beans do not use the class variables (instance variables). So they do not persist data across method invocation and therefore there is no need to passivates the bean's instance. Because stateless session beans can support multiple clients, they provide the better scalability for applications that require large numbers of clients.
- Stateful Session Beans: These types of beans use the instance variables that allows the data persistent across method invocation because the instance variables allow persistence of data across method invocation. The client sets the data to these variables which he wants to persist. A stateful session bean retains its state across multiple method invocations made by the same client. If the stateful session bean's state is changed during a method invocation, then that state will be available to the same client on the following invocation. The state of a client bean is retained for the duration of the client-bean session. Once the client removes the bean or terminates, the session ends and the state disappears. Because the client interacts with its bean, this state is often called the conversational state.
For example, consider a customer using a debit card at an ATM machine. The ATM could perform various operations like checking an account balance, transferring funds, or making a withdrawal. These operations could be performed one by one, by the same customer. So the bean needs to keep track its state for each of these operations to the same client.
Thus Stateful session beans has the extra overhead for the server to maintain the state than the stateless session bean.
The user interface calls methods of session beans if the user wants to use the functionality of the session bean. Session beans can call to other session beans and entity beans.
When to use session beans:
Generally session beans are used in the following circumstances:
- When there is only one client is accessing the beans instance at a given time.
- When the bean is not persistent that means the bean is going to exist no longer.
- The bean is implementing the web services.
Stateful session beans are useful in the following circumstances:
- What the bean wants to holds information about the client across method invocation.
- When the bean works as the mediator between the client and the other component of the application.
- When the bean have to manage the work flow of several other enterprise beans.
Stateless session beans are appropriate in the circumstances illustrated below:
- If the bean does not contain the data for a specific client.
- If there is only one method invocation among all the clients to perform the generic task.
Life Cycle of a Stateless Session Bean: Since the Stateless session bean does not passivates across method calls therefore a stateless session bean includes only two stages. Whether it does not exist or ready for method invocation. A stateless session bean starts its life cycle when the client first obtains the reference of the session bean. For this, the container performs the dependency injection before invoking the annotated@PreConstruct method if any exists. After invoking the annotated @PreConstruct method the bean will be ready to invoke its method by the client.
The above figure demonstrates how the Stateless Session Beans are created and destroyed.
The container calls the annotated @PreDestroy method while ending the life cycle of the session bean. After this, the bean is ready for garbage collection.
Life Cycle of a Stateful Session Bean: A Stateful session bean starts its life cycle when the client first gets the reference of a stateful session bean. Before invoking the method annotated @PostConstruct the container performs any dependency injection after this the bean is ready. The container may deactivate a bean while in ready state (Generally the container uses the least recently use algorithm to passivates a bean). In the passivate mechanism the bean moves from memory to secondary memory. The container invokes the annotated @PrePassivate method before passivating the bean. If a client invokes a business method on the passivated bean then the container invokes the annotated @PostActivatemethod to let come the bean in the ready state.
|
The above image shows the various states of the Stateful Session Beans
While ending the life cycle of the bean, the client calls the annotated @Remove method after this the container calls the annotated @PreDestroy method which results in the bean to be ready for the garbage collection.
Lets see an example.
The example application consists of an enterprise bean, which performs the calculations, and two types of clients: an application client and a web client.
There are following steps that you have to follow to develop a example JEE application.
Create the enterprise bean: CalculatorBean
Create the web client: WebClient
Deploy example onto the server.
Using a browser, run the web client.
I. Creating the enterprise bean:
The enterprise bean in our example is a stateless session bean called CalculatorBean. The source code for CalculatorBean is in “net/opensourzesupport.blogspot/ejb3/stateless” directory.
Creating CalculatorBean requires these steps:
(i) Coding the bean’s Remote business interface and Enterprise bean class.
(ii) Compiling the source code with the Ant tool.
(i) Coding the Business Interface
The business interface defines the business methods that a client can call remotely. The business methods are implemented in the enterprise bean class. The source code for the CalculatorRemote business interface is given below.
package net.opensourzesupport.blogspot.ejb3.stateless;
import java.math.*;
import javax.ejb.Remote;
import java.lang.annotation.*;
@Remote
public interface CalculatorRemote {
public float add(float x, float y);
public float subtract(float x, float y);
public float multiply(float x, float y);
public float division(float x, float y);
}
|
Note that, the @Remote annotation decorating the interface definition. This lets the container know thatCalculatorBean will be accessed by remote clients.
II. Coding the Enterprise Bean Class
The enterprise bean class for this example is called CalculatorBean. This class implements the four business methods (add, subtract, multiply, division) that are defined in the CalculatorRemote business interface. The source code for the CalculatorBean class is given below.
package net.opensourzesupport.blogspot.ejb3.stateless;
import java.math.*;
import javax.ejb.Stateless;
import javax.ejb.Remote;
@Stateless(name="CalculatorBean")
@Remote(CalculatorRemote.class)
public class CalculatorBean implements CalculatorRemote{
public float add(float x, float y){
return x + y;
}
public float subtract(float x, float y){
return x - y;
}
public float multiply(float x, float y){
return x * y;
}
public float division(float x, float y){
return x / y;
}
} |
Note that, the @Stateless annotation decorating the enterprise bean class. This lets the container know that CalculatorBean is a stateless session bean.
Compiling and Packaging the example Example
Now you are ready to compile the remote business interface (CalculatorRemote.java), the enterprise bean class (CalculatorBean.java) and the application client (CalculatorClient.java), then package the compiled classes into an enterprise bean JAR.
II. Creating the calculator Web Client
The web client is contained in the JSP page "WebClient.jsp". A JSP page is a text-based document that contains JSP elements, which construct dynamic content, and static template data, expressed in any text-based format such as HTML, WML, and XML.
The source code for the “form.jsp” is given below.
<html>
<head>
<title>Calculator</title>
</head>
<body bgcolor="pink">
<h1>Calculator</h1>
<hr>
<form action="WebClient.jsp" method="POST">
<p>Enter first value:
<input type="text" name="num1" size="25"></p>
<br>
<p>Enter second value:
<input type="text" name="num2" size="25"></p>
<br>
<b>Seclect your choice:</b><br>
<input type="radio" name="group1" value ="add">Addition<br>
<input type="radio" name="group1" value ="sub">Subtraction<br>
<input type="radio" name="group1" value ="multi">Multiplication<br>
<input type="radio" name="group1" value ="div">Division<br>
<p>
<input type="submit" value="Submit">
<input type="reset" value="Reset"></p>
</form>
</body>
</html> |
The following statements given below in “WebClient.jsp” are used for locating the business interface, creating an enterprise bean instance, and invoking a business method.
InitialContext ic = new InitialContext();
CalculatorRemote calculator = (CalculatorRemote)ic.lookup("example/CalculatorBean/remote"); |
The classes needed by the client are declared using a JSP page directive (enclosed within the <%@ %>characters). Because locating the business interface and creating the enterprise bean are performed only once, this code appears in a JSP declaration (enclosed within the <%! %> characters) that contains the initialization method, jspInit, of the JSP page. A scriptlet (enclosed within the <% %> characters) retrieves the parameters from the request and converts it to a Float object. Finally, a JSP scriptlet invokes the enterprise bean’s business methods, and JSP expressions (enclosed within the <%= %> characters) insert the results into the stream of data returned to the client.
The full source code for the WebClient program is given below.
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page import="com.javajazzup.examples.ejb3.stateless.*, javax.naming.*"%>
<%!
private CalculatorRemote calculator = null;
float result=0;
public void jspInit() {
try {
InitialContext ic = new InitialContext();
calculator = (CalculatorRemote) ic.lookup("example/CalculatorBean/remote");
System.out.println("Loaded Calculator Bean");
//CalculatorBean
} catch (Exception ex) {
System.out.println("Error:"+
ex.getMessage());
}
}
public void jspDestroy() {
calculator = null;
}
%>
<%
try {
String s1 = request.getParameter("num1");
String s2 = request.getParameter("num2");
String s3 = request.getParameter("group1");
System.out.println(s3);
if ( s1 != null && s2 != null ) {
Float num1 = new Float(s1);
Float num2 = new Float(s2);
if(s3.equals("add"))
result=calculator.add(num1.floatValue(),num2.floatValue());
else if(s3.equals("sub"))
result=calculator.subtract(num1.floatValue(),num2.floatValue());
else if(s3.equals("multi"))
result=calculator.multiply(num1.floatValue(),num2.floatValue());
else
result=calculator.division(num1.floatValue(),num2.floatValue());
%>
<p>
<b>The result is:</b> <%= result %>
<p>
<%
}
}// end of try
catch (Exception e) {
e.printStackTrace ();
//result = "Not valid";
}
%> |
Note: The Application Server automatically compiles web clients that are JSP pages. If the web client were a servlet, you would have to compile it.
The source code for the “index.jsp” is given below that will actual call the client-design form.
<%@page language="java" %>
<html>
<head>
<title>Ejb3 Stateless Tutorial</title>
</head>
<body bgcolor="#FFFFCC">
<p align="center"><font size="6" color="#800000"><b>Welcome to <br>
Ejb3-Jboss 4.2.0 Tutorial</b></font>
Click <a href="ejb3/form.jsp">Calculator Example</a> to execute Calculator<br></p>
</body>
</html> |
III. Deploy example onto the server
To deploy the created example application we are going to use Jboss 4.2.0 Application Server about which you have read in the previous section of this Javajazzup issue. So you first need to download the following tools to deploy this application.
· JDK 1.5 or Higher
· apache-ant-1.7.0
· JBoss 4.2.0
Do the following steps to deploy the example application:
(i) Make a directory structure. You can Click here to extract the readymade directory structure according to this tutorial.
(ii) Create the essential deployment descriptor .xml files.
build.xml
<?xml version="1.0"?>
<project name="Jboss Tutorials" default="all" basedir=".">
<target name="init">
<!-- Define -->
<property name="dirs.base" value="${basedir}"/>
<property name="classdir" value="${dirs.base}/build/classes"/>
<property name="src" value="${dirs.base}/src"/>
<property name="web" value="${dirs.base}/web"/>
<property name="deploymentdescription" value="${dirs.base}/deploymentdescriptors"/>
<property name="warFile" value="example.war"/>
<property name="earFile" value="example.ear"/>
<property name="jarFile" value="example.jar"/>
<property name="earDir" value="${dirs.base}/build/ear"/>
<property name="warDir" value="${dirs.base}/build/war"/>
<property name="jarDir" value="${dirs.base}/build/jar"/> <!-- classpath for Project -->
<path id="library.classpath">
<pathelement path ="libext/servlet-api.jar"/>
<pathelement path ="libext/ejb3-persistence.jar"/>
<pathelement path ="libext/javaee.jar"/>
<pathelement path ="${classpath}"/> </path> <!-- Create Web-inf and classes directories --> <mkdir dir="${warDir}/WEB-INF"/>
<mkdir dir="${warDir}/WEB-INF/classes"/>
<!-- Create Meta-inf and classes directories -->
<mkdir dir="${earDir}/META-INF"/>
<mkdir dir="${jarDir}/META-INF"/>
<mkdir dir="${classdir}"/>
</target> <!-- Main target --> <target name="all" depends="init,build,buildWar,buildJar,buildEar"/>
<!-- Compile Java Files and store in /build/src directory -->
<target name="build" >
<javac srcdir="${src}" destdir="${classdir}" debug="true" includes="**/*.java" >
<classpath refid="library.classpath"/>
</javac>
</target> <!-- Create the web archive File --> <target name="buildWar" depends="init">
<copy todir="${warDir}/WEB-INF/classes">
<fileset dir="${classdir}" includes="**/*.class" />
</copy>
<copy todir="${warDir}/WEB-INF">
<fileset dir="${deploymentdescription}/web/" includes="web.xml" />
</copy> <copy todir="${warDir}">
<fileset dir="${web}" includes="**/*.*" />
</copy>
<!-- Create war file and place in ear directory --> <jar jarfile="${earDir}/${warFile}" basedir="${warDir}" />
</target> <!-- Create the jar File --> <target name="buildJar" depends="init">
<copy todir="${jarDir}">
<fileset dir="${classdir}" includes="**/*.class" />
</copy> <copy todir="${jarDir}/META-INF">
<fileset dir="${deploymentdescription}/jar/" includes="ejb-jar.xml,weblogic-cmp-rdbms-jar.xml,weblogic-ejb-jar.xml" />
</copy> <!-- Create jar file and place in ear directory -->
<jar jarfile="${earDir}/${jarFile}" basedir="${jarDir}" /> </target>
<!-- Create the ear File --> <target name="buildEar" depends="init">
<copy todir="${earDir}/META-INF">
<fileset dir="${deploymentdescription}/ear" includes="application.xml" />
</copy>
<!-- Create ear file and place in ear directory -->
<jar jarfile="../${earFile}" basedir="${earDir}" /> <copy todir="C:/jboss-4.2.0.GA/server/default/deploy/">
<fileset dir="../" includes="${earFile}" /> </copy>
</target>
</project> |
Put this file in the base (stateless\code)directory.
Application.xml
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="5" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_5.xsd">
<display-name>Stateless Session Bean Example</display-name>
<module>
<web>
<web-uri>example.war</web-uri>
<context-root>/example</context-root>
</web>
</module>
<module>
<ejb>example.jar</ejb>
</module>
</application> |
Put this file in the Stateless\code\deploymentdescriptors\ear directory.
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app > </web-app> |
Put this file in the Stateless\code\deploymentdescriptors\web directory.
Put all .jsp files in the Stateless\code\web directory.
Put all .java files in the Stateless\code\src directory.
(iii) Start command prompt, and go to the Stateless\code directory. Then type the command as:
C:\Stateless\code>ant build.xml
The Ant tool will deploy the example.ear file to the jboss-4.2.0.GA\server\default\deploy directory.
V. Running the example Web Client
Open the web browser and type the following URL to run the application:
http://localhost:8080/example
Click at the given link as Calculator Example:
Give values to the textbox and choose the desire option button as Addition then clicks the Submit button to get the result.
The result is: 9.0
Stateful Session Bean
In this part of Enterprise Session Beans, you will learn how to develop, deploy, and run a simple Java EE application named accountusing stateful session bean. The purpose ofaccount is to performs two transaction operations (deposit and withdraw) for the customer.
The account application consists of an enterprise bean, which performs thetransactions, and two types of clients: anapplication client and a web client.
here are following steps that you have to follow to develop a account JEE application.
Create the enterprise bean: AccountBean
Create the application client: AccountCustomer
Deploy account onto the server.
Run the application client.
I. Creating the enterprise bean:
The enterprise bean in our example is a statelful session bean called AccountBean.
The account session bean represents an account information in an online customer account. The bean’s customer can deposit to or withdraw the amount from his account. To manage account, you need the following code:
The Business Interface:
The Account business interface is a plain Java interface that defines all the business methods implemented in the bean class. If the bean class implements a single interface, that interface is assumed to the business interface. The business interface is a local interface unless it is annotated with the javax.ejb.Remote annotation.
The bean class may also implement more than one interface. If the bean class implements more than one interface, the business interfaces must be specified by decorating the bean class with @Local or@Remote.
The source code for the Account business interface is given below.
package ejbExample.stateful;
import javax.ejb.Remote;
@Remote
public interface Account {
public float deposit(float amount);
public float withdraw(float amount);
@Remove
public void remove();
} |
Coding the Session Bean Class:
The session bean class for this example is called AccountBean. This class implements the two business methods (deposit and withdraw). The AccountBean class must meet these requirements:
The source code for the AccountBean class is given below.
package ejbExample.stateful;
import javax.ejb.Stateful;
import javax.ejb.Remote;
import javax.ejb.Remove;
import javax.ejb.*;
@Stateful(name="AccountBean")
@Remote(AccountRemote.class)
public class AccountBean implements AccountRemote {
float balance = 0;
public float deposit(float amount){
balance += amount;
return balance;
}
public float withdraw(float amount){
balance -= amount;
return balance;
}
@Remove
public void remove() {
balance = 0;
}
}
|
The Remove Method
Business methods annotated with javax.ejb.Remove in the stateful session bean class can be invoked by enterprise bean client to remove the bean instance. The container will remove the enterprise bean after a @Remove method completes, either normally or abnormally. Thus, we can retain the bean's state invoked by the client until we call the annotated @Remove method.
In AccountBean , the remove method is a @Remove method shown as:
@Remove
public void remove() {
balance = 0;
} |
Stateful session beans also may:
Implement any optional life cycle callback methods, annotated @PostConstruct,@PreDestroy, @PostActivate, and @PrePassivate.
Implement optional business method annotated @Remote.
Life-Cycle Callback Methods:
Methods in the bean class may be declared as a life-cycle callback method by annotating the method with the following annotations:
- javax.annotation.PostConstruct
- javax.annotation.PreDestroy
- javax.ejb.PostActivate
- javax.ejb.PrePassivate
Life-cycle callback methods must return void and have no parameters. Lets understands these callback annotated methods shown in the table given below:
II. Coding the account Web Client
The application client source code is in the WebClient.jsp file That illustrates the basic tasks performed by the client of an enterprise bean:
The full source code for the WebClient.jsp program is given below.
<%@page language="java" %>
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page import="com.javajazzup.examples.ejb3.stateful.*, javax.naming.*"%>
<%!
public AccountRemote account = null;
float bal=0;
public void jspInit() {
try {
InitialContext ic = new InitialContext();
account = (AccountRemote) ic.lookup("example/AccountBean/remote");
System.out.println("Loaded Account Bean");
} catch (Exception ex) {
System.out.println("Error:"+
ex.getMessage());
}
}
public void jspDestroy() {
account = null;
}
%>
<%
try {
String s1 = request.getParameter("amt");
String s2 = request.getParameter("group1");
if ( s1 != null) {
Float amt = new Float(s1);
if(s2.equals("dep"))
bal=account.deposit(amt.floatValue());
else if(s2.equals("with"))
bal=account.withdraw(amt.floatValue());
else
%>
<p>Please select your choice</p>
<%
}
else
%>
<br>Please enter the amount<br>
<p>
The Transaction is complete<br>
<b>Your Current Balance is:</b> <%= bal%>
<p>
<%
}// end of try
catch (Exception e) {
e.printStackTrace ();
}
%>
|
The source code for the “form.jsp” is given below.
<html>
<head>
<title>Bank Account</title>
</head>
<body>
<h1><p align="center"><font size="6" color="#800000">Bank Transaction Request Form</h1>
<hr><br>
<table bgcolor="#FFFFCC" align="center">
<form action="WebClient.jsp" method="POST">
<tr><td></tr></td>
<tr><td>Enter the amount in rupees:
<input type="text" name="amt" size="10"></tr></td>
<br>
<tr><td><b>Select your choice:</b></tr></td>
<tr><td><input type="radio" name="group1" value ="dep">Deposit</tr></td>
<tr><td><input type="radio" name="group1" value ="with">Withdraw<br></tr></td>
<tr><td>
<input type="submit" value="Transmit">
<input type="reset" value="Reset"></tr></td>
<tr><td></tr></td>
</form>
</table>
</body>
</html> |
The source code for the “index.jsp” is given below that will actual call the client-design form.
<%@page language="java" %>
<html>
<head>
<title>Ejb3 Stateful Tutorial</title>
</head>
<body bgcolor="#FFFFCC">
<p align="center"><font size="6" color="#800000"><b>Welcome to <br>
Ejb3-Jboss 4.2.0 Tutorial</b></font>
Click <a href="ejb3/form.jsp">Bank Transaction Example</a> to execute Bank Bean<br></p>
</body>
</html> |
III. Deploy account onto the server
IV. Running the account Application Client
Message Driven Beans
Message driven beans are the light weight components used for communication. In message driven beans the messaging service is in asynchronous mode because the user is not intended to get the instant result. To understand the concept of message driven beans more clearly first we should go through the various concepts illustrated given below: - Techniques to implement messaging, message-oriented-middleware (MOM) and the asynchronous behavior.
- Utilization of JMS, message-oriented-middleware to implement JMS based message-driven-beans.
- Features and comparison of message-driven-beans with entity and session beans.
- Techniques to develop message driven beans, including advanced topics like gotchas and possible actions.
Motivations for messaging: EJB components are used to develop the applications for the distributed computing network. Distributed computing network uses the RMI-IIOP protocol to communicate with each other. This protocol is used to call the EJB components. RMI-IIOP accepts challenges in several areas like: - Asynchrony: A typical RMI-IIOP client has to wait until the server completes its processing and returns the result to the client. After that the server enables to the client to continue its processing.
- Decoupling: An RMI-IIOP server must have the knowledge about the server that it want to use. The client can address them directly through object references. It is not possible to remove a server from the server without directly impacting the clients because the client and server are closely coupled with each other.
- Reliability: Data may be lost or the client can't perform any operation if the server or the network crashes.
- Support for multiple senders and receivers: You can use messaging server instead of remote method invocation (RMI) but the messaging service uses the middleman between the client and the server. This middleman simply receives the messages from one or more senders and sends these messages to one or more consumers. It is not required to get the response instantly from the receiver. The receiver may sends back response back to the sender after completing all the processing. This is known as asynchronous programming.
There are four previous concerns that the messaging addresses with RMI-IIOP as follows: Non blocking request processing: There is no need to block the messaging request while executing another request. For example suppose you are purchasing a book from Amazon.com having a single click functionality. you are enable to continue browsing the site without waiting to check the authorization of your credit card. Until and unless there is something wrong Amazon.com sends you a confirmation email. These types of systems are developed by using the messaging technique. Decoupling: In case of message-oriented-middleware, it is not necessary for the sender to have the knowledge about the message receiver. It only interacts with the messaging system while sending messages. Thus the message senders are decoupled from consumers. Reliability: Your message-oriented-middleware guarantees to send a message to its destination if the receiver is not temporarily available, simply by sending the message to the message-oriented-middleware which sends the message to the receiver when he is available. While it is not possible with RMI-IIOP protocol because there is no middleman in this case. If you send a message using the RMI-IIOP protocol and if server is down then it throws the exception. Support for multiple senders and receivers: Most of the message-oriented-middleware supports this features i.e. receiving messages from multiple senders and can also broadcast them to many receivers. Message-oriented-middleware is the term that can be given to any system that supports the messaging system. There are a number of products based on MOM architecture. BEA Tuxedo/Q, Sun Java System Messaging Server, IBM WebSphere MQ, Tibco Rendezevous, Microsoft MSMQ, FioranoMQ and Sonic Software SonicMQ are the examples of MOM based architecture. Java Message Services (JMS): JMS API is an enterprise tool developed by Sun Microsystems used to develop the enterprise applications. JMS API supports to a framework that allows the development of portable and message based applications. JMS communicates in synchronous or in asynchronous mode by using point-to-point and the publish-subscribe models respectively. JMS has become vendor specific and many vendors such as IBM, Oracle, Hewlett-Packard, BEA Systems and Macromedia are providing the JMS implementation. JMS API: JMS APIs play an important role as comparing the RMI-IIOP protocol. You need to aware with different interfaces, low level topology issues like structure, messaging format, networking protocol and server location.
|
- Locate the JMS provider's ConnectionFactory instance: First establish the connection by using a ConnectionFactory instance to get access the JMS provider of the MOM product you are using. An administrator typically creates and configures the ConnectionFactory for the JMS client's use.
- Create a JMS connection: A JMS connection manages the low level network communications similar to JDBC connection. Use ConnectionFactory to get a connection. For large deployment this connection may be load balance across a group of machines.
- Create a JMS session: A JMS session object is used to send and receive the messages and works as the ConnectionFactory for message producers and message consumers. It also allows the encapsulation of messages in transactions. We use Connection to get the session object.
- Locate the JMS Destination: A JMS destination is an object to which we are sending or from which we are receiving the messages. Locating the right destination is similar to tuning the channel in the right direction to get the clear picture while watching the television or answering the correct phone to get the desired message.
- Create a JMS producer or a JMS consumer: If you are interested to send a message then you need an object to pass your message. This object is known as the JMS producer. If you want to receive a message you need to call a JMS object. This object is known as the Consumer object. To get hold an object Session and Destination are used.
- Send or Receive a message: There may be different types of messages like text, streams, maps, bytes, objects and so on. To send a messages first instantiate it and then send it by using the Producer object. If you are intended to receive a message then first receive the message with the help of Consumer object and then crack it to see what it contains.
All the points described above are applicable to both point-to-point as well as publish/subscribe. Here we are going to discuss JMS by taking the queuing system. Queuing system includes the following parts: - JMS Server: The JMS server maintains the message queue to receive emails.
- JMS Queue: In case of point-to-point messaging system, a queue is used to hold the messages from clients. Messages holding this queue are of MapMessages type that stores the information about the email as name/value pair.
- Email Message Client: A client of this messaging system creates the JMS message to put it on the JMS Queue. This message contains the information about the message to be sent out.
- Email Message Driven Bean: It is the message driven bean that is responsible to take the JMS MapMessage to mail it out.
JMS Architecture: Talk first about JMS while talking about the message driven beans. There are a lot of messaging systems exist in the market. Messaging systems provide a mechanism to exchange data and events asynchronously. JMS API defines a standard way to access any messaging system such as JDBC that enables the user to talk to SQL Server, Oracle and Sybase simply by using the same API. The additional benefits of JMS API are loose coupling between the generated request and the code that services the request. Here are some of the basics of the messaging server that one should know to more clearly understand the concept of JMS APIs: - Messaging Domains
- JMS Messages
Messaging Domains: A messaging system includes several models of operation. JMS API provides separate domains corresponding to different models. JMS provider is free to implement one or more domains. Point-to-Point and Publish/Subscribe are the two most commonly used domains. These two domains concludes the following concepts. - Producer: The client, responsible for sending the message to the destination is known as the producer.
- Consumer: The client, responsible for receiving the message is known as the consumer.
- Destination: Destination is the object used by the client to specify the target that uses it to send the message to or to receive the message from.
Point-to-Point (PTP): An application that uses the point-to-point technique for messaging has the following characteristics. - A PTP producer is the sender.
- A PTP consumer is the receiver.
- PTP uses a queue as the destination.
- A receiver can consume only a single message.
A call center application is the example of a PTP domain, where a phone call enters in the queue therefore only one operator takes care of this call rather than all of the operators. Publish/Subscribe (pub/sub): An application that uses the pub/sub technique must include the following characteristics. - A pub/sub producer is the publisher
- A pub/sub consumer is the subscriber
- pub/sub uses the topic as the destination.
- A message can have the multiple consumer.
An email newsletter application may use the pub/sub model, where an interested candidate may become the subscriber to receive a new published message. Integrating JMS with EJB: Integration of JMS with EJB is the excellent idea because of it the EJB components gets benefit from the value proposed by messaging like multinary communications and non blocking clients. The idea behind the introduction of new type of bean is to consume messages in an EJB application. Use a Java Object that receives the JMS messages to call an EJB client: Instead of developing the whole new bean the java community proposed an idea of object to receive a message and to call the appropriate EJB component such as the session bean or the entity bean. But the problems that come with this approach are: - You have to implement the multithreading concept just to increase the message consumption so that you can listen the messages in multiple threads. However developing the multithreaded application is not a tuff task for the developer.
- Register yourself as a listener by writing the special code for JMS messages.
- Hard code the JMS destination name in your java object that access the destination information required for extra effort to access the destination information from the dish like property files.
- JMS message listener receives services from the EJB container just like a plain java object such as clustering, pooling, transaction, automatic life cycle management and many more. You need to hard code this yourself that is a tuff task and error prone.
- Your java object is wrapped by other EJB components therefore it requires some way to start up. If the class is running inside the container then you are required to use a server specific startup class for the activation of the java object when the EJB server starts. This is not portable as the EJB container does not define an standard way to activate the given logic.
Reuse an existing type of EJB component somehow to receive JMS messages: Session beans or entity beans may receive messages but the problem with this approach is: - Life-cycle-management: The container doesn't know the way of creating a bean when a JMS message arrives.
- Threading: EJB does not allow multithreading when a message arrives to the bean that is processing other request. If a bean is processing a request it does not take the new message arrive to the bean.
Message driven bean: Message driven beans are the special type of components that can receive the JMS as well as other type of messages. Message driven bean can also be used to receive the messages other than JMS. When a message is reached at the destination then the EJB container invokes the message driven bean. A message driven bean is decoupled with the client that sends the message. A client is not allowed to access the message driven bean through a business interface. The client can interact with the message driven bean only through the messaging system. To interact with the message driven bean use the message provider specific API such as JMS.
For more info see JMX posting..
POJO (Plain Old Java Object) Programming
One of the new features of added by Sun Microsystems in EJB 3.0 is POJO (Plain Old Java Object). It is a Java object that doesn't extend or implement some specialized classes and interfaces respectively require by the EJB framework. Therefore, all normal Java objects are POJO’s only. The following classes are not POJO classes shown as: class MyServlet extends HttpServlet {}
class MyRemote implements SessionBean {}
In POJO model, it is recommended that, interfaces should be explicitly implemented whenever you want to pick and choose the methods of the interface. The interfaces are optional for entity beans but required for session beans and message-driven beans. In this model, both the interface and the bean class do not have to throw unnecessary exceptions such as RemoteException. The interface class in POJO model is a Plain Old Java Interface (POJI). The Benefits of POJOs: Decoupling: It decouples the application components from the infrastructure of the EJB framework that lets you construct an application from loosely coupled components. There are no longer need to write the tedious JNDI framework-specific lookup code. You can design and implement the business logic. Once that's working, and then you can deal with persistence and transactions. Easier testing: You can test or run your business logic outside of the application server in a few seconds.
Flexible: A Java POJO code can be implemented with any type of enterprise bean such as Message Driven Bean and Entity Bean. The POJO technology can be used with any type of Enterprise Java Beans(e.g Session Bean, Message Driven Bean or Entity Bean). Let’s understand the POJO with Message Driven Bean: Message Driven POJOs: Message-driven POJOs offer the functionality like MDB to make a simple JavaBeans for the developers. Similar to a MDB in EJB, it acts as a receiver for JMS messages. Writing a message-driven POJO is not much different than writing a message-driven EJB. The major difference between both is that, an message-driven POJO (MDP) must implement the javax.jms.MessageListenerinterface. Like an MDB, you don't have to implement javax.ejb.MessageDrivenBean and the EJB lifecycle methods defined by the interface.
The EJB 3.0 uses annotations to build completely POJO-based messaging applications. In EJB 3.0’s container application server, there is an easier way to implement message driven RPCs. You can use POJOs as message end-points (message driven POJO). The RPC caller retrieves an automatically generated stub of the POJO and makes regular calls against the POJO methods. The message driven POJO works much like a session bean of EJB3, except that all calls are tunneled via a message queue. Let’s see the structure of Message Driven POJO given below: Now, let’s see how message driven POJO is used in EJB3 taking an example. In our sample application, the class MessagePojoClient.java asynchronously invokes the onMessage method to display a simple “Hello...” message on a message driven POJO over a message queue. After the message driven POJO finishes the display task, it saves the result in a server wide cache manager. The POJO business interface: In our example, we are using the javax.jms.MessageListener interface, so we don’t need to define it again. You can also define new interface using @producer annotation to implement specific methods. The message driven POJO implementation: The implementation of the message driven POJO is tagged with the @Consumer annotation. You can specify the message queue property in the annotation attribute. If a message queue is un-defined, the EJB container will create one for you at server start-up. The code for MDP is given below:
package mdb.pojo;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
@Consumer(activationConfig =
{
@ActivationConfigProperty(propertyName="destinationType",
propertyValue="javax.jms.Queue"),
@ActivationConfigProperty(propertyName="destination",
propertyValue="queue/mdpojo")
})
public class MDPojoBean implements MessageListener {
public void onMessage(Message message) {
if (message instanceof TextMessage) {
try {
TextMessage tmsg = null;
tmsg = (TextMessage) msg;
System.out.println( "Message received: " + tmsg.getText());
} catch (JMSException ex) {
throw new RuntimeException(ex);
}
} else {
throw new IllegalArgumentException("Message must be of type TextMessage");
}
}
}
|
Note that, here we didn’t use @MessageDriven annotation to map the JNDI name. The Client: To use the message driven POJO on the client side, client looks up a stub object of the @Producer interface from the JNDI. The auto-generated stub-object not only implements the @Producer interface but also a component interface named ProducerObject. Using the ProducerObject.getProducerManager() method, you can get a ProducerManager object, which is used to make JMS connections. After a JMS connection is established, you can call any method in the @Producer stub object and the method is actually invoked over the pre-defined message queue. The following code snippet shows how the message driven POJO client works.
package mdb.pojo;
import javax.jms.*;
import javax.naming.*;
import java.text.*;
class MessagePojoConn{
public MessagePojoConn(){
ProducerManager manager = null;
MessageListener msglst=null;
try {
// lookup a stub object of the MessageListener interface from the JNDI
InitialContext ctx = new InitialContext();
msglst = (MessageListener) ctx.lookup(MessageListener.class.getName());
ProducerObject po = (ProducerObject)msglst;
ProducerManager manager = po.getProducerManager();
} catch (Exception e) {
e.printStackTrace ();
}
manager.connect(); // internally create a JMS connection
try{
msglst.onMessage("Hello Message Driven POJO");
}
finally{
manager.close(); // clean up the JMS connection
}
}
}
public class MessagePojoClient{
public static void main(String[] args){
MessagePojoConn msgcon = new MessagePojoConn();
}
}
|
Description of Code: When the EJB3 container deploys the @Consumer, it looks for all of its implemented interfaces and registers each one of them in JNDI under. The client code above looks up the MessageListener interface in JNDI. Each producer implements the ProducerObject. The client typecasts the MessageListener to the ProducerObject. It then gets a ProducerManager that manages the JMS connection for this proxy. To start being able to send messages to the Queue, the client calls Connect( ) method on the manager. It then can successfully call methods on the "msglst" object. This method called onMessage( ) is converted into a JMS message and published to the Queue of the Consumer. The consumer will receive the message and invoke its onMessage method. There are a variety of ways to send a JMS message such as using JmsTemplate or Spring. Let’s see the configuration of the message listener containers that ships with Spring.
<!-- this is the Message Driven POJO (MDP) --> <bean id="queue/mdpojo" class="jmsexample.MDPojoBean" /> <!--This is the message listener container --> <bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"><property name="connectionFactory" ref="connectionFactory"/>
<property name="destination" ref="destination"/>
<property name="messageListener" ref="messageListener" />
</bean>
|
Deploy and Run the MDP Application:
|
No comments:
Post a Comment