Tuesday, August 19, 2014

Spring MVC + BIRT + Scripted Data Source

One fine morning I was looking for birt report implementation where in alike jasper the framework should be able to receive a populated collection/s of POJOs and render the same in report.

The quest gave me a real hard time to find an effective and efficient solution and finally yoooooo..EUREKA!!!!!!!!!!!!!

The solution was using a scriped data source in BIRT. But after finding a lil light in a whole blackhole darkness finally I found something which was relevant. I was happy but woooo then I realized it was actually sign of a coming trouble.
I was already running on a fire fighting mode and pressure situation, albeit I was able to find out a way of using scripted data source to populate a collection/s of POJOs to render the same on report I lost another day to find how to do this task or more specifically a step through example of this.

After questing a lot on google I was finally able to club some code from different articles/documentations to implement a final solution. And that's the reason I started writting this out to help somebody pulling hair to find such solution on web.

Here are the steps to use scripted data source and exploit spring's service layer to populate POJOs and render a report.

Assuming the reader has a background of spring mvc, BIRT, and has BIRT installation in existing web application & BIRT eclipse report designer.

1. Create a Simple Java classes.

POJOs
public class Employee {
 
 private String name;
 private String dob;
 private String address;
 private String mobile;
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public String getDob() {
  return dob;
 }
 public void setDob(String dob) {
  this.dob = dob;
 }
 public String getAddress() {
  return address;
 }
 public void setAddress(String address) {
  this.address = address;
 }
 public String getMobile() {
  return mobile;
 }
 public void setMobile(String mobile) {
  this.mobile = mobile;
 }

}
     



Service:



public interface EmployeeService extends GenericService{

   List getReportObjects(String departmentId);

}

@Service //Spring bean configuration annotation
public class EmployeeServiceImpl extends GenericServiceImpl implements EmployeeService {

  public List getReportObjects(String departmentId){
  System.out.printLn("Department Id is just how to pass a parameter from report to spring layer to filter results "+departmentId);
  List list = new ArrayList();
  
  Employee e = new Employee();
  e.setName("anant");
  e.setDob("26-Jun-1982");
  e.setAddress("my Address 1");
  e.setMobile("9912345667");
  list.add(e);
  e = new Employee();
  e.setName("Ashay");
  e.setDob("26-Jul-1984");
  e.setAddress("my Address 1");
  e.setMobile("9912345667");
  list.add(e);
  e = new Employee();
  e.setName("anant");
  e.setDob("26-Jun-1982");
  e.setAddress("my Address 1");
  e.setMobile("9912345667");
  list.add(e);
  return list;
 }
}



2. Use eclipse birt plugin to create a report design file test.rptdesign
3. Under "Data Explorer ---> Data Sources --> Create New Data Source ---> Scripted Data Source ---> Finish".


4. Under "Data Explorer ---> Data Sets --> Create New Data Set ---> Next --->".
5. On next screen of data set creation wizard Click on "Add" you need to create number of output columns this data set should have.
6. "Column Name" element and "Display Name" element are the key element. String which you will enter in "Column Name" will be used to later in article to store data in data set elements.

7. Select ""Data Explorer ---> Data Sets" and select "script" tab.
8. Under "script --> open" use following Rhino script to get spring application context instance and an instance of you service class bean.


importPackage(Packages.org.springframework.context);
importPackage(Packages.org.springframework.web.context.support );
//ServletContext
var sc = reportContext.getHttpServletRequest().getSession().getServletContext();
//ApplicationContext 
var spring = WebApplicationContextUtils.getWebApplicationContext(sc);
//your spring bean 
var employeeService = spring.getBean("employeeService");
//Load the rows (Note here is where you are able to pass your parameter into the Java layer)

//Get employee list from your spring service bean for a given department Id
var data = employeeService.getReportObjects(params["departmentId"]);

dataIterator = data.iterator();


9. You must be wondering what is "params["departmentId"]"? This is a report parameter which will be created under "Data Explorer --> report Parameters" and will be entered by user.
10. Under "script --> fetch" use following Rhino script to fetch and assign data in data set.

 if(dataIterator.hasNext()){
 var object = dataIterator.next();
 //name,dob,address,mobile will be "Column Name" in output columns window in data set creation wizard as discussed earlier
 // Please do not refer display names
    row["name"] = object.getName(); //Getter of Employee Domain object
    row["dob"] = object.getDob();
    row["address"] = object.getAddress();
    row["mobile"] = object.getMobile();
    return true;
 }else{
  return false;
 }

11. Drag your data set on report layout and you are good to go.
12. All remains is a beutification part and I am very poor in color selections and can not help you out there

3 comments:

  1. Jun 15, 2016 1:09:19 PM org.eclipse.birt.report.engine.script.internal.DtEScriptExecutor handleJS
    WARNING: Fail to execute script in function __bm_OPEN(). Source:
    ------
    " + importPackage(Packages.org.springframework.context);
    importPackage(Packages.org.springframework.web.context.support );
    var sc = reportContext.getHttpServletRequest().getSession().getServletContext();
    var spring = WebApplicationContextUtils.getWebApplicationContext(sc);
    var employeeService = spring.getBean("dashboardService");
    var data = dashboardService.getTrendingScan();
    dataIterator = data.iterator(); + "
    -----
    A BIRT exception occurred. See next exception for more information.
    TypeError: Cannot call method "getBean" of null (/report/data-sets/script-data-set[@id="27"]/method[@name="open"]#5)
    org.eclipse.birt.data.engine.core.DataException: Fail to execute script in function __bm_OPEN(). Source:

    ReplyDelete