Using Richfaces 'Suggestion Box' As Combo Box

If you had already tried to use Richfaces Combo Box for populating the 'id-value' pairs, you would have noticed that the dropdown/combo box will be populated with id's, rather than values. It's not a bug or a problem with richfaces framework, but a different design. There's a workaround for this, which lets you use the 'Richfaces Suggestion Box' component, to work like a combo box or a dropdown list.

Below is the sample code snippet from a facelets file, which acts like a combo box:

<a4j:form id="form1">

...............

...............

<h:outputText value="Key :"/>
<a4j:region selfRendered="true" id="region1">
<h:inputText id="value" value="Value : "/>
<h:graphicImage value="arrow.png" 
onclick="openSuggestionBox('suggestion','form1','value','');" 
alt=""/>

<rich:suggestionbox id="suggestion" for="value" 
suggestionAction="#{someBean.fill}"  var="result" ignoreDupResponses="true">
<h:column>
<h:outputText value="#{result.description}"/>
</h:column>

<a4j:support event="onselect">
<f:setPropertyActionListener value="#{result.id}" 
target="#{someBean.selId}"/>
</a4j:support>
</rich:suggestionbox>
</a4j:region>
</a4j:form>


In the above code, I'm using a arrow image (down arrow) beside the input text box, to make it look like a combo-box/drop-down list and created a javascript function, which is called on click of that arrow image. This javascript function does nothing special, but clears the text-box and calls the actual 'Suggestion Box' method (creates an AJAX request).

And below is the Javascript code for 'openSuggestion' function:


Hashcode Of A String In Java

Many of the Java programmers know what 'Hashcode' means, but don't really know how exactly it is calculated and why 31 is used to calculate the hashcode. Below is the code snippet from Java 1.6, which calculates the hashcode for a string:

public int hashCode() {
int h = hash;
if (h == 0) {
int off = offset;
char val[] = value;
int len = count;

for (int i = 0; i < len; i++) {
h = 31*h + val[off++];
}
hash = h;
}

return h;
}
Even if someone knows why 31 is used, there is a lot of stuff to know about 'Hashing', 'Hash Collisions' and multiple algorithms related to calculating hash values. First off, its a known fact that there is no perfect hashing algorithm, for which there are no collisions. But there are several algorithms, which minimize the collisions and are good enough to use. Now, coming to why 31 is used in calculating hashcode, this is the reason given by Joshua Bloch, in the book 'Effective Java':
The value 31 was chosen because it is an odd prime. If it were even and the multiplication overflowed, information would be lost, as multiplication by 2 is equivalent to shifting. The advantage of using a prime is less clear, but it is traditional. A nice property of 31 is that the multiplication can be replaced by a shift and a subtraction for better performance: 31 * i == (i << 5) - i. Modern VMs do this sort of optimization automatically.
This wasn't sufficient for me, to understand why 31 is used. I did a bit of research and found some good links, providing some info about why 31 is used. Here are some links with very good info: Stack Overflow - Why does java hashcode use 31 as a multiplier Apart from the above link, there are a couple of other links with pretty good info about hashing, hash collisions and performance of hashing algorithms: Consistency Of Hashcode On A Java String Best Hashing Algos, In Terms Of Collisions and Performance Java Array Hashcode Implementation

After reading up a bit, I wrote a sample test Java program, to find the hashcode of a string by multiplying by 31 (which is the same as shifting left (bitwise) by 5 times and subtracting, as in (i << 5) - i). Below is the sample test program:
public class TestHash {
public static void main(String[] args) {
String str1 = "What the heck?";

int hashcode1 = 0;
int hashcode2 = 0;

for(int i=0;i<str1.length();i++) {
hashcode1 = 31*hashcode1 + str1.charAt(i);
hashcode2 = (hashcode2 << 5) - hashcode2 + str1.charAt(i);
}

System.out.println("Hashcode1 : " + hashcode1);
System.out.println("Hashcode2 : " + hashcode2);
}
}


The output for this program is:

Hashcode1 : 277800975
Hashcode2 : 277800975


Apart from the above info, I want to share some info from the recent article on java.sun.com, written by Joseph Darcy. It was an interesting case of 'Unhashing' - Reverse Engineering Hashcode, To Find A String That Collides With The Actual String. This was an interesting way of finding 'Hash Collisions'. I then tested the code from Joseph Darcy, by writing a sample program, as below:

public class TestHash {
/**
* @author - Babji P, Chetty
*/
public static void main(String[] args) {
String str1 = "what the heck?";

int hashcode1 = 0;
int hashcode2 = 0;

for(int i=0;i<str1.length();i++) {
hashcode1 = 31*hashcode1 + str1.charAt(i);
hashcode2 = (hashcode2 << 5) - hashcode2 + str1.charAt(i);
}

System.out.println("Hashcode1 : " + hashcode1);
System.out.println("Hashcode2 : " + hashcode2);

String str2 = unhash(hashcode1);
System.out.println("Unhashed String From Hashcode : " + str2);

int hashcode3 = 0;
int hashcode4 = 0;

for(int i=0;i<str2.length();i++) {
hashcode3 = 31*hashcode3 + str2.charAt(i);
hashcode4 = (hashcode4 << 5) - hashcode4 + str2.charAt(i);
}

System.out.println("Hashcode3 : " + hashcode3);
System.out.println("Hashcode4 : " + hashcode4);

}

/**
* Returns a string with a hash equal to the argument.
* @return string with a hash equal to the argument.
* @author - Joseph Darcy
*/
public static String unhash(int target) {
StringBuilder answer = new StringBuilder();
if (target < 0) {
// String with hash of Integer.MIN_VALUE, 0x80000000
answer.append("\u0915\u0009\u001e\u000c\u0002");

if (target == Integer.MIN_VALUE)
return answer.toString();
// Find target without sign bit set
target = target & Integer.MAX_VALUE;
}

unhash0(answer, target);
return answer.toString();
}

/**
* 
* @author - Joseph Darcy
*/
private static void unhash0(StringBuilder partial, int target) {
int div = target / 31;
int rem = target % 31;

if (div <= Character.MAX_VALUE) {
if (div != 0)
partial.append((char)div);
partial.append((char)rem);
} else {
unhash0(partial, div);
partial.append((char)rem);
}
}
}



The output for the above program is:

Hashcode1 : 1279794159
Hashcode2 : 1279794159
Unhashed String From Hashcode : ?☻§◄
Hashcode3 : 1279794159
Hashcode4 : 1279794159


So the strings "what the heck?" and "?☻§◄" have the same hashcode. What the heck?!?!

Richfaces - Modal Panel As A Wizard

Richfaces 'Modal Panel' component can be used to create a 'Dialog Box' or a 'Wizard' (or Wizard like behaviour), which is useful, when some part of the website/application has to ask for the input from the user, in steps. It can be customized, as per the requirements of that particular application, although everything that you implement doesn't sound like a standard mechanism, from the 'Richfaces' AJAX framework. Below is an example of creating a 'Wizard' out of a 'Richfaces Modal Panel' component:

1) Lets suppose that this 'Wizard' is opened, when a user clicks on some link (or any other AJAX/Javascript event)...and 2 steps, for that Wizard. So, the modal panel is on one page and there would be 2 other pages that are to be included, in the modal panel, to get that 'Wizard' like behavior. In my case, I'm using JSF and Facelets (Xhtml files). Below is a code snippet for the main page (where the modal panel is included):

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:rich="http://richfaces.org/rich"
xmlns:a4j="http://richfaces.org/a4j">

<ui:composition>
...........
...........
............

<rich:modalPanel id="panel1">
<f:facet name="header">
<h:outputText value="Test" />
</f:facet>

<f:facet name="controls">
<h:commandLink value="Close"
style="cursor:pointer"
onclick="Richfaces.hideModalPanel('panel1')" />
</f:facet>

<a4j:include binding="#{someBean.include}" viewId="/view/include1.xhtml"/>
</rich:modalPanel>
</ui:composition>
</html>


2) And below is the code snippet, for the first included page, on the modal panel:

<!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:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:rich="http://richfaces.org/rich"
xmlns:a4j="http://richfaces.org/a4j">

<ui:composition>
...........
...........
............

<h:form>
<h:panelGrid columns="2">
<h:outputText value="#{msg.input}"
<h:inputText value="#{someBean.someText}"/>

<rich:spacer width="20"/>
<a4j:commandButton value="#{msg.submit}" action="include2" reRender="wizard"/>
</h:panelGrid>
</h:form>
</ui:composition>
</html>


Note that the above included page, doesn't need to have f:view tags. Also, there are a couple of important points to consider from the Richfaces documentation:

RichFaces allows to organize a page flow inside the component. This is a typical scenario for Wizard like behavior. The new content is rendered inside the area. The content is taken from the navigation rule of the faces configuration file (usually, the faces-config.xml). Note, that the content of the "wizard" is not isolated from the rest of the page. The included page should not have own (it does not matter if you use facelets). You need to have an Ajax component inside the to navigate between the wizard pages. Otherwize, the whole page update will be performed.

If you want to involve the server side validators and navigate to the next page only if the Validation phase is passed successfully, you can replace with and point to the action method that navigates to the next page. If Validation process fails, the partial page update will occur and you will see an error message. Otherwize, the application proceeds to the next page. Make sure, you define option for the navigation rule to avoid memory leaks.


3) And below is the "include2.xhtml", which is shown as a second step, for that wizard. This wizard appears only if the validation succeeds on the previously included page (in case, if you have any input validations).

<!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:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:rich="http://richfaces.org/rich"
xmlns:a4j="http://richfaces.org/a4j">

<ui:composition>
...........
...........
............

<h:form>
<a4j:commandButton value="#{msg.confirm}" action="#{someBean.doSomeBusinessShit}" reRender="someId,wizard"/>
<a4j:commandButton value="#{msg.cancel}" action="#{someBean.reset}" onclick="javascript:Richfaces.hideModalPanel('panel1')" reRender="wizard"/>
</h:form>
</ui:composition>
</html>


4) And the faces-config.xml configuration, is as follows:

<?xml version="1.0"?>
<!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN"
"http://java.sun.com/dtd/web-facesconfig_1_1.dtd">
<faces-config>
............
............
............

<navigation-rule>
<from-view-id>/view/include1.xhtml</from-view-id>
<navigation-case>
<from-outcome>include2</from-outcome>
<to-view-id>/view/include2.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>



...And hey, its not yet over. If you happened to implement the above stuff and if you navigated to the second step, clicked 'Cancel' and tried to open the 'Wizard' again, the second included page, opens up directly, without the first step (included page). To remedy this, I've to reset the "viewId" in the "a4j:include" component. The "a4j:include" tag, already includes a binding. The only thing that has to be done is to implement the "reset" method, as below:

package echo;

import org.ajax4jsf.component.html.Include;

public class SomeBean {
.........
.........
private Include include;

.......
.......
.......

public void reset() {
include.setViewId("/view/include1.xhtml");
}
}

Jasper Reports - Thermometer Report

Below is the code of 'ThermoBean', which holds the data for 'Thermometer Report':

package com.chetty.reporting.beans;

public class ThermoBean {
private String title;
private double value;
private double rangeMin;
private double rangeMax;
private double firstSubRangeMin;
private double firstSubRangeMax;
private double secondSubRangeMin;
private double secondSubRangeMax;
private double thirdSubRangeMin;
private double thirdSubRangeMax;

public void setTitle(String title) {
this.title = title;
}

public String getTitle() {
return title;
}

public void setValue(double value) {
this.value = value;
}

public double getValue() {
return value;
}

public void setRangeMin(double rangeMin) {
this.rangeMin = rangeMin;
}

public double getRangeMin() {
return rangeMin;
}

public void setRangeMax(double rangeMax) {
this.rangeMax = rangeMax;
}

public double getRangeMax() {
return rangeMax;
}

public void setFirstSubRangeMin(double firstSubRangeMin) {
this.firstSubRangeMin = firstSubRangeMin;
}

public double getFirstSubRangeMin() {
return firstSubRangeMin;
}

public void setFirstSubRangeMax(double firstSubRangeMax) {
this.firstSubRangeMax = firstSubRangeMax;
}

public double getFirstSubRangeMax() {
return firstSubRangeMax;
}

public void setSecondSubRangeMin(double secondSubRangeMin) {
this.secondSubRangeMin = secondSubRangeMin;
}

public double getSecondSubRangeMin() {
return secondSubRangeMin;
}

public void setSecondSubRangeMax(double secondSubRangeMax) {
this.secondSubRangeMax = secondSubRangeMax;
}

public double getSecondSubRangeMax() {
return secondSubRangeMax;
}

public void setThirdSubRangeMin(double thirdSubRangeMin) {
this.thirdSubRangeMin = thirdSubRangeMin;
}

public double getThirdSubRangeMin() {
return thirdSubRangeMin;
}

public void setThirdSubRangeMax(double thirdSubRangeMax) {
this.thirdSubRangeMax = thirdSubRangeMax;
}

public double getThirdSubRangeMax() {
return thirdSubRangeMax;
}
}


And below is the class file with business logic, used to generate a collection of 'ThermoBean' objects, which is passed on to the Jasper reporting engine, to dynamically generate the Thermometer report:

package com.chetty.reporting.business;

import java.util.ArrayList;

import com.chetty.reporting.beans.ThermoBean;

public class ThermoBeanMaker {
public ArrayList getThermoData() {
ArrayList thermoBeanList = new ArrayList();

thermoBeanList.add(create(-10.0, -40.0, 50.0, -40.0, 0.0, 0.0, 15.0, 15.0, 50.0));

return thermoBeanList;
}

private ThermoBean create(double value, double rangeMin, double rangeMax, double firstSubRangeMin, 
double firstSubRangeMax, double secondSubRangeMin, double secondSubRangeMax, 
double thirdSubRangeMin, double thirdSubRangeMax) {
ThermoBean thermoBean = new ThermoBean();

thermoBean.setTitle("Germany - Temparature Report");
thermoBean.setValue(value);
thermoBean.setRangeMin(rangeMin);
thermoBean.setRangeMax(rangeMax);
thermoBean.setFirstSubRangeMin(firstSubRangeMin);
thermoBean.setFirstSubRangeMax(firstSubRangeMax);
thermoBean.setSecondSubRangeMin(secondSubRangeMin);
thermoBean.setSecondSubRangeMax(secondSubRangeMax);
thermoBean.setThirdSubRangeMin(thirdSubRangeMin);
thermoBean.setThirdSubRangeMax(thirdSubRangeMax);

return thermoBean;
}
}


And below is the main class, that generates the report:

package com.chetty.reporting.engine;

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import com.chetty.reporting.beans.GanttChartBean;
import com.chetty.reporting.beans.PieChartBean;
import com.chetty.reporting.beans.ThermoBean;
import com.chetty.reporting.business.GanttChartBeanMaker;
import com.chetty.reporting.business.PieChartBeanMaker;
import com.chetty.reporting.business.ThermoBeanMaker;

import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.xml.JRXmlLoader;

public class Reporter {
@SuppressWarnings("unchecked")
public static void main(String[] args) throws Exception {
InputStream inputStream = new FileInputStream ("reports/thermochart.jrxml");

ThermoBeanMaker thermoBeanMaker = new ThermoBeanMaker();
ArrayList thermoBeanList = thermoBeanMaker.getThermoData();

JRBeanCollectionDataSource beanColDataSource = new JRBeanCollectionDataSource(thermoBeanList);

Map parameters = new HashMap();

JasperDesign jasperDesign = JRXmlLoader.load(inputStream);
JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, beanColDataSource);
JasperExportManager.exportReportToPdfFile(jasperPrint, "c:/reports/thermochart.pdf"); 
}
}


When you run the above class, the following report is generated:

Thermometer Report

You can find the report design file, here: thermochart.jrxml

Jasper Reports - Gantt Chart

Jasper Reports framework uses JFreeChart, to dynamically generate charts in a Java application. In this post, I'm gonna use the Java beans as data holders and pass a collection of these beans, to the Jasper reporting engine, to dynamically generate these reports. Below is the code for the Java bean:

package com.chetty.reporting.beans;

import java.util.Date;

public class GanttChartBean {
private String series;
private String task;
private Date startDate;
private Date endDate;

public void setSeries(String series) {
this.series = series;
}

public String getSeries() {
return series;
}

public void setTask(String task) {
this.task = task;
}

public String getTask() {
return task;
}

public void setStartDate(Date startDate) {
this.startDate = startDate;
}

public Date getStartDate() {
return startDate;
}

public void setEndDate(Date endDate) {
this.endDate = endDate;
}

public Date getEndDate() {
return endDate;
}
}


And below is the code for the Java class, that holds the business logic for creating these beans:

package com.chetty.reporting.business;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;

import com.chetty.reporting.beans.GanttChartBean;

public class GanttChartBeanMaker {
public ArrayList getGanttChartData() {
ArrayList ganttChartDataList = new ArrayList();

Calendar calendar = Calendar.getInstance();

for(int i=1;i<8;i++) {
calendar.set(Calendar.HOUR_OF_DAY, i*1);

Date startDate = calendar.getTime();

calendar.set(Calendar.HOUR_OF_DAY, i*3);

Date endDate = calendar.getTime();

String series = (i % 2 == 0) ? "High Priority" : "Normal";

ganttChartDataList.add(create(series, "Meeting" + i, startDate, endDate));
}

return ganttChartDataList;
}

private GanttChartBean create(String series, String task, Date startDate, Date endDate) {
GanttChartBean ganttChartBean = new GanttChartBean();

ganttChartBean.setSeries(series);
ganttChartBean.setTask(task);
ganttChartBean.setStartDate(startDate);
ganttChartBean.setEndDate(endDate);

return ganttChartBean;
}
}
And below is the main class, which passes the collection of beans, to the Jasper reporting engine, to dynamically generate the Gantt Chart:
package com.chetty.reporting.engine;

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import com.chetty.reporting.beans.GanttChartBean;
import com.chetty.reporting.beans.PieChartBean;
import com.chetty.reporting.business.GanttChartBeanMaker;
import com.chetty.reporting.business.PieChartBeanMaker;

import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.xml.JRXmlLoader;

public class Reporter {
@SuppressWarnings("unchecked")
public static void main(String[] args) throws Exception {
InputStream inputStream = new FileInputStream ("reports/ganttchart.jrxml");

GanttChartBeanMaker ganttChartBeanMaker = new GanttChartBeanMaker();
ArrayList ganttChartBeanList = ganttChartBeanMaker.getGanttChartData();

JRBeanCollectionDataSource beanColDataSource = new JRBeanCollectionDataSource(ganttChartBeanList);

Map parameters = new HashMap();

JasperDesign jasperDesign = JRXmlLoader.load(inputStream);
JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, beanColDataSource);
JasperExportManager.exportReportToPdfFile(jasperPrint, "c:/reports/ganttchart.pdf"); 
}
}
When you run the code, the following report is generated: Gantt Chart The above report uses a different theme, which is not present in the jasperreports.jar file. To use that theme, you would have to include the 'jasperreports-chart-themes.jar' file. You can find the report design file, for the above report, here: ganttchart.jrxml

Jasper Reports - Example

Jasper Reports is one of the best 'Business Intelligence (BI)' tools/frameworks, which can be used for generating reports for Java/Groovy applications. It is just partly 'Open Source', but if you can practice or have good enough work experience in Java, you can easily build basic/complex reports.

'Jasper Reports' framework can handle different kinds of data sources, but in this post I will show how to generate a basic report, just by passing a collection of Java data objects (Java beans), to the Jasper Report Engine. Below is the code for the data object (Java bean):

package com.chetty.reporting.beans;

public class DataBean {
private String name;
private String occupation;
private String place;
private String country;

public void setName(String name) {
this.name = name;
}

public String getName() {
return name;
}

public void setOccupation(String occupation) {
this.occupation = occupation;
}

public String getOccupation() {
return occupation;
}

public void setPlace(String place) {
this.place = place;
}

public String getPlace() {
return place;
}

public void setCountry(String country) {
this.country = country;
}

public String getCountry() {
return country;
}
}


And below is the code for the class file with business logic to generate a collection of java bean objects, which is further passed to the Jasper report engine, to generate the report:

package com.chetty.reporting.business;

import java.util.ArrayList;

import com.chetty.reporting.beans.DataBean;

public class DataBeanMaker {
public ArrayList getDataBeanList() {
ArrayList dataBeanList = new ArrayList();

//dataBeanList.add(produce("Babji, Chetty", "Engineer", "Nuremberg", "Germany"));
dataBeanList.add(produce("Albert Einstein", "Engineer", "Ulm", "Germany"));
dataBeanList.add(produce("Alfred Hitchcock", "Movie Director", "London", "UK"));
dataBeanList.add(produce("Wernher Von Braun", "Rocket Scientist", "Wyrzysk",                                               "Poland (Previously Germany)"));
dataBeanList.add(produce("Sigmund Freud", "Neurologist", "Pribor", "Czech Republic (Previously Austria)"));
dataBeanList.add(produce("Mahatma Gandhi", "Lawyer", "Gujarat", "India"));
dataBeanList.add(produce("Sachin Tendulkar", "Cricket Player", "Mumbai", "India"));
dataBeanList.add(produce("Michael Schumacher", "F1 Racer", "Cologne", "Germany"));

return dataBeanList;
}

private DataBean produce(String name, String occupation, String place, String country) {
DataBean dataBean = new DataBean();

dataBean.setName(name);
dataBean.setOccupation(occupation);
dataBean.setPlace(place);
dataBean.setCountry(country);

return dataBean;
}
}


And below is the main class file, which gets the java bean collection from the class (with business logic) and passes it to the Jasper report engine, to generate the report:

package com.chetty.reporting.engine;

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import com.chetty.reporting.beans.DataBean;
import com.chetty.reporting.business.DataBeanMaker;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.xml.JRXmlLoader;

public class Reporter {
@SuppressWarnings("unchecked")
public static void main(String[] args) throws Exception {
InputStream inputStream = new FileInputStream ("reports/test_jasper.jrxml");

DataBeanMaker dataBeanMaker = new DataBeanMaker();
ArrayList dataBeanList = dataBeanMaker.getDataBeanList();

JRBeanCollectionDataSource beanColDataSource = new 
JRBeanCollectionDataSource(dataBeanList);

Map parameters = new HashMap();

JasperDesign jasperDesign = JRXmlLoader.load(inputStream);
JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, beanColDataSource);
JasperExportManager.exportReportToPdfFile(jasperPrint, "c:/reports/test_jasper.pdf"); 
}
}


To design the jasper report design file, you can either use iReport or the JasperAssistant Plugin for Eclipse. I used iReport, as it has more features and options. You can find the jasper report design file here: test_jasper.jrxml

When you run the 'Reporter' class, the following pdf file is generated:

Test Jasper

You can find all the source files here: jaspertest

Seam - Load i18n Messages From Database

In some of the JavaEE web applications, it might be a requirement for you, to load internationalization (i18n) messages from database, instead of the usual way of using 'Resource Bundles'. Seam is a pretty good and extensible framework. It provides you an option to override the built-in 'ResourceLoader' functionality and provide your custom logic. Below is the code for the Java class, which extends the Seam's 'ResourceLoader' component and loads i18n messages from the database:



This component is instantiated, only if the user is authenticated, as the annotations show that it depends on the 'Identity' component. Apart from this, in the overridden methods, I'm getting the 'User' component (which holds the logged-in user details, from database) and loading messages from database (for whatever his/her settings are).

Autoboxing In Java & Bug Patterns

Consider the following example:

1) Some Java Bean:

public class SomeBean implements Serializable {
private int someInt;

public int getSomeInt() {
return this.someInt;
}

public void setSomeInt(int someInt) {
this.someInt = someInt;
}
}



2) And somewhere in some class (with business logic), you have this:

HashMap<String, Integer> someMap = new HashMap<String, Integer>();


...and somewhere down the line, you find a code statement like this:

someBean.setSomeInt(someMap.get("someString"));


The above code statement works fine, when there are no 'null' values. But if there is a null value for some key, it fails.....because 'AutoBoxing' throws a NullPointerException when the above code statement tries to unbox a 'null' value.

So, the immediate solution for that would be something like:

Integer someInt = someMap.get("someString");

someBeam.setSomeInt((someInt != null) ? someInt : 0);