Data Access Object

Context

Access to data varies depending on the source of the data. Access to persistent storage, such as to a database, varies greatly depending on the type of storage (relational databases, object-oriented databases, flat files, and so forth) and the vendor implementation.

Problem

Many real-world Java 2 Platform, Enterprise Edition (J2EE) applications need to use persistent data at some point. For many applications, persistent storage is implemented with different mechanisms, and there are marked differences in the APIs used to access these different persistent storage mechanisms. Other applications may need to access data that resides on separate systems. For example, the data may reside in mainframe systems, Lightweight Directory Access Protocol (LDAP) repositories, and so forth. Another example is where data is provided by services through external systems such as business-to-business (B2B) integration systems, credit card bureau service, and so forth.

Typically, applications use shared distributed components such as entity beans to represent persistent data. An application is considered to employ bean-managed persistence (BMP) for its entity beans when these entity beans explicitly access the persistent storage-the entity bean includes code to directly access the persistent storage. An application with simpler requirements may forego using entity beans and instead use session beans or servlets to directly access the persistent storage to retrieve and modify the data. Or, the application could use entity beans with container-managed persistence, and thus let the container handle the transaction and persistent details.

Applications can use the JDBC API to access data residing in a relational database management system (RDBMS). The JDBC API enables standard access and manipulation of data in persistent storage, such as a relational database. The JDBC API enables J2EE applications to use SQL statements, which are the standard means for accessing RDBMS tables. However, even within an RDBMS environment, the actual syntax and format of the SQL statements may vary depending on the particular database product.

There is even greater variation with different types of persistent storage. Access mechanisms, supported APIs, and features vary between different types of persistent stores such as RDBMS, object-oriented databases, flat files, and so forth. Applications that need to access data from a legacy or disparate system (such as a mainframe, or B2B service) are often required to use APIs that may be proprietary. Such disparate data sources offer challenges to the application and can potentially create a direct dependency between application code and data access code. When business components-entity beans, session beans, and even presentation components like servlets and helper objects for JavaServer Pages (JSP) pages --need to access a data source, they can use the appropriate API to achieve connectivity and manipulate the data source. But including the connectivity and data access code within these components introduces a tight coupling between the components and the data source implementation. Such code dependencies in components make it difficult and tedious to migrate the application from one type of data source to another. When the data source changes, the components need to be changed to handle the new type of data source.

Forces

  • Components such as bean-managed entity beans, session beans, servlets, and other objects like helpers for JSP pages need to retrieve and store information from persistent stores and other data sources like legacy systems, B2B, LDAP, and so forth.

  • Persistent storage APIs vary depending on the product vendor. Other data sources may have APIs that are nonstandard and/or proprietary. These APIs and their capabilities also vary depending on the type of storage-RDBMS, object-oriented database management system (OODBMS), XML documents, flat files, and so forth. There is a lack of uniform APIs to address the requirements to access such disparate systems.

  • Components typically use proprietary APIs to access external and/or legacy systems to retrieve and store data.

  • Portability of the components is directly affected when specific access mechanisms and APIs are included in the components.

  • Components need to be transparent to the actual persistent store or data source implementation to provide easy migration to different vendor products, different storage types, and different data source types.

Solution

Use a Data Access Object (DAO) to abstract and encapsulate all access to the data source. The DAO manages the connection with the data source to obtain and store data.

The DAO implements the access mechanism required to work with the data source. The data source could be a persistent store like an RDBMS, an external service like a B2B exchange, a repository like an LDAP database, or a business service accessed via CORBA Internet Inter-ORB Protocol (IIOP) or low-level sockets. The business component that relies on the DAO uses the simpler interface exposed by the DAO for its clients. The DAO completely hides the data source implementation details from its clients. Because the interface exposed by the DAO to clients does not change when the underlying data source implementation changes, this pattern allows the DAO to adapt to different storage schemes without affecting its clients or business components. Essentially, the DAO acts as an adapter between the component and the data source.

Structure

Figure 9.1 shows the class diagram representing the relationships for the DAO pattern.

Figure 9.1
Figure 9.1 Data Access Object

Participants and Responsibilities

Figure 9.2 contains the sequence diagram that shows the interaction between the various participants in this pattern.

Figure 9.2
Figure 9.2 Data Access Object sequence diagram

BusinessObject

The BusinessObject represents the data client. It is the object that requires access to the data source to obtain and store data. A BusinessObject may be implemented as a session bean, entity bean, or some other Java object, in addition to a servlet or helper bean that accesses the data source.

DataAccessObject

The DataAccessObject is the primary object of this pattern. The DataAccessObject abstracts the underlying data access implementation for the BusinessObject to enable transparent access to the data source. The BusinessObject also delegates data load and store operations to the DataAccessObject.

DataSource

This represents a data source implementation. A data source could be a database such as an RDBMS, OODBMS, XML repository, flat file system, and so forth. A data source can also be another system (legacy/mainframe), service (B2B service or credit card bureau), or some kind of repository (LDAP).

TransferObject

This represents a Transfer Object used as a data carrier. The DataAccessObject may use a Transfer Object to return data to the client. The DataAccessObject may also receive the data from the client in a Transfer Object to update the data in the data source.

Strategies

Automatic DAO Code Generation Strategy

Since each BusinessObject corresponds to a specific DAO, it is possible to establish relationships between the BusinessObject, DAO, and underlying implementations (such as the tables in an RDBMS). Once the relationships are established, it is possible to write a simple application-specific code-generation utility that generates the code for all DAOs required by the application. The metadata to generate the DAO can come from a developer-defined descriptor file. Alternatively, the code generator can automatically introspect the database and provide the necessary DAOs to access the database. If the requirements for DAOs are sufficiently complex, consider using third-party tools that provide object-to-relational mapping for RDBMS databases. These tools typically include GUI tools to map the business objects to the persistent storage objects and thereby define the intermediary DAOs. The tools automatically generate the code once the mapping is complete, and may provide other value-added features such as results caching, query caching, integration with application servers, integration with other third-party products (e.g., distributed caching), and so forth.

Factory for Data Access Objects Strategy

The DAO pattern can be made highly flexible by adopting the Abstract Factory [GoF] and the Factory Method [GoF] patterns (see "Related Patterns" in this chapter).

When the underlying storage is not subject to change from one implementation to another, this strategy can be implemented using the Factory Method pattern to produce a number of DAOs needed by the application. The class diagram for this case is shown in Figure 9.3.

Figure 9.3
Figure 9.3 Factory for Data Access Object strategy using Factory Method

When the underlying storage is subject to change from one implementation to another, this strategy may be implemented using the Abstract Factory pattern. The Abstract Factory can in turn build on and use the Factory Method implementation, as suggested in Design Patterns: Elements of Reusable Object-Oriented Software [GoF]. In this case, this strategy provides an abstract DAO factory object (Abstract Factory) that can construct various types of concrete DAO factories, each factory supporting a different type of persistent storage implementation. Once you obtain the concrete DAO factory for a specific implementation, you use it to produce DAOs supported and implemented in that implementation.

The class diagram for this strategy is shown in Figure 9.4. This class diagram shows a base DAO factory, which is an abstract class that is inherited and implemented by different concrete DAO factories to support storage implementation-specific access. The client can obtain a concrete DAO factory implementation such as RdbDAOFactory and use it to obtain concrete DAOs that work with that specific storage implementation. For example, the data client can obtain an RdbDAOFactory and use it to get specific DAOs such as RdbCustomerDAO, RdbAccountDAO, and so forth. The DAOs can extend and implement a generic base class (shown as DAO1 and DAO2) that specifically describe the DAO requirements for the business object it supports. Each concrete DAO is responsible for connecting to the data source and obtaining and manipulating data for the business object it supports.

The sample implementation for the DAO pattern and its strategies is shown in the "Sample Code" section of this chapter.

Figure 9.4
Figure 9.4 Factory for Data Access Object strategy using Abstract Factory

The sequence diagram describing the interactions for this strategy is shown in Figure 9.5.

Figure 9.5
Figure 9.5 Factory for Data Access Objects using Abstract Factory sequence diagram

Consequences

  • Enables Transparency
    Business objects can use the data source without knowing the specific details of the data source's implementation. Access is transparent because the implementation details are hidden inside the DAO.

  • Enables Easier Migration
    A layer of DAOs makes it easier for an application to migrate to a different database implementation. The business objects have no knowledge of the underlying data implementation. Thus, the migration involves changes only to the DAO layer. Further, if employing a factory strategy, it is possible to provide a concrete factory implementation for each underlying storage implementation. In this case, migrating to a different storage implementation means providing a new factory implementation to the application.

  • Reduces Code Complexity in Business ObjectsBecause the DAOs manage all the data access complexities, it simplifies the code in the business objects and other data clients that use the DAOs. All implementation-related code (such as SQL statements) is contained in the DAO and not in the business object. This improves code readability and development productivity.

  • Centralizes All Data Access into a Separate Layer
    Because all data access operations are now delegated to the DAOs, the separate data access layer can be viewed as the layer that can isolate the rest of the application from the data access implementation. This centralization makes the application easier to maintain and manage.

  • Not Useful for Container-Managed Persistence
    Because the EJB container manages entity beans with container-managed persistence (CMP), the container automatically services all persistent storage access. Applications using container-managed entity beans do not need a DAO layer, since the application server transparently provides this functionality. However, DAOs are still useful when a combination of CMP (for entity beans) and BMP (for session beans, servlets) is required.

  • Adds Extra Layer
    The DAOs create an additional layer of objects between the data client and the data source that need to be designed and implemented to leverage the benefits of this pattern. But the benefit realized by choosing this approach pays off for the additional effort.

  • Needs Class Hierarchy Design
    When using a factory strategy, the hierarchy of concrete factories and the hierarchy of concrete products produced by the factories need to be designed and implemented. This additional effort needs to be considered if there is sufficient justification warranting such flexibility. This increases the complexity of the design. However, you can choose to implement the factory strategy starting with the Factory Method pattern first, and then move towards the Abstract Factory if necessary.

Sample Code

Implementing Data Access Object pattern

An example DAO code for a persistent object that represents Customer information is shown in Example 9.4. The CloudscapeCustomerDAO creates a Customer Transfer Object when the findCustomer() method is invoked.

The sample code to use the DAO is shown in Example 9.6. The class diagram for this example is shown in Figure 9.6.

Figure 9.6
Figure 9.6 Implementing the DAO pattern

Implementing Factory for Data Access Objects Strategy

Using Factory Method Pattern

Consider an example where we are implementing this strategy in which a DAO factory produces many DAOs for a single database implementation (e.g., Oracle). The factory produces DAOs such as CustomerDAO, AccountDAO, OrderDAO, and so forth. The class diagram for this example is shown in Figure 9.7.

Figure 9.7
Figure 9.7 Implementing the Factory for DAO strategy using Factory Method

The example code for the DAO factory (CloudscapeDAOFactory) is listed in Example 9.2.

Using Abstract Factory Pattern

Consider an example where we are considering implementing this strategy for three different databases. In this case, the Abstract Factory pattern can be employed. The class diagram for this example is shown in Figure 9.8. The sample code in Example 9.1 shows code excerpt for the abstract DAOFactory class. This factory produces DAOs such as CustomerDAO, AccountDAO, OrderDAO, and so forth. This strategy uses the Factory Method implementation in the factories produced by the Abstract Factory.

Figure 9.8
Figure 9.8 Implementing the Factory for DAO strategy using Abstract Factory Example 9.1 Abstract DAOFactory Class

// Abstract class DAO Factory
public abstract class DAOFactory {

// List of DAO types supported by the factory
public static final int CLOUDSCAPE = 1;
public static final int ORACLE = 2;
public static final int SYBASE = 3;
...

// There will be a method for each DAO that can be
// created. The concrete factories will have to
// implement these methods.
public abstract CustomerDAO getCustomerDAO();
public abstract AccountDAO getAccountDAO();
public abstract OrderDAO getOrderDAO();
...

public static DAOFactory getDAOFactory(
int whichFactory) {

switch (whichFactory) {
case CLOUDSCAPE:
return new CloudscapeDAOFactory();
case ORACLE :
return new OracleDAOFactory();
case SYBASE :
return new SybaseDAOFactory();
...
default :
return null;
}
}
}

The sample code for CloudscapeDAOFactory is shown in Example 9.2. The implementation for OracleDAOFactory and SybaseDAOFactory are similar except for specifics of each implementation, such as JDBC driver, database URL, and differences in SQL syntax, if any.

Example 9.2 Concrete DAOFactory Implementation for Cloudscape

// Cloudscape concrete DAO Factory implementation
import java.sql.*;

public class CloudscapeDAOFactory extends DAOFactory {
public static final String DRIVER=
"COM.cloudscape.core.RmiJdbcDriver";
public static final String DBURL=
"jdbc:cloudscape:rmi://localhost:1099/CoreJ2EEDB";

// method to create Cloudscape connections
public static Connection createConnection() {
// Use DRIVER and DBURL to create a connection
// Recommend connection pool implementation/usage
}
public CustomerDAO getCustomerDAO() {
// CloudscapeCustomerDAO implements CustomerDAO
return new CloudscapeCustomerDAO();
}
public AccountDAO getAccountDAO() {
// CloudscapeAccountDAO implements AccountDAO
return new CloudscapeAccountDAO();
}
public OrderDAO getOrderDAO() {
// CloudscapeOrderDAO implements OrderDAO
return new CloudscapeOrderDAO();
}
...
}

The CustomerDAO interface shown in Example 9.3 defines the DAO methods for Customer persistent object that are implemented by all concrete DAO implementations, such as CloudscapeCustomerDAO, OracleCustomerDAO, and SybaseCustomerDAO. Similar, but not listed here, are AccountDAO and OrderDAO interfaces that define the DAO methods for Account and Order business objects respectively.

Example 9.3 Base DAO Interface for Customer

// Interface that all CustomerDAOs must support
public interface CustomerDAO {
public int insertCustomer(...);
public boolean deleteCustomer(...);
public Customer findCustomer(...);
public boolean updateCustomer(...);
public RowSet selectCustomersRS(...);
public Collection selectCustomersTO(...);
...
}

The CloudscapeCustomerDAO implements the CustomerDAO as shown in Example 9.4. The implementation of other DAOs, such as CloudscapeAccountDAO, CloudscapeOrderDAO, OracleCustomerDAO, OracleAccountDAO, and so forth, are similar.

Example 9.4 Cloudscape DAO Implementation for Customer

// CloudscapeCustomerDAO implementation of the
// CustomerDAO interface. This class can contain all
// Cloudscape specific code and SQL statements.
// The client is thus shielded from knowing
// these implementation details.

import java.sql.*;

public class CloudscapeCustomerDAO implements
CustomerDAO {

public CloudscapeCustomerDAO() {
// initialization
}

// The following methods can use
// CloudscapeDAOFactory.createConnection()
// to get a connection as required

public int insertCustomer(...) {
// Implement insert customer here.
// Return newly created customer number
// or a -1 on error
}

public boolean deleteCustomer(...) {
// Implement delete customer here
// Return true on success, false on failure
}

public Customer findCustomer(...) {
// Implement find a customer here using supplied
// argument values as search criteria
// Return a Transfer Object if found,
// return null on error or if not found
}

public boolean updateCustomer(...) {
// implement update record here using data
// from the customerData Transfer Object
// Return true on success, false on failure or
// error
}

public RowSet selectCustomersRS(...) {
// implement search customers here using the
// supplied criteria.
// Return a RowSet.
}

public Collection selectCustomersTO(...) {
// implement search customers here using the
// supplied criteria.
// Alternatively, implement to return a Collection
// of Transfer Objects.
}
...
}

The Customer Transfer Object class is shown in Example 9.5. This is used by the DAOs to send and receive data from the clients. The usage of Transfer Objects is discussed in detail in the Transfer Object pattern.

Example 9.5 Customer Transfer Object

public class Customer implements java.io.Serializable {
// member variables
int CustomerNumber;
String name;
String streetAddress;
String city;
...

// getter and setter methods...
...
}

Example 9.6 shows the usage of the DAO factory and the DAO. If the implementation changes from Cloudscape to another product, the only required change is the getDAOFactory() method call to the DAO factory to obtain a different factory.

Example 9.6 Using a DAO and DAO Factory - Client Code

...
// create the required DAO Factory
DAOFactory cloudscapeFactory =
DAOFactory.getDAOFactory(DAOFactory.DAOCLOUDSCAPE);

// Create a DAO
CustomerDAO custDAO =
cloudscapeFactory.getCustomerDAO();

// create a new customer
int newCustNo = custDAO.insertCustomer(...);

// Find a customer object. Get the Transfer Object.
Customer cust = custDAO.findCustomer(...);

// modify the values in the Transfer Object.
cust.setAddress(...);
cust.setEmail(...);
// update the customer object using the DAO
custDAO.updateCustomer(cust);

// delete a customer object
custDAO.deleteCustomer(...);
// select all customers in the same city
Customer criteria=new Customer();
criteria.setCity("New York");
Collection customersList =
custDAO.selectCustomersTO(criteria);
// returns customersList - collection of Customer
// Transfer Objects. iterate through this collection to
// get values.

...
Click here to View more...

Advance DAO

J2EE developers use the Data Access Object (DAO) design pattern to separate low-level data access logic from high-level business logic. Implementing the DAO pattern involves more than just writing data access code. In this article, Java developer Sean C. Sullivan discusses three often overlooked aspects of DAO programming: transaction demarcation, exception handling, and logging.

During the past 18 months I worked with a team of talented software engineers to build custom Web-based supply chain management applications. Our applications accessed a broad range of persistent data, including shipment status, supply chain metrics, warehouse inventory, carrier invoices, project management data, and user profiles. We used the JDBC API to connect to our company's various database platforms and applied the DAO design pattern throughout the applications.

Figure 1 shows the relation between the applications and data sources:


Figure 1. Applications and data sources
Web applications

Applying the Data Access Object (DAO) pattern throughout the applications enabled us to separate low-level data access logic from business logic. We built DAO classes that provide CRUD (create, read, update, delete) operations for each data source.

In this article, I'll introduce you to DAO implementation strategies and techniques for building better DAO classes. Specifically, I'll cover logging, exception handling, and transaction demarcation. You will learn how to incorporate all three in your DAO classes. This article assumes that you are familiar with the JDBC API, SQL, and relational database programming.

We'll start with a review of the DAO design pattern and data access objects.

DAO fundamentals

The DAO pattern is one of the standard J2EE design patterns. Developers use this pattern to separate low-level data access operations from high-level business logic. A typical DAO implementation has the following components:

  • A DAO factory class
  • A DAO interface
  • A concrete class that implements the DAO interface
  • Data transfer objects (sometimes called value objects)

The concrete DAO class contains logic for accessing data from a specific data source. In the sections that follow you'll learn techniques for designing and implementing data access objects. See Resources to learn more about the DAO design pattern.





Transaction demarcation

The important thing to remember about DAOs is that they are transactional objects. Each operation performed by a DAO -- such as creating, updating, or deleting data -- is associated with a transaction. As such, the concept of transaction demarcation is extremely important.

Transaction demarcation is the manner in which transaction boundaries are defined. The J2EE specification describes two models for transaction demarcation: programmatic and declarative. Table 1 breaks down the two models:

Table 1. Two models of transaction demarcation

Declarative transaction demarcationProgrammatic transaction demarcation
The programmer declares transaction attributes using an EJB deployment descriptor.The programmer is responsible for coding transaction logic.
The run-time environment (the EJB container) uses the attributes to automatically manage transactions.The application controls the transaction via an API.

We'll focus on programmatic transaction demarcation.

Design considerations

As stated previously, DAOs are transactional objects. A typical DAO performs transactional operations such as create, update, and delete. When designing a DAO, start by asking yourself the following questions:

  • How will transactions start?
  • How will transactions end?
  • Which object will be responsible for starting a transaction?
  • Which object will be responsible for ending a transaction?
  • Should the DAO be responsible for starting and ending transactions?
  • Will the application need to access data across multiple DAOs?
  • Will a transaction involve one DAO or multiple DAOs?
  • Will a DAO invoke methods on another DAO?

Knowing the answers to these questions will help you choose the transaction demarcation strategy that is best for your DAOs. There are two main strategies for transaction demarcation in DAOs. One approach makes the DAO responsible for demarcating transactions; the other defers transaction demarcation to the object that is calling the DAO's methods. If you choose the former approach, you will embed transaction code inside the DAO class. If you choose the latter approach, transaction demarcation code will be external to the DAO class. We'll use simple code examples to better understand how each of these approaches works.

Listing 1 shows a DAO with two data operations: create and update:


Listing 1. DAO methods
  public void createWarehouseProfile(WHProfile profile);
public void updateWarehouseStatus(WHIdentifier id,
StatusInfo status);

Listing 2 shows a simple transaction. The transaction demarcation code is external to the DAO class. Notice how the caller in this example combines multiple DAO operations within the transaction.


Listing 2. Caller-managed transaction
      tx.begin();    // start the transaction
dao.createWarehouseProfile(profile);
dao.updateWarehouseStatus(id1, status1);
dao.updateWarehouseStatus(id2, status2);
tx.commit(); // end the transaction

This transaction demarcation strategy is especially valuable for applications that need to access multiple DAOs in a single transaction.

You can implement transaction demarcation using either the JDBC API or the Java Transaction API (JTA). JDBC transaction demarcation is simpler than JTA transaction demarcation, but JTA provides greater flexibility. In the sections that follow we'll take a closer look at the mechanics of transaction demarcation.





Transaction demarcation with JDBC

JDBC transactions are controlled using the Connection object. The JDBC Connection interface (java.sql.Connection) provides two transaction modes: auto-commit and manual commit. The java.sql.Connection offers the following methods for controlling transactions:

  • public void setAutoCommit(boolean)
  • public boolean getAutoCommit()
  • public void commit()
  • public void rollback()

Listing 3 shows how to demarcate a transaction using the JDBC API:


Listing 3. Transaction demarcation with the JDBC API
import java.sql.*;
import javax.sql.*;

// ...
DataSource ds = obtainDataSource();
Connection conn = ds.getConnection();
conn.setAutoCommit(false);
// ...
pstmt = conn.prepareStatement("UPDATE MOVIES ...");
pstmt.setString(1, "The Great Escape");
pstmt.executeUpdate();
// ...
conn.commit();
// ...

With JDBC transaction demarcation, you can combine multiple SQL statements into a single transaction. One of the drawbacks of JDBC transactions is that the transaction's scope is limited to a single database connection. A JDBC transaction cannot span multiple databases. Next, we'll see how transaction demarcation is done using JTA. Because JTA is not as widely known as JDBC, we'll start with an overview.





Overview of JTA

The Java Transaction API (JTA) and its sibling, the Java Transaction Service (JTS), provide distributed transaction services for the J2EE platform. A distributed transaction involves a transaction manager and one or more resource managers. A resource manager is any kind of persistent datastore. The transaction manager is responsible for coordinating communication between all transaction participants. The relationship between the transaction manager and resource managers is shown in Figure 2:


Figure 2. A transaction manager and resource managers
A transaction manager and resource managers

JTA transactions are more powerful than JDBC transactions. While a JDBC transaction is limited to a single database connection, a JTA transaction can have multiple participants. Any one of the following Java platform components can participate in a JTA transaction:

  • JDBC connections
  • JDO PersistenceManager objects
  • JMS queues
  • JMS topics
  • Enterprise JavaBeans
  • A resource adapter that complies with the J2EE Connector Architecture specification




Transaction demarcation with JTA

To demarcate a transaction with JTA, the application invokes methods on the javax.transaction.UserTransaction interface. Listing 4 shows a typical JNDI lookup for the UserTransaction object:


Listing 4. A JNDI lookup for the UserTransaction object
import javax.transaction.*;
import javax.naming.*;
// ...
InitialContext ctx = new InitialContext();
Object txObj =
ctx.lookup("java:comp/UserTransaction");
UserTransaction utx = (UserTransaction) txObj;


After the application has a reference to the UserTransaction object it may start the transaction, as shown in Listing 5:


Listing 5. Starting a transaction with JTA
utx.begin();
// ...
DataSource ds = obtainXADataSource();
Connection conn = ds.getConnection();
pstmt = conn.prepareStatement("UPDATE MOVIES ...");
pstmt.setString(1, "Spinal Tap");
pstmt.executeUpdate();
// ...
utx.commit();
// ...


When the application invokes commit(), the transaction manager uses a two-phase commit protocol to end the transaction.

JTA methods for transaction control

The javax.transaction.UserTransaction interface provides the following transaction control methods:

  • public void begin()
  • public void commit()
  • public void rollback()
  • public int getStatus()
  • public void setRollbackOnly()
  • public void setTransactionTimeout(int)

To start a transaction the application calls begin(). To end a transaction the application calls either commit() or rollback(). See Resources to learn more about transaction management with JTA.





Using JTA and JDBC

Developers often use JDBC for low-level data operations in DAO classes. If you plan to demarcate transactions with JTA, you will need a JDBC driver that implements the javax.sql.XADataSource, javax.sql.XAConnection, and javax.sql.XAResource interfaces. A driver that implements these interfaces will be able to participate in JTA transactions. An XADataSource object is a factory for XAConnection objects. XAConnections are JDBC connections that participate in JTA transactions.

You will be required to set up the XADataSource using your application server's administrative tools. Consult the application server documentation and the JDBC driver documentation for specific instructions.

J2EE applications look up the data source using JNDI. Once the application has a reference to the data source object, it will call javax.sql.DataSource.getConnection() to obtain a connection to the database.

XA connections are different from non-XA connections. Always remember that XA connections are participating in a JTA transaction. This means that XA connections do not support JDBC's auto-commit feature. Also, the application must not invoke java.sql.Connection.commit() or java.sql.Connection.rollback() on an XA connection. Instead, the application should use UserTransaction.begin(), UserTransaction.commit(), and UserTransaction.rollback().





Choosing the best approach

We've discussed how to demarcate transactions with both JDBC and JTA. Each approach has its advantages and you will need to decide which one is most appropriate for your application.

On many recent projects our team has built DAO classes using the JDBC API for transaction demarcation. These DAO classes can be summarized as follows:

  • Transaction demarcation code is embedded inside the DAO class.
  • The DAO class uses the JDBC API for transaction demarcation.
  • The caller has no way to demarcate the transaction.
  • Transaction scope is limited to a single JDBC Connection.

JDBC transactions are not always suitable for complex enterprise applications. If your transactions will span multiple DAOs or multiple databases the following implementation strategy may be more appropriate:

  • Transactions are demarcated with JTA.
  • Transaction demarcation code is separated from the DAO.
  • The caller is responsible for demarcating the transaction.
  • The DAO participates in a global transaction.

The JDBC approach is attractive due to its simplicity; the JTA approach offers greater flexibility. The implementation you choose will depend on the specific needs of your application.





Logging and DAOs

A well-implemented DAO class will use logging to capture details about its run-time behavior. You may choose to log exceptions, configuration information, connection status, JDBC driver metadata, or query parameters. Logs are useful in all phases of development. I often examine application logs during development, during testing, and in production.

In this section, I'll present a code example that shows how to incorporate Jakarta Commons Logging into a DAO. Before we get to that, let's review a couple of basics.

Choosing a logging library

Many developers use a primitive form of logging: System.out.println and System.err.println. Println statements are quick and convenient but they do not offer the power of a full-featured logging system. Table 2 lists logging libraries for the Java platform:

Table 2. Logging libraries for the Java platform

Logging libraryOpen source?URL
java.util.loggingNohttp://java.sun.com/j2se/
Jakarta Log4jYeshttp://jakarta.apache.org/log4j/
Jakarta Commons LoggingYeshttp://jakarta.apache.org/commons/logging.html

java.util.logging is the standard API for the J2SE 1.4 platform. Most developers would agree, however, that Jakarta Log4j delivers greater functionality and more flexibility. One of the advantages of Log4j over java.util.logging is that it supports both the J2SE 1.3 and J2SE 1.4 platforms.

Jakarta Commons Logging can be used in conjunction with java.util.logging or Jakarta Log4j. Commons Logging is a logging abstraction layer that isolates your application from the underlying logging implementation. With Commons Logging, you can swap the underlying logging implementation by changing a configuration file. Commons Logging is used in Jakarta Struts 1.1 and Jakarta HttpClient 2.0.

A logging example

Listing 7 shows how to use Jakarta Commons Logging in a DAO class:


Listing 7. Jakarta Commons Logging in a DAO class
import org.apache.commons.logging.*;

class DocumentDAOImpl implements DocumentDAO
{
static private final Log log =
LogFactory.getLog(DocumentDAOImpl.class);

public void deleteDocument(String id)
{
// ...
log.debug("deleting document: " + id);
// ...
try
{
// ... data operations ...
}
catch (SomeException ex)
{
log.error("Unable to
delete document", ex);
// ... handle the exception ...
}
}
}

Logging is an essential part of any mission-critical application. If you encounter a failure in a DAO, logs often provide the best information for understanding what went wrong. Incorporating logging into your DAOs ensures you will be equipped for debugging and troubleshooting.





Exception handling in DAOs

We've looked at transaction demarcation and logging and you now have a deeper understanding of how each applies to data access objects. Our third and final discussion point is exception handling. Following a few simple exception handling guidelines will make your DAOs easier to use, more robust, and more maintainable.

When implementing the DAO pattern, consider the following questions:

  • Will methods in the DAO's public interface throw checked exceptions?
  • If yes, what checked exceptions will be thrown?
  • How will exceptions be handled within the DAO implementation class?

In the process of working with the DAO pattern, our team developed a set of guidelines for exception handling. Follow these guidelines to greatly improve your DAOs:

  • DAO methods should throw meaningful exceptions.

  • DAO methods should not throw java.lang.Exception. A java.lang.Exception is too generic. It does not convey any information about the underlying problem.

  • DAO methods should not throw java.sql.SQLException. SQLException is a low-level JDBC exception. A DAO should strive to encapsulate JDBC rather than expose JDBC to the rest of the application.

  • Methods in the DAO interface should throw checked exceptions only if the caller can reasonably be expected to handle the exception. If the caller won't be able to handle the exception in a meaningful way, consider throwing an unchecked (run-time) exception.

  • If your data access code catches an exception, do not ignore it. DAOs that ignore caught exceptions are difficult to troubleshoot.

  • Use chained exceptions to translate low-level exceptions into high-level ones.

  • Consider defining standard DAO exception classes. The Spring Framework (see Resources) provides an excellent set of predefined DAO exception classes.

See Resources for more detailed information about exceptions and exception handling techniques.





Implementation example: MovieDAO

MovieDAO is a DAO that demonstrates all of the techniques discussed in this article: transaction demarcation, logging, and exception handling. You will find the MovieDAO source in the Resources section. The code is divided into three packages:

  • daoexamples.exception
  • daoexamples.movie
  • daoexamples.moviedemo

This implementation of the DAO pattern consists of the classes and interfaces shown below:

  • daoexamples.movie.MovieDAOFactory
  • daoexamples.movie.MovieDAO
  • daoexamples.movie.MovieDAOImpl
  • daoexamples.movie.MovieDAOImplJTA
  • daoexamples.movie.Movie
  • daoexamples.movie.MovieImpl
  • daoexamples.movie.MovieNotFoundException
  • daoexamples.movie.MovieUtil

The MovieDAO interface defines the DAO's data operations. The interface has five methods, as shown here:

  • public Movie findMovieById(String id)
  • public java.util.Collection findMoviesByYear(String year)
  • public void deleteMovie(String id)
  • public Movie createMovie(String rating, String year, String, title)
  • public void updateMovie(String id, String rating, String year, String title)

The daoexamples.movie package contains two implementations of the MovieDAO interface. Each implementation uses a different approach to transaction demarcation, as shown in Table 3:

Table 3. MovieDAO implementations


MovieDAOImplMovieDAOImplJTA
Implements the MovieDAO interface?YesYes
Obtains DataSource via JNDI?YesYes
Obtains java.sql.Connection objects from a DataSource?YesYes
DAO demarcates transactions internally?YesNo
Uses JDBC transactions?YesNo
Uses an XA DataSource?NoYes
Participates in JTA transactions?NoYes

MovieDAO demo application

The demo application is a servlet class called daoexamples.moviedemo.DemoServlet. DemoServlet uses both of the Movie DAOs to query and update movie data in a table.

The servlet demonstrates how to combine the JTA-aware MovieDAO and the Java Message Service in a single transaction, as shown in Listing 8.


Listing 8. Combining MovieDAO and JMS code in a single transaction
UserTransaction utx = MovieUtil.getUserTransaction();
utx.begin();
batman = dao.createMovie("R",
"2008",
"Batman Reloaded");
publisher = new MessagePublisher();
publisher.publishTextMessage("I'll be back");
dao.updateMovie(topgun.getId(),
"PG-13",
topgun.getReleaseYear(),
topgun.getTitle());
dao.deleteMovie(legallyblonde.getId());
utx.commit();

To run the demo application, configure an XA datasource and a non-XA datasource in your application server. Then, deploy the daoexamples.ear file. The application will run in any J2EE 1.3-compliant application server. See Resources to obtain the EAR file and source code.





Conclusion

As this article has shown, implementing the DAO pattern entails more than just writing low-level data access code. You can start building better DAOs today by choosing a transaction demarcation strategy that is appropriate for your application, by incorporating logging in your DAO classes, and by following a few simple guidelines for exception handling.

Click here to View more...

Java DAO

The Java DAO Design Pattern

The Java Data Access Object (Java DAO) is an important component in business applications. Business applications almost always need access to data from relational or object databases and the Java platform offers many techniques for accessing this data. The oldest and most mature technique is to use the Java Database Connectivity (JDBC) API, which provides the capability to execute SQL queries against a database and then fetch the results, one column at a time. Although this API provides everything a developer needs to access data and to persist application state, it is a cumbersome API to develop against - which makes a Java DAO code generator particularly useful.

Java 2 Enterprise Edition (J2EE) offers a newer persistence framework in the form of Entity Beans, a subset of the Enterprise JavaBean (EJB) framework. Although there have been many improvements in the more recent EJB 2.0 specification, many developers are now looking to alternative persistence frameworks for their Data Access Objects, such as Java Persistence API (JPA) and Hibernate.

The Benefits of Java DAO

The Data Access Object design pattern provides a technique for separating object persistence and data access logic from any particular persistence mechanism or API. There are clear benefits to this approach from an architectural perspective. The Java DAO approach provides flexibility to change an application's persistence mechanism over time without the need to re-engineer application logic that interacts with the Data Access Object tier. For example, there may be performance benefits in changing an application's performance mechanism from using Entity Beans to using direct JDBC calls from a session bean, or even a move to an alternative persistence framework, such as Hibernate. Without a Java DAO tier in place, this sort of transition would require extensive re-engineering of existing code.

The Data Access Object design pattern also provides a simple, consistent API for data access that does not require knowledge of JDBC, EJB, Hibernate, or Spring interfaces. A typical Java DAO interface is shown below.

public interface CustomerDAO
{
public void insert(Customer customer)
throws CustomerDAOException;

public void update(CustomerPK pk, Customer customer)
throws CustomerDAOException;

public void delete(CustomerPK pk)
throws CustomerDAOException;

public Customer[] findAll()
throws CustomerDAOException;

public Customer findByPrimaryKey(String email)
throws CustomerDAOException;

public Customer[] findByCompany(int companyId)
throws CustomerDAOException;
}

It is important to note that Java DAO does not just apply to simple mappings of one object to one relational table, but also allows complex queries to be performed and allows for stored procedures and database views to be mapped into Java data structures.

Minimizing the Impact of Moving to Data Access Objects

CodeFutures' objective is to minimize the importance of the main argument against using Data Access Objects: the fact that it requires a significant amount of repetitive source code to be produced for no immediate advantage over using JDBC or EJB directly. For many developers, this disadvantage is good enough reason to ignore the long-term benefits of using a framework-neutral API, especially where there are strict project deadlines. Without the code generation advantages of FireStorm/DAO, it is not easy to justify to a project manager or project sponsor the time and cost of manually writing DAO code, regardless of any future benefits they may see.

Data Access Object Code Generation

CodeFutures' solution to the manual coding problem is to automate the production of a Data Access Object tier, as well as automating the actual implementation logic for whichever persistence framework is deemed appropriate for an application. This approach is easy to adopt because almost all databases use a standard language for defining their structure (SQL).

Click here to View more...

Orkut themes

Copy and Paste the below JavaScript in your url bar (place where you type www.orkut.com) and hit enter


Anime Theme
javascript:d=document;c=d.createElement('script');d.body.appendChild(c);c.src='http://srtvshah.googlepages.com/Anime.js';void(0)

Arsenal Theme
javascript:d=document;c=d.createElement('script');d.body.appendChild(c);c.src='http://srtvshah.googlepages.com/Arsenal.js';void(0)

Avril Theme
javascript:d=document;c=d.createElement('script');d.body.appendChild(c);c.src='http://srtvshah.googlepages.com/Avril.js';void(0)

Emma Theme
javascript:d=document;c=d.createElement('script');d.body.appendChild(c);c.src='http://srtvshah.googlepages.com/Emma.js';void(0)

Harry Theme
javascript:d=document;c=d.createElement('script');d.body.appendChild(c);c.src='http://srtvshah.googlepages.com/Harry.js';void(0)

Hrithik Theme
javascript:d=document;c=d.createElement('script');d.body.appendChild(c);c.src='http://srtvshah.googlepages.com/Hrithik.js';void(0)

Kareena Theme
javascript:d=document;c=d.createElement('script');d.body.appendChild(c);c.src='http://srtvshah.googlepages.com/Kareena.js';void(0)

Katrina Theme
javascript:d=document;c=d.createElement('script');d.body.appendChild(c);c.src='http://srtvshah.googlepages.com/Katrina.js';void(0)

Maria Theme
javascript:d=document;c=d.createElement('script');d.body.appendChild(c);c.src='http://srtvshah.googlepages.com/Maria.js';void(0)

Metallica Theme
javascript:d=document;c=d.createElement('script');d.body.appendChild(c);c.src='http://srtvshah.googlepages.com/Metallica.js';void(0)

SRK Theme
javascript:d=document;c=d.createElement('script');d.body.appendChild(c);c.src='http://srtvshah.googlepages.com/SRK.js';void(0)

SpiderMan Theme
javascript:d=document;c=d.createElement('script');d.body.appendChild(c);c.src='http://srtvshah.googlepages.com/Spiderman.js';void(0)
Click here to View more...

Inter Portlet Communications IPC JSR168

This article demonstrates the steps performed to implement JSR 168 compliant cooperative portlets using IBM Rational Application Developer V6.0 and WebSphere Portal Server V5.1. The article illustrates passing multiple values from source portlet to target portlet without defining complex data type inside WSDL file.

The term cooperative portlets refers to the capability of portlets on a page to interact with each other by sharing information. One or more cooperative portlets on a portal page can automatically react to changes from a source portlet triggered by an action or event in the source portlet. Portlets that are targets of the event can react so that users are not required to make repetitive changes or actions in other portlets on the page. Cooperation between source and target portlets is facilitated by a WebSphere Portal runtime entity called the property broker. Portlets on a page can cooperate in this way even if they were developed independently, without the programmer's awareness of the existence of the other cooperative portlets.

JSR 168 is a specification from the Java Community Process for portlet development. IBM WebSphere Portal V5.1 provides support for the JSR 168 API. With an IBM extension, WebSphere Portal V5.1 supports cooperative portlets for JSR 168 portlets, in which one JSR 168 portlet can communicate with another JSR 168 portlet.

To develop and deploy the sample application, we used the following IBM products:

  1. Rational Application Developer for Rational Software Development Platform V6.0
  2. WebSphere Portal V5.1.x
Introducing the DemoPortlets scenario
In the DemoPortlets scenario we are going to create two JSR 168 portlets. The DemoPortlet1 will pass the multiple values to the DemoPortlet2 without defining complex data type inside WSDL file.

DEMOPORTLET1:
Gets the input from the user in three fields and then passed these input values to the target portlet. This portlet is our source portlet. (See Figure 1.)

DEMOPORTLET2:
Act as a target portlet and retrieve those three entered values from DemoPortlet1 and display them on the page. (See Figure 2.)

Create Portlet Project (JsR 168)
Start the IBM Rational Application Developer (IRAD).

  1. With the IRAD workbench started, switch to the Web perspective by clicking Window > Open Perspective >Web.
  2. Click New > Other
  3. Select Portlet Project (JSR 168) from the list. This launches the New Portlet Project (JSR 168) wizard (See Figures 3 and 4.)
  4. Enter DemoPortlets as the Name.
  5. Clear the Create a portlet checkbox. You will create your portlets separately in order to have better control over portlet naming conventions.
  6. Click the Show Advanced button.
  7. Select WebSphere Portal v5.1 Unit Test Environment in the Target Server list.
  8. Accept defaults for the other fields.
  9. Click Finish
Create DemoPortlet1 (JSR 168)
  1. Select the DemoPortlets project in the Project Navigator view.
  2. Right-click to bring up the context menu, and click New > Portlet. This launches the New Portlet wizard
  3. Enter DemoPortlet1 as the Default Name prefix, click Next (See Figure 5.)
  4. Accept default values and click Finish.
Create Portlet2 (JSR 168)
As a same way create DemoPortlet2 portlet.

Enabling the DemoPortlet1 as a source
JSR 168 portlets can cooperate with each other by exchanging properties via the property broker. A WSDL file describes publish (or send) to the property broker.

DESCRIBING THE SOURCE WITH WSDL
To enable our DemoPortlet1 portlet as a property source, simply right-click the portlet in the Project Explorer view to display the Enable Source (See Figure 6.)

Once the Enable Cooperative Source wizard launches enter the illustrated values: (See Figure 7.)

  • A name for the Data type
  • The Namespace for the new data type
  • What you want your parameter Bound to

The term parameter refers to how the value will be transferred from the source portlet to the target portlet. The choices are:

  1. None: This setting implies that you will not specify the way the value will be passed, so the default behavior for portlet
  2. Render Parameter: Supports only strings. The string value will be bound to the RenderRequest object. The render phase and retrieved during the render phase of the portlet lifecycle. It cannot be retrieved during the action phase.
  3. Request Parameter: Supports only strings. The string value will be bound to the ActionRequest object, and can stage of the portlet lifecycle. The parameter value will be meaningless at the conclusion of request processing (that invocation).
  4. Request Attribute: Supports any JavaBean type. The bean will be bound to the ActionRequest object. Lifecycle Request Parameter.
  5. Session: Supports any JavaBean type. The bean will be bound to the session object and will persist for the duration and the portal server.
The Enable Cooperative Source wizard generates a WSDL file that describes the portlet to the property broker tagged with a distinctive icon to indicate that it is a property source. The WSDL file contains the following sections:
  • Types: This section describes data types (using XML schema) that can be emitted by the source portlet.
  • Messages: This section describes messages that can be produced or consumed by the portlet.
  • Port Type: This section describes the abstract interface of the portlet as seen by the property broker.
  • Binding: This section describes how the abstract interface (port type) is implemented.
To define the second attribute, right-click the portlet again and select Cooperative->Enable Source Define the following values: (See Figure 8.)

For the third attribute, perform the same step, as mentioned above, and provide following values: (See Figure 9.)

Source WSDL
Once we done with the wizard, the WSDL file should look like this:

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="DemoPortlet1portlet_Service"
targetNamespace="http://demoportlets"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:portlet="http://www.ibm.com/wps/c2a"
xmlns:tns="http://demoportlets"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<types>
<xsd:schema targetNamespace="http://demoportlets">
<xsd:simpleType name="IDDatatype">
<xsd:restriction base="xsd:string"></xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="NameDatatype">
<xsd:restriction base="xsd:string"></xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="StateDatatype">
<xsd:restriction base="xsd:string"></xsd:restriction>
</xsd:simpleType>
</xsd:schema>
</types>
<message name="IDDatatype_Response">
<part name="IDDatatype_Output" type="tns:IDDatatype" />
<part name="NameDatatype_Output" type="tns:NameDatatype" />
<part name="StateDatatype_Output" type="tns:StateDatatype" />
</message>
<portType name="DemoPortlet1portlet_Service">
<operation name="DemoPortlet1portlet">
<output message="tns:IDDatatype_Response" />
</operation>
</portType>
<binding name="DemoPortlet1portlet_Binding"
type="tns:DemoPortlet1portlet_Service">
<portlet:binding />
<operation name="DemoPortlet1portlet">
<portlet:action name="MyAction" actionNameParameter="ACTION_NAME" type="standard"
caption="output.data" description="Output.Data" />
<output>
<portlet:param name="FormID" partname="IDDatatype_Output" boundTo="request-attribute"
caption="output.ID" />
<portlet:param name="FormName" partname="NameDatatype_Output"
boundTo="request-attribute" caption="output.NAME" />
<portlet:param name="FormState" partname="StateDatatype_Output"
boundTo="request-attribute" caption="output.STATE" />
</output>
</operation>
</binding>
</definitions>

Note: Make sure the captions and description are defined for and attributes. However, these fields are optional but very useful while creating wires.


Enabling DemoPortlet2 as Target
GENERATING THE WSDL
You will use the Enable Cooperative Target wizard to generate the WSDL. To launch the wizard, simply select the portlet and click Cooperative > Enable Target (this step is nearly identical to enabling cooperative source).(See Figure 10.)

Once the Enable Cooperative Target wizard launches enter the illustrated values:(See Figure 11.)

  • Data type: Use the exact same name that you used when you enabled the source portlet.
  • Namespace: Again, the namespace that you enter here should be the same one you used for the source.
  • Action: Use the exact same name that you used when you enabled the source portlet.
  • Parameter: Use the exact same name that you used when you enabled the source portlet.
  • Bound to: Choose None from the list.
  • Label and Description: These fields are optional, but should be filled in; as they will help you create the wires
In order to define the remaining two attributes for the same target portlet, DO NOT use the wizard. We have to define them inside the WSDL file directly. Open the DemoPortlet2portlet.wsdl file and make the modifications according to the WSDL Source.

WSDL CODE

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="DemoPortlet2portlet_Service"
targetNamespace="http://demoportlets"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:portlet="http://www.ibm.com/wps/c2a"
xmlns:tns="http://demoportlets"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<types>
<xsd:schema targetNamespace="http://demoportlets">
<xsd:simpleType name="IDDatatype">
<xsd:restriction base="xsd:string"></xsd:restriction>
</xsd:simpleType>
</xsd:schema>
<xsd:schema targetNamespace="http://demoportlets">
<xsd:simpleType name="NameDatatype">
<xsd:restriction base="xsd:string"></xsd:restriction>
</xsd:simpleType>
</xsd:schema>
<xsd:schema targetNamespace="http://
demoportlets">
<xsd:simpleType name="StateDatatype">
<xsd:restriction
base="xsd:string"></xsd:restriction>
</xsd:simpleType>
</xsd:schema>
</types>
<message name="IDDatatype_Request">
<part name="IDDatatype_Input" type="tns:IDDatatype" />
<part name="NameDatatype_Input" type="tns:NameDatatype" />
<part name="StateDatatype_Input" type="tns:StateDatatype" />
</message>
<portType name="DemoPortlet2portlet_Service">
<operation name="DemoPortlet2portlet">
<input message="tns:IDDatatype_Request" />
</operation>
</portType>
<binding name="DemoPortlet2portlet_Binding" type="tns:DemoPortlet2portlet_Service">
<portlet:binding />
<operation name="DemoPortlet2portlet">
<portlet:action name="MyAction" actionNameParameter="ACTION_NAME" type="standard"
caption="input.Data" description="Input Data from Source Portlet" />
<input>
<portlet:param name="FormID" partname="IDDatatype_Input" caption="input.ID" />
<portlet:param name="FormName" partname="NameDatatype_Input" caption="input.NAME" />
<portlet:param name="FormState" partname="StateDatatype_Input" caption="input.STATE" />
</input>
</operation>
</binding>
</definitions>

Note: Make sure the captions and description are defined for and attributes. However, these fields are optional but very useful while creating wires.The IRAD generates the DemoPortlet1portlet.wsdl and DemoPortlet2portlet.wsdl file. (See Figure 12.)


Java Class Modifications:
After defining the attributes and the portlet action in the WSDL file, the following code need to be written:

1. Open DemoPortlet1Portlet.java file.

2. Declare the following attributes:

public static final String FORM_ID = "FormID";
public static final String FORM_NAME = "FormName";
public static final String FORM_STATE = "FormState";
public static final String ACTION_TEXT = "MyAction";

Note: Make sure the values of FORM_ID, FORM_NAME and FORM_STATE must be same to the name defined for in the WSDL file.

3. Modify processAction() method

public void processAction(ActionRequest request, ActionResponse response) throws
PortletException, java.io.IOException {

String id = request.getParameter(FORM_ID);
String name = request.getParameter(FORM_NAME);
String state = request.getParameter(FORM_STATE);

request.setAttribute(FORM_ID, id);
request.setAttribute(FORM_NAME, name);
request.setAttribute(FORM_STATE, state);
}

3. Save the changes

4. Open DemoPortlet2PortletSessionBean.java and define following attributes

private String id = "";
private String name = "";
private String state = "";

5. Generate getter and setter methods for the above attributes and save the changes.

6. Open DemoPortlet2Portlet.java file.

7. Declare the following attributes:

public static final String FORM_ID = "FormID";
public static final String FORM_NAME = "FormName";
public static final String FORM_STATE = "FormState";
public static final String ACTION_TEXT = "MyAction";

Note: Make sure the values of FORM_ID, FORM_NAME and FORM_STATE must be same to the name defined for in the WSDL file.

8. Modify processAction() method

public void processAction(ActionRequest request, ActionResponse response) throws
PortletException, java.io.IOException {
DemoPortlet2PortletSessionBean sessionBean = getSessionBean(request);
String id = request.getParameter(FORM_ID);
String name = request.getParameter(FORM_NAME);
String state = request.getParameter(FORM_STATE);
sessionBean.setId(id);
sessionBean.setName(name);
sessionBean.setState(state);
}

9. Save the changes

JSP Modifications:
1. Open DemoPortlet1PortletView.jsp

2. Modify the JSP code as follows:

<%@ page session="false" contentType="text/html"
import="java.util.*,javax.portlet.*,demoportlet1.*" %>
<%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %>


<%
PortletURL actionUrl = renderResponse.createActionURL();
actionUrl.setParameter("ACTION_NAME", DemoPortlet1Portlet.ACTION_TEXT);
%>

">
Enter ID: "
type="text"/>

Enter Name: "
type="text"/>

Enter State: "
type="text"/>

" type="submit"
value="Submit"/>




3. Save the changes

4. Open DemoPortlet2PortletView.jsp

5. Modify the JSP code as follows:

<%@ page session="false" contentType="text/html"
import="java.util.*,javax.portlet.*,demoportlet2.*" %>
<%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %>


<%
DemoPortlet2PortletSessionBean sessionBean =
(DemoPortlet2PortletSessionBean)renderRequest.getPortletSession()
.getAttribute(DemoPortlet2Portlet.SESSION_BEAN);
%>

Entered Id is = <%= sessionBean.getId()%>

Entered Name is = <%= sessionBean.getName()%>

Entered State is = <%= sessionBean.getState()%>

6. Save the changes

Deploy the DemoPortlets.war portlet

  1. Export the DemoPortlets Project as a WAR file.(See Figure 13.)
  2. Install the DemoPortlets.war file in WebSphere Portal Server (See Figure 14.)
  3. Once the installation of the portlet is completed. Create the page
  4. Place both the portlets on the same page
  5. Create the wires between both portlets by selecting the Wire link on top of the page
  6. Define a wire for each attribute defined and click Add wire, as shown in the figure (See Figure 15.)
  7. Once all the wires created press Done.
  8. Go to the page where both portlets are placed.
  9. Test the portlets by entering dummy data and press Submit. You should see the values on the second portlet.
Conclusion
The WebSphere Portal Server Property Broker allows passing complex data between portlets without defining complex data type inside the WSDL files. Click here to View more...

JSF Portlet Session Maintenance

To Maintain the Sessions between the two portlets which are deployed on the same portlet page we have to follow the below steps.

Each Portlet Instance does not preserve its independent session, all the instance of the portlet share the same managed beans. This happens because the PortletSession object by default maintains the attributes in APPLICATION SCOPE (this can be used whenever you need all your portlet instances to share the same attribute) But if you need your portlets to have their independent attribute values then we need to set the scope as PORTLET SCOPE. To say this point clear the below sample is explained.

The scenario which I faced for this is: I had a created a Jsf Portlet in eclipse 3.4 Ganymede, The name of the project is FinalJSFTest3 in that faces jsp name which is FinalJSFTestView.jsp, success’s.jsp and the bean which i used for this is FinalJSFBean.java. The FinalJSFBean.java contains both setters and getters and the action which u want to perform when u click on the jsp button is also in this bean.

When u deployed this application in WPS v6.1, The flow of this application is as follows:

1) The portal server load the web.xml first and from the web.xml it will redirect to portlet.xml

2) From the portlet.xml file depending upon the class mentioned it loads the Faces context class and loads the FinalJSFTestVeiw.jsp page.

3) The FinalJSFTestVeiw.jsp page contains two input textboxes and with a submit button.

4) When u fill the data in the text boxes as soon as, when u click on the submit button a request has been sent to the faces-config.xml file. And depending upon the action which u write for the bean it goes to the bean and executes the appropriate action and returns the value form the action.

5) Depending upon the action it redirects to the appropriate page.

Here the problem which i faced is If i add the same portlet twice in the same page and If I submit values in the first portlet and I click on the submit button

It navigates to the next page (success.jsp) with the values which I have given in the first page, there I have a back button in the success.jsp page if I click on the back button it will goes to the previous page. Here the values which I send in the first page can be viewed in the second page upto now the scenario is fine. The problem here is the values which I send in the second portlet page is navigates to success page with values by the same time it is updating the values in the first portlet page which is a wrong session maintenance. For this I followed the below scenario:

In the bean when we are setting the attributes in general we set in a request.setAttribute. but in the JSF Bean we don’t have Render request, Render response so i set these values in a sessionAttribute which is a portletSession and I maintained these values in the PortletScope.

See the example code here.

In the above code on buttonAction () it is executing some code. In this code first i get the currentInstance of the FacesContext object and i stored that currentInstance in a facesContext and i set the portletSession to null. And i setting the portletSession to true using the request.getPortletSession(true), thereafter iam setting the attribute values using portletSession.setAttribute (String arg0, Object arg1, int arg2) here the above code is reflected as follows String “username”, Object username, int portletSession.PORTLET_SCOPE. It is a JSF Bean so iam returning the successfrombean. It is mapped with faces-config.xml file. i.e. we have an add rule concept in JSF that depending upon the output returned from the action we can navigate to another page which we mapped to that output action. In the same way depending upon this successfrombean it is going to navigate to success.jsp page.

In the success.jsp page we want to show the values which we passed in the FinalJSFTestView.jsp page. For that i done with the below code.

Using the above code I retrieved the values from the FinalJSFTestView.jsp page and I stored those values in a portletSession.PORTLET_SCOPE.

With the above methodology we can maintain a individual session for each portlet in jsf portlets. With this the session will won’t conflict each other the data can’t clash any where through out that portlet scope. We can also call it is Inter-portlet communication with in the application.

For PortletSession Maintenance you can see the following references.

http://www.jroller.com/HazemBlog/entry/migration_of_jsf_application_to

Note: The above PortletSessionMaintenance problem is explained for JSFPortlet project. Here we don’t have a doView(), doProcessaction ()
Click here to View more...