My blog has moved!

You should automatically be redirected in 6 seconds. If not, visit
http://blogs.i2m.dk/allan
and update your bookmarks.

Monday, 16 March 2009

Sending files through action listeners

For this weeks JSF tip, I’ll show you how to send binary data (such as a file) to the user by way of an action handler or listener.

Say, you want to generate a custom PDF and send it to the user as he clicks a link. You need a JSF page, and a backing bean.

Your JSF page may look like this:


<h:form>
<h:commandLink id="lnkDownload"
actionListener="#{myBean.onDownload}"
target="_blank"
value="Download PDF" />
</h:form>



Your JSF backing bean may look like this:

public MyBean {

public void onDownload(ActionEvent event) {
try {
// here you need to get the byte[] representation of
// the file you want to send
byte[] binary_data = ;
String filename = "generated_file.pdf”;
FacesContext fctx = FacesContext.getCurrentInstance();
ExternalContext ectx = fctx.getExternalContext();

HttpServletResponse response = (HttpServletResponse) ectx.getResponse();
response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
response.setHeader("Content-Transfer-Encoding", "Binary");
response.setHeader("Pragma", "private");
response.setHeader("cache-control", "private, must-revalidate");

ServletOutputStream outs = response.getOutputStream();
outs.write(binary_data);
outs.flush();
outs.close();
response.flushBuffer();

fctx.responseComplete();
} catch (IOException ex) {
ex.printStackTrace();
}
}


That’s it for today.

P.S. alternatively you can use this component which is less code intensive: http://kenai.com/projects/scales/pages/Download

Monday, 9 March 2009

JSF and I18N

It has been a busy year so far. Every year I start out thinking that I really need to relax because the previous year was too hectic, but every year it ends up being much more hectic. Anyway, I thought I’d post a JSF quick time that might shave some headache for people developing internationalised applications.

Most JSF developers are aware of the resource-bundle tag in faces-config. Using this tag you can specify a resource bundle that should be available to all your pages using a given variable. For example, the code below will make a variable, msgs, available in all your pages without having to use the loadBundle tag.


<faces-config version="1.2">
...
<application>
<resource-bundle>
<base-name>my.class.path.Messages</base-name>
<var>msgs</var>
</resource-bundle>
</application>
...
</faces-config>


So, say that Messages.properties contains the following:


HELLO_WHAT_IS_YOUR_NAME=Hello, what’s your name?


you can from any page reference this text by writing:


<h:outputText value=”#{mgs.HELLO_WHAT_IS_YOUR_NAME}” />

or

<h:outputText value=”#{mgs[‘HELLO_WHAT_IS_YOUR_NAME’]}” />


I prefer the former as my favourite IDE (NetBeans) support code completion for all the messages in a managed resource bundle.

So far so good. But what if you want to do something a bit more advanced, such as outputting “Hello Allan, welcome to my site. Your last visit was 7. February 2009 at 10:45”. You are not limited to static text in your resource bundle. You can provide placeholders for content that will be replaced at run-time. Let’s have a look at the Message.properties:


WELCOME_MESSAGE=Hello {0}, welcome to my site. Your last visit was {1,date,long} at {1,time,short}


You’ll notice that the message is parameterised using two parameters. The first parameter we are expecting a string containing the name of the user, the second parameter is a java.util.Date containing both the date and time when user last visited the site. Notice that I’ve reused the second paramenter ({1}), one time for the date and the other for the time. On your JSF page you would use the message as follows (imaging that you have a bean called welcome containing a property for getting the name of the user and last visit):


<h:outputFormat value=”#{msgs.WELCOME_MESSAGE}”>
<f:param value=”#{welcome.userName}” />
<f:param value=”#{welcome.lastVisit}” />
</h:outputFormat>


Pretty neat, eh?

What about the classical case of singular and plural messages? Imagine that you want to display the number of records in a table “There are 10 records in the table”. If the Message.properties contained:


RECORDS_IN_TABLE=There are {0} records in the table


You’d end up an embarrassing problem if there was only one record in the table:

“There are 1 records in the table” (This sentence is grammatical incorrect)

Instead you would want it to output:

“There is 1 record in the table”

To do this, you have to use the choice pattern:


RECORDS_IN_TABLE=There {0, choice, 0#are|1#is|2#are} {0} {0, choice, 0#records|1#record|2#records}


The format might look a bit awkward, but once you have understood the pattern it is simple:


{0,choicemeans, taking the first parameter and base the output on a choice of formats
0#areif the first parameter contains 0 (or below), then it should print “are”
|1#isor, if the first parameter contain 1, then it should print “is”
|2#are}or, if the first parameter contains 2 (or above), then it should print “are”


Now, that is nice! So let’s examine the output of these examples:


<h:outputFormat value=”#{msgs.RECORDS_IN_TABLE}”>
<f:param value=”#{0}” />
</h:outputFormat>
There are 0 records in the table

<h:outputFormat value=”#{msgs.RECORDS_IN_TABLE}”>
<f:param value=”#{1}” />
</h:outputFormat>
There is 1 record in the table

<h:outputFormat value=”#{msgs.RECORDS_IN_TABLE}”>
<f:param value=”#{2}” />
</h:outputFormat>
There are 2 records in the table

<h:outputFormat value=”#{msgs.RECORDS_IN_TABLE}”>
<f:param value=”#{10}” />
</h:outputFormat>
There are 10 records in the table


Enjoy!

Monday, 2 February 2009

Review: Getting Real -- The smarter, faster, easier way to build a successful web application


Since mid last week I've been down with a terrible flu. It has been so bad that I haven't been able to look at the computer screen (imagine that!!). To pass time I picked up a book that I picked up from Lulu.com a few months ago called "Getting Real -- The smarter, faster, easier way to build a successful web application". The authors behind the book are the developers behind 37signals (probably most known for developing the Ruby on Rails framework). The contents of the book is actually freely available from their website, but since I'm spending more and more time away from the computer these days I decided to buy a paper copy.

I absolutely loved the book. I knew that I would love the book when I read part of the disclaimer: "If our tone seems too known-it-allish, bear with us. We think it's better to present ideas in bold strokes than to be wishy-washy about it. If that comes off as cocky or arrogant, so be it. We'd rather be provocative than water every down with "it depends..."". It is so refreshing to read something that is written with confidence and not some generic advice that can mean everything and nothing.

The book takes you through the stages of launching a web application from staffing, to interface design, to pricing and post-launch activities. Each chapter deals with a specific stage of the launch and provide easy-to-read, snappy, no bull advices on how to go about the given stage. Although I don't agree with everything in the book it is very enlighting, refreshing and entertaining. It reminds me a lot about the book "How to become a CEO- The Rules for Rising to the Top of Any Organization" by Jeffrey J Fox, which I can recommend for a quick entertaining read.

It's a must read for everything developing web applications. I'll give this book five stars out of five!!

Thursday, 8 January 2009

Another big shot goes bust

Another big shot goes bust! This time it's the Indian IT "giant" Satyam (http://www.computing.co.uk/vnunet/news/2233443/satyam-chairman-admits-seven). This is not long after the Danish company; IT Factory, pulled a similar stunt (http://politiken.dk/newsinenglish/article605506.ece). I'm starting to think that when all things are going well, it's just an illusion with a few puppet masters pulling all the strings. However, I just can't believe that in both cases it is claimed that the auditors and board didn't have any knowledge of the wrong doings. If this is true then we must be talking about the dumbest people in the world.

Friday, 2 January 2009

Christmas present from Sun

Just as the year was ended I got a great Christmas present from Sun Microsystems.

1) A cool NetBeans 10 year anniversary T-shirt for participating in the community acceptance test programme for NetBeans 6.5 (NetCAT)



2) A pass on my exam to become Sun Certified Specialist for NetBeans IDE

The exam was special to me as it was my first ever certification exam. My score was 82%, with the least score in questions about building Java SE applications. I guess it shows that I've never build Java SE applications on NetBeans. Otherwise I think the exam was great. Studying for the exam revealed a lot of useful features that I had never used before, but now wondering how I could ever live without. I can highly recommend doing the exam!

Thanks Sun!

Wednesday, 31 December 2008

Setting JAVA_HOME on Ubuntu

A thing that always annoys me about installing Java is that it doesn't automatically set up the JAVA_HOME environment variable after installation. I guess this is to avoid having problems when you have multiple virtual machines installed. Anyway, I use Ubuntu Linux to host the majority of my Java Application Server. It is easy install Java (sudo apt-get install sun-java6-jdk) but there always seems to be a debate about where to set the JAVA_HOME environment variable. Some instructions say you should add it to your personal profile (e.g. ~/.bashrc) others suggest adding it to the global profile (i.e. /etc/profile), some people even suggest adding it directly in the init script for the services that need the variable. My suggest is to add an executable shell script to /etc/profile.d/ called javahome.sh. The content of the file would be: export JAVA_HOME=/usr/lib/jvm/java-6-sun. All shell scripts (i.e. executable files with the extension .sh) located in the /etc/profile.d/ directory are loaded upon login and would therefore work for all users without having to change system files that may change upon the next O/S upgrade. To test the script simply type source /etc/profile This will reload the profile for the current user. To verify that the environment variable has been initialised type export|grep JAVA_HOME

Enjoy!

Monday, 24 November 2008

Getting value expressions from f:attributes

If you have a custom converter or validator you may provide these with the option of letting developers specify attributes. For example, let's say that we are creating a converter that will allow the formatting of a Calendar object. Note, that the <f:convertDateTime /> is for Date objects (which can be easily retrieved from a Calendar, but that is beside the point). So the custom converter I'll create here is for converting/formatting Calendar objects.


package com.blogspot.bigallan.converters;

import java.text.*;
import java.util.*;
import javax.el.ValueExpression;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;

public class CalendarConverter implements Converter {

/**
* Not implemented as the converter is one-way only.
*/
public Object getAsObject(FacesContext ctx, UIComponent component, String value) {
return null;
}

public String getAsString(FacesContext ctx, UIComponent component, Object value) {

// Get the Calendar to convert
Calendar calendar = (Calendar) value;

String pattern = "";

// Obtain attributes specified along with the converter
Map<String, Object> attributes = component.getAttributes();

// Check if the pattern attribute was specified
if (!attributes.containsKey("pattern")) {
System.out.println("pattern was not specified");
return "";
} else {
pattern = (String)attributes.get("pattern");
}

// Create a DateFormatter for the pattern
DateFormat outputFormat = new SimpleDateFormat(pattern);

// Format the calendar
try {
Date date = originalFormat.parse(calendar.getTime());
return outputFormat.format(originalDate));
} catch (ParseException ex) {
ex.printStackTrace()
return "";
}
}
}


In faces-config.xml you would declare the converter like this:


<converter>
<converter-id>calendarConverter</converter-id>
<converter-class>com.blogspot.bigallan.converters.CalendarConverter</converter-class>
</converter>


We can now use the converter in a view:


<h:outputText value="#{myBean.calendarObject}">
<f:converter converterId="calendarConverter" />
<f:attribute name="pattern" value="d. MMMM yyyy" />
</h:outputText>


When the code is rendered in the browser you'll get the calendar converter to something like this 24. November 2008. So far so good. However, what if we didn't specify the date pattern as static text, but rather bind it to a value. This technique is efficient when you reuse the pattern in many places and want to keep the pattern in a central place. So say that we had a managed-bean called common with a method getDateFormat() : String that would provide the pattern. The code would look like this:


<h:outputText value="#{myBean.calendarObject}">
<f:converter converterId="calendarConverter" />
<f:attribute name="pattern" value="#{common.dateFormat}" />
</h:outputText>


When the code is rendered in the browser you'll get a blank response and see the following in the log, "pattern was not specified". The log statement is generated from out code above where we check for the attribute named "pattern". This is because of a requirement in the JSF 1.2 specification (JSR-252) that states (Section 9.4.2) that literal (static) text should be stored in the attribute map of the component and non-literal texts should be stored in the value expression map of the component. So to get the pattern from the value expression map we modify the getAsString method as follows:



public String getAsString(FacesContext ctx, UIComponent component, Object value) {

// Get the Calendar to convert
Calendar calendar = (Calendar) value;

String pattern = "";

// Obtain attributes specified along with the converter
Map<String, Object> attributes = component.getAttributes();

// Check if the pattern attribute was specified
if (!attributes.containsKey("pattern")) {

ValueExpression ve = component.getValueExpression("pattern");
if (ve == null) {
System.out.println("pattern was not specified");
return "";
} else {
pattern = (String) ve.getValue(ctx.getELContext());
}
} else {
pattern = attributes.get("pattern");
}

// Create a DateFormatter for the pattern
DateFormat outputFormat = new SimpleDateFormat(pattern);

// Format the calendar
try {
Date date = originalFormat.parse(calendar.getTime());
return outputFormat.format(originalDate));
} catch (ParseException ex) {
ex.printStackTrace()
return "";
}
}


The difference is that we now first check to see if there is a literal value specified. If not, we check if there is a value expression, and if there is no value expression either we will fail. If there is a value express we evaluate it and use it as our pattern.

Tuesday, 28 October 2008

Open Source vs. Commercial Software

Today I stumbled upon the following article about Open Source vs Commercial Software. It's quite entertaining and shows may of the pros and cons for both open source and commercial software licensing.

http://www.isitedesign.com/insight/08_07/open-source-versus-commercial-web-software.cfm

Enjoy!

Friday, 24 October 2008

Replacing TopLink Essentials with OpenJPA as my persistence provider

During the development of my latest pet project I decided to go head-on with many of the latest Java Enterprise APIs. One of these was the Java Persistence API (JPA), which I had already used in a handful of projects before. On previous projects the persistence requirements were very simple. I could use JPA out-of-the-box with TopLink Essentials which is the standard set-up for a JPA project in NetBeans/GlassFish. However, for this new pet project of mine I was in need of storing large binary objects (BLOBs). I was shocked to discover that TopLink Essentials doesn't support the Fetching configuration for relationships and properties. Instead it will Fetch.EAGER everything in a relationship and property. This made my application crash hard (OutOfMemoryException) when ever I would query for all entities containing the BLOB. So, I set out to replace the persistence provider. First I looked at Hibernate. I used Hibernate before JPA was released and never had much trouble with it. Unfortunately I found that Hibernate also doesn't support the fetching configuration (in JPA mode). That lead me to OpenJPA which really surprised me. It is well documented, clean, easy to use, and support the fetch configuration. I've now replaced the persistence provider on two projects with OpenJPA and the performance has increased significantly. However, here are a few gotchas that you have to look out for:


  • Auto-generated identity fields must not have a preset value in your JavaBean (hence, this would give you problems:

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id = 0L


    Instead you should write

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;


  • Collections are Fetch.LAZY by default, so if you got an existing using TopLink Essentials, you have to double check that your relations are not throwing LazyInitializationException upon fetching outside the transation.

  • Remember to specify the Fetch depth (openjpa.MaxFetchDepth) in persistence.xml for using the Fetch.EAGER configuration

  • TopLink Essentials compiles named queries when your application is deploy on the application server, OpenJPA on the other hand compiles the named queries upon first usage.

  • When enabling SQL DDL on OpenJPA it doesn't generate foreign key constraints, unlike TopLink Essentials



That's all for now. I'd love to hear about your experiences with OpenJPA or any other persistence provide you find suitable for your need.

Friday, 10 October 2008

Cycling

For the past week I've been cycling to and from work. That might not sound like a big deal to you, but it has certainly been a challenge for me. In the past it has been all to easy to jump into the car and head off for work. No more, I've decided. The distance to work is very do-able, 5.5 KM each way. It's better for me and it's better for the environment. The biggest problem so far has been the uphill route on my way back. Nevertheless, I've made great progress already. The first day was absolutely hell! When I got to work I could barely breathe and I had to spend several minutes in the bike shed to compose myself. On the third day I managed to cut off 5 minutes from the ride, and today I was only plagued by fatigue in my joints. I'm looking forward to seeing how I'll be feeling on Monday and if I can take another week.

Thursday, 9 October 2008

MyFaces and Facelets - The Definitive Guide

For the past five months or so, I've had the pleasure of participating as a contributing author and editor of the recently released Apress publication, "MyFaces and Facelets - The Definitive Guide".



It was a great experience that I hope that I'll be able to relive in the near future on other book writing projects. What I liked about the book was the focus on the array of JSF components under the MyFaces Apache project. Most people seem to think that MyFaces is simply an implementation of the JavaServer Faces specification. MyFaces is an umbrella project for JavaServer Faces related technologies. The most famous of the sub-projects is the Tomahawk components project which provides a lot of useful JSF component that I certainly couldn't live without.

The focus of the book is on technologies under the Apache MyFaces project as well as the Facelets technology. Facelets is another very important JSF technology that deserves more attention from the community. There are lots of people using Facelets, but little development is going on to make it truly professional.

The book is not for newcomers to JSF, but for programmers already familiar with the basics of JSF. If you are looking to get familiar with JSF I can highly recommend JSF In Action by Kito D. Mann published by Manning.

Thanks to Zubin Wadia and Hazem Saleh for making the project a great experience!

Monday, 1 September 2008

On the road again... (Uganda)

I'm on the road again again. This time I'm in Uganda. Uganda has to be one of my absolute favorite countries. I've be dropping in and out of Uganda the past nine years and even lived here for a few years. What I like about Uganda is the friendliness of the people. Ugandans have to be the friendliest people in the world! That is not to say that there are no dodgy Ugandans, but overall they are very easy people to get along with.

This time I'm not travelling for the company. Instead I'm here to assess some business opportunities for the near future. You would be surprised how many IT-related business opportunities you will find in a developing economy.

Anyways, just wanted to drop a post on the blog to show that I'm still alive and well. More about my trip later.

By the way, if you are ever in Uganda there are two things you must try; 1) A whole deep fried tilapia from the Lake Victoria 2) Roasted pork. Both usually come with a range of accessories such as avocado, cassava, and matoke.

Wednesday, 6 August 2008

Project-based formatting in NetBeans 6.5

Being part of the NetBeans Community Acceptance Testing (NetCAT) Programme has definate advantages. For one, you get to try out all the new features planned and influence how they will work before being released to the general public (that is not quite true....anyone can download the daily development builds).



One of the features in the upcoming NetBeans 6.5 that I'm particularly happy about is Formatting by project. In NetBeans it has always been one configuration for all projects. This is slowly changing. During NetCAT for 6.1 the "Shared Library" feature was implemented to detach library management from NetBeans and thereby making projects more portable. So, this time the brilliant guys on the NetBeans development team implemented a feature making it possible to do project-based formatting. This is a great feature when you work on many different projects with different formatting requirements. Way to go! My hope is that for the next version of NetBeans they will also have made template management project-based.

Wednesday, 25 June 2008

On the road again...

After a lovely week back home in Denmark with my family, I am once again on the road. This time I'm in Zambia to conduct training and hand-over a system we have built for COMESA. I've been to Zambia twice before and always enjoy coming here as it is clean and people are friendly. Anyways, I still hope this will be must last trip this year as I really need to spend some time at home with my family.

Note: If you are planning on going to Zambia I can highly recommend staying at the Intercontinental. At my first visit I was staying at Holiday-Inn. The food and service was excellent but the rooms were terrible!

Thursday, 12 June 2008

Finalised my mission in Djibouti and Kenya

Today, I finalised my mission to Djibouti and Kenya. I've still got another three days until I'm back home, but at least my work is done. While in Djibouti I carried out four days of System Administration training for the Web Portal I'm putting into place. That was followed by a one day steering committee meeting and four days workshop on Portal Management in Nairobi. It has been a very exhausting trip as I caught a food poisoning in Djibouti two days after having arrived. The food poisoning persisted until yesterday (almost a week) after which I had to go see a doctor. Fortunately, Nairobi Hospital is located just opposite the venue where I was conducting the workshop. So after having consulted a doctor and taken a few samples, I was given some medicine that would hope initially until they had time to examine my samples. So, today I got a call from the doctor explaining that I had a fungus growing in my stomach that was developing into a yest infection. I was then given some antibiotica and now feeling very fine. However, the last week was hell. Imagine having to do presentation from morning till afternoon with a constant stomach ache and having to run off to the wash room after every meal. Anyways, it is now being treated and I'm feeling much better.

Besides my illness I got to talk and meet some wonderful people from around Eastern Africa. Tomorrow morning I'm off to Dubai where I'll spend one day before heading home to the family! Traveling can be very tiring and stressful when you'd rather spend time with your wife and baby.

That's all for now folks.

Sunday, 1 June 2008

Dubai is hot!!

Dubai is hot, in more than one sense. I'm currently on my way to Djibouti to finalise some work on a project. On my way I stopped in Dubai for two days as I've always been curious about the place. I was very pleasantly surprised as people were nice, the place was clean, and the city was beautiful!

The real hotness though is the weather. I couldn't help laughing when I saw the sticker on the window in my hotel room.



It says "WARNING - Humidity from outside may activate the fire alarm". I can testify to the hotness (between 40 and 50 degrees celcius) as I spent a whole day on the top deck of a Big Bus tour around Dubai (if you only got a day in Dubai I would strongly suggest the Big Bus Tour - it' is excellent!).

Of all the places I've been I'd give it a 9 out of 10.

That's all for now - I'm off to Djibouti in a few minutes.

Thursday, 8 May 2008

Using Facelets with NetBeans 6.1 (without nbfaceletssupport)

--
Update 27. May 2008: You can download the Facelets NetBeans plug-in for 6.1 from: http://project-template.googlecode.com/files/nbfaceletssupport-6.1.zip
--

I'm a fan of Facelets when it comes to templating for JSF applications. Prior to version 6.1 of NetBeans I was using the nbfaceletssupport plug-in. Sure, it had its quirks, but overall it was a good plug-in. After installing NetBeans 6.1 and really got into using all the new cool features (shared libraries being the most significant) I realised that the nbfaceletssupport plug-in for NetBeans 6.0 didn't work and a fix had not yet been released at the nbfaceletssupport project site (note: Po-Ting Wu of Sun Microsystems has provided instructions on how to re-compile the plug-in for NetBeans 6.1). This also happened when I switched from NetBeans 5.5.1 to 6.0, so I anticipate that this will also happen in the future. So, I thought to myself, why not use the powerful XML support already built-in NetBeans to give me what I need. What I really needed the plug-in for is code completion. So, here goes. First I decided to drop JSP pages (.jsp) for JSP documents (.jspx). The difference being that .jspx is pure XML and .jsp is HTML.

Facelets file as a JSP page (.xhtml):


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html">
<head>
<title>JSP facelets file</title>
</head>
<body>

<ui:composition template="/resources/templates/page.xhtml">
<ui:define name="pageTitle">This is a page title</ui:define>
<ui:define name="pageContent">This is the page content</ui:define>
</ui:composition>

</body>
</html>



Facelets file as a JSP document (.jspx):

<jsp:root version="2.0" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:fn="http://java.sun.com/jsp/jstl/functions" xmlns:t="http://myfaces.apache.org/tomahawk" xmlns:c="http://java.sun.com/jstl/core" xmlns:jsfExt="http://java.sun.com/jsf/extensions/dynafaces">
<ui:composition template="templates/page.xhtml">
<ui:define name="pageTitle">This is a page title</ui:define>
<ui:define name="pageContent">This is the page content</ui:define>
</ui:composition>
</jsp:root>



When creating facelets file as JSP document in NetBeans you will automatically get code completion (without any third-party plug-ins).



For this to work, ensure that the following configuration is set it web.xml:


<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.jspx</param-value>
</context-param>



and that the faclets tag library descriptor (TLD) is accessible in the classpath (eg. /WEB-INF/tlds).




References:

Tuesday, 6 May 2008

Yearly conference at the local Danish IT Society branch

Last week I went to the yearly conference for my local Danish IT Society branch. The topic of the conference was Enterprise Architecture. I was a bit unsure about attending as I was expecting some obscure high-level talks that has never seen the light of day. I was pleasantly surprised! All the speakers did a great job and managed to cover the various facets (from theory, to best practice, to practice) of Enterprise Architecture. What especially caught my attention was the excellent governance and organisational re-structuring implemented at NyKredit headed by their CIO (and president of Danish IT Society) Lars Mathiesen (You can read articles about Mathiesen on Computerworld.dk). From a vendor point-of-view the Vice President SOA Strategy, Ivo Totev of Software AG flew in from Germany. Last year I went for another meeting arranged by Danish IT Society with Scrum founder Jeff Sutherland. I wasn't too impressed as there was too much "going-around-the-bush" and not a clear business case for Scrum. Anyways, I didn't know what to expect from Ivo Totev's presesentation. However, I was very impressed with his presentation about the best practices of Enterprise Architecture coupled with anecdotes about what was working and not working with their clients. If you've got interest in Enterprise Architecture, Service-oriented Architecture (SOA), and Business Process Management, I suggest visiting Software AG's customer community at http://communities.softwareag.com/ where you'll interesting resources such as podcasts, blogs, discussion groups and even a freely downloadable PDF version of the book "BPM Basics for Dummies".

Friday, 18 April 2008

Creating a generic error page for JSF

Sometimes using FacesMessages is not sufficient for reporting errors. For example, if you have a runtime error (invalid JSF mark-up or NullPointerExceptions) it is difficult to report them using FacesMessage.

Creating a generic error page for JSF is similar to creating a generic error page for plain JSP applications. You'll need a configuration in web.xml to tell the servlet container to redirect errors to a given page. Then you'll need to create that page as well as a backing bean that can show you the stacktrace or error message.

web.xml


<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

... markup for your web app ...

<error-page>
<error-code>500</error-code>
<location>/Error.jsp</location>
</error-page>

</web-app>


With that we will get the servlet container to forward any Internal Server Errors (HTTP 500) to the page Error.jsp.

Okay, now we need to create a bean that will prepare the error message based on the exception that was thrown:

Error.java

package bigallan.beans;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.servlet.ServletException;

public class Error {

public Error() {}

public String getStackTrace() {

// Get the current JSF context
FacesContext context = FacesContext.getCurrentInstance();
Map requestMap = context.getExternalContext().getRequestMap();

// Fetch the exception
Throwable ex = (Throwable) requestMap.get("javax.servlet.error.exception");

// Create a writer for keeping the stacktrace of the exception
StringWriter writer = new StringWriter();
PrintWriter pw = new PrintWriter(writer);

// Fill the stack trace into the write
fillStackTrace(ex, pw);

return writer.toString();
}

/**
* Write the stack trace from an exception into a writer.
*
* @param ex
* Exception for which to get the stack trace
* @param pw
* PrintWriter to write the stack trace
*/
private void fillStackTrace(Throwable ex, PrintWriter pw) {
if (null == ex) {
return;
}

ex.printStackTrace(pw);

// The first time fillStackTrace is called it will always be a ServletException
if (ex instanceof ServletException) {
Throwable cause = ((ServletException) ex).getRootCause();

if (null != cause) {
pw.println("Root Cause:");
fillStackTrace(cause, pw);
}
} else {
// Embedded cause inside the ServletException
Throwable cause = ex.getCause();

if (null != cause) {
pw.println("Cause:");
fillStackTrace(cause, pw);
}
}
}
}


Now that we have the Backing Bean we need to register it in faces-config.xml:


.. usual faces-config stuff ..

<managed-bean>
<managed-bean-name>Error</managed-bean-name>
<managed-bean-class>bigallan.beans.Error</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>


And lastly the JSP page (Error.jsp) displaying the error:

.. usual JSP header stuff ..

<h:panelGrid>
<h:outputText value="The follow error occured:" />
<h:inputTextarea style="width: 100%;" rows="20" readonly="true" value="#{Error.stackTrace}" />
</h:panelGrid>


That's all!

Enjoy.

Wednesday, 2 April 2008

Tomato juice on airplanes

I've just returned from a two week business trip and there is something that just keeps puzzling me when I fly. The amount of people that drink tomato juice on airplanes just amazes me. I have never dined with anyone who ordered tomato juice neither I have ever tasted it. However, on airplanes it seems like people have the urge to drink tomato juice. Flying back from Uganda (via Nairobi) to Amsterdam, an 8+ hours journey my co-passenger only had tomato juice! Tomorrow I've got to go buy myself some tomato juice to see what the craze is all about.