Sunday, December 21, 2008

Extending the BIRT Google Spreadsheet ODA

I've extended the Dataset UI in the BIRT Google ODA that Scott Rosenbaum posted in BIRT World . The Google ODA utilizes the Google Spreadsheet API and I've extended the UI, by giving a graphical user interface in the custom Dataset page.

From OpenReports



From OpenReports



The Dataset page now initializes a "Google Spreadsheet Model" which contains the
a drop down of the list of available Spreadsheets in the model. Selecting a given
spreadsheet will list the selected Worksheets for that Spreadsheet, and in turn
display the Worksheet-based feed in the form of
http://spreadsheets.google.com/feeds/worksheets/key/visibility/projection
I've added a few helper classes to initialize the Spreadsheet in the Dataset UI.
You can actually test this out as I've included the modifieid source code,
and both the designer and ui jars.

Simply take the files:
1. org.eclipse.datatools.connectivity.oda.google.ui_1.0.0.jar
(Designer UI plugin)
2. org.eclipse.datatools.connectivity.oda.google_1.0.0.jar
(Runtime ODA Plugin)
and place it in the plugins directory of BIRT.

This has only been tested in BIRT 2.3.1, and I currently used JDK 6 to build these jars.
Thanks again toScott Rosenbaum for supplying the initial source code. This example actually helped
me develop my own custom ODA for work.

You can download the ODA Plugin here: google-spreadsheet-oda_1.0.0.zip

Friday, December 19, 2008

Integrating the Birt Viewer into OpenReports using Struts Part 2

In the last mini-tutorial, we've integrated the BIRT Ajax Viewer 2.3.1 servlet
into OpenReports 3.1, and updated the BIRT libraries from 2.3 to 2.3.1.
In this section, we wrap up the tutorial by basically modifying
the OpenReports UI such that when a BIRT Report is run, we'll get
a UI that allows the additional enhancements:

1. Execute the current BIRT rptdesign report using the BIRT Viewer in the Same Window
2. Execute the current BIRT rptdesign report using the BIRT Viewer in a new Window
Futhermore , we can specify if the BIRT Viewer will be using the Full Window,
or if it will be embeded showing us the Report Name and Path to the Design file.
3. Adding Postscript and Word Export options for BIRT Reports (OpenReports is missing this)

Here are some screenshots of the enhancement and a link to the modified source code here-  openReportsWithBIRT2.3.1.zip  
From OpenReports


From OpenReports



I've highlighted the Java files that I've modified using the original OpenReports source code. The perspective below is from Eclipse Ganymede 3.4 which I'm working with.

From OpenReports


We modify struts.xml by adding a new Action called
birtRunReport and create an action class in org.efs.openreports.actions.BirtReportAction.java that extends ActionSupport.
(I've basically mimicked what I've seen with the existing OpenReport Actions
since I'm fairly new to Struts )







ReportOptions.jsp


reportRun


queryReport


chartReport


jxlsReport


jpivot.action


reportSchedule.action


listScheduledReports.action


birtRunReport





BirtViewer.jsp




Here's the BirtReportAction.java class that I wrote that is used in BirtViewer.jsp where we use
the birt tag library (birt.tld) to run the Viewer.
The birt_isHostPage is an attribute used to indicate if the Viewer will use the whole page.


package org.efs.openreports.actions;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

import java.util.Date;
import java.util.Map;
import org.apache.log4j.Logger;
import org.efs.openreports.ORStatics;
import org.efs.openreports.engine.BirtReportEngine;
import org.efs.openreports.engine.ReportEngine;
import org.efs.openreports.engine.ReportEngineHelper;
import org.efs.openreports.engine.input.ReportEngineInput;
import org.efs.openreports.objects.ORProperty;
import org.efs.openreports.objects.Report;
import org.efs.openreports.objects.ReportLog;
import org.efs.openreports.objects.ReportUser;
import org.efs.openreports.providers.DataSourceProvider;
import org.efs.openreports.providers.DirectoryProvider;
import org.efs.openreports.providers.PropertiesProvider;
import org.efs.openreports.providers.ReportLogProvider;
import org.efs.openreports.util.LocalStrings;
import org.efs.openreports.util.ORUtil;

public class BirtReportAction extends ActionSupport
{
private static final long serialVersionUID = 7473180642590984527L;
protected static Logger log = Logger.getLogger(BirtReportAction.class);
private Map<Object, Object> session;
private String birt_isHostPage; // see birt.tld

private DirectoryProvider directoryProvider;

private Report report;
private String designFile;

public String execute() throws Exception
{
report = (Report) ActionContext.getContext().getSession().get(ORStatics.REPORT);
designFile = directoryProvider.getReportDirectory() + report.getFile();
log.info("BirtReportAction chained - directoryProvider:" + directoryProvider.getReportDirectory());
log.info("BIRT Report Action , Report File:" + report.getFile() );
log.info("BIRT Report Action , Report Name:" + report.getName() );
log.info("BIRT Report Action ), DESIGN FILE:" + designFile );
log.info("BIRT Report Action , birt_isHostPage:" + birt_isHostPage);
return SUCCESS;
}

public String getDesignFile()
{
return designFile;
}

public Report getReport()
{
return report;
}

public void setBirt_isHostPage(String birt_isHostPage)
{
this.birt_isHostPage = birt_isHostPage;
}

public String getBirt_isHostPage()
{
return birt_isHostPage;
}



public void setDirectoryProvider(DirectoryProvider directoryProvider)
{
this.directoryProvider = directoryProvider;
}

@SuppressWarnings("unchecked")
public void setSession(Map session)
{
this.session = session;
}

}

There are 2 JSP's that need to be added/modified that contribute to the UI.
The first is ReportOptions.jsp which is the result of the action associated
with clicking on a BIRT Report.

<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ taglib uri="http://displaytag.sf.net" prefix="display" %>
<?xml:namespace prefix = s /><s:include value="Banner.jsp"></s:include>
<s:actionerror></s:actionerror>
<script language="JavaScript" type="text/JavaScript">
function setDefaultExportType()
if (optionsForm.exportType.length)
{
optionsForm.exportType[0].checked=true
}
else
{
optionsForm.exportType.checked=true
}
}

function setBlankTarget()
{
optionsForm.target="_blank";
}

function setNoTarget()
{
optionsForm.target="";
}


function setBlankTargetBirt()
{
birtForm.target="_blank";
}

function setNoTargetBirt()
{
birtForm.target="";
}

</script>

<div align="center">

<a class="back-link img-report-small" href="http://www.blogger.com/reportList.action"><s:text name="link.back.reports"></s:text></a>
<a class="back-link img-group-small" href="http://www.blogger.com/reportGroup.action"><s:text name="link.back.groups"></s:text></a>





<div class="img-export important" id="instructions" style="WIDTH: 70%">
<s:text name="reportOptions.title"></s:text> <s:property value="report.name"></s:property>
</div>

<form class="dialog-form" style="WIDTH: 75%" name="optionsForm" action="reportOptions.action">
<table class="dialog">
<tbody><tr>
<td class="boldText"><s:text name="reportOptions.exportType"></s:text></td>
<s:if test="report.pdfExportEnabled">
<td>
<input type="radio" value="0" name="exportType">PDF
</td>
</s:if>
<s:if test="report.htmlExportEnabled">
<td>
<input type="radio" value="2" name="exportType">HTML
</td>
</s:if>
<s:if test="report.csvExportEnabled">
<td>
<input type="radio" value="3" name="exportType">CSV
</td>
</s:if>
<s:if test="report.xlsExportEnabled report.jXLSReport">
<td>
<input type="radio" value="1" name="exportType">XLS
</td>
</s:if>
<s:if test="report.rtfExportEnabled">
<td>
<input type="radio" value="5" name="exportType">RTF
</td>
</s:if>
<s:if test="report.textExportEnabled &amp;&amp; report.birtReport">
<td>
<input type="radio" value="6" name="exportType">Text
</td>
</s:if>
<s:if test="report.excelExportEnabled">
<td>
<input type="radio" value="7" name="exportType">Excel
</td>
</s:if>
<s:if test="report.jasperReport &amp;&amp; report.imageExportEnabled">
<td>
<input type="radio" value="4" name="exportType">Image
</td>
</s:if>
<!-- enhancements to support BIRT export types for BIRT 2.3.1 -->
<s:if test="report.birtReport">
<td>
<input type="radio" value="9" name="exportType">MS DOC
</td>
<td>
<input type="radio" value="10" name="exportType">PPT
</td>
<td>
<input type="radio" value="11" name="exportType">Postscript
</td>
</s:if>

<script language="JavaScript" type="text/JavaScript">
setDefaultExportType()
</script>
</tr>
</tbody></table>




<div class="button-bar" id="buttons">

<input class="standardButton" onclick="setNoTarget()" type="submit" value="<s:text name=" name="submitRun">">
<input class="standardButton" onclick="setBlankTarget()" type="submit" value="<s:text name=" name="submitRun">">
<s:if test="user.scheduler">
<input class="standardButton" onclick="setNoTarget()" type="submit" value="<s:text name=" name="submitSchedule">">
</s:if>


<s:if test="report.birtReport">
<td>
<input class="standardButton" onclick="setBlankTarget()" type="submit" value="<s:text name=" name="submitBirtReport">">
</td>
</s:if>

</div>

</form>




<!-- BIRT AJAX Viewer Form -->
<s:if test="report.birtReport">
<div class="img-export important" id="instructions" style="WIDTH: 70%">
BIRT AJAX-Based Report Viewer Output
</div>

<form class="dialog-form" style="WIDTH: 75%" name="birtForm" action="reportOptions.action">
<table class="dialog">
<tbody><tr>
<td class="boldText"><s:text name="View Options"></s:text></td>
<td>
<input type="radio" value="true" name="birt_isHostPage">Full Window
</td>
<td>
<input type="radio" value="false" name="birt_isHostPage">Embedded
</td>
</tr>
</tbody></table>



<div class="button-bar" id="buttons">
<input class="standardButton" onclick="setNoTargetBirt()" type="submit" value="<s:text name=" name="submitBirtReport">">
<input class="standardButton" onclick="setBlankTargetBirt()" type="submit" value="<s:text name=" name="submitBirtReport">">
</div>
</form>

</s:if>

</div>
<s:include value="Footer.jsp"></s:include>





The second JSP we require to modify is BirtViewer.jsp . This is the page
that calls the BIRT Viewer. We use the BIRT Tag library to show the viewer. You can read about it here from BIRT Eclipse site under Using the BIRT Report Viewer


<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ taglib uri="http://displaytag.sf.net" prefix="display" %>
<%@ taglib uri="/birt.tld" prefix ="birt" %>
<!-- refer here for documentation http://struts.apache.org/2.x/docs/tag-reference.html -->

<html>
<head>


<link href="styles/iv/index.css" type="text/css" rel="stylesheet">
<link href="http://www.eclipse.org/images/eclipse.ico" type="image/x-icon" rel="shortcut icon">
<style>
.warningMessage { color:red; }
</style>



<s:textfield label="Report Name" name="report.file"></s:textfield>


<s:textfield label="Design File Path" name="designFile"></s:textfield>
<?xml:namespace prefix = birt /><birt:viewer id="birtViewer" format="html" width="700" height="450" pattern="frameset" reportdesign="${designFile}" ishostpage="${birt_isHostPage}">
</birt:viewer>



That's the core of the work. There are other a few other Java files
that need to be modified to get this example working - they only
involve very minor changes, so I'll just present some snit bit code Fragments.

In org.efs.openreports.actions.ReportOptionsAction.java,
we need to pass the attribute birt_isHostPage and execute
th Birt Viewer action.


if (report.isBirtReport() && !submitSchedule)
{
log.info("This is a BirtReport (aong)");
if(submitBirtReport) {
log.info("Submitting BIRT REPORT(aong)");
if (birt_isHostPage != null){
log.info("birt_isHostPage" + birt_isHostPage);
} else {
log.info("birt_isHostPage" + birt_isHostPage);
}

return ORStatics.BIRT_VIEWER_ACTION;
}
}



The action is defined in org.efs.openreports.ORStatics.java
as

public static final String BIRT_VIEWER_ACTION = "birtReport";


In org.efs.openreports.ReportConstants, we need
to define the new Export Types "DOC", "PPT", and "POSTSCRIPT".

Lastly, we need to add support to the Export types that OpenReports does not
support that the BirtEngine handles in org.efs.openreports.engine.BirtReportEngine.java


if (input.getExportType() == ExportType.DOC)
{
output.setContentType(ReportEngineOutput.CONTENT_TYPE_MSWORD);
renderOption.setOutputFormat("doc");
}

else if (input.getExportType() == ExportType.PPT)
{
output.setContentType(ReportEngineOutput.CONTENT_TYPE_POWERPOINT);
renderOption.setOutputFormat("ppt");
}

else if (input.getExportType() == ExportType.POSTSCRIPT)
{
output.setContentType(ReportEngineOutput.CONTENT_TYPE_POSTSCRIPT);
renderOption.setOutputFormat("postscript");
}

.

That's about it - bundle the package up , build it and deploy it to Tomcat.

I've enclosed the source code here.  There are two folders enclosed.
1. src folder -> contains all java classes, struts.xml
2. WebRoot -> Tomcat context files.  

*Note* - I've stripped down the WebRoot/WEB-INF folder.
It is missing the lib folder jars that you can get from openReports
(OpenReports 3.1) and the platform folder which contains the BIRT plugins which you can
get from BIRT .   (BIRT 2.3.1 Runtime).  

Download link: openReportsWithBIRT2.3.1.zip  (src files only)

Integrating the BIRT Viewer into OpenReports using Struts Part 1

I wanted to integrate the BIRT 2.3.1 Viewer into OpenReports as a mini-project. The implementation is rather simple, and loose as this was done for a hobby (so nothing professional here) - but hopefully this will help someone out. The final result allows a user in OpenReports to view BIRT reports in the Ajax Based BIRT Web Viewer. I simply utilized the birt tag libraries to deploy the viewer using a simple jsp page.

Since OpenReports uses the Apache Struts 2 Framework, I did a little bit of simple reading on how to configure struts.xml.

Here, I'll give a mini-tutorial on how to get the BIRT Viewer into OpenReports.
The first part of this tutorial will show you how to integrate the viewer into open reports.
I'm using OpenReports 3.1 as of this post and BIRT 2.3.1

1. Download the OpenReports zip file here
2. Download the BIRT 2.3.1 run-time from BIRT here (birt-runtime-2_3_1.zip)
3. Next you'll need to update the BIRT Libraries in OpenReports to the one
which you want to deploy and at the same time we need
to integrate the BIRT Viewer by making some changes to the web.xml descriptor file
(In this tutorial, we'll be using BIRT 2.3.1)

a. We'll first copy the comlete directory that contains the BIRT Viewer located in
birt-runtime-2_3_1\WebViewerExample\webcontent
to
openreports-tomcat\openreports\WebRoot\webcontent

b. Next take the jar files from the BIRT Web Application in
birt-runtime-2_3_1\WebViewerExample\WEB-INF\lib
and carefully copy and replace the old BIRT libraries (2.3.) in
Open reports found in openreports-tomcat\openreports\WebRoot\WEB-INF\lib

b. We need to also port the plugins, tlds, and web.xml to Open Reports.
Copy and integrate the following files from BIRT :

birt-runtime-2_3_1\WebViewerExample\WEB-INF\platform
birt-runtime-2_3_1\WebViewerExample\WEB-INF\tlds
birt-runtime-2_3_1\WebViewerExample\WEB-INF\*.xml
birt-runtime-2_3_1\WebViewerExample\WEB-INF\server-config.wsdd
birt-runtime-2_3_1\WebViewerExample\WEB-INF\viewer.properties

to

openreports-tomcat\openreports\WebRoot\WEB-INF\
For the OpenReport web.xml file, make sure you add the following entries





BIRT_VIEWER_LOCALE
en-US




BIRT_VIEWER_TIMEZONE





BIRT_VIEWER_WORKING_FOLDER





BIRT_VIEWER_DOCUMENT_FOLDER





WORKING_FOLDER_ACCESS_ONLY
false




BIRT_VIEWER_IMAGE_DIR





BIRT_VIEWER_LOG_DIR





BIRT_VIEWER_LOG_LEVEL
WARNING




BIRT_VIEWER_SCRIPTLIB_DIR





BIRT_RESOURCE_PATH





BIRT_VIEWER_MAX_ROWS





BIRT_VIEWER_MAX_CUBE_ROWLEVELS



BIRT_VIEWER_MAX_CUBE_COLUMNLEVELS





BIRT_VIEWER_CUBE_MEMORY_SIZE





BIRT_OVERWRITE_DOCUMENT
true




BIRT_VIEWER_CONFIG_FILE
WEB-INF/viewer.properties




BIRT_VIEWER_PRINT_SERVERSIDE
ON




HTML_ENABLE_AGENTSTYLE_ENGINE
true




ViewerFilter
org.eclipse.birt.report.filter.ViewerFilter


ViewerFilter
ViewerServlet


ViewerFilter
EngineServlet




org.eclipse.birt.report.listener.ViewerServletContextListener




org.eclipse.birt.report.listener.ViewerHttpSessionListener




ViewerServlet
org.eclipse.birt.report.servlet.ViewerServlet




EngineServlet
org.eclipse.birt.report.servlet.BirtEngineServlet



ViewerServlet
/frameset



ViewerServlet
/run



EngineServlet
/preview



EngineServlet
/download



EngineServlet
/parameter



EngineServlet
/document



EngineServlet
/output



EngineServlet
/extract




/birt.tld
/WEB-INF/tlds/birt.tld




http://www.tonbeller.com/wcf

/WEB-INF/wcf/wcf-tags.tld




http://www.tonbeller.com/jpivot

/WEB-INF/jpivot/jpivot-tags.tld





In part 2 of this tutorial we'll integrate the Viewer into the UI.

How to Integrate SyntaxHighlighter into Blogger

I've been looking for a utility to format source code for this blog. A great open source utility provided by Google is SyntaxHighlighter which is a free syntax highlighter written in Javascript. Since it's 100% Java Script, it doesn't care what you have on your server. It's a great tool for Bloggers. The original instructions that I found on the web that have SyntaxHighlighter library files (js and css files) are not required. All credit goes to yehyeh's blog.

I've modified the instructions so that you can pull the library files from SyntaxHighlighter directly.

Here are the steps to get it work (with my modifications):

1. You'll want to visit SyntaxHighlighter and read up on the overall usage. As of this post I'm currently using SyntaxHighlighter_1.5.1.

2. Login to your Blogger Account, and go to Layout -> Template -> Edit HTML
and make the following changes to your template. (You may want to backup your
template).

You will want to enclose the following code before the end of the tag.









Now when you publish posts in your Blogger, in the 'Edit Html' section
you can now format your code like this using SyntaxHighlighter.
You'll want to read the Google SyntaxHighlighter Wiki for usage details.