Wednesday, March 28, 2012

EJB ,database connection with JDBC

Summary of JDBC Interfaces

JDBC Interface

Description

DataSource

Represents a particular database or other data source and its connection pool. It’s used as a factory to establish a Connection with a data source.

Connection

Represents a session to the database. It’s used as a factory for other types of objects such as Statement. It handles all other database manipulation and operations.

Statement

Sends simple SQL statements, with no parameters, to a database. Created from a Connection object.

PreparedStatement

Inherits from Statement. Used to execute a precompiled SQL statement with or without parameters. Used for more efficient data access.

CallableStatement

Inherits from PreparedStatement. Used to execute a call to a database stored procedure.

ResultSet

Contains the results of executing an SQL query. It contains the rows that satisfy the conditions of the query.

ResultSetMetaData

Provides information about the types and properties of the columns in a ResultSet object.

DataBaseMetaData

Provides information about database schema objects.

Clob

A built-in data type that stores a Character Large Object as a column value in a row of a database table. Part of SQL3 data types.

Blob

A built-in data type that stores a Binary Large Object as a column value in a row of a database table. Part of SQL3 data types.

figure the main classes and interfaces of the JDBC API and the main methods used.

API main classes and interfaces.

The javax.sql Package

The javax.sql package extends the functionality of the JDBC API from a client-side API to a server-side API, and is an essential part of J2EE technology. The key interface to this package is the DataSource interface, which is the factory for creating connections. Other interfaces and classes of this package support distributed transactions, which are commonly used by EJB container providers. As application and bean developers, our main interface in this package is the DataSource interface.

Using Connection Pooling

JDBC supports the concept of connection pooling. A pool is a collection of database connections maintained and managed by the application server. A J2EE application reuses database connections from the connection pool. An application server assigns a connection transparently to the application. A connection pool is represented as a DataSource object.

The main reason for using a connection pool is to enhance the performance of running applications. The task of establishing a connection to a database is usually slow because it requires considerable time for the initialization process. With connection pools, connections are established during application server startup and are available to be used by all components. Both database servers and application servers run more efficiently with dedicated connections than if they have to handle incoming connection attempts at runtime. Using connection pools increases the scalability of the system, which can therefore handle more number of users.

Another reason for using connection pools is to separate the application code from database configuration. In setting up a connection pool, we use a declarative approach to describe these configuration settings outside the application. Applications do not need to know of or transmit the database username, password, and location. This separation between application logic and database environment allows you to develop portable and reusable code, which is an important factor in designing enterprise applications. A connection pool, represented by a DataSource object, is created and registered by the system administrators into the JNDI service using a logical name. Hence it becomes available as a resource to be shared by all system components and users.

database connection pool.

Configuring the Connection Pool

Connection pools are set in the application server configuration files. Depending on the application, you can have more than one connection pool, with each being used by different components of the application. The following parameters are required to configure a connection pool:

  • Connection pool name: Used to identify and register the DataSource with the JNDI service, and later used by the application to recognize the DataSource‘s name.

  • Initial number of connections: The number of connections to be created in the pool at startup.

  • Maximum and minimum pool size.

  • JDBC URL: Specifies the database location, database name, listening port, and the hostname.

  • JDBC driver class name.

  • JDBC driver properties: Any properties required to connect to the data source. They are name/value pairs, such as user ID and password.

Note

Setting up both maximum and minimum pool size is of prime importance. The impact of setting your maximum below the expected peak load of system users will degrade performance at the time you need it most.


Understanding DataSource Interface

A DataSource object is a factory for Connection objects. An object that implements the DataSource interface will typically be registered with a JNDI service provider. A DataSource is a representation of a database and its connection pool. An application uses the JNDI service provider to look up the connection pool name and creates a DataSource object factory. An application can be directed to a different data source simply by changing the DataSource object’s properties; no change in the application code is needed. Likewise, a DataSource implementation can be changed without changing the application code that uses it, which enhances application portability.

To create a Connection object from a DataSource object, we can use either a declarative or a programmatic approach. In the following sections, we will discuss both these approaches.

Declarative Approach

One of the objectives of the J2EE architecture is to enhance the deployment of enterprise applications. This is accomplished by separating the application code, from its deployment and configuration files. In the declarative approach, you set all configuration parameters of the databases and connection pools in a configuration file or deployment descriptor.

Using the declarative approach, a Connection object is created from a DataSource object by using the following method:

Connection Conn = datasource.getConnection()

This method has no parameters, and the container, behind the scenes, will use all the settings in the deployment and configuration files as the default settings.

If the database location or settings must be changed, you change only the configuration files without any modifications to the application code. This container-managed approach is one of the attractive features for many of the common services provided by the J2EE platform.

Programmatic Approach

The programmatic approach, on the other hand, enables you to control and manage the database setting from inside the application code. The following method is used in making a connection to the database using this approach:

Connection conn =     dataSource.getConnection (String username, String password);

This method creates a Connection to the database by overriding the default user and password. Both the username and password must be hard-coded in the application code, which has a negative affect on application portability.

Caution

Another method of obtaining a database connection is the use of the DriverManager. The DataSource concept was introduced in the JDBC 2.0 Extension package. The JDBC specification recommends the cleaner DataSource method as the preferred method of obtaining a Connection for a J2EE application. The current use of obtaining a Connection through hard-coded parameters to the DriverManager method is deprecated. DriverManager is a shared object with synchronized methods and therefore it’s single threaded. This technique establishes a bottleneck for the applications trying to access databases. On the other hand, the DataSource object is a multithreaded object than can handle the access of more than one concurrent user.

Learning the Connection Interface

A connection to a specific database represents a user session. Within the context of a Connection, SQL statements are executed and results are returned to the client for more processing. Connections are created from a DataSource object as described in the previous section. A connection is assigned transparently to the application by the JDBC driver. table the methods used for the Connection interface.

Summary of Connection Methods

Method

Purpose

Statement createStatement()

Creates a Statement object for sending SQL statements to the database

PreparedStatement prepareStatement(String sql)

Creates a PreparedStatement object for sending parameterized SQL statements to the database

void commit()

Makes all changes made since the previous commit()/rollback() permanent, and releases any database locks currently held by the Connection

void rollback()

Drops all changes made since the previous commit()/rollback(), and releases any database locks currently held by this Connection

void setAutoCommit(boolean ac)

Sets this connection’s auto-commit mode

DatabaseMetaObject getMetaData()

Get all database schema information

void close()

Releases a Connection‘s database and JDBC resources immediately instead of waiting for them to be released automatically

A Connection object to the database is able to provide connection parameters and schema object information. This includes data tables, supported SQL grammar, stored procedures, and the capabilities of this connection. This information can be obtained with the getMetaData() method.

Note

A Connection object manages transaction behavior. By default, the Connection automatically commits changes after executing each statement. If autoCommit has been disabled, an explicit commit() must be done or database changes will not be saved.

Exception Handling

A number of exceptions can be thrown as a result of connecting to a database or performing any of the operations mentioned earlier. The main exception is SQLException, which is thrown by most of the methods in the java.sql package. Other exceptions are summarized in

Summary of Exceptions

Exception

Purpose

SQLException

Thrown by most methods when there is a problem accessing data and by some methods for other reasons.

SQLWarning

Queried from the Statement object to indicate a warning. It inherits from SQLExecption.

DataTruncation

Thrown to indicate that data might have been truncated. It inherits from SQLWarning.

BatchUpdateException

Thrown to indicate that not all commands in a batch update executed successfully. It inherits from SQLException.

Note

SQLWarning objects are not thrown as other exceptions—you have to query them. SQLWarning objects will build up due to multiple Statement method calls (such as execute() and executeUpdate()) until you ask for each Statement object with getWarning() and getNextWarning(). Statement objects automatically clear warnings on the next execution.

SQLExceptions must be handled in the catch clause. Information about errors can be obtained by the getErrorCode(), which prints a vendor-specific error. The getSQLState() method prints a standard SQL message. In addition, the method getMessage() prints a message that describes the error.

Connecting to a Data Source

Applications must first be connected to a database before performing any database operation. As explained earlier, connections are made ready by the container, at startup, through the creation of a connection pool.

Connections are created using the DataSource object. Applications need to locate a DataSource object, before creating a Connection. Applications locate a DataSource through the JNDI service. The following is an example of these steps:

// Connect to the default JNDI service and establish a context Context ctx = new InitialContext(); // Lookup the DataSource for the configured database javax.sql.DataSource ds = (javax.sql.DataSource)         ctx.lookup ("java:comp/env/jdbc/styejbDB"); // Make a connection to the database java.sql.Connection conn = ds.getConnection();  // do some work  // Release the connection after you are done conn.close();

Note

You must release the connection as soon as you have done work with it by closing the connection. When the client virtually closes the connection with close(), behind the scenes, the container returns the connection to the pool, and makes it available for use by other clients.

As recommended, JDBC DataSource references should always be declared in the java:comp/env/jdbc subcontext. This is established by the system administrator when the DataSource is being created.

Establishing a context to the JNDI service is an expensive operation, especially when using an RMI call. Always connect to the JNDI service to obtain a DataSource object in the initialization code of your application. This can be done once, and connection(s) can be assigned by the DataSource to other parts of the application during its lifetime.

Applications rely on the container to manage the connection pool, but when building scalable applications, releasing connections as soon as possible is the responsibility of the developer.

The traditional way of getting a connection is by using the DriverManager. As mentioned early today, this is a deprecated method, and we recommend using the DataSource method if possible. For the sake of completeness, the following snippet shows how to make a connection using the DriverManager:

String sourceURL = "jdbc:cloudscape:styejbPool"; String driverClass = "COM.cloudscape.core.JDBCDriver" // Loading the JDBC driver Class.forName(driverClass); // Make a connection using the DriverManager java.sql.Connection conn = DriverManager.getConnection(sourceURL);

Data Manipulation

After a connection is made to the data source, the JDBC API is furnished with comprehensive operations. Both DDL (Data Definition Language) and DML (Data Manipulation Language) operations are available. Metadata (information about the database itself) or the result set can also be queried.

Note

We assume that the reader is familiar with SQL fundamentals. For more coverage of SQL, we recommend you to refer to the book, Sams Teach Yourself SQL in 10 Minutes (ISBN: 0672321289).

A Statement object represents a SQL statement, and must be created from the Connection object. A Statement sends simple SQL statements to the database:

// Create a Statement object java.sql.Statement stmt = conn.createStatement();

One of the powerful methods of the Statement object is the execute() method. All DDL and DML database operations can be performed using the execute() method.

Caution

All DDL operations, such as creating and dropping objects, can be performed by the execute() method of the Statement object. However, creating a database instance is DBMS-specific, and is not available to all JDBC drivers.

// Using the execute method for some DDL operations try { stmt.execute(“DROP TABLE Student “); } catch (SQLException e) { System.out.println(“Table Student already exists.”); } stmt.execute(“CREATE TABLE Student (id integer, fname varchar(15), lname varchar(15), ssn varchar(12))”); System.out.println(“Table Student is created…”); // Using the execute method for some DML operations stmt.executeUpdate (“INSERT into Student values (1, ‘Lillian’, ‘Ghaly’ , ’111-000-1111′)”); stmt.executeUpdate (“INSERT into Student values (2, ‘Raj’, ‘Talla’ , ’222-000-2222′)”); stmt.executeUpdate (“INSERT into Student values (3, ‘Tony’, ‘Hunter’ , ’333-000-3333′)”); stmt.executeUpdate (“INSERT into Student values (4, ‘John’, ‘Smith’ , ’444-000-4444′)”); // close statements when done stmt.close();

Note

When creating a Statement, resources will be allocated to the application in order to execute the SQL. It is vital to release these resources, by closing the Statement when execution is complete, using the close() method.

The execute() method returns a boolean: true if the next result is a ResultSet object, or false if it is an update count or there are no more results. The following code gets a ResultSet object, which holds the result of the last query:

stmt.execute(“SELECT * from DAY09_STUDENTS”); // Obtain the result of the last query ResultSet rs = stmt.getResultSet();

The ResultSet is initially positioned before the first row. table below gives a summary of the ResultSet methods.

Summary of ResultSet Methods

Method

Purpose

Boolean next()

Scrolls the cursor to the next available row

String getString(int columnIndex)

Returns data at the current cursor, under a particular column number or index

String getString(String columnName)

Returns data at the current cursor, under a particular column name

Boolean isFirst()

Returns true if the cursor is at the first row

Boolean isLast()

Returns true if the cursor is at the last row

int getFetchSize()

Returns the default fetched number of rows

setFetchSize(int rows)

Set the required number of rows to be fetched

ResultSetMetaData getMetaData()

Returns data about the ResultSet, such as number of columns and the properties of data elements

Now we can scroll through the ResultSet to display the retrieved data using getString() method. From the earlier example, the ResultSet contains four columns and four rows. Columns can be identified by column name or column number. This example uses the column name:

// Display the ResultSet data on the screen using column name while (rs.next()) System.out.println(rs.getString(“student_id”) + ” ,” + rs.getString(“first_name”) + ” ,” + rs.getString(“last_name”) + ” ,” + rs.getString(“address”));

When using the column number, you pass an integer value to getString() that starts with 1, which represents the first column:

// Display the ResultSet data using column number while (rs.next()) System.out.println(rs.getString(1) + ” ,” + rs.getString(2) + ” ,” + rs.getString(3) + ” ,” + rs.getString(4)); // close the result set after done. rs.close();

In both cases, the output of the last println should look like this:

1, LILLIAN, GHALY, 15 DIAMOND ST, BOSTON, MA 3, SAM, LE, 12 APPLEBEE RD, LOS ANGELES, CA

Much like the Statement object, the ResultSet object can be tuned to the optimum number of fetched rows. To do this, use the getFetchSize() and setFetchSize() methods of ResultSet. This increases the performance when a large number of rows is retrieved during search operations. Close the ResultSet object when you’re done to release allocated resources.

Optimized Queries to the Database

A shortcut method of querying the database is to use the executeQuery() method of the Statement object. This combines both execute() and getResultSet() in one method. The preceding example can be written as

// Obtain the ResultSet directly ResultSet rs = stmt.executeQuery("SELECT * DAY09_STUDENTS");

Both simple queries, such as the one specified in the preceding example, and more sophisticated joins can be specified as a parameter String to the executeQuery() method.

Another variant used with the INSERT, UPDATE, and DELETE operations is the executeUpdate() method:

// Using the executeUpdate method instead of execute() String sql = "INSERT into DAY09_STUDENTS values " +    "('1', 'LILLIAN', 'GHALY', '15 DIAMOND ST, BOSTON, MA')"); stmt.executeUpdate(sql);

The executeUpdate() method specializes in DML operations. DDL operations, such as drop table, create table, and so on, are made available only through the execute() method as explained in the previous section.

Using a PreparedStatement

In situations where the same statement is performed repeatedly, a more optimized way is to use a PreparedStatement. This divides the operation into a creation phase and an execution phase. When creating the statement, the database is instructed to be ready by pre-parsing and compiling the statement, and preparing its buffers to assign variables to the table elements. The execution phase requests the database to execute the operation after the required elements filled up. Let’s illustrate this with the following code:

// Create a PreparedStatement PreparedStatement pstmt =      conn.preparedStatement("INSERT INTO DAY09_STUDENT values (?,?,?,?)")

The database is now instructed to prepare the buffers for the operation. Each data element is mapped to the wild card in sequence. We use setString() method to fill up the holes:

// Fill up the data elements and execute pstmt.setInt(1, 2); pstmt.setString(2, "DOUG"); pstmt.setString(3, "ZANDER"); pstmt.setString(4, "11 ORANGE AVE, SACRAMENTO, CA"); int rcount = pstmt.executeUpdate();

Other methods to pass these parameters depend on the parameter type, and take the pattern setXXX(). For example, setInt() to pass in an int, setFloat() to pass in a float, setBoolean() to pass in a boolean, and so on.

Using PreparedStatement saves time for a repeated statement, and hence enhances the performance of your application. The return value of the last executeUpdate() indicates the number of rows affected as a result of any INSERT, UPDATE, or DELETE operation. The PreparedStatement inherits all its properties and methods from the Statement object.

Using a CallableStatement for Stored Procedures

The JDBC API provides support for calling a stored procedure. The CallableStatement inherits from PreparedStatement, and is used to call a stored procedure. procedure is a group of SQL statements that can be called by name, and are stored in a file and managed by the underlying Relational Database Management System (RDBMS). Stored procedures, once written, can be compiled and then reused. They are executed on the database server, which relieves the application server of performing the task. The CallableStatement is created from the Connection method prepareCall().

The following snippet demonstrates how the stored procedure getStudentById is created and sent to the RDBMS to compile and store under the name getStudentById:

// Create stored procedure String storedPoc = "create procedure GetStudentById(Stid integer)" +      "as begin" +      "SELECT * FROM DAY09_STUDENT" +      "WHERE student_id = 'Stid'" +      "end"; Statement stmt = conn.createStatement(); stmt.executeUpdate(storedPoc);

The next code demonstrates the use of a CallableStatement that calls the previous stored procedure getStudentById:

CallableStatement cstmt = conn.prepareCall(                "{call getStudentById(?)}"); cstmt.setInt(1,4); ResultSet rs = cstmt.executeQuery();

The variable cstmt contains a call to the stored procedure getStudentById, which has one IN parameter, represented by the wildcard ? placeholder. Normally, stored procedure parameter types can be one of type IN, OUT, or INOUT. Passing in any IN parameter values to a CallableStatement object is done using the setXXX() methods inherited from PreparedStatement. The JDBC type of each OUT parameter must be registered before the CallableStatement object can be executed. Registering the JDBC type is done with the method registerOutParameter() of the CallableStatement. After the statement has been executed, CallableStatement‘s getXXX() methods can be used to retrieve OUT parameter values. An INOUT parameter requires both treatments of IN and OUT parameter.

Caution

Care should be taken when writing stored procedures. Because it belongs to the data layer, too much logic in a stored procedure violates the purpose of separating data from the application logic. Be aware also that stored procedures do not work the same way across all RDBMSes. In addition, all stored procedures must be compiled again if you have to change just one of them

Using Local Transactions

A transaction is a group of SQL statements that represents one unit of work. A transaction executes all of its statements or none at all. JDBC handles both local and distributed transactions. Today we’re covering only local transactions.

A local transaction belongs only to the current process, and deals with only a single resource manager that handles a DataSource. An RDBMS is an example of a resource manager., A distributed transaction, on the other hand, manages multiple DataSources across multiple processes. All database operations mentioned earlier today that use a Statement object are implicitly transactional with auto-commit. That means the DBMS commits the transaction as soon as any execute(), executeUpdate(), or executeBatch() is done.

Local transactions are managed by the Connection object, and not by the EJB container. To change this implicit behavior, JDBC provides the method setAutoCommit(false) to set the transaction mode on the Connection object. The commit() and rollback() methods also are used by the Connection object to control the transaction’s behavior. An example of a local transaction is as follows:

// Create a Statement from Connection and its set transaction mode conn.setAutoCommit(false); Statement stmt = conn.createStatement(); try { stmt.executeUpdate(“UPDATE DAY09_STUDENT set first_name=’Laura’ where student_id =’5′”); // assume something wrong happen here….. stmt.executeUpdate(“UPDATE DAY09_STUDENT set last_name=’Smith’ where student_id =’5′”); conn.commit(); } catch (SQLException ex) { conn.rollback(); stmt.close(); }

Disabling auto-commit using setAutoCommit(false) is required when a batch of SQL statements must execute together, or the EJB container is managing the transaction. Controlling transactions can increase performance because you commit a batch of SQL statements instead doing so one at a time. JDBC architects realized this fact and have built the concept of batch updates into the JDBC API. Batch updates will be covered in the next section.


Using Batch Updates

Another aspect of enhancing performance of applications is the reduction of network traffic between J2EE tiers, or applications that partitioned to run on different servers. One way to reduce network traffic back and forth between components and enhance the performance of the running application is to use bulk updates, which are coarse-grain updates. This experience is reflected by the JDBC architects in the JDBC API, and is implemented by using the addBatch() method of the Statement object to prepare the batch before using the executeBatch() method. Batch updates use any of the INSERT, UPDATE, and DELETE operations. To use batch updates, you must disable the auto-commit mode.

try{   // Disable auto-commit   conn.setAutoCommit(false);   // Create a Statement from Connection   Statement stmt = conn.createStatement()   stmt.addBatch("INSERT INTO DAY09_STUDENT " +   "values('7', 'ERIC', 'CHRISTIAN', '1 MEMORIAL DRIVE, CAMBRIDGE, MA')";   stmt.addBatch("UPDATE DAY09_STUDENT set first_name='Laura' where id='5'");   int [] rc = stmt.executeBatch();   conn.commit();   conn.setAutoCommit(true); } catch(BatchUpdateException sqlb) {     System.err.println("SQL State: " + sqlb.getSQLState());     System.err.println("Message: " + sqlb.getMessage());     System.err.println("Vendor Error: " + sqlb.getErrorCode());     System.err.print("Update counts:  ");     int [] updateCounts = sqlb.getUpdateCounts();     for (int i = 0; i < updateCounts.length; i++) {       System.err.print(updateCounts[i] + "   ");     }     System.err.println("");   }

The executeBatch() method returns an array of integers that specifies the row count of each operation in the batch.

Batch updates throw BatchUpdateException, which inherits from SQLException, and information can extracted about each update. Performance can be enhanced by tuning the number of rows to be fetched at a runtime from database. By default, you can get the default number of rows provided by the JDBC driver by using getFetchSize() on the Statement object. You can tune the size by using the setFetchSize(int rows) method of the Statement object.

Working with Metadata

Metadata is data about data, and in the context of our study of JDBC, it’s the information provided about the properties of data sources and result sets. Querying metadata is very powerful in creating tools for database manipulation and sophisticated database applications.

To find information about the connected database, we use the method getMetaData() of the Connection object to retrieve a DatabaseMetaData object. You can get information about schemas, tables, and properties of each table. The following sample queries database metadata to display all the table names and properties of each table in the schema "APP":

// Finding MetaData about database DatabaseMetaData dbmd = conn.getMetaData(); String[] types = {"TABLE"}; System.out.println("Database Table Names for the Schema "APP") rs = dbmd.getTables(null, "APP", null, types); while (rs.next()){     String tableName = rset.getString("TABLE_NAME");     System.out.println("Table Name: " + tableName);     ResultSet rsc = dbmd.getColumns(null,null,tableName,"%");     System.out.println("Column Name" + "    Data Type" + " Width");     while (rsc.next()){       System.out.println(rsc.getString("COLUMN_NAME") + "..." +                          rsc.getString("TYPE_NAME") + "..." +                          rsc.getInt("COLUMN_SIZE"));     } }

When sending a SELECT statement to the database, you receive a ResultSet that holds the records to satisfy your criteria. To find metadata information about a ResultSet object, use the getMetaData() method of the ResultSet interface. This metadata will be captured and retrieved by getMetaData() into a ResultSetMetaData object. Such metadata of a ResultSet is the number of columns and the database properties of each column, such as its name, type, width, and precision. An example of retrieving a ResultSetMetaData object about a ResultSet is the following:

// Finding MetaData about result set Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("select * from student"); ResultSetMetaData rsmd = rs.getMetaData(); int cn = rsmd.getColumnCount(); // Printing column information for (int i=1; i<= cn ; i++) {       if (i > 1) { System.out.print(", "); }       System.out.print(rsmd.getColumnLabel(i)); } System.out.print("") // Printing the data while (rs.next ()) {        for (int i=1; i<=cn; i++) {          if (i > 1) { System.out.print(", "); }            System.out.print(rs.getString(i));        }        System.out.println(""); }

By combining ResultSetMetaData and DatabaseMetaData, toolmakers can build very powerful database interactive tools to query and schema objects and data.

Working with JDBC Through a Full Example

Now it’s time for todayís example. it gives a skeleton of code that performs the following:

  • Connects to a database

  • Performs few of both DDL and DML statements

  • Queries ResultSet metadata and database metadata

  • Closes the statements and the connection

  • Handles SQL exceptions


Home Interface /QueryDBHome.java
import java.rmi.RemoteException; import javax.ejb.*;  /*   QueryDBHome is the home interface for the stateless session bean.  */ public interface QueryDBHome extends EJBHome{   QueryDB create() throws CreateException, RemoteException; }
Remote Interface /QueryDB.java
package day09; import java.util.*; import javax.ejb.*; import java.rmi.RemoteException;  /*   QueryDB is the remote interface for the stateless session bean.  */ public interface QueryDB extends EJBObject{    public void initDB() throws RemoteException;    public void doDDL() throws RemoteException;    public void getMetaData() throws RemoteException; }
The Bean Class /QueryDBBean.java

 import java.util.*; import javax.ejb.*; import javax.naming.*; import java.sql.*;  /**  * QueryDBEJB is stateless session bean to query database properties  */ public class QueryDBBean implements SessionBean {   public void initDB(){   try {     System.out.println("\nDay 9: Demonstrate the use of JDBC...\n");     System.out.println("initDB: Get initial context from the JNDI service...");     ctx = new InitialContext();     System.out.println("Lookup the DataSource as configured by administrator...");     ds = (javax.sql.DataSource)ctx.lookup ("java:comp/env/jdbc/styejbDB");     System.out.println("Getting a Connection from the pool...");     conn = ds.getConnection();     System.out.println("Connection is obtained...");    } catch (Exception e) {       System.out.println("Exception was thrown: " + e.getMessage());    } finally {           try {            if (stmt != null)                   stmt.close();            if (conn != null)                   conn.close();           } catch (SQLException sqle) {                      System.out.println("SQLException during close(): " + sqle.getMessage( graphics/ccc.gif));           }     }   }   public void doDDL(){     System.out.println("Run some DDL statements:");    try{      conn = ds.getConnection();     stmt = conn.createStatement();     try {            System.out.println("Trying to drop table DAY09_STUDENTS...");            stmt.execute("DROP TABLE DAY09_STUDENTS");     } catch (SQLException e) {            System.out.println("Table DAY09_STUDENTS already exists.");     }     stmt.execute("CREATE TABLE DAY09_STUDENTS (student_id varchar(12),"+                                  "first_name varchar(15),"+                                  "last_name varchar(15),"+                                  "address varchar(64))");     System.out.println("Table DAY09_STUDENTS is created...");      System.out.println("Run some DML statements:");     stmt.executeUpdate("INSERT into DAY09_STUDENTS values " +                    "('1', 'LILLIAN', 'GHALY', '15 DIAMOND ST, BOSTON, MA')");     stmt.executeUpdate("INSERT into DAY09_STUDENTS values " +                    "('2', 'DOUG','ZANDER','11 ORANGE AVE, SACRAMENTO, CA' )");     stmt.executeUpdate("INSERT into DAY09_STUDENTS values " +                    "('3', 'SAM','LE', '12 APPLEBEE RD, LOS ANGELES, CA' )");     stmt.executeUpdate("DELETE from DAY09_STUDENTS where student_id = '2'");     rs = stmt.executeQuery("SELECT * from DAY09_STUDENTS");     // Get some Metadata about result set     System.out.println("Query ResultSet Metadata:");     rsmd = rs.getMetaData();     cn = rsmd.getColumnCount();     for (i=1; i<= cn ; i++) {            if (i>1) System.out.print(", ");            System.out.print(rsmd.getColumnLabel(i));     }     System.out.println("");     while (rs.next()) {            for (i=1; i<= cn ; i++) {                   if (i>1) System.out.print(", ");                   System.out.print(rs.getString(i));            }            System.out.println("");     }   } catch (Exception e) {           System.out.println("Exception was thrown: " + e.getMessage());   } finally {           try {            if (stmt != null)                   stmt.close();            if (conn != null)                   conn.close();           } catch (SQLException sqle) {              System.out.println("SQLException during close(): " + sqle.getMessage());           }    }   }   public void getMetaData() {     // Get some Metadata about database    System.out.println("Query Database Metadata:");    try{      conn = ds.getConnection();      dbmd = conn.getMetaData();      System.out.println("  Product Name: " + dbmd.getDatabaseProductName());      System.out.println("  Driver Name: " + dbmd.getDriverName());      rs = dbmd.getSchemas();      System.out.println("Database Schemas:");      rsmd = rs.getMetaData();      cn = rsmd.getColumnCount();      for (i=1; i<= cn ; i++) {             if (i>1) System.out.print(", ");             System.out.print(rsmd.getColumnLabel(i));      }      System.out.println("");      while (rs.next()) {             for (i=1; i<= cn ; i++) {                    if (i>1) System.out.print(", ");                    System.out.print(rs.getString(i));                    if (schema == null)                       schema = new StringBuffer(rs.getString(i));             }             System.out.println("");      }      String[] types = {"TABLE"};      System.out.println("Printing All Data Tables for Schema: " + schema);      rs = dbmd.getTables(null, schema.toString(), null, types);      while (rs.next()){             String tableName = rs.getString("TABLE_NAME");             System.out.println("Table Name: " + tableName);              ResultSet rsc = dbmd.getColumns(null,null,tableName,"%");             rsmd = rsc.getMetaData();             cn = rsmd.getColumnCount();             for (i=1; i<= cn ; i++) {                    if (i>1) System.out.print(", ");                    System.out.print(rsmd.getColumnLabel(i));             }             System.out.println("");             while (rsc.next()) {                    for (i=1; i<= cn ; i++) {                       if (i>1) System.out.print(", ");                       System.out.print(rsc.getString(i));                    }                    System.out.println("");             }      }    } catch (Exception e) {      System.out.println("Exception was thrown: " + e.getMessage());    } finally {      try {             if (stmt != null)                    stmt.close();             if (conn != null)                    conn.close();      } catch (SQLException sqle) {         System.out.println("SQLException during close(): " + sqle.getMessage());      }    }  }   public void setSessionContext(SessionContext ctx) {this.bctx = ctx;}   public void ejbCreate() throws CreateException {}   public void ejbRemove() {}   public void ejbActivate() {}   public void ejbPassivate() {}    private SessionContext bctx;   private Context ctx                       = null;   private StringBuffer schema    = null;   private javax.sql.DataSource ds        = null;   private java.sql.Connection conn  = null;   private java.sql.Statement stmt   = null;   private java.sql.ResultSet rs             = null;   private java.sql.ResultSetMetaData rsmd    = null;   private int cn, i;   private java.sql.DatabaseMetaData dbmd    = null;
EJB Client Client.java
import java.util.*; import java.rmi.*; import java.io.*; import javax.naming.*; import javax.ejb.*;  public class Client {    public static void main(String argv[]) {        Context initialContext = null;        QueryDBHome qdbHome = null;        QueryDB qdb = null;        System.out.print("\nDay 9: Demonstration the use of JDBC...\n ");         try        {           System.out.print("Looking up the QueryDB home via JNDI.\n");           initialContext = new InitialContext();           Object object = initialContext.lookup("day09/QueryDBHome");           qdbHome = (QueryDBHome)              javax.rmi.PortableRemoteObject.narrow(object, QueryDBHome.class);           System.out.print("Creating an Query DB.\n");           qdb =  (QueryDB) qdbHome.create();           qdb.initDB();           qdb.doDDL();           qdb.getMetaData();        }catch ( Exception e){        e.printStackTrace();       }   } }
Standard Deployment Descriptor ejb-jar.xml
                  QueryDB       day09.QueryDBHome       day09.QueryDB       day09.QueryDBBean       Stateless       Container               jdbc/styejbDB        javax.sql.DataSource        Application                      jdbc/styejbDB        javax.sql.DataSource                
WebLogic Deployment Descriptor weblogic-ejb-jar.xml
            QueryDB                      jdbc/styejbDB          jdbc.styejbDB                        jdbc/styejbDB          jdbc.styejbDB                 day09/QueryDBHome    
The JBoss Deployment Descriptor jboss.xml
                 QueryDB       day09/QueryDBHome                  jdbc/styejbDB           java:/DefaultDS                          jdbc/styejbDB           java:/DefaultDS                 

Because each application server has its own way of referencing its own resources in the JNDI services, your application needs to be written to avoid such dependency. In order to make your application portable, you need to use the element in the standard deployment descriptor (ejb-jar.xml) to define a logical name, which is used by the application. Then you need to map this logical name to a <reference-descriptor> in your server-specific deployment descriptor, which is the physical reference to the JNDI name. The lines of code (shown in bold) in the preceding example demonstrate the use of such technique.

Configuring the DataSource and the Connection Pool

Before you run the example, you need first to create and configure the connection pool styejbPool. You also need to create the DataSource styejbDB for the connection pool and register it in the JNDI service. The accompanying day09/Readme.txt file explains this process for both WebLogic and JBoss servers.

Compile and Run the Example

This section describes the steps to comoile and run the example for both WebLogic Server and JBoss application servers.

To run the example in WebLogic Server, you must follow these steps:

  1. Open a new command window.

    Set up the environment for the appropriate application server, and then start the server. Run the accompanying script, found at the root of the sample directory, to set up an environment for either WebLogic Server or JBoss. The following are the scripts for WebLogic Server.

    Figure the connection pool styejbPool in WebLogic Server.

    Figure Configuring a JDBC connection pool.

    Figure Configuring a JDBC connection pool.

  2. Set up and start the PointBase database using the following steps:

    c:\>cd c:\styejb\examples c:\styejb\examples>startPointbase.bat c:\styejb\examples>setEnvWebLogic.bat c:\styejb\examples>setupPointbase.bat

    The above steps start PointBase Server and create the tables in a PointBase server named styejbPool.

  3. Start WebLogic Server using the following steps:

    c:\>cd c:\styejb\examples c:\styejb\examples>setEnvWebLogic.bat c:\styejb\examples>startWebLogic.bat
  4. Open the WebLogic Administration Console using a Web browser such as Internet Explorer, and point to the URL http://localhost:7001/console. When prompted, enter the user name (system) and password you chose when you installed WebLogic Server

  5. Create a connection pool for the Pointbase Database by doing the following:

    In the left pane, expand Services > JDBC.

    Click Connection Pools.

    In the right pane, click Configure a New JDBC Connection Pool.

    Enter these values:

    Name: styejbPool

    URL: jdbc:pointbase:server://localhost:9092/styejbPool

    Driver: com.pointbase.jdbc.jdbcUniversalDriver

    Properties: user=PBPUBLIC

    Password: PBPUBLIC

    Leave both the fields ACLName and Open String Password blank.

    Click Create.


    Click the Connections tab and change the Maximum Capacity to 10 and click the Apply button.

    Click the Targets tab.

    Move myserver to the Chosen (right) column.


    Click Apply.

  6. Create the JDBC data source.

    Click the Home icon in the upper-right corner of the Administration Console.

    In the left pane, expand Services > JDBC.

    Click Tx Data Sources.

    In the right pane, click Configure a New JDBC Data Source.

    For Name, enter styejbDB

    For JNDI Name, enter jdbc.styejbDB

    For Pool Name, enter styejbPool


    Click Create.

    Click the Targets tab.

    Move myserver to the Chosen (right) column.

    Click Apply.

    To check the current list of data sources, click Home, and then click JDBC > TXData Sources.

  7. Build the example for the appropriate application server. From the directory Day09, run the build script. This creates a subdirectory with the name build, which contains all the compiled code.

    c:\>cd c:\styejb\examples c:\styejb\examples>setEnvWebLogic.bat c:\styejb\examples>cd day09 c:\styejb\examples\day09>buildWebLogic.bat
  8. To run the example, use the appropriate script for each server. Set up the environment for the client in a new command window, and then use the run script in the Day09 directory:

    c:\styejb\examples>setEnvWebLogic.bat c:\styejb\examples>cd day09 c:\styejb\examples\day09> runClientWebLogic.bat

Refer to the README.TXT file in the day09 directory to information to configure your JBoss datasource. The following is the server-side output of the example:

Day 9: Demonstrate the use of JDBC...  initDB: Get initial context from the JNDI service... Lookup the DataSource as configured by administrator... Getting a Connection from the pool... Connection is obtained... Run some DDL statements: Trying to drop table STUDENTS... Table STUDENTS is created... Run some DML statements: Query ResultSet Metadata: STUDENT_ID, FIRST_NAME, LAST_NAME, ADDRESS 1, LILLIAN, GHALY, 15 DIAMOND ST, BOSTON, MA 3, SAM, LE, 12 APPLEBEE RD, LOS ANGELES, CA Query Database Metadata:   Product Name: PointBase   Driver Name: PointBase JDBC Driver Database Schemas: TABLE_SCHEM PBPUBLIC POINTBASE Printing All Data Tables for Schema: PBPUBLIC Table Name: COURSES ...

Note

If your output contains an exception such as Exception was thrown: Unable to resolve jdbc.styejbDB. Resolved: 'jdbc' Unresolved:'styejbDB', your connection pool and data source configuration are incorrect.

The following steps describe how to start JBoss server, run the sample client, and set up the database tables required for the remaining days:

  1. Start JBoss server in a new command window as follows:

    C:\>cd styejb\examples C:\styejb\examples>setEnvJBoss.bat C:\styejb\examples>startJBoss.bat

    The JBoss server automatically starts the default HyperSonic database.

  2. Build and run the example as follows:

    c:\>cd c:\styejb\examples c:\styejb\examples>setEnvJBoss.bat c:\styejb\examples>cd day09 c:\styejb\examples\day09>buildJBoss.bat C:\styejb\examples\day09>runClientJBoss.bat
  3. Set up the database tables required for the remaining days by doing the following:

    In the command window that you used to build and run the example, run the following command:

    c:\styejb\examples>setupHypersonic.bat

    This opens the HSQL Database Manager Connect window. Enter the value jdbc:hsqldb:hsql://localhost:1476 for the URL field. Leave default values for other fields. figure below the correspon ding screen shot. Click the Ok button.

    Connecting to the HyperSonic Database Manager.

    Click the File\Open Script… menu item. When prompted, enter the filename c:\styejb\examples\styejbhs.sql.

Click the Execute button on the right. figure below shows the corresponding screen shot.

up the database tables in HyperSonic database.

  • Best Practices

    Some of the best practices are already built-in the JDBC API itself, such as connection pooling, PreparedStatement, and batch updates. Still some of the widely known practices help when developing large and enterprise J2EE applications.

    Some factors affecting the performance of your application with respect to database are independent of JDBC or any other access method. Examples of such factors are writing optimized queries, and tuning the database using caching of often-used resources. Both database tuning and query optimization are beyond the scope of this book. A simple example such as using the query "SELECT * from Student” rather than "SELECT id from Student" when you need only the student IDs, increases network traffic and the allocated resources to handle such ResultSet. Performing an UPDATE row operation rather than a DELETE on the row followed by an INSERT of new row, is another type of good practice.

    With respect to JDBC, performance gain can be established by obtaining a Context to the DataSource in the initialization code. Use PreparedStatement to performing the same query repeatedly. CallableStatement also gives better performance than PreparedStatement and Statement when there is a requirement for single request to process multiple complex statements. It parses and stores the stored procedures in the database and optimizes the work at the database itself to improve its performance. Use stored procedure and triggers for large operations, but use them with care. Stored procedures are handled differently by database products. This has a negative affect on application portability and makes you rely on vendor-specific stored procedures.

    Use batch updates to perform batches of SQL statements. Release all resources appropriately; that is, in the reverse order of how they were allocated. If possible, avoid transaction auto-commit, and control your transaction behavior.

    Tuning your connection pool is a prime factor in the overall system performance. Both minimum and maximum size should be selected based on the expected user load. Another factor is that the Connection must be returned to the pool as soon as you are done working with it. Delaying the release of the connection has negative impact on an application’s scalability. Disabling auto-commit to control batch operations through a single transaction also helps improve application performance.

  • Summary

    Today we covered JDBC as a standard and unified API to access many data sources in tabular forms, such as relational tables, flat files, and spreadsheets. J2EE applications and components use JDBC across all tiers. We examined the methods of connecting to a data source, and showed how to construct and implement SQL statements, and the optimized ways of handling them. We looked briefly at local transactions and stored procedures. Metadata of both the DBMS and the ResultSet was discussed, and we ended by giving a brief account of the best practices in dealing with database objects and queries using JDBC.

Monday, March 19, 2012

This keyword in java

Within an instance method or a constructor, this is a reference to the current object — the object whose method or constructor is being called. You can refer to any member of the current object from within an instance method or a constructor by using this.

Using this with a Field

The most common reason for using the this keyword is because a field is shadowed by a method or constructor parameter.

For example, the Point class was written like this

public class Point {
public int x = 0;
public int y = 0;

//constructor
public Point(int a, int b) {
x = a;
y = b;
}

}

but it could have been written like this:

public class Point {
public int x = 0;
public int y = 0;

//constructor
public Point(int x, int y) {
this.x = x;
this.y = y;
}

}

Each argument to the constructor shadows one of the object's fields — inside the constructor x is a local copy of the constructor's first argument. To refer to the Point field x, the constructor must use this.x.

Using this with a Constructor

From within a constructor, you can also use the this keyword to call another constructor in the same class. Doing so is called an explicit constructor invocation. Here's another Rectangle class, with a different implementation .

public class Rectangle {
private int x, y;
private int width, height;

public Rectangle() {
this(0, 0, 0, 0);
}
public Rectangle(int width, int height) {
this(0, 0, width, height);
}
public Rectangle(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
...
}

This class contains a set of constructors. Each constructor initializes some or all of the rectangle's member variables. The constructors provide a default value for any member variable whose initial value is not provided by an argument. For example, the no-argument constructor calls the four-argument constructor with four 0 values and the two-argument constructor calls the four-argument constructor with two 0 values. As before, the compiler determines which constructor to call, based on the number and the type of arguments.

If present, the invocation of another constructor must be the first line in the constructor.

Friday, March 16, 2012

Garbage collector in Java

Since objects are dynamically allocated by using the new operator, you might be wondering how such objects are destroyed and their memory released for later reallocation. In some languages, such as C++, dynamically allocated objects must be manually released by use of a delete operator. Java takes a different approach; it handles deallocation for you automatically. The technique that accomplishes this is called garbage collection. It works like this: when no references to an object exist, that object is assumed to be no longer needed, and the memory occupied by the object can be reclaimed. There is no explicit need to destroy objects as in C++. Garbage collection only occurs sporadically (if at all) during the execution of your program. It will not occur simply because one or more objects exist that are no longer used. Furthermore, different Java run-time implementations will take varying approaches to garbage collection, but for the most part, you should not have to think about it while writing your programs.

The finalize( ) Method

Sometimes an object will need to perform some action when it is destroyed. For example, if an object is holding some non-Java resource such as a file handle or window character font, then you might want to make sure these resources are freed before an object is destroyed. To handle such situations, Java provides a mechanism called finalization. By using finalization, you can define specific actions that will occur when an object is just about to be reclaimed by the garbage collector.
To add a finalizer to a class, you simply define the finalize( ) method. The Java run time calls that method whenever it is about to recycle an object of that class. Inside the finalize( ) method you will specify those actions that must be performed before an object is destroyed. The garbage collector runs periodically, checking for objects that are no longer referenced by any running state or indirectly through other referenced objects. Right before an asset is freed, the Java run time calls the finalize() method on the object. The finalize( ) method has this general form:

protected void finalize( )
{
// finalization code here
}

Here, the keyword protected is a specifier that prevents access to finalize( ) by code defined outside its class. It is important to understand that finalize( ) is only called just prior to garbage collection. It is not called when an object goes out-of-scope, for example. This means that you cannot know when—or even if—finalize( ) will be executed. Therefore, your program should provide other means of releasing system resources, etc., used by the object. It must not rely on finalize( ) for normal program operation.

1) objects are created heap in java irrespective of there scope e.g. local or member variable. while its worth noting that class variables or static members are created in method area of space and both heap and method area is shared between different thread.
2) Garbage collection is a mechanism provided by Java Virtual Machine to reclaim space from objects which are eligible for Garbage collection.
3) Garbage collection relieves java programmer from memory management which is essential part of C++ programming and gives more time to focus on business logic.
4) Garbage Collection in Java is carried by a daemon thread called Garbage Collector.
5) Before removing an object from memory Garbage collection thread invokes finalize () method of that object and gives an opportunity to perform any sort of cleanup required.
6) You as Java programmer can not force Garbage collection in Java; it will only trigger if JVM thinks it needs a garbage collection based on java heap size
7) There are methods like System.gc () and Runtime.gc () which is used to send request of Garbage collection to JVM but it’s not guaranteed that garbage collection will happen.
8) If there is no memory space for creating new object in Heap Java Virtual Machine throws OutOfMemoryError .
9) J2SE 5(Java 2 Standard Edition) adds a new feature called Ergonomics goal of ergonomics is to provide good performance from the JVM with minimum of command line tuning.


When an Object becomes Eligible for Garbage Collection
An Object becomes eligible for Garbage collection or GC if its not reachable from any live threads or any static refrences in other words you can say that an object becomes eligible for garbage collection if its all references are null. Cyclic dependencies are not counted as reference so if Object A has reference of object B and object B has reference of Object A and they don't have any other live reference then both Objects A and B will be eligible for Garbage collection.
Generally an object becomes eligible for garbage collection in Java on following cases:
1) All references of that object explicitly set to null e.g. object = null
2) Object is created inside a block and reference goes out scope once control exit that block.
3) Parent object set to null, if an object holds reference of another object and when you set container object's reference null, child or contained object automatically becomes eligible for garbage collection.
4) If an object has only live references via WeakHashMap it will be eligible for garbage collection..

Heap Generations for Garbage Collection in Java
Java objects are created in Heap and Heap is divided into three parts or generations for sake of garbage collection in Java, these are called as Young generation, Tenured or Old Generation and Perm Area of heap.
New Generation is further divided into three parts known as Eden space, Survivor 1 and Survivor 2 space. When an object first created in heap its gets created in new generation inside Eden space and after subsequent Minor Garbage collection if object survives its gets moved to survivor 1 and then Survivor 2 before Major Garbage collection moved that object to Old or tenured generation.There are many opinions around whether garbage collection in Java happens in perm area of java heap or not, as per my knowledge this is something which is JVM dependent and happens at least in Sun's implementation of JVM. You can also try this by just creating millions of String and watching for Garbage collection or OutOfMemoryError.

Types of Garbage Collector in Java
Java Runtime (J2SE 5) provides various types of Garbage collection in Java which you can choose based upon your application's performance requirement. Java 5 adds three additional garbage collectors except serial garbage collector. Each is generational garbage collector which has been implemented to increase throughput of the application or to reduce garbage collection pause times.

1) Throughput Garbage Collector: This garbage collector in Java uses a parallel version of the young generation collector. It is used if the -XX:+UseParallelGC option is passed to the JVM via command line options . The tenured generation collector is same as the serial collector.

2) Concurrent low pause Collector: This Collector is used if the -Xingc or -XX:+UseConcMarkSweepGC is passed on the command line. This is also referred as Concurrent Mark Sweep Garbage collector. The concurrent collector is used to collect the tenured generation and does most of the collection concurrently with the execution of the application. The application is paused for short periods during the collection. A parallel version of the young generation copying collector is sued with the concurrent collector. Concurrent Mark Sweep Garbage collector is most widely used garbage collector in java and it uses algorithm to first mark object which needs to collected when garbage collection triggers.

3) The Incremental (Sometimes called train) low pause collector: This collector is used only if -XX:+UseTrainGC is passed on the command line. This garbage collector has not changed since the java 1.4.2 and is currently not under active development. It will not be supported in future releases so avoid using this and please see 1.4.2 GC Tuning document for information on this collector.
Important point to not is that -XX:+UseParallelGC should not be used with -XX:+UseConcMarkSweepGC. The argument passing in the J2SE platform starting with version 1.4.2 should only allow legal combination of command line options for garbage collector but earlier releases may not find or detect all illegal combination and the results for illegal combination are unpredictable. It’s not recommended to use this garbage collector in java.

JVM Parameters for garbage collection in Java
Garbage collection tuning is a long exercise and requires lot of profiling of application and patience to get it right. While working with High volume low latency Electronic trading system I have worked with some of the project where we need to increase the performance of Java application by profiling and finding what causing full GC and I found that Garbage collection tuning largely depends on application profile, what kind of object application has and what are there average lifetime etc. for example if an application has too many short lived object then making Eden space wide enough or larger will reduces number of minor collections. you can also control size of both young and Tenured generation using JVM parameters for example setting -XX:NewRatio=3 means that the ratio among the young and tenured generation is 1:3 , you got to be careful on sizing these generation. As making young generation larger will reduce size of tenured generation which will force Major collection to occur more frequently which pauses application thread during that duration results in degraded or reduced throughput. The parameters NewSize and MaxNewSize are used to specify the young generation size from below and above. Setting these equal to one another fixes the young generation. In my opinion before doing garbage collection tuning detailed understanding of garbage collection in java is must and I would recommend reading Garbage collection document provided by Sun Microsystems for detail knowledge of garbage collection in Java. Also to get a full list of JVM parameters for a particular Java Virtual machine please refer official documents on garbage collection in Java.

Full GC and Concurrent Garbage Collection in Java
Concurrent garbage collector in java uses a single garbage collector thread that runs concurrently with the application threads with the goal of completing the collection of the tenured generation before it becomes full. In normal operation, the concurrent garbage collector is able to do most of its work with the application threads still running, so only brief pauses are seen by the application threads. As a fall back, if the concurrent garbage collector is unable to finish before the tenured generation fill up, the application is paused and the collection is completed with all the application threads stopped. Such Collections with the application stopped are referred as full garbage collections or full GC and are a sign that some adjustments need to be made to the concurrent collection parameters. Always try to avoid or minimize full garbage collection or Full GC because it affects performance of Java application. When you work in finance domain for electronic trading platform and with high volume low latency systems performance of java application becomes extremely critical an you definitely like to avoid full GC during trading period.

In any application, objects could be categorized according to their life-line. Some objects are short-lived, such as most local variables, and some are long-lived such as the backbone of the application. The thought about generational garbage collection was made possible with the understanding that in an s lifetime, most instantiated objects are short-lived, and that there are few connections between long-lived objects to short-lived objects.

In order to take advantage of this information, the memory space is divided to two sections: young generation and old generation. In Java, the long-lived objects are further divided again to permanent objects and old generation objects. Permanent objects are usually objects the Java VM itself created for caching like code, reflection information etc. Old generation objects are objects that survived a few collections in the young generation area.

Since we know that objects in the young generation memory space become garbage early, we collect that area frequently while leaving the old generations memory space to be collected in larger intervals. The young generation memory space is much smaller, thus having shorter collection times.

An additional advantage to the knowledge that objects die quickly in this area, we can also skip the compacting step and do something else called copying. This means that instead of seeking free areas (by seeking the areas marked as unused after the marking step), we copy the live objects from one young generation area to another young generation area. The originating area is called the From area, and the target area is called the To area, and after the copying is completed the roles switch: the From becomes the To, and the To becomes the From.

Thursday, March 15, 2012

SOA

you have probably heard the phrase service-oriented architecture (SOA). But what is SOA, and more importantly, why is it of interest to the business integration space? WebSphere Integration Developer applications are implemented using a service-oriented architecture, so let's start by looking at what SOA is and what it means for your application to follow this architectural pattern.

Ideally, you want to be able to reuse your existing IT assets as building blocks or components for new applications. Each building block is a service, which means you can access each one in a standard way without regard to its implementation or location. In an SOA, the business logic is separated from the infrastructure, or "plumbing," so that developers can focus on the implementation and not worry about how the service will be accessed.

Put in simplest terms, services are black boxes; you don't care what goes on inside as long as they perform as advertised. Once you have the black boxes, the next key step is to connect them together into an overall integrated application. The boxes can be Java™ technology, Business Process Execution Language (BPEL), connections or adapters to your legacy systems, or connections to Web services provided by partners. These black boxes are your service building blocks.

Services generally are stateless, which means you do not have to worry about calling them in a certain order or in a specific context. Furthermore, you might want to incorporate the services of your business partners and access those in the same way that you access your own services. You might also want your partners to be able to access your services. With SOA, you can adapt or respond easily to a changing business environment by swapping one service for another, or by calling new services as needed. This makes it easy for transactions to occur between businesses.

What is a standard way to access services? Services have published interfaces, which serve as a contract between the service and the caller. An interface can be described with Web Services Definition Language (WSDL), for example, as in the case of Web services. The interface includes the specification of the data that is to be passed to and from the service. The interface doesn't specify how or with what language the service is implemented. So, you could have a service implemented with Java that makes calls to another service that is implemented with BPEL.

All that is a high level, generic view that sounds nice, but we should get down to how you can realize a service-oriented architecture with WebSphere Integration Developer. In the last article, we described all of the different ways to implement services, but we didn't say much about how the services work together.

Java Calculator functionalty

The code below is to implement Calculator through Java.


import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;

public class Calculator extends JFrame implements ActionListener{
// Variables
final int MAX_INPUT_LENGTH = 20;
final int INPUT_MODE = 0;
final int RESULT_MODE = 1;
final int ERROR_MODE = 2;
int displayMode;

boolean clearOnNextDigit, percent;
double lastNumber;
String lastOperator;

private JMenu jmenuFile, jmenuHelp;
private JMenuItem jmenuitemExit, jmenuitemAbout;

private JLabel jlbOutput;
private JButton jbnButtons[];
private JPanel jplMaster, jplBackSpace, jplControl;

/*
* Font(String name, int style, int size)
Creates a Font from the specified name, style and point size.
*/

Font f12 = new Font("Times New Roman", 0, 12);
Font f121 = new Font("Times New Roman", 1, 12);

// Constructor
public Calculator()
{
/* Set Up the JMenuBar.
* Have Provided All JMenu's with Mnemonics
* Have Provided some JMenuItem components with Keyboard Accelerators
*/

jmenuFile = new JMenu("File");
jmenuFile.setFont(f121);
jmenuFile.setMnemonic(KeyEvent.VK_F);

jmenuitemExit = new JMenuItem("Exit");
jmenuitemExit.setFont(f12);
jmenuitemExit.setAccelerator(KeyStroke.getKeyStroke( KeyEvent.VK_X,
ActionEvent.CTRL_MASK));
jmenuFile.add(jmenuitemExit);

jmenuHelp = new JMenu("Help");
jmenuHelp.setFont(f121);
jmenuHelp.setMnemonic(KeyEvent.VK_H);

jmenuitemAbout = new JMenuItem("About Calculator");
jmenuitemAbout.setFont(f12);
jmenuHelp.add(jmenuitemAbout);

JMenuBar mb = new JMenuBar();
mb.add(jmenuFile);
mb.add(jmenuHelp);
setJMenuBar(mb);

//Set frame layout manager

setBackground(Color.gray);

jplMaster = new JPanel();

jlbOutput = new JLabel("0");
jlbOutput.setHorizontalTextPosition(JLabel.RIGHT);
jlbOutput.setBackground(Color.WHITE);
jlbOutput.setOpaque(true);

// Add components to frame
getContentPane().add(jlbOutput, BorderLayout.NORTH);

jbnButtons = new JButton[23];
// GridLayout(int rows, int cols, int hgap, int vgap)

JPanel jplButtons = new JPanel(); // container for Jbuttons

// Create numeric Jbuttons
for (int i=0; i<=9; i++)
{
// set each Jbutton label to the value of index
jbnButtons[i] = new JButton(String.valueOf(i));
}

// Create operator Jbuttons
jbnButtons[10] = new JButton("+/-");
jbnButtons[11] = new JButton(".");
jbnButtons[12] = new JButton("=");
jbnButtons[13] = new JButton("/");
jbnButtons[14] = new JButton("*");
jbnButtons[15] = new JButton("-");
jbnButtons[16] = new JButton("+");
jbnButtons[17] = new JButton("sqrt");
jbnButtons[18] = new JButton("1/x");
jbnButtons[19] = new JButton("%");

jplBackSpace = new JPanel();
jplBackSpace.setLayout(new GridLayout(1, 1, 2, 2));

jbnButtons[20] = new JButton("Backspace");
jplBackSpace.add(jbnButtons[20]);

jplControl = new JPanel();
jplControl.setLayout(new GridLayout(1, 2, 2 ,2));

jbnButtons[21] = new JButton(" CE ");
jbnButtons[22] = new JButton("C");

jplControl.add(jbnButtons[21]);
jplControl.add(jbnButtons[22]);

// Setting all Numbered JButton's to Blue. The rest to Red
for (int i=0; i<10)
jbnButtons[i].setForeground(Color.blue);

else
jbnButtons[i].setForeground(Color.red);
}

// Set panel layout manager for a 4 by 5 grid
jplButtons.setLayout(new GridLayout(4, 5, 2, 2));

//Add buttons to keypad panel starting at top left
// First row
for(int i=7; i<=9; i++) {
jplButtons.add(jbnButtons[i]);
}

// add button / and sqrt
jplButtons.add(jbnButtons[13]);
jplButtons.add(jbnButtons[17]);

// Second row
for(int i=4; i<=6; i++)
{
jplButtons.add(jbnButtons[i]);
}

// add button * and x^2
jplButtons.add(jbnButtons[14]);
jplButtons.add(jbnButtons[18]);

// Third row
for( int i=1; i<=3; i++)
{
jplButtons.add(jbnButtons[i]);
}

//adds button - and %
jplButtons.add(jbnButtons[15]);
jplButtons.add(jbnButtons[19]);

//Fourth Row
// add 0, +/-, ., +, and =
jplButtons.add(jbnButtons[0]);
jplButtons.add(jbnButtons[10]);
jplButtons.add(jbnButtons[11]);
jplButtons.add(jbnButtons[16]);
jplButtons.add(jbnButtons[12]);

jplMaster.setLayout(new BorderLayout());
jplMaster.add(jplBackSpace, BorderLayout.WEST);
jplMaster.add(jplControl, BorderLayout.EAST);
jplMaster.add(jplButtons, BorderLayout.SOUTH);

// Add components to frame
getContentPane().add(jplMaster, BorderLayout.SOUTH);
requestFocus();

//activate ActionListener
for (int i=0; i< 1)
setDisplayString("0");
}
break;

case 21: // CE
clearExisting();
break;

case 22: // C
clearAll();
break;
}
}
}
}

void setDisplayString(String s){
jlbOutput.setText(s);
}

String getDisplayString (){
return jlbOutput.getText();
}

void addDigitToDisplay(int digit){
if (clearOnNextDigit)
setDisplayString("");

String inputString = getDisplayString();

if (inputString.indexOf("0") == 0){
inputString = inputString.substring(1);
}

if ((!inputString.equals("0") || digit > 0)
&& inputString.length() < MAX_INPUT_LENGTH){
setDisplayString(inputString + digit);
}


displayMode = INPUT_MODE;
clearOnNextDigit = false;
}

void addDecimalPoint(){
displayMode = INPUT_MODE;

if (clearOnNextDigit)
setDisplayString("");

String inputString = getDisplayString();

// If the input string already contains a decimal point, don't
// do anything to it.
if (inputString.indexOf(".") < 0)
setDisplayString(new String(inputString + "."));
}

void processSignChange(){
if (displayMode == INPUT_MODE)
{
String input = getDisplayString();

if (input.length() > 0 && !input.equals("0"))
{
if (input.indexOf("-") == 0)
setDisplayString(input.substring(1));

else
setDisplayString("-" + input);
}

}

else if (displayMode == RESULT_MODE)
{
double numberInDisplay = getNumberInDisplay();

if (numberInDisplay != 0)
displayResult(-numberInDisplay);
}
}

void clearAll() {
setDisplayString("0");
lastOperator = "0";
lastNumber = 0;
displayMode = INPUT_MODE;
clearOnNextDigit = true;
}

void clearExisting(){
setDisplayString("0");
clearOnNextDigit = true;
displayMode = INPUT_MODE;
}

double getNumberInDisplay() {
String input = jlbOutput.getText();
return Double.parseDouble(input);
}

void processOperator(String op) {
if (displayMode != ERROR_MODE)
{
double numberInDisplay = getNumberInDisplay();

if (!lastOperator.equals("0"))
{
try
{
double result = processLastOperator();
displayResult(result);
lastNumber = result;
}

catch (DivideByZeroException e)
{
}
}

else
{
lastNumber = numberInDisplay;
}

clearOnNextDigit = true;
lastOperator = op;
}
}

void processEquals(){
double result = 0;

if (displayMode != ERROR_MODE){
try
{
result = processLastOperator();
displayResult(result);
}

catch (DivideByZeroException e) {
displayError("Cannot divide by zero!");
}

lastOperator = "0";
}
}

double processLastOperator() throws DivideByZeroException {
double result = 0;
double numberInDisplay = getNumberInDisplay();

if (lastOperator.equals("/"))
{
if (numberInDisplay == 0)
throw (new DivideByZeroException());

result = lastNumber / numberInDisplay;
}

if (lastOperator.equals("*"))
result = lastNumber * numberInDisplay;

if (lastOperator.equals("-"))
result = lastNumber - numberInDisplay;

if (lastOperator.equals("+"))
result = lastNumber + numberInDisplay;

return result;
}

void displayResult(double result){
setDisplayString(Double.toString(result));
lastNumber = result;
displayMode = RESULT_MODE;
clearOnNextDigit = true;
}

void displayError(String errorMessage){
setDisplayString(errorMessage);
lastNumber = 0;
displayMode = ERROR_MODE;
clearOnNextDigit = true;
}

public static void main(String args[]) {
Calculator calci = new Calculator();
Container contentPane = calci.getContentPane();
// contentPane.setLayout(new BorderLayout());
calci.setTitle("Java Swing Calculator");
calci.setSize(241, 217);
calci.pack();
calci.setLocation(400, 250);
calci.setVisible(true);
calci.setResizable(false);
}

} //End of Swing Calculator Class.

class DivideByZeroException extends Exception{
public DivideByZeroException()
{
super();
}

public DivideByZeroException(String s)
{
super(s);
}
}

class CustomABOUTDialog extends JDialog implements ActionListener {
JButton jbnOk;

CustomABOUTDialog(JFrame parent, String title, boolean modal){
super(parent, title, modal);
setBackground(Color.black);

JPanel p1 = new JPanel(new FlowLayout(FlowLayout.CENTER));

StringBuffer text = new StringBuffer();
text.append("Calculator Information\n\n");
text.append("Developer: Hemanth\n");
text.append("Version: 1.0");

JTextArea jtAreaAbout = new JTextArea(5, 21);
jtAreaAbout.setText(text.toString());
jtAreaAbout.setFont(new Font("Times New Roman", 1, 13));
jtAreaAbout.setEditable(false);

p1.add(jtAreaAbout);
p1.setBackground(Color.red);
getContentPane().add(p1, BorderLayout.CENTER);

JPanel p2 = new JPanel(new FlowLayout(FlowLayout.CENTER));
jbnOk = new JButton(" OK ");
jbnOk.addActionListener(this);

p2.add(jbnOk);
getContentPane().add(p2, BorderLayout.SOUTH);

setLocation(408, 270);
setResizable(false);

addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e)
{
Window aboutDialog = e.getWindow();
aboutDialog.dispose();
}
}
);

pack();
}

public void actionPerformed(ActionEvent e)
{
if(e.getSource() == jbnOk) {
this.dispose();
}
}

}