Planet Jaspersoft

January 17, 2014


First question which comes to mind after coming across this word Scriptlet is that does it have any relationships with scripts, if yes then what scripts, the answer  to this question is No it does not have any relation with scripts.    Scriptlets basically act as an interface between the Jasper Reports and Java. It provides much of flexibility to the reporting as now we can introduce user defined functions.

Scriptlet is nothing but a java class which is extended with either
1. net.sf.jasperreports.engine. JRAbstractScriptlet
2. net.sf.jasperreports.engine.JRDefaultScriptlet.

Now we need to identify which class we need to extend based upon the usage, JRAbstractSriptlet contains a number of abstract methods that must be overridden in every implementation, developer must implement all the abstract methods whereas JRDefaultScriptlet contains default empty implementations of every method in JRAbstractScriptlet, a developer is only required to implement those methods he/she needs for their project.

Now following listed are the methods that will be called by the report engine at the appropriate time, during report filling phase.

public void beforeReportInit()
Called before report initialization.
public void afterReportInit()
Called after report initialization.
public void beforePageInit()
Called before each page is initialized.
public void afterPageInit()
Called after each page is initialized.
public void beforeColumnInit()
Called before each column is initialized.
public void afterColumnInit()
Called after each column is initialized.
public void beforeGroupInit(String groupName)
Called before the group specified in the parameter is initialized.
public void afterGroupInit(String groupName)
Called after the group specified in the parameter is initialized.
public void beforeDetailEval()
Called before each record in the detail section of the report is evaluated.
public void afterDetailEval()
Called after each record in the detail section of the report is evaluated.



Except these we can also use User defined custom functions, I have already posted about them in my previous post here is the link-

Few important facts which need to be kept in mind using scriptlets are-
  1. When we do a System.out.println in any of the function then it does not directly print in the report, many a times people have some misconception but to remind System.out.println  is a console command and prints the value in the Report console, that is called the Report output window.
  2.  These functions are fired when the Jasper Print object is created, and it is created when a JRXML runs.


Now after creating our scriptlet classes and packaging  it into a jar file we are ready to use it in our Jasper Report created either in iReport or JasperSoft Studio.

Follow the following  steps to implement scriptlets in iReport
  1.  Add the Scriptlet jar file in the classpath by clicking on the Tools(Menu Bar) àOptions àClasspath Tab  and add the Jar file here.
  2.  Locate the Report Inspector Window
  3.  There is a node called Scriptlet, expand the node and we could see REPORT
  4.  You can create a another scriptlet label by right clicking the scriptlet label and then select Add
  5. Now locate the new element called Scriptlet1 under the node SCRIPTLET. (Check Fig-1)
  6.  Navigate to the properties of the Scriptlet1 there could be seen Name, Scriptlet Class and Description.
  7. Now you can enter the desired name for the scriptlet.
  8.  Scriptlet Class  is the fully qualified path of the scriptlet class in the JAR File.
  9.  Description is for the describing the role of the scriptlet ( Check Fig-2)



Follow the following  steps to implement scriptlets in  JasperSoft Studio
  1.  Add the Scriptlet jar file in the classpath by clicking on the Project(Menu Bar) àProperties, then select Java Build Path and external JAR File.
  2.  Locate the Outline window
  3.  There is a node called Scriptlet, expand the node and we could see REPORT_SCRIPTLET
  4.  You can create a another scriptlet label by right clicking the scriptlet label and then select Create Scriptlet (As in Fig 1)
  5. Now locate the new element called Scriptlet_1 under the node SCRIPTLETS.
  6.  Navigate to the properties of the Scriptlet_1 there could be seen Name, Class and Description.
  7. Now you can enter the desired name for the scriptlet.
  8.  Class is the fully qualified path of the scriptlet class in the JAR File.
  9.  Description is for the describing the role of the scriptlet.  (As in Fig 2)




Now until now we have success fully linked the scriptlet JAR with the iReport/JasperSoft Studio, now we need to understand that how can it be used in the report in order to get the desired outputs from the scriptlet or basically from the JAVA end.

To use the scriptlet functions in either iReport/ JasperSoft Studio following are the steps:
  1.  When we successfully create a new scriptlet under the scriptlet node, and define the properties of the scriptlet we could  see a new parameter formed under the Parameter node.
  2.  Locate the scriptlet parameter, you can find the parameter as by default it is named as ( {name of the scriptlet defined}_SCRIPTLET )
  3. Then wherever you want to use any function of the scriptlet, you just need to use as:
    ( {name of the scriptlet defined}_SCRIPTLET ).function Name


That is all we need to implement to use scriptlet in Jasper Reports, hope that the above description and methodology helps to grasp important points.

Here is a sample using the sample database, you can try the above customization too.

                                            ======SAMPLE========


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!!

January 17, 2014

December 20, 2013

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.,,,!!!

December 20, 2013

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.!!

December 20, 2013

December 9, 2013

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!!

December 9, 2013

December 5, 2013

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!!

December 5, 2013

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....!!

December 5, 2013

September 25, 2013

What you need to do is add a property to the fields you are wanting referenced. To add the class name you need to add net.sf.jasperreports.export.html.class and to include an id you need to addnet.sf.jasperreports.export.html.id as a property. As an example, below is a Text field that sets both:
<textField>
<reportElement uuid="2399e4ef-633c-4d17-b964-3e093ece1936" x="0" y="22" width="100" height="20">
<property name="net.sf.jasperreports.export.html.class" value="TEST"/>
<property name="net.sf.jasperreports.export.html.id" value="ID"/>
</reportElement>
<textElement markup="html"/>
<textFieldExpression><![CDATA[($F{field1}]]></textFieldExpression>
</textField>
In iReport you add these by selecting the field, and then in the properties window clicking the ellipses button next to Properties expressions. enter image description here
To include the link to the css file in the exported report, you need to set the value for theJRHtmlExporterParameter.HTML_HEADER parameter before exporting. Note the parameter is not the header in the sense of HTML (the contents of the head tag), but the header of the exported HTML report. Meaning it is what is first placed in the exported report to begin with, before including the report. The default that Jasper Reports uses is:
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<style type="text/css">
a {text-decoration: none}
</style>
</head>
<body text="#000000" link="#000000" alink="#000000" vlink="#000000">
<table width="100%" cellpadding="0" cellspacing="0" border="0">
<tr><td width="50%">&nbsp;</td><td align="center">
So you will need to modify this to include the link to your stylesheet by adding:
<link rel="stylesheet" type="text/css" href="<cssfile you want to point to>" />
to that in the appropriate place, which I think is inside the head tag, but if not move to appropriate area. So the java code would end looking something like:
<span style="font-size:11px;"><strong>JRHtmlExporter exporter = new JRHtmlExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRHtmlExporterParameter.HTML_HEADER,
"<html>"+
"<head>"+
" <title></title>"+
" <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>"+
" <link rel=\"stylesheet\" type=\"text/css\" href=\"css/jasper.css\" />"+
" <style type="text/css">"+
" a {text-decoration: none}"+
" </style>"+
"</head>"+
"<body text="#000000" link="#000000" alink="#000000" vlink="#000000">"+
"<table width="100%" cellpadding="0" cellspacing="0" border="0">"+
"<tr><td width="50%">&nbsp;</td><td align="center">");
exporter.exportReport();</strong></span>
Hope that it helps

September 25, 2013

Hi,
Suppose there are reports ABX,BNC and KLM  which have a same header and footer Then what you can do is create a master Report suppose mainReport, in there you add 3 subreports in the details section and then  and give the path of the the three reports ABX,BNC and KLM.  
You will have to specify the input control in the mainReport which user will have to enter suppose REPORT_SELECTION. Now you will have to decide the disctinct codes for each of the subreports . Suppose in this case I assign codes as :
ABX-1
BNC-2
KLM-3 
It  would accept the 1,2,3 from the user as input from the user in the parameter $P{REPORT_SELECTION} on the basis of this very choice of user it will trigger the presence or absence of the subreport.(Here 1,2,3 are just the cases could be anything like A,B,C or name itself like "ABX","BNC","KLM" )
Now to trigger the appearance of the subreport on the basis of this parameter $P{REPORT_SELECTION} ,which is entered by user we need to write the print when expression. The printwhen expression(which you would find in the property of the subreport element) you need to specify it as  : $P{REPORT_SELECTION}  ==1 (This will be for the report ABX ). So in this way the expression will vary. and you will get the desired subreport.
Please keep in mind that in the subreports header and footer is removed .
Here the input control REPORT_SELECTION is included on the mainReport so would be global too, and even you could accept the values of other parameters required by the reports and then pass it on to the subreports.So the parameters or input controls would be turned global too.
Hope that above explanation helps .


Happy Coding!!

September 25, 2013

I found a way for that by parsing the xml and then extracting the tags with parameter and retrieving the attribute name and class keeping in mind the check attribute  isForPrompting is blank or not present for the parameters , In this way I got the Hashmap of all the parameters with their types and I put that in the parameterMap and hence fulfilling the parameters in the jrxml dynamically


The jars need to be included are-
1.commons-beanutils-x.x.x.jar
2.commons-collections-x.x.x.jar
3.commons-digester-x.x.jar
4.commons-logging-x.x.jar
5.groovy-all-x.x.x.jar
6.iText-x.x.x.jar
7.jasperreports-x.x.x.jar
8.poi-x.x.jar(for excel export)
9.jfreechart-x.x.x.jar


Happy Coding!!

September 25, 2013

Pages

Feedback
randomness