Translate

Friday 20 December 2013

How to set datasource in iReport using a JRDatasource Provider as well as custom JRDataSource - Along with sample and Video Tutorial

JRDataSource is interface that represents the abstract representation of a JasperReports data source. All data source types must implement this interface.

We could create   JRDatasource using java code, but there is a stipulation that the class made as the datasource needs to implement JRDataSource interface.

Now, in this article I will talk about:
1. Setting the datasource using custom JRDataSource.
2. Setting the datasource using JRDataSourceProvider.

To start with, 
Setting the datasource using custom JRDataSource.
The prerequisites for the creating a custom datasource are:
1. JRDataSource
2. Factory class setting the JRDataSource.



Setting the datasource using JRDataSourceProvider
The prerequisites for the creating a custom datasource are:
1. JRDataSource
2. JRDataSourceProvider implemented class.


For showing setting of each of the methods I have created a youtube video.
                                                ==VIDEO LINK==

In the sample I have created, what I intend to do is that I want to know the names, is directory(boolean true/false) and the size on disk, of the folder whose path is passed in the constructor of the datasource. Now in my datasource I have 3 columns NAME, SIZE and IS_DIRECTORY.

In both the cases we need to create a JRDatasource class .. that is the class which implements JRDataSource, so in the sample it looks like this 

/**
* JR DataSource Class
* @author Ankur Gupta
*/
public class JRFileSystemDataSource implements JRDataSource {
File[] files = null;
int index = -1;
public JRFileSystemDataSource(String path) {
File dir = new File(path);
if (dir.exists() && dir.isDirectory()) {
files = dir.listFiles();
}
}

@Override
public boolean next() throws JRException {
index++;
if (files != null && index < files.length) {
return true;
}
return false;
}

@Override
public Object getFieldValue(JRField jrf) throws JRException {
File f = files[index];
if (f == null) {
return null;
}
if (jrf.getName().equals("name")) {
return f.getName();
} else if (jrf.getName().equals("IS_DIRECTORY")) {
return new Boolean(f.isDirectory());
} else if (jrf.getName().equals("totalSpace")) {
return new Long(f.length());
}
// Field not found...
return null;
}

/**
* This method is responsible for setting the field names in the provider.(Required for the provider)
* @return
*/
public static String[] fieldNames() {
String[] fieldNames = {"name", "IS_DIRECTORY", "totalSpace"};
return fieldNames;
}
}
CODE SCRIPTLET #1
The  fieldNames()  method is not required for custom JRDataSource , but is required for JRDataSource Provider.

Now for the custom JRDatasource
1. The JRDataSource as shown above.(Remove the last method not required.)
2. The Factory Class for the custom JRDataSource looks like.

/**
*
* @author Ankur Gupta
*/
public class FactoryClassDataSource {

/**
* Factory Class responsible for setting the JRdatasource.
* @return
*/
public static JRDataSource generateDS(){
return new JRFileSystemDataSource("Path of the desired folder");
}
}
CODE SCRIPTLET #2

This is it, now you can compile these two classes , and place the jar file in the class path.

Now for the  JRDatasource Provider.
1. The JRDataSource as shown as above in the code scriptet #1.
2. Next is the JRDataSourceProvider class shown as below.


/**
* JRDatasource Provider
* @author Ankur Gupta
*/
public class JRFileSystemDataSourceProvider implements JRDataSourceProvider{

@Override
public boolean supportsGetFieldsOperation() {
return false;
}

@Override
public JRField[] getFields(JasperReport jr) throws JRException, UnsupportedOperationException {

ArrayList fields = new ArrayList();
String [] fieldNames = JRFileSystemDataSource.fieldNames();
for (String s : fieldNames) {
JRDesignField field = new JRDesignField();
field.setName(s);
field.setValueClassName("java.lang.String");
fields.add(field);
}
return (JRField[]) fields.toArray(new JRField[fields.size()]);
}

@Override
public JRDataSource create(JasperReport jr) throws JRException {
return new JRFileSystemDataSource("Enter the path of folder");
}

@Override
public void dispose(JRDataSource jrds) throws JRException {
}

}
CODE SCRIPTLET #3

Now, you can compile the classes and get the jar and place it in the classpath of iReport.

This was the portion you need to complete in creating the JAR file, now we need to set the datasource in thr iReport .
For setting the datasource as custom JRDataSource, you need to enter the qualified path of the factory class. In iReport it looks like :

 
Custom JRDataSource

Now you need to create the fields in the iReport by doing a right click on the field node and remember that the name of the field should be same as in the datasource . In the sample we need to create 3 fields as  name, IS_DIRECRTORY,totalSpace. 
And then place these fields in the detail section of the report and then preview the report and then you could see the contents of the folder(In the sample the folder path is set to C drive.)

For setting the datasource as JRDataSourceProvider, you need to set datasource by selecting to create a new datasource of type JRDataSourceProvider. In the sample it looks like
JRDataSourceProvider

Now the difference in the custom JRDataSource and JRDataSource Provider is that in this function you will not be worried for creating the field  you could directly fetch it by going to the Report query, navigate to DataSource Provider tab and click on Get Fields from dataSource , it will display all the fields in case of this sample it look like :



You then use the fields in the report and you can obtain similar structure of folder.


Here is the sample ZIP file 

                                                              ==ZIP FILE==
This ZIP  file will contain
1, TestRun PDF
2. JRXMLs for both the custonm JRDataSource as well  as JRDataSource Provider
3, JAR file which is needed to be placed in the classpath of iReport.

You could follow the video and sample and learn how to set the datasource with JRDataSource easily.

Please put you questions or demands for clarification in the comments section below.

Happy Coding.,,,!!!

How to set JavaBean set as Datasource in iReports, along with a working sample.

Java beans are practically, classes that encapsulate many objects into a single object (the bean). This is pretty simple to create and could easily hold lots of data in them. They are serializable, have a 0-argument constructor, and allow access to properties using getter and setter methods.

In a nutshell, java bean is easy to use methodology to obtain data. Now the task in hand is that how to use this bean in our reports . For setting the bean in reports there are few prerequisites, 

  1. There should be a Bean class
  2. There should be a factory class which returns the collection/array of the beans
iReport provides two options, either it could read from collection of beans or array of beans. First of all we need a bean, so below is how the bean looks like.
/**
* Bean
*
* @author Ankur Gupta
*/
public class PersonBean {
private String name = "";
private int age = 0;
public PersonBean(String name, int age) {
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
}

Now you need to create a factory class which contains the function which returns the bean.There are two ways to do that :
1. Collection of bean

/**
* Responsible for filling values in the Bean and return it as collection of bean.
*
* @author Ankur Gupta
*/
public class TestFactory {

public static java.util.Collection generateCollection() {
// Creates the collection
java.util.Vector collection = new java.util.Vector();

// Adds the values in the bean and adds it into the collection
collection.add(new PersonBean("Ted", 20));
collection.add(new PersonBean("Jack", 34));
collection.add(new PersonBean("Bob", 56));
collection.add(new PersonBean("Alice", 12));
collection.add(new PersonBean("Robin", 22));
collection.add(new PersonBean("Peter", 28));

// returns the collection of beans.
return collection;
}
}
2. Array of Beans

/**
* Responsible for filling values in the Bean and return it as collection of bean.
*
* @author Ankur Gupta
*/
public class TestFactory {

// Creates the Arraylist
PersonBean[] list = new PersonBean[6];

// Adds the values in the bean and adds it into the Array
list[0]= (new PersonBean("Ted", 20));
list[1]= (new PersonBean("Jack", 34));
list[2]= (new PersonBean("Bob", 56));
list[3]= (new PersonBean("Alice", 12));
list[4]= (new PersonBean("Robin", 22));
list[5]= (new PersonBean("Peter", 28));

// returns the Array of beans.
return list;
}
}

Now, we need to compile these files  and put the generated jar file in the classpath of the iReport.

Next we need to set the datasource, by adding datasource Java Bean set as datasource and fill in the Factory class as well as the function which generates the bean as array or collection, whichever suits our purpose.

In this case:
Factory class  :  javabeanset.TestFactory
Generating function: generateBeanArray/generateCollection (based upon collection or array)
Below are some screen shots.

Array of JavaBeans



Collection of JavaBeans

You can follow the video link for setting javabeans as datasource.  Here is the Youtube video made by me which gives a complete walkthrough to set the datasource as javabean with the help of a sample report also.

                                                                   ==The video link==



I have made a sample in the video itself here is zip file which contains:
1, Jar File (You need to place this in your classpath)
2. JRXML File
3. Set datasource as shown in the video and insert the values provided in the above screenshots.
4. Test Run PDF(PDF output of the Sample report)
                                                            == ZIP Sample File ==
Follow all the steps in order to get the sample working.


Hope this clears your doubt for this topic. Still if you face any issues or problems then you can add a comment below .

Happy Coding.!!

Thursday 12 December 2013

Introduction to jasper Reports .

JasperReports is an open source Java reporting tool that can write to a variety of targets, such as: screen, a printer, into PDF,HTMLMicrosoft ExcelRTFODTComma-separated values or XML files.

It can be used in Java-enabled applications, including Java EE or web applications, to generate dynamic content. It reads its instructions from an XML or .jasper file.
JasperReports is part of the Lisog open source stack initiative.

Jasper Reports is quite handy , in huge projects which could summarize the whole project in form of few reports .


I have recently developed a great interest for jasper reports and , stay tuned to the blog and I would post some great tricks and solutions to the common problems.
To know more about this check out a video on this topic which I have created.
Introduction to jasper reports.



Please provide your suggestions and feedback.

Monday 9 December 2013

How to write conditional query in iReport using parameters

Inside iReport creating static query that is, writing a simple static query in the the Query executor and set it up running is quite simple and too monotonous.

The real challenge arrives in actually changing the query of the report dynamically based upon some condition, this could be achieved with a simple implementation of parameters.

Following are the steps to use the conditional SQL Statements.

1. Create a parameter if you want user triggered change of the SQL Query , if not user triggered then it must be based upon the field, so that can be used too.

2. Create a different parameter which will be responsible for triggering the changed query based upon the condition.

3. Now identify the condition which is responsible for changing the query,

4. The parameter which contains the conditional SQL switching should have the property "Used as prompt" turned off and the condition should be placed in the default value.

5. Then after setting this, move onto set the Report Query Expression. Now see the dynamism of the query could be provided to the whole query or a portion of query so accordingly place the expression .The parameter containing the conditional expression should be used as the expression and it should be denoted as $P!{name of the param containing expression}
Here is a little illustration
Suppose there is a parameter called $P{TestParamSQL}, the prompt should be turned off as we are setting the value at runtime checking the value of the $P{TEST_PARAM}. 
Set the default value of the parameter as:
For a single condition 
$P{TEST_PARAM}.equals("test")
? " select SQL query"
: " else SQL select query"
For a multiple condition 

$P{TEST_PARAM}.equals("test")
? " select SQL query"
: $P{TEST_PARAM}.equals("test1")
? " SQL select query"
: $P{TEST_PARAM}.equals("test2")
?" SQL Query"
: "else SQL Query"

Now in the iReport Query executor you should give the following expression$P!{TestParamSQL} 

Do take care that the dependent parameter $P{TEST_PARAM}. should be set before the $P{TestParamSQL} else would throw a null pointer exception.
Another thing which should be kept in mind is that the query given in the quotes in the expression should be syntactically correct, that is the SQL in as the string should be correct.

Here is a running sample-

Prerequesites-
1. JRXML File
2. PDF Export

Steps to set up this Sample Report.
1. Then you must choose Sample Database in the datasource
4. Then next you need to activate the the sample database from Help(in the iReport Menu bar)---> Samples---->Run Sample Database
5. Then Run the  Report

There is a PDF export also which would show exactly how the report looks(The input value is employeeId= 2).

Please put in you queries/suggestions, I will be more than happy to know.
Cheers .. Happy Coding!!

Friday 6 December 2013

How to add user defined function in iReport

In iReport it is very important to have a knowledge of integrating the Java code with the Jasper Report as the things do easier and provide lot of versatility to the report. Usage of Java Code in iReport is achieved by usage of scriptlets.

Scriptlets acts as bridge to get the Java Code in the iReport, scriptlet is a Java class which extends the JRDefaultScriptlet, and in this class we could write our user defined functions which later could be easily accessed in the report.


There are few simple steps which could be followed in order to run the User Defined Functions.

1. Tools(in the iReport Menu bar ) ----->  Options -----> Click on Claspath Tab ------> ADD Jar -----> choose the Jar file ( This JAR is made on building the project containing the scriptlet )
2. Then in the iReport there is a node called Scriptlet in the Report Inspector ( By Default on left ).
3. Go to the properties of the scriptlet , there is a property called 'Scriptlet Class'
4. Key in the the location of the scriptlet class where the user defined function is present  for instance:
com.jasper.scriptlet.TestScriptlet -- In this scenario TestScriptlet is my class where the user defined function is written.
(Remember the the class containing the user defined function needs to be extended by the JRDefaultScriptlet )
5. Now you are set to use it in the report, to use in the iReport you need to use the reference of a parameter called $P{REPORT_SCRIPTLET} , this is a predefined parameter which could come handy.
 6. In order to use the user defined in the iReport, in the the expression would be given as 
 $P{REPORT_SCRIPTLET} .userDefinedFun() -  This is a user defined function which returns values from the scriptlet.
$P{REPORT_SCRIPTLET} .userDefinedFun($F{field})  - This is also a user defined function which returns values from scriptlet, but has an input parameter from the field in the report. So this gives fluidity of the Java from Jasper to Java code.

Here is a running sample-

Prerequesites-
1. JRXML File
2. Jar File
3. PDF Export 

Steps to set up this Sample Report.
1. Tools(in the iReport Menu bar )-----> Options ----- > Click on Claspath Tab ------> ADD Jar -----> choose the Jar file
2.  Then navigate to Scriptlet node in the Report inspector, and then modify the property Scriptlet Class to 'pkg1.ConvertToWord'
3. Then you must choose Sample Database in the datasource
4. Then next you need to activate the the sample database from Help(in the iReport Menu bar)---->Samples---->Run Sample Database
5. Then Run the  Report
There is a PDF export also which would show exactly how the report looks.

Please put in you queries/suggestions, I will be more than happy to know.
Cheers .. Happy Coding!!

How to format number when running report from Java code in iReport

There is always ambiguity that how could you format the data conditionally or at runtime of the report based upon the data in the iReport.

iReport does provides a robust methodology to format the values of the textfield but sometime you require data to be formatted conditionally or needs to be formatted not at the design time but needs to be modified dynamically, that is, based upon the data coming from the datasource or upon the user choice. So this particular article is dedicated to cater this very problem.

The formatting done in the iReport is report specific it like extra utility , of providing the pattern provided by the iReport. When you run that in java code the formatting is removed. So what you can do for the java code is that you could use:
 new java.text.DecimalFormat("pattern").format(put the field here)

So to provide similarity in the report and in the Java code what can be done is that you could replace the expression of the text field with the same expression and the discrepancy could be easily taken care off.In that case the expression would look something like this
 new java.text.DecimalFormat("¤ #,##0").format($F{VALUE})   
Now here the in the field expression easily , any field or parameter could be put and same would work fine for java code too,
Here any pattern can be put, and formatting could be applied to any described field.


Cheers Happy Coding....!!