Saturday, February 21, 2009

Catch All exception page for a JSF web application

If your application wants to display a generic error page if an internal exception occurs in your web application then all you have to do is register an action listener in your faces config, under the application as follows

<faces-config>
<application>
<default-render-kit-id>oracle.adf.core</default-render-kit-id>
<action-listener>
view.faces.GlobalActionListener
</action-listener>
</application>
<navigation-rule>
<navigation-case>
<from-outcome>exceptionNavigation</from-outcome>
<to-view-id>/global_exception.html</to-view-id>
<redirect>
</redirect>
</navigation-case>
</navigation-rule>
</faces-config>



Once you have configured your faces config with the action listener you create your java class called GlobalActionListener



import com.sun.faces.application.ActionListenerImpl;
import javax.faces.application.Application;
import javax.faces.application.NavigationHandler;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.ActionListener;
import javax.servlet.http.HttpSession;

public class GlobalActionListener extends ActionListenerImpl implements ActionListener{
public GlobalActionListener() {
super();
}
public void processAction(ActionEvent event){
try{
super.processAction(event);
}catch(Throwable exception){
//This part of the code is reached if any of your pages throw an exception and if it is not handled
FacesContext fc = FacesContext.getCurrentInstance();
Application app = fc.getApplication();
// goto this error page
NavigationHandler nhandler = app.getNavigationHandler();
nhandler.handleNavigation(fc, null, "exceptionNavigation");
// invalidate the session
ExternalContext ectx = FacesContext.getCurrentInstance().getExternalContext();
HttpSession session = (HttpSession)ectx.getSession(false);
session.invalidate();
fc.renderResponse();
}
}
}

Our GlobalActionListener implements the interface ActionListener and implements processAction method. It also extends the default Implementation from sun's class ActionListenerImpl. All that we have to do is call the base class's process Action and if an exception is throw catch that and redirect it to an exception page. In addition to redirecting to the exception page we also invalidate the http session.

The NavigationHandler class navigates to the exception page defined in faces config.

Tuesday, February 17, 2009

Using Client Acknowledge mode to expose a JMS topic as a Web service

A JMS session has three acknowledge modes AUTO, CLIENT and DUPS_OK, messages are removed from the JMS destination (Queue or Topic) only when the session has acknowledged that the client has received the message. In AUTO acknowledge mode the message is acknowledged as soon as the receive method has been completed. In DUPS_OK acknowledge the message is acknowledged lazily which means the message could be sitting in the destination for some time before the broker removes it at its will. In CLIENT acknowledge mode the client after receiving the message acknowledges it by calling its acknowledge method.This mode is key when you want to expose your JMS destination as a web service.

The one problem that needs to be solved when exposing a JMS destination as a web service is reliability. How do we make sure that the web service client has successfully received the message. In other words how do we support distributed transaction. The following example demonstrates this.

Target is to expose a JMS topic called yahoonews as web service.

Step1. Create a durable subscriber with CLIENT acknowledge mode

public Class DurableSubscriber{
Context jndiContext = null;
TopicConnectionFactory topicConnectionFactory = null;
TopicConnection topicConnection = null;
TopicSession topicSession = null;
BasicTopic topic = null;
TopicSubscriber topicSubscriber = null;

public DurableSubscriber(){
try {
topicConnectionFactory = new com.sun.messaging.TopicConnectionFactory();
topicConnectionFactory.setProperty("imqBrokerHostName",brokerHost);
topicConnectionFactory.setProperty("imqBrokerHostPort",brokerPort);

topicConnection = (com.sun.messaging.jms.TopicConnection)
topicConnectionFactory.createTopicConnection();
topicConnection.setClientID("yahoouserid1001");

topicSession =
topicConnection.createTopicSession(false,
Session.CLIENT_ACKNOWLEDGE);
topic = (com.sun.messaging.BasicTopic)topicSession.createTopic("yahoonews");
} catch (Exception e) {
e.printStackTrace();
if (topicConnection != null) {
try {
topicConnection.close();
} catch (javax.jms.JMSException ee) {}
}
}
}// end constructor

public void startSubscriber(){
try {

topicConnection.stop();
topicSubscriber =
topicSession.createDurableSubscriber(topic,
"finanancialnewsSubscriber");

topicConnection.start();
} catch (javax.jms.JMSException e) {
System.err.println("Exception occurred: " +
e.toString());
}

}

public javax.jms.Message getMessage(int timeout) throws Exception{

javax.jms.Message m = topicSubscriber.receive(timeout);
return m;
}
}

Step2. Create a wrapper class that will exposed as web service using REST or SOAP.
The web service should have two functions getMessage and ackMessage.
The class should also store the message that needs to be acknowledged.


public class JMSWebService{

private static DurableSubscriber ds = new DurableSubscriber();
static{
ds.startSubscriber();
}
private javax.jms.Message ackMessage;

public String getMessage(){
if (ackMessage==null)
ackMessage = ds.getMessage(1000); // 1 sec blocking call to get messages
String str = ackMessage.getText();
return str;
}

public void ackMessage(){
if (ackMessage!=null)
ackMessage.acknowledge();
ackMessage = null;
}
}

In this example reliability is achieved by having the ackMessage service along with getMessage, the client has to call the ackMessage function to indicate that all is well at the client side and that the client has commited the transaction at his end. If the ackMessage call is never made and the client keeps calling the getMessage function the transaction will not be commited and so the same message is returned to the client.

Sunday, February 15, 2009

Traversing a large database result set using toplink

If you are developing a web application at some point you would have to deal with database queries that return large result sets, your web site might not give the best user experience if it takes several minutes to display your result set with thousands of rows in it. There are several patterns that address this, if you are using plain JDBC then there is the rowid pattern to traverse large result sets. Oracle toplink makes this pattern really simple using "Scrollable Cursors", combine this with some basic pagination logic will make users traversing through thousands of records in your web application very happy.

Here is a basic example that makes traversing an email database a breeze.

Using workbench generate your Email class from your sample Email table, work bench will also generate the database session file which have connection pool information.

Lets call our data access class EmailDAO

public class EmailDAO{
private static Server dbServer;

class EmailResultSet{
String mymail;
Integer totalEmails;
Integer pagesize;
Integer pagenumber;
Vector emails;
};

static{
// in 3 tier there needs to be one server instance and multiple client instances
// db-session.xml contains the database connection information and should be in classpath
XMLSessionConfigLoader loader = new XMLSessionConfigLoader("db-session.xml");
SessionManager mgr = SessionManager.getManager();
dbServer = (ServerSession)mgr.getSession(loader, "DBSession",
Thread.currentThread().getContextClassLoader());
}

/*
* mymail is the email address whose email we need to return
* pagesize is the number of emails to be returned.
* pagenumber
*/
public EmailResultSet getMails(EmailResultSet emset){
// Step 1 Establish connection using toplink 3 tier architecture
Session clientSession = establishConnection();

// Step2 construct the query
ExpressionBuilder exbuilder = new ExpressionBuilder();
Expression whereclause= exbuilder.get("emailaddress").equal(emset.mymail);
ReadAllQuery rquery = new ReadAllQuery(Email.class,whereclause);
rquery.addDescendingOrdering("time"); // sort by time column

// Step3 tell the read query you want the result set split into chuncks of emails each chunk has pagesize number of emails in them
rquery.useScrollableCursor(emset.pagesize);

// Step4 execute the query
ScrollableCursor cursor = (ScrollableCursor) clientSession.execute(rquery);
// instead of returning a ResultSet as in a conventional execute call a cursor is returned.

// Step 5 find total emails
cursor.last();
// find the total number of email records by going to the last records position
emset.totalEmails = new Integer(cursor.getPosition());

// Step 6 position the cursor
// If pagenumber is greater than zero it means the caller knows which page he wants else position it to the first page
if (emset.pagenumber>0)
cursor.absolute(pagenumber); //point the cursor to the wanted page
else
cursor.first();

// Step 7 get the result set
Vector results = new Vector(emset.pagesize);
for (int i=0; i<
emset.pagesize && cursor.hasNext(); i++)
{
results.add(cursor.next());

}
emset.emails=results;
return emset;

}

public Session establishConnection(){
ConnectionPolicy connectionPolicy = new ConnectionPolicy();
// Use an exclusive connection for the session
connectionPolicy.setShouldUseExclusiveConnection(true);
Session clientSession = dbServer.acquireClientSession(connectionPolicy);
return clientSession;

}

}

Saturday, February 14, 2009

JPA Entities with composite keys

EJB3 spec has made a real come back with JPA. Very often when we need to create a POJO with a composite primary key. JPA makes this very simple. If you want to create an Employee POJO with a composite primary key as first name and last name this is how you do it.

@IDClass(EmployeePK.class)
@Entity(name="EMPLOYEE")
public class Employee implements Serializable{

@ID
private String firstName;
@ID
private String lastName;
private String qualification;
private String speciality;

// getters and setters go here

}



Now create a class called EmployeePK in the same package as Employee class with attributes firstName and lastName.

public class EmployeePK implements Serializable{
private String firstName;
private String lastName;

// getters and setters for firstName and lastName go here...

}

REST vs SOAP

REST or Representational State Transfer has becoming more popular in the SOA world due to its simplicity compared to SOAP. Using SOAP it is definitely possible for different kinds of clients (java, .net etc) to call a SOAP service, but the style of the service does play a role in what the client can and cannot do. For instance .net client will have trouble calling a JAX-RPC style service. With document literal style all bean mappings in the WSDD should have name spaces which is not required in JAX-RPC. REST has made this very simple by dealing with XML or JSON instead of marshalled objects. The disadvantage being that the client will be getting back an XML or JSON.