• No results found

J2EE

N/A
N/A
Protected

Academic year: 2021

Share "J2EE"

Copied!
283
0
0

Loading.... (view fulltext now)

Full text

(1)

J2EE

(2)

CONTENTS

SL.NO.

CHAPTER

PAGE NO.

1. CORE JAVA REVIEW 4

1.1 Object oriented principle 1.2 Programming structures 1.3 Object and classes 1.4 Inheritance

1.5 Package and Interface 1.6 Exception handling 1.7 Threading

1.8 Input and Output

2. INTRODUCTION TO J2EE 29 2.1 Introduction 2.2 J2EE architecture 2.3 Component technologies 2.4 Service technologies 2.5 Communication technologies 2.6 Servers 3. JDBC 40 3.1 Introduction to JDBC 3.2 Types of drivers

3.3 Steps to connect with database 3.4 ResultSetMetaData 3.5 Scrollable ResultSet 3.6 PreparedStatement 3.7 CallableStaement 3.8 Batch Statement 3.9 Connection pooling 4. SERVLETS 52

4.1 Introduction to servlets and alternatives

4.2 Directory structure and Web Application Deployment Descriptor

4.3 Life-cycle of Servlet and Servlet APIstructure 4.4 Request and Response

4.5 ServletConfig, ServletContext, Servlet Collaboration 4.6 Session tracking

4.7 Applet-servlet communication

5. JAVA SERVER PAGES [ JSP ] 80

5.1 Introduction 5.2 Directives

5.3 Scripting elements 5.4 Implicit Objects

(3)

5.5 Standard Action and Java Bean

6. REMOTE METHOD INVOCATION [ RMI ] 97

6.1 Introduction.

6.2 Defining the RMI contract 6.3 RMI Client

6.4 RMI Server

6.5 Deploying RMI across a Network

7. ENTERPRISE JAVA BEAN [ EJB ] 103

7.1 Introduction 7.2 EJB and Java Bean 7.3 Session Bean 7.4 Entity Bean

7.5 Message Driven Bean

8. STRUTS 127 8.1 Introduction to struts 8.2 A simple application 8.3 Controller 8.4 Views 9. XML 164 9.1 Introduction to XML 9.2 XML Syntax 9.3 XML Elements 9.4 XML Attributes 9.5 XML Validation 9.6 XML with CSS 9.7 XML with XSL 9.8 XML Namespace 9.9 Introduction to DTD 9.10 DTD – XML Building blocks 9.11 XML Schema 10. SUPPORTING TECHNOLOGIES 196 10.1 Introduction to SQL queries 10.2 Intoduction to HTML 10.3 Introduction to CSS 10.4 Introduction to javascript 10.5 UML

(4)

CHAPTER 1

CORE JAVA REVIEW

1.1 Object oriented principle

OBJECT

Basic building block for Object-Oriented Programming (OOP). Usually correspond to real-life entities. An object is a unit of software comprising of :

a) State / Attribute : Defines the properties of the object & the current values of each of these properties.

b) Behavior : Defines the response of an object reacts in terms of its state changes & message passing.

c) Identity : Defines an unique name.

EXAMPLE:

Car, Mobile phone, An invoice, John

Object : John

CLASS

 User-defined data type.

 Used to represent a template for several similar type of objects.  Describes how the objects are structured internally.

 Objects of the same class have the same definition both for their state & behavior.

IDENTITY

NAME OF THE PERSON

STATE / ATTRIBUTES AGE ADDRESS PHONE BODY PARTS BEHAVIORS JUMP WALK MOVE ARMS

(5)

Example:

CLASS : PERSON

INSTANCE

 Creation of an object for a particular class.  Attributes & behavior are described by the class.  Each instance has a unique identity.

 Several different instances can be created from the same class.

 Each instance will have different internal states depending upon the different sequences of operations performed. CLASS : PERSON Instance of Instance of Instance of STATE / ATTRIBUTES AGE ADDRESS PHONE BODY PARTS BEHAVIORS JUMP WALK MOVE ARMS ATTRIBUTES AGE ADDRESS PHONE BODY PARTS BEHAVIORS JUMP WALK MOVE ARMS Neha Vivek Smith

(6)

INHERITANCE

A property which allows a class to inherit the properties from another class. Supports the concept of hierarchical classification. The parent class is known as base class and the descendent class is known as derived class. The base class serves as a pattern for the derived class.

Advantages

Core idea for reuse in the software industry. Useful for easy modification of models. Useful for avoiding redundancy , leading to smaller models that are easier to understand.

Types of Inheritance

a) Single Inheritance : If the derived class inherits from a single parent, the inheritance is said to be single inheritance.

b) Multiple Inheritance : If the derived class inherits from two or more parents, the inheritance is said to be multiple inheritance.

POLYMORPHISM

 Ability to take more than one form

 The same operation may exhibit different behavior in different instances.  Behavior depends upon the types of data used in the operation.

EXAMPLE

Operation to be performed : Addition Input Data Type Result

Integer Sum

Character Concatenated String

Advantages

 Extensively used in implementing inheritance.

 Allows objects having different internal structures to share the same external interface.

TYPES OF POLYMORPHISM

(a) Compile-time Polymorphism

Achieved with static binding. The procedure call is replaced with memory address statically at compile-time. Polymorphism is achieved with function overloading. Function Overloading means that in a program more than one functions can be defined with the same name & return type. The type & number of parameters can vary.

(7)

(b) Run-time Polymorphism

Achieved with dynamic binding. At run-time the procedure call matching the object under current reference will be called. This gives objects the ability to respond to messages from routines when the object’s exact type is not known till the run-time.

DATA ABSTRACTION

Refers to the act of representing essential features without including the background details or explanations. Controls the visibility of information. Focuses upon the essential characteristics of some object, relative to the perspective of the viewer.

ENCAPSULATION

The method of combining the data member & member functions of an object into a single structure / unit (called class). Isolates the functional details of the object from outside the class. Helps in data hiding.

1.2 PROGRAMMING STRUCTURES

 A Simple Java Program  Comments

 Data Types  Variables

 Assignments and Initializations  Operators

 Arrays

Before we get into the details of the language, a brief overview would be of benefit. This section gives a very quick look at the main features of the language, without going too far into the details or showing us any actual syntax, to give us a feel for the main concepts behind Object-Oriented programming in Java.

A Java program is a collection of classes. Some of these we write; some are provided as a part of the java language.

A Simple Java Program

Let's look more closely at about the simplest Java program we can have—one that simply prints a message to the console window:

public class FirstSample {

public static void main(String[] args) {

(8)

}}

Now let's look at this source code line by line. The keyword public is called an access modifier; these modifiers control what other parts of a program can use this code. The keyword class is there to remind us that everything in a Java program lives inside a class. Classes are the uilding blocks with which all Java applications and applets are built. Everything in a Java program must be inside a class.

Following the keyword class is the name of the class. The rules for class names in Java are quite generous. Names must begin with a letter, and after that, they can have any combination of letters and digits. The length is essentially unlimited. We cannot use a Java reserved word (such as public or if) for a class name.

COMMENTS

Comments in Java, like comments in most programming languages, do not show up in the executable program. Java has three ways of showing comments. The most common method is a

//. We use this for a comment that will run from the // to the end of the line.

System.out.println("We will not use 'Hello world!'"); // is this too cute?

When longer comments are needed, we can mark each line with a //. Or we can use the /* and */

comment delimiters that let we block off a longer comment. /*

This is the first sample program in Core Java Chapter 3 Copyright (C) 1996...2000 Cay Horstmann and Gary Cornell */

DATA TYPES

Java is a strongly typed language. This means that every variable must have a declared type. There are eight primitive types in Java. Four of them are integer types; two are floating-point number types; one is the character type char, used for characters in the Unicode encoding and one

is a boolean type for truth values.

INTEGERS

The integer types are for numbers without fractional parts. Negative values are allowed. Java provides the four integer types

JAVA INTEGER TYPES

Type Storage Requirement Range (inclusive)

Int 4 bytes 2,147,483,648 to 2,147,483, 647 (just over 2 billion) short 2 bytes -32,768 to 32,767

(9)

Byte 1 byte -128 to 127 FLOATING-POINT TYPES

The floating-point types denote numbers with fractional parts. There are two floating-point Types

Type Storage Requirement Range (inclusive)

Float 4 bytes ±3.40282347E+38F (6–7 significant decimal digits)

double 8 bytes ±1.79769313486231570E+308 (15 significant decimal digits)

THE CHARACTER TYPE

First, single quotes are used to denote char constants. For example, 'H' is a character. It is different from "H", a string containing a single character. Second, the char type denotes characters in the

Unicode encoding scheme.

Special characters

Escape Sequence Name Unicode Value

\b Backspace \u0008

\t Tab \u0009

\n Linefeed \u000a \r Carriage return \u000d \” Double quote \u0022 \’ Single quote \u0027 \\ Backslash \u005c

THE BOOLEANTYPE

The boolean type has two values, false and true. It is used for evaluating logical conditions. We

cannot convert between integers and boolean values.

VARIABLES

In Java, every variable has a type. We declare a variable by placing the type first, followed by the name of the variable. Here are some examples:

double salary; int vacationDays; long earthPopulation; char yesChar;

boolean done;

Notice the semicolon at the end of each declaration. The semicolon is necessary because a declaration is a complete Java statement.

(10)

OPERATORS

An operator takes one or more arguments and produces a new value. The arguments are in a different form than ordinary method calls, but the effect is the same. There are different types of operators are there. They are

 Arithmetic Operators  Assignment Operators

 Unary minus and plus Operators

 Auto increment and Decrement Operators  Relational Operators

 Logical Operators  Bitwise Operators  Ternary Operators

Arithmetic Operators

The following are the arithmetic operators :

addition (+), subtraction (-), division (/), multiplication (*) and modulus (%, which produces the remainder from integer division). Integer division truncates, rather than rounds, the result.

Assignment Operators

Assignment is performed with the operator =. It means “take the value of the right-hand side (often called the rvalue) and copy it into the left-hand side (often called the lvalue). An rvalue is any constant, variable or expression that can produce a value, but an lvalue must be a distinct, named variable.

For instance; A = 5;

Java also uses a shorthand notation to perform an operation and an assignment at the same time. This is denoted by an operator followed by an equal sign, and is consistent with all the operators in the language

Instead of writing x = x + 4; we can write x+=4;

Unary minus and plus Operators

The unary minus (-) and unary plus (+) are the same operators as binary minus and plus. The compiler figures out which use is intended by the way we write the expression. For instance, the statement

x = -a;

has an obvious meaning. The compiler is able to figure out: x = a * -b;

(11)

AUTO INCREMENT AND DECREMENT OPERATORS

The increment and decrement operators are the two of the nicer shortcuts. The decrement operator is -- and means “decrease by one unit.” The increment operator is ++ and means “increase by one unit.” If a is an int, for example, the expression ++a is equivalent to (a = a + 1). Increment and decrement operators produce the value of the variable as a result.

There are two versions of each type of operator, often called the prefix and postfix versions. Pre-increment means the ++ operator appears before the variable or expression, and post-increment means the ++ operator appears after the variable or expression. Similarly, pre-decrement means the -- operator appears before the variable or expression, and post-pre-decrement means the -- operator appears after the variable or expression. For increment and pre-decrement, (i.e., ++a or --a), the operation is performed and the value is produced. For post-increment and post-decrement (i.e. a++ or a--), the value is produced, then the operation is performed.

Relational Operators

Relational operators generate a boolean result. They evaluate the relationship between the values of the operands. A relational expression produces true if the relationship is true, and false if the relationship is untrue.

The relational operators are less than (<), greater than (>), less than or equal to (<=), greater than or equal to (>=), equivalent (==) and not equivalent (!=). Equivalence and nonequivalence works with all built-in data types, but the other comparisons won’t work with type boolean. The relational operators == and != also work with all objects, but their meaning often confuses the first-time Java programmer.

Logical Operators

The logical operators AND (&&), OR (||) and NOT (!) produce a boolean value of true or false based on the logical relationship of its arguments.

Bitwise Operators

The bitwise operators allow us to manipulate individual bits in an integral primitive data type. Bitwise operators perform boolean algebra on the corresponding bits in the two arguments to produce the result.

The bitwise AND operator (&) produces a one in the output bit if both input bits are one; otherwise it produces a zero. The bitwise OR operator (|) produces a one in the output bit if either input bit is a one and produces a zero only if both input bits are zero. The bitwise EXCLUSIVE OR, or XOR (^), produces a one in the output bit if one or the other input bit is a one, but not both. The bitwise NOT (~, also called the ones complement operator) is a unary operator; it takes only one argument. (All other bitwise operators are binary operators.) Bitwise NOT produces the opposite of the input bit—a one if the input bit is zero, a zero if the input bit is one.

(12)

Ternary operators

This operator is unusual because it has three operands. The expression is of the form: boolean-exp ? value0 : value1

If boolean-exp evaluates to true, value0 is evaluated and its result becomes the value produced by the operator. If boolean-exp is false, value1 is evaluated and its result becomes the value produced by the operator.

The conditional operator can be used for its side effects or for the value it produces, but in general we want the value since that’s what makes the operator distinct from the if-else. Here’s an example:

static int ternary(int i) {

return i < 10 ? i * 100 : i * 10; }

We can see that this code is more compact than what we’d need to write without the ternary operator:

static int alternative(int i) { if (i < 10) return i * 100; else return i * 10; } Control flow

Java, like any programming language, supports both conditional statements and loops to determine control flow. We start with the conditional statements and then move on to loops. We end with the somewhat cumbersome switch statement that we can use when we have to test for many values of a single expression.

CONDITIONAL STATEMENTS

The conditional statement in Java has the form

if statement

if ( condition ) statement

In Java, as in most programming languages, we will often want to execute multiple statements when a single condition is true.

For example:

if (ourSales >= target)

(13)

if/else statement if ( condition ) statement 1 else statement 2; For example:

if (ourSales >= target) { performance = "Satisfactory"; bonus = 100 + 0.01 * (ourSales - target); } else { performance = "Unsatisfactory"; bonus = 0; } if / elseif (multiple branches) statement

Repeated if . . . else if . . . alternatives are very common For example:

if (ourSales >= 2 * target)

{ performance = "Excellent"; bonus = 1000; }

else if (ourSales >= 1.5 * target)

{ performance = "Fine"; bonus = 500; }

else if (ourSales >= target)

{ performance = "Satisfactory"; bonus = 100; }

else

{ System.out.println("We're fired"); } Indeterminate Loops

In Java, as in all programming languages, there are control structures that let us repeat statements. There are two forms for repeating loops that are best when we do not know how many times a loop should be processed (these are “indeterminate loops”). First, there is the while

loop that only executes the body of the loop while a condition is true . The general form is:

while ( condition ) statement

The while loop will never execute if the condition is false at the outset see Figure 3-10). For example:

while (balance < goal)

{

balance += payment;

double interest = balance * interestRate / 100; balance += interest;

years++; }

A while loop tests at the top. Therefore, the code in the block may never be executed. If we want to make sure a block is executed at least once, we will need to move the test to the bottom. This is done with the do / while loop. Its syntax looks like this:

(14)

do statement while ( condition ); do { balance += payment;

double interest = balance * interestRate / 100; balance += interest; year++;

// print current balance . . .

// ask if ready to retire and get input . . . } while (input.equals("N"));

DETERMINATE LOOPS

The for loop is a very general construct to support iteration that is controlled by a counter or similar variable that is updated after every iteration. The following is the syntax :

for ( statement 1; expression 1; expression 2)

statement 2;

The following loop prints the numbers from 1 to 10 on the screen.

for (int i = 1; i <= 10; i++)

System.out.println(i);

Multiple Selections—the switch Statement

The if/else construct can be cumbersome when we have to deal with multiple selections with

many alternatives. Java has a switch statement that is exactly like the switch statement. The syntax, switch (choice) { case 1: . . . break; case 2: . . . break; case 3: . . . break; case 4: . . . break;

default: // bad input . . . break; }

Arrays

An array is a data structure that stores a collection of values of the same type. We access each individual value through an integer index. For example, if a is an array of integers, then a[i] is the

ith integer in the array. We declare an array variable by specifying the array type—which is the

element type followed by []—and the array variable name. For example, here is the declaration

of an array a of integers: int[] a;

(15)

However, this statement only declares the variable a. It does not yet initialize a with an actual array. We use the new operator to create the array.

int[] a = new int[100];

This statement sets up an array that can hold 100 integers. The array entries are numbered from 0 to 99 (and not 1 to 100). Once the array is created, we can fill the entries in an array, for example, by using a loop:

int[] a = new int[100];

for (int i = 0; i < 100; i++)

a[i] = i; // fills the array with 0 to 99

We can define an array variable either as

int[] a; or as int a[];

Most Java programmers prefer the former style because it neatly separates the type int[] (integer array) from the variable name.

Array Initializers and Anonymous Arrays

Java has a shorthand to create an array object and supply initial values at the same time. Here's an example of the syntax at work:

int[] smallPrimes = { 2, 3, 5, 7, 11, 13 };

Array Inititalization with new operator. The syntax is Datatype arrayname[] = new datatype[arraysize]; For Example:

int[] a = new int[10]; . . . Program

//To get string values from the command prompt and to display the values public class array1

{

public static void main(String arg[]) {

int size = arg.length;

System.out.println(“The Elements are”); for(int i=0;i<size;i++) System.out.println(arg[i]); } } output: c:\>javac array1.java

(16)

c:\>java array1 C C++ PASCAL COBOL JAVA

The Elements are C C++ PASCAL COBOL JAVA Multidimensional Arrays

Multidimensional arrays use more than one index to access array elements. They are used for tables and other more complex arrangements.

Declaring a matrix in Java is simple enough. For example: double[][] matrix;

As always, we cannot use the array until we initialize it with a call to new . In this case, we can do the initialization as follows:

matrix = new double[5][5];

In other cases, if we know the array elements, we can use a shorthand notion for initializing multidimensional arrays without needing a call to new . For example;

int[][] magicSquare = { {16, 3, 2, 13}, {5, 10, 11, 8}, {9, 6, 7, 12}, {4, 15, 14, 1} }; program

// To print a multidimensional arrays public class array2

{

public static void main(String arg[]) {

int[][] matrix = { {16, 3, 2, 13}, {5, 10, 11, 8}, {9, 6, 7, 12}, {4, 15, 14, 1} };

System.out.println("The given matrix is\n\n"); for(int i=0;i<4;i++) { for(int j=0;j<4;j++) { System.out.print(matrix[i][j]+"\t"); } System.out.println("\n"); } }

(17)

output

c:\>javac array2.java c:\>java array2

The given matrix is

16 3 2 13

5 10 11 8

9 6 7 12

4 15 14 1

1.3 OBJECT AND CLASSES

Introduction to Object-Oriented Programming

Object-oriented programming (or OOP for short) is the dominant programming paradigm these days, having replaced the “structured,” procedure-based programming techniques that were developed in the early '70s. Java is totally object oriented, and it is impossible to program it in the procedural style that we may be most comfortable with.

We need to understand some of the terminology of OOP to go further. The most important term is the class,A class is the template or blueprint from which objects are actually made. This leads to the standard way of thinking about classes: as cookie cutters. Objects are the cookies themselves. When we construct an object from a class, we are said to have created an instance of the class. apply a method to an object, its state may change. manipulate the data, no other object will know or care. As we have seen, all code that we write in Java is inside a class. Encapsulation (sometimes called data hiding) is a key concept in working with objects. Formally, encapsulation is nothing more than combining data and behavior in one package and hiding the implementation of the data from the user of the object. The data in an object are called its instance fields, and the functions and procedures that operate on the data are called its methods. A specific object that is an instance of a class will have specific values for its instance fields. The set of those values is the current state of the object. Whenever we apply a method to an object, its state may change. When we extend an existing class, the new class has all the properties and methods of the class that we extend. We supply new methods and data fields that apply to our new class only. The concept of extending a class to obtain another class is called inheritance.

The syntax for creating a class is

class classname { variable declarations method definitions … … … }

Here the class, is the keyword which should be prefixed in a class definition. All the data and methods are enclosed inside the class. We can place more than one class in a file, in that case

(18)

only one class can have the main method and it should be public. This file should be saved as the name of the main method class. The following program consists of two classes and saved as a math.java ( main method class name ).

Program

class methodclass {

int x,y;

int add(int m, int n) {

return m+n; }

int sub(int m, int n) {

return m-n; }

int mul(int m, int n) {

return m*n; }

int div(int m, int n) {

return m/n; }

}

public class math {

public static void main(String arg[]) {

if(arg.length==2) {

methodclass m = new methodclass(); int a = Integer.parseInt(arg[0]); int b = Integer.parseInt(arg[1]);

System.out.println("Arithmetic Operations\n");

System.out.println("The given numbers are "+a+", "+b); System.out.println("Addition : "+m.add(a,b)); System.out.println("Subtraction : "+m.sub(a,b)); System.out.println("Multiplication : "+m.mul(a,b)); System.out.println("Division : "+m.div(a,b)); } else {

System.out.println("Invalid input, Usage : java math number1 number2"); } } } output c:\>javac math.java c:\>java math 22 6

The given numbers are 22, 6 Addition :28

Subtraction :16

(19)

C:\>java math

Invalid input, Usage : java math number1 number2 C:\>java math 44 5 7

Invalid input, Usage : java math number1 number2 Objects and Object Variables

To work with objects, we first construct them and specify their initial state. Then we apply methods to the objects. In the Java programming language, we use constructors to construct new instances.

A Constructor is a special method whose purpose is to construct and initialize objects. Constructor always have the same name as the class name. Thus, the constructor for the Date class is called Date . To construct a Date object, we combine the constructor with the new operator, as follows:

new Date()

While writing a constructor, keep the following in our mind  A constructor has the same name as the class.  A class can have more than one constructor.

 A constructor may take zero, one, or more parameters.  A constructor has no return value.

 A constructor is always called with the new operator. Syntax for creating an object for a class

classname objectname = new classname(); For Example:

Date Birthday = new Date();

Through an object we can access any method of the particular class, For this we use a special kind of operator called Dot operator ‘.’.

int d = Birthday.get(Calendar.DAY_OF_MONTH); int m = Birthday.get(Calendar.MONTH);

1.4 INHERITANCE

Inheritance, another fundamental concept of object-oriented programming. The idea behind inheritance is that we can create new classes that are built upon existing classes. When we inherit from an existing class, we reuse (or inherit) methods and fields, and we add new methods and fields to adapt our new class to new situations.

(20)

(The arrow in the above UML diagram points from the derived class to the base class. As we will see, there can be more than one derived class.)

We have two ways to differentiate our new derived class from the original base class. The first is: We simply add new functions to the derived class. These new functions are not part of the base class interface. The second and more important way to differentiate our new class is to change the behavior of an existing base-class function. This is referred to as overriding that function.

Here is how we define a Derived class that inherits from the Base class. We use the Java keyword extends to denote inheritance.

class Derived extends Base {

added methods and fields }

1.5 PACKAGE AND INTERFACE

PACKAGE:-There is a large set of predefined classes, grouped into packages. The full name of one of these predefined classes includes the name of the package as prefix. For example, the library class java.util.Random is in package java.util, and a program may use the class with code like this: java.util.Random r = new java.util.Random();

Base

(21)

The import statement allows we to omit the package name from one of these classes. A Java program that includes the line

import java.util.Random;

can abbreviate the use of Random to Random r = new Random();

We can import all the classes in a package at once with a notation like import java.util.*;

The package java.lang is special; every program behaves as if it started with import java.lang.*;

whether it does or not. We can define our own packages, but defining packages is an advanced topic beyond the scope of what's required for this course.

The import statement doesn't really "import" anything. It just introduces a convenient abbreviation for a fully-qualified class name. When a class needs to use another class, all it has to do is use it. The Java compiler will know that it is supposed to be a class by the way it is used, will import the appropriate .class file, and will even compile a .java file if necessary. (That's why it's important for the name of the file to match the name of the class). For example, here is a simple program that uses two classes:

public class HelloTest {

public static void main(String[] args) { Hello greeter = new Hello();

greeter.speak(); }

}

public class Hello { void speak() {

System.out.println("Hello World!"); }

}

Put each class in a separate file (HelloTest.java and Hello.java). Then try this: javac HelloTest.java

java HelloTest

We should see a cheery greeting. If we type ls we will see that we have both HelloTest.class and Hello.class even though we only asked to compile HelloTest.java. The Java compiler figured out that class HelloTest uses class Hello and automatically compiled it. Try this to learn more about what's going on:

rm -f *.class

javac -verbose HelloTest.java java HelloTest

INTERFACE

The interface keyword takes the abstract concept one step further. We could think of it as a “pure” abstract class. It allows the creator to establish the form for a class: method names, argument lists, and return types, but no method bodies. An interface can also contain fields, but these are implicitly static and final. An interface provides only a form, but no implementation.

(22)

To create an interface, use the interface keyword instead of the class keyword. Like a class, we can add the public keyword before the interface keyword (but only if that interface is defined in a file of the same name) or leave it off to give “friendly” status so that it is only usable within the same package. To make a class that conforms to a particular interface (or group of interfaces) use the implements keyword. Once we’ve implemented an interface, that implementation becomes an ordinary class that can be extended in the regular way. A simple example is as follows:

interface Area{

float pi=3.14f;

float compute (float x, float y); }

class rect implements Area{

public float compute(float x, float y){ return x*y;

}

}

class cir implements Area{

public float compute(float x, float y){ return pi*x*y;

}

}

class intfacetest {

public static void main(String arg[]) [ rect r=new rect();

cir c=new cir();

System.out.println(“Rect= “+r.compute(10.20)); System.out.println(“Cir= “+c.compute(10.20)); } }

1.6 EXCEPTION HANDLING

EXCEPTIONS

A Java program should never "core dump," no matter how buggy it is. If the compiler excepts it and something goes wrong at run time, Java throws an exception. By default, an exception causes the program to terminate with an error message, but we can also catch an exception.

try { // ... foo.bar(); // ... a[i] = 17; // ... }

(23)

The try statement says we're interested in catching exceptions. The catch clause (which can only appear after a try) says what to do if an IndexOutOfBoundsException occurs anywhere in the try clause. In this case, we print an error message. The toString() method of an exception generates a string containing information about what went wrong, as well as a call trace.

WARNING Never write an empty catch clause. If we do, we will regret it. Maybe not today, but tomorrow and for the rest of our life.

Because we caught this exception, it will not terminate the program. If some other kind of exception occurs (such as divide by zero), the exception will be thrown back to the caller of this function and if that function doesn't catch it, it will be thrown to that function's caller, and so on back to the main function, where it will terminate the program if it isn't caught. Similarly, if the function foo.bar throws an IndexOutOfBoundsException and doesn't catch it, we will catch it here.

The catch clause actually catches IndexOutOfBoundsException or any of its subclasses,

including ArrayIndexOutOfBoundsException , StringIndexOutOfBoundsException , and others. An Exception is just another kind of object, and the same rules for inheritance hold for

exceptions as any other king of class.

We can define and throw our own exceptions.

class SytaxError extends Exception { int lineNumber;

SytaxError(String reason, int line) { super(reason);

lineNumber = line; }

public String toString() {

return "Syntax error on line " + lineNumber + ": " + getMessage(); }

}

class SomeOtherClass {

public void parse(String line) throws SyntaxError { // ...

if (...)

throw new SyntaxError("missing comma", currentLine); //...

}

public void parseFile(String fname) { //... try { // ... nextLine = in.readLine(); parse(nextLine); // ... } catch (SyntaxError e) { err.println(e); } }}

(24)

Each function must declare in its header (with the keyword throws) all the exceptions that may be thrown by it or any function it calls. It doesn't have to declare exceptions it catches. Some exceptions, such as IndexOutOfBoundsException, are so common that Java makes an exception for them (sorry about that pun) and doesn't require that they be declared. This rule applies to RuntimeException and its subclasses. We should never define new subclasses of RuntimeException.

There can be several catch clauses at the end of a try statement, to catch various kinds of exceptions. The first one that "matches" the exception (i.e., is a super class of it) is executed. We can also add a finally clause, which will always be executed, no matter how the program leaves the try clause (whether by falling through the bottom, executing a return, break, or continue, or throwing an exception).

1.7 THREADING

Java lets we do several things at once by using threads. If our computer has more than one CPU, it may actually run two or more threads simultaneously. Otherwise, it will switch back and forth among the threads at times that are unpredictable unless we take special precautions to control it.

There are two different ways to create threads. I will only describe one of them here.

Thread t = new Thread(command); //

t.start(); // t start running command, but we don't wait for it to finish // ... do something else (perhaps start other threads?)

// ... later:

t.join(); // wait for t to finish running command

The constructor for the built-in class Thread takes one argument, which is any object that has a method called run. This requirement is specified by requiring that command implement the Runnable interface described earlier. (More precisely, command must be an instance of a class that implements Runnable). The way a thread "runs" a command is simply by calling its run() method. It's as simple as that!

In project 1, we are supposed to run each command in a separate thread. Thus we might declare something like this:

class Command implements Runnable { String commandLine;

Command(String commandLine) {

this.commandLine = commandLine; }

public void run() {

// Do what commandLine says to do }

(25)

We can parse the command string either in the constructor or at the start of the run() method. The main program loop reads a command line, breaks it up into commands, runs all of the commands concurrently (each in a separate thread), and waits for them to all finish before issuing the next prompt. In outline, it may look like this.

for (;;) {

out.print("% "); out.flush();

String line = inputStream.readLine();

int numberOfCommands = // count how many commands there are on the line

Thread t[] = new Thread[numberOfCommands]; for (int i=0; i<numberOfCommands; i++) { String c = // next command on the line t[i] = new Thread(new Command(c)); t[i].start();

}

for (int i=0; i<numberOfCommands; i++) { t[i].join();

} }

This main loop is in the main() method of our main class. It is not necessary for that class to implement Runnable.

Although we won't need it for project 1, the next project will require to to synchronize threads with each other. There are two reasons why we need to do this: to prevent threads from interfering with each other, and to allow them to cooperate. We use synchronized methods to prevent interference, and the built-in methods Object.wait() , Object.notify() , Object.notifyAll()

, and Thread.yield() to support cooperation.

Any method can be preceded by the word synchronized (as well as public, static, etc.). The rule is: No two threads may be executing synchronized methods of the same object at the same time. The Java system enforces this rule by associating a monitor lock with each object. When a thread calls a synchronized method of an object, it tries to grab the object's monitor lock. If another thread is holding the lock, it waits until that thread releases it. A thread releases the monitor lock when it leaves the synchronized method. If one synchronized method of a calls contains a call to another, a thread may have the same lock "multiple times." Java keeps track of that correctly. For example,

class C {

public synchronized void f() { // ...

g(); // ... }

public synchronized void g() { /* ... */ } }

If a thread calls C.g() "from the outside", it grabs the lock before executing the body of g() and releases it when done. If it calls C.f(), it grabs the lock on entry to f(), calls g() without waiting, and only releases the lock on returning from f().

(26)

Sometimes a thread needs to wait for another thread to do something before it can continue. The methods wait() and notify(), which are defined in class Object and thus inherited by all classes, are made for this purpose. They can only be called from within synchronized methods. A call to wait() releases the monitor lock and puts the calling thread to sleep (i.e., it stops running). A subsequent call to notify on the same object wakes up a sleeping thread and lets it start running again. If more than one thread is sleeping, one is chosen arbitrarily2 and if no threads are sleeping in this object, notify() does nothing. The awakened thread has to wait for the monitor lock before it starts; it competes on an equal basis with other threads trying to get into the monitor. The method notifyAll is similar, but wakes up all threads sleeping in the object.

class Buffer {

private List queue = new ArrayList(); public synchronized void put(Object o) { queue.add(o);

notify(); }

public synchronized Object get() { while (queue.isEmpty()) { wait(); } return queue.remove(0); } }

This class solves the so-call "producer-consumer" problem. (The class ArrayList and interface List are part of the java.util package.) "Producer" threads somehow create objects and put them into the buffer by calling Buffer.put(), while "consumer" threads remove objects from the buffer (using Buffer.get()) and do something with them. The problem is that a consumer thread may call Buffer.get() only to discover that the queue is empty. By calling wait() it releases the monitor lock and goes to sleep so that producer threads can call put() to add more objects. Each time a producer adds an object, it calls notify() just in case there is some consumer waiting for an object.

This example is not correct as it stands (and the Java compiler will reject it). The wait() method can throw an InterruptedException exception, so the get() method must either catch it or declare that it throws InterruptedException as well. The simplest solution is just to catch the exception and print it:

class Buffer {

private List queue = new ArrayList(); public synchronized void put(Object o) { queue.add(o);

notify(); }

public synchronized Object get() { while (queue.isEmpty()) { try {

wait();

} catch (InterruptedException e) { e.printStackTrace();

(27)

}

return queue.remove(0); }

}

The method printStackTrace() prints some information about the exception, including the line number where it happened. It is a handy thing to put in a catch clause if we don't know what else to put there. Never use an empty catch clause. If we violate this rule, we will live to regret it! There is also a version of Object.wait() that takes an integer parameter. The call wait(n) will return after n milliseconds if nobody wakes up the thread with notify or notifyAll sooner.

We may wonder why Buffer.get() uses while (queue.isEmpty()) rather than if (queue.isEmpty()). In this particular case, either would work. However, in more complicated situations, a sleeping thread might be awakened for the "wrong" reason. Thus it is always a good idea when we wake up to recheck the condition that made to decide to go to sleep before we continue.

1.8 INPUT AND OUTPUT

Input/Output is not as complicated as it looks. We can get pretty far just writing to System.out

(which is of type PrintStream ) with methods print , println , and printf . The method print simply writes converts its argument to a String and writes it to the output stream. The method println is similar, but adds a newline so that following output starts on a new line. The method printf is new in Java 1.5. It expects a String as its first argument and zero or more additional arguments. Each '%' in the first argument indicates a request to print one of the other arguments. The details are spelled out by one or more characters following the '%'. For example, out.printf("pair(%d, %d)%n", pair.x, pair.y);

produces exactly the same thing as

out.println("pair(" + pair.x + "," + pair.y + ")");

but is much easier to read, and to write. The characters %d are replaced by the result of converting the next argument to a decimal integer. Similarly, "%f" looks for a float or double, "%x" looks for an integer and prints it in hexadecimal, and "%s" looks for a string. Fancier formatting is supported; for example, "%6.2f" prints a float or double with exactly two digits following the decimal point, padding with leading spaces as necessary to make the result at least 6 character long.

For input, we probably want to wrap the standard input System.in in a BufferedReader , which provides the handy method readLine()

BufferedReader input =

new BufferedReader(new InputStreamReader(System.in)); for(;;) {

String line = input.readLine(); if (line == null) {

break; }

// do something with the next line }

(28)

If We want to read from a file, rather than from the keyboard (standard input), we can use FileReader, probably wrapped in a BufferedReader.

BufferedReader input =

new BufferedReader(new FileReader("somefile")); for (;;) {

String line = input.readLine(); if (line == null) {

break; }

// do something with the next line }

Similarly, we can use new PrintWriter(new FileOutputStream("whatever")) to write to a file.

(29)

CHAPTER

II

INTRODUCTION TO J2EE

Today, Java is one of the most mature and commonly used programming languages for building enterprise software. The evolution of Java from a means of developing applets to be run in browsers, to a programming module capable of driving today is enterprise applications has been remarkable. Over the years, java has evolved into three different platform editions, each addressing a distinct set of programming needs;

The Java 2 Platform , Standard Edition (J2SE) :

This is most commonly used of these java platforms, consisting of a runtime environment and a set of API’s for building a wide variety of applications ranging from applets, through stand alone applications that run on over various platforms, to client applications for various enterprise applications.

The Java 2 Platform , Enterprise Edition (J2EE) :

J2EE is a platform for building server-side applications.

The Java 2 Platform, Micro Edition (J2ME):

The latest addition to the java family, this edition enables the building of java applications for “Micro devices”.

The J2EE Platform

J2EE specifies both the infrastructure for managing our applications, and the service API’s for building our applications. The J2EE Platform is essentially distributed application-server environment - a java environment that provides the following;

 A set of java extension API’s to build applications. These APIs define a programming model for J2EE applications.

 A run-time infrastructure for hosting and managing applications. This is the server runtime in which our application reside.

The applications that we could develop with the above may be programs to drive web pages, or components to implement complex data base transactions, or even java applets, all distributed across the network.

(30)

The J2EE APIs

Distributed applications require access to a set of enterprise services. Typical services include transaction processing, database access, multithreading, etc. The J2EE architecture unifies access to such services in its enterprise service APIs. However, instead of having to access these service through proprietary or non-standard interfaces, application programs in J2EE can across these APIs via the container.

A typical commercial J2EE platform (or J2EE application server) includes one or more containers, and access to the enterprise APIs is specifies by the J2EE. The specification of the J2EE platform includes a set of Java standard extensions that each J2EE platform must support:

JDBC

More specifically, the JDBC optional package. This API improves the standard JDBC API by adding more efficient means of obtaining connections, connection pooling, distributed transaction, etc.

Enterprise JavaBeans (EJB)

This specifies a component framework for multi-tier distributed applications. This provides a standard means of defining server-side components, and specifies a rich run-time infrastructure for hosting components on the server side.

Java Servlets

The Java Servlets API provides object-oriented abstractions for building dynamic web applications.

JavaServer Pages

This extension further enhances J2EE web applications by providing for template-driven web application development.

Java Message Service

JMS provides a Java API for message queuing, and publish and subscribe types of message-oriented middleware services.

Java Transaction API (JTA)

(31)

Java Mail

This API provides a platform-independent and protocol-independent framework to build Java based email applications.

JavaBeans Activation Framework

This API is required for the Java Mail API. The Java Mail API uses JAF to determine the contents of a MIME (Multipurpose Internet Mail Extension) message and determine what appropriate operations can be done on different parts of a mail message.

Java API for XML Parsing (JAXP)

This API provides abstractions for XML parsers and transformation APIs. JAXP helps to isolate specific XML parsers, or XML Document Object Model (DOM) implementations, or XSLT transformation APIs from J2EE application code.

The Java Connector Architecture (JCA)

This API has recently been included in J2EE, and provides a means to integrate J2EE application components to legacy information systems.

Java Authentication and Authorization Service (JAAS)

This API provides authentication and authorization mechanisms to J2EE applications.

Most of these API are specifications, independent of implementation. That is, one should be able to access services provided by these APIs in a standard way, irrespective of how they are implemented. The J2EE-specific APIs mentioned above are in addition to the following J2SE APIs:

Java Interface Definition Language (IDL) API

This API allows J2EE application components to invoke CORBA objects via IIOP

JDBC Core API

This API provides the basic database programming facilities.

RMI-IIOP API

This provides on implementation of the usual Java Remote Method Invocation (RMI) API over the Internet Inter-ORB protocol (IIOP). This bridges the gap between RMI and CORBA applications. This is the standardized communication protocol to be used between J2EE containers.

(32)

JNDI API

The Java Naming and Directory Interface (JNDI) API standardized access to different types of naming and directory services available today. This API is designed to be independent of any specific naming or directory service implementations. J2SE also specifies a JNDI service provider interface (SPI), for naming and directory service providers to implement.

2.2 J2EE ARCHITECTURE

A typical commercial J2EE, platform includes one or more containers. But what exactly is a container? A J2EE container is a runtime to manage application components developed according to the API specifications, and to provide access to the J2EE APIs. Beyond the Identity associated with the runtime, J2EE does not specify any identity for containers. This gives a great amount of flexibility to achieve a variety of features within the container runtime. The following figure shows the architecture of J2EE in terms of its containers and APIs:

This architecture shows four containers :

A web container for hosting Java servlets and JSP pages.

An EJB container for hosting Enterprise JavaBeans components.An applet container for hosting Java applets.

(33)

Each of these containers provides a run-time environment for the respective components. J2EE components are also called managed objects, as these objects are created and managed within the container runtime.

In this architecture, there are primarily two types of clients:

Web clients normally run in web browsers.

For these clients, the user interface is generated on the server side as HTML or XML, and it’s downloaded and then rendered by the browsers. These clients use HTTP to communicate with web containers. Application components in web containers include Java servlets and JSP pages. These components implement the functionality required for the clients. Web containers are responsible for accepting requests from web clients, and generating responses with the help of the application components.

EJB clients are applications that access EJB components in EJB container.

There are three possible types of EJB clients. First categories application clients. Application clients are standalone applications accessing the EJB components using RMI-IIOP protocol. The second category of application clients are components in the web container. That is, Java servlets and JSP pages can also access the EJB components via the RMI-IIOP protocol in the same way as the application clients. The final category is other EJBs running within the EJB container. These communicate via standard Java method calls through a local interface.

J2EE Technologies

J2EE technologies that provide the mechanics we need to build large, distributed enterprise applications. This large collection, of quite disparate technologies, can be divided according to use:

The component technologies

These technologies are used to hold the most important part of the application-the business logic. There are three types of components: JSP pages, servlets and Enterprise JavaBeans.

The service technologies

These technologies provide the applications components with supported services to function efficiently.

The communication technologies

These technologies, which are mostly transparent to the application programmer, provide the mechanisms for communication among different parts of the application, whether they are local or remote.

(34)

2.3 COMPONENT TECHNOLOGIES

These components will be dependent upon the container for many services, such as life cycle management, threading, and security. These allows us to concentrate on providing the requisite business functionality without getting into details of low-level (container-level) semantics.

Web components

These can be categorized as any component that response to an HTTP request. A further distinction can be drawn is based on the hosting container for the application components.

Servlets

Servlets are server side programs that allow application logic to be embedded in the HTTP request-response process. Servlets provide a means to extends the functionality of the web server to enable dynamic content in HTML, XML, or other web languages.

JavaServer Pages

JavaServer Pages (JSP) provides a way to embed components in a page, and to have them do their work to generate the page is eventually send to the client. A JSP page can contain HTML, Java code, and JavaBean components. JSP pages are infact an extension of the servlets programming model. When a user requests a JSP page, a web container compiles the JSP page into a servlets. The web container then invokes the servlets and returns the resulting content to the web browser. Thus, JSP pages provide a powerful and dynamic page assembly mechanism that benefits from the many advantages of the Java platform.

Enterprise JavaBean components

Enterprise JavaBeans (EJB) is a distributed component model for developing secure,

scalable, transactional, and multi-user components. To put it simply, EJBs are reusable software units containing business logic. Just as JSP pages allow the separation of application and presentation logic, EJBs allow separation of application logic from system-level services thus allowing the developer to concentrate on the business domain issues and not system programming. These enterprise bean business objects take three basic forms – again, It is not necessary to implement them all – session beans, entity beans, and message driven beans.

Session Beans

Session beans themselves come in two types. A stateful session bean is a transient object used to represent a clients interaction with the system – it performs the clients request in the application, accessing a database etc., and when the clients operations are compleate and it is destroyed. The alternative, a stateless session bean, maintains no state between client requests. Generally this type of session bean is used to implement a specific service that does not require client state.

(35)

Entity Beans

An entity bean on the other hand is a persistent object that models the data held within the data store , that is, it is an object wrapper for the data. Compared to session beans that can be used by any client, entity beans can be accessed concurrently by many clients but must maintain a unique identity through a primary key.

Message-Driven Beans

Message-driven beans are a special class of EJBs that are not meant for direct client invocation. The purpose of message-driven beans is to process messages received via JMS. Message-driven beans complement the asynchronous nature of JMS by providing a means of processing messages within the EJB container. When an application client or an application sends a message via JMS, the container invokes the appropriate message-driven bean to process the message.

2.4 SERVICE TECHNOLOGIES

Some of the J2EE services for application components are managed by the containers themselves, thus allowing the developer to concentrate on the business logic. However, there will be times when developers find it necessary to programmatically invoke some services themselves using some of the various service technologies.

JDBC

Although all data access should be accessible through the single standard API of the Connector architecture in the future, database connectivity is probably one of the key services that developers implement in their application component.

The JDBC API provides the developer with the ability to connect to relational database systems. It allows the transactional querying, retrieval, and manipulation of data from a JDBC-complaint database.

Java transaction API and service

The Java Transaction API (JTA) is a means for working with transactions and especially distributed transactions independent of the transaction manager’s implementation.

JNDI

The Java Naming and Directory Interface (JNDI) API standardized access to different types of naming and directory services available today. This API is designed to be independent of any specific naming or directory service implementations. J2SE also specifies a JNDI service provider interface (SPI), for naming and directory service providers to implement.

(36)

Java Message Service (JMS)

JMS provides a Java API for message queuing, and publish and subscribe types of message-oriented middleware (MOM) services.

Java Mail

This API provides a platform-independent and protocol-independent framework to build Java based email applications

The Java Connector Architecture (JCA)

This API has recently been included in J2EE, and provides a means to integrate J2EE application components to legacy information systems.

Java Authentication and Authorization Service (JAAS)

This API provides authentication and authorization mechanisms to J2EE applications. It provides a means to grant permissions based on who is executing the code.

2.5 COMMUNICATION TECHNOLOGIES

The final technology grouping is those technologies that provide the means for the various components and services within a J2EE application to communicate with each other – a distributed application would be pretty ineffectual if these technologies didn’t provide the ‘glue’ to hold it all together.

Internet Protocols

A client request and the server’s responses are communicated over three main protocols.

HTTP

HTTP or Hypertext Transfer Protocol is a generic, stateless, application-level protocol, which has many uses beyond simply hypertext capabilities. It works on a request/response basis. A client sends a request to a server in the form of a request method, URI (Uniform Resource Identifier), and protocol version, followed a MIME-like message containing request modifiers, client information, and possible body content over a connection with a server. The server in turn responds with a ststus line followed by a MIME-like message containing server information, entity-meta information, and possible entity-body content.

TCP/IP

TCP(Transmission Control Protocol) over IP(Internet Protocol) is actually two separate

(37)

making sure that data is received by both endpoints in communication over the Internet. When we type the address of the website into our browser, IP is what ensures that our request and the fulfillment of those requests make it to the proper destinations. TCP is the protocol that keeps track of the packets and make sure they are assembled in the same order as they were dispatched and are error free. Therefore, TCP and IP work together to move data around on the Internet.

SSL

Secure Sockets Layer (SSL) uses cryptography to encrypt the flow of information between the

client and the server. This also provides a means for both parties to authenticate each other. Secure HTTP (HTTPs) is usually distinguished from regular unencrypted HTTP by being served on a different port number.

Remote object Protocols

In applications where the components are often distributed across many tiers and servers, some mechanism for using the components remotely I srequired, preferably leaving the client unaware that the component is not local to itself.

RMI and RMI-IIOP

Remote Method Invocation (RMI) is one of the primary mechanism in distributed object applications. It

allows us to use interface to define remote objects. We can then call methods on these remote objects as if they were local. The exact wire-level transportation mechanism is implementation-specific.

RMI-IIOP is an extension of RMI but over IIOP (Inter-ORB Protocol) , which allows us to define a

remote interface to any remote object that can be implemented in any language that supports OMG mapping and ORB.

2.6 SERVERS

The J2EE platform is a large collection of APIs, all working together to provide a unified platform for enterprise development. The J2EE platform consists of various components and services that are available and operate in containers. However, J2EE itself does not actually implement these components but relies on third-party vendors to provide the actual implementation. That implementation is called J2EE application servers.

Features of an application server

The following are the features that an application server should provide:  Scalability

 Client agnosticism  Server management  Development

(38)

The term application server as we know it today is assigned to a product that implements the J2EE standard and offers a web container and EJB container, as a minimum, packaged as server software. This product must comply with a version of J2EE standards, preferably the latest and be able to provide:

Web and EJB container

An environment for component based applications to map easily to the functionality desired from the application.

Component behavior

To enable assembly and deploy-time behaviors. Components can expect the availability of services in run-time environment, and can be connected to other components providing a set of well-defined interfaces. As a result, components can be configured for a certain type of behavior at application assembly or deployment time without any recoding required.

Scalability

J2EE containers must provide a mechanism that supports simplified scaling of distributed applications, without requiring any effort on the part of the application development team. Clustering is one of the features used to fulfill this standard requirement.

Integration with existing enterprise systems

This can be done with a number of standard APIs that have to be supported in a J2EE implementation:

 JDBC APIs for accessing relational data from Java.

 Java Transaction API (JTA) for managing and coordinating transactions across heterogenous enterprise information systems.

 Java Naming and Directory Interface (JNDI) API for accessing information in enterprise name and directory services.

 Java Messaging Service (JMS) API for sending and receiving messages via enterprise messaging systems like IBM MQ Series, or TIBCO Rendezvous.

 JavaMail APIs for sending and receiving e-mails.  Java IDL APIs for calling CORBA services.

 Security services like the Java Authentication and Authorization Service (JAAS).

While the J2EE specification defines the component containers that must be supported and the APIs that should be available. It does not try to specify or restrict the configuration of these containers, and the layout of the services. Thus, both container types can run either on a single platform or on a distributed environment.

Examining Full J2EE Implementations

The available application servers that fully support the J2EE platform. They implement what is effectively a one-stop shop for our J2EE needs. Even though the J2EE platform is middleware

(39)

and we may opt for one J2EE component, we are not tied to its whole implementation; we are still free to swap in third-party implementations to replace specific layers.

The following are the application servers that fully support the J2EE platform.  BEA WebLogic

 Borland Enterprise Server  IBM WebSphere

 JBoss  Oracle 9iAS

 Orion Application Server  Sun ONE

Examining Partial J2EE Implementations

Without a doubt, the J2EE platform is large, Many developers will only ever use servlets and JSP; the requirement to install the full J2EE server is overkill for them. The Servlet API is one of the oldest and best-established APIs of the J2EE platform. Many servlets engines on the market provide support for the full Servlet API and JSP specifications, and these are some of the more popular ones:

 Apache Tomcat  Resin

References

Related documents

The others (e.g. Playing Videos, adding the shutdown button) are not crucial to the camera project but can be done if you’re also interested in exploring these capabilities.

This paper presents the performance and emission characteristics of a CRDI diesel engine fuelled with UOME biodiesel at different injection timings and injection pressures..

and relocations. The section containing the entry symbol and all sections con- taining symbols undefined on the command-line will be kept, as will sections containing symbols

Table 5 reveals that, type of Integrated Library Management Software (ILMS) packages used in Engineering College Libraries, the data shows that majority of engineering

When Hashem told Moshe that He will destroy the Jewish people and only save him and make a nation of him (exactly like He did to Noach) Moshe said “macheni” which means erase my

Urban Uco Sauvignon Blanc 2008 88 points Wine Spectator Daily Wine Pick 85 points Wine Advocate (Robert Parker) Urban Uco Sauvignon Blanc 2007 85 points Wine Advocate

By focusing on multiple categories of owners of a corporation, we contribute in three ways to the literature dealing with minority controlling shareholders (Bebchuk and Weis-