Integrating Applications into BIRT iHub Information in this document is subject to change without notice. Examples provided are fictitious. No part of this document may be reproduced or transmitted in any form, or by any means, electronic or mechanical, for any purpose, in whole or in part, without the express written permission of Actuate Corporation.
© 1995 - 2015 by Actuate Corporation. All rights reserved. Printed in the United States of America.
Contains information proprietary to: Actuate Corporation, 951 Mariners Island Boulevard, San Mateo, CA 94404 www.actuate.com
The software described in this manual is provided by Actuate Corporation under an Actuate License agreement. The software may be used only in accordance with the terms of the agreement. Actuate software products are protected by U.S. and International patents and patents pending. For a current list of patents, please see http://www.actuate.com/patents.
Actuate Corporation trademarks and registered trademarks include: Actuate, ActuateOne, the Actuate logo, Archived Data Analytics, BIRT, BIRT 360, BIRT Analytics, The BIRT Company, BIRT Content Services, BIRT Data Analyzer, BIRT for Statements, BIRT iHub, BIRT Metrics Management, BIRT Performance Analytics, Collaborative Reporting Architecture, e.Analysis, e.Report, e.Reporting, e.Spreadsheet, Encyclopedia, Interactive Viewing, OnPerformance, The people behind BIRT, Performancesoft, Performancesoft Track, Performancesoft Views, Report Encyclopedia, Reportlet, X2BIRT, and XML reports.
Actuate products may contain third-party products or technologies. Third-party trademarks or registered trademarks of their respective owners, companies, or organizations include: Mark Adler and Jean-loup Gailly (www.zlib.net): zLib. Adobe Systems Incorporated: Flash Player, Source Sans Pro font. Amazon Web Services, Incorporated: Amazon Web Services SDK. Apache Software Foundation (www.apache.org): Ant, Axis, Axis2, Batik, Batik SVG library, Commons Command Line Interface (CLI), Commons Codec, Commons Lang, Commons Math, Crimson, Derby, Hive driver for Hadoop, Kafka, log4j, Pluto, POI ooxml and ooxml-schema, Portlet, Shindig, Struts, Thrift, Tomcat, Velocity, Xalan, Xerces, Xerces2 Java Parser, Xerces-C++ XML Parser, and XML Beans. Daniel Bruce (www.entypo.com): Entypo Pictogram Suite. Castor (www.castor.org), ExoLab Project (www.exolab.org), and Intalio, Inc. (www.intalio.org): Castor. Alessandro Colantonio: CONCISE Bitmap Library. d3-cloud. Day Management AG: Content Repository for Java. Dygraphs Gallery. Eclipse Foundation, Inc. (www.eclipse.org): Babel, Data Tools Platform (DTP) ODA, Eclipse SDK, Graphics Editor Framework (GEF), Eclipse Modeling Framework (EMF), Jetty, and Eclipse Web Tools Platform (WTP). Bits Per Second, Ltd. and Graphics Server Technologies, L.P.: Graphics Server. Dave Gandy: Font Awesome. Gargoyle Software Inc.: HtmlUnit. GNU Project: GNU Regular Expression. Google Charts. Groovy project (groovy.codehaus.org): Groovy. Guava Libraries: Google Guava. HighSlide: HighCharts. headjs.com: head.js. Hector Project: Cassandra Thrift, Hector. Jason Hsueth and Kenton Varda (code.google.com): Protocole Buffer. H2 Database: H2 database. IDAutomation.com, Inc.: IDAutomation. IDRsolutions Ltd.: JPedal JBIG2. InfoSoft Global (P) Ltd.: FusionCharts, FusionMaps, FusionWidgets, PowerCharts. InfoVis Toolkit. Matt Inger (sourceforge.net): Ant-Contrib. Matt Ingenthron, Eric D. Lambert, and Dustin Sallings (code.google.com): Spymemcached. International Components for Unicode (ICU): ICU library. JCraft, Inc.: JSch. jQuery: jQuery, JQuery Sparklines. Yuri Kanivets (code.google.com): Android Wheel gadget. LEAD Technologies, Inc.: LEADTOOLS. The Legion of the Bouncy Castle: Bouncy Castle Crypto APIs. Bruno Lowagie and Paulo Soares: iText. Membrane SOA Model. MetaStuff: dom4j. Microsoft Corporation (Microsoft Developer Network): CompoundDocument Library. Mozilla: Mozilla XML Parser. MySQL Americas, Inc.: MySQL Connector/J. Netscape Communications Corporation, Inc.: Rhino. NodeJS. nullsoft project: Nullsoft Scriptable Install System. OOPS Consultancy: XMLTask. OpenSSL Project: OpenSSL. Oracle Corporation: Berkeley DB, Java Advanced Imaging, JAXB, Java SE Development Kit (JDK), Jstl, Oracle JDBC driver. PostgreSQL Global Development Group: pgAdmin, PostgreSQL, PostgreSQL JDBC driver. Progress Software Corporation: DataDirect Connect XE for JDBC Salesforce, DataDirect JDBC, DataDirect ODBC. Quality Open Software: Simple Logging Facade for Java (SLF4J), SLF4J API and NOP. Raphael. RequireJS. Rogue Wave Software, Inc.: Rogue Wave Library SourcePro Core, tools.h++. Sencha Inc.: Extjs, Sencha Touch. Shibboleth Consortium: OpenSAML, Shibboleth Identity Provider. Matteo Spinelli: iscroll. StAX Project (stax.codehaus.org): Streaming API for XML (StAX). Sam Stephenson (prototype.conio.net): prototype.js. SWFObject Project (code.google.com): SWFObject. ThimbleWare, Inc.: JMemcached. Twittr: Twitter Bootstrap. VMWare: Hyperic SIGAR. Woodstox Project (woodstox.codehaus.org): Woodstox Fast XML processor (wstx-asl). World Wide Web Consortium (W3C) (MIT, ERCIM, Keio): Flute, JTidy, Simple API for CSS. XFree86 Project, Inc.: (www.xfree86.org): xvfb. ZXing Project (code.google.com): ZXing.
All other brand or product names are trademarks or registered trademarks of their respective owners, companies, or organizations. Document No. 141215-2-430301 September 1, 2015 Contents
About Integrating Applications into BIRT iHub ...... xvii Chapter 1 Overview of Actuate APIs ...... 1 Introducing Actuate APIs ...... 2 API libraries overview ...... 2 Information Delivery API (IDAPI) ...... 2 JavaScript API (JSAPI) ...... 2 Online Archive Driver API ...... 2 API plug-ins overview ...... 3 Report Engine API ...... 3 Design Engine API or model API ...... 3 Chart Engine API ...... 3 BIRT scripting ...... 3 EasyScript ...... 4 Dashboard and gadgets ...... 4 BIRT emitters ...... 4 BIRT data connectors ...... 4 Application extensions overview ...... 4 BIRT Viewer Java Extension ...... 5 Data Object API ...... 5 iHub API ...... 5 iPortal Security Extension (IPSE) ...... 5 Report Server Security Extension (RSSE) ...... 5 REST API ...... 6 Overview of other application development tools ...... 6
Part 1 Understanding and integrating the Eclipse BIRT framework Chapter 2 Understanding the BIRT architecture ...... 3 Understanding BIRT integration ...... 4 The BIRT applications ...... 8 BIRT Report Designer and BIRT RCP Report Designer ...... 8 BIRT Report Viewer ...... 9 BIRT engines and services ...... 9 Design engine ...... 9
i Report engine ...... 9 Generation services ...... 10 Presentation services ...... 10 Chart engine ...... 10 Data engine and services ...... 10 Data services ...... 11 ODA framework ...... 11 Types of BIRT report items ...... 11 Standard report items ...... 11 Custom report items ...... 11 Chart report item ...... 12 The Report Object Model (ROM) ...... 12 Types of BIRT files ...... 12 Report design files ...... 12 Report document files ...... 13 Report library files ...... 13 Report template files ...... 13 About custom Java applications ...... 14 Custom report designer ...... 14 Custom Java report generator ...... 14 Extensions to BIRT ...... 14 Chapter 3 Understanding the Report Object Model ...... 17 Report Object Model (ROM) overview ...... 18 The ROM specification ...... 18 ROM methods ...... 19 ROM properties ...... 19 ROM slots ...... 19 ROM styles ...... 19 The ROM schema ...... 20 The rom.def file ...... 20 ROM elements ...... 25 Primary ROM elements ...... 25 Report item elements ...... 26 Report item types ...... 26 Report item element properties ...... 27 Data report elements ...... 27 Chapter 4 Understanding the BIRT APIs ...... 29 BIRT APIs overview ...... 30 Package hierarchy diagrams ...... 30
ii About the BIRT Report Engine API ...... 31 Creating the ReportEngine instance ...... 32 Using the BIRT Report Engine API ...... 32 EngineConfig class ...... 33 ReportEngine class ...... 33 IReportRunnable interface ...... 34 IReportDocument interface ...... 34 IEngineTask interface ...... 34 IGetParameterDefinitionTask interface ...... 34 IDataExtractionTask interface ...... 35 IRunTask interface ...... 35 IRenderTask interface ...... 35 IRunAndRenderTask interface ...... 35 Report Engine API class hierarchy ...... 35 Report Engine API interface hierarchy ...... 37 About the Design Engine API ...... 39 Using the BIRT Design Engine API ...... 40 DesignConfig class ...... 40 DesignEngine class ...... 40 SessionHandle class ...... 41 ModuleHandle class ...... 41 ReportDesignHandle class ...... 42 LibraryHandle class ...... 42 DesignElementHandle class ...... 43 Individual element handle classes ...... 43 Design Engine API class hierarchy ...... 43 DesignElementHandle hierarchy ...... 45 ReportElementHandle hierarchy ...... 46 ReportItemHandle hierarchy ...... 48 ElementDetailHandle hierarchy ...... 49 StructureHandle hierarchy ...... 49 Design Engine API interface hierarchy ...... 51 About the BIRT Chart Engine API ...... 52 Using the BIRT Chart Engine API ...... 52 Chart Engine API class and interface hierarchy ...... 53 chart.aggregate class and interface hierarchy ...... 53 chart.datafeed class and interface hierarchy ...... 54 chart.device class and interface hierarchy ...... 54 chart.event class and interface hierarchy ...... 55 chart.exception class hierarchy ...... 57 chart.factory class and interface hierarchy ...... 57 chart.log class and interface hierarchy ...... 58 chart.model interface hierarchy ...... 59
iii chart.model.attribute class and interface hierarchy ...... 59 chart.model.component interface hierarchy ...... 64 chart.model.data interface hierarchy ...... 65 chart.model.layout interface hierarchy ...... 66 chart.model.type interface hierarchy ...... 67 chart.render class and interface hierarchy ...... 69 chart.script class and interface hierarchy ...... 69 chart.util class hierarchy ...... 70 Chapter 5 Programming using the BIRT reporting APIs ...... 71 Reporting application overview ...... 72 Choosing POJO or OSGi run-time deployment ...... 72 Building a reporting application ...... 73 About the development environment ...... 75 About plug-ins in BIRT home (OSGi only) ...... 75 About the BIRT libraries ...... 75 About required JDBC drivers ...... 78 Setting up the build path and accessing Javadoc ...... 78 Modifying a report design using the API ...... 79 About the deployment environment ...... 79 Generating reports from an application ...... 79 Setting up the report engine ...... 79 Configuring the BIRT home (OSGi only) ...... 80 Configuring the report engine ...... 80 Setting up a stand-alone or WAR file environment ...... 81 Starting the platform ...... 84 Creating the report engine ...... 85 Using the logging environment to debug an application ...... 85 Opening a source for report generation ...... 86 Understanding an IReportRunnable object ...... 87 Understanding an IReportDocument object ...... 87 Accessing a report parameter ...... 88 Preparing to generate the report ...... 95 Setting the parameter values for running a report design ...... 95 Adding to the report engine’s class path ...... 96 Providing an external object to a report design ...... 97 Generating a binary report document ...... 97 Preparing to render a formatted report ...... 98 Setting up the rendering options ...... 98 Rendering formatted output ...... 102 Accessing the formatted report ...... 104 Checking the status of a running report task ...... 105
iv Cancelling a running report task ...... 105 Programming the structure of a report design ...... 106 About BIRT model API capabilities ...... 107 Opening a report design for editing ...... 108 Configuring the design engine to access a design handle ...... 108 Using an IReportRunnable object to access a design handle ...... 109 Using a report item in a report design ...... 109 Accessing a report item by iterating through a slot ...... 110 Accessing a report item by name ...... 110 Examining a report item ...... 110 Accessing the properties of a report item ...... 111 Modifying a report item in a report design ...... 113 Accessing and setting complex properties ...... 114 Understanding property structure objects ...... 115 Adding a report item to a report design ...... 119 Accessing a data source and data set with the API ...... 120 About data source classes ...... 120 About data set classes ...... 121 Using a data set programmatically ...... 121 Saving a report design ...... 123 Creating a report design ...... 123 Chapter 6 Programming using the BIRT charting API ...... 125 Charting application overview ...... 126 Chart engine contents ...... 126 Environment for a charting application ...... 127 Configuring the chart engine run-time environment ...... 127 Verifying the environment for a charting application ...... 127 Charting API and the chart structure ...... 128 Chart visual components ...... 128 Chart data ...... 129 Static data ...... 129 Dynamic data ...... 129 Using the charting API to create a new chart ...... 130 Modifying chart properties ...... 131 Simple and complex properties ...... 131 Plot properties ...... 132 Legend properties ...... 132 Axes properties ...... 133 Using series ...... 134 Adding a series to a chart ...... 135 Creating a category series ...... 135 Creating an orthogonal series ...... 135
v Setting series properties ...... 136 Associating data with a series ...... 136 Adding a series definition to a chart ...... 137 Setting up the default aggregation for the chart ...... 138 Changing the aggregation for secondary value series ...... 138 Chart event handlers ...... 138 Java chart event handlers ...... 139 JavaScript chart event handlers ...... 139 Using a chart item in a report design ...... 139 Accessing an existing chart item ...... 140 Creating a new chart item ...... 140 Getting a design engine element factory object ...... 142 Setting the chart type and subtype ...... 142 Creating sample data ...... 143 Getting an extended item handle object ...... 144 Setting up the report item as a chart ...... 144 Preparing a data set and data columns ...... 144 Binding the chart to the data set ...... 145 Setting any other report item properties ...... 145 Adding the new chart to the report design ...... 146 Saving the report design after adding the chart ...... 146 Putting it all together ...... 146 Using the BIRT charting API in a Java Swing application ...... 154 Chart programming examples ...... 159 api.data examples ...... 160 DataCharts example ...... 160 GroupOnXSeries example ...... 160 GroupOnYAxis example ...... 160 api.data.autobinding example ...... 161 api.format example ...... 161 api.interactivity examples ...... 161 api.pdf example ...... 161 api.preference example ...... 162 api.processor example ...... 162 api.script examples ...... 162 api.viewer examples ...... 163 Chart3DViewer example ...... 163 CurveFittingViewer example ...... 163 DialChartViewer example ...... 163 SwingChartViewerSelector example ...... 163 SwingLiveChartViewer example ...... 164 SWTChartViewerSelector example ...... 164 builder example ...... 164
vi radar.ui example ...... 164 report.api examples ...... 164 MeterChartExample example ...... 165 SalesReport example ...... 165 StockReport example ...... 165 report.design examples ...... 165 report.design.script examples ...... 165 view example ...... 165
Part 2 Using Actuate BIRT APIs Chapter 7 Using Actuate APIs to access iHub environment information ...... 169 Writing event handlers to retrieve iHub environment information ...... 170 Writing a JavaScript event handler ...... 170 Writing a Java event handler ...... 170 About the serverContext object ...... 171 JavaScript event handler example ...... 172 Java event handler example ...... 173 Debugging event handlers that use the iHub API ...... 174 iHub API reference ...... 175 Chapter 8 Using the BIRT data object API ...... 181 Generating data object elements for BIRT report designs ...... 182 Creating data object data sets for BIRT report designs ...... 183 Creating data object data cubes for BIRT report designs ...... 184 Tutorial 1: Creating a data element using the Design Engine API ...... 184
Part 3 Introduction to the Actuate Information Delivery API Chapter 9 Understanding the Information Delivery API and schema ...... 195 About the Actuate Information Delivery API ...... 196 About web services and WSDL ...... 197 Understanding the elements of the iHub WSDL schema ...... 197 About the definitions element ...... 197 About data type definitions ...... 199 About message definitions ...... 200 About the portType definition ...... 201
vii About the binding definition ...... 201 About the service definition ...... 202 Accessing the Actuate schema using a web browser ...... 203 Chapter 10 Constructing a SOAP message ...... 205 About SOAP messaging ...... 206 Calling an Actuate web service ...... 206 About SOAP message elements ...... 207 Understanding the HTTP header ...... 208 Understanding the SOAP envelope ...... 209 About XML namespace declarations ...... 210 Understanding the SOAP header ...... 211 Understanding the SOAP message body ...... 213 About SOAP Fault messages ...... 215 Chapter 11 Text string limits in Actuate operations ...... 217
Part 4 Using Actuate security Chapter 12 Using Visualization Platform security ...... 223 About Actuate Visualization Platform security ...... 224 Protecting corporate data ...... 224 Protecting corporate data using firewalls ...... 224 Protecting corporate data using proxy servers ...... 225 Understanding the authentication process ...... 225 Creating a custom security adapter ...... 226 Accessing the IPSE Java classes ...... 227 Creating a custom security adapter class ...... 227 Deploying a custom security adapter ...... 228 Creating an upload security adapter ...... 229 Accessing the necessary Java classes ...... 230 Creating a custom security adapter class ...... 231 Deploying an upload security adapter ...... 232 Chapter 13 Using Java Report Server Security Extension and iPortal Security Extension ...... 233 About Java Report Server Security Extension (RSSE) and iPortal Security Extension (IPSE) .234
viii Installing the software required to run the RSSE and IPSE examples ...... 235 Understanding the RSSE example ...... 237 Understanding initialization ...... 237 Understanding user log in ...... 239 Understanding SampleRSSE.json ...... 239 Running the RSSE example ...... 242 Understanding the IPSE example ...... 245 Using the OpenText Directory Services RSSE driver ...... 252 Configuring the OTDS RSSE driver ...... 253 About the OTDS RSSE driver classes ...... 254 Deploying the OTDS RSSE driver ...... 254
Part 5 Archiving BIRT iHub volume content Chapter 14 Aging and archiving volume items ...... 261 Automating report archival and removal ...... 262 About Actuate Online Archive Driver ...... 262 Configuring the Online Archive Driver ...... 262 Understanding aging and archiving rules for items in a volume ...... 267 Understanding precedence in archiving ...... 268 Aging and archiving an item using the Archiving API ...... 268 Setting and updating autoarchive rules ...... 268 Setting default autoarchive rules when creating a folder ...... 270 Setting autoarchive rules when creating a job schedule ...... 270 Updating autoarchive rules for a file or folder ...... 271 Updating autoarchive rules for a job output file ...... 272 Updating the autoarchive rules for a file type in a folder or volume ...... 272 Setting an autoarchive schedule when updating a volume ...... 273 Starting an archive process for a volume ...... 274 Retrieving autoarchive rules for a file or folder ...... 274 Setting job notice expiration for all users ...... 275 Setting job notice expiration for a user ...... 276
Part 6 Using Actuate REST API in an application Chapter 15 Understanding the Actuate REST API ...... 279 Accessing Actuate BIRT iHub content using the Actuate REST API ...... 280 Working with Actuate REST API ...... 280
ix Using the interactive documentation ...... 281 UTF-8 encoding ...... 285 Using a special character in a REST request ...... 285 Using AuthId, Locale, and TargetVolume parameters ...... 287 Using search functionality ...... 287 About privileges ...... 287 About response codes ...... 288 Fetching a large number of items ...... 288 Handling HTTPS requests using the REST API ...... 289 Stopping and starting the REST service ...... 289 Configuring the REST API using constants.js ...... 290 Deploying the iHub REST service ...... 292 Integrating REST API and JSAPI into an application ...... 296 Using REST API resources ...... 297 Actuate REST API summary ...... 297 Actuate REST API syntax ...... 299 Getting authentication credentials ...... 300 Tutorial 2: Logging in to an iHub volume ...... 301 Managing folders ...... 307 Managing files ...... 310 Tutorial 3: Managing files and folders...... 314 Using visualizations ...... 325 Tutorial 4: Viewing a report using JSAPI ...... 330 Managing jobs ...... 342 Extracting data ...... 343 Managing user accounts ...... 344 Managing user groups ...... 346
Part 7 Using Actuate JavaScript API in an application Chapter 16 Creating a custom web page using the Actuate JavaScript API ...... 351 About the Actuate JavaScript API ...... 352 Accessing the Actuate JavaScript API ...... 352 About the DOCTYPE tag ...... 353 About UTF8 character encoding ...... 353 Establishing an HTTP session with an Actuate web application ...... 354 About Actuate JavaScript API security integration ...... 355 Establishing a secure connection to more than one web service ...... 355 Using a login servlet to connect to an Actuate web application ...... 356 Using a custom servlet to connect to an Actuate web application ...... 357
x Unloading authentication information from the session ...... 357 Viewing reports ...... 358 Tutorial 5: Implementing the JSAPI in a web page to display the viewer ...... 360 Controlling viewer user interface features ...... 362 Accessing report content ...... 362 Accessing HTML5 Chart features ...... 363 Using a filter ...... 363 Using a sorter ...... 364 Using dashboards and gadgets ...... 364 Tutorial 6: Implementing the JSAPI in a web page to display a dashboard ...... 366 Tutorial 7: Implementing the JSAPI to catch exceptions with an error callback function . . . . 368 Navigating repository content using ReportExplorer ...... 370 Displaying ReportExplorer ...... 370 Opening files from ReportExplorer ...... 372 Tutorial 8: Displaying repository contents and opening files ...... 375 Using and submitting report parameters ...... 380 Using a parameter component ...... 380 Accessing parameter values from the viewer ...... 382 Tutorial 9: Implementing the JSAPI in a web page to display report parameters ...... 383 Tutorial 10: Changing parameter values and definitions ...... 385 Using session level parameters ...... 390 Understanding the parameter value collection sequence ...... 390 Configuring the session level parameter ...... 390 Understanding the SessionLevelParameter Java class ...... 391 Setting the session level parameter using JSP ...... 392 Getting the application level parameter using JSP ...... 392 Getting the session level parameter from HttpServletRequest ...... 393 Retrieving report content as data ...... 393 Using a data service component ...... 393 Using a result set component ...... 394 Controlling Interactive Viewer user interface features ...... 395 Disabling UI features in a custom web page ...... 398 Tutorial 11: Control the BIRT Interactive Viewer user interface ...... 399 Chapter 17 Creating dynamic report content using the Actuate JavaScript API . . . 405 About Actuate JavaScript API scripting in a BIRT report design ...... 406 Using the Actuate JavaScript API in an HTML button ...... 407 Tutorial 12: Adding scripted chart controls to a BIRT design ...... 408 Tutorial 13: Using HTML buttons to apply filters to a chart ...... 413 Using the Actuate JavaScript API in chart interactive features ...... 418 Tutorial 14: Adding an interactive chart filter to a BIRT report...... 423 Using the Actuate JavaScript API in chart themes ...... 426
xi Tutorial 15: Adding scripted HTML5 Chart controls to a BIRT design ...... 427 Chapter 18 Working with Interactive Crosstabs ...... 433 About cross tabs ...... 434 Tutorial 16: Viewing and pivoting a cross tab ...... 435 About cubes ...... 436 Handling Interactive Crosstabs viewer events ...... 438 Working with dimensions, measures, and levels ...... 438 Adding a dimension with levels ...... 439 Removing a dimension ...... 439 Adding and removing measures ...... 439 Changing measures and dimensions ...... 440 Working with totals ...... 441 Sorting and filtering cross tab data ...... 442 Drilling down within a cross tab ...... 443 Controlling the Interactive Crosstabs viewer user interface ...... 444
Part 8 Accessing BIRT applications using URIs Chapter 19 Actuate application URIs ...... 449 Working with Actuate application URIs ...... 450 Information Console URIs ...... 450 Using a special character in a URI ...... 451 UTF-8 encoding ...... 452 Actuate application URIs overview ...... 453 Actuate application URIs quick reference ...... 453 Common URI parameters ...... 454 Information Console Struts actions ...... 456 Actuate application URIs reference ...... 460 Chapter 20 Actuate Report Studio URIs ...... 489 Accessing Report Studio using a URI ...... 490 Using the Report Studio servlet ...... 490 Using the Report Studio URLs ...... 491 Chapter 21 Actuate BIRT Viewer URIs ...... 493 About the BIRT Viewer servlet ...... 494
xii Using open source BIRT URIs in Actuate BIRT Viewer ...... 494 Accessing the BIRT Viewer using a URI ...... 494
Part 9 Developing a BIRT extension Chapter 22 Extending BIRT ...... 499 Overview of the extension framework ...... 500 Building the BIRT project ...... 500 Installing a working version of BIRT ...... 501 Configuring Eclipse to compile BIRT ...... 501 Downloading and extracting the correct version of the BIRT SDK ...... 502 Importing, building, and testing the BIRT project ...... 502 The structure of a BIRT plug-in ...... 506 The extension point schema definition file ...... 506 The plug-in manifest file ...... 509 The plug-in run-time class ...... 512 Working with the Eclipse PDE ...... 513 Plug-in project properties ...... 515 Understanding the Eclipse PDE Workbench ...... 515 Creating the structure of a plug-in extension ...... 517 Creating the plug-in extension content ...... 520 Building a plug-in extension ...... 526 Generating an Ant build script ...... 529 Testing a plug-in extension ...... 529 Deploying the extension plug-in ...... 530 Creating an update site project ...... 531 Installing available software ...... 533 Downloading the code for the extension examples ...... 534 Chapter 23 Developing a report item extension ...... 537 Understanding a report item extension ...... 538 Developing the sample report item extension ...... 539 Downloading BIRT source code ...... 541 Creating a rotated label report item plug-in project ...... 541 Defining the dependencies for the rotated label report item extension ...... 544 Declaring the report item extensions ...... 545 Creating the plug-in extension content ...... 550 The rotated label report item extension ...... 556 RotatedLabelItemFactoryImpl class ...... 556
xiii RotatedLabelUI class ...... 556 RotatedLabelPresentationImpl class ...... 557 GraphicsUtil class ...... 557 RotatedLabelPageGenerator class ...... 560 RotatedLabelCategoryProviderFactory class ...... 561 RotatedLabelGeneralPage class ...... 562 Deploying and testing the rotated label report item plug-in ...... 564 Deploying a report item extension ...... 564 Launching the rotated label report item plug-in ...... 564 Developing an advanced report item ...... 568 Report item model ...... 568 Report item UI design ...... 572 Report item presentation ...... 576 Improving the report item UI design ...... 581 Image UI provider ...... 581 Figure UI provider ...... 587 Report item builder ...... 592 Context menu ...... 595 Property editor ...... 598 Binding the report item to data ...... 608 Changes in the model definition ...... 609 Changes in the report item presentation ...... 609 Changing the report item UI to support expressions ...... 610 Adding data binding to the builder ...... 610 Adding data binding to the property page ...... 613 Chapter 24 Developing a report rendering extension ...... 617 Understanding a report rendering extension ...... 618 Developing a CSV report rendering extension ...... 618 Creating a CSV report rendering plug-in project ...... 619 Defining the dependencies for the CSV report rendering extension ...... 621 Declaring the emitter extensions ...... 622 The sample CSV report rendering extension ...... 624 The CSV report rendering extension package ...... 625 CSVReportEmitter class ...... 625 CSVTags class ...... 631 CSVWriter class ...... 632 CSVRenderOption class ...... 632 Testing the CSV report rendering plug-in ...... 632 ExecuteCSVReport class ...... 638 Report design XML code ...... 639 Developing an XML report rendering extension ...... 652
xiv Creating an XML report rendering plug-in project ...... 653 Defining the dependencies for the XML report rendering extension ...... 655 Declaring the emitters extension ...... 655 The sample XML report rendering extension ...... 656 The XML report rendering extension package ...... 656 XMLReportEmitter ...... 657 XMLTags class ...... 663 XMLFileWriter class ...... 664 XMLRenderOption class ...... 664 LoadExportSchema class ...... 665 Testing the XML report rendering plug-in ...... 667 Chapter 25 Developing an ODA extension ...... 671 ODA extension overview ...... 672 Understanding an ODA extension ...... 673 Developing the CSV ODA driver extensions ...... 674 About the CSV ODA plug-ins ...... 674 Downloading BIRT source code ...... 675 Implementing the CSV ODA driver plug-in ...... 676 ODA data source extension points ...... 679 dataSource extension point properties ...... 679 ConnectionProfile properties ...... 683 Dependencies for the CSV ODA driver extension ...... 683 The sample CSV ODA driver extension ...... 684 CSVFileDriver class ...... 685 Connection class ...... 686 Query class ...... 686 ResultSet class ...... 689 ResultSetMetaData class ...... 691 DataSetMetaData class ...... 691 Messages class ...... 692 CommonConstants class ...... 692 The CSV ODA user interface extension ...... 693 Creating the CSV ODA user interface plug-in project ...... 693 The ODA data source user interface extensions ...... 696 connectionProfile extension point ...... 698 propertyPages extension point ...... 698 dataSource extension point ...... 699 The sample CSV ODA user interface extension ...... 700 Implementing the ODA data source and data set wizards ...... 700 org.eclipse.birt.report.data.oda.csv.ui.impl package ...... 701 org.eclipse.birt.report.data.oda.csv.ui.wizards package ...... 701
xv Constants class ...... 702 CSVFilePropertyPage class ...... 702 CSVFileSelectionPageHelper class ...... 703 Understanding CSVFileSelectionWizardPage ...... 705 Understanding FileSelectionWizardPage ...... 706 Testing the CSV ODA user interface plug-in ...... 711 Developing a Hibernate ODA extension ...... 717 Creating the Hibernate ODA driver plug-in project ...... 719 The sample Hibernate ODA driver extension ...... 726 HibernateDriver class ...... 727 Connection class ...... 727 DataSetMetaData class ...... 730 Statement class ...... 730 ResultSet class ...... 734 HibernateUtil class ...... 735 Building the Hibernate ODA driver plug-in ...... 739 Developing the Hibernate ODA UI extension ...... 739 The sample Hibernate ODA UI extension ...... 746 HibernatePageHelper class ...... 747 HibernateDataSourceWizard class ...... 750 HibernatePropertyPage class ...... 750 HibernateHqlSelectionPage class ...... 751 Building the Hibernate ODA user interface plug-in ...... 757 Testing the Hibernate ODA user interface plug-in ...... 757 Chapter 26 Developing a data extraction extension ...... 763 Understanding a data extraction extension ...... 764 Developing an XML data extraction extension ...... 766 Creating an XML data extraction plug-in project ...... 766 Defining the dependencies for the XML data extraction extension ...... 769 Specifying the data extraction extension ...... 770 The sample XML data extraction extension ...... 772 Implementing the data extraction interfaces ...... 773 XML document format ...... 774 XMLDataExtractionImpl class ...... 776 Testing the XML data extraction plug-in ...... 783 The report design XML code ...... 786 Index ...... 795
xvi About Integrating Applications into BIRT iHub
Integrating Applications into BIRT iHub provides information about integrating applications using Actuate APIs and URIs into BIRT iHub. The APIs include client-side programming using Actuate JavaScript API and server-side programming using the XML-based Actuate Information Delivery API. This guide includes an introduction to the concepts required to work with the APIs. This guide also provides information about using external security systems to provide user credentials to BIRT iHub. Integrating Applications into BIRT iHub includes the following parts and chapters: ■ About Integrating Applications into BIRT iHub. This chapter provides an overview of this guide. ■ Chapter 1. Overview of Actuate APIs. This chapter lists all the public APIs that Actuate provides. Each API description includes an example of the type of application that uses the API. ■ Part 1. Understanding and integrating the Eclipse BIRT framework. This part introduces the BIRT architecture and the Report Object Model (ROM) and provides background information that helps programmers design or modify reports programmatically, instead of using the graphical tools in a BIRT Designer. This part also describes the public APIs that are available to Java developers, except the extension APIs. ■ Chapter 2. Understanding the BIRT architecture. This chapter provides an architectural overview of BIRT and its components, including the relationships among the BIRT components and BIRT’s relationship to Eclipse and Eclipse frameworks. Architectural diagrams illustrate and clarify the relationships and workflow of the components. The chapter also provides brief overviews of all the major BIRT components. ■ Chapter 3. Understanding the Report Object Model. This chapter provides an overview of the BIRT ROM. ROM is a specification for a set of XML elements that define both the visual and non-visual elements that comprise a report
About Integrating Applications into BIRT iHub xvii design. The ROM specification includes the properties and methods of those elements, and the relationships among the elements. ■ Chapter 4. Understanding the BIRT APIs. This chapter introduces BIRT’s public API, which are the classes and interfaces in three package hierarchies: ■ The Report Engine API, in the org.eclipse.birt.report.engine.api hierarchy, supports developers of custom report generators. ■ The Design Engine API, in the org.eclipse.birt.report.engine.api hierarchy, supports the development of custom report designs. ■ The Chart Engine API, in the org.eclipse.birt.chart hierarchy, is used to develop a custom chart generator. ■ Chapter 5. Programming using the BIRT reporting APIs. This chapter describes the fundamental requirements of a reporting application and lists the BIRT API classes and interfaces that are used to create a reporting application. This chapter describes the tasks that are required of a reporting application and provides an overview of how to build a reporting application. The org.eclipse.birt.report.engine.api package supports the process of generating a report from a report design. The org.eclipse.birt.report.model.api package supports creating new report designs and modifying existing report designs. ■ Chapter 6. Programming using the BIRT charting API. This chapter describes the requirements of a charting application, either in a stand-alone environment or as part of a reporting application. The org.eclipse.birt.chart hierarchy of packages provides the charting functionality in BIRT. By describing the fundamental tasks required of charting applications, this chapter introduces the API classes and interfaces that are used to create a chart. This chapter also describes the chart programming examples in the chart examples plug-in. ■ Part 2. Using Actuate BIRT APIs. This part describes how to use classes in the com.actuate.birt.* public packages to integrate BIRT applications and data objects into BIRT iHub. ■ Chapter 7. Using Actuate APIs to access iHub environment information. This chapter describes how to write event handlers in a report to retrieve BIRT iHub environment information. ■ Chapter 8. Using the BIRT data object API. This chapter describes how to work with BIRT data objects and report designs programmatically. ■ Part 3. Introduction to the Actuate Information Delivery API. This part describes the structure and implementation of the Actuate Information Delivery API and how to pass messages from an application to BIRT iHub using this API. ■ Chapter 9. Understanding the Information Delivery API and schema. This chapter introduces the features of the API and describes the Actuate Web Services Description Language (WSDL) schema.
xviii Integrating Applications into BIRT iHub ■ Chapter 10. Constructing a SOAP message. This chapter discusses the elements of Actuate Simple Object Access Protocol (SOAP) messages. ■ Chapter 11. Text string limits in Actuate operations. This chapter lists the maximum field lengths for text elements in BIRT iHub Information Console and System Console for elements the Actuate Information Delivery API creates. ■ Part 4. Using Actuate security. This part describes two ways to access BIRT iHub using external security to provide user login credentials. ■ Chapter 12. Using Visualization Platform security. This chapter introduces the iPortal Security Extension (IPSE) for accessing the Visualization Platform and explains how to use it. ■ Chapter 13. Using Java Report Server Security Extension and iPortal Security Extension. This chapter describes how to create and install an Actuate iHub Java Report Server Security Extension (RSSE) application as a web service. Using the Java RSSE framework, a developer can create an application that provides external authentication, external registration, and page-level security. ■ Part 5. Archiving BIRT iHub volume content. This part describes how to archive the contents of a BIRT iHub volume. ■ Chapter 14. Aging and archiving volume items. This chapter describes how to automate the archival of items in a BIRT iHub volume, including the use of relevant Information Delivery API (IDAPI) operations. ■ Part 6. Using Actuate REST API in an application. This part describes how to use and deploy the Actuate REST API. Tutorials provide an example of using the REST API in an application. ■ Chapter 15. Understanding the Actuate REST API. This chapter describes the Actuate REST API architecture and usage, including many tutorials. ■ Part 7. Using Actuate JavaScript API in an application. This part describes how to design custom reporting web applications with the Actuate JavaScript API. ■ Chapter 16. Creating a custom web page using the Actuate JavaScript API. This chapter describes the Actuate JavaScript API requirements and common implementations. ■ Chapter 17. Creating dynamic report content using the Actuate JavaScript API. This chapter describes using Actuate JavaScript API code in a BIRT report. ■ Chapter 18. Working with Interactive Crosstabs. This chapter describes how to create, access, view, and modify Interactive Crosstabs. ■ Part 8. Accessing BIRT applications using URIs. This part describes how to access the Information Console, Interactive Viewer, and Report Studio applications using URIs.
About Integrating Applications into BIRT iHub xix ■ Chapter 19. Actuate application URIs. This chapter describes the JavaServer Pages (JSPs) for Information Console and the URIs and parameters to access those pages. ■ Chapter 20. Actuate Report Studio URIs. This chapter describes the servlet for Report Studio and the URI and parameters to access the servlet. ■ Chapter 21. Actuate BIRT Viewer URIs. This chapter describes the servlet for Actuate BIRT Viewer and the URI and parameters to access the servlet. ■ Part 9. Developing a BIRT extension. This part shows Java programmers how to add new functionality to the BIRT framework. ■ Chapter 22. Extending BIRT. This chapter first explains how to download BIRT 4.3.1 source code and build the BIRT project for development. This is an optional task and usually performed when a developer is directly modifying BIRT source code. This chapter then provides an overview of the BIRT extension framework and describes how to use the Eclipse Plug-in Development Environment (PDE) and the BIRT extension points to create, build, and deploy a BIRT extension. ■ Chapter 23. Developing a report item extension. This chapter describes how to develop a report item extension. The rotated label extension example is a plug- in that renders the text of a report item as an image. The extension rotates the image in the report design to display the text at a specified angle. This chapter also describes how to build a rotated text report item plug-in and add the report item to the BIRT Report Designer using the defined extension points. ■ Chapter 24. Developing a report rendering extension. This chapter describes how to develop a report rendering extension using the Eclipse PDE with sample CSV and XML report rendering extensions as the examples. The chapter describes how to extend the emitter interfaces using the defined extension points to build and deploy a customized report rendering plug-in that runs in the BIRT Report Engine environment. ■ Chapter 25. Developing an ODA extension. This chapter describes how to develop several types of DTP ODA extensions. The CSV ODA driver example is a plug-in that reads data from a CSV file. The Hibernate ODA driver example uses Hibernate Query Language (HQL) to provide a SQL-transparent extension that makes the ODA extension portable to all relational databases. This chapter shows how to develop an ODA extension to the BIRT Report Designer 4.3.1 user interface that allows a report designer to select an extended ODA driver. ■ Chapter 26. Developing a data extraction extension. This chapter describes how to develop a report data extraction extension using the Eclipse PDE. The data extraction example exports report data to XML format. The Eclipse PDE provides the basis for the extension.
xx Integrating Applications into BIRT iHub About Integrating Applications into BIRT iHub xxi xxii Integrating Applications into BIRT iHub Chapter 1
Chapter 1Overview of Actuate APIs
This chapter contains the information about Introducing Actuate APIs.
Chapter 1, Overview of Actuate APIs 1 Introducing Actuate APIs Actuate provides software development tools as a collection of APIs that support a developer designing new Actuate applications or extending or customizing existing applications. The APIs are provided as libraries, plug-ins, or application extensions. Each API can be used independently unless there is an explicit prerequisite. For example, the iHub API, an Actuate application extension, is an extension of the BIRT Event Model, an Eclipse BIRT plug-in, and therefore cannot be implemented without the Event Model included in the server application libraries. API libraries overview Actuate APIs libraries are capable of supporting independent applications as well as extending functionality in applications that provide API integration points. Actuate provides: Information Delivery API (IDAPI) Description IDAPI provides libraries for server-side data integration and manipulation using Simple Object Access Protocol (SOAP) messaging. IDAPI messages are defined by a Web Service Definition Language (WSDL) schema file located at http://
JavaScript API (JSAPI) Description JSAPI provides libraries for web and client-side visualizations using the JavaScript programming language. JSAPI is available to iHub web clients using the iportal context in the iportal\jsapi folder. Purpose Use JSAPI in a web page to embed reports, Reportlets, and gadgets in a dashboard and to modify the behavior of the Actuate Viewer. Use JSAPI in a report design to enhance interactivity.
Online Archive Driver API Description Online Archive Driver API provides libraries that are a SOAP-based interface between BIRT iHub and external archive software. Purpose Use Online Archive Driver API for automating the aging and archiving processes for items in a volume
2 Integrating Applications into BIRT iHub API plug-ins overview Eclipse BIRT plug-ins are function-specific libraries for enhancing BIRT applications with additional features such as security, database integration, encryption, and data objects using Eclipse. Most Eclipse BIRT plug-ins are built using the Java programming language, but may support HTML, XML, JavaScript, SQL, or custom command sets. Actuate develops and supports many Eclipse BIRT plug-ins, both open source and commercial. The APIs are available to BIRT Designer Professional as plug-ins in the eclipse\plugins folder and to iHub as JAR files in the BIRT iHub installation in the $ACTUATE_HOME\modules\BIRTiHub\iHub\Jar\BIRT\lib folder. BIRT Designer Professional also provides the JAR files in the iportal\WEB-INF\lib folder in the com.actuate.birt.report.viewer plug-in.
Report Engine API Description A set of open source Java packages that provides access to all the tasks that create a report from a report design or a report document. The org.eclipse.birt.report .engine.api.* packages in the engineapi.jar file contains this API. Purpose Use the Report Engine API to set parameter values, run a report design, and render a report document to one or more output formats.
Design Engine API or model API Description A set of open source Java packages that provides access to the content and structure of a report design, a template, or a library. The org.eclipse.birt.report .model.api.* packages in the modelapi.jar file contain the components of this API. Purpose Use the Design Engine API to modify the structure of an existing report design or to create a completely new report design.
Chart Engine API Description A set of open source Java packages used to create and modify chart elements. This API supports charting in a stand-alone application or, in conjunction with the Report Engine and Design Engine APIs, in a report design. The org.eclipse.birt.chart.* packages in the chartengineapi.jar file contain the components of this API. Purpose Use the Chart Engine API to modify an existing chart element or to create a completely new chart element. Extend the chart element to provide new chart types. BIRT scripting Description A set of Java packages that enables creation of custom code to control various aspects of report creation and interactivity. BIRT scripting supports JavaScript and Java functions. Script handling follows the BIRT Event model. This model
Chapter 1, Overview of Actuate APIs 3 provides support for event registration and triggers initiated from BIRT content or the server environment. The org.eclipse.birt.report.engine.api.script.* packages in the scriptapi.jar file contain this API and model. Purpose Use BIRT scripting in event handlers and in expressions.
EasyScript Description An expression syntax similar to the syntax used in Excel formulas. EasyScript supports formula and data manipulations using its own markup. The com.actuate.script.* plug-ins provide this scripting syntax and user interface. Purpose Use EasyScript to write expressions in BIRT Designer Professional, Interactive Viewer, and Report Studio.
Dashboard and gadgets Description A plug-in that supports arranging data into interactive visualizations that can deployed individually. Dashboards and gadgets use JavaScript to control their functionality. Supported gadgets include Google gadgets that display dynamic web content using HTML and JavaScript. The com.actuate.birt.report.model .api.dashboard package in the modelapi.jar file contains this API. Purpose Use the dashboard and gadgets API to enhance dashboard and gadget functionality.
BIRT emitters Description Plug-ins that support generating content in different formats, such as PDF, HTML, CSV, and so on. The org.eclipse.birt.report.engine.emitter.* and com.actuate.birt.report.engine.emitter.* plug-ins provide the content emitters. Purpose Use the emitter APIs to customize the built-in emitters to change their behavior or to create a new emitter to generate output in an additional format.
BIRT data connectors Description Connectors that implement drivers to establish connections with specific database or other data source types. For example, Actuate provides connectors for Oracle, MySQL, and flat file data source types. You can use database connectors in IDAPI applications, Report Engine applications, Data Objects, or as the basis for custom database connectors. The org.eclipse.birt.report.data.oda.* and com.actuate.data.oda.* plug-ins provide the data connectors. Purpose Use the Open Data Access (ODA) standard to create custom data connectors to access data from additional data sources. Application extensions overview Actuate application extensions provide additional functionality to commercial Actuate products, such as BIRT Viewer or iHub.
4 Integrating Applications into BIRT iHub BIRT Viewer Java Extension Description A commercial implementation of the BIRT Design Engine API that expands the capabilities of the Actuate BIRT Viewer. This API is provided by the com.actuate.birtviewer.extension package in com.actuate.iportal.jar, which is located in the $ACTUATE_HOME\modules\BIRTiHub\iHub\web\iportal \WEB-INF\lib folder. Use the BIRT Viewer Java extension API to implement event handlers that fire when a user views or interacts with the report.
Data Object API Description A Java API extension used to create and alter data objects. The com.actuate.birt .report.model.api package in the modelapi.jar file contains this API extension. Purpose Use the Data Object API to create, alter, and refresh data objects, based on custom conditions or events. iHub API Description An Event Model extension that provides a report with access to the iHub server environment for specific logistical operations. This extension is provided in $ACTUATE_HOME\modules\BIRTiHub\iHub\reportengines\lib\jrem.jar. Purpose Use the iHub API in an event handler in a report design to customize report content based on conditions such as the user credentials, volume, or the web browser used to view the report.
iPortal Security Extension (IPSE) Description An API extension that supports custom security adapters to implement single-sign on and download security features. The iPortalSecurityAdapter class is provided in com.actuate.iportal.jar, which is located in the $ACTUATE_HOME \modules\BIRTiHub\iHub\web\iportal\WEB-INF\lib folder. Purpose Use IPSE to customize and control the user login and authentication process. Report Server Security Extension (RSSE) Description A SOAP-based security module that creates individual security protocols for consumable content, for example by using an existing Lightweight Directory Access Protocol (LDAP) implementation to control access to a volume. RSSE is based on the IDAPI and can implement a highly granular security scheme for all BIRT content. Purpose Use RSSE to implement external authentication or external registration, or to customize page-level security.
Chapter 1, Overview of Actuate APIs 5 REST API Description The REST API is a resource extension installed with BIRT iHub that responds to RESTful requests. The REST API adheres to the REST standard, a strategy for developing web and mobile components that are platform and language independent, require very little time to implement, and that use minimal client and server resources. Purpose Use the REST API to access and manage dynamic data built with Actuate BIRT technology and generate new documents for distribution. Use the REST API to deliver BIRT content and data from BIRT iHub to any mobile or web application. Overview of other application development tools Actuate provides an extension to ANSI Structured Query Language (SQL) syntax, called Actuate SQL. This syntax is supported by Actuate information objects. Information Object Query Builder provides a graphical interface to build queries using Actuate SQL. For a complete description of Actuate SQL syntax, see Designing Information Objects. Actuate reports and dashboards support the use of the Highcharts JavaScript API to customize HTML 5 charts, such as providing interactivity or changing the appearance of an axis, a series, or a data point. For more information about this API, see the Highcharts reference documentation at http://api.highcharts.com/highcharts.
6 Integrating Applications into BIRT iHub Part One1
Part 1Understanding and integrating the Eclipse BIRT framework
■ Understanding the BIRT architecture ■ Understanding the Report Object Model ■ Understanding the BIRT APIs ■ Programming using the BIRT reporting APIs ■ Programming using the BIRT charting API
Chapter 2
Chapter 2Understanding the BIRT architecture
This chapter contains the following topics: ■ Understanding BIRT integration ■ The BIRT applications ■ BIRT engines and services ■ Types of BIRT report items ■ The Report Object Model (ROM) ■ Types of BIRT files ■ About custom Java applications ■ Extensions to BIRT
Chapter 2, Understanding the BIRT architecture 3 Understanding BIRT integration BIRT consists of many related components. This chapter provides an overview of the BIRT architecture, the BIRT components, the Eclipse components upon which BIRT relies, and the relationships that tie them all together. As an Eclipse project, BIRT is tightly integrated with Eclipse frameworks and platforms. Like all Eclipse projects, BIRT is implemented as a set of Eclipse plug- ins. The BIRT plug-ins provide the functionality for all BIRT components, including BIRT applications, the engines that drive the applications, and supporting application programming interfaces (APIs). The BIRT plug-ins also provide the interface mechanism for communicating with several Eclipse frameworks and platforms. The relationships between BIRT and the Eclipse components are most easily viewed as a stack. Each tier in the stack depends upon, uses, and integrates with the tier below it, as shown in Figure 2-1. Figure 2-2 presents the various BIRT components and how they relate to one another. In this diagram, a component in a solid box is a standard BIRT component. A component in a dashed box is a custom component that a Java developer can provide. Some custom components are extensions of BIRT and others are applications that use the BIRT APIs. A component in a dotted box is a standard BIRT component that the containing component uses. For example, because BIRT Report Designer uses the design engine, the design engine appears in a dotted box within the box for BIRT Report Designer. Figure 2-3 shows the relationships among BIRT components as they generate a formatted report from a design. BIRT Report Designer provides drag-and-drop capabilities to design reports quickly. The report designer uses the design engine to produce XML report design files. The BIRT Report Engine consumes these report design files, and then, at run time, fetches the appropriate data using queries defined at design time. A BIRT report for immediate viewing is generated in memory and emitted in the desired output format, which can be Microsoft Excel, non-paginated HTML, paginated HTML, Open Document formats, Adobe PDF, PostScript, Microsoft PowerPoint, or Microsoft Word. To create a persistent report, the report engine transforms and summarizes the data and caches the generated report in an intermediate binary file, the report document file. This caching mechanism enables BIRT to scale to handle large quantities of data.
4 Integrating Applications into BIRT iHub BIRT applications
BIRT designers BIRT run-time application
BIRT Report Designer BIRT Report Viewer
Chart Builder
BIRT RCP Report Designer
BIRT engines and services
Design engine Report engine Chart engine Script engine
Presentation Generation Data services services services
BIRT core component plug-ins
Eclipse frameworks
Data Tools Graphical Eclipse Modeling Framework Framework Framework
Eclipse platforms
Eclipse Tools Platform Eclipse Rich Client Platform
Figure 2-1 BIRT components as plug-ins to the Eclipse platform
Chapter 2, Understanding the BIRT architecture 5 BIRT Report Designer
Tools to create and edit report components and rules, including:
■ Bookmarks ■ Expressions ■ Report layout ■ Charts ■ Highlighting rules ■ Report parameters ■ Cross tabs ■ Hyperlinks ■ Report XML ■ Data filters and groups ■ Library components ■ Scripts ■ Data mapping rules ■ Master pages ■ Styles ■ Data sets and data ■ Properties ■ Tables of content sources ■ Report items
Report outline explorer Data explorer
Report item palette Library outline explorer
Report previewer Data previewer
BIRT Report Viewer Data services
Design engine ODA framework Report Object Model (ROM)
Standard BIRT report items Data source Custom data Report item extensions source
Report library files Report design Report template files (.rptlibrary) (.rptdesign) (.rpttemplate)
Web application Report previewer Custom Java application
BIRT Report Viewer BIRT Report Viewer BIRT Report Engine
Figure 2-2 Task flow among standard BIRT components and custom components
6 Integrating Applications into BIRT iHub Report design (.rptdesign)
BIRT Report Viewer
Report engine
Preparation and generation services
Chart engine Script engine Data services
Data transform services Design engine Report executor Data access service Report items
ODA Framework Report document (.rptdocument) Data source Custom data source
Presentation services
Chart Engine Report renderer Script engine
Emitters
PDF DOC PPT
HTML XLS PostScript
Custom
Report in specified format Figure 2-3 Task flow among BIRT and custom components to generate a report
Chapter 2, Understanding the BIRT architecture 7 BIRT also provides a tightly integrated charting component, which supports including a variety of chart types in reports. The charts are rendered at run time using the charting engine. This charting engine also supports creating chart output separate from a report. Figure 2-4 illustrates this architecture and process flow.
Figure 2-4 BIRT architecture and process flow
The BIRT applications There are three BIRT applications: BIRT Report Designer, BIRT RCP Report Designer, and BIRT Report Viewer. The two report designers are very similar. BIRT Report Designer runs as a set of Eclipse plug-ins and lets you build reports within the Eclipse Workbench. BIRT RCP Report Designer has a simplified report design interface based on Eclipse Rich Client Platform. Although BIRT RCP Report Designer can be used for report development, it is included in this book as a reference implementation to help you develop your own Rich Client Platform applications. BIRT Report Designer and BIRT RCP Report Designer BIRT Report Designer is a graphical report design tool. BIRT Report Designer uses the design engine to generate a report design file based on the report object model (ROM). ROM supports the standard set of BIRT report items and custom report items. BIRT Report Designer also supports the reuse of a report design by saving it as a template. You can also save individual report components in a component library, making those components accessible to other report designs. The primary functional differences between the BIRT RCP Report Designer and BIRT Report Designer are: ■ BIRT RCP Report Designer has no integrated debugger. ■ BIRT RCP Report Designer does not support Java event handlers.
8 Integrating Applications into BIRT iHub Other than these differences, the functionality of the two report designers is identical and any further mention of BIRT Report Designer in this chapter apply equally to BIRT RCP Report Designer. BIRT Report Viewer BIRT provides the BIRT Report Viewer web application that includes all the necessary files to deploy to most J2EE application servers. This web application supports running reports and viewing paginated HTML, with a table of contents and bookmarks, and extracting data to a values file. URLs provide this level of integration. The host application forwards the reporting request to the BIRT Report Viewer and allows the user to interact directly with the report. The BIRT Report Viewer is also available as an Eclipse plug-in. This plug-in is used within the report designer to preview and display a report while it is being developed. Within BIRT Report Designer, it is deployed to and works with the Eclipse Tomcat application server plug-in. As report requests are made, the Eclipse Workbench starts the Tomcat application and launches the BIRT Report Viewer.
BIRT engines and services An engine is a set of Java APIs that provide basic functionality in a specific domain. BIRT contains several engines, for example, the report engine, design engine, and chart engine. These engines provide several different types of services. A service is a set of Java classes that provide functionality using the API provided from different engines. For example, the generation services use the design engine API and report engine API to generate reports and produce report documents respectively. Design engine The design engine contains the APIs used to validate and generate a report design file. BIRT Report Designer and any custom Java application that generates a BIRT report design use the design engine. The generation services also use the design engine when building the report document. The design engine contains APIs that validate the elements and structure of the design file against the ROM specification. Report engine The BIRT report engine enables XML report designs created by the BIRT Report Designer to be used by a J2EE/Java application. To support this functionality, the report engine provides two core services, generation and presentation.
Chapter 2, Understanding the BIRT architecture 9 The report engine provides extensions to support custom report items and custom output formats. The report engine also supports Java application developers who want to integrate powerful report generation and viewing capabilities into their applications without having to build the infrastructure from lower-level Java components. The BIRT Report Engine API supports integrating the run-time part of BIRT into Java applications. The report engine provides the ability to specify parameters for a report, run a report to produce HTML, PDF, DOC, PS, or PPT output and fetch an image or chart.
Generation services The generation service within the report engine connects to the data sources specified in a report design, uses the data engine to retrieve and process the data, creates the report layout, and generates the report document. Report content can be either viewed immediately using the presentation services, or saved for later use. The saved report documents containing snapshot views of data can be retained for use and comparison over time.
Presentation services The presentation services process the report document created by the generation services and render the report to the requested format and the layout specified in the design. The presentation services use the data engine to retrieve and process data from the report document. The presentation services use whichever report emitter they require to generate a report in the requested format. BIRT has several standard emitters, HTML PDF, DOC, PPT, PS, and XLS. BIRT also supports custom emitters that modify these default formats or deliver new formats. Extensions to the presentation engine and services provide display capability for chart report items and custom report items. Chart engine The chart engine contains APIs to generate charts and associate them with data from a data source. BIRT Report Viewer interprets any chart information in a report design and uses the chart engine to generate the chart specified by the design. Use of the chart engine is not restricted to a BIRT application. Any Java application can use chart engine APIs to create and display a chart. Data engine and services The data engine provides services to retrieve and transform data. The data services retrieve data from its source and process the data as specified by the report design. When used by the generation engine, the data services retrieve data from the data source specified in the design. When used by the presentation engine, the data services retrieve data from the report document.
10 Integrating Applications into BIRT iHub Data services The data engine provides two key service types: data access services and data transformation services. The data access services communicate with the ODA framework to retrieve data. The data transformation services perform such operations as sorting, grouping, aggregating, and filtering the data returned by the data access services.
ODA framework BIRT uses the Open Data Access (ODA) framework provided by the Eclipse Data Tools Platform project to manage ODA and native drivers, load drivers, open connections, and manage data requests. The ODA framework contains extension points that support adding a custom ODA driver. Write a custom ODA driver if you have a data source that BIRT does not support and a scripted data source is not desired. Use of a custom ODA driver may require extending not only the data engine but also BIRT Report Designer. A BIRT Report Designer extension is necessary if the data source requires a user interface component to specify the data set and data source properties.
Types of BIRT report items A report item is a visual component of a report, such as a label, a list, or a chart. There are three categories of report items in BIRT: standard report items, custom report items, and the chart report item. Standard report items A report item is a visual component of a report. A report item can be as simple as a label or as complex as a cross tab. Every report item has an icon on the Palette view in BIRT Report Designer. Custom report items Custom report items are either new report items or extensions of existing report items. An example of an extension to a report item is adding a property, such as color. An example of a new report item is the rotated text report item, which is a reference implementation of a report item extension. Creating a new report item and extending an existing report item both involve extending BIRT through the Eclipse plug-in mechanism. Custom items require an extension to one or more of the following components to support the new item:
■ BIRT Report Designer Extending BIRT Report Designer provides user interface components for a report developer to specify properties and other settings for the report item.
Chapter 2, Understanding the BIRT architecture 11 ■ The design engine Extending the design engine validates the report item settings provided by a report developer.
■ The report engine Extending the report engine supports generating and presenting report output for the report item. Chart report item A chart report item is a standard BIRT component implemented as a BIRT extension. The user interface for creating a chart report item is a chart builder that steps the report developer through the process of designing the chart and associating it with the appropriate data columns.
The Report Object Model (ROM) ROM is the model upon which BIRT is based. ROM is a specification for the structure, syntax, and semantics of the report design. The formal expression of ROM is through an XML schema and a semantic definition file. The ROM specification appears in the following plug-in JAR file: $INSTALL_DIR\eclipse\plugins \org.eclipse.birt.report.model_
Types of BIRT files BIRT Report Designer uses four types of files: ■ Report design files ■ Report document files ■ Report library files ■ Report template files The following sections provide a brief overview of each of these file types. Report design files A report design file is an XML file that contains the report design, the complete description of a BIRT report. The report design describes every aspect of a report, including its structure, format, data sources, data sets, JavaScript event handler code, and the names of Java event handlers. BIRT Report Designer creates the report design file and BIRT Report Engine processes it.
12 Integrating Applications into BIRT iHub The file extension of a report design file is rptdesign. Report document files A report document file is a binary file that encapsulates the report design, incorporates the data, and contains additional information, such as data rows, pagination information, and table of contents information. The file extension of a report document file is rptdocument. Report library files A report library file is an XML file that contains reusable and shareable BIRT report components. A report developer uses Resource Explorer in BIRT Report Designer to provide shared access to a library, update a library, and use report elements from a library. A BIRT report library can contain any report element, such as: ■ Data sets and data sources ■ Embedded images ■ Event handler code ■ Styles ■ Visual report items The file extension of a report library file is rptlibrary. Report template files A report template is an XML file that contains a reusable design. A report developer can use a template as a basis for developing a new report. A report developer uses a report template to maintain a consistent style across a set of report designs and for streamlining the report design process. A report template can specify many different elements of a report, including: ■ One or more data sources ■ One or more data sets ■ Part or all of the layout of a report design, including grids, tables, lists, and other report items ■ Grouping, filtering, and data binding definitions ■ Styles ■ Library components
Chapter 2, Understanding the BIRT architecture 13 ■ Master pages ■ Cheat sheets Building BIRT templates is similar to building BIRT reports. The difference lies in converting report items into template report items which act as placeholders. The file extension of a report template file is rpttemplate.
About custom Java applications Java developers can use the BIRT APIs to create a custom report designer or a custom report generator. Custom report designer A custom report designer is a Java application that a Java developer creates to generate a well-formed report design file based on specific requirements. A custom report designer does not necessarily include a user interface. A typical example of a custom report designer is a Java application that dynamically determines the content, structure, or data source for a report, based on business logic. A custom report designer uses the same design engine API as BIRT Report Designer. Custom Java report generator A custom Java report generator performs the same function as the BIRT report generator and is typically integrated into either a web application or a stand-alone Java application. A custom Java report generator uses the Report Engine API to read a report design file and generate a report. A custom Java report generator can use business logic to implement security requirements, control content, and determine the output format.
Extensions to BIRT Through its public APIs and the BIRT extension framework, BIRT enables a Java developer to expand the capabilities of BIRT. BIRT uses Eclipse extensions to enable extending the functionally of the framework. The extension points provided by BIRT support the creation of new graph types, additional data sources, report controls, and emitters for rendering to additional outputs. These extension points appeal to users who have specialized data access and formatting needs. The following list shows some of the possible custom extensions:
14 Integrating Applications into BIRT iHub ■ A custom report item A custom report item is a report item extension. This report item can be an extension, an existing BIRT report item, or a new report item. ■ A custom ODA data source driver A custom ODA data source driver is a custom ODA extension that connects to a data source type other than those that BIRT directly supports. ■ A custom report emitter A custom report emitter generates a report in a format other than HTML or PDF. Later chapters in this book provide fully worked examples of all these types of extensions.
Chapter 2, Understanding the BIRT architecture 15 16 Integrating Applications into BIRT iHub Chapter 3
Chapter 3Understanding the Report Object Model
This chapter contains the following topics: ■ Report Object Model (ROM) overview ■ The ROM specification ■ The ROM schema ■ The rom.def file ■ ROM elements
Chapter 3, Understanding the Report Object Model 17 Report Object Model (ROM) overview This chapter provides an overview of the BIRT Report Object Model (ROM) and the primary elements that comprise the model. ROM defines the rules for constructing a valid report design file in much the same way that HTML defines the rules for constructing a valid web page. ROM, therefore, is the model for the BIRT report design, template, or library file in the same way that HTML is the model for the web page. For information about every component of ROM, see the online help entry Report Object Model (ROM) Definitions Reference in BIRT Programmer Reference.
The ROM specification The ROM specification defines a set of XML elements that describe the visual and non-visual components of a report. The XML file that BIRT Report Designer generates to describe a report design, library, or template consists entirely of ROM elements. Visual components, known as report items, include data items, labels, and tables. ROM also provides the framework for extended report items such as charts and cross tabs. Non-visual components, for example, data cubes, data sets, data sources, report parameters, and styles, support report items, but do not appear in a report. The ROM specification defines elements, their properties, and an element’s relationship to other elements. The ROM specification describes elements by their methods, properties, slots, and styles. ROM elements describe: ■ The data source and query with which to populate a report ■ The placement, size, style, and structure of report items ■ The report page layout The report design, template, or library file contains XML elements that describe the ROM elements in the file. The BIRT design engine interprets the ROM elements using the ROM specification and the ROM schema. The ROM specification describes the content of each report element type. The ROM schema describes the supported structure of the XML in a file. Each BIRT file type appears in the ROM schema. Examining the XML in a BIRT file and the ROM schema shows that a template’s structure is identical to a report design. BIRT Report Designer displays the elements that the design engine interprets. Visual report items appear in the layout window. Data-related items such as cubes, data sets, and report parameters appear in the data explorer. All elements in the report design appear in the Outline view.
18 Integrating Applications into BIRT iHub ROM methods A ROM element can have one or more methods, called event handlers. BIRT fires many different events during the course of executing a report. When BIRT fires an event, the appropriate event handler executes to handle the event. By default, event handlers are empty methods that do nothing. By supplying code for an event handler, a report developer customizes and extends the functionality of BIRT. Supplying code for an event handler is called scripting. An event handler can be scripted in either JavaScript or Java. Report items can have four events: onPrepare, onCreate, onPageBreak, and onRender. Each event fires in a specific phase of report creation. onPrepare fires in the preparation phase. onCreate fires during the generation phase. onRender and onPageBreak fire during the presentation phase. ROM properties ROM element properties are typed. Property types are similar to variable types in programming or data types in database terminology. Like variables and data types, ROM property types can be simple or complex. Design.xsd defines these types. Simple types include color, dimension, number, and string. Complex types include lists and structures. A complex type contains more than one component. For example, a text type contains both the text and a resource key used to internationalize the text. ROM slots A ROM slot is a container for elements of defined types. For example, a report element has a Body slot that contains any number of any type of report item. The Styles slot in the report element contains only Style items, which are the styles available to the report. ROM styles The ROM style system is based on cascading style sheets (CSS), where a style set in a container cascades to its contents. The Report element contains all other elements, so the style property of the Report element defines the default style for the entire report. An element within the report can override the default style. A report developer can either choose a style from a defined set of styles or create a new style. Typical style attributes include alignment, background image, color, and text size.
Chapter 3, Understanding the Report Object Model 19 The ROM schema The ROM schema, written in the XML Schema language, encapsulates the ROM specification. XML Schema provides a standard way of defining the structure, content, and semantics of an XML file. XML Schema is similar to document type definition (DTD). The ROM schema, therefore, contains the formal expression of the content, structure, and semantics of the ROM report design. The ROM schema, design.xsd, is located at: http://www.eclipse.org/birt/2005/design Design.xsd is also in the plug-in, org.eclipse.birt.report.model. A statement similar to the following one appears at the top of every report design, library, or template file:
The rom.def file The rom.def file contains metadata defining the specific ROM elements, their properties, their slots, and their methods. You can find rom.def in: $INSTALL_DIR\eclipse\plugins \org.eclipse.birt.report.model_
20 Integrating Applications into BIRT iHub The rom.def file is an internal file that the design engine uses to present a property sheet for a ROM element. The property sheet for an element contains the element’s properties and their types, the element’s methods, and valid choice selections for each of the element’s properties. When the BIRT development team changes the structure of a ROM element, the changed item includes an attribute that shows the BIRT version in which that change occurred, for example:
■ Class Class defines a Java class that a report designer application can access using the BIRT model API. Class definitions describe the following component types: ■ Data types, such as Array, Number, and String ■ Functional classes, such as Global, Math, and RegExp A class definition defines attributes, constructors, localization, members, and methods identifiers. The following example from rom.def shows part of the definition of the Number class:
Chapter 3, Understanding the Report Object Model 21
■ Element The rom.def file contains an element definition for every ROM element. Every element definition includes attributes, such as the element’s name, display name, and the element type that it extends. ROM supports methods, properties, property visibility, slot, and style properties in an element definition. The following example from the rom.def file illustrates an element definition:
22 Integrating Applications into BIRT iHub
Chapter 3, Understanding the Report Object Model 23 StyleProperty defines the style components supported by the ROM element. The following example illustrates style property definitions for the data element. The label element definition does not have these style properties because it contains only string values, not numbers.
■ Structure Structure is a complex data type that typically consists of two or more members. A few structures that are candidates for future expansion have only a single member. The following example from the rom.def file illustrates the definition of a structure.
■ Style Style contains the least information of any type of metadata described in rom.def. A style definition defines the name of the style, its display name, and a reference value, as shown in the following example.
■ Validator A validator definition specifies a Java class with which to do validation. Two of the validator classes are for validating values. The rest are semantic validators. The following example from rom.def illustrates a SemanticValidator definition.
24 Integrating Applications into BIRT iHub
ROM elements ROM elements are defined in a set of hierarchies. Abstract elements, which cannot be used directly in a BIRT file, are at the top of each hierarchy. These elements define key characteristics of concrete elements in the same way that abstract classes in Java define methods and variables that a concrete class implements. Report designs are made of concrete elements that derive from the abstract elements. Primary ROM elements The primary ROM elements consist of abstract elements from which other elements derive and concrete elements that provide the overall file definition. The following elements are the abstract components that form the basis for understanding ROM: ■ DesignElement DesignElement defines basic features of ROM elements. DesignElement represents any component of a report design that has properties and defines the available property types. Property types include name-value pairs, methods, and user-defined properties. ■ ReportElement ReportElement extends DesignElement to represent any item that can be named and customized. Most components in ROM derive from ReportElement, including the elements that are visible in the user interface, such as data sets, styles, master pages, and report items. ■ DataSet DataSet extends ReportElement to define the fundamental properties of a data set relating to columns and parameters. ■ DataSource DataSource extends ReportElement to define the methods that a concrete data source element must support. ■ ReportItem ReportItem is the base element for the visual elements. This element extends ReportElement to include characteristics such as data set, data column, and parameter bindings, position and size, and bookmark and table of contents
Chapter 3, Understanding the Report Object Model 25 values. ReportItem uses a style to provide visual characteristics, such as font and background color, for the element as it appears in a report. ■ Listing Listing is the abstract base element that extends ReportItem for list and table items. Both items support filtering, sorting, and methods. ■ MasterPage MasterPage defines the basic properties of a page, such as size, margins, and orientation. The following concrete elements describe the root element of a BIRT file: ■ ReportDesign ReportDesign contains information about a report design, defining properties that describe the design as a whole. Report design properties do not support inheritance because a design cannot extend another design. ReportDesign is the root element of a report design or a template. ■ Library Library is similar to ReportDesign, extending LayoutModule, but has a different set of slots and does not have methods. Report item elements BIRT provides many types of visual report components. Every type of visual report component has a corresponding ROM element that derives from the ReportItem element. Visual report components are called report items. Every report item type has an entry in Palette, the view in BIRT Report Designer that the report developer uses to build a report layout. Report item types BIRT provides container and simple report items. Container items are structural components provide slot elements to hold other report items. The slots in container items support both container and simple report items, so a grid can contain tables that contain other tables and grids, and so on. Simple report items are not structural and do not contain other items. These report items have properties that describe their behavior and appearance and do not provide slots. For example, the Image element is a simple report item. Examples of container report items include: ■ Grid A grid contains a set of report items arranged into a matrix having a fixed set of columns and rows. Each cell in the grid can contain one or more simple or container report items.
26 Integrating Applications into BIRT iHub ■ List A list contains a set of arbitrary content based on data retrieved from a data set. A list is appropriate when some report items require a sophisticated layout and repeat that layout for each row in a query. ■ Table A table contains a set of report items arranged into a matrix. A table has a fixed set of columns and an arbitrary number of rows. A table produces a detail row for every row of data retrieved from a data set.
Report item element properties Each type of report item has its own set of properties in addition to the properties it inherits from ReportItem. Types of inherited properties include: ■ Method, which defines executable code. ■ Property, which includes such values as names and dimensions. ■ Slot, which contains Type elements that define its contents, as shown in the following element definition.
■ StyleProperty, which defines style-related characteristics, such as color and font size. Data report elements Several elements in the ROM specification apply to data rather than visual report items. These data report elements describe data sources and data sets. The following elements are data report elements: ■ OdaDataSource The OdaDataSource element represents a connection to an external data system, such as an RDBMS, text file, or XML file. ■ ScriptedDataSource The ScriptedDataSource element represents a connection to an external data system that is not an ODA data source. The developer must provide scripts for opening and closing a scripted data source. ScriptedDataSource inherits from DataSource.
Chapter 3, Understanding the Report Object Model 27 ■ OdaDataSet The OdaDataSet element represents a tabular result set retrieved from a data source. An OdaDataSet element defines a data source, query, filters, parameters, and result set columns. ■ ScriptDataSet The ScriptDataSet element represents a data set that is associated with a scripted data source. The developer must provide scripts for opening, closing, and fetching a row from a scripted data source. ■ JointDataSet The JointDataSet element represents a data set that results from a join of several data sets.
28 Integrating Applications into BIRT iHub Chapter 4
Chapter 4Understanding the BIRT APIs
This chapter contains the following topics: ■ BIRT APIs overview ■ Package hierarchy diagrams ■ About the BIRT Report Engine API ■ About the Design Engine API ■ About the BIRT Chart Engine API
Chapter 4, Understanding the BIRT APIs 29 BIRT APIs overview The Eclipse BIRT code consists of many hundreds of Java classes and interfaces, but most of them are private, for use by contributors to the BIRT open-source project. Developers of applications use the classes and interfaces that are in the public API. The public API consists of the classes and interfaces in the following package hierarchies:
■ Report Engine API The org.eclipse.birt.report.engine.api package hierarchy contains the API that a developer of a custom report generator uses. This API provides the most commonly used functionality for a reporting application. The key class in the Report Engine API is ReportEngine. This class provides access to all the tasks that create a report from a report design or a report document. The Report Engine API also includes the classes and packages that support the scripting capabilities of a report design.
■ Design Engine API The org.eclipse.birt.report.model.api package hierarchy is by far the larger of the two reporting APIs. This API provides access to the content and structure of a report design, a template, or a library. A reporting application can call this API to change the structure of a design. The Design Engine API is also the API that a developer of a custom report designer uses.
■ Chart Engine API The org.eclipse.birt.chart package hierarchy contains the API that a developer of a custom chart generator uses. A reporting application can also use this API in conjunction with the Report Engine and Design Engine APIs to create and modify chart elements in a report design.
■ Extension APIs BIRT provides a set of extension APIs for creating custom report items, custom data sources and data sets, custom rendering formats, and custom charts. For detailed information about API classes and interfaces, see the Javadoc in the online help in BIRT Programmer Reference➛Reference➛API Reference and BIRT Charting Programmer Reference➛Reference➛API Reference.
Package hierarchy diagrams This chapter contains hierarchical diagrams for the packages in the BIRT APIs. These diagrams show the hierarchy of the classes in the package and interfaces local to the package or implemented by classes in the package. Classes and interfaces preceded by a package name are not local to the package. In these
30 Integrating Applications into BIRT iHub hierarchical diagrams, the graphics shown in Table 4-1 indicate different attributes and relationships of the classes and interfaces. Table 4-1 Conventions for the hierarchy diagrams Item Symbol
Abstract class Class Class that has one or more subclasses Class
Class that has no subclasses Class
Final class Class
Interface Interface
Solid lines indicate a Superclass superclass-subclass relationship Subclass
Broken lines indicate an Class Interface implementation relationship
An asterisk indicates too many Superclass subclasses to list Subclass (*)
About the BIRT Report Engine API The BIRT report engine supports report generation and rendering in several different environments, such as:
■ Stand-alone engine A Java developer uses a stand-alone engine to render a BIRT report from an existing report design (.rptdesign) file. In this environment, the Java developer creates a command line application to write a complete report in any of the supported formats.
■ BIRT report viewer BIRT Report Designer uses the BIRT report viewer to view a report as paginated HTML. The BIRT report viewer is a web application that runs in the Tomcat Application Server, which is embedded in Eclipse. This viewer contains an embedded report engine.
Chapter 4, Understanding the BIRT APIs 31 ■ Custom report designer with an embedded engine A custom desktop reporting application integrates the BIRT report engine for the purpose of previewing the report.
■ Web application that embeds the engine A web application similar to the BIRT report viewer can use the BIRT report engine to generate a web-based report. The BIRT report engine supports running and rendering reports in these diverse environments. It does not perform environment-dependent processing such as URL construction, image storage, and design file caching. The application using the engine API must provide such context information to the engine. The BIRT Report Engine API consists of interfaces and implementation classes that support integrating the run-time part of BIRT into an application. The API provides task classes that support the following operations: ■ Discovering the set of parameters defined for a report ■ Getting the default values for parameters ■ Running a report design to produce an unformatted report document ■ Running a report design or report document to produce any of the supported output formats ■ Extracting data from a report document Creating the ReportEngine instance Each application, whether it is stand-alone or web-based, only needs to create one ReportEngine instance. As the BIRT report engine is thread-safe, the single-instance recommendation is not a restriction. Use an IReportEngineFactory instance and an EngineConfig object to create the ReportEngine instance. Using the BIRT Report Engine API The BIRT Report Engine API supports the following key tasks to generate reports: ■ Setting options for the report engine using an EngineConfig object ■ Starting the platform ■ Creating a ReportEngine object using the ReportEngineFactory ■ Opening an existing report design using one of the openReportDesign( ) methods of ReportEngine or opening an existing report document using the openReportDocument( ) method
32 Integrating Applications into BIRT iHub ■ Optionally, obtaining design details of the report parameters using an IGetParameterDefinitionTask object ■ Running and rendering a report using IRunAndRenderTask or IRunTask followed by IRenderTask ■ Cleaning up the report engine by calling destroy( ) on the engine instance to unload extensions and delete temporary files A few key classes and interfaces provide the core functionality of the BIRT report engine. The following sections provide an overview of these classes.
EngineConfig class The EngineConfig class wraps configuration settings for a report engine. Use the EngineConfig object to set global options for the environment of the report engine, including: ■ Setting OSGi arguments ■ Setting the platform context ■ Setting resource locations ■ Adding application-wide scriptable objects ■ Setting the directory where the report engine writes temporary files ■ Managing logging
ReportEngine class The ReportEngine class represents the BIRT report engine. To instantiate the ReportEngine object, use a factory method that takes an EngineConfig object as an argument. Use a ReportEngine object to perform the following tasks: ■ Getting the configuration object ■ Opening a report design or a report document ■ Creating an engine task to get parameter definitions ■ Creating an engine task to access the data from a report item ■ Getting supported report formats and MIME types ■ Creating an engine task to run a report or render a report to an output format ■ Creating an engine task to extract data from a report document ■ Changing the logging configuration ■ Cleaning up and destroying the engine
Chapter 4, Understanding the BIRT APIs 33 IReportRunnable interface To use the engine to work with the report design, load the design using one of the openReportDesign( ) methods in the ReportEngine class. These methods return an IReportRunnable instance that represents the engine’s view of the report design. Use an IReportRunnable object to perform the following tasks: ■ Getting standard report design properties, such as the report title ■ Getting any images embedded within the report design ■ Getting a handle to the report design IReportDocument interface To use a report document, load the document using one of the ReportEngine .openReportDocument( ) methods. These methods return an IReportDocument instance. Use an IRenderTask object to render the report specified by an IReportDocument object to a supported output format. Use table of contents markers in the IReportDocument to determine pages to render. The IReportDocument interface also supports retrieving page counts, parameter values used while creating the report document, and bookmarks.
IEngineTask interface The IEngineTask interface provides the framework for the tasks that the report engine performs. The IEngineTask interface manages the scripting context, getting and setting parameter values, setting the report’s locale, getting the current status of a task, and cancelling a task. The other task interfaces extend IEngineTask. IGetParameterDefinitionTask interface The IGetParameterDefinitionTask interface extends IEngineTask to provide access to information about parameters. Use the engine factory method to create an IGetParameterDefinitionTask object takes an IReportRunnable argument. Parameter definitions provide access to: ■ Information that BIRT Report Designer specified at design time ■ Static or dynamic selection lists ■ User-supplied values ■ Grouping structure of the parameters ■ Custom XML ■ User-defined properties
34 Integrating Applications into BIRT iHub IDataExtractionTask interface The IDataExtractionTask interface extends IEngineTask to provide access to the data stored in an IReportDocument object. Use an IDataExtractionTask object to examine the metadata for a set of data rows. Use the metadata to select a set of columns to extract, sort, or filter. This interface can extract the data from: ■ The whole report document ■ A single report item ■ A single instance of a report item IRunTask interface The IRunTask interface provides the methods to run a report design. This task saves the result as a report document (.rptdocument) file on disk. An IRunTask object takes parameter values as a HashMap. Call the validateParameters( ) method to validate the parameter values before running the report.
IRenderTask interface The IRenderTask interface provides the methods to render a report document to one of the supported output formats. This task can save the report to a file on disk or to a stream. Use the RenderOption class to set options for rendering. Set options specific to particular output formats using subclasses of the RenderOption class. Pass the appropriate render option object to the IRenderTask object before rendering the report.
IRunAndRenderTask interface The IRunAndRenderTask interface provides the methods to run a report and render it in one of the supported output formats. This task can save the report to disk or to a stream. This task does not create an intermediate report document (.rptdocument) file. An IRunAndRenderTask object takes parameter values as a HashMap or individually. Call the validateParameters( ) method to validate the parameter values before running the report. An IRunAndRenderTask object supports setting the same rendering options as an IRenderTask object. Pass the appropriate render option object to the IRunAndRenderTask object before running the report. Report Engine API class hierarchy The class hierarchy in Figure 4-1 illustrates the organization of the classes in the report engine package. Unless otherwise specified, all classes and interfaces in this diagram are in the org.eclipse.birt.report.engine.api package.
Chapter 4, Understanding the BIRT APIs 35 java.lang.Object
CachedImage
ComponentID
DataExtractionFormatInfo
DataID
DataSetID
DefaultStatusHandler IStatusHandler
DOCRenderContext
DocumentUtil
EmitterInfo
EngineConstants
HTMLActionHandler IHTMLActionHandler
HTMLImageHandler IHTMLImageHandler
HTMLCompleteImageHandler
HTMLServerImageHandler
HTMLRenderContext
ImageSize
InstanceID
PDFRenderContext
org.eclipse.birt.core IPlatformConfig .framework.PlatformConfig
EngineConfig IEngineConfig
Figure 4-1 Classes within the report engine package
36 Integrating Applications into BIRT iHub ReportEngine IReportEngine
ReportParameterConverter
ReportRunner
TaskOption ITaskOption
DataExtractionOption IDataExtractionOption
RenderOption IRenderOption
EXCELRenderOption IEXCELRenderOption
HTMLRenderOption IHTMLRenderOption
HTMLEmitterConfig
PDFRenderOption IPDFRenderOption
RenderOptionBase
java.lang.Throwable java.io.Serializable
java.lang.Exception
org.eclipse.birt.core.exception .BirtException
EngineException
UnsupportedFormatException
TOCNode
TOCStyle IScriptStyle Figure 4-1 Classes within the report engine package Report Engine API interface hierarchy Figure 4-2 contains the interface hierarchy for the Report Engine API. Unless otherwise specified, all interfaces in this diagram are in the org.eclipse.birt.report.engine.api package.
Chapter 4, Understanding the BIRT APIs 37 IAction IParameterDefnBase
IDataAction IParameterDefn
org.eclipse.birt.report.model IDynamicFilterParameterDefn .api.util.IBookmarkInfo IScalarParameterDefn
IBookmarkInfo IParameterGroupDefn
IDataIterator ICascadingParameterGroup
IDocument IParameterSelectionChoice
IReportDocument ICascadingParameterSelectionChoice
IDocumentWriter org.eclipse.birt.core.framework .IPlatformConfig IEngineTask IEngineConfig IDataSetPreviewTask
IExtractionTask IProgressMonitor
IDataExtractionTask IReportDocumentHelper
IGetParameterDefinitionTask IReportDocumentInfo IRenderTask IReportDocumentLock IRunAndRenderTask IReportDocumentLockManager IRunTask
IReportEngine IExtractionResults
ICubeExtractionResults IReportEngineFactory
IHTMLActionHandler IReportPart
IHTMLImageHandler IImage
IMetaDataFilter IResultMetaData
IPageHandler IResultSetItem Figure 4-2 Interface hierarchy for the report engine package
38 Integrating Applications into BIRT iHub IRunnable
IReportRunnable
IStatusHandler
ITaskOption
IExtractionOption
IDataExtractionOption
IRenderOption
IExcelRenderOption
IHTMLRenderOption
IPDFRenderOption
IPostscriptRenderOption
ITOCTree Figure 4-2 Interface hierarchy for the report engine package
About the Design Engine API The Design Engine API is also known as the report model API. The Design Engine API is the API that a tool writer uses to develop a design tool. The Design Engine API supports creating, accessing, and validating a report design, library, or template. The org.eclipse.birt.report.model.api package contains the interfaces and classes used to access the design model objects. The Design Engine API supports the following tasks: ■ Reading and writing design files ■ Maintaining the command history for undo and redo ■ Providing a rich semantic representation of the report design ■ Providing metadata about the ROM ■ Performing property value validation ■ Notifying the application when the model changes
Chapter 4, Understanding the BIRT APIs 39 Using the BIRT Design Engine API The purpose of the BIRT Design Engine API is to modify or create a design file that the BIRT report engine can use to generate a report. BIRT Report Designer, for example, uses the BIRT Design Engine API for this purpose. A custom report design tool, written for the same general purpose as BIRT Report Designer, can also use the BIRT Design Engine API to generate a design file. The Design Engine API supports libraries and templates in the same way as report designs. The BIRT Design Engine API does not include any user interface classes. A custom report design tool must provide its own user interface code. The design engine supports the following tasks to create or modify a BIRT report design: ■ Setting options for the design engine by using a DesignConfig object ■ Starting the platform, if not already started ■ Creating a DesignEngine object using the DesignEngineFactory ■ Beginning a user session by using the DesignEngine.newSessionHandle( ) method to instantiate a SessionHandle object ■ Setting session parameters and loading the property definitions of the report elements by using the SessionHandle object to create an instance of the ReportDesignHandle class ■ Using the ReportDesignHandle to create an ElementFactory, which can create report elements ■ Using the ReportDesignHandle to add new elements to the report design or modify existing elements ■ Saving the report design file by using the ReportDesignHandle The following sections describe the primary classes of the BIRT Design Engine API.
DesignConfig class The DesignConfig class wraps configuration settings for a design engine. Use a DesignConfig object to set global options for the design engine, including: ■ Setting the platform context ■ Specifying configuration variable ■ Set OSGi arguments DesignEngine class The DesignEngine class represents the BIRT design engine. Create the DesignEngine with a factory method that takes a DesignConfig object. The
40 Integrating Applications into BIRT iHub DesignEngine class is the gateway to creating the other objects needed to build a report design tool. Use the methods of the DesignEngine class to create a locale-specific SessionHandle object by calling the newSession( ) method. The SessionHandle provides access to report design objects.
SessionHandle class The SessionHandle class represents the user session. A SessionHandle object provides access to the set of open designs. A session has a set of default values for style properties and a default unit of measure. The session also has methods to create and open report designs, templates, and libraries, as well as setting the path and algorithm used to locate resources. The methods to create or open a report design return a ReportDesignHandle object. ModuleHandle class ModuleHandle provides access to the common structure and functionality of report designs, templates, and libraries. The ModuleHandle class is the parent class of the ReportDesignHandle and LibraryHandle classes. ModuleHandle provides access to the generic properties, such as author and comments. Use ModuleHandle for many tasks on the file, including: ■ Saving the module to a file ■ Accessing the command stack for undo and redo ■ Navigating to the various parts of the module ■ Retrieving the module location ■ Getting configuration variables Other ModuleHandle methods support getting handles to the individual report items and all the other elements in a report design, template, or library. These elements and supporting components include: ■ Report items. These elements are visual report elements such as tables, grids, images, and text elements. ■ Code modules. These modules are global scripts that apply to the file as a whole. ■ Parameters. ■ Data sources, data sets, and cubes. ■ Color palette. This component is a set of custom color names. ■ CSS files that the module uses. ■ Theme. The theme is a group of styles that the module uses for formatting report elements.
Chapter 4, Understanding the BIRT APIs 41 ■ Master page. This element defines the layout of pages in paginated report output. ■ Libraries. Any module can use one or more libraries to provide predefined elements. ■ Resources. External files, for example, providing images or lists of messages in localized forms. ■ Embedded images.
ReportDesignHandle class ReportDesignHandle provides access to report design-specific properties such as the scripts that execute when generating or rendering a report. This class also provides access to properties that templates use, such as the cheat sheet, display name, and icon file. ReportDesignHandle is a subclass of ModuleHandle, so it supports all the functionality of that class. Use ReportDesignHandle to get handles to individual report items and for many report design-specific tasks, including: ■ Navigating to the various parts of the design ■ Setting the event-specific scripts that execute when the report engine runs and renders the report The ReportDesignHandle also has methods to gain access to the following report components: ■ Styles, the list of user-defined styles for formatting report elements ■ Base directory, the location of file system resources with relative paths ■ Body, a list of the report sections and report items in the design ■ Scratch Pad, a temporary place to hold report items while restructuring a report
LibraryHandle class LibraryHandle is a subclass of ModuleHandle, so it supports all the functionality of that class. LibraryHandle also provides access to the following library-specific properties: ■ Name space, the name that a module including a library uses to identify the elements that the library defines ■ The set of themes that the library defines ■ Imported CSS styles used by themes
42 Integrating Applications into BIRT iHub DesignElementHandle class DesignElementHandle is the base class for all report elements, both visual report item elements and non-visual ones, such as data sets and cubes. DesignElementHandle provides generic services for all elements, such as: ■ Adding a report item to a slot ■ Registering a change event listener ■ Getting and setting properties, names, and styles ■ Getting available choices for specific properties ■ Dropping an element from the design ■ Copying, pasting, and moving report items
Individual element handle classes Element handle classes derive from ReportElementHandle. Each report element has its own handle class. To work with operations unique to a given report element, cast the ReportElementHandle to the appropriate subclass for the element. For example, the CellHandle class provides methods such as getColumn( ), and the DataSourceHandle class has methods such as setBeforeOpen( ). Design Engine API class hierarchy Figure 4-3 illustrates the hierarchy of the classes within the design engine package. Unless otherwise specified, all classes and interfaces in this diagram are in the org.eclipse.birt.report.model.api package.
java.lang.Object
BundleFactory
ColumnBandData java.lang.Cloneable
DefaultResourceLocator IResourceLocator
DesignElementHandle org.eclipse.birt.report.model.elements .interfaces.IDesignElementModel (*) DesignEngine IDesignEngine
DesignVisitor ElementDetailHandle (*) ElementFactory Figure 4-3 Classes within the report model package
Chapter 4, Understanding the BIRT APIs 43 ErrorDetail ErrorCodes
Expression
Expression Type
FactoryElementHandle
GridColumnBandAdaptor
GroupElementFactory
GroupElementHandle
EmptyGroupElementHandle
SimpleGroupElementHandle
GroupPropertyHandle
MemberIterator java.util.Iterator
ModelConstants
ModuleOption IModuleOption
ModuleUtil
org.eclipse.birt.core.framework.PlatformConfig IPlatformConfig
DesignConfig IDesignConfig
RowBandAdapter
GridRowBandAdapter
TableRowBandAdapter
RowBandInsertAction
RowBandInsertAndPasteAction
RowBandPasteAction
RowBandShiftAction
RowOperationParameters
SessionHandle
SlotIterator java.util.Iterator
SortedSlotIterator java.util.Iterator
StructureFactory Figure 4-3 Classes within the report model package
44 Integrating Applications into BIRT iHub TableColumnBandAdaptor
java.lang.Throwable java.io.Serializable
java.lang.Exception
org.eclipse.birt.core.exception.BirtException
ModelException
DesignFileException
java.lang.RuntimeException
IllegalOperationException Figure 4-3 Classes within the report model package DesignElementHandle hierarchy Figure 4-4 contains the class hierarchy for DesignElementHandle in the org.eclipse.birt.report.model.api package and the classes that derive from it.
java.lang.Object org.eclipse.birt.report.model.elements DesignElementHandle .interfaces.IDesignElementModel ContentElementHandle
AccessControlHandle IAccessControlModel
ValueAccessControlHandle IValueAccessControlModel DataGroupHandle IDataGroupModel
FilterConditionElementHandle IFilterConditionElementModel
MemberValueHandle IMemberValueModel
SortElementHandle ISortElementModel
VariableElementHandle IVariableElementModel
ModuleHandle IModuleModel
LibraryHandle ILibraryModel
ReportDesignHandle IReportDesignModel
MultiViewsHandle IMultiViewsModel
ReportElementHandle (*) Figure 4-4 DesignElementHandle class hierarchy
Chapter 4, Understanding the BIRT APIs 45 ReportElementHandle hierarchy Figure 4-5 contains the class hierarchy for ReportElementHandle in the org.eclipse.birt.report.model.api package and the classes that derive from it. The interfaces that the classes implement are all in the org.eclipse.birt.report.model .elements.interfaces and org.eclipse.birt.report.model.elements packages. Classes with names that have a prefix of olap are in the org.eclipse.birt.report.model.olap package.
java.lang.Object
DesignElementHandle
ReportElementHandle
AbstractThemeHandle IAbstractThemeModel
ReportItemThemeHandle IReportItemThemeModel
ThemeHandle IThemeModel
CellHandle ICellModel
ColumnHandle ITableColumnModel
DataSetHandle IDataSetModel
ISimpleDataSetModel
DerivedDataSetHandle IDerivedDataSetModel
IDerivedExtendableElementModel
JointDataSetHandle IJointDataSetModel
OdaDataSetHandle IOdaDataSetModel
ScriptDataSetHandle IScriptDataSetModel
DataSourceHandle IDataSourceModel
OdaDataSourceHandle IOdaDataSourceModel
IOdaExtendableElementModel
ScriptDataSourceHandle IScriptDataSourceModel
GroupHandle IGroupElementModel
ListGroupHandle
TableGroupHandle Figure 4-5 ReportElementHandle class hierarchy
46 Integrating Applications into BIRT iHub MasterPageHandle IMasterPageModel
GraphicMasterPageHandle IGraphicMasterPageModel
SimpleMasterPageHandle ISimpleMasterPageModel
ParameterGroupHandle IParameterGroupModel
CascadingParameterGroupHandle ICascadingParameterGroupModel
ParameterHandle IParameterModel
AbstractScalarParameterHandle IAbstractScalarParameterModel
DynamicFilterParameterHandle IDynamicParameterModel
ScalarParameterHandle IScalarParameterModel
ReportItemHandle IReportItemMethodContext
(*) IReportItemModel
IStyleElementModel
RowHandle ITableRowModel
StyleHandle IStyleModel
PrivateStyleHandle
SharedStyleHandle
CSSSharedStyleHandle
TemplateElementHandle
TemplateDataSetHandle
TemplateReportItemHandle
TemplateParameterDefinitionHandle ITemplateParameterDefinitionModel Figure 4-5 ReportElementHandle class hierarchy
Chapter 4, Understanding the BIRT APIs 47 ReportItemHandle hierarchy Figure 4-6 contains the class hierarchy for ReportItemHandle in the org.eclipse.birt.report.model.api package and the classes that derive from it. The interfaces that the classes implement are all in the org.eclipse.birt.report.model .elements.interfaces and org.eclipse.birt.report.model.elements packages.
java.lang.Object
DesignElementHandle IReportItemMethodContext
ReportElementHandle IReportItemModel
ReportItemHandle IStyledElementModel
AutoTextHandle IAutoTextModel
DataItemHandle IDataItemModel
ExtendedItemHandle IExtendedItemModel
IReportItemMethodContext
FreeFormHandle IFreeFormModel
GridHandle IGridItemModel
ISupportThemeElementConstants
ImageHandle IImageItemModel
LabelHandle ILabelModel
LineHandle ILineItemModel
ListingHandle IListingElementModel
ListHandle ISupportThemeElementConstants
TableHandle ITableItemModel
RectangleHandle
TextDataHandle ITextDataItemModel
MultilineDataHandle
TextItemHandle ITextItemModel Figure 4-6 ReportItemHandle class hierarchy
48 Integrating Applications into BIRT iHub ElementDetailHandle hierarchy Figure 4-7 contains the class hierarchy for ElementDetailHandle in the org.eclipse.birt.report.model.api package and the classes that derive from it.
java.lang.Object
ElementDetailHandle
FactoryPropertyHandle
SlotHandle
TranslationHandle
UserPropertyDefnHandle
ValueHandle
ComplexValueHandle
ColorHandle
DimensionHandle
ExpressionHandle
ExpressionListHandle
FontHandle
SimpleValueHandle
MemberHandle
PropertyHandle
StructureHandle (*) Figure 4-7 ElementDetailHandle class hierarchy StructureHandle hierarchy Figure 4-8 contains the class hierarchy for StructureHandle in the org.eclipse.birt.report.model.api package and the classes that derive from it.
java.lang.Object
ElementDetailHandle
ValueHandle
Figure 4-8 StructureHandle class hierarchy
Chapter 4, Understanding the BIRT APIs 49 StructureHandle
ActionHandle
AggregationArgumentHandle
CachedMetaDataHandle
ColumnHintHandle
ComputedColumnHandle
ConfigVariableHandle
CustomColorHandle
DataSetParameterHandle
OdaDataSetParameterHandle
DimensionConditionHandle
DimensionJoinConditionHandle
EmbeddedImageHandle
ExtendedPropertyHandle
FilterConditionHandle
FormatValueHandle
HideRuleHandle
IncludedCssStyleSheetHandle
IncludedLibraryHandle
IncludeScriptHandle
JoinConditionHandle
LevelAttributeHandle
OdaLevelAttributeHandle
OdaDesignerStateHandle
ParamBindingHandle
PropertyBindingHandle
PropertyMaskHandle Figure 4-8 StructureHandle class hierarchy
50 Integrating Applications into BIRT iHub ResultSetColumnHandle
OdaResultSetColumnHandle
RuleHandle
ScriptLibHandle
SearchKeyHandle
SelectionChoiceHandle
SortHintHandle
SortKeyHandle
StyleRuleHandle
HighlightRuleHandle
MapRuleHandle
TimeIntervalHandle
TOCHandle Figure 4-8 StructureHandle class hierarchy Design Engine API interface hierarchy Figure 4-9 contains the interface hierarchy for the Design Engine API. All interfaces in this diagram are in the org.eclipse.birt.report.model.api package.
CommandStack
ErrorCodes
IAbsoluteFontSizeValueProvider
IBundleFactory
IDesignEngine
IDesignEngineFactory
IModuleOption
org.eclipse.birt.core.framework.IPlatformConfig
IDesignConfig Figure 4-9 Interface hierarchy for the design engine package
Chapter 4, Understanding the BIRT APIs 51 IResourceLocatorBase
IResourceLocator
IVersionInfo Figure 4-9 Interface hierarchy for the design engine package
About the BIRT Chart Engine API The Chart Engine API uses the Eclipse Modeling Framework (EMF) as a structured data model. Use the classes and interfaces in the Chart Engine API to modify Chart objects within a BIRT reporting application or in a stand-alone charting application. The Chart Engine API includes many packages in the org.eclipse.birt.chart hierarchy. The model.* packages contain the core chart model interfaces and enumeration classes generated using EMF. The model.*.impl packages contain the core chart model implementation classes generated using EMF. All other packages are dependencies from and indirect references to the core model. There is a one-to-one correspondence between classes in the impl packages and interfaces in matching model packages. The classes in the impl packages implement the methods in the interfaces of the model classes. The impl classes also contain factory methods used to create an instance of a class. Using the BIRT Chart Engine API Although there are over 500 classes and interfaces in the BIRT Chart Engine API, most functionality for creating or modifying a chart is concentrated in a small subset of classes and interfaces. The primary interface in the BIRT Chart Engine API is the Chart interface. An object of the Chart type is called the chart instance object. The Chart interface has two subinterfaces, ChartWithAxes and ChartWithoutAxes. DialChart is a third interface that inherits from ChartWithoutAxes. ChartWithoutAxes defines a pie chart and DialChart defines a meter chart. ChartWithAxes defines all other chart types. To create a chart instance object, call create( ) in ChartWithAxesImpl, ChartWithoutAxesImpl, or DialChartImp, as in the following statement:
ChartWithAxes myChart = ChartWithAxesImpl.create( ); To set the basic properties of a chart, such as its orientation and dimensionality, use setter methods of the Chart interface, such as:
myChart.setOrientation( Orientation.VERTICAL_LITERAL ); myChart.setDimension( ChartDimension.THREE_DIMENSIONAL );
52 Integrating Applications into BIRT iHub Set more complex properties of a chart, like characteristics of the chart’s axes and series by getting an instance of the object to modify and then setting its properties. For example, to set an x-axis caption, use the following code: Axis xAxis = myChart.getPrimaryBaseAxes( )[0]; xAxis.getTitle( ).getCaption( ).setValue( "Months" ); Although charts are often identified by type, such as a pie chart or a line chart, a chart with multiple series of differing types cannot be classified as one type. A series has a specific type. Use the BIRT Chart Engine API to create a specific type of series by using the create( ) method of one of the SeriesImpl subclasses. For example, the following code creates a bar series:
BarSeries barSeries1 = ( BarSeries ) BarSeriesImpl.create( );
Chart Engine API class and interface hierarchy The diagrams that follow contain hierarchies for the following chart engine packages:
■ org.eclipse.birt.chart.aggregate ■ org.eclipse.birt.chart.model.attribute ■ org.eclipse.birt.chart.datafeed ■ org.eclipse.birt.chart.model.component ■ org.eclipse.birt.chart.device ■ org.eclipse.birt.chart.model.data ■ org.eclipse.birt.chart.event ■ org.eclipse.birt.chart.model.layout ■ org.eclipse.birt.chart.exception ■ org.eclipse.birt.chart.model.type ■ org.eclipse.birt.chart.factory ■ org.eclipse.birt.chart.render ■ org.eclipse.birt.chart.log ■ org.eclipse.birt.chart.script ■ org.eclipse.birt.chart.model ■ org.eclipse.birt.chart.util
The hierarchy diagrams for the org.eclipse.birt.chart.model.*.impl packages are not included because they are simply implementations of the interfaces in the corresponding org.eclipse.birt.chart.model.* packages. The model packages, with two exceptions, contain only interfaces. The first exception is org.eclipse.birt.chart.model, which has one class, ScriptHandler. The second exception is org.eclipse.birt.chart.model.attribute, which has a set of enumeration classes, one for each attribute. Each of the enumeration classes contains only a list of valid values for its attribute. chart.aggregate class and interface hierarchy The chart.aggregate package contains the class and interface that support the aggregate functions that produce the values that a chart shows. Figure 4-10 contains the class and interface hierarchy for org.eclipse.birt.chart.aggregate.
Chapter 4, Understanding the BIRT APIs 53 java.lang.Object
AggregateFunctionAdapter IAggregateFunction
IAggregateFunction Figure 4-10 Classes and interfaces in org.eclipse.birt.chart.aggregate chart.datafeed class and interface hierarchy The chart.datafeed package contains the class and interfaces that support defining a custom data set for a chart. Figure 4-11 contains the class and interface hierarchy for org.eclipse.birt.chart.datafeed.
java.lang.Object
AbstractDataPointDefinition IDataPointDefinition
org.eclipse.birt.chart org.eclipse.birt.chart.computation.Methods .computation.IConstants
DataSetAdapter IDataSetProcessor
NumberDataPointEntry IDataPointEntry
IResultSetDataSet Figure 4-11 Classes and interfaces in org.eclipse.birt.chart.datafeed chart.device class and interface hierarchy The chart.device package contains the classes and interfaces that support rendering a chart to a specific output type. Device adapter classes provide the rendered output. These classes process the events defined in the chart.event package. Display adapter classes provide metrics for the output device. Figure 4-12 contains the class hierarchy for org.eclipse.birt.chart.device.
java.lang.Object
DisplayAdapter IDisplayServer
EmptyUpdateNotifier IUpdateNotifier
org.eclipse.birt.chart.event.EventObjectCache
DeviceAdapter IDeviceRenderer
FontUtil Figure 4-12 Classes in org.eclipse.birt.chart.device
54 Integrating Applications into BIRT iHub ImageWriterFactory IImageWriterFactory
ScriptMenuHelper IScriptMenuHelper
TextAdapter ITextMetrics
TextRendererAdapter ITextRenderer Figure 4-12 Classes in org.eclipse.birt.chart.device Figure 4-13 contains the interface hierarchy for org.eclipse.birt.chart.device.
java.util.EventListener IDeviceRenderer IPrimitiveRenderer IStructureDefinitionListener org.eclipse.birt.chart .computation.IConstants
ITextRenderer
IDisplayServer
IImageMapEmitter
IImageWriterFactory
IScriptMenuHelper
IStructureDefinitionListener
IDeviceRenderer
IPrimitiveRenderer
ITextMetrics
IUpdateNotifier
ICallbackNotifier Figure 4-13 Interfaces in org.eclipse.birt.chart.device chart.event class and interface hierarchy The chart.event package contains the set of events that a rendering device that extends the chart.device.DeviceAdapter class can support. It also provides structural and caching classes for events. Figure 4-14 contains the interface hierarchy for org.eclipse.birt.chart.event.
Chapter 4, Understanding the BIRT APIs 55 I3DRenderEvent
java.lang.Comparable
IRenderInstruction Figure 4-14 Interfaces in org.eclipse.birt.chart.event Figure 4-15 contains the class hierarchy for org.eclipse.birt.chart.event.
java.lang.Object
java.util.EventObject
ChartEvent
BlockgenerationEvent
InteractionEvent
PrimitiveRenderEvent java.lang.Comparable
ArcRenderEvent
Arc3DRenderEvent I3DRenderEvent
AreaRenderEvent
Area3DRenderEvent I3DRenderEvent
ClipRenderEvent
ImageRenderEvent
Image3DRenderEvent I3DRenderEvent
LineRenderEvent
Line3DRenderEvent I3DRenderEvent
OvalRenderEvent
Oval3DRenderEvent I3DRenderEvent
PolygonRenderEvent
Polygon3DRenderEvent I3DRenderEvent
RectangleRenderEvent
Figure 4-15 Classes in org.eclipse.birt.chart.event package
56 Integrating Applications into BIRT iHub TextRenderEvent
Text3DRenderEvent I3DRenderEvent
TransformationEvent
StructureChangeEvent
EventObjectCache
MarkerInstruction IRenderInstruction
StructureSource
WrappedStructureSource
StructureType
WrappedInstruction IRenderInstruction Figure 4-15 Classes in org.eclipse.birt.chart.event package chart.exception class hierarchy The chart.exception package contains the single exception class the BIRT Chart Engine defines. Figure 4-16 contains the class hierarchy for org.eclipse.birt.chart.exception.
java.lang.Object
java.util.lang.Throwable
java.util.lang.Exception
org.eclipse.birt.core.exception.BirtException
ChartException Figure 4-16 Class in org.eclipse.birt.chart.exception chart.factory class and interface hierarchy The chart.factory package contains classes and interfaces that build and generate a chart. It also contains a context class that provides information about the environment in which the factory runs, such as the locale and associated localization information. Figure 4-17 contains the class hierarchy for org.eclipse.birt.chart.factory.
Chapter 4, Understanding the BIRT APIs 57 java.lang.Object
AbstractGroupedDataRowExpressionEvaluator IGroupedDataRowExpressionEvaluator
ActionEvaluatorAdapter IActionEvaluator
DataRowExpressionEvaluatorAdapter IDataRowExpressionEvaluator
GeneratedChartState
Generator IGenerator
RunTimeContext java.i.o.Serializable
RunTimeContext.StateKey Figure 4-17 Classes in org.eclipse.birt.chart.factory
Figure 4-18 contains the interface hierarchy for org.eclipse.birt.chart.factory.
IActionEvaluator
IDataRowExpressionEvaluator
IGroupedDataRowExpressionEvaluator
IExternalizer
IGenerator
IMessageLookup
IResourceFinder Figure 4-18 Interfaces in org.eclipse.birt.chart.factory chart.log class and interface hierarchy The chart.log package contains a single class and an interface to manage logging of the tasks that the BIRT Chart Engine performs. Figure 4-19 contains the class hierarchy for org.eclipse.birt.chart.log.
ILogger
java.lang.Object
Logger Figure 4-19 Class and interface in org.eclipse.birt.chart.log
58 Integrating Applications into BIRT iHub chart.model interface hierarchy The chart.model package contains the interfaces that describe the available chart types and the factory for generating charts. Figure 4-20 contains the interface hierarchy for org.eclipse.birt.chart.model.
IChartModelHelper
IExtChartModelLoader
ModelPackage.Literals
org.eclipse.emf.common.notify.Notifier
org.eclipse.emf.ecore.EObject
org.eclipse.emf.ecore.EModelElement
org.eclipse.emf.ecore.EFactory
ModelFactory
org.eclipse.emf.ecore.ENamedElement
org.eclipse.emf.ecore.EPackage
ModelPackage
IChartObject
Chart
ChartWithAxes
ChartWithoutAxes
DialChart
Serializer Figure 4-20 Interfaces in org.eclipse.birt.chart.model chart.model.attribute class and interface hierarchy The chart.model.attribute package contains classes that define the permitted values for attributes as static fields. Figure 4-21 contains the class hierarchy for org.eclipse.birt.chart.model.attribute.
Chapter 4, Understanding the BIRT APIs 59 java.lang.Object
org.eclipse.emf.common.util.AbstractEnumerator
ActionType
Anchor
AngleType
AxisType
ChartDimension
ChartType
CursorType
DataPointComponentType
DataType
DateFormatDetail
DateFormatType
Direction
GroupingUnitType
HorizontalAlignment
IntersectionType
LeaderLineStyle
LegendBehaviorType
LegendItemType
LineDecorator
LineStyle
MarkerType
MenuStylesKeyType
Orientation
Position
Figure 4-21 Classes in org.eclipse.birt.chart.model.attribute
60 Integrating Applications into BIRT iHub RiserType
RuleType
ScaleUnitType
SortOption
Stretch
StyledComponent
TickStyle
TriggerCondition
TriggerFlow
UnitsOfMeasurement
VerticalAlignment Figure 4-21 Classes in org.eclipse.birt.chart.model.attribute The interfaces in the chart.model.attribute provide the getter and setter methods that chart engine objects use to test and set the values of the attributes. Figure 4-22 contains the interface hierarchy for org.eclipse.birt.chart.model.attribute.
AttributePackage.Literals
org.eclipse.emf.common.notify.Notifier
org.eclipse.emf.ecore.EObject
org.eclipse.emf.ecore.EModelElement
org.eclipse.emf.ecore.EFactory
AttributeFactory
org.eclipse.emf.ecore.ENamedElement
org.eclipse.emf.ecore.EPackage
AttributePackage Figure 4-22 Interfaces in org.eclipse.birt.chart.model.attribute
Chapter 4, Understanding the BIRT APIs 61 org.eclipse.birt.chart.model.IChartObject
ActionValue
AccessibilityValue
CallbackValue
MultiURLValue
ScriptValue
SeriesValue
TooltipValue
URLValue
Angle3D
AxisOrigin
Bounds
Cursor
DataPoint
DataPointComponent
ExtendedProperty
Fill
ColorDefinition
Gradient
Image
EmbeddedImage
PatternImage
MultipleFill
Figure 4-22 Interfaces in org.eclipse.birt.chart.model.attribute
62 Integrating Applications into BIRT iHub FontDefinition
FormatSpecifier
DateFormatSpecifier
FractionNumberFormatSpecifier
JavaDateFormatSpecifier
JavaNumberFormatSpecifier
NumberFormatSpecifier
StringFormatSpecifier
Insets
Interactivity
LineAttributes
Location
Location3D
Marker
Palette
Rotation3D
Size
Style
StyleMap
Text
TextAlignment Figure 4-22 Interfaces in org.eclipse.birt.chart.model.attribute
Chapter 4, Understanding the BIRT APIs 63 chart.model.component interface hierarchy The chart.model.component package contains the interfaces that define the behavior of all the components that make up a chart. Figure 4-23 contains the interface hierarchy for org.eclipse.birt.chart.model.component.
ComponentPackage.Literals
org.eclipse.emf.common.notify.Notifier
org.eclipse.emf.ecore.EObject
org.eclipse.emf.ecore.EModelElement
org.eclipse.emf.ecore.EFactory
ComponentFactory
org.eclipse.emf.ecore.ENamedElement
org.eclipse.emf.ecore.EPackage
ComponentPackage
org.eclipse.birt.chart.model.IChartObject
Axis
ChartPreferences
CurveFitting
Dial
Grid
Label
MarkerLine
MarkerRange
DialRegion
Needle
Scale
Series Figure 4-23 Interfaces in org.eclipse.birt.chart.model.component
64 Integrating Applications into BIRT iHub chart.model.data interface hierarchy The chart.model.data package contains interfaces that define a data source, a query structure, and the data components for a chart. These interfaces define getter and setter methods for data set properties and the permitted values for these properties as static fields. Figure 4-24 contains the interface hierarchy for org.eclipse.birt.chart.model.data.
DataPackage.Literals
org.eclipse.emf.common.notify.Notifier
org.eclipse.emf.ecore.EObject
org.eclipse.emf.ecore.EModelElement
org.eclipse.emf.ecore.EFactory
DataFactory
org.eclipse.emf.ecore.ENamedElement
org.eclipse.emf.ecore.EPackage
DataPackage
org.eclipse.birt.chart.model.IChartObject
Action
MultipleActions
BaseSampleData
DataElement
DateTimeDataElement
NumberDataElement
TextDataElement Figure 4-24 Interfaces in org.eclipse.birt.chart.model.data
Chapter 4, Understanding the BIRT APIs 65 DataSet
BubbleDataSet
DateTimeDataSet
DifferenceDataSet
GanttDataSet
NullDataSet
NumberDataSet
StockDataSet
TextDataSet
OrthogonalSampleData
Query
Rule
SampleData
SeriesDefinition
SeriesGrouping
Trigger Figure 4-24 Interfaces in org.eclipse.birt.chart.model.data chart.model.layout interface hierarchy The chart.model.layout package contains the interfaces that define and arrange the blocks that make up the main components of a chart, such as the plot, title, and legend areas. Figure 4-25 contains the interface hierarchy for org.eclipse.birt.chart.model.layout.
66 Integrating Applications into BIRT iHub LayoutPackage.Literals
org.eclipse.emf.common.notify.Notifier
org.eclipse.emf.ecore.EObject
org.eclipse.emf.ecore.EModelElement
org.eclipse.emf.ecore.EFactory
LayoutFactory
org.eclipse.emf.ecore.ENamedElement
org.eclipse.emf.ecore.EPackage
LayoutPackage
org.eclipse.birt.chart.model.IChartObject
Block
LabelBlock
TitleBlock
Legend
Plot
ClientArea Figure 4-25 Interfaces in org.eclipse.birt.chart.model.layout chart.model.type interface hierarchy The chart.model.type package contains the interfaces that define the series for all the available chart types. Figure 4-26 contains the interface hierarchy for org.eclipse.birt.chart.model.type.
Chapter 4, Understanding the BIRT APIs 67 org.eclipse.emf.common.notify.Notifier
org.eclipse.emf.ecore.EObject
org.eclipse.emf.ecore.EModelElement
org.eclipse.emf.ecore.EFactory
TypeFactory
org.eclipse.emf.ecore.ENamedElement
org.eclipse.emf.ecore.EPackage
TypePackage
org.eclipse.birt.chart.model.IChartObject
org.eclipse.birt.chart.model.component.Series
BarSeries
DialSeries
GanttSeries
LineSeries
AreaSeries
DifferenceSeries
ScatterSeries
BubbleSeries
PieSeries
StockSeries
TypePackage.Literals Figure 4-26 Interfaces in org.eclipse.birt.chart.model.type
68 Integrating Applications into BIRT iHub chart.render class and interface hierarchy The chart.render package contains classes and interfaces that render a chart. Figure 4-27 contains the interface hierarchy for org.eclipse.birt.chart.render.
IActionRenderer
IAccessDecorator
ISeriesRenderer
ISeriesRenderingHints
ISeriesRenderingHints3D Figure 4-27 Interfaces in org.eclipse.birt.chart.render Figure 4-28 contains the class hierarchy for org.eclipse.birt.chart.render.
java.lang.Object
ActionRendererAdapter IActionRenderer
AxesRenderHelper
BaseRenderer ISeriesRenderer
AxesRenderer
EmptyWithAxes
EmptyWithoutAxes
CurveRenderer
DeferredCache
DeferredCacheManager
InteractiveRenderer
MarkerRenderer Figure 4-28 Classes in org.eclipse.birt.chart.render chart.script class and interface hierarchy The chart.script package contains the classes and interfaces that support script handling for chart developers to write custom code within the chart class itself. Figure 4-29 contains the class and interface hierarchy for org.eclipse.birt.chart.script.
Chapter 4, Understanding the BIRT APIs 69 java.lang.Object
AbstractScriptContext IScriptContext
ChartScriptContext IChartScriptContext
ChartEventHandlerAdapter IChartEventHandler
org.mozilla.javaScript.ScriptableObject
AbstractScriptHandler
ScriptHandler
ScriptClassLoaderAdapter IScriptClassLoader
IChartEventHandler
IScriptClassLoader
java.io.Serializable
IExternalContext
IScriptContext
IChartScriptContext Figure 4-29 Classes and interfaces in org.eclipse.birt.chart.script package chart.util class hierarchy The chart.util package contains classes that support data types and looking up attribute and property values in the literal classes. Figure 4-30 contains the class hierarchy for org.eclipse.birt.chart.util.
java.lang.Object
com.ibm.icu.util.Calendar
com.ibm.icu.util.GregorianCalendar
CDateTime Figure 4-30 Classes in org.eclipse.birt.chart.util
70 Integrating Applications into BIRT iHub Chapter 5
Chapter 5Programming using the BIRT reporting APIs
This chapter contains the following topics: ■ Reporting application overview ■ Choosing POJO or OSGi run-time deployment ■ Building a reporting application ■ Generating reports from an application ■ Programming the structure of a report design
Chapter 5, Programming using the BIRT reporting APIs 71 Reporting application overview A reporting application uses the BIRT Report Engine API to generate reports from report design (.rptdesign) files. Typically, the application produces the report as a formatted file or stream, in HTML or PDF format. Alternatively, the application creates a report document (.rptdocument) file that contains the report content in binary form and renders the report to one of the supported output formats later. This chapter describes the fundamental requirements of a reporting application and describes the BIRT API classes and interfaces that you use in the application. This chapter also provides detailed information about the tasks that a reporting application performs. There are two Report Engine run-time environments. The newer one is a simplified Plain Old Java Object (POJO) configuration and the other is an OSGi run time. The BIRT APIs in the org.eclipse.birt.report.engine.api package support the process of generating a report from a report design. This package provides the ReportEngine class and supporting interfaces and classes. Optionally, the reporting application can use the BIRT Design Engine API to access the structure of report designs, templates, and libraries. Using this API, the application can create and modify report designs before generating a report. This API supports creating and modifying the report items and other elements within designs. The org.eclipse.birt.report.model.api package and its subpackages provide access to all the items that comprise a report design. For complete information about all the methods and fields of the classes and interfaces in these packages, see the online Javadoc. You must have the BIRT SDK package installed in order to access the Javadoc. Instructions on installing the SDK are provided in Installing and Deploying BIRT. To view the Javadoc, open the online help and navigate to BIRT Programmer Reference➛Reference➛API Reference. Choose Report Engine API Reference for the Report Engine API and Report Object Model API Reference for the Design Engine API. The Javadoc also shows supporting packages in the public API.
Choosing POJO or OSGi run-time deployment The standard BIRT Report Engine run time is a POJO run time. It is recommended for most application development purposes, including installation in a Java Enterprise Edition (EE) application server to run reports over the web. The POJO run time is included in the Report Designer Full Eclipse Install (All-in-One) download, which provides a complete Eclipse environment for BIRT.
72 Integrating Applications into BIRT iHub The POJO run time is also available as a separate download. That download includes a WebViewerExample directory, which simplifies initial deployment to an application server, as shown in Figure 5-1.
BIRT-Runtime-4_3_1
BIRT.war
WebViewerExample
webcontent Customizable JSP/JS files
WEB-INF
lib
BIRT JARs
ReportEngine
lib
BIRT JARs Figure 5-1 BIRT Report Engine POJO run-time structure If you wish to deploy the BIRT run time as an OSGi run time, that is available as well. Since the first releases of BIRT included only this run time choice, you may need to continue using it to support your existing applications. Both environments include the classes and interfaces described in this chapter. Also, note that OSGi is a framework designed with modularization and decoupling in mind; OSGi services are, in fact, POJOs themselves. Conversely, the POJO environment continues to use some OSGi services.
Building a reporting application An application that generates a report must complete the required tasks described in the following sections. Additional tasks, such as supplying user-entered values for parameters, are optional.
Chapter 5, Programming using the BIRT reporting APIs 73 Creating and configuring a report engine A single report engine object can generate multiple reports from multiple report designs. Use the Platform.createFactoryObject( ) method to create a ReportEngine object. For OSGi, set the BIRT home directory in the BIRT_HOME environment variable, which defines the location of required plug-ins and libraries.
Opening a report design or report document Use one of the openReportDesign( ) methods of the ReportEngine class to open a report design from a String file name or an input stream. These methods return an IReportRunnable object. Use the openReportDocument( ) method of the ReportEngine class to open a report document (.rptdocument) file from a String file name. This method returns an IReportDocument object.
Ensuring access to the data source Ensure the report engine can locate the classes that connect to the data source and supply data to the data set. The report engine can either create a connection to the data source or use a Connection object that the application provides.
Preparing to create a report in the supported output formats Use an IRenderOption object to set the output format, the output file name or stream, the locale, and format-specific settings. The HTMLRenderOption class supports the HTML output format. For PDF output, use PDFRenderOption.
Generating a report in one of the supported output formats Use an IRunAndRenderTask object to create the report from the IReportRunnable object. Use an IRenderTask object to create the report from an IReportDocument object. Alternatively, use a URL to access the report viewer servlet, such as when deploying a BIRT report to an application server, as described earlier in this book. The report viewer can generate a report from either a design or a document file.
Destroying the engine Destroy the report engine after the application has generated all required reports.
Optional tasks The tasks in the following list are optional for a reporting application. Typically, the application performs one or more of these tasks. ■ Gather values for parameters. If the application uses a report design that has parameters, use the default values for the parameters or set different values.
74 Integrating Applications into BIRT iHub ■ Create a report document file. A report document file contains the report in a binary storage form. If the application uses a report design, use an IRunTask object to create the report document as an IReportDocument object. ■ Export data from a report document. Use an IDataExtractionTask object to extract data values from any item or set of items in the report document. Export the data values to a file or another application, or perform further processing on the data. About the development environment The development environment for a reporting application must provide access to all the required API libraries. For OSGi, which includes plug-ins in addition to library jars, the key requirement for the application is the path to the BIRT home directory. About plug-ins in BIRT home (OSGi only) The plugins subdirectory of the BIRT home directory contains the org.eclipse.birt and other plug-ins that provide the functionality of a reporting application. Depending on the requirements of your reporting application and the items in your report designs, you can omit plug-ins that provide functionality that the application and designs do not use.
About the BIRT libraries The lib subdirectory contains JAR files providing BIRT API classes and classes that support the APIs. For POJO run time, applicable JARs from your lib subdirectory need to be in your application’s build path or, in the case of a web application, in the WEB-INF/lib directory. For OSGi, the BIRT home directory ensures that the class loader of the application server or JVM in which you deploy the report engine can locate the libraries. Depending on the requirements of your reporting application and the items in your report designs, you can omit libraries that provide functionality that the application and designs do not use. Table 5-1 lists and describes all the JAR files in the POJO lib directory. Table 5-2 lists and describes all the JAR files in the OSGi lib directory. Table 5-1 Libraries in the BIRT POJO run-time lib directory Library Description com.ibm.icu_
Chapter 5, Programming using the BIRT reporting APIs 75 Table 5-1 Libraries in the BIRT POJO run-time lib directory (continued) Library Description derby.jar Used for access to Derby databases. flute.jar Used by the report.model plug-in. Provides access to CSS functionality. javax.*_
Table 5-2 Libraries in the BIRT OSGi home lib directory Library Description chartengineapi.jar Contains chart model and factory API classes. Supports generation of charts in a report. chartexamplescoreapi.jar Contains classes providing an example of a charting extension. chartitemapi.jar Contains the classes for the chart report item.
76 Integrating Applications into BIRT iHub Table 5-2 Libraries in the BIRT OSGi home lib directory Library Description com.ibm.icu_
Chapter 5, Programming using the BIRT reporting APIs 77 About required JDBC drivers BIRT applications load JDBC drivers from the directory plugins/org.eclipse.birt.report.data.oda.jdbc_
Setting up the build path and accessing Javadoc To access the BIRT APIs during application development using the Java perspective in the Eclipse Workbench, add API JAR files to the build path. To view the Javadoc, open the online help and navigate to BIRT Programmer Reference➛Reference➛API Reference. Choose Report Engine API Reference for the Report Engine API and Report Object Model API Reference for the Design Engine API.
How to add BIRT libraries and API Javadoc to a Java application’s build path Use the Java perspective in the Eclipse Workbench to perform these steps on an existing Java project. 1 If you did not start with the BIRT All-in-One download, unzip the BIRT run time to a directory. For OSGi, this directory is the BIRT home directory. 2 In Package Explorer, right-click the Java project. Choose Build Path ➛Configure Build Path. 3 In Properties for
78 Integrating Applications into BIRT iHub 4 If necessary, correct the path to the Javadoc. In Javadoc for
Generating reports from an application The key tasks that a reporting application must perform are to set up the report engine, any required parameter values, and the task objects to generate the report document, and finally to render the report. The reporting application does not require the BIRT Report Designer user interface to generate a report. The org.eclipse.birt.report.engine.api package contains the classes and interfaces that an application uses to generate reports. The main classes and interfaces are ReportEngine, EngineConfig, IReportRunnable, IRenderOption and its descendants, and IEngineTask and its descendants. Setting up the report engine A report engine is an instantiation of the ReportEngine class. This object is the key component in any reporting application. It provides access to runnable report designs, parameters, the structure of a report design, and the task for generating a report from a report design. Prepare the report engine’s properties with an EngineConfig object. After setting all the required properties, use the BIRT engine factory to create the report engine. The following sections describe the various configuration options and creation of the engine.
Chapter 5, Programming using the BIRT reporting APIs 79 Configuring the BIRT home (OSGi only) The BIRT home, which is the location of the BIRT plug-ins and libraries, is the key property that the OSGi report engine requires. The OSGi report engine cannot parse a report design nor render the report without a defined BIRT home. For a stand-alone application, the BIRT home is an absolute path to a file system location. For an application running from a web archive (.war) file on an application server, the BIRT home is a relative path in the WAR file. To set the BIRT home location, use one of the following techniques: ■ For a stand-alone application, use one of the following techniques: ■ Call EngineConfig.setBIRTHome( ) with an argument that is the path to the BIRT home directory, for example: config.setBIRTHome("C:/birt-runtime-
■ In the application’s environment, set up the BIRT_HOME and CLASSPATH variables to access the required libraries. For example, in a Windows batch file, include commands similar to the following ones before launching the stand-alone application: set BIRT_HOME="C:\birt-runtime-
■ For a deployed web application, use one of the following techniques: ■ If the application has a location in the file system, use the servlet context to find the real path of the BIRT home, for example: config.setBIRTHome( servletContext.getRealPath("/WEB-INF") );
■ If the application runs from a WAR file, use a relative path from the WAR file root, as shown in the following example. This configuration uses PlatformServletContext.
config.setBIRTHome( "" );
■ If you use BIRT in an Eclipse-based application, such as an RCP application, and the BIRT plug-ins are located in the application’s plugins directory, you do not need to set BIRT_HOME. Configuring the report engine Set configuration properties using methods on an EngineConfig object.
80 Integrating Applications into BIRT iHub Table 5-3 describes these properties and how to set them using EngineConfig methods. The EngineConfig class also provides getter methods to access these properties. Table 5-3 EngineConfig properties Property type Setting the property Configuring an emitter To set the properties for the required report output format, call setEmitterConfiguration( ) with arguments providing the format and a IRenderOption object for that format. Logging To set the logging file location and level, call setLogConfig( ). To refine the logging file name and properties, use the other setLogXXX( ) methods. OSGi configuration To set specific OSGi start-up parameters, call setOSGiArguments( ) or setOSGiConfig( ). Platform context To indicate whether the application is in a stand-alone environment or packaged as a web archive (.war) file, create an implementation of the IPlatformContext interface. Then, call setPlatformContext( ). Resource files To set the location from which the reporting application accesses resource files such as libraries and properties files containing localized strings, call setResourcePath( ). To change the algorithm for locating these resources, call setResourceLocator( ). Scripting configuration To provide external values to scripting methods, call setProperty( ). To provide additional Java resources to scripting methods, call getAppContext( ) and add the object to the application context object. Status handling To provide a custom status handler, create an implementation of the IStatusHandler interface. Then, call setStatusHandler( ). Temporary file location To set up a custom location for temporary files, call setTempDir( ).
Setting up a stand-alone or WAR file environment Two engine configuration properties depend on whether the environment in which the application runs is stand-alone or in a web archive (.war) file on an application server. These properties are the platform context and the HTML emitter configuration. The platform context provides the report engine with the mechanism to access plug-ins. The default platform context provides direct file system access to these plug-ins, as used by a stand-alone application. The HTML emitter configuration provides the functionality to process images and handle hyperlinking and bookmark actions.
Chapter 5, Programming using the BIRT reporting APIs 81 Setting up the platform context Because BIRT is an Eclipse-based application, it uses the OSGi platform to start up the plug-ins that make up the report and design engines. The BIRT application locates the plug-ins in the Java build path or in the BIRT home using the platform context, which is an implementation of the org.eclipse.birt.core .framework.IPlatformContext interface. This interface defines the method, getPlatform( ) that returns the location of the plugins directory. Use the IPlatformContext object as the argument to the EngineConfig object’s setPlatformContext( ) method. The BIRT framework provides two implementations of the IPlatformContext interface. These implementations provide all the required functionality for the platform context. The default implementation, PlatformFileContext, accesses the plug-ins in the BIRT home folder on the file system. For OSGi, the application either sets the BIRT home location in the EngineConfig object or the application environment contains BIRT_HOME and creating a PlatformFileContext object is not necessary. For a web deployment, such as an application running from a WAR file on an application server, use the PlatformServletContext implementation. This class uses the resource-based access provided by the J2EE ServletContext class to locate the required plug-ins. The constructor for this class takes one argument, a ServletContext object. By default, PlatformServletContext finds plug-ins in the /WEB-INF/platform/ directory by using the ServletContext.getRealPath( ) method. Some application servers return null from this method. In this case, the PlatformServletContext object creates a platform directory in the location defined by the system property, javax.servlet.context.tempdir. The PlatformServletContext object copies the plug-ins and configuration folders to this location. Listing 5-1 sets up a platform context for a reporting application that runs from a WAR file. You can also implement your own version of IPlatformContext. In the same way as for the built-in platform contexts, call EngineConfig.setPlatformContext( ) to configure the engine to use the new implementation.
How to set up a report engine as a web application 1 Set up the platform context, as shown in Listing 5-1. Listing 5-1 Setting up the platform context for WAR file deployment
//Example class to create the report engine public class BirtEngine { private static IReportEngine birtEngine = null; public static synchronized IReportEngine getBirtEngine( ServletContext sc ) {
82 Integrating Applications into BIRT iHub if (birtEngine == null) { EngineConfig config = new EngineConfig( ); //config.setBIRTHome( "" ); IPlatformContext context = new PlatformServletContext( sc ); config.setPlatformContext( context ); try { Platform.startup( config ); IReportEngineFactory factory = ( IReportEngineFactory ) Platform.createFactoryObject ( IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY ); birtEngine = factory.createReportEngine( config ); } catch ( Exception e ) { e.printStackTrace( ); } } return birtEngine; } } 2 Set up further configuration options on the engine after instantiating the class, as shown in Listing 5-2. Listing 5-2 Setting up HTML options for WAR file deployment
// In a different class, get the report engine IReportEngine reportEngine = BirtEngine.getBirtEngine ( request.getSession( ).getServletContext( )); // Set up the engine EngineConfig config = reportEngine.getConfig( ); HTMLRenderOption ho = new HTMLRenderOption( ); ho.setImageHandler( new HTMLServerImageHandler( )); ho.setImageDirectory("output/image"); ho.setBaseImageURL("http://myhost/prependme?image="); config.setEmitterConfiguration( RenderOption.OUTPUT_FORMAT_HTML, ho ); In this listing, request is an HttpServletRequest object.
Setting up the HTML emitter To generate a report in HTML format, the report engine uses an org.eclipse .birt.report.engine.api.HTMLRenderOption object to determine how to handle resources that the HTML emitter uses or creates. These resources include new image files for image elements and chart elements, and the locations of jumps from bookmark and drill-through actions. BIRT uses different image handlers for file system-based applications and applications deployed on the web. Use the EngineConfig object to set up the HTML emitter options when creating the report
Chapter 5, Programming using the BIRT reporting APIs 83 engine, as shown in Listing 5-3, or set the options later when rendering a report to HTML. To set up the HTML emitter, instantiate an HTMLRenderOption object. Use this object as the argument to ReportEngine.setEmitterConfiguration( ) to define the HTML rendering options when creating the report engine. Call the HTMLRenderOption.setImageHandler( ) method to configure the image handler. This method determines how to save the image files by using an org.eclipse.birt.report.engine.api.IHTMLImageHandler object. Images defined in a report as a URL are not saved locally. BIRT provides two implementations of the IHTMLImageHandler interface. Both implementations create unique image file names for temporary images. The default image handler implementation, HTMLCompleteImageHandler, saves images to the file system. Use this implementation for a stand-alone application or for a web application that uses file system deployment on the application server. This image handler finds the location for images by searching first for the image directory set in the HTMLRenderOption object, next the temporary files directory as set by the EngineConfig.setTempDir( ) method, and finally the location set by the system setting, java.io.tmpdir. All images in the generated HTML use file references to the created images. For a web deployment, such as an application running from a WAR file on an application server, use the HTMLServerImageHandler implementation. This class saves images to the image directory set in the HTMLRenderOption object. The src attribute of images in the generated HTML appends the image name to the base image URL, also set in the HTMLRenderOption object. In this way, the report engine produces the images locally and shares the images using a URL. To use this implementation, set the image directory and the base image URL, as shown in Listing 5-2. The example BIRT Web Viewer in the org.eclipse.birt.report.viewer plug-in uses this implementation. If neither IHTMLImageHandler meets your needs, create a class that implements IHTMLImageHandler or extends an existing image handler. Typically, HTMLCompleteImageHander provides sufficient functionality for file system access, so an application does not extend the class. For the application server environment, extend from HTMLServerImageHandler. To configure the engine to use the new implementation, in the same way as for the built-in image handlers, call EngineConfig.setEmitterConfiguration( ).
Starting the platform After setting up the PlatformContext, an application starts the platform by using the org.eclipse.birt.core.framework.Platform class. This class acts as a wrapper around the Eclipse OSGILauncher class and provides the method, startup( ), to start the platform. Calling this synchronized static method uses substantial system resources, so an application should call this method only once. If the report engine is deployed in a web application, call Platform.startup( ) in the
84 Integrating Applications into BIRT iHub servlet’s init( ) method or in the first request that uses the platform. To achieve this behavior, wrap the platform start-up code in a singleton, as shown in Listing 5-1. When an application finishes using the platform, call Platform.shutdown( ). If you use the example Web Viewer or deploy the report engine in an Eclipse-based project such as a Rich Client Platform (RCP) application, do not start up or shut down the platform, because these applications control the OSGi start-up and shutdown.
Creating the report engine BIRT provides a factory service to create the ReportEngine object. Call Platform.createFactoryObject( ) to create this factory, which implements the org.eclipse.birt.report.engine.api.IReportEngineFactory interface. The createFactoryObject( ) method uses a PlatformConfig object. Call IReportEngineFactory.createReportEngine( ) to create the report engine.
How to set up a report engine as a stand-alone application Listing 5-3 shows an example of setting up a report engine as a stand-alone application on a Windows system. The application uses the BIRT home located in the BIRT run-time directory. The report output format is HTML. Listing 5-3 Setting up the report engine for a stand-alone application
//Create an EngineConfig object. EngineConfig config = new EngineConfig( ); //For OSGi, set up the path to your BIRT home directory. //config.setBIRTHome ( "C:/Program Files/birt-runtime-4_3_0/ReportEngine" ); //Start the platform for a non-RCP application. try { Platform.startup( config ); IReportEngineFactory factory = ( IReportEngineFactory ) Platform.createFactoryObject ( IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY ); // Set up writing images or charts embedded in HTML output. HTMLRenderOption ho = new HTMLRenderOption( ); ho.setImageHandler( new HTMLCompleteImageHandler( )); config.setEmitterConfiguration ( RenderOption.OUTPUT_FORMAT_HTML, ho ); // Create the engine. IReportEngine engine = factory.createReportEngine( config ); } catch ( BirtException e ) { e.printStackTrace(); }
Using the logging environment to debug an application BIRT Report Engine uses the java.util.logging classes, Logger and Level, to log information about the processing that the engine performs. When an application
Chapter 5, Programming using the BIRT reporting APIs 85 runs in the Eclipse Workbench, by default, the messages appear in the console. When an application runs outside Eclipse, the default location of the log messages depends on the environment. The default logging threshold is Level.INFO. Typically, you change this level in your application to reduce the number of internal logging messages. To set up the logging environment to write the engine’s log messages to a file, use the EngineConfig.setLogConfig( ) method. This method takes two arguments. The first argument is the directory in which to create the log file. The second argument is the lowest level at which to log information. Set the logging level to a high threshold so that the engine logs fewer messages. Typically, you want to see information at INFO level when you first develop a block of code. Use the ReportEngine.changeLogLevel( ) method to modify the amount of information that the engine logs. This method takes a single argument, which is a Level constant. When the code is stable, you no longer need to see all the engine’s INFO messages. At that point, delete or comment out the call to changeLogLevel( ). BIRT Report Engine creates a log file with a name of the format ReportEngine_YYYY_MM_DD_hh_mm_ss.log. To change this name, call EngineConfig.setLogFile( ). Use the EngineConfig methods, setLogRollingSize( ) and setLogMaxLogBackupIndex( ), to control the size and number of log files.
How to use BIRT logging The following example shows how to use logging in an application. You set up the logging environment and modify it later in your application. The variable, config, is the EngineConfig object that the code’s active ReportEngine object, engine, is using. 1 Configure logging on the report engine object. // Set up the location and level of the logging output. config.setLogConfig( "C:/Temp", Level.SEVERE ); config.setLogFile( "myBIRTApp.log" ); 2 In any newly written code, increase the amount of logging. engine.changeLogLevel( Level.INFO );
Opening a source for report generation BIRT Report Engine classes generate a formatted report from either a report design or a binary report document. Typically, these files have the extensions RPTDESIGN and RPTDOCUMENT respectively. The engine can also generate a binary report document from a report design. To open a report design, call one of the openReportDesign( ) methods on ReportEngine. These methods instantiate an IReportRunnable object, using a String that specifies the path to a report design or an input stream. To open a report document, call ReportEngine.openReportDocument( ). This method
86 Integrating Applications into BIRT iHub instantiates an IReportDocument object, using a String that specifies the path to a report document. Handle the EngineException that these methods throw.
Understanding an IReportRunnable object The IReportRunnable object provides direct access to basic properties of the report design. The names of report design properties are static String fields, such as IReportRunnable.AUTHOR. To access a report design property, use getProperty( ) with a String argument that contains one of these fields. To generate a report from a design, open the report design as shown in Listing 5-4. Then, perform the tasks shown later in this chapter.
How to access a report design Listing 5-4 shows how to open a report design and find a property value. If the engine cannot open the specified report design, the code destroys the engine. The variable, engine, is a ReportEngine object. Listing 5-4 Accessing a report design
String designName = "./SimpleReport.rptdesign"; IReportRunnable runnable = null; try { runnable = engine.openReportDesign( designName ); } catch ( EngineException e ) { System.err.println ( "Design " + designName + " not found!" ); engine.destroy( ); System.exit( -1 ); } // Get the value of a simple property. String title = ( String ) runnable.getProperty ( IReportRunnable.TITLE );
Understanding an IReportDocument object The IReportDocument object provides access to the structure and contents of a binary report document. IReportDocument provides methods to retrieve bookmark, page, and report design information. A bookmark is a String object that locates an instance of a report element in the document and the page on which the element exists. Use page information to render individual pages in the document to an output format. Bookmarks also provide access to the design elements that generated the element instance. Use the getBookmarks( ) method to get a List object containing all the bookmarks in the document. Call the getBookmarkInstance( ) method with a String argument containing a bookmark to access the instantiated report element. Calling the getReportRunnable( ) method returns an IReportRunnable object, which an
Chapter 5, Programming using the BIRT reporting APIs 87 application can use to access report design information or generate another report document. Close the document after use by calling IReportDocument.close( ).
How to access a report document Listing 5-5 shows how to open a report document and find a page. If the engine cannot open the specified report design, the code logs the error. The variable, engine, is a ReportEngine object. Listing 5-5 Accessing a report document
String dName = "./SimpleReport.rptdocument"; IReportDocument doc = null; try { doc = engine.openReportDocument( dName ); } catch ( EngineException e ) { System.err.println( "Document " + dName + " not found!" ); return; } // Get the second bookmark in the document. java.util.List bookmarks = doc.getBookmarks( ); String bookmark = ( String ) bookmarks.get( 1 ); long pageNumber = doc.getPageNumber( bookmark ); logger.log(Level.INFO, bookmark + " Page number: " + pageNumber); // Close the document. doc.close( );
Accessing a report parameter A report parameter is a report element that provides input to a report design before an application generates the report. A report document does not use report parameters to create a formatted report. If an application already has the parameter names and the values to set, or the default values for all report parameters for a report design are always valid, or the report source is a report document, you do not need to perform the tasks in this section. Report parameters have attributes that a reporting application can access. The most commonly used attributes are name and value. The report engine uses the report design logic and the report parameter values to perform tasks such as filtering a data set or displaying an external value in the report. After the reporting application sets values for the report parameters, it must pass these values to the task that generates the report, as shown later in this chapter. To access report parameters and their default values and to set user-supplied values to a parameter, the application uses the BIRT Report Engine API classes and interfaces shown in Table 5-4.
88 Integrating Applications into BIRT iHub An application can access report parameters by name or using generic code. Use generic code if the application must be able to run any report design, for example, to access report designs from a list that depends on user input. An application that runs only a fixed set of known report designs can access the report parameters by name. Table 5-4 Classes and interfaces that support report parameters Class or interface Use ReportEngine class Instantiates the task that accesses report parameters. To create the task object, call the createGetParameterDefinitionTask( ) method. This method returns an instance of IGetParameterDefinitionTask. IGetParameterDefinitionTask Accesses a single report parameter or a interface collection of all the report parameters in a report design. Also provides access to valid values for parameters that use restricted sets of values, such as cascading parameters. IParameterDefnBase The base interface for report parameter interface elements. Scalar parameters implement the derived interface, IScalarParameterDefn. Parameter groups implement the derived interface IParameterGroupDefn. To get information about parameter attributes, use objects implementing these interfaces. IParameterGroupDefn The base interface for report parameter groups. interface Cascading parameter groups implement the derived interface ICascadingParameterGroup. IParameterSelectionChoice Defines valid values for a report parameter that interface uses a restricted set of values, such as a cascading parameter. ReportParameterConverter Converts a String value provided by a user class interface into a locale-independent format.
Creating a parameter definition task object for the report design A single IGetParameterDefinitionTask object provides access to all parameters in a report design. Create only one of these objects for each report design, by calling ReportEngine.createGetParameterDefinitionTask( ). Close the parameter definition task object after use by calling its close( ) method.
Chapter 5, Programming using the BIRT reporting APIs 89 Testing whether a report design has report parameters To test if a report design has report parameters, call the getParameterDefns( ) method on IGetParameterDefinitionTask. This method returns a Collection. To test whether the Collection has elements call the Collection.isEmpty( ) method. An application that runs only known report designs does not need to perform this task.
Getting the report parameters in a report design To access a single report parameter of a known name, use the IGetParameterDefinitionTask.getParameterDefn( ) method. This method returns an object of type IParameterDefnBase. Use the IGetParameterDefinitionTask.getParameterDefns( ) method to return a Collection of IParameterDefnBase objects. The application can then use an Iterator to access each report parameter from this Collection in turn. The getParameterDefns( ) method takes a boolean argument. For an argument value of false, the method returns an ungrouped set of report parameters. For a value of true, the method returns parameter groups, as defined in the report design. To create a user interface that replicates the parameter group structure, use a value of true. To check whether a report parameter is a group, the application must call IParameterDefnBase.getParameterType( ). This method returns IParameterDefnBase.PARAMETER_GROUP if the parameter is a group or IParameterDefnBase.CASCADING_PARAMETER_GROUP if the parameter is a cascading parameter group. To access the group’s report parameters, use the IParameterGroupDefn.getContents( ) method. This method returns an ArrayList object of objects of type IScalarParameterDefn.
Getting the default value of each report parameter This task is optional. To get the default value of a single known report parameter, use IGetParameterDefinitionTask.getDefaultValue( ). This method returns an Object. To determine the effective class of the Object, use IScalarParameterDefn .getDataType( ). This method returns an int value, which is one of the static fields in IScalarParameterDefn. Call IGetParameterDefinitionTask.getDefaultValues( ) to get the default value of all parameters in the report design. This method returns a HashMap object, which maps the report parameter names and their default values.
Getting valid values for parameters using a restricted set of values Some report parameters accept only values from a restricted list. In some cases, this list is a static list of values, such as RED, BLUE, or GREEN. In other cases, the list is dynamic and a query to a database provides the valid values. For example, a query can return the set of sales regions in a sales tracking database. To determine the list of valid values, call the method,
90 Integrating Applications into BIRT iHub IGetParameterDefinitionTask.getSelectionList( ). This method returns a Collection of IParameterSelectionChoice objects. IParameterSelectionChoice has two methods. getLabel( ) returns the display text and getValue( ) returns the value. If the Collection is null, the report parameter can take any value.
Getting the attributes of each report parameter This task is optional. To get the attributes of a report parameter, use the IScalarParameterDefn methods. The application can use the attributes to generate a customized user interface. For example, to get the data type of a report parameter, use the getDataType( ) method.
Collecting an updated value for each report parameter To provide new values for the report parameters, provide application logic such as a user interface or code to retrieve values from a database. Call IGetParameterDefinitionTask.setParameterValue( ) to set the value of the parameter. If a user interface returns String values to your application for date and number parameters, convert the String into a locale-independent format before setting the value. To perform this task, call the method, ReportParameterConverter.parse( ), before calling setParameterValue( ). After setting the report parameter values, call the method, IGetParameterDefinitionTask.getParameterValues( ). This method returns a HashMap object containing the current parameter values as set by calls to IGetParameterDefinitionTask.setParameterValue( ). Use this HashMap object to set parameter values for report generation, as described later in this chapter.
How to set the value of a known report parameter The code sample in Listing 5-6 shows how to set the value of a report parameter that has a known name. The sample creates a HashMap object that contains the parameter values to use later to run the report. The variable, engine, is a ReportEngine object. The variable, runnable, is an object of type IReportRunnable. This sample does not show details of code for retrieving the parameter value from a user interface or a database. The code to perform these tasks depends on your application’s requirements. Listing 5-6 Setting the value of a single parameter
// Create a parameter definition task. IGetParameterDefinitionTask task = engine.createGetParameterDefinitionTask( runnable ); // Instantiate a scalar parameter. IScalarParameterDefn param = (IScalarParameterDefn) task.getParameterDefn( "customerID" ); // Get the default value of the parameter. In this case, // the data type of the parameter, customerID, is Double.
Chapter 5, Programming using the BIRT reporting APIs 91 int customerID = ((Double) task.getDefaultValue( param )).intValue( ); // Get a value for the parameter. This example assumes that // this step creates a correctly typed object, inputValue. // Set the value of the parameter. task.setParameterValue( "customerID", inputValue ); // Get the values set by the application for all parameters. HashMap parameterValues = task.getParameterValues( ); // Close the parameter definition task. task.close( );
How to use the Collection of report parameters The code sample in Listing 5-7 shows how to use the Collection of report parameters. The sample uses the ReportParameterConverter class to convert the String values that the user interface supplies into the correct format for the parameter. The sample creates a HashMap object that contains the parameter values to use later to run the report. The variable, engine, is a ReportEngine object. The variable, runnable, is an IReportRunnable object. This sample does not show details of code for retrieving the parameter values from a user interface or a database. The code to perform these tasks depends on your application’s requirements. Listing 5-7 Setting the values of multiple parameters without grouping
// Create a parameter definition task. IGetParameterDefinitionTask task = engine.createGetParameterDefinitionTask( runnable ); // Create a flat collection of the parameters in the design. Collection params = task.getParameterDefns( false ); // Get the default values of the parameters. HashMap parameterValues = task.getDefaultValues( ); // Get values for the parameters. Later code in this example // assumes that this step creates a HashMap object, // inputValues. The keys in the HashMap are the parameter // names and the values are those that the user provided. // Iterate through the report parameters, setting the values // in standard locale-independent format. Iterator iterOuter = params.iterator( ); ReportParameterConverter cfgConverter = new ReportParameterConverter( "", Locale.getDefault( ) ); while ( iterOuter.hasNext( ) ) { IScalarParameterDefn param = (IScalarParameterDefn) iterOuter.next( ); String value = (String) inputValues.get( param.getName( )); if ( value != null ) {
92 Integrating Applications into BIRT iHub parameterValues.put( param.getName( ), cfgConverter.parse( value, param.getDataType( ) ) ); } } // Close the parameter definition task. task.close( ); Getting the values for cascading parameters A cascading parameter group contains an ordered set of parameters that provide lists of acceptable values for the end user to select. The value chosen for the first parameter limits the available values for the second one, and so on. The parameters use one or more queries to retrieve the values to display to the user from a data set. The parameter definition task uses the data rows from the queries to filter the values for each parameter, based on the values of preceding parameters in the group. For example, consider a cascading parameter group that uses the following query: SELECT PRODUCTS.PRODUCTLINE, PRODUCTS.PRODUCTNAME, PRODUCTS.PRODUCTCODE FROM CLASSICMODELS.PRODUCTS The group has two parameters, ProductLine on PRODUCTS.PRODUCTLINE and ProductCode on PRODUCTS.PRODUCTCODE. The display text for ProductCode uses values from PRODUCTS.PRODUCTNAME. Figure 5-2 shows the appearance of the requester that prompts for values for these parameters when a user previews the report in BIRT Report Designer.
Figure 5-2 Cascading report parameters To use the Report Engine API to get the values for cascading parameters, perform the tasks in the following list. ■ To populate the list of values for the first report parameter in the group, call IGetParameterDefinitionTask.getSelectionListForCascadingGroup( ). This
Chapter 5, Programming using the BIRT reporting APIs 93 method takes two parameters, the String name of the parameter group and an array of Object. For the first parameter, this array is empty. The method returns a Collection of IParameterSelectionChoice objects. ■ To populate the list of values for further report parameter in the group, call getSelectionListForCascadingGroup( ) again. In this case, the Object[ ] array contains the values for the preceding report parameters in the group. In the example shown in Figure 5-2, the Object[ ] array is: new Object[ ] { "Trains" }
How to use cascading parameters The code sample in Listing 5-8 accesses the set of valid values for each parameter in the cascading parameter group in turn. The variable, task, is an object of type IGetParameterDefinitionTask. Listing 5-8 Getting the valid values for cascading parameters
// Create a grouped collection of the design’s parameters. Collection params = task.getParameterDefns( true ); // Iterate through the parameters to find the cascading group. Iterator iter = params.iterator( ); while ( iter.hasNext( ) ) { IParameterDefnBase param = (IParameterDefnBase) iter.next(); if ( param.getParameterType() == IParameterDefnBase.CASCADING_PARAMETER_GROUP ) { ICascadingParameterGroup group = (ICascadingParameterGroup) param; String groupName = group.getName(); Iterator i2 = group.getContents( ).iterator( ); Object[ ] userValues = new Object[group.getContents( ).size( )]; // Get the report parameters in the cascading group. int i = 0; while ( i2.hasNext( ) ) { IScalarParameterDefn member = (IScalarParameterDefn) i2.next( ); // Get the values for the parameter. Object[ ] setValues = new Object[i]; if ( i > 0 ) { System.arraycopy( userValues, 0, setValues, 0, i ); } Collection c = task.getSelectionListForCascadingGroup ( group.getName(), setValues ); String[ ] choiceValue = new String[c.size( )]; String[ ] choiceLabel = new String[c.size( )];
94 Integrating Applications into BIRT iHub // Iterate through the values for the parameter. Iterator i3 = c.iterator(); for ( int j = 0; j < c.size( ); j++ ) { IParameterSelectionChoice s = ( IParameterSelectionChoice ) i3.next( ); choiceValue[j] = ( String ) s.getValue( ); choiceLabel[j] = s.getLabel( ); } // Get the value for the parameter from the list of // choices. This example does not provide the code for // this task. userValues[i] = inputChoiceValue; i++; } }
Preparing to generate the report BIRT provides output emitters for HTML, Adobe PDF, Adobe PostScript (PS), Microsoft Excel (XLS), Microsoft PowerPoint (PPT), and Microsoft Word (DOC) formats. BIRT also supports custom output formats provided by renderers developed from the rendering extension points. Three task classes support generating a report from a source. Sections earlier in this chapter described how to open the two types of source, a report design and a report document. The following tasks support generating a report from the source: ■ IRunAndRenderTask. An object of this type creates a report in one of the supported formats by running a report design directly. To instantiate this object, call the ReportEngine method, createRunAndRenderTask( ). ■ IRunTask. An object of this type creates a report document (.rptdocument) file from a report design. To instantiate this object, call the ReportEngine method, createRunTask( ). After creating the binary format report document, create the report output using an IRenderTask object. ■ IRenderTask. An object of this type creates a complete report or a set of pages from a report by formatting the contents of a binary report document. To instantiate this object, call the ReportEngine method, createRenderTask( ). Each type of task object can act on multiple sources. When the application no longer needs the task object, call the task’s close( ) method.
Setting the parameter values for running a report design To set the values for parameters for generating a report, use methods on an IRunAndRenderTask or an IRunTask object. These tasks run a report design to generate output. IRenderTask supports reading but not changing the parameters
Chapter 5, Programming using the BIRT reporting APIs 95 for a report because its source is a report document. The IRunTask object that created the report document already specified the parameter values. Call setParameterValues( ) to set values for all the parameters in a report design. This method takes a HashMap as an argument. To create a suitable HashMap, use the techniques shown in Listing 5-6 or Listing 5-7, earlier in this chapter. To set the value for a single parameter when generating a report, call the setParameterValue( ) method. When the task generates the report or the report document, it uses the default values for any parameters having unset values.
Adding to the report engine’s class path Some report designs require access to external Java classes. The BIRT Report Engine uses class path information from various settings in its environment to locate the external classes. BIRT supports defining some of these locations by setting properties programmatically on the application context or on the EngineConfig object, or with the Java System class. To set the properties, use constants from the org.eclipse.birt.report.engine.api.EngineConstants class. To set a property on the application context, use the EngineTask object or the EngineConfig object, as shown in the following lines of code, where MyClass is the class that starts the report engine: configOrTask.getAppContext( ).put ( EngineConstants.APPCONTEXT_CLASSLOADER_KEY, MyClass.class.getClassLoader( )); To set a CLASSPATH property on the EngineConfig object, use code similar to the following lines. The property value must be a valid CLASSPATH.
config.setProperty( EngineConstants.WEBAPP_CLASSPATH_KEY, "c:/myjars/jar1.jar;c:/myclasses" ); To use the Java System class to set a CLASSPATH property, use code similar to the following lines. The property value must be a valid CLASSPATH.
System.setProperty( EngineConstants.WEBAPP_CLASSPATH_KEY, "c:/myjars/jar1.jar;c:/myclasses" ); BIRT searches locations for external classes in the order shown in the following list: ■ The CLASSPATH for the report engine plug-in. ■ The CLASSPATH of the parent class loader that is set as the EngineConstants.APPCONTEXT_CLASSLOADER_KEY. Define this property on the application context. ■ The CLASSPATH set as EngineConstants.WEBAPP_CLASSPATH_KEY. Define this property using the Java System class or on the EngineConfig object.
96 Integrating Applications into BIRT iHub ■ The CLASSPATH set as EngineConstants.PROJECT_CLASSPATH_KEY. Define this property using the Java System class or on the EngineConfig object. ■ The CLASSPATH in EngineConstants.WORKSPACE_CLASSPATH_KEY. Define this property using the Java System class or on the EngineConfig object. ■ JAR files included in the report design.
Providing an external object to a report design BIRT supports an application passing previously instantiated objects into the report engine. Using this technique, the engine does not have to provide the code to create the object using information external to BIRT. The calling application can manipulate the object in memory immediately before calling the report engine. A typical use of external objects is in the BIRT scripting environment. After the application passes the object to the report engine, script expressions can reference the object by name at the appropriate stage in the report generation process. To supply an object to the report engine, use the application context, accessed from either the EngineConfig object or the task object, as shown in the code in Listing 5-9. Listing 5-9 Setting up an external Connection object myConnection mc = DriverManager.getConnection( myURL ); config = new EngineConfig( ); // Get the application context from the config or the task HashMap hm = configOrTask.getAppContext( ); hm.put( "MyConnectionObject", mc ); configOrTask.setAppContext( hm ); // To refer to this object in a BIRT script // or expression, use MyConnectionObject.myMethod()
Generating a binary report document A binary report document contains all the information required to create a formatted report. The document contains appearance, data, and pagination information. Generate a binary report document if the same information must be rendered to multiple formats, if the output format is unknown at the time the report runs, or to render a subset of the pages in the report. Call an IRunTask.run( ) method to create a binary report document.
How to generate a binary report document The code sample in Listing 5-10 uses an IRunTask object to set the output file name. The variable, engine, is a ReportEngine object. The variable, runnable, is an object of type IReportRunnable. The variable, name, is the name of the report design. The variable, str_DateStamp, is a String representing today’s date.
Chapter 5, Programming using the BIRT reporting APIs 97 Listing 5-10 Using an IRunTask object to create a binary report document
// Create a run task object. IRunTask task = engine.createRunTask( runnable ); String output = name.replaceFirst( ".rptdesign", str_DateStamp + ".rptdocument" ); try { task.run( output ); task.close( ); System.out.println( "Created document " + output + "." ); } catch ( EngineException e1 ) { System.err.println( "Report " + output + " creation failed." ); System.err.println( e1.toString( ) ); }
Preparing to render a formatted report Render a formatted report from a report design by calling the method IRunAndRenderTask.run( ). Render a formatted report from a binary report document by calling the method IRenderTask.render( ).
Setting up the rendering options Before rendering a report to an output format, the application must set options that determine features of the output. The options must specify either an output file name or a stream. Other settings, such as the type of HTML to generate, are optional. BIRT supports two types of HTML output, HTML and embeddable HTML. Embeddable HTML is suitable for including inside another web page. This format contains no header information nor the
or tags. The application uses a rendering options object to set the output options on an IRunAndRenderTask or an IRenderTask object. Format-specific rendering options classes implement IRenderOption and extend RenderOption. The rendering options class for the Excel format is EXCELRenderOption, for the HTML format is HTMLRenderOption, and for the PDF format is PDFRenderOption. All other output formats use the RenderOption class. After creating the rendering option object, call the task’s setRenderOption( ) method. This method takes an IRenderOption object as an argument. Use the setRenderOption( ) method on an IRenderTask or an IRunAndRenderTask object. This method performs no function on an IRunTask object as this task does not render output. Listing 5-11 includes code to set the rendering option for HTML. To apply a rendering setting, use setter methods on the rendering option object. These objects also have getter methods that retrieve render settings. Common option settings are a base URL for hyperlinks, an action handler, an image handler, output format, and supported image output formats.98 Integrating Applications into BIRT iHub The supported image formats setting is used for extended report items such as charts or custom extended items. The final rendering environment for the report, such as the browser for a report in HTML format, affects this option value. To set supported formats, use setSupportedImageFormats( ) with a String argument containing a list of the supported image formats. The image formats are standard types, such as GIF, JPG, PNG, and SVG. Semicolons separate the items in the list. The method getSupportedImageFormats( ) returns a String of the same format.
Understanding HTML rendering options Before generating an HTML report that uses images on disk or creates images or charts in a report, the application must provide additional settings. The HTMLRenderOption class provides many ways to customize the emitted HTML. The following list describes some of the commonly used options and how the options interact with each other: ■ Image directory. Many reports include either static or dynamic images. For example, charts are dynamic images. HTML reports place all these images in a defined location. To set this location, call the setImageDirectory( ) method. ■ Base image URL. For web deployment, such as a WAR file, the images created in the image directory must be available to a user’s web browser. Provide the engine with a URL prefix to apply to the image directory. To set the URL, use the setBaseImageURL( ) method, as shown in Listing 5-2. ■ Image handler. Use the setImageHandler( ) method to set up an image handler, as described earlier in this chapter. ■ Embeddable HTML. Call the setEmbeddable( ) method with the argument, true, to set this option. The embeddable produced HTML does not have and
tags. ■ Right-to-left generation. To set the HTML emitter to generate content right to left, call the setHtmlRtLFlag( ) method with the argument, true. ■ Title tag. Use the setHtmlTitle( ) method to write aChapter 5, Programming using the BIRT reporting APIs 99 ■ Master page margins. Master page margins affect the appearance of the HTML output if the report uses fixed layout or if the value, true, is the argument to the setOutputMasterPageMargins( ) method. ■ Paginated HTML. When rendering the report in HTML, the engine supports paginating the results. The report design’s master page defines the size of the page and the content of its page headers and footers. To display the entire or partial report as a single HTML page, call the setHtmlPagination( ) method with the argument, false. In this case, setting a render task page range of 5-7 renders pages 5 to 7 as one HTML page. Header and footer information appear several times within this HTML page if you choose to display master page content. For your application to support pagination, you need to set up pagination controls similar to the example Web Viewer. ■ Fixed or automatic layout. By default, BIRT generates tables with columns that are fixed in size. When the user changes the width of the browser window, the column widths do not change. BIRT also supports automatic layout, in which column widths adjust according to the width of the window. Fixed layout produces reports with a consistent layout, but this choice can increase rendering time. The table-layout:fixed attribute is applied to all tables. Appropriate div statements set column widths and padding. The div settings are also applied if master page content is used. To change this setting, use the setLayoutPreference( ) method. Pass the LAYOUT_PREFERENCE_AUTO or LAYOUT_PREFERENCE_FIXED value as its argument. ■ Style calculation. The setEnableAgentStyleEngine( ) method provides the developer control over how the styles are calculated. Passing a value of true to this method emits the styles directly to the produced HTML. In this case, the browser performs the style calculations. Passing a value of false to the method causes the emitter to use the BIRT style engine to do the calculations. As with the fixed or automatic layout setting, this setting affects the consistency of the report’s appearance. ■ Base URL. Most BIRT report items have a hyperlink property. When building this hyperlink in the report designer, the report developer uses a URL, an internal bookmark, or a drill-through operation. The report design stores the results of the design session. The setBaseURL( ) method defines the base URL to prefix to the hyperlinks built using the designer. Use this setting for applications deployed in a web environment. ■ Action handler. The emitter handles hyperlink, bookmark, and drill-through actions. When rendering the report as HTML, BIRT uses the HTMLActionHandler class to determine how to build the hyperlink for these actions. The HTMLActionHandler class implements the IHTMLActionHandler interface. If the default HTMLActionHandler does not meet your needs, use a custom implementation of IHTMLInterface. To set up the new action handler, use the setActionHandler( ) method.
100 Integrating Applications into BIRT iHub The HTMLRenderOption class provides equivalent getter methods for the setter methods described in the previous list.
How to configure properties for a report in HTML format The code sample in Listing 5-11 shows the use of rendering options on an IRunAndRenderTask object to set report parameter values, the output format of the report, and the output file name. The variable, engine, is a ReportEngine object. The variable, runnable, is an object of type IReportRunnable. The variable, name, is the name of the report design. Listing 5-11 Configuring properties on an IRunAndRenderTask object
// Create a run and render task object. IRunAndRenderTask task = engine.createRunAndRenderTask( runnable ); // Set values for all parameters in a HashMap, parameterValues task.setParameterValues( parameterValues ); // Validate parameter values. boolean parametersAreGood = task.validateParameters( ); // Set the name of an output file and other HTML options. HTMLRenderOption options = new HTMLRenderOption( ); String output = name.replaceFirst( ".rptdesign", ".html" ); options.setOutputFileName( output ); options.setImageDirectory( "image" ); options.setEmbeddable( false ); // Apply the rendering options to the task. task.setRenderOption( options );
Understanding Excel rendering options The EXCELRenderOption class provides the following methods to modify the appearance of the generated spreadsheet: ■ setHideGridlines( ) uses a boolean value of true or false to hide or show gridlines in the spreadsheet. ■ setOfficeVersion( ) sets the compatibility level of the spreadsheet. Valid values for the String parameter are office2003 and office2007. The default value is office2003. ■ setWrappingText( ) uses a boolean value of true or false to set or unset text wrapping in cells in the spreadsheet. The EXCELRenderOption class provides equivalent getter methods to retrieve the current values of the options.
Using generic methods to access rendering options The RenderOption class provides getter and setter methods for accessing the most commonly used rendering options. For example, this class provides
Chapter 5, Programming using the BIRT reporting APIs 101 the getOutputFileName( ) and setOutputFileName( ) methods to get and set the file name of rendered report. RenderOption also provides fields to identify the options. An application accesses the less commonly used options by calling the following generic methods, inherited from TaskOption, using a RenderOption field as an argument:
■ getOption( ) This method returns an Object containing the option value. For boolean or int values, the returned Object is a Boolean or Integer, respectively.
■ getBooleanOption( ), getIntOption( ), getStringOption( ) Use these methods if the code is accessing an option of known type. These methods return a boolean value, an int value, and a String object, respectively.
■ getOptions( ) This method returns a Hashmap object containing all the rendering options that have been set explicitly using setOption( ).
■ hasOption( ) Use this method to check whether the rendering options object supports a particular option. If the object supports an option, this method returns true even if the value of the option is null.
■ setOption( ) This method takes a second argument, an Object that contains the value of the option. For boolean or int values, use a Boolean or Integer object, respectively. The code sample in Listing 5-12 provides examples of these methods. Listing 5-12 Using generic rendering options
RenderOption ro = new RenderOption( ); if ( ro.getOption( RenderOption.RENDER_DPI ) == null ) { ro.setOption( RenderOption.RENDER_DPI, new Integer( 96 ) ); } ro.setOption( RenderOption.RTL_FLAG, new Boolean( true ) ); // The following line returns: // INFO: Options: {RenderDpi=96, RTLFlag=true} logger.log( Level.INFO, "Options: " + ro.getOptions().toString());
Rendering formatted output To generate a formatted report, the application calls the run( ) method on an IRunAndRenderTask or the render( ) method on an IRenderTask object. The application must handle the EngineException that these methods can throw. After generating the report, the application can reuse the report engine and the task to generate further reports. If the application generates only a single report, close the task and destroy the engine after performing the report generation.
102 Integrating Applications into BIRT iHub The IRunAndRenderTask.run( ) method creates a formatted document containing all the data in the report. The IRenderTask.render( ) method is more versatile. This method supports rendering the whole report or a subset of pages based on a bookmark, a page number, or a page range. A bookmark is a String that identifies a location in the report document. Use a value defined by the report developer using BIRT Report Designer or navigate the table of contents to identify the required portion of a report. To access table of contents entries, use ITOCTree and TOCNode objects. The ITOCTree interface provides access to the tree of table of contents entries. A TOCNode object defines each table of contents entry. Each entry contains three strings: the identifier, the display value, and the bookmark of the entry. Get an ITOCTree object by calling the IRenderTask.getTOCTree( ) method. Then, use the ITOCTree.getRoot( ) method to retrieve the root TOCNode object. To find the subentries of a table of contents entry, use the TOCNode.getChildren( ) method. This method returns a List of TOCNode objects. Alternatively, call the findTOCByValue( ) method to retrieve a List of all TOCNode objects having a particular value. Use the bookmark String to locate the page to which the bookmark links by calling the getPageNumber( ) method. Using this information, the application calls the setPageNumber( ) or setPageRange( ) methods to specify pages to render to a formatted report.
How to generate a report from a report design The code sample in Listing 5-13 generates a report from a report design and then closes the task. The variable, task, is an IRunAndRenderTask object. The variable, htmlRO, is an HTMLReportOption object. The variable, name, is the name of the report design. The variable, output, is the name of the output file. Listing 5-13 Generating a report from a report design task.setRenderOptions( htmlRO ); try { task.run( ); System.out.println( "Created Report " + output + "." ); task.close( ); } catch ( EngineException e1 ) { System.err.println( "Report " + name + " run failed." ); System.err.println( e1.toString( ) ); }
How to generate a partial report from a binary report document The code sample in Listing 5-14 generates a single page of a report from a binary report document. The sample shows two techniques to locate the page to generate. The variable, htmlRO, is an HTMLReportOption object. The variable, name, is the name of the report design. The variable, output, is the name of the output file. The variable, engine, is a ReportEngine object.
Chapter 5, Programming using the BIRT reporting APIs 103 Listing 5-14 Generating part of a report from a binary report document
IReportDocument binaryDoc = engine.openReportDocument(output); // Create a render task object. IRenderTask task = engine.createRenderTask( binaryDoc ); // Get the root of the table of contents. ITOCTree tocTree = task.getTOCTree( ); TOCNode td = tocTree.getRoot( ); // Traverse the tree of top-level items in the table of contents. java.util.List children = td.getChildren( ); long pNumber; // Loop through the top level table of contents entries. if ( children != null && children.size( ) > 0 ) { for ( int i = 0; i < children.size( ); i++ ) { // Find the required table of contents entry. TOCNode child = ( TOCNode ) children.get( i ); if ( child.getDisplayString( ).equals( "157" ) ) { // Get the number of the page that contains the data. pNumber = binaryDoc.getPageNumber( child.getBookmark( )); task.setPageNumber( pNumber ); } } } // Alternatively, use the first entry having the correct value. java.util.List desiredNodes = tocTree.findTOCByValue( "157" ); if ( desiredNodes != null && desiredNodes.size( ) > 0 ) { TOCNode child = (TOCNode) desiredNodes.get(0); pNumber = binaryDoc.getPageNumber( child.getBookmark( ) ); task.setPageNumber( pNumber ); } // Render the page. Then, close the document and the task. output = output.replaceFirst( ".rptdocument", ".html" ); htmlRO.setOutputFileName( output ); task.setRenderOption( htmlRO ); task.render(); binaryDoc.close(); task.close();
Accessing the formatted report After generating a formatted report document as a file on disk, access the file in the same way as any other file. For example, open an HTML document in a web browser and a PDF document using Adobe Reader. If the application sends the report to a stream, the stream must be able to process the content.
104 Integrating Applications into BIRT iHub Checking the status of a running report task The BIRT Report Engine supports checking the status of any engine task and cancelling that task. Typically, an application uses a separate thread to perform these actions. To check the status of a running report, use the EngineTask.getStatus( ) method, which returns one of the following values: ■ IEngineTask.STATUS_NOT_STARTED. The task has not started. ■ IEngineTask.STATUS_RUNNING. The task is currently running. ■ IEngineTask.STATUS_SUCCEEDED. The task completed with no errors. ■ IEngineTask.STATUS_FAILED. The task failed to execute. ■ IEngineTask.STATUS_CANCELLED. The task was cancelled. Cancelling a running report task To cancel a running task call the IEngineTask.cancel( ) method. All the tasks that run and render reports implement and extend the IEngineTask interface. If the application cancels a task that is running a report, the task stops generating the report content. If the task has started a query on a database, the database continues to run the query to completion.
How to cancel a running report task 1 Define a thread class as an inner class to cancel the report. In Listing 5-15, the name of this class is CancelReport. 2 Within the code that creates the task, create an instance of the CancelReport class, as shown in the following line: CancelReport cancelThread = new CancelReport( "cancelReport", task); 3 Test for a condition. Then, use the CancelReport object to cancel the report, as shown in the following line: cancelThread.cancel( ); Listing 5-15 Defining a class to cancel an engine task
private class CancelReport extends Thread { private IEngineTask eTask; public CancelReport( String myName, IEngineTask task ) { super( myName ); eTask = task; }
Chapter 5, Programming using the BIRT reporting APIs 105 public void cancel( ) { try { Thread.currentThread( ).sleep( 100 ); eTask.cancel( ); System.out.println( "#### Report cancelled #####" ); } catch( Exception e ) { e.printStackTrace(); } } }
Programming the structure of a report design A reporting application typically generates reports from report designs. When deploying this type of application, the report designs are deployed with the application. Any changes to the generated reports depend on the values of report parameters and the data from the data set. To access a report design, the application uses an IReportRunnable object. Sometimes business logic requires changes to the report design before generating the report. Some changes are possible through using parameters and scripting. Other changes can only occur through modification of the report design itself. The API to perform these tasks is known as the model API. The package containing the classes and interfaces to work with the items in a report design, library, or template is org.eclipse.birt.report.model.api. To access the structure of the report design, the application obtains a ReportDesignHandle object from the design engine. ReportDesignHandle provides access to all properties of the report design and to the elements that the report design contains. The model API provides handle classes to access all Report Object Model (ROM) elements. For example, a GridHandle object provides access to a grid element in the report design. All ROM element handles, including the report design handle, inherit from DesignElementHandle. Report items inherit from ReportElementHandle and ReportItemHandle. After making changes to a report design or its elements, the application writes the result to a stream or a file. To generate a formatted report or a binary report document, use the report engine to open an IReportRunnable object on the updated design. Then, use the report engine as described earlier in this chapter. To access the design engine, an application must first instantiate a report engine.
106 Integrating Applications into BIRT iHub An application typically accesses the items in a report design to perform one of the following tasks: ■ Modify an existing report design programmatically to change the contents and appearance of the report output. An application can modify page characteristics, grids, tables, and other report items in the design, the data source, and the data set that extracts data from a data source. ■ Build a complete report design and generate report output in a single application. A reporting application can access and modify the structures in a template or a library file in the same way as the structures in a report design. The techniques described in the rest of this chapter are as applicable to these file types as to report designs. A template has identical functionality to a report design. For this reason, the ReportDesignHandle class provides access to a template. The LibraryHandle class provides access to a library. Both these classes derive from the ModuleHandle class, which provides the fields and methods for the common functionality, such as accessing elements in the file. About BIRT model API capabilities A Java developer can use the BIRT model API to write an application that creates and modifies a report design programmatically. This API has the same capabilities as BIRT Report Designer. For example, the following list shows some of the ways in which the BIRT model API supports manipulating a report design programmatically: ■ Adding a report item to a report design: ■ Add a simple report item such as a data item, label, or image. Set a value to display in the new report item, such as the expression of a data item or the text in a label item. ■ Create a complex item such as a grid, table, or list. Add other items into the grid, table, or list. ■ Changing the properties of a report item in a report design: ■ Change the data set bound to a table or list. ■ Change the expression or other property of a report item. ■ Format a report item, changing the font, font color, fill color, format, alignment, or size. ■ Changing the structure of a report design: ■ Add a report parameter. ■ Add or delete a group or column in a table or list. ■ Modifying non-visual elements in a report design:
Chapter 5, Programming using the BIRT reporting APIs 107 ■ Set a design property such as a report title, author, wallpaper, or comment. ■ Set a page property, such as height, width, or margins. ■ Specify a data source for a data set. Opening a report design for editing To access a report design and its contents, the application must instantiate first, a report engine, and second, a ReportDesignHandle object. The ReportDesignHandle object provides access to the ROM elements in the design opened by the report engine. Instantiate a ReportDesignHandle by calling a method on either the model class, SessionHandle, or the report engine interface, IReportRunnable. The SessionHandle object manages the state of all open report designs. Use a SessionHandle to open, close, and create report designs, and to set global properties, such as the locale and the units of measure for report elements. The SessionHandle can open a report design from a file or a stream. Create the session handle only once. BIRT supports only a single SessionHandle for a user of a reporting application.
Configuring the design engine to access a design handle The DesignEngine class provides access to all the functionality of the ROM in the same way that the ReportEngine class provides access to report generation functionality. Before creating a DesignEngine object, create a DesignConfig object to contain configuration settings for the design engine. The DesignConfig object sets up custom access to resources and custom configuration variables for scripting. Use a factory service to create a DesignEngine in the same way as creating a ReportEngine. After setting configuration properties, create a design engine by calling the Platform.createFactoryObject( ) and the IDesignEngineFactory .createDesignEngine( ) methods. The DesignConfig object defines the settings for this process. If the application has already started the platform in order to set up a report engine, use the same platform instance to create the design engine. If the application runs in an RCP environment, do not start the platform. Create the SessionHandle object by calling the method, newSessionHandle( ) on the DesignEngine object. To open the report design, call the method, openDesign( ), on the SessionHandle object. This method takes the name of the report design as an argument and instantiates a ReportDesignHandle.
How to open a report design for editing The code sample in Listing 5-16 creates a DesignEngine object from which to create a SessionHandle object. The code uses the SessionHandle object to open a report design.
108 Integrating Applications into BIRT iHub Listing 5-16 Opening a report design for editing
// Create a design engine configuration object. DesignConfig dConfig = new DesignConfig( ); // Start the platform for a non-RCP application. Platform.startup( dConfig ); IDesignEngineFactory factory = ( IDesignEngineFactory ) Platform.createFactoryObject ( IDesignEngineFactory.EXTENSION_DESIGN_ENGINE_FACTORY ); IDesignEngine dEngine = factory.createDesignEngine( dConfig ); // Create a session handle, using the system locale. SessionHandle session = dEngine.newSessionHandle( null ); // Create a handle for an existing report design. String name = "./SimpleReport.rptdesign"; ReportDesignHandle design = null; try { design = session.openDesign( name ); } catch (Exception e) { System.err.println( "Report " + name + " not opened!\nReason is " + e.toString( ) ); return null; }
Using an IReportRunnable object to access a design handle An alternative way to open a report design is by calling the getDesignHandle( ) method on an IReportRunnable object. Use a design engine to access the elements in this report design in the same way as for any other design handle. Using a report item in a report design A report item is a visual element in the report design. Typically, a report developer uses BIRT Report Designer to add a report item to the design by dragging an item from the palette to the layout editor. Sometimes a reporting application must change the properties of certain report items in the design before running the report. The application uses methods on the ReportDesignHandle class to access a report item either by name or from a list of items in a slot in a container report item. These methods return a DesignElementHandle object. All report items derive from this class. A slot is a logical component of a container report item. A slot holds zero or more members of the appropriate report item type. For example, a table element has four slots: Header, Detail, Footer, and Groups. Each of these slots is a container for further slots. The Header, Detail, and Footer slots all contain elements of type RowHandle. RowHandle has a Cell slot that contains all the cells in the row. The Outline view in BIRT Report Designer provides a visual representation of the slots in an individual report item.
Chapter 5, Programming using the BIRT reporting APIs 109 Accessing a report item by iterating through a slot To access a report item through the report design’s structure, first get the slot handle of the report body by calling the ReportDesignHandle.getBody( ) method. This slot handle holds the top-level report items in the report design. For example, consider a simple report structure that has a table with a header detail row, and footer, with two named groups called ProductLineGroup and ProductNameGroup. Figure 5-3 shows its Outline view in BIRT Report Designer.
Figure 5-3 Slots in a report design To access the top-level items in this report design, iterate over the contents of the body slot handle. To access the iterator for a slot handle, call SlotHandle.iterator( ). Each call to Iterator.getNext( ) returns ReportDesignHandle object, which is a handle to a report item or another slot. Alternatively, to access a report item at a known slot index, call SlotHandle.get( ). The slot index number is zero-based.
Accessing a report item by name To make a report item accessible by name, the item must have a name. Either a report developer sets the name in BIRT Report Designer or an application sets the name programmatically by using the item’s setName( ) method. To find a report item by name, use ReportDesignHandle.findElement( ).
Examining a report item To examine a report item, check the class of the report item and cast the object to its actual class. Then, call methods appropriate to that class. For example, the class of a label element handle is LabelHandle. To get the text that the label displays, call LabelHandle.getText( ). Some report items, such as a label or a text element, are simple items. Other items, such as a grid or a table element, are structured items. Access properties for the whole of a structured item in the same way as for a simple item.
110 Integrating Applications into BIRT iHub To examine the contents of a structured item, iterate over its slots. Use this technique to determine the contents of a cell in a table. First, call a method to retrieve a slot handle for the table’s rows. Next, iterate over the contents of the slot to access the cells. For example, to access the RowHandle objects that make up a table element’s footer, call TableHandle.getFooter( ). Table and list elements also have a slot for groups.
Accessing the properties of a report item To provide information about report items, each class has getter methods specific to the report item type. For example, an image element handle, ImageHandle, has the getURI( ) method. This method returns the URI of an image referenced by URL or file path. The DesignElementHandle class and other ancestor classes in the hierarchy also provide generic getter methods, such as getName( ). Some properties of a report item are simple properties of a Java type or type wrapper class. An example of a simple property is the name property, which is a String object. Some simple properties, like name, have an arbitrary value. Other simple properties have restricted values from a set of BIRT String constants. The interface, DesignChoiceConstants in the package, org.eclipse.birt.report.model.api.elements, defines these constants. For example, the image source property of an image element can have one of the following values: IMAGE_REF_TYPE_EMBED, IMAGE_REF_TYPE_EXPR, IMAGE_REF_TYPE_FILE, IMAGE_REF_TYPE_NONE, or IMAGE_REF_TYPE_URL. Other properties are complex properties and the getter method returns a handle object. For example, the DesignElementHandle.getStyle( ) method returns a SharedStyleHandle object and ReportItemHandle.getWidth( ) returns a DimensionHandle object. The handle classes provide access to complex properties of a report item, as described later in this chapter. These classes provide getter methods for attributes of the complex properties. For example, StyleHandle classes provide access to background color, font, and highlights.
How to access a report item by name The code sample in Listing 5-17 finds an image item by name, checks its type, and examines its URI. The variable, design, is a ReportDesignHandle object. Listing 5-17 Finding a report item having a given name
DesignElementHandle logoImage = design.findElement( "Company Logo" ); // Check for the existence of the report item. if ( logoImage == null) { return null; } // Check that the report item has the expected class. if ( !( logoImage instanceof ImageHandle ) ) {
Chapter 5, Programming using the BIRT reporting APIs 111 return null; } // Retrieve the URI of the image. String imageURI = ( (ImageHandle ) logoImage ).getURI( ); return imageURI;
How to use the report structure to access a report item The code sample in Listing 5-18 finds an image item in a grid, checks its type, and examines its URI. Use this technique for generic code to navigate a report design structure or if to find an item that does not have a name. The variable, design, is a ReportDesignHandle object. Listing 5-18 Navigating the report structure to access a report item
// Instantiate a slot handle and iterator for the body slot. SlotHandle shBody = design.getBody( ); Iterator slotIterator = shBody.iterator( ); // To retrieve top-level report items, iterate over the body. while (slotIterator.hasNext( )) { Object shContents = slotIterator.next( ); // To get the contents of the top-level report items, // instantiate slot handles. if ( shContents instanceof GridHandle ) { GridHandle grid = ( GridHandle ) shContents; SlotHandle grRows = grid.getRows( ); Iterator rowIterator = grRows.iterator( ); while ( rowIterator.hasNext( )) { // Get RowHandle objects. Object rowSlotContents = rowIterator.next( ); // To find the image element, iterate over the grid. SlotHandle cellSlot = ( ( RowHandle ) rowSlotContents ).getCells( ); Iterator cellIterator = cellSlot.iterator( ); while ( cellIterator.hasNext( )) { // Get a CellHandle object. Object cellSlotContents = cellIterator.next( ); SlotHandle cellContentSlot = ( ( CellHandle) cellSlotContents ).getContent( ); Iterator cellContentIterator = cellContentSlot.iterator( ); while ( cellContentIterator.hasNext( )) { // Get a DesignElementHandle object. Object cellContents = cellContentIterator.next( ); // Check that the element is an image.
112 Integrating Applications into BIRT iHub if (cellContents instanceof ImageHandle) { String is = ( ( ImageHandle ) cellContents ) .getSource( ); // Check that the image has a URI. if ( ( is.equals( DesignChoiceConstants.IMAGE_REF_TYPE_URL )) || ( is.equals( DesignChoiceConstants.IMAGE_REF_TYPE_FILE ))) { // Retrieve the URI of the image. String imageURI = ( ( ImageHandle ) cellContents ).getURI( ); } } } } } } }
Modifying a report item in a report design To set the simple properties of report items, each class has setter methods specific to the report item type. For example, an image element handle, ImageHandle, has the setURI( ) method. This method sets the URI of an image referenced by URL or file path. The DesignElementHandle class and other ancestor classes in the hierarchy provide generic setter methods, such as setName( ). Setter methods throw exceptions, such as NameException, SemanticException, and StyleException. To set attributes of a complex property, such as a style, call methods on a handle object, as described later in this chapter. These classes provide setter methods for related properties. For example, StyleHandle classes provide access to style properties, such as font and background color.
How to change a simple property of a report item The code sample in Listing 5-19 uses a method on LabelHandle to change the text in a label. The variable, design, is a ReportDesignHandle object. This sample accesses the label by name. Alternatively, access a report item by navigating the report structure. Listing 5-19 Changing the text property of a label report item
// Access the label by name. LabelHandle headerLabel = ( LabelHandle ) design.findElement( "Header Label" ); try { headerLabel.setText( "Updated " + headerLabel.getText( )); } catch ( Exception e ) { // Handle the exception }
Chapter 5, Programming using the BIRT reporting APIs 113 Accessing and setting complex properties Complex properties use BIRT handle objects to access data structures. For example, a DimensionHandle object provides access to size and position properties, such as the absolute value and the units of the width of a report item. Some String properties on a handle object, such as font style and text alignment on a style handle, have restricted values defined by constants in the org.eclipse.birt.report.model.api.elements.DesignChoiceConstants interface. For example, the font style property can have one of only the values, FONT_STYLE_ITALIC, FONT_STYLE_NORMAL, or FONT_STYLE_OBLIQUE.
Using a BIRT property handle To access complex properties, use getter methods on the report item. For example, to access the width of a report item, call the method ReportItemHandle.getWidth( ). This method returns a DimensionHandle object. To work with complex properties, use getter and setter methods on the property handle object. For example, to get and set the size of a dimension, use the DimensionHandle methods getMeasure( ) and setAbsolute( ), respectively. Calling a method on a property handle object to set a value on a complex property affects the report item straight away. You do not call another setter method on the report item itself.
Using styles on a report item The StyleHandle class provides access to many fundamental properties of a report item, such as margin size, text alignment, background color, borders, font, and so on. StyleHandle provides a full set of getter methods for each style property. For simple properties, StyleHandle provides setter methods. To modify complex properties, use setter methods on the property handle object, not on the style handle itself. A report item can use two styles; a private style and a shared style. The handle classes for these styles are PrivateStyleHandle and SharedStyleHandle, respectively. Both classes derive from StyleHandle. A private style contains the settings that the report developer chose in the property editor when designing the report using BIRT Report Designer. Shared styles appear in the Outline view in BIRT Report Designer. Use shared styles to apply the same appearance to multiple items in a report design. Changes to a shared style affect all report items that use the style. Style settings in a private style override the settings in a shared style.
How to change a complex property of a report item The code sample in Listing 5-20 shows how to use PrivateStyleHandle and ColorHandle objects to change the background color of a label. The variable, design, is a ReportDesignHandle object. This sample accesses the label by name. Alternatively, access a report item by navigating the report structure.
114 Integrating Applications into BIRT iHub Listing 5-20 Changing a complex property of a report item
// Access the label by name. LabelHandle headerLabel = ( LabelHandle ) design.findElement( "Header Label" ); try { // To prepare to change a style property, get a StyleHandle. StyleHandle labelStyle = headerLabel.getPrivateStyle(); // Update the background color. ColorHandle bgColor = labelStyle.getBackgroundColor(); bgColor.setRGB( 0xFF8888 ); } catch ( Exception e ) { // Handle the exception }
Understanding property structure objects Complex property structures represent many optional report element features within BIRT. For example, computed columns, highlight rules, sort keys, and table of contents entries are all optional complex properties of report elements. The classes for these properties all derive directly or indirectly from org.eclipse.birt.report.model.core.Structure. An application can access existing structure property objects on a report element or create new ones.
Using an existing property structure object Use the property handle, which is an object of class PropertyHandle, to apply a new structure object to a report element’s property or to modify an existing property structure. To access the property handle call the method, DesignElementHandle.getPropertyHandle( ), which is available on all report elements. This method takes a String argument that defines the property to access. Class fields having names of the form XXX_PROP define the available property structures for a report element class. The property handle object provides access to one or more property structure objects. Use the PropertyHandle getter methods to access settings on existing property structures. Typically, the property structure class provides setter methods only for a few key values. Set other values by calling the property structure object’s setProperty( ) method. This method takes two arguments: a String that identifies the property and an object that specifies the value. Class fields defined on the property structure class or on the DesignChoiceConstants class provide the values for the property identifier.
How to set values on an existing property structure object The code sample in Listing 5-21 shows how to change the sort direction value on a table item’s first sort key.
Chapter 5, Programming using the BIRT reporting APIs 115 Listing 5-21 Changing the sort direction on a table
void modSortKey( TableHandle th ) { try { SortKeyHandle sk; PropertyHandle ph = th.getPropertyHandle( TableHandle.SORT_PROP ); if ( ph.isSet( ) ) { sk = ( SortKeyHandle ) ph.get( 0 ); sk.setDirection ( DesignChoiceConstants.SORT_DIRECTION_DESC ); } } catch ( Exception e ) { e.printStackTrace( ); } }
Creating a property structure object The design engine class, StructureFactory, provides static methods for creating property structure objects. Most StructureFactory methods take the form createXXX, where XXX is the structure to create. After creating a new structure object, set its simple or complex properties using its setter methods. Report element handles provide methods to add key structure properties to their property handles. For example, add a filter condition to a data set object by using the addFilter( ) method. To add other properties to a report element, use the method, PropertyHandle.addItem( ).
How to create a complex property object The code sample in Listing 5-22 shows how to create a highlight rule object and apply that rule to a row handle. The variable, rh, is a RowHandle object. Because RowHandle does not have a specific method to add a highlight rule property, the code uses the PropertyHandle.addItem( ) method. Listing 5-22 Adding a highlight rule to a table or grid row
try { HighlightRule hr = StructureFactory.createHighlightRule( ); hr.setOperator( DesignChoiceConstants.MAP_OPERATOR_GT ); hr.setTestExpression( "row[\"CustomerCreditLimit\"]" ); hr.setValue1( "100000" ); hr.setProperty ( HighlightRule.BACKGROUND_COLOR_MEMBER, "blue" ); PropertyHandle ph = rh.getPropertyHandle( StyleHandle.HIGHLIGHT_RULES_PROP ); ph.addItem( hr ); } catch ( Exception e ){ e.printStackTrace(); }
116 Integrating Applications into BIRT iHub The code samples in Listing 5-23 provide further examples of using the structure factory to create complex properties. Listing 5-23 Various structure factory examples
// Use the structure factory to add a sort key to a table. void addSortKey( TableHandle th ) { try { SortKey sk = StructureFactory.createSortKey( ); sk.setKey( "row[\"CustomerName\"]" ); sk.setDirection ( DesignChoiceConstants.SORT_DIRECTION_ASC ); PropertyHandle ph = th.getPropertyHandle( TableHandle.SORT_PROP ); ph.addItem( sk ); } catch ( Exception e ) { e.printStackTrace( ); } } // Add a column binding to a table. void addColumnBinding( TableHandle th ) { try { ComputedColumn cs1; cs1 = StructureFactory.createComputedColumn( ); cs1.setName( "CustomerName" ); cs1.setExpression( "dataSetRow[\"CUSTOMERNAME\"]" ); th.addColumnBinding( cs1, false ); } catch ( Exception e ) { e.printStackTrace( ); } } // Add a filter condition to a table. void addFilterCondition( TableHandle th ) { try { FilterCondition fc = StructureFactory.createFilterCond(); fc.setExpr( "row[\"CustomerCountry\"]" ); fc.setOperator(DesignChoiceConstants.MAP_OPERATOR_EQ); fc.setValue1("'USA'"); PropertyHandle ph = th.getPropertyHandle( TableHandle.FILTER_PROP ); ph.addItem( fc ); } catch ( Exception e ) { e.printStackTrace( ); } } // Add a filter condition to a data set. void addFilterCondition( OdaDataSetHandle dh ) { try { FilterCondition fc = StructureFactory.createFilterCond(); fc.setExpr( "row[\"COUNTRY\"]" ); fc.setOperator( DesignChoiceConstants.MAP_OPERATOR_EQ );
Chapter 5, Programming using the BIRT reporting APIs 117 fc.setValue1( "'USA'" ); // Add the filter to the data set. dh.addFilter( fc ); } catch ( Exception e ) { e.printStackTrace( ); } } // Add a hyperlink to a label. void addHyperlink( LabelHandle lh ) { try { Action ac = StructureFactory.createAction( ); ActionHandle actionHandle = lh.setAction( ac ); actionHandle.setURI( "'http://www.google.com'" ); actionHandle.setLinkType ( DesignChoiceConstants.ACTION_LINK_TYPE_HYPERLINK ); } catch ( Exception e ) { e.printStackTrace( ); } } // Add a table of contents entry to a data item. void addToc( DataItemHandle dh ) { try { TOC myToc = StructureFactory.createTOC ( "row[\"CustomerName\"]" ); dh.addTOC( myToc ); } catch ( Exception e ) { e.printStackTrace( ); } } // Add an embedded image to the report design. void addImage( ) { try { EmbeddedImage image = StructureFactory.createEmbeddedImage( ); image.setType ( DesignChoiceConstants.IMAGE_TYPE_IMAGE_JPEG ); image.setData( load( "logo3.jpg" )); image.setName( "mylogo" ); designHandle.addImage( image ); } catch ( Exception e ) { e.printStackTrace( ); } } // Load the embedded image from a file on disk. public byte[ ] load( String fileName ) throws IOException { InputStream is = null; is = new BufferedInputStream ( this.getClass( ).getResourceAsStream( fileName )); byte data[ ] = null; if ( is != null ) { try { data = new byte[is.available( )];
118 Integrating Applications into BIRT iHub is.read( data ); } catch ( IOException e1 ) { throw e1; } } return data; }
Adding a report item to a report design A reporting application can use a simple report design or a template to create more complex designs. The application can add extra report items to the design’s structure based on external conditions. For example, based on the user name of the user requesting generation of a report, the application can add extra information to the report for that category of user. To create a design entirely with the API, use the same techniques to add content to the design. The class that creates new elements, such as report items, in a report design is ElementFactory. This class provides methods of the form, newXXX( ), where XXX is the type of report element to create. The method newElement( ) is a generic method that creates an element of any type. To access the element factory, call the ReportDesign.getElementFactory( ) method. Place new report items directly in the body slot, within containers such as a cell in a table or grid, or on the master page. The model API supports adding a simple item, such as a label, or complex items, such as a table with contents in its cells. The location of the new report item is a slot, such as the body slot of the report design or a cell slot in a row in a table. To add a report item to a slot, use one of the SlotHandle.add( ) methods. The method has two signatures that support adding the report item to the end of a slot, or to a particular position in a slot. Table and list elements iterate over the rows that a data set provides. To support access to the data rows for these report item types, bind the item to a data set. The table or list element provides data rows to the report items that it contains. For this reason, bind only the container item to a data set, as described later in this chapter.
How to add a grid item and label item to a report design The code sample in Listing 5-24 creates a grid item and adds a label item to one of the cells in the grid. An application can create any other report item in a similar manner. The variable, design, is a ReportDesignHandle object. Listing 5-24 Adding a container item to the body slot
// Instantiate an element factory. ElementFactory factory = design.getElementFactory( ); try { // Create a grid element with 2 columns and 1 row.
Chapter 5, Programming using the BIRT reporting APIs 119 GridHandle grid = factory.newGridItem( "New grid", 2, 1 ); // Set a simple property on the grid, the width. grid.setWidth( "50%" ); // Create a new label and set its properties. LabelHandle label = factory.newLabel( "Hello Label" ); label.setText( "Hello, world!" ); // Get the first row of the grid. RowHandle row = ( RowHandle ) grid.getRows( ).get( 0 ); // Add the label to the second cell in the row. CellHandle cell = ( CellHandle ) row.getCells( ).get( 1 ); cell.getContent( ).add( label ); // Get the body slot. Add the grid to the end of the slot. design.getBody( ).add( grid ); } catch ( Exception e ) { // Handle any exception }
Accessing a data source and data set with the API This section shows how to use ROM elements that are not report items. To use other ROM elements, such as the libraries that the report design uses, employ similar techniques as for report items. Access the report design’s data sources and data sets using methods on the ReportDesignHandle instance, in a similar way to other report elements. The model classes that define a data source and data set are DataSourceHandle and DataSetHandle, respectively. A data set provides a report item such as a table with data from a data source. For a report item to access the data set, use the item’s setDataSet( ) method. Use a finder method on the report design handle to access a data source or data set by name. The finder methods are findDataSource( ) and findDataSet( ), respectively. Alternatively, to access all the data sources or data sets, use a getter method that returns a slot handle. The getter methods are getDataSources( ) and getDataSets( ), respectively. To access the individual data sources or data sets in a slot handle, iterate over the contents of the slot handle in the same way as for any other slot handle.
About data source classes DataSourceHandle is a subclass of ReportElementHandle. Get and set report item properties for a data source in the same way as for any other report element. DataSourceHandle also provides methods to access the scripting methods of the data source. The two subclasses of DataSourceHandle, OdaDataSourceHandle and ScriptDataSourceHandle, provide the functionality for the two families of BIRT
120 Integrating Applications into BIRT iHub data sources. For more information about ODA data sources, install the Javadoc for the ODA API. The scripting methods for a scripted data source fully define the data source, as described earlier in this book.
About data set classes DataSetHandle is a subclass of ReportElementHandle. Get and set properties for a data set in the same way as for any other report element. DataSetHandle also provides methods to access properties specific to a data set, such as the data source, the data set fields, and the scripting methods of the data set. The two subclasses of DataSetHandle, OdaDataSetHandle and ScriptDataSetHandle, provide the functionality for the two families of BIRT data sets. For more information about ODA data sets, see the Javadoc for the ODA API.
Using a data set programmatically Typically, a reporting application uses data sets and data sources already defined in the report design. Use the data set’s setDataSource( ) method to change the data source of a data set. For example, based on the name of the user of the reporting application, access data from the sales database for a particular geographical region, such as Europe or North America.
Changing the properties of a data set Changing the properties of a data set requires consideration of the impact on the report design. If the application changes the data source of a data set, the type of the data source must be appropriate for the type of the data set. Also ensure that the new data source provides the same data fields as the original data source.
How to change the data source for a data set The code sample in Listing 5-25 shows how to check for a particular data source and data set in a report design and changes the data source for the data set. The code finds the data source and data set by name. Alternatively, use the getDataSets( ) and getDataSources( ) methods. Then, use the technique for iterating over the contents of a slot handle. The variable, design, is a ReportDesignHandle object. Listing 5-25 Modifying a data set
// Find the data set by name. DataSetHandle ds = design.findDataSet( "Customers" ); // Find the data source by name. DataSourceHandle dso = design.findDataSource( "EuropeSales" ); // Check for the existence of the data set and data source. if ( (dso == null) || ( ds == null ) ) {
Chapter 5, Programming using the BIRT reporting APIs 121 System.err.println( "EuropeSales or Customers not found" ); return; } // Change the data source of the data set. try { ds.setDataSource( "EuropeSales" ); } catch ( SemanticException e1 ) { e1.printStackTrace( ); }
Changing the data set binding of a report item Call the report item’s setDataSet( ) method to set or change the data set used by a report item. If the application changes the data set used by a report item, ensure that the new data set supplies all the data bindings that the contents of the report item require. If necessary, change the references to data bindings in data elements, text elements, and scripting methods. If the data bindings in the old data set do not match the names or data types of the fields that the new data set provides, the application or a report developer must resolve the data bindings before generating a report from the modified report design. Use the ReportItemHandle method, columnBindingsIterator( ), to iterate over the column bindings that the report item uses. The items in the list are of type ComputedColumnHandle. This class provides methods to access the name, expression, and data type of the column binding. To access the data set column and expression that a data item uses, call the methods, getResultSetColumn( ) and getResultSetExpression( ). Then, compare the data type and name with the result-set columns that the data set returns.
How to bind a data set to a table The code sample in Listing 5-26 shows how to check for a particular data set in a report design and changes the data set for a table. The code finds the table and data set by name. Alternatively, use slot handles to navigate the design structure. The variable, design, is a ReportDesignHandle object. Listing 5-26 Binding a data set to a report item
// Find the table by name. TableHandle table = ( TableHandle ) design.findElement( "Report Data" ); // Find the data set by name. DataSetHandle ds = design.findDataSet( "EuropeanCustomers" ); // Check for the existence of the table and the data set. if ( ( table == null ) || ( ds == null ) ) { System.err.println( "Incorrect report structure" ); return;
122 Integrating Applications into BIRT iHub } // Change the data set for the table. try { table.setDataSet( ds ); } catch ( Exception e ) { System.err.println( "Could not set data set for table" ); }
Saving a report design After making changes to an existing report design or creating a new report design, an application can save the design for archival purposes or for future use. To overwrite an existing report design to which the application has made changes, use the ReportDesignHandle.save( ) method. To save a new report design or to keep the original report design after making changes, use the ReportDesignHandle.saveAs( ) method. Alternatively, saving the changes to the report design is unnecessary, call ReportDesignHandle.serialize( ) method. This method returns an output stream. The report engine can generate a report by opening this stream as an input stream. If no further changes to the report design are necessary, call the method, ReportDesignHandle.close( ), to close the report design, as shown in the following code. The variable, design, is a ReportDesignHandle object. design.saveAs( "sample.rptdesign" ); design.close( );
Creating a report design The BIRT APIs support using an application to build a report design and generate the report output without using BIRT Report Designer. Use the createDesign( ) method on the session handle class, SessionHandle, to create a report design. Use the other model classes to create its contents, as shown earlier in this chapter.
How to create a new report design The following code creates a report design: SessionHandle session = DesignEngine.newSession( null ); ReportDesignHandle design = session.createDesign( );
Chapter 5, Programming using the BIRT reporting APIs 123 124 Integrating Applications into BIRT iHub Chapter 6
Chapter 6Programming using the BIRT charting API
This chapter contains the following topics: ■ Charting application overview ■ Chart engine contents ■ Environment for a charting application ■ Charting API and the chart structure ■ Using the charting API to create a new chart ■ Modifying chart properties ■ Using a chart item in a report design ■ Using the BIRT charting API in a Java Swing application ■ Chart programming examples
Chapter 6, Programming using the BIRT charting API 125 Charting application overview This chapter describes the basic requirements of a charting application and demonstrates how to use the BIRT charting API to create a new chart and modify an existing chart definition. The BIRT chart engine provides the BIRT charting API. Classes and interfaces in this API support: ■ Writing Java applications to generate many types of charts, such as bar charts, line charts, pie charts, scatter charts, and stock charts. ■ Customizing the properties of a chart to fit the users’ requirements. ■ Modifying an existing chart item in a BIRT report design or adding a chart to an existing report design. This chapter shows how to customize an existing chart and create a new chart within a BIRT application. Use of the charting API in a stand-alone application is beyond the scope of this book. For examples of completed charting applications, download the BIRT samples from the BIRT website. This chapter discusses only the most important of the more than 400 classes and interfaces in the BIRT charting API. For information about the complete set of charting API classes and interfaces, see the online Javadoc. To view the Javadoc, open the online help and navigate to BIRT Charting Programmer Reference ➛Reference➛API Reference.
Chart engine contents Downloading and extracting the chart engine archive file from the Eclipse BIRT download page creates the following three folders: ■ ChartRuntime, which contains the Eclipse plug-ins required to run, render, and edit charts ■ ChartSDK, which contains everything you need to create charting applications, including the following components: ■ All the chart run-time plug-ins and an example plug-in providing sample charting applications including a chart viewer ■ Documentation in the form of online help, context-sensitive help for the user interface components, and Javadoc for the charting API ■ Source code for all the BIRT Chart Engine packages ■ DeploymentRuntime, which contains the JAR files that you need to run a charting application outside Eclipse
126 Integrating Applications into BIRT iHub Environment for a charting application The minimum requirements for creating a basic charting application are: ■ The BIRT charting run-time engine ■ The BIRT run-time engine, for an application that runs within the BIRT report context ■ Java Development Kit 1.6.0 or later ■ Deployment Java archive (.jar) files To develop or run a Java application that incorporates a BIRT chart, you need to include certain JAR files in the Java CLASSPATH. To be certain that the CLASSPATH includes all the JAR files your application needs, include the following files in the CLASSPATH: ■ All the JAR files in DeploymentRuntime/ChartEngine ■ Any custom extension plug-in JAR files that you use Typically, a charting application does not use the functionality from every JAR file in the ChartEngine folder, but having extra JAR files in the CLASSPATH does not affect the performance or size of an application, so the easiest technique is to include them all. Configuring the chart engine run-time environment An application using the BIRT Chart Engine can run either in the context of the BIRT Report Engine or as a stand-alone application. To deploy charts in a BIRT report, use the BIRT Report Engine. A stand-alone application does not use the BIRT Report Engine. Either application produces and consumes charts within itself or passes the chart structure and data to another application. Verifying the environment for a charting application Listing 6-1 illustrates a very basic charting application. The output of this program is a file called myChart.chart, which contains several hundred lines of XML code. This code defines a basic chart with no data, no labels, no series, and no titles. Although this output does not represent a useful chart, compiling and running the program verifies that the environment is configured correctly for a charting application. Listing 6-1 Basic charting application
import java.io.*; import org.eclipse.birt.chart.api.ChartEngine; import org.eclipse.birt.chart.model.*; import org.eclipse.birt.chart.model.impl.*;
Chapter 6, Programming using the BIRT charting API 127 import org.eclipse.birt.core.framework.PlatformConfig; public class MyFirstChartProg { public static void main( String[ ] args ) { PlatformConfig pf = new PlatformConfig(); pf.setProperty("STANDALONE", true); ChartEngine ce = ChartEngine.instance(pf); Chart myChart = ChartWithAxesImpl.create(); Serializer si = SerializerImpl.instance(); try { si.write( myChart,new FileOutputStream( new File ( "C:/temp/myChart.chart" ) ) ); } catch ( IOException e ) { e.printStackTrace( ); } } }
Charting API and the chart structure The chart element in a report design extends the basic BIRT report item through the org.eclipse.birt.report.model.api.ExtendedItemHandle class, so it supports the same standard properties and functionality as all other report items. To access the chart item using the design engine API, call the ExtendedItemHandle .getProperty( ) method with an argument of chart.instance. This call returns an org.eclipse.birt.chart.model.Chart object. All chart types implement this interface through one of the classes, ChartWithAxesImpl, ChartWithoutAxesImpl, and DialChartImpl from the org.eclipse.birt.chart.model.impl package. Cast the Chart object to the appropriate class to change its properties. ChartWithAxesImpl is the most commonly used chart class. This class supports area, bar, bubble, cone, difference, Gantt, line, pyramid, scatter, stock, and tube charts. ChartWithoutAxesImpl supports pie and radar charts. DialChartImpl supports meter charts. Many of these chart types provide subtypes. For example, a bar chart has stacked, percent stacked, and side-by-side subtypes that affect the appearance of a multi-series bar chart. Chart visual components The key visual components of a chart are movable areas known as blocks that are defined by the interface org.eclipse.birt.chart.model.layout.Block. Blocks include the plot, title, and legend areas. A charting application can change the location of the title and legend areas with respect to the plot area.
128 Integrating Applications into BIRT iHub Chart data The key data component of a chart is the series. The series controls the set of values to plot and how to group those values. Charts display the values from series as data points in a chart with axes and as slices or pointers in a chart without axes. A charting application can define series values statically as a data set or dynamically as a query. The chart engine also provides extension points to support custom data set types.
Static data The chart engine requires placing all data in an object that implements the chart org.eclipse.birt.chart.model.data.DataSet interface before generating the chart. The following interfaces in the org.eclipse.birt.chart.model.data.impl package extend the DataSet interface: ■ BubbleDataSet ■ DateTimeDataSet ■ DifferenceDataSet ■ GanttDataSet ■ NumberDataSet ■ StockDataSet ■ TextDataSet Each interface has a corresponding implementation class that supplies a static create method to initialize a data structure. For example, the following code creates a static NumberDataSet for a series in a chart: NumberDataSet seriesOneValues = NumberDataSetImpl.create( new double[ ]{ 15, 23, 55, 76 } ); The chart engine does not support sorting or grouping on a static data set. A chart displays one data point for every value in a static data set in the order provided. Dynamic data The chart engine supports sourcing data from a dynamic source, which includes BIRT data sets and java.sqlResultSet objects. In these cases, the binding phase generates the chart data sets based on the expressions defined in the model for each series in the chart. After completing this phase, each Chart series binds to one of the chart data sets listed in the static data section. A series is a set of plotted values in a chart. BIRT uses a series definition object to define what data a series contains. For example, row["month"] populates a series with the month column from a BIRT data set bound to a chart. This series
Chapter 6, Programming using the BIRT charting API 129 definition object results in a run-time series that is bound to a supported chart data set type when the chart generates. BIRT also supports defining groups and sorting in a series definition. When using these features, BIRT creates additional run-time series as necessary, each with its own chart data set. For example, if a BIRT report contains a data set having three columns, such as the product name, amount sold, and month sold, you can create a bar chart to display the data. The category series contains the product and the value series contains the amount. Using the category series as the x-axis and the value series as the y-axis, the chart model produces two run-time series when generating the chart. You can add the month to the y-axis series to group the data and produce multiple run-time series. The category series and the value series can contain up to twelve run-time series, one for each month. All run-time series for a chart must have the same number of data points. To get the run-time series for a series, call the getRunTimeSeries( ) method for the specific series definition. Listing 6-2 gets a run-time series and sets the first bar series to have a riser type of triangle. Some chart types use nested SeriesDefinitions objects. For example, a pie chart creates a top-level series definition that stores category series information. This top-level series definition also contains another nested series definition that stores the information for the value series. Listing 6-2 Getting a run-time series
function beforeGeneration( chart, icsc ) { importPackage( Packages.org.eclipse.birt.chart.model.attribute ); var xAxis = chart.getBaseAxes( )[0]; var yAxis = chart.getOrthogonalAxes( xAxis, true )[0] var seriesDef = yAxis.getSeriesDefinitions( ).get( 0 ) var runSeries = seriesDef.getRunTimeSeries( ); var firstRunSeries = runSeries.get( 0 ); firstRunSeries.setRiser( RiserType.TRIANGLE_LITERAL ); }
Using the charting API to create a new chart To create a chart instance object for use in a stand-alone application or a report design, use a static method of one of the chart implementation classes. Depending on which chart implementation object you use, you can either create a chart with or without axes. The following line of code creates a chart with axes: ChartWithAxes newChart = ChartWithAxesImpl.create( );
130 Integrating Applications into BIRT iHub Modifying chart properties Each of the available chart implementations provides a set of properties. The properties of the chart define everything about a stand-alone chart. Chart properties do not define the integration of a Chart object into a chart element in a report design, such as binding a data set to a chart and a chart’s ultimate display size. A section later in this chapter describes how to set up a chart as an element in a report design. The BIRT Chart Engine API supports changing chart properties. All charts have the properties that the Chart interface provides, such as dimension, which sets the appearance of the chart as two-dimensional, two-dimensional with depth, or three-dimensional, and plot, which is the area that contains the chart itself. The ChartWithAxesImpl class implements the ChartWithAxes interface, which provides properties related to x-, y-, and for some chart types, z-axes. The ChartWithoutAxesImpl class implements the ChartWithoutAxes interface, which provides properties for pie slices. The DialChartImpl class implements the ChartWithoutAxes and DialChart interfaces. DialChart supports the superimposition property that meter charts use. Each interface provides getter and setter methods for its properties, and other methods if necessary. For example, for the dimension property, the Chart interface provides getDimension( ), setDimension( ), isSetDimension( ), and unsetDimension( ) methods. Simple and complex properties Some properties, like dimension, are simple properties that take a single value. Some simple properties accept a restricted set of values that the class defines as static fields. Use the Javadoc to find these values. Other properties, such as a chart’s plot or title, are complex. A getter method for a complex property returns an object. For example, the Chart.getTitle( ) method returns an org.eclipse.birt.chart.model.layout.TitleBlock object. The Chart interfaces do not provide setter methods for complex properties. When code changes the properties of a complex property, the changes take effect on the chart immediately. Some properties, such as the horizontal spacing of elements within a plot, use values based on the current units of measurement. Call the Chart.setUnits( ) method to set the units that you prefer. Listing 6-3 shows how to set simple and complex properties and the units of measurement.
Chapter 6, Programming using the BIRT charting API 131 Listing 6-3 Getting and setting chart properties
// Simple properties // Set a chart’s appearance to two-dimensional chart.setDimension( ChartDimension.TWO_DIMENSIONAL_LITERAL ); // Set the units of measurement for the chart chart.setUnits( UnitsOfMeasurement.PIXELS_LITERAL.getLiteral( ) ); // Complex properties // Set the chart’s title chart.getTitle( ).getLabel( ).getCaption( ).setValue( "Europe" ); // Rotate the text in the chart’s title chart.getTitle( ).getLabel( ).getCaption( ).getFont( ) .setRotation( 5 ); // Set chart block properties chart.getBlock( ).setBackground( ColorDefinitionImpl.WHITE( )); chart.getBlock( ).setBounds( BoundsImpl.create( 0, 0, 400, 250 ));
Plot properties All charts have a plot property, which specifies the area in a Chart object that contains the chart itself. The plot is an object that implements the org.eclipse .birt.chart.model.layout.Plot interface. Plot defines horizontal and vertical spacing and the client area, which contains the rendering of the chart. The client area is itself a complex property that defines properties such as the background color and outline of the rendered chart. Plot provides all the properties defined by the Block interface in the same package, such as the background and outline. When setting values for a property that multiple components provide, determine the best class on which to modify the property based on the characteristics of all the classes. To set properties of the plot, first get a Plot object from the chart instance object. Then, use a setter method of a component of the Plot object. Listing 6-4 illustrates how to get the chart plot and modify its properties. Listing 6-4 Getting chart plot and modifying its properties
Plot plot = chart.getPlot( ); plot.getClientArea().setBackground( ColorDefinitionImpl.CREAM( )); plot.setHorizontalSpacing( plot.getHorizontalSpacing( ) + 10 ); plot.getOutline( ).setVisible( true );
Legend properties All charts have a legend property, which is the area in a Chart object that contains the chart legend. For a chart without axes, the legend identifies the slices on a pie chart or pointers on a meter chart. For a chart with axes, the legend identifies the
132 Integrating Applications into BIRT iHub series that display values on the x-axis. For a chart with multiple y-series, the legend displays separate sections for each series. Typically, if there is only one x-axis group and one y-series, do not make the legend visible. The legend is an object that implements the org.eclipse.birt.chart.model .layout.Legend interface, which extends the Block interface. Legend provides all the Block properties, plus properties specific to Legend, such as position, title, text, and values. The default position of the legend is to the right of the plot area. Within this position, change the location of the legend by setting its anchor property. To set properties of the chart legend, first get a Legend object from the chart instance object. Then, use a setter method of a component of the Legend object. To set properties of legend lines, use a LineAttribute object from the Legend object. Listing 6-5 illustrates how to get the chart legend and modify its properties. Listing 6-5 Getting and setting legend properties
Legend legend = chart.getLegend( ); legend.getText( ).getFont( ).setSize( 16 ); legend.getInsets( ).set( 10, 5, 0, 0 ); legend.setAnchor( Anchor.NORTH_LITERAL ); // Set the attributes of the legend’s outline legend.getOutline( ).setVisible( false ); LineAttributes lia = legend.getOutline( ); lia.setStyle( LineStyle.SOLID_LITERAL );
Axes properties A chart with axes always has at least two axes, the primary base axis and the axis orthogonal to the base axis. A primary base axis is a category axis, which displays values of any data type and is typically an x-axis. A chart can have more than one primary base axis. Every base axis has at least one axis that is orthogonal to it. An orthogonal axis is a value axis, which displays numeric values and is typically a y-axis. The org.eclipse.birt.chart.model.component.Axis interface supports both category and value axes. To set the properties of one or more axes of a chart, cast the Chart object to a type of ChartWithAxes, as shown in the following statement: cwaChart = ( ChartWithAxes ) chart; To access a category axis, call the ChartWithAxes.getPrimaryBaseAxes( ) method. This method returns an array. If there is only one primary base axis, get the first element of the array, as shown in the following code: Axis xAxisPrimary = newChart.getPrimaryBaseAxes( )[0];
Chapter 6, Programming using the BIRT charting API 133 To access the value axis for a single value-axis chart, call the method, getPrimaryOrthogonalAxis( ). For a chart having multiple value axes, access the list of axes by calling getOrthogonalAxes( ). Listing 6-6 illustrates the technique for getting the axes of a chart and setting their properties. Listing 6-6 Getting category and value axes and setting their properties
Axis xAxisPrimary = cwaChart.getPrimaryBaseAxes( )[0]; xAxisPrimary.getLabel( ).getCaption( ).getFont( ).setRotation(45); xAxisPrimary.setType( AxisType.TEXT_LITERAL ); xAxisPrimary.getMajorGrid().setTickStyle(TickStyle.BELOW_LITERAL); xAxisPrimary.getOrigin( ).setType(IntersectionType.VALUE_LITERAL); xAxisPrimary.getTitle( ).setVisible( false ); Axis yAxisPrimary = cwaChart.getPrimaryOrthogonalAxis( xAxisPrimary ); yAxisPrimary.getMajorGrid( ).setTickStyle(TickStyle.LEFT_LITERAL); yAxisPrimary.setType( AxisType.LINEAR_LITERAL ); yAxisPrimary.getScale( ).setMax( NumberDataElementImpl.create (1000)); yAxisPrimary.getScale( ).setMin( NumberDataElementImpl.create(0)); yAxisPrimary.getTitle( ).getCaption( ).setValue( "Sales Growth" ); yAxisPrimary.setFormatSpecifier ( JavaNumberFormatSpecifierImpl.create( "$" ));
Using series All charts use series to define the data values to represent. Series objects contain a list of values to plot on the chart. To instantiate a Series object, call the static create( ) method on org.eclipse.birt.chart.model.component.impl.SeriesImpl. Define the set of values for a series either with a dynamic query that accesses an external data source or with a static data set that is a list of values. A query on the series definition object supports grouping and sorting of the data. The series for an x-axis or for the values that control the number of sectors in a pie can contain non-numeric data values, such as dates or text values. For example, these series can contain the quarters in a range of years, or product codes or countries. The series for a y-axis or for the values that control the size of the sectors in a pie chart must hold numeric values. These series are implementations of specific subinterfaces of the Series interface. Each chart type uses its own series type, to control the chart represents the values. For example, a BarSeries object has riser and riser outline properties to control the appearance of the bars. Series definition objects provide access to the series objects for the chart and standard properties such as the palette of colors in which to display pie sectors, bars, and other markers. To instantiate a SeriesDefinition object, call the static
134 Integrating Applications into BIRT iHub org.eclipse.birt.chart.model.data.impl.SeriesDefinitionImpl.create( ) method. To add a series to a series definition, get the collection of series and add the series to that collection. To set the color of a series, get a SeriesPalette object and call its shift( ) method. A series definition supports multiple series. The series do not all have to be the same type. For example, a line chart can use the same axes as a bar chart. Typically, a chart displays extra series on a y-axis, not on an x-axis. Listing 6-7 illustrates how to get a series definition from an axis and how to change a property of the series. Listing 6-7 Getting a series definition and setting a property
SeriesDefinition seriesDefX = SeriesDefinitionImpl.create( ); seriesDefX = ( SeriesDefinition ) xAxisPrimary.getSeriesDefinitions( ).get( 0 ); seriesDefX.getSeriesPalette( ).shift( 1 );
Adding a series to a chart To display values on a chart, add category and value series to a newly created chart or modify the series on an existing chart. For a chart with axes, associate series with both category and value axes.
Creating a category series On a chart with axes, the category series is the set of values that the category axis displays. On a chart without axes, the category series defines the number of sectors in a pie chart or the number of pointers on a meter chart. To create a category series, use the static create( ) method of the SeriesImpl class, as shown in the following line: Series seriesCategory = SeriesImpl.create( );
Creating an orthogonal series The orthogonal series specifies the representation of the values in the value series. On a chart with axes, the orthogonal series is the set of values that display on the y-axis, for example, appearing as bars, bubbles, stock bar sticks or candlesticks. On a chart without axes, the orthogonal series sets the size of slices in a pie or the position of a pointer on a meter chart. A chart can have multiple orthogonal series of the same or differing types. The orthogonal series classes are subclasses of the SeriesImpl class, and are located in the org.eclipse.birt.chart.model.type.impl package. The following classes are available:
Chapter 6, Programming using the BIRT charting API 135 ■ AreaSeriesImpl ■ GanttSeriesImpl ■ BarSeriesImpl ■ LineSeriesImpl ■ BubbleSeriesImpl ■ PieSeriesImpl ■ DialSeriesImpl ■ ScatterSeriesImpl ■ DifferenceSeriesImpl ■ StockSeriesImpl
The BarSeriesImpl class supports bar, cone, pyramid, and tube chart types. To create an orthogonal series, use the static create( ) method of the series class. The following line shows an example of creating a bar series: BarSeries barSeries2 = ( BarSeries ) BarSeriesImpl.create( );
Setting series properties A category series supports only the properties defined by the SeriesImpl class. A value series supports additional properties defined by the relevant subclass of SeriesImpl. For example, a bar series supports bar stacking and outlines on the risers. A pie series supports slice outlines and exploded slices. To set the properties of a series, use getter and setter methods of the appropriate series objects, as shown in Listing 6-8, which sets properties on BarSeries and LineSeries objects. Listing 6-8 Setting the properties of a bar series and line series
LineSeries ls1 = ( LineSeries ) LineSeriesImpl.create( ); ls1.getLineAttributes( ).setColor( ColorDefinitionImpl.RED( ) ); BarSeries bs1 = ( BarSeries ) BarSeriesImpl.create( ); bs1.getLabel( ).setVisible( true ); bs1.getLabel( ).getCaption( ).setValue( "Q2" );
Associating data with a series Create either a query or a data set, and add that object to the series data definition. To create a query, use the static create( ) method of the org.eclipse.birt.chart.model.data.impl.QueryImpl class. To create a data set, use the static create( ) method on a subclass of DataSetImpl. The data set type must match the type of values that the axis displays. For example, a category axis displaying date-and-time data values requires a data set of class DateTimeDataSet. Similarly, a bar series requires a numeric data set, of class NumberDataSet. Some series require multiple sets of data. For example, a stock series requires four sets of data, high, low, open, and close. Either add four queries in that order to the series, or add a StockDataSet to the series. Listing 6-9 adds queries and data sets to line, bar, and stock series.
136 Integrating Applications into BIRT iHub Listing 6-9 Setting a query and a data set on category series
// Setting a query on a category series Series seriesCategory = SeriesImpl.create( ); Query query = QueryImpl.create( "row[\"CATEGORY\"]" ); seriesCategory.getDataDefinition( ).add( query ); // Setting a data set on a category series Series seBase = SeriesImpl.create( ); DateTimeDataSet dsDateValues = DateTimeDataSetImpl.create( new Calendar[ ]{ new CDateTime( 2011, 12, 21 ), new CDateTime( 2011, 12, 20 ), new CDateTime( 2011, 12, 19 ), new CDateTime( 2011, 12, 18 ), } ); seBase.setDataSet( dsDateValues ); Listing 6-10 illustrates how to create a second value series, set some of its properties, assign data to the series, and add the series to an axis. Listing 6-10 Creating a series, setting properties, and adding it to an axis
SeriesDefinition seriesDefY = SeriesDefinitionImpl.create( ); seriesDefY.getSeriesPalette( ).update( ColorDefinitionImpl .YELLOW( ) ); BarSeries barSeries2 = ( BarSeries ) BarSeriesImpl.create( ); barSeries2.setSeriesIdentifier( "Q2" ); barSeries2.setRiserOutline( null ); barSeries2.getLabel( ).setVisible( true ); barSeries2.setLabelPosition( Position.INSIDE_LITERAL ); // Assign data to the series Query query2 = QueryImpl.create( "row[\"VALUE2\"]" ); barSeries2.getDataDefinition( ).add( query2 ); seriesDefY.getSeries( ).add( barSeries2 ); // Add the new series to the y-axis yAxisPrimary.getSeriesDefinitions( ).add( seriesDefY );
Adding a series definition to a chart After setting the properties of a SeriesDefinition object, add the object to the chart. For a chart without axes, add the series definitions directly to the Chart object’s collection of series definitions. The first series definition in the collection defines the category series and the second one defines the orthogonal series. For a chart with axes, add the series definition to each Axis object’s collection of series definitions as shown in Listing 6-11.
Chapter 6, Programming using the BIRT charting API 137 Listing 6-11 Adding series definitions to a pie chart and a chart with axes
ChartWithoutAxes cwoaPie = ChartWithoutAxesImpl.create( ); cwoaPie.getSeriesDefinitions( ).add( sd ); PieSeries sePie = ( PieSeries ) PieSeriesImpl.create( ); sePie.setDataSet( seriesOneValues ); sePie.setSeriesIdentifier( "Cities" ); sd.getSeriesDefinitions( ).add( sdCity ); xAxisPrimary.getSeriesDefinitions( ).add( sdX ); yAxisPrimary.getSeriesDefinitions( ).add( sdY1 ); yAxisPrimary.getSeriesDefinitions( ).add( sdY2 );
Setting up the default aggregation for the chart A chart plots every value that it receives unless an org.eclipse.birt.chart .model.data.SeriesGrouping object defines the type of aggregation to perform. Set up aggregation on the category series to define the value on which to aggregate and the type of aggregation, as shown in Listing 6-12. The chart builder user interface displays the available aggregation types. All orthogonal series use the aggregation type specified by the category series grouping by default. Listing 6-12 Defining aggregation on the category series
SeriesGrouping grouping = sdX.getGrouping( ); grouping.setEnabled( true ); grouping.setGroupType( DataType.TEXT_LITERAL ); grouping.setGroupingUnit( GroupingUnitType.STRING_LITERAL ); grouping.setGroupingInterval( 0 ); grouping.setAggregateExpression( "Sum" );
Changing the aggregation for secondary value series Every value series uses the same aggregation expression to aggregates values to display unless the application changes the aggregation by setting up a SeriesGrouping specific to the series. Change only the grouping properties that differ from the default grouping, as shown in Listing 6-13. Listing 6-13 Defining aggregation on a value series
SeriesGrouping groupingY2 = sdY2.getGrouping( ); groupingY2.setEnabled( true ); groupingY2.setAggregateExpression( "Average" );$
Chart event handlers Two kinds of chart event handlers are available to a charting application: a Java event handler or a JavaScript event handler.
138 Integrating Applications into BIRT iHub Java chart event handlers To add a Java event handler, create a separate Java class file containing the event handler method or methods. The process for creating a Java event handler class is identical to the process for creating a Java event handler class for any other report item, as described in the chapters on scripting with Java and scripting for charts. The class must include a function for every event handler method of the chart. To register a Java class in the charting application code, use the setScript( ) method of the chart instance object, as shown in the following statement: chart.setScript ( "com.MyCompany.eventHandlers.ChartEventHandlers" ); The string argument passed to the setScript( ) method is the fully qualified name of the Java class. Do not include the .class extension in the class name.
JavaScript chart event handlers To add a JavaScript event handler, code the script as one long string and pass that string to the setScript( ) method of the chart instance object. For example, the statement in Listing 6-14 passes a string to chart.setScript( ) containing event handler script for the beforeDrawDataPointLabel event handler. Line breaks in the JavaScript code are indicated by backslash n ( \n ), and quotes within the script are indicated by a backslash quote ( \" ). The JavaScript code consists of several strings concatenated together to form a single string. This technique helps make the script more readable. Listing 6-14 Adding an event handler script to a bar chart
cwaBar.setScript ( "function beforeDrawDataPointLabel" + "(dataPoints, label, scriptContext)" + "{val = dataPoints.getOrthogonalValue( );" + "clr = label.getCaption( ).getColor( );" + "if ( val < -10 ) clr.set( 32, 168, 255 );" + "else if ( ( val >= -10 ) & ( val <=10 ) )" + "clr.set( 168, 0, 208 );" + "else if ( val > 10 ) clr.set( 0, 208, 32 );}")
Using a chart item in a report design A Java program can open an existing BIRT report design file and alter the content of the report before displaying or saving the report. The chapter on programming BIRT describes how to open a report design file using the BIRT engine and model APIs. This section describes how to use the BIRT charting API to modify an existing chart element in the report design and to create a new chart element. The following sections contain code examples for each step in the process.
Chapter 6, Programming using the BIRT charting API 139 Accessing an existing chart item To get a chart report item from a report design, first perform the following steps using the BIRT core and model APIs, as described earlier in this book: ■ Start the platform using a configuration object, a design engine factory, and a design engine. ■ Use the design engine to create a session handle object. ■ Create a design handle object for a report design from the session handle. ■ Use the design handle object to access the chart element in the design. Next, retrieve a Chart object from the chart item. This Chart object supports accessing the BIRT Chart Engine classes and using BIRT’s charting API. Listing 6-15 illustrates the process of getting a chart report item. This code assumes that the chart is the first report item in a list and that the list is the first report item in the report. Listing 6-15 Getting a ReportDesignHandle object and a Chart object
DesignConfig dConfig = new DesignConfig( ); IDesignEngine dEngine = null; ReportDesignHandle dHandle = null; try { Platform.startup( dConfig ); IDesignEngineFactory dFactory = ( IDesignEngineFactory ) Platform. createFactoryObject( IDesignEngineFactory. EXTENSION_DESIGN_ENGINE_FACTORY ); dEngine = dFactory.createDesignEngine( dConfig ); SessionHandle sessionHandle = dEngine.newSessionHandle( ULocale.ENGLISH ); dHandle = sessionHandle.openDesign( reportName ); } catch ( BirtException e ) { e.printStackTrace( ); return; } ListHandle li = ( ListHandle ) dHandle.getBody( ).getContents( ).get( 0 ); ExtendedItemHandle eihChart1 = ( ExtendedItemHandle ) li.getSlot( 0 ).getContents( ).get( 0 ); Chart chart = ( Chart ) eihChart1.getProperty( "chart.instance" );
Creating a new chart item Before creating a new chart item in a report design, a charting application performs all the steps to start up the platform and design engine, as described in the previous section. Next, the application creates the Chart object as described
140 Integrating Applications into BIRT iHub earlier in this chapter. Creating a new Chart object for use in a report design is identical to creating a chart for a stand-alone application. Finally, the application creates a chart element and sets up the properties required to link the Chart object to the element by performing the following tasks. These tasks relate to the appearance and behavior of a chart inside a report design. If the chart is not deployed in a report, the tasks in this section are not required.
■ Getting an ElementFactory object The ElementFactory object supports creating a new report element.
■ Setting the chart type and creating sample data The chart type and sample data provide a guide to the appearance of a chart element in a report design in BIRT Report Designer.
■ Getting an ExtendedItemHandle object The ExtendedItemHandle object is similar to a standard report item handle. The item handle associates the Chart object with the report item instance in the report design. The handle is also the object that binds to a data set.
■ Setting the chart.instance property on the report item The chart.instance property of the report item identifies the chart instance object and links the report item to the chart instance object.
■ Getting a data set from the report design A chart must bind to data in order to have meaning. The report design provides access to one or more data sets that the report developer defined. The program can create a data set and add it to the design.
■ Binding a chart to the data set To bind a chart to a data set, specify the data set as a property of the extended item handle object.
■ Setting any other report item properties
■ Adding the new chart to the report design The last step is to add the chart to the report design by adding the extended item handle object to the report design.
■ Optionally saving the report design An application program that creates or modifies a BIRT report design can save the new or modified report design. The following sections describe these tasks in more detail and provide code examples for every step.
Chapter 6, Programming using the BIRT charting API 141 Getting a design engine element factory object Creating a chart item in a report design requires an ElementFactory object. To get an ElementFactory object, use the getElementFactory( ) method of the ReportDesignHandle object, as shown in the following line of code: ElementFactory ef = dHandle.getElementFactory( ); The chapter on programming with the BIRT APIs provides more information about using the Design Engine APIs and how to place a new item in a report design. Setting the chart type and subtype A chart’s type and subtype determine the appearance of the chart in BIRT Report Designer. In conjunction with sample data, these properties provide a realistic rendering of the chart item in the report design’s layout window and in the chart wizard. To ensure that the appearance of this rendered chart is as accurate as possible, set the chart’s type so that it matches the series type set on the axis. Many types, such as bar, Gantt, line, and stock, are available for a chart with axes. Charts without axes can be dial, pie, or radar types only. The bubble, dial, difference, Gantt, and pie classes each support only a single type. The other chart types have multiple subtypes. Set the chart type and subtype by using the Chart methods setType( ) and setSubType( ) respectively. These methods take a single String argument. Table 6-1 shows the available values for chart types and the valid subtypes for each chart type. Because cone, pyramid, and tube charts are merely different representations of a bar chart, they have the same subtypes as a bar chart. Table 6-1 Chart type and subtype properties Chart axes Type Subtype With axes Area Chart Overlay Percent Stacked Stacked Bar Chart Percent Stacked Side-by-side Stacked Bubble Chart Standard Bubble Chart Cone Chart Percent Stacked Side-by-side Stacked Difference Chart Standard Difference Chart
142 Integrating Applications into BIRT iHub Table 6-1 Chart type and subtype properties Chart axes Type Subtype Gantt Chart Standard Gantt Chart Line Chart Overlay Percent Stacked Stacked Pyramid Chart Percent Stacked Side-by-side Stacked Scatter Chart Standard Scatter Chart Stock Chart Standard Stock Chart Bar Stick Stock Chart Tube Chart Percent Stacked Side-by-side Stacked Without axes Meter Chart Standard Meter Chart Superimposed Meter Chart Pie Chart Standard Pie Chart Radar Radar.STANDARD_SUBTYPE_LITERAL Radar.SPIDER_SUBTYPE_LITERAL Radar.BULLSEYE_SUBTYPE_LITERAL
Listing 6-16 shows how to set a chart type and subtype. Listing 6-16 Setting a chart’s type and subtype
ChartWithAxes cwaBar = ChartWithAxesImpl.create( ); cwaBar.setType( "Bar Chart" ); cwaBar.setSubType( "Side-by-side" );
Creating sample data This section describes an optional step in the creation of a chart. Sample data provides visual information in BIRT Report Designer about a chart’s appearance. If you omit the code in Listing 6-17, the chart renders correctly when the report generates, but the designer’s layout window does not display sample values.
Chapter 6, Programming using the BIRT charting API 143 Listing 6-17 Adding sample data to a chart
SampleData sdt = DataFactory.eINSTANCE.createSampleData( ); BaseSampleData sdBase = DataFactory.eINSTANCE.createBaseSampleData( ); sdBase.setDataSetRepresentation( "A" ); sdt.getBaseSampleData( ).add( sdBase ); OrthogonalSampleData sdOrthogonal = DataFactory.eINSTANCE.createOrthogonalSampleData( ); sdOrthogonal.setDataSetRepresentation( "1" ); sdOrthogonal.setSeriesDefinitionIndex( 0 ); sdt.getOrthogonalSampleData( ).add( sdOrthogonal ); newChart.setSampleData( sdt );
Getting an extended item handle object A chart report item extends from the design engine’s ReportItemHandle class by further extending the ExtendedItemHandle class. Use the ElementFactory object to create this object by using the newExtendedItem( ) method of the ElementFactory object, as shown in the following line of code: ExtendedItemHandle chartHandle = ef.newExtendedItem( null, "Chart" );
Setting up the report item as a chart Set the chart.instance property of the report item object to contain the chart instance object. Get the report item from the extended item handle object, as shown in Listing 6-18. Listing 6-18 Associating a Chart object with an extended item handle
ExtendedItemHandle chartHandle = ef.newExtendedItem( null, "Chart" ); try { chartHandle.getReportItem( ).setProperty( "chart.instance", newChart ); } catch( ExtendedElementException e ) { e.printStackTrace( ); }
Preparing a data set and data columns The new chart item still does not have access to data from the report design. The chart item uses data rows from a data set and column bindings that define how to apply values from data set columns to the chart. The names of the column bindings must match the column names used in the chart’s series objects.
144 Integrating Applications into BIRT iHub To access a data set, create a data set or get an existing data set from the report design. Next, set up the columns to bind to the chart by instantiating org.eclipse.birt.report.model.api.elements.structures.ComputedColumn objects. A ComputedColumn object contains an expression that accesses columns from a data set. The code in Listing 6-19 gets the first data set in the report design. Listing 6-19 Accessing a data set and preparing columns
DataSetHandle dataSet = ( DataSetHandle ) dHandle.getDataSets( ).get( 0 ); ComputedColumn col1 = StructureFactory.createComputedColumn( ); col1.setName( "VALUE1" ); col1.setExpression( "dataSetRow[\"QUANTITYORDERED\"]") ; col1.setDataType( DesignChoiceConstants.COLUMN_DATA_TYPE_INTEGER ); ComputedColumn col2 = StructureFactory.createComputedColumn( ); col2.setName( "VALUE2" ); col2.setExpression( "dataSetRow[\"PRICEEACH\"]" ); col2.setDataType( DesignChoiceConstants.COLUMN_DATA_TYPE_FLOAT ); ComputedColumn col3 = StructureFactory.createComputedColumn( ); col3.setName( "CATEGORY" ); col3.setExpression( "dataSetRow[\"PRODUCTLINE\"]"); col3.setDataType( DesignChoiceConstants.COLUMN_DATA_TYPE_STRING );
Binding the chart to the data set Use the extended item handle to bind the chart to the data set and data columns, as shown in Listing 6-20. Listing 6-20 Binding a data set and columns to the chart item try { chartHandle.setDataSet( dataSet ); extendedItemHandle.addColumnBinding( col1, true ); extendedItemHandle.addColumnBinding( col2, true ); extendedItemHandle.addColumnBinding( col3, true ); } catch ( SemanticException e ) { e.printStackTrace( ); }
Setting any other report item properties The extended report item supports all the properties provided by the org.eclipse.birt.report.model.api.ReportItemHandle class. These properties include a bookmark, dimensions, and a theme. For example, to set the dimensions of the chart report item, use code as shown in Listing 6-21.
Chapter 6, Programming using the BIRT charting API 145 Listing 6-21 Setting chart item properties
try { extendedItemHandle.setHeight( "250pt" ); extendedItemHandle.setWidth( "400pt" ); } catch ( SemanticException e ) { e.printStackTrace( ); }
Adding the new chart to the report design After setting the properties of the chart and binding the chart to data, add the new chart to the report design. Listing 6-22 adds the chart item to the footer of an existing list item. Listing 6-22 Adding the chart item to the report design
ListHandle li = ( ListHandle ) dHandle.getBody( ).getContents( ).get( 0 ); try { li.getFooter( ).add( chartHandle ); } catch ( ContentException e3 ) { e3.printStackTrace( ); } catch ( NameException e3 ) { e3.printStackTrace( ); }
Saving the report design after adding the chart The report design file on disk does not yet contain the chart report item. Typically, you save the modified report design with a new name in order not to overwrite the original report design file. try { dHandle.saveAs( "./Test_modified.rptdesign" ); } catch ( IOException e ) { e.printStackTrace( ); } dHandle.close( );
Putting it all together The code in Listing 6-23 uses many of the techniques illustrated in this chapter in a complete Java application that creates a chart report item. Listing 6-23 Adding a chart to the report design
import java.io.IOException; import org.eclipse.birt.chart.model.ChartWithAxes; import org.eclipse.birt.chart.model.attribute.Anchor;
146 Integrating Applications into BIRT iHub import org.eclipse.birt.chart.model.attribute.AxisType; import org.eclipse.birt.chart.model.attribute.DataType; import org.eclipse.birt.chart.model.attribute.GroupingUnitType; import org.eclipse.birt.chart.model.attribute.IntersectionType; import org.eclipse.birt.chart.model.attribute.LineAttributes; import org.eclipse.birt.chart.model.attribute.LineStyle; import org.eclipse.birt.chart.model.attribute.MarkerType; import org.eclipse.birt.chart.model.attribute.TickStyle; import org.eclipse.birt.chart.model.attribute.impl.BoundsImpl; import org.eclipse.birt.chart.model.attribute.impl .ColorDefinitionImpl; import org.eclipse.birt.chart.model.component.Axis; import org.eclipse.birt.chart.model.component.Series; import org.eclipse.birt.chart.model.component.impl.SeriesImpl; import org.eclipse.birt.chart.model.data.BaseSampleData; import org.eclipse.birt.chart.model.data.DataFactory; import org.eclipse.birt.chart.model.data.OrthogonalSampleData; import org.eclipse.birt.chart.model.data.Query; import org.eclipse.birt.chart.model.data.SampleData; import org.eclipse.birt.chart.model.data.SeriesDefinition; import org.eclipse.birt.chart.model.data.SeriesGrouping; import org.eclipse.birt.chart.model.data.impl .NumberDataElementImpl; import org.eclipse.birt.chart.model.data.impl.QueryImpl; import org.eclipse.birt.chart.model.data.impl .SeriesDefinitionImpl; import org.eclipse.birt.chart.model.impl.ChartWithAxesImpl; import org.eclipse.birt.chart.model.layout.Legend; import org.eclipse.birt.chart.model.layout.Plot; import org.eclipse.birt.chart.model.type.LineSeries; import org.eclipse.birt.chart.model.type.impl.LineSeriesImpl; import org.eclipse.birt.core.exception.BirtException; import org.eclipse.birt.core.framework.Platform; import org.eclipse.birt.report.engine.api.EngineConfig; import org.eclipse.birt.report.model.api.DataSetHandle; import org.eclipse.birt.report.model.api.DesignConfig; import org.eclipse.birt.report.model.api.ElementFactory; import org.eclipse.birt.report.model.api.ExtendedItemHandle; import org.eclipse.birt.report.model.api.IDesignEngine; import org.eclipse.birt.report.model.api.IDesignEngineFactory; import org.eclipse.birt.report.model.api.ListHandle;
Chapter 6, Programming using the BIRT charting API 147 import org.eclipse.birt.report.model.api.PropertyHandle; import org.eclipse.birt.report.model.api.ReportDesignHandle; import org.eclipse.birt.report.model.api.SessionHandle; import org.eclipse.birt.report.model.api.StructureFactory; import org.eclipse.birt.report.model.api.activity .SemanticException; import org.eclipse.birt.report.model.api.command.ContentException; import org.eclipse.birt.report.model.api.command.NameException; import org.eclipse.birt.report.model.api.elements .DesignChoiceConstants; import org.eclipse.birt.report.model.api.elements.structures .ComputedColumn; import org.eclipse.birt.report.model.api.extension .ExtendedElementException; import org.eclipse.birt.report.model.api.extension.IReportItem; import com.ibm.icu.util.ULocale; /************************************************************* * Read a BIRT report design file, add a chart and write a * new report design file containing the added chart. * Run this application with the following command line: * java ChartReportApp origDesign modifiedDesign ************************************************************/ public class ChartReportApp { private static String reportName = "./test.rptdesign"; private static String newReportDesign = "./test_new.rptdesign"; /************************************************************ * Get the report design name and the name of the modified * report design from the command line if the command line has * any arguments. * Create an instance of this class, create a new chart, * write a new design file containing both the original and * the new chart *************************************************************/ public static void main( String[ ] args ) { if( args.length > 0 ) { reportName = args[0]; } if( args.length > 1 ) { newReportDesign = args[1]; }
148 Integrating Applications into BIRT iHub ReportDesignHandle dHandle = createDesignHandle(reportName); // create an instance of this class ChartReportApp cra = new ChartReportApp( ); // Call the build method of this class. cra.build( dHandle, newReportDesign ); } /******************************************************** * The report design handle object is the entry point to * the report. * Create a report design handle object based on the * original design file by performing the following steps: * 1) Start the platform using the configuration object * 2) Create a design engine factory object from the platform * 3) Create a design engine using the factory object * 4) Create a session handle object from the design engine * 5) Create a design handle object from the session handle * The resulting design handle object is the entry point * to the report design and thus to the chart. *********************************************************/ private static ReportDesignHandle createDesignHandle ( String reportName ) { EngineConfig config = new EngineConfig( ); DesignConfig dConfig = new DesignConfig( ); IDesignEngine dEngine = null; ReportDesignHandle dHandle = null; try { Platform.startup( config ); IDesignEngineFactory dFactory = ( IDesignEngineFactory ) Platform.createFactoryObject( IDesignEngineFactory.EXTENSION_DESIGN_ENGINE_FACTORY ); dEngine = dFactory.createDesignEngine( dConfig ); SessionHandle sessionHandle = dEngine.newSessionHandle( ULocale.ENGLISH ); dHandle = sessionHandle.openDesign( reportName ); } catch(BirtException e) { e.printStackTrace(); } return dHandle; } /*********************************************************** * Build a chart
Chapter 6, Programming using the BIRT charting API 149 ***********************************************************/ public void build ( ReportDesignHandle dHandle, String newDesignName ) { // Create a new chart instance object ChartWithAxes newChart = ChartWithAxesImpl.create( ); // Set the properties of the chart newChart.setType( "Line Chart" ); newChart.setSubType( "Overlay" ); newChart.getBlock().setBackground( ColorDefinitionImpl.WHITE() ); newChart.getBlock().setBounds( BoundsImpl.create( 0, 0, 400, 250 ) ); Plot p = newChart.getPlot(); p.getClientArea().setBackground( ColorDefinitionImpl.create( 255, 255, 225 )); newChart.getTitle().getLabel().getCaption() .setValue( "Europe" ); Legend lg = newChart.getLegend( ); LineAttributes lia = lg.getOutline( ); lg.getText().getFont().setSize( 16 ); lia.setStyle( LineStyle.SOLID_LITERAL ); lg.getInsets().set( 1, 1, 1, 1 ); lg.getOutline().setVisible( false ); lg.setAnchor( Anchor.NORTH_LITERAL ); Axis xAxisPrimary = newChart.getPrimaryBaseAxes( )[0]; xAxisPrimary.setType( AxisType.TEXT_LITERAL ); xAxisPrimary.getMajorGrid().setTickStyle( TickStyle.BELOW_LITERAL ); xAxisPrimary.getOrigin().setType( IntersectionType.VALUE_LITERAL ); xAxisPrimary.getTitle().setVisible( false ); Axis yAxisPrimary = newChart.getPrimaryOrthogonalAxis( xAxisPrimary ); yAxisPrimary.getMajorGrid().setTickStyle( TickStyle.LEFT_LITERAL ); yAxisPrimary.getScale().setMax( NumberDataElementImpl.create( 160 )); yAxisPrimary.getScale().setMin(NumberDataElementImpl .create( -50 )); yAxisPrimary.getTitle().getCaption() .setValue( "Sales Growth" ); // Create sample data.
150 Integrating Applications into BIRT iHub SampleData sdt = DataFactory.eINSTANCE.createSampleData(); BaseSampleData sdBase = DataFactory.eINSTANCE.createBaseSampleData(); sdBase.setDataSetRepresentation("A"); sdt.getBaseSampleData().add( sdBase ); OrthogonalSampleData sdOrthogonal = DataFactory.eINSTANCE.createOrthogonalSampleData(); sdOrthogonal.setDataSetRepresentation( "1"); sdOrthogonal.setSeriesDefinitionIndex(0); sdt.getOrthogonalSampleData().add( sdOrthogonal ); newChart.setSampleData(sdt); // Create the category series. Series seCategory = SeriesImpl.create(); // Set the data value for X-Series. Query query = QueryImpl.create( "row[\"CATEGORY\"]" ); seCategory.getDataDefinition().add( query ); // Create the primary data set LineSeries ls1 = ( LineSeries ) LineSeriesImpl.create(); ls1.setSeriesIdentifier( "Q1" ); // Set the data value for Y-Series 1. Query query1 = QueryImpl.create( "row[\"VALUE1\"]/1000" ); ls1.getDataDefinition().add( query1 ); ls1.getLineAttributes().setColor(ColorDefinitionImpl.RED()); for ( int i = 0; i < ls1.getMarkers( ).size( ); i++ ) { ( ls1.getMarkers( ).get( i ) ).setType( MarkerType.TRIANGLE_LITERAL ); } ls1.getLabel().setVisible( true ); LineSeries ls2 = (LineSeries) LineSeriesImpl.create( ); ls2.setSeriesIdentifier( "Q2" ); // Set the data value for Y-Series 2. Query query2 = QueryImpl.create( "row[\"VALUE2\"]" ); ls2.getDataDefinition().add( query2 ); ls2.getLineAttributes().setColor( ColorDefinitionImpl.YELLOW() ); for ( int i = 0; i < ls2.getMarkers( ).size( ); i++ ) { ( ls2.getMarkers( ).get( i ) ).setType( MarkerType.CIRCLE_LITERAL ); } ls2.getLabel().setVisible( true );
Chapter 6, Programming using the BIRT charting API 151 SeriesDefinition sdX = SeriesDefinitionImpl.create(); sdX.getSeriesPalette().shift( 0 ); // Set default grouping. SeriesGrouping grouping = sdX.getGrouping( ); grouping.setEnabled( true ); grouping.setGroupType( DataType.TEXT_LITERAL ); grouping.setGroupingUnit( GroupingUnitType.STRING_LITERAL ); grouping.setGroupingInterval( 0 ); grouping.setAggregateExpression( "Sum" ); //$NON-NLS-1$ xAxisPrimary.getSeriesDefinitions().add( sdX ); sdX.getSeries().add( seCategory ); SeriesDefinition sdY1 = SeriesDefinitionImpl.create(); sdY1.getSeriesPalette().shift( 0 ); sdY1.getSeries().add( ls1 ); yAxisPrimary.getSeriesDefinitions().add( sdY1 ); SeriesDefinition sdY2 = SeriesDefinitionImpl.create(); sdY2.getSeriesPalette().shift( 0 ); sdY2.getSeries().add( ls2 ); yAxisPrimary.getSeriesDefinitions().add( sdY2 ); // Change the aggregation for Y-Series 2. SeriesGrouping groupingY2 = sdY2.getGrouping( ); groupingY2.setEnabled( true ); groupingY2.setAggregateExpression( "Average" );//$NON-NLS-1$ // Get a chart implementation object and set its // chart.instance property ElementFactory ef = dHandle.getElementFactory( ); ExtendedItemHandle extendedItemHandle = ef.newExtendedItem( null, "Chart" ); try{ IReportItem chartItem = extendedItemHandle.getReportItem( ); chartItem.setProperty( "chart.instance", newChart ); } catch( ExtendedElementException e ) { e.printStackTrace( ); } // Get a data set and bind it to the chart. DataSetHandle dataSet = ( DataSetHandle ) dHandle.getDataSets( ).get( 0 ); ComputedColumn col1 = StructureFactory.createComputedColumn( ); col1.setName( "VALUE1" ); col1.setExpression( "dataSetRow[\"QUANTITYORDERED\"]") ;
152 Integrating Applications into BIRT iHub col1.setDataType( DesignChoiceConstants.COLUMN_DATA_TYPE_INTEGER ); ComputedColumn col2 = StructureFactory.createComputedColumn( ); col2.setName( "VALUE2" ); col2.setExpression( "dataSetRow[\"PRICEEACH\"]" ); col2.setDataType( DesignChoiceConstants.COLUMN_DATA_TYPE_FLOAT ); ComputedColumn col3 = StructureFactory.createComputedColumn( ); col3.setName( "CATEGORY" ); col3.setExpression( "dataSetRow[\"PRODUCTLINE\"]"); col3.setDataType( DesignChoiceConstants.COLUMN_DATA_TYPE_STRING ); try { extendedItemHandle.setDataSet( dataSet ); extendedItemHandle.addColumnBinding(col1, true); extendedItemHandle.addColumnBinding(col2, true); extendedItemHandle.addColumnBinding(col3, true); extendedItemHandle.setHeight( "250pt" ); extendedItemHandle.setWidth( "400pt" ); } catch ( SemanticException e ) { e.printStackTrace( ); } // Add the chart to the report design ListHandle li = (ListHandle) dHandle.getBody( ) .getContents( ).get( 0 ); try { li.getFooter( ).add( extendedItemHandle ); } catch ( ContentException e3 ) { e3.printStackTrace( ); } catch ( NameException e3 ) { e3.printStackTrace( ); } // Save the report design that now contains a chart try { dHandle.saveAs( newDesignName ); } catch ( IOException e ) { e.printStackTrace( ); } dHandle.close( ); Platform.shutdown( ); System.out.println( "Finished" ); } }
Chapter 6, Programming using the BIRT charting API 153 Using the BIRT charting API in a Java Swing application The BIRT charting API does not rely on the BIRT design engine or the BIRT report engine, nor does it process a BIRT report design file. You can use the BIRT charting API to generate a chart in any Java application. The program shown in Listing 6-24 uses the BIRT charting API to build a chart in a Java Swing application. Listing 6-24 Java Swing charting application
import java.awt.BorderLayout; import java.awt.Container; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Toolkit; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.util.HashMap; import java.util.Map; import javax.swing.JFrame; import javax.swing.JPanel; import org.eclipse.birt.chart.api.ChartEngine; import org.eclipse.birt.chart.device.IDeviceRenderer; import org.eclipse.birt.chart.device.IUpdateNotifier; import org.eclipse.birt.chart.exception.ChartException; import org.eclipse.birt.chart.factory.GeneratedChartState; import org.eclipse.birt.chart.factory.Generator; import org.eclipse.birt.chart.model.Chart; import org.eclipse.birt.chart.model.ChartWithAxes; import org.eclipse.birt.chart.model.attribute.AxisType; import org.eclipse.birt.chart.model.attribute.Bounds; import org.eclipse.birt.chart.model.attribute.IntersectionType; import org.eclipse.birt.chart.model.attribute.LegendItemType; import org.eclipse.birt.chart.model.attribute.Position; import org.eclipse.birt.chart.model.attribute.TickStyle; import org.eclipse.birt.chart.model.attribute.impl.BoundsImpl; import org.eclipse.birt.chart.model.attribute.impl
154 Integrating Applications into BIRT iHub .ColorDefinitionImpl; import org.eclipse.birt.chart.model.component.Axis; import org.eclipse.birt.chart.model.component.Series; import org.eclipse.birt.chart.model.component.impl.SeriesImpl; import org.eclipse.birt.chart.model.data.NumberDataSet; import org.eclipse.birt.chart.model.data.SeriesDefinition; import org.eclipse.birt.chart.model.data.TextDataSet; import org.eclipse.birt.chart.model.data.impl.NumberDataSetImpl; import org.eclipse.birt.chart.model.data.impl .SeriesDefinitionImpl; import org.eclipse.birt.chart.model.data.impl.TextDataSetImpl; import org.eclipse.birt.chart.model.impl.ChartWithAxesImpl; import org.eclipse.birt.chart.model.layout.Legend; import org.eclipse.birt.chart.model.layout.Plot; import org.eclipse.birt.chart.model.type.BarSeries; import org.eclipse.birt.chart.model.type.impl.BarSeriesImpl; import org.eclipse.birt.core.framework.PlatformConfig; /* * The selector of charts in Swing JPanel. */ public final class SwingChartingApp extends JPanel implements IUpdateNotifier, ComponentListener { private static final long serialVersionUID = 1L; private boolean bNeedsGeneration = true; private GeneratedChartState gcs = null; private Chart cm = null; private IDeviceRenderer idr = null; private Map contextMap; /* * Create the layout with a container for displaying a chart */ public static void main( String[ ] args ) { SwingChartingApp scv = new SwingChartingApp( ); JFrame jf = new JFrame( ); jf.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE ); jf.addComponentListener( scv ); Container co = jf.getContentPane( );
Chapter 6, Programming using the BIRT charting API 155 co.setLayout( new BorderLayout( ) ); co.add( scv, BorderLayout.CENTER ); Dimension dScreen = Toolkit.getDefaultToolkit( ) .getScreenSize( ); Dimension dApp = new Dimension( 800, 600 ); jf.setSize( dApp ); jf.setLocation( ( dScreen.width - dApp.width ) / 2, ( dScreen.height - dApp.height ) / 2 ); jf.setTitle( scv.getClass( ).getName( ) + " [device=" + scv.idr.getClass( ).getName( ) + "]" );//$NON-NLS-1$ jf.setVisible( true ); } /* * Connect with a SWING device to render the graphics. */ SwingChartingApp( ) { contextMap = new HashMap( ); try { PlatformConfig config = new PlatformConfig( ); config.setProperty( "STANDALONE", "true" ); //$NON-NLS-1$ //$NON-NLS-2$ idr = ChartEngine.instance( config ).getRenderer( "dv.SWING" );//$NON-NLS-1$ } catch ( ChartException ex ) { ex.printStackTrace( ); } cm = createBarChart( ); } /* Build a simple bar chart */ public static final Chart createBarChart( ) { ChartWithAxes cwaBar = ChartWithAxesImpl.create( ); /* Plot */ cwaBar.getBlock( ) .setBackground( ColorDefinitionImpl.WHITE( ) ); cwaBar.getBlock( ).getOutline( ).setVisible( true ); Plot p = cwaBar.getPlot( ); p.getClientArea( ).setBackground( ColorDefinitionImpl.create( 255, 255, 225 ) ); p.getOutline( ).setVisible( false ); /* Title */
156 Integrating Applications into BIRT iHub cwaBar.getTitle( ).getLabel( ).getCaption( ) .setValue( "Bar Chart" ); /* Legend */ Legend lg = cwaBar.getLegend( ); lg.getText( ).getFont( ).setSize( 16 ); lg.setItemType( LegendItemType.CATEGORIES_LITERAL ); /* X-Axis */ Axis xAxisPrimary = cwaBar.getPrimaryBaseAxes( )[0]; xAxisPrimary.setType( AxisType.TEXT_LITERAL ); xAxisPrimary.getMajorGrid( ) .setTickStyle( TickStyle.BELOW_LITERAL ); xAxisPrimary.getOrigin( ) .setType( IntersectionType.VALUE_LITERAL ); xAxisPrimary.getTitle( ).setVisible( true ); /* Y-Axis */ Axis yAxisPrimary = cwaBar .getPrimaryOrthogonalAxis( xAxisPrimary ); yAxisPrimary.getMajorGrid( ) .setTickStyle( TickStyle.LEFT_LITERAL ); yAxisPrimary.setType( AxisType.LINEAR_LITERAL ); yAxisPrimary.getLabel( ).getCaption( ).getFont( ) .setRotation( 90 ); /* Data Sets */ TextDataSet categoryValues = TextDataSetImpl .create( new String[]{ "Item 1", "Item 2", "Item 3"} ); NumberDataSet orthoValues = NumberDataSetImpl .create( new double[]{ 25, 35, 15 } ); /* X-Series */ Series seCategory = SeriesImpl.create( ); seCategory.setDataSet( categoryValues ); SeriesDefinition sdX = SeriesDefinitionImpl.create( ); sdX.getSeriesPalette( ).shift( 0 ); xAxisPrimary.getSeriesDefinitions( ).add( sdX ); sdX.getSeries( ).add( seCategory ); /* Y-Series */ BarSeries bs = (BarSeries) BarSeriesImpl.create( ); bs.setDataSet( orthoValues ); bs.setRiserOutline( null ); bs.getLabel( ).setVisible( true ); bs.setLabelPosition( Position.INSIDE_LITERAL ); SeriesDefinition sdY = SeriesDefinitionImpl.create( ); yAxisPrimary.getSeriesDefinitions( ).add( sdY );
Chapter 6, Programming using the BIRT charting API 157 sdY.getSeries( ).add( bs ); return cwaBar; } public void regenerateChart( ) { bNeedsGeneration = true; repaint( ); } public void repaintChart( ) { repaint( ); } public Object peerInstance( ) { return this; } public Chart getDesignTimeModel( ) { return cm; } public Object getContext( Object key ) { return contextMap.get( key ); } public Object putContext( Object key, Object value ) { return contextMap.put( key, value ); } public Object removeContext( Object key ) { return contextMap.remove( key ); } public Chart getRunTimeModel( ) { return gcs.getChartModel( ); } public void paint( Graphics g ) { super.paint( g ); Graphics2D g2d = (Graphics2D) g; idr.setProperty( IDeviceRenderer.GRAPHICS_CONTEXT, g2d ); idr.setProperty( IDeviceRenderer.UPDATE_NOTIFIER, this );
158 Integrating Applications into BIRT iHub Dimension d = getSize( ); Bounds bo = BoundsImpl.create( 0, 0, d.width, d.height ); bo.scale( 72d / idr.getDisplayServer( ).getDpiResolution()); Generator gr = Generator.instance( ); if ( bNeedsGeneration ) { bNeedsGeneration = false; try { gcs = gr.build( idr.getDisplayServer( ), cm, bo, null, null, null ); } catch ( ChartException ex ) { System.out.println( ex ); } } try { gr.render( idr, gcs ); } catch ( ChartException ex ) { System.out.println( ex ); } } public void componentHidden( ComponentEvent e ) { } public void componentMoved( ComponentEvent e ) { } public void componentResized( ComponentEvent e ) { bNeedsGeneration = true; } public void componentShown( ComponentEvent e ) { } }
Chart programming examples The org.eclipse.birt.chart.examples plug-in is a collection of chart programming examples provided in the ChartSDK folder of the chart engine. To access the Java source code of the examples, extract the org.eclipse.birt.chart.examples.source plug-in’s JAR file to your workspace. Then, import those files as a project. Include the JAR files and the Java EE JAR file, servlet.jar, in the build path. Add further JAR files from the chart engine’s ChartSDK and Eclipse home plugins folders as necessary to resolve build errors in individual examples. To run the examples, use a Java application run configuration.
Chapter 6, Programming using the BIRT charting API 159 The examples are located in subdirectories of the plug-in’s src/org/eclipse /birt/chart/examples directory, called EXAMPLES_ROOT. Most of the examples consist of a Java application that displays a chart. The application classes, which have a main( ) method, are called viewer applications and their class names end in Viewer. Typically, these examples use one or more additional classes to build the chart. The following sections provide brief summaries of the examples in the chart examples plug-in. api.data examples The api.data package contains three examples, one that displays charts in a Java Swing environment and two that modify chart items in a report design.
DataCharts example The DataCharts example consists of DataChartsViewer, a Java Swing application that uses the DataCharts class to build a chart. DataCharts displays hard-coded data values in the charts. Depending on user selection, the application builds one of the following kinds of charts: ■ A bar chart that has multiple y-axes ■ A bar chart that has multiple y-series ■ A pie chart that has a minimum slice
GroupOnXSeries example The GroupOnXSeries example is a Java application that reads a BIRT report design and modifies and saves it. The original report design, NonGroupOnXSeries.rptdesign, contains a chart report item that uses data from a scripted data source. The chart item has no grouping on the x-series. The GroupOnXSeries Java application modifies the design so that the chart report item does group on the x-series. The application saves the modified report design as GroupOnXSeries.rptdesign. Open these report designs and preview the reports to see the effect of this modification.
GroupOnYAxis example The GroupOnYAxis example is a Java application that reads a BIRT report design and modifies and saves it. The original report design, NonGroupOnYAxis.rptdesign, contains a chart report item that uses data from a scripted data source. The chart item has no grouping on the y-axis. The GroupOnYAxis Java application modifies the design so that the chart report item does group on the y-axis. The application saves the modified BIRT report design as GroupOnYAxis.rptdesign. Open these report designs and preview the reports to see the effect of this modification.
160 Integrating Applications into BIRT iHub api.data.autobinding example This example is an Eclipse SWT application that consists of the AutoDataBindingViewer class. This class instantiates an SWT Display object and adds a chart to it. The application creates data row structures, which it binds to the chart. Then, the application renders the chart. api.format example This example is a Java Swing application that consists of the FormatCharts and FormatChartsViewer Java classes. The FormatChartsViewer class displays an interface that presents choices to the user. Based on the user choice, FormatChartsViewer calls static methods in the FormatCharts class to build a chart. FormatChartsViewer then renders the chart. The methods in FormatCharts modify the following chart properties: ■ Axis format ■ Colored by category ■ Legend title ■ Percentage value ■ Plot format ■ Series format api.interactivity examples This set of related example applications demonstrate chart interactivity features in the three Java frameworks: SVG, Swing, and SWT. The viewer applications are SvgInteractivityViewer, SwingInteractivityViewer, and SwtInteractivityViewer. The viewer classes display an interface that presents the same interactivity choices to the user. Based on the choice, the viewer class calls static methods in InteractivityCharts to build an interactive chart. Then, the viewer renders the chart. The interactivity types in these charts are: ■ Displaying tooltips ■ Executing call-back code ■ Highlighting a series ■ Linking to an external site by using a URL ■ Toggling the visibility of a series api.pdf example This example is a Java application that builds a simple chart and renders it as a PDF file. The classes in the PDFChartGenerator example are ChartModels and
Chapter 6, Programming using the BIRT charting API 161 PDFChartGenerator. ChartModels has a single method that builds a simple chart using hard-coded data values. PDFChartGenerator uses the BIRT charting API to render the chart into PDF format. The application saves the PDF file as test.pdf. api.preference example This example shows how a Java servlet can process URL parameters to set style preferences for a chart. The servlet class, PreferenceServlet, uses the ChartModels class to generate a chart. The servlet uses the style parameters in the LabelStyleProcessor class to affect the style of a label in the chart. The example also includes a help page, Help.htm, that explains how to: ■ Develop chart pages using JSPs and servlets. ■ Run the Preference example. ■ Set up Eclipse to work with Tomcat. api.processor example This example builds a simple chart and applies styles to text in the chart. The example consists of StyleChartViewer, an SWT application, and StyleProcessor, which implements the IStyleProcessor interface to create a style object. StyleChartViewer creates a chart and applies the style to text in the chart. Finally, StyleChartViewer renders the chart. api.script examples This example consists of two SWT applications, JavaScriptViewer and JavaViewer. Both applications present the same set of choices to the user. The appearance of the chart that appears for a particular user choice is the same for both viewers. Each choice calls a static method in the ScriptCharts class to create a chart and displays the event handlers that the chart implements. JavaScriptViewer calls ScriptCharts methods to build charts that have JavaScript event handlers. JavaViewer calls ScriptCharts methods to build charts that have Java event handlers. The ScriptCharts class illustrates techniques for creating charts having report element event handlers. Methods in this class create charts having report element event handlers written in JavaScript. Each JavaScript event handler is defined as a single string in ScriptCharts. A further set of methods creates charts having the same functionality using report element event handlers written in Java. The Java event handlers are Java classes that are located in EXAMPLES_ROOT/api /script/java. The ScriptCharts methods that define a Java event handler pass a string containing the path of the Java class.
162 Integrating Applications into BIRT iHub api.viewer examples The api.viewer package contains example applications that create a wide variety of charts. Each class creates and displays a set of charts based on user choices. Each viewer class, except SwingLiveChartViewer.java, calls static methods in the PrimitiveCharts class to create the chart to display. PrimitiveCharts uses hard-coded data values for each chart.
Chart3DViewer example Chart3DViewer.java is an SWT application that displays the following chart types: ■ 3D area chart ■ 3D bar chart ■ 3D line chart
CurveFittingViewer example CurveFittingViewer.java is an SWT application that displays the following chart types: ■ Curve fitting area chart ■ Curve fitting bar chart ■ Curve fitting line chart ■ Curve fitting stock chart
DialChartViewer example DialChartViewer.java is an SWT application that displays the following chart types: ■ Multiple-dial, multiple-region chart ■ Multiple-dial, single-region chart ■ Single-dial, multiple-region chart ■ Single-dial, single-region chart
SwingChartViewerSelector example SwingChartViewerSelector.java is a Swing application that supports showing the same data values in different ways. For each chart type, the user can choose to show the chart as two-dimensional or two-dimensional with depth. The user can also choose to display the chart with axes transposed, with the values shown as percentages, or on a logarithmic scale. Some choices are available only for charts with axes. SwingChartViewerSelector displays the following chart types:
Chapter 6, Programming using the BIRT charting API 163 ■ Area chart ■ Bar and line stacked chart ■ Bar chart ■ Bar chart that has two series ■ Bubble chart ■ Difference chart ■ Line chart ■ Pie chart ■ Pie chart that has four series ■ Scatter chart ■ Stock chart
SwingLiveChartViewer example SwingChartLiveChartViewer.java is a Swing application that displays a live, animated chart with scrolling data. SWTChartViewerSelector example SWTChartViewerSelector.java is an SWT application that displays the same user interface choices and chart types as SwingChartViewerSelector.java. builder example The builder example consists of two Java classes, ChartWizardLauncher and DefaultDataServiceProviderImpl. ChartWizardLauncher attempts to read a chart from testCharts.chart. If the file exists, ChartWizardLauncher modifies that file. If the file does not exist, the application creates a new file. ChartWizardLauncher uses the BIRT chart wizard to create the chart. DefaultDataServiceProviderImpl provides a basic implementation of a simulated data service. radar.ui example The radar.ui example consists of the classes that provide the user interface pages for the radar chart. report.api examples The three report.api examples are all Java applications that have no user interface. These examples use the BIRT design engine to build a new BIRT report design file
164 Integrating Applications into BIRT iHub in the chart example plug-in’s output folder. All the report examples add the following components to the report design file in the order shown: ■ Master page ■ Data source ■ Data set ■ A chart element in the body of the report All the report examples use the BIRT charting API to add a chart to the body slot of the report design. After running these applications, open the new report design file and preview the report to see the chart.
MeterChartExample example The MeterChartExample example adds a meter chart to the report design. The name of the report design is MeterChartExample.rptdesign.
SalesReport example The SalesReport example creates styles and adds a pie chart to the report design. The name of the report design is SalesReport.rptdesign. StockReport example The StockReport example adds a stock chart to the report design. The name of the report design is StockAnalysis.rptdesign. report.design examples The report designs in this folder demonstrate ways to display chart elements in a report design. BarChartWithinTableGroup.rptdesign shows how to use a chart in a table element. BarChartWithJavascript.rptdesign shows how to use JavaScript to modify the rendered chart when a user views the report. DynamicSeriesPieChart.rptdesign shows how to customize a pie chart. report.design.script examples The report designs in this folder contain chart elements that use the same JavaScript event handlers that the api.script examples create dynamically. These report designs show how the scripts appear in BIRT Report Designer. view example The view folder and its subfolders include the content for the Eclipse view, Chart Examples. To open this view, from the Eclipse main menu, choose Window➛Show View➛Other. On Show View, expand Report and Chart Design, then select Chart Examples and choose OK. By default, the Chart Examples view
Chapter 6, Programming using the BIRT charting API 165 appears below the main window, in the same position as the console window. To use the Chart Examples view, expand a node on the left of the view, then select an item. The selected chart appears on the right of the view, as shown in Figure 6-1.
Figure 6-1 Chart Examples view showing the percentage value format example To view the source code of the application that generates the selected chart, choose Open Java Source from the toolbar. To save the XML of the chart item structure, choose Save XML Source from the toolbar.
166 Integrating Applications into BIRT iHub Part Two 2
Part 2Using Actuate BIRT APIs
■ Using Actuate APIs to access iHub environment information ■ Using the BIRT data object API
Chapter 7
Chapter 7Using Actuate APIs to access iHub environment information
This chapter contains the following topics: ■ Writing event handlers to retrieve iHub environment information ■ Debugging event handlers that use the iHub API ■ iHub API reference
Chapter 7, Using Actuate APIs to access iHub environment information 169 Writing event handlers to retrieve iHub environment information Report developers distribute reports to users by publishing them to BIRT iHub. Sometimes a report requires information about the iHub environment to implement application or business logic based on, for example, the security credentials of the user running the report, the browser in which the report is viewed, the server volume on which the report is run, and so on. BIRT provides an API, referred to in this chapter as the iHub API, that enables access to this type of information. To use the iHub API in a report, you write event handler scripts in either Java or JavaScript. BIRT event handlers are associated with all the elements that make up a report, such as data sources, data sets, tables, charts, and labels. When a report is run, BIRT fires events and executes event handlers in a specific sequence to generate and render the report. Writing event handlers in a report requires knowledge of the BIRT event model. For information about the event model and details about writing event handlers in Java and JavaScript, see Integrating and Extending BIRT. This chapter describes the additional requirements for accessing and debugging the iHub API in an event handler. Writing a JavaScript event handler You write a JavaScript event handler that uses the iHub API the same way you write other event handlers. In Actuate BIRT Designer Professional, you select an element, such as the report design or a table, then use the script editor to select an event, such as beforeFactory or onCreate, for which to write an event handler. Figure 7-1 shows the script editor displaying event-handling code written for the report design’s beforeFactory event.
Figure 7-1 Event-handling code in the script editor
Writing a Java event handler Writing a Java event handler that uses the iHub API is similar to writing other types of event handlers. You create a Java event handler class, make the class
170 Integrating Applications into BIRT iHub available to BIRT, and associate the class with a report element. The difference is the additional JAR files required to access the iHub API. You must add the following JAR files in the build path and classpath when configuring the Java event handler project: ■ $ACTUATE_HOME\modules\BIRTiHub\iHub\Jar\BIRT\lib\scriptapi.jar This JAR file provides the event handler classes and access to the reportContext object. If you use the ULocale methods, com.ibm.icu_version.jar is also required. $ACTUATE_HOME is the location where iHub is installed. ■ $ACTUATE_HOME\modules\BIRTiHub\iHub\reportengines\lib\jrem.jar This JAR file contains the definitions of the classes and methods in the iHub API. Figure 7-2 shows the build path of a Java project that uses the iHub API. In this example, BIRT Designer Professional is installed on the same machine where iHub is installed. If Actuate BIRT Designer Professional is installed on a different machine, you must copy the JAR files from the iHub machine to your workspace.
Figure 7-2 Build path of a Java project that uses the iHub API
About the serverContext object The BIRT engine uses an object called serverContext to store information about the iHub environment. The serverContext methods and properties are defined in the IServerContext interface. The container for the serverContext object is the application context object appContext. The appContext object stores objects and values that are used in all phases of report generation and presentation.
Chapter 7, Using Actuate APIs to access iHub environment information 171 The appContext object, in turn, is a property of the reportContext object. This object stores information associated with the instance of the report that is being generated or viewed. For example, the reportContext object stores information about report parameters, global variables, report output format, locale, the request that runs the report, and the application context. The report context class defines methods for setting and retrieving these properties. Every event handler in a BIRT report has access to the reportContext object. In Java, the report context object is an argument to all event-handler methods. To call a method to retrieve iHub environment information, the code must reflect the relationships between the serverContext, appContext, and reportContext objects. The following JavaScript code snippet shows how to call the getVolumeName( ) method to retrieve the name of the iHub volume in which a report runs: reportContext.getAppContext().get("ServerContext").getVolumeName() The following example shows the equivalent code snippet in Java: IServerContext scontext; scontext = (IServerContext) reportContext.getAppContext().get("ServerContext"); scontext.getVolumeName();
JavaScript event handler example The code example in Listing 7-1 uses the getUserRoles( ) method to retrieve the user’s roles and displays the contents of a report element if the user role is Manager. This code can be used, for example, in the onPrepare event of a table element to hide or display the table depending on the user role. The code example also uses the appendToJobStatus( ) method to write messages about the user’s roles to the server job status. Listing 7-1 JavaScript event handler
userRoles = reportContext.getAppContext().get("ServerContext") .getUserRoles();
reportContext.getAppContext().get("ServerContext") .appendToJobStatus("The user roles are:" + userRoles +"\n");
if (userRoles != null) { for (i = 0; i < userRoles.size(); i++) { if ( userRoles.get(i) == "Manager") { reportContext.setGlobalVariable("HideDetails", "false");
172 Integrating Applications into BIRT iHub reportContext.getAppContext().get("ServerContext") .appendToJobStatus("The user has a Manager role\n"); break; } } }
Java event handler example Like the JavaScript event handler in the previous section, the Java code example in Listing 7-2 uses the getUserRoles( ) method to retrieve the user’s roles and displays the contents of a table if the user role is Manager. The TableEH class extends the TableEventAdapter class and implements the event-handler script in the onPrepare event method. Listing 7-2 Java event handler class
package server.api.eh; import java.util.List; import org.eclipse.birt.report.engine.api.script.IReportContext; import org.eclipse.birt.report.engine.api.script.element.ITable; import org.eclipse.birt.report.engine.api.script.eventadapter .TableEventAdapter; import com.actuate.reportapi.engine.IServerContext; public class TableEH extends TableEventAdapter { public void onPrepare(ITable tbl, IReportContext reportContext) { IServerContext scontext; scontext = (IServerContext) reportContext.getAppContext().get("ServerContext"); List
Chapter 7, Using Actuate APIs to access iHub environment information 173 Debugging event handlers that use the iHub API A report that uses the iHub API returns the expected results only when it is run on iHub. When the report is run in Actuate BIRT Designer Professional, the report cannot access the iHub to retrieve the server information, and the report typically returns null values. Therefore, you cannot debug the iHub API calls in the same way you debug other event handlers in Actuate BIRT Designer Professional. To debug iHub API calls, use the appendToJobStatus( ) method to write a debugging message for each event handler. For example, in a JavaScript event handler for the beforeFactory event, add the following line of debugging code: reportContext.getAppContext().get("ServerContext") .appendToJobStatus("Debugging: beforeFactory called.\n"); In a Java event handler, write: IServerContext scontext; scontext = (IServerContext) reportContext.getAppContext().get("ServerContext"); scontext.appendToJobStatus("Debugging: beforeFactory called.\n"); The appendToJobStatus( ) method writes a specified string message in the status section of a job-completion notice. After running the report on iHub, you can view these messages in iHub client. In iHub client, choose My Jobs➛Completed, then choose the job’s details. The job’s Status page displays the debug messages in the Status section, as shown in Figure 7-3.
Figure 7-3 Debug message in the job status page in iHub client
174 Integrating Applications into BIRT iHub appendToJobStatus( ) iHub API reference This section lists all the methods in the iHub API in alphabetical order. Each method entry includes a general description of the method, the JavaScript and Java syntaxes, the result the method returns, and examples. appendToJobStatus( ) Appends a specified string to the status of the current job. iHub writes status messages for each report-generation job. JavaScript appendToJobStatus(statusString) syntax Java public void appendToJobStatus( String statusString ) syntax Argument statusString The string to add to the job status. Usage Provide information for debugging purposes. For example, to verify that an event handler is executed, write a message indicating that the event method is called. JavaScript reportContext.getAppContext().get("ServerContext") example .appendToJobStatus("This message appears when beforeFactory is called.\n"); Java IServerContext scontext; example scontext = (IServerContext) reportContext.getAppContext().get("ServerContext"); scontext.appendToJobStatus("This message appears when beforeFactory is called.\n"); getAuthenticationId( ) Retrieves the current user’s authentication ID. JavaScript getAuthenticationId( ) syntax Java public String getAuthenticationId( ) syntax Usage Use in cases when the report application needs to pass the ID to another application, such as IDAPI calls to iHub. Returns An authentication ID in String format.
Chapter 7, Using Actuate APIs to access iHub environment information 175 getServerWorkingDirectory( )
JavaScript reportContext.getAppContext().get("ServerContext") example .getAuthenticationId(); Java IServerContext scontext; example scontext = (IServerContext) reportContext.getAppContext().get("ServerContext"); scontext.getAuthenticationId(); getServerWorkingDirectory( ) Retrieves the path to the folder in the file system where temporary files are stored. JavaScript getServerWorkingDirectory( ) syntax Java public String getServerWorkingDirectory( ) syntax Usage Use to read or write information from and to the file system. Returns The full path to the iHub working directory. JavaScript reportContext.getAppContext().get("ServerContext") example .getServerWorkingDirectory(); Java IServerContext scontext; example scontext = (IServerContext) reportContext.getAppContext().get("ServerContext"); scontext.getServerWorkingDirectory(); getUserName( ) Retrieves the current user name. JavaScript getUserName( ) syntax Java public String getUserName( ) syntax Usage Use in cases when an application requires different code for different users. Returns The current user name. JavaScript reportContext.getAppContext().getUserName() example Java IServerContext scontext; example scontext = (IServerContext) reportContext.getAppContext().get("ServerContext"); String currentUser = scontext.getUserName();
176 Integrating Applications into BIRT iHub getUserAgentString( ) getUserAgentString( ) Identifies the browser used to view a report. JavaScript getUserAgentString( ) syntax Java public String getUserAgentString( ) syntax Usage Use in cases when an application requires different code for different browsers. The browser information is available only when the report is rendered, so use getUserAgentString( ) in a report element’s onRender event. Returns The browser type in String format. For Internet Explorer, for example, getUserAgentString( ) might return a string, such as: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; InfoPath.1; MS-RTC LM 8)
JavaScript reportContext.getAppContext().get("ServerContext") example .getUserAgentString(); Java IServerContext scontext; example scontext = (IServerContext) reportContext.getAppContext().get("ServerContext"); scontext.getUserAgentString(); getUserRoles( ) Retrieves the roles assigned to the current user. JavaScript getUserRoles( ) syntax Java public List
Chapter 7, Using Actuate APIs to access iHub environment information 177 getVolumeName( ) getVolumeName( ) Retrieves the name of the iHub volume on which the report runs. JavaScript getVolumeName( ) syntax Java public String getVolumeName( ) syntax Usage Use in cases when an application running in a multivolume environment requires volume information. Returns The name of the iHub volume running a report. JavaScript reportContext.getAppContext().get("ServerContext") example .getVolumeName(); Java IServerContext scontext; example scontext = (IServerContext) reportContext.getAppContext().get("ServerContext"); scontext.getVolumeName(); setHeadline( ) Sets the headline of a generated report. A headline appears in a job completion notice that iHub writes to a channel. JavaScript setHeadline(headline) syntax Java public void setHeadline( String headline ) syntax Argument headline A string that represents the headline of a completed job. Usage Use to specify a headline based on the contents of a report, or on the value of a report parameter. JavaScript reportContext.getAppContext().get("ServerContext") example .setHeadline("Sales Report for " + params["Region"].value); Java String region = (String)reportContext.getParameterValue("Region") example IServerContext scontext; scontext = (IServerContext) reportContext.getAppContext().get("ServerContext"); scontext.setHeadline("Sales Report for " + region);
178 Integrating Applications into BIRT iHub setVersionName( ) setVersionName( ) Sets the version name of a generated report. JavaScript setVersionName(versionName) syntax Java public void setVersionName( String versionName ) syntax Argument versionName A string that represents the report’s version name. Usage Use to specify a version name that includes dynamic data, such as the contents of a report, the value of a report parameter, or the report-generation date. JavaScript reportContext.getAppContext().get("ServerContext") example .setVersionName("Version " + new Date()); Java IServerContext scontext; example scontext = (IServerContext) reportContext.getAppContext().get("ServerContext"); scontext.setVersionName("Version " + new Date());
Chapter 7, Using Actuate APIs to access iHub environment information 179 setVersionName( )
180 Integrating Applications into BIRT iHub Chapter 8
Chapter 8Using the BIRT data object API
This chapter contains the following topics: ■ Generating data object elements for BIRT report designs ■ Creating a data element using the Design Engine API BIRT iHub provides a Design Engine API extension to create and alter data objects programmatically with Java, allowing programs to refresh their data from the database as needed. This mechanism can retrieve data based on user controls at run time, such as the availability or status of certain goods and services, or generate content dynamically according to criterion outside of a usual query, such as a network outage or an escrow account closing. In this way, an application can respond to important events and incorporate any outside factors, with or without the direct involvement of any users. This Actuate extension provides Java classes to automate data object generation, retrieving important information required regularly for any application. The classes that support BIRT data objects, DataMartCubeHandle, DataMartDataSetHandle, and DataMartDataSourceHandle, are contained in the com.actuate.birt.report.model.api package. Like the BIRT data objects implemented in the BIRT data explorer, BIRT data objects generated by the Design Engine API generate data sources and data sets from a .datadesign or .data file. Using the extension requires programming in Java. Knowledge of XML is also helpful. Handling data objects for BIRT reports requires knowledge of programming using the BIRT reporting API and the report object model. For information about the BIRT reporting API and the report object model, see Integrating and Extending
Chapter 8, Using the BIRT data object API 181 BIRT. This chapter describes the additional requirements for generating data objects for reports.
Generating data object elements for BIRT report designs To generate data object data sources, data sets, and cubes for a BIRT report design, first configure BIRT_HOME to access the Actuate commercial model API Java archive (JAR) files from Actuate iHub. To accomplish this task, generate a DesignConfig object with a custom BIRT_HOME path, as shown in the following code: // Create an DesignConfig object. DesignConfig config = new DesignConfig( ); // Set up the path to your BIRT Home Directory. config.setBIRTHome("C:\Actuate3\BIRTiHubVisualization\modules\ BIRTiHub\iHub\Jar\BIRT\platform"); Use the path to the iHub installation specific to your system. Using this design configuration object, create and configure a Design Engine object, open a new session, and generate or open a report design object, as shown in the following code: // Create the engine. DesignEngine engine = new DesignEngine( config ); SessionHandle sessionHandle = engine.newSessionHandle( ULocale.ENGLISH ); ReportDesignHandle designHandle = sessionHandle.createDesign( ); These objects are contained in the model API package org.eclipse.birt.report.model.api. The ElementFactory class supports access to all the elements in a report. The following code generates an Element Factory object: ElementFactory factory = designHandle.getElementFactory( ); To generate data sources, data sets, and cubes, use the datamart methods of an ElementFactory object: newDataMartCube( ) for a new cube, newDataMartDataSet( ) for a data set, and newDataMartSource( ) for a new data source. For example, to instantiate a new data source, use the following code: DataMartDataSourceHandle dataSource = factory.newDataMartDataSource("Data Object Data Source"); Associate a handle for a data object data source with an actual data source from the contents of a data or data design file. For example, to associate a data source handle with a data source from test.datadesign, use the following code:
182 Integrating Applications into BIRT iHub dataSource.setDataMartURL( "test" ); dataSource.setAccessType( DesignChoiceConstants.ACCESS_TYPE_TRANSIENT ); Finally, add the data element to the report design, as shown in the following code: designHandle.getDataSources( ).add( dataSource ); To complete the data source assignment, output the report design into a file and close the design handle object, using code similar to the following: FileOutputStream fos = new FileOutputStream( "output.rptdesign" ); designHandle.serialize( fos ); // Close the document. fos.close( ); designHandle.close( ); The resulting output file, output.rptdesign, contains the new data source, retrieved from test.datadesign. This data source appears in Data Sources in Data Explorer and establishes a link to the .datadesign file, test.datadesign. The XML source for output.rptdesign includes markup similar to the following lines:
Chapter 8, Using the BIRT data object API 183 Finally, add the data element to the report design, as shown in the following code: designHandle.getDataSets( ).add( dataSet );
Creating data object data cubes for BIRT report designs To create a data object data cube, use the newDataMartDataCube( ) method from ElementFactory. For example, to instantiate a new data cube, use the following code: DataMartDataCubeHandle dataCube = factory.newDataMartDataCube("Data Cube"); Associate the data object data cube with a DataMartDataSourceHandle object and assign a data cube from the data or data design file. For example, to access a data cube called "CubeName", use the following code: dataCube.setDataSource( dataSource.getName( ) ); dataCube.setDataObject("CubeName"); Finally, add the data element to the report design, as shown in the following code: designHandle.getDataCubes( ).add( dataCube );
Tutorial 1: Creating a data element using the Design Engine API This tutorial provides step-by-step instructions for creating a Java class that generates a BIRT report design with a BIRT data source generated from a BIRT data design file. You perform the following tasks: ■ Set up a project. ■ Create a GenerateDataObject Java class. ■ Create the main( ) method to test the code. ■ Run the code. Task 1: Set up a project To compile a Design Engine API application, the design engine Java archive (JAR) files from Actuate iHub must be in your classpath. You can find the design engine JAR files in the
184 Integrating Applications into BIRT iHub 1 In Java perspective, select File➛New➛Project. New Project appears, as shown in Figure 8-1.
Figure 8-1 Creating a new project 2 Expand Java, select Java Project, and choose Next. New Java Project appears, as shown in Figure 8-2.
Chapter 8, Using the BIRT data object API 185 Figure 8-2 Creating the DataObjectExample project 3 In Project Name type: DataObjectExample 4 In Project layout, select: Use project folder as root for sources and class files 5 Choose Next. Java Settings appears. 6 Set the project build path. 1 Select the Libraries tab. 2 Choose Add External JARs. 3 In JAR Selection, navigate to the iHub\Jar\BIRT\lib directory. For the default installation of BIRT on Windows, this directory is: C:\Actuate3\BIRTiHubVisualization\modules\BIRTiHub\iHub\Jar\ BIRT\lib 4 In JAR Selection, select all of the JAR files in the directory. 5 Choose Open. The libraries are added to the classpath as shown in Figure 8-3.
186 Integrating Applications into BIRT iHub Figure 8-3 DataObjectsAPI project build path 6 Choose Finish. 7 Import the data design file. 1 In the Package Explorer, right-click the DataObjectExample project. 2 Choose Import from the context menu. 3 In Import, choose General➛File System and then choose Next. 4 In File System, next to the From Directory field, choose Browse. 5 Navigate to and select a data design file. Then choose Finish. The data design file appears in the project as shown in Figure 8-4.
Figure 8-4 DataObjectExample project showing the data design file Task 2: Create a GenerateDataObject Java class This Java class creates a simple report design, with table, list, and image elements. 1 Choose File➛New➛Class. New Java Class appears.
Chapter 8, Using the BIRT data object API 187 2 In Name type: GenerateDataObject 3 In Package, as shown in Figure 8-5, type: myPackage
Figure 8-5 Creating a GenerateDataObject class 4 Choose Finish. GenerateDataObject.java opens in the Java editor. 5 Add a BIRT_HOME static variable to the class. For the default installation of iHub on a Windows system, use the following line in the body of the GenerateDataObject class body: private static final String BIRT_HOME = "C:\Actuate3\ BIRTiHubVisualization\modules\BIRTiHub\iHub\Jar\BIRT\ platform";
Task 3: Create the main( ) method to test the code Add a main( ) method to run the class. 1 Type the following main method: public static void main( String[] args ) throws Exception{} An error indicating that the BirtException class is not defined appears. 2 Use Quick Fix (Ctrl+1) to import the BirtException class definition.
188 Integrating Applications into BIRT iHub 3 Add the main method body shown in Listing 8-1 to your main( ) method. Listing 8-1 main( ) method code
DesignConfig config = new DesignConfig( ); config.setBIRTHome( BIRT_HOME );
DesignEngine engine = new DesignEngine( config ); SessionHandle sessionHandle = engine.newSessionHandle( ULocale.ENGLISH ); ReportDesignHandle designHandle = sessionHandle.createDesign(); ElementFactory factory = designHandle.getElementFactory( );
DataMartDataSourceHandle dataSource = factory.newDataMartDataSource( "Data Source" ); dataSource.setDataMartURL( "include" ); dataSource.setAccessType( DesignChoiceConstants.ACCESS_TYPE_TRANSIENT ); designHandle.getDataSources( ).add( dataSource );
FileOutputStream fos = new FileOutputStream("test.rptdesign"); designHandle.serialize( fos ); fos.close( );
designHandle.close( ); System.out.println("Done"); Read the code explanations: ■ To access a data source and its contents, the application must first generate and configure a design engine object. ■ After creating the engine object, the code instantiates a new session. The SessionHandle object manages the state of all open data and report designs. Use SessionHandle to open, close, and create data designs, and to set global properties, such as the locale and the units of measure for data elements. Create the session handle only once. BIRT supports only a single SessionHandle. ■ Generate a new design handle using the SessionHandle object. Create a design engine element factory using the DesignHandle object. ■ Create a new instance of DataMartDataSourceHandle and set the datamart URL to the name of a datamart file, include, which corresponds to the include.datadesign file added to the project. Then, configure the access type and add the data source handle to the design handle object. ■ Finally, open a file output stream to a report design, test.rptdesign, that uses the data object. Export the data design element to the report design.
Chapter 8, Using the BIRT data object API 189 4 Add the import statements shown in Listing 8-2 to the beginning of the file. Listing 8-2 import statement code
import java.io.FileOutputStream; import org.eclipse.birt.report.model.api.DesignConfig; import org.eclipse.birt.report.model.api.DesignEngine; import org.eclipse.birt.report.model.api.ElementFactory; import org.eclipse.birt.report.model.api.ReportDesignHandle; import org.eclipse.birt.report.model.api.SessionHandle; import org.eclipse.birt.report.model.api.elements .DesignChoiceConstants; import com.actuate.birt.report.model.api .DataMartDataSourceHandle; import com.ibm.icu.util.ULocale;
Task 4: Run the code 5 Create a Run configuration for GenerateDataObject.java class. 1 In Package Explorer, select: GenerateDataObject.java 2 From the main menu, choose Run➛Run Configurations. 3 Double-click the Java Application link in the left frame of Run Configurations. The GenerateDataObjects configuration gets created. 4 Choose Run. Save and Launch appears. Choose OK. 6 After the execution completes, refresh the contents of the DataObjectExample project. test.rptdesign appears. 7 Open the report design and view the XML source. The XML contains a datamart element that points to include.datadesign and a data source called include, as shown in the following code:
190 Integrating Applications into BIRT iHub Figure 8-6 Data Source in test.rptdesign The final code for GenerateDataObject is shown in Listing 8-3. Listing 8-3 GenerateDataObject.java package myPackage; import java.io.FileOutputStream; import org.eclipse.birt.report.model.api.DesignConfig; import org.eclipse.birt.report.model.api.DesignEngine; import org.eclipse.birt.report.model.api.ElementFactory; import org.eclipse.birt.report.model.api.ReportDesignHandle; import org.eclipse.birt.report.model.api.SessionHandle; import org.eclipse.birt.report.model.api.elements .DesignChoiceConstants; import com.actuate.birt.report.model.api.DataMartDataSourceHandle; import com.ibm.icu.util.ULocale; public class GenerateDataObject {
private static final String BIRT_HOME = "C:/Program Files/BIRTiHubVisualization/modules/BIRTiHub/iHub /Jar/BIRT/platform";
public static void main( String[] args ) throws Exception { DesignConfig config = new DesignConfig( ); config.setBIRTHome( BIRT_HOME ); DesignEngine engine = new DesignEngine( config ); SessionHandle sessionHandle = engine.newSessionHandle( ULocale.ENGLISH ); ReportDesignHandle designHandle = sessionHandle.createDesign(); ElementFactory factory = designHandle.getElementFactory( );
Chapter 8, Using the BIRT data object API 191 DataMartDataSourceHandle dataSource = factory.newDataMartDataSource( "Data Source" ); dataSource.setDataMartURL( "include" ); dataSource.setAccessType( DesignChoiceConstants .ACCESS_TYPE_TRANSIENT ); designHandle.getDataSources( ).add( dataSource );
FileOutputStream fos = new FileOutputStream("test.rptdesign"); designHandle.serialize( fos ); fos.close( );
designHandle.close( ); System.out.println("Done"); } }
192 Integrating Applications into BIRT iHub Part Three 3
Part 3Introduction to the Actuate Information Delivery API
■ Understanding the Information Delivery API and schema ■ Constructing a SOAP message ■ Text string limits in Actuate operations
Chapter 9
Chapter 9Understanding the Information Delivery API and schema
This chapter contains the following topics: ■ About the Actuate Information Delivery API ■ About web services and WSDL ■ Understanding the elements of the iHub WSDL schema ■ Accessing the Actuate schema using a web browser
Chapter 9, Understanding the Information Delivery API and schema 195 About the Actuate Information Delivery API The Actuate Information Delivery API (IDAPI) is a Simple Object Access Protocol (SOAP) message schema that supports integrating and administering BIRT iHub using Extensible Markup Language (XML). Using the Actuate Information Delivery API, developers create applications that perform such tasks as uploading and downloading files, generating a document and scheduling document generation, sending an e-mail notification when a job completes, and accessing external libraries. SOAP is the underlying layer that provides a messaging framework for web services. The IDAPI schema defines the message elements for a well-formed request to BIRT iHub and the format of the response. The Actuate Information Delivery API has the following features:
■ Platform- and language-independent access to Actuate web services Using SOAP messaging, Actuate’s web services integrate into applications developed in Java, Visual Basic, C++, C#, and other programming languages. The SOAP serialization and deserialization framework translates XML messages to the language of the calling application. Deployment of these applications can be across multiple platforms, including UNIX, Windows, or Linux, and integrate with web technologies such as J2EE and Microsoft Visual Studio .NET.
■ Comprehensive volume administration The volume is the central repository for the design files, folders, and other items that BIRT iHub stores and manages. The Actuate Information Delivery API, can manage the items in a volume from a single machine, and can send success or failure notices for immediate and scheduled jobs using Simple Mail Transfer Protocol (SMTP), or UNIX sendmail. The notifications can include an attachment or embedded file.
■ Open infrastructure The Actuate Information Delivery API supports BIRT iHub’s open-server infrastructure. This infrastructure generates, distributes, and manages Actuate and third-party designs and integrates the designs into a volume. The API also automates extracting parameters from a third-party executable file when integrating the file into a volume.
■ Localization support By setting the Locale parameter in the header of a SOAP request, localization generates data in a language other than the BIRT iHub default language. The data display uses the currency format, date format, and other conventions for specific locales.
196 Integrating Applications into BIRT iHub About web services and WSDL Actuate web services support interactions with BIRT iHub, from running and viewing designs to managing volume items. Actuate describes its services using Web Services Description Language (WSDL), an XML schema that provides the structure for requests to and responses from BIRT iHub. A WSDL schema provides an abstract definition of the operations that a web service supports. The schema describes web services by providing such information as the name of the service, the transport protocol, data types, messages and operations, and input and output parameters. The schema binds these definitions to a concrete network protocol and message format. The WSDL schema resides on BIRT iHub. The iHub WSDL schema serves as an interface to applications that integrate with BIRT iHub. The schema encompasses all web services accessible using the Actuate Information Delivery API. A developer can use the schema to generate a code library that contains the classes, including proxies, that the developer uses to write an application that communicates with a web service. A developer can use an integrated development environment (IDE) to develop an application that uses the Information Delivery API schema. Actuate supplies WSDL files for the Apache Axis and Microsoft .NET development environments. The elements of the iHub schema are case-sensitive. Capitalization must occur as the schema indicates. For example, to use the AuthId element of the complex data type Header, write AuthId instead of AuthID or authid.
Understanding the elements of the iHub WSDL schema A WSDL file defines every element used in a SOAP message. Figure 9-1 shows the basic structure of a WSDL file. Find additional details about how the Actuate Information Delivery API defines each element in the following sections. About the definitions element Because it is a definitions document, the WSDL schema begins with a definitions element. The opening tag defines the following Actuate namespace and attribute declarations: Chapter 9, Understanding the Information Delivery API and schema 197 xmlns:wsdlns="http://schemas.actuate.com/actuate11/wsdl" targetNamespace="http://schemas.actuate.com/actuate11/wsdl">
198 Integrating Applications into BIRT iHub Table 9-1 Namespace and attribute declarations for the definitions element Declaration Description xmlns="http://schemas.xmlsoap.org/wsdl/" Defines a namespace for the WSDL specification to which Actuate adheres xmlns:xsd="http://www.w3.org/2001 Defines a namespace prefix, xsd, for the /XMLSchema" XML schema standard xmlns:soap="http://schemas.xmlsoap.org Defines a namespace prefix, soap, for the /wsdl/soap/" SOAP specification to which Actuate messages adhere xmlns:typens="http://schemas.actuate.com Defines a namespace prefix, typens, for the /actuate11" Actuate 11 XML schema xmlns:wsdlns="http://schemas.actuate.com Defines a namespace prefix, wsdlns, for /actuate11/wsdl" Actuate 11 web services targetNamespace="http://schemas.actuate.com Scopes messages to the Actuate WSDL file /actuate11/wsdl" for Actuate 11
About data type definitions The types element of a schema describes every complex data type that Actuate web services recognize. The types element begins with the following declarations:
Chapter 9, Understanding the Information Delivery API and schema 199
200 Integrating Applications into BIRT iHub The following example shows the Apache Axis message description for a request to search for jobs:
Chapter 9, Understanding the Information Delivery API and schema 201 The following example shows the binding definition for ActuateSoapBinding:
■ The name of the port through which the client accesses the iHub web services. port name="ActuateSoapPort"
■ The binding definition expressed as a namespace. binding="wsdlns:ActuateSoapBinding"
■ The location of the port, defined as host_name:port_number, expressed as a valid URL. soap:address location="http://localhost:8000"
202 Integrating Applications into BIRT iHub The following example shows the service definition for ActuateAPI:
Accessing the Actuate schema using a web browser To access the list of BIRT iHub WSDL files using a web browser, type the following URL: http://localhost:8000/wsdl where ■ localhost is the machine name.
■ 8000 is the port to which the SOAP endpoint binds. This URL retrieves the WSDL file list for the Apache Axis and Microsoft .NET development environments, as shown in Figure 9-2.
Figure 9-2 Accessing the iHub WSDL files using a web browser To run a utility that displays the list of classes defined in a WSDL file, choose one of the items in the list. For example, in IDAPI/SSI, choose Apache Axis to view the list of operation classes defined in that WSDL file. The list of Information Delivery API operation classes appears, as shown in Figure 9-3. To view the WSDL schema definition for a particular operation class, choose the class name. To view the entire contents of the WSDL file, choose All or type the following URL: http://localhost:8000/wsdl/v11/axis/all
Chapter 9, Understanding the Information Delivery API and schema 203 Figure 9-3 Actuate Information Delivery API operations Choosing All displays the entire WSDL document, as shown in Figure 9-4. Choosing Login displays the schema for the Login operation, preceded by iHub namespace information, as shown in Figure 9-4.
Figure 9-4 WSDL schema definitions
204 Integrating Applications into BIRT iHub Chapter 10
Chapter 10Constructing a SOAP message
This chapter contains the following topics: ■ About SOAP messaging ■ Calling an Actuate web service ■ About SOAP message elements ■ About SOAP Fault messages
Chapter 10, Constructing a SOAP message 205 About SOAP messaging This chapter describes the elements of Actuate Simple Object Access Protocol (SOAP) messages. The Actuate Information Delivery API uses SOAP messaging in the request and response pattern for communications between the client and BIRT iHub. SOAP messages are written in XML to ensure standard message formatting and standard data representation. The principal advantage of SOAP is that it supports communications among applications written in different programming languages and running on different platforms. SOAP supports Java, Visual Basic, C++, C#, and other programming languages. It operates on Windows, UNIX, Linux, Mac, and other operating systems. Certain messages in the Actuate Information Delivery API can be composite messages, supporting multiple operations in a single message. The Actuate Information Delivery API packages an XML request into a SOAP envelope and sends it to the BIRT iHub using a HyperText Transfer Protocol (HTTP) connection. Although a SOAP message can use other transport mechanisms, Actuate supports HTTP because this protocol is ubiquitous and because it simplifies external firewall management. The client application sends the request and reads the response in the client’s native language. The system’s SOAP endpoints, ports that accept SOAP messages, listen for requests and direct them to the appropriate BIRT iHub node. As with any other XML document, a SOAP message must be well formed and valid. A well-formed message has a single root, is correctly nested, and displays tags in starting and ending pairs. Valid XML is well formed and adheres to a schema. XML instruction is outside the scope of this book.
Calling an Actuate web service When accessing Actuate’s web services, you create a library of proxy objects for the client application. In Java, a proxy object is a class implementation in a JAR file. In C#, a proxy is a CS file. Use a proxy object directly. Actuate does not support subclassing an Information Delivery API (IDAPI) class generated from an Actuate WSDL document. To ensure high availability of an IDAPI application accessing an iHub cluster, set up a load balancer between the application and the cluster. Using a load balancer also distributes IDAPI requests evenly across the nodes in the cluster.
206 Integrating Applications into BIRT iHub Access proxy objects using a request and response pattern. As Figure 10-1 shows, the client uses a proxy object to send a SOAP request to BIRT iHub and receives a response in the client’s native language.
IDAPI schema Toolkit Client application 2 Generate 3 Call the proxy ActuateAPI.wsdl com.actuate.schemas to submit the proxy web service request
HTTP 4
1 BIRT iHub
Factory service SOAP service SOAP Dispatch service 6 layer 5 View service Figure 10-1 Calling an Actuate web service In the sequence shown in Figure 10-1: 1 BIRT iHub sends the Information Delivery API schema over the web in response to a client query. 2 The client generates a proxy object that corresponds to a service or an operation in Actuate’s schema. At this point, you build or modify a client application. 3 The deployed client application calls a proxy object. 4 Using the proxy, the client generates a SOAP request, adds an HTTP header, and sends this serialized XML package to BIRT iHub over the web. 5 BIRT iHub processes the SOAP message header, deserializes the SOAP envelope, and invokes the appropriate service. In the preceding diagram, the Factory service processes the request. 6 The service serializes the result, creates the response XML, places the encoded result into a SOAP response, and returns the package to the client application. The application then extracts and decodes the result.
About SOAP message elements The Actuate Information Delivery API uses the standard SOAP message structure. A message consists of an HTTP header followed by a SOAP envelope, header, and body. The SOAP envelope wraps the header and body elements. The
Chapter 10, Constructing a SOAP message 207 HTTP header encloses the entire message, which goes over the web to a server that can accept SOAP messages. The following sections provide details about each element of a SOAP message. Understanding the HTTP header This header is a mandatory element that specifies items such as the HTTP version, the host machine and port, the content type, and character set. The elements of an HTTP header can vary from message to message. The following example shows a typical HTTP header:
POST / HTTP/1.0 Content-Type: text/xml; charset=utf-8 Accept: application/soap+xml, application/dime, multipart/related, text/* User-Agent: Axis/2.0 Host: localhost:8080 Cache-Control: no-cache Pragma: no-cache SOAPAction: "" Content-Length: 1387 In the preceding example: ■ POST routes the message to a servlet running on a web server, using HTTP version 1.0 or 1.1. The message determines which HTTP version to use. Version 1.0 treats an attachment as a single block of data. Version 1.1 supports sending chunked attachments. ■ Content-Type specifies the message’s media type. Set Content-Type to text/xml when calling an Actuate service. ■ The default character set is UTF-8. To use the UTF-8 character set, it is not necessary to include this element in the HTTP header. ■ Accept indicates the acceptable types of media in the response: ■ The application/soap+xml media type describes a SOAP message serialized as XML. ■ The application/dime media type supports processing a message either using MIME or by reference to a uniform resource identifier (URI) that accesses a plug-in. A URI is a unique string that can be a uniform resource locator (URL), a uniform resource name (URN), or both. Using a URI ensures uniqueness. ■ The multipart/related media type indicates a compound object containing several inter-related parts in the body of a message.
208 Integrating Applications into BIRT iHub ■ The asterisk in text/* indicates the response can contain any type of text. ■ User-Agent is the client that initiates the request. ■ Host is the name of the host machine where the target BIRT iHub resides and, optionally, the port number. ■ Cache-Control is a directive to any caching mechanism operating along the request-response transport layer. A no-cache directive keeps a cache from using the response to satisfy a subsequent request. This directive prevents the cache from returning a stale response to a client. ■ Pragma is a directive to all recipients along the request-response transport layer. This no-cache directive requires the system to forward the original request to the target BIRT iHub even when a cached copy exists. Forwarding the original request prevents the transmission of a stale copy of a request. ■ SOAPAction, a required element, tells the BIRT iHub that the message is a SOAP message. For an Actuate message, use a set of empty quotation marks for the SOAPAction value. The volume determines the action based on the message body. The SOAPAction attribute requires empty quotes because it has no default value. ■ Content-Length is the number of characters in the message. Understanding the SOAP envelope The SOAP envelope is a required element of each message. It defines an overall framework for the message and contains other elements of the message. The envelope contains namespace declarations that apply to the specific message that contains them and to any child elements of that message. An XML namespace is a unique identifier for the elements and attributes of an XML document. When declaring an XML namespace in a SOAP envelope, define the rules by which the system interprets the content and structure of the message. To ensure that a namespace is globally unique, the namespace must be a URI. A namespace does not have to point to a web site or online document. In the following example, the namespace declarations indicate that the message adheres to specific XML and SOAP standards and identifies the version of the Actuate XML schema:
Chapter 10, Constructing a SOAP message 209
210 Integrating Applications into BIRT iHub xmlns:sales="http://www.actuate.com/soap/Sales and Marketing"> These new namespaces define prefixes, fin and sales in the example above, as shorthand for data sources. Add the prefix to the appropriate tag name to indicate which data source to use. Use a simple prefix, separated from the tag name by a colon, as shown in the following example:
Understanding the SOAP header The SOAP header contains authentication data, locale information, and other required or optional data. The SOAP header element is mandatory for calls to the BIRT iHub. Using the SOAP header, parser tools can locate key information without having to parse the entire message. The following example shows a typical SOAP header with authentication and locale information:
Chapter 10, Constructing a SOAP message 211 AuthId When the client logs in using the Actuate Information Delivery API, the system returns a system-generated, encrypted AuthId string in the Login response. All requests except Login requests must have a valid AuthId in the SOAP header. The header passes this ID to BIRT iHub for validation. The example shows a typical AuthId. In subsequent requests in the same session, the AuthId identifier appears in the SOAP header. AuthId expires after a configurable period of time. In the example, AuthId contains two attributes: ■ soapenv:actor The value for actor, "http://schemas.xmlsoap.org/soap/actor/next", is a URI indicating that this message is for the first SOAP application capable of processing it. ■ soapenv:mustUnderstand Indicates that the actor must understand and process the message and, if it cannot, the actor must return a SOAP fault containing the value specified by the attribute. The mustUnderstand attribute can have a value of 0 or False, or 1 or True.
ConnectionHandle An optional element that supports keeping a connection open to view a persistent document. ConnectionHandle is a session ID of the object. ConnectionHandle supports phased downloading and viewing of a persistent report in the volume to improve performance. When ConnectionHandle is present in the header, iHub System ignores the value for TargetVolume. ConnectionHandle returns in two ways: ■ As an element of a document generation response when the document is transient and progressive viewing is enabled. BIRT iHub System routes subsequent viewing requests to the BIRT iHub that generated the transient document. ■ As a response to a viewing request, to ensure that subsequent requests by the same user go to the same View service until the report data changes. If the report name changes but the data remains the same, the View service displays the same report. If ConnectionHandle is present in the SOAP header, the system routes subsequent viewing requests to the same View service that returned the ConnectionHandle.
DelayFlush A Boolean element that tells BIRT iHub to write updates to the disk when the value is False.
212 Integrating Applications into BIRT iHub FileType An element that specifies the file type to run, such as an HTML or BIRT design (.rptdesign) file. Specify FileType in the SOAP header for all execute, submit, and view IDAPI requests, such as ExecuteReport, SelectPage, or GetContent. When running a design that specifies a TargetResourceGroup, specify FileType in the SOAP header. BIRT iHub System looks for a machine that can execute that file type. The default setting is for BIRT iHub System to look for any available iHub to manage a request, whether or not that iHub can run the requested file type.
Locale BIRT iHub uses this element to format data using the language, date and time conventions, currency and other locale-specific conventions before returning the data to the client. If the client does not specify another locale, BIRT iHub System uses the client’s default locale.
TargetResourceGroup An optional element that supports assigning a synchronous report generation request to a specific resource group at run time. When using ExecuteReport to run a BIRT design that specifies a TargetResourceGroup, you must specify FileType in the SOAP header.
TargetServer An optional element that refers to the BIRT iHub within a cluster to which to direct the request. Use TargetServer for requests pertaining to system administration, such as GetFactoryServiceJobs and GetFactoryServiceInfo.
TargetVolume Refers to the volume to which to direct the request. Use this optional element of the SOAP header to route a request to a volume other than the default volume for the system. In iServer Release 11 and iHub 2, the Login message required specifying the volume name using TargetVolume in the SOAP header and Domain in the SOAP message body. In iHub 3, the Login message no longer requires specifying a volume name using TargetVolume in the SOAP header or Domain in the SOAP message body.
RequestID An optional element that represents a unique value identifying the SOAP request. Understanding the SOAP message body The body of the message contains either the request for a specific operation, the response to a request, or an error message. The following example requests detailed data about users on the volume:
Chapter 10, Constructing a SOAP message 213
214 Integrating Applications into BIRT iHub About SOAP Fault messages A SOAP Fault occurs when a request cannot be completed. Fault contains information identifying the source of the error or the component returning the error, the request, an error code, and a text description of the error. In the following example, a request to download a file results in a SOAP Fault. The Description element contains a text error message and a reference to the requested file.
Chapter 10, Constructing a SOAP message 215 216 Integrating Applications into BIRT iHub Chapter 11
Chapter 11Text string limits in Actuate operations
Actuate’s internal data store imposes a fixed upper limit on the length of certain text strings. An application that uses elements such as user names, URLs, file types, and descriptions must adhere to these limits. Table 11-1 lists the maximum field lengths for text elements in BIRT iHub Information Console and for elements you create using Actuate Information Delivery API. Table 11-1 Text string limits in Actuate operations Maximum length, Complex data type Element name in characters ArchiveRule FileType 20 Attachment ContentEncoding 10 File Name 255 FileType 20 Description 500 VersionName 100 FileType Name 20 DriverName 100 MutexClass 50 ShortDescription 40 (continues)
Chapter 11, Text string limits in Actuate operations 217 Table 11-1 Text string limits in Actuate operations (continued) Maximum length, Complex data type Element name in characters FileType (continued) LongDescription 60 LocalExtension 20 OutputType 20 SmallImageURL 100 LargeImageURL 100 ContentType 200 JobProperties JobName 100 InputFileName 276 RequestedOutputFileName 1000 ActualOutputFileName 1000 RequestedHeadline 100 ActualHeadline 100 JobNotice JobName 100 OutputFileName 276 OutputFileVersionName 100 Headline 100 JobPrinterOptions PageRange 20 PrintToFile 256 Printer Name 50 Manufacturer (UNIX only) 50 Model (UNIX only) 50 Location (UNIX only) 50 Description 100 Orientation 20 PageSize 50 Resolution 20 PaperTray 50 Duplex 20 JobSchedule TimeZoneName 32
218 Integrating Applications into BIRT iHub Table 11-1 Text string limits in Actuate operations (continued) Maximum length, Complex data type Element name in characters User Name 256 Password 256 EmailAddress 80 DefaultPrinterName 50 Description 100 UserGroup Name 50 Description 500
Chapter 11, Text string limits in Actuate operations 219 220 Integrating Applications into BIRT iHub PartFour 4
Part 4Using Actuate security
■ Using Visualization Platform security ■ Using Java Report Server Security Extension and iPortal Security Extension
Chapter 12
Chapter 12Using Visualization Platform security
This chapter contains the following topics: ■ About Actuate Visualization Platform security ■ Protecting corporate data ■ Understanding the authentication process ■ Creating a custom security adapter ■ Creating an upload security adapter
Chapter 12, Using Visualization Platform security 223 About Actuate Visualization Platform security A reporting web application is accessible to any user who has a web browser and the URI for the application. This chapter discusses the Actuate Visualization Platform security features and how to use them to: ■ Ensure that users access only those objects in the volume for which they have permission. ■ Protect sensitive reports. The types of security you can provide for Visualization Platform are: ■ Default user authentication. Use the default Visualization Platform and BIRT iHub facilities to ensure that users access only those reports and other volume items for which they have permission. ■ User authentication using the iPortal Security Extension (IPSE). Use IPSE to customize and control the user login and authentication process. For details about implementing custom user authentication, see “Creating a custom security adapter,” later in this chapter.
Protecting corporate data iHub provides a structured content generation solution for web applications. Deploying Actuate applications developed for the internet, such as Visualization Platform, requires planning for network security. Internet applications support access to information within an organization from outside that organization. Because the organization’s internal network is connected to the internet, there is the risk of unauthorized access to the corporate network and to the data that resides on that network. Organizations use one or a combination of the technologies described in the following sections to prevent unauthorized access to the corporate network and protect authentication transactions from intrusion. Protecting corporate data using firewalls Typically companies use firewalls to prevent unauthorized access to corporate networks and data. A firewall is a system or group of systems that restrict access between two networks, such as an organization’s internal network and the internet. Firewalls keep unauthorized users out. As a result, firewalls prevent damage caused by malicious programs such as worms and viruses from spreading to other parts of your network. At the same time, firewalls allow legitimate business to tunnel through the firewall and be efficiently conducted on your network.
224 Integrating Applications into BIRT iHub Firewalls can be used to restrict access between two internal networks, for example, the accounting and engineering networks. Security teams configure firewalls to allow traffic using specific protocols, such as HTTP, over specific network addresses and ports. Be sure that your firewall allows access for the Visualization Platform and iHub ports. Protecting corporate data using proxy servers Proxy servers, specialized web servers or hardware that operate on or behind a firewall, improve efficient use of network bandwidth and offer enhanced network security. For more information about proxy servers and Visualization Platform, see Managing Volumes and Users.
Understanding the authentication process The authentication process involves the following steps, in this order: ■ A user or client makes a request by choosing a link on a Visualization Platform page or by typing a Visualization Platform URI in a web browser. The Visualization Platform application processes the request. ■ Visualization Platform checks the URI for the forceLogin parameter. If the forceLogin parameter is set to “true” in the URI, the application activates the Visualization Platform Login page, even if the user has already logged in. If forceLogin is set to “false” or does not appear, the request process continues. For details about the forceLogin URI parameter, see Chapter 19, “Actuate application URIs.” ■ Visualization Platform authenticates the user for the cluster. If the login information is invalid, the login screen appears in the browser. If a custom security adapter parameter is set in the web.xml file, Visualization Platform attempts to load the custom security adapter class. If the class loads successfully, the following steps occur: ■ Visualization Platform calls the custom security adapter’s authenticate( ) method with the parameters that the browser sent. ■ The authenticate( ) method performs the custom validation. ■ Visualization Platform calls the required getUserName( ), getPassword( ), and getVolumeProfile( ) methods to retrieve the user information needed by iHub. ■ Optionally, Visualization Platform calls the getExtendedCredentials( ) method. If this method returns null, there are no extended credentials to send to iHub.
Chapter 12, Using Visualization Platform security 225 ■ Visualization Platform now has all the information that it requires for connecting to iHub. Visualization Platform creates the necessary SOAP message for connecting to iHub and sends a login request. iHub Information Console client uses the default Volume Profile setting if the server, volume, or volume profile if it is not registered as a service provider with the cluster.
Creating a custom security adapter The Visualization Platform security adapter enables other applications to authenticate users and log in to the Visualization Platform application, for example, by using a URL. A custom security adapter can define alternate authentication requirements. In this way, a Visualization Platform security adapter establishes an additional layer of logic to the existing Visualization Platform authentication, as shown in Figure 12-1.
Security No Authentication adapter required configured?
Yes Generic Visualization Authenticate( ) Platform authentication
Figure 12-1 Visualization Platform authentication system A user cannot update their password from Visualization Platform if a custom security adapter class is set. In this way, Visualization Platform prevents conflicts between the user’s current password and the security system that is used to verify passwords. To create a custom security adapter, perform the following steps: ■ Ensure that your application can access the IPSE Java classes. ■ Create a Java class that implements the custom security adapter class for IPSE. ■ Deploy the Custom Security Adapter to iHub Information Console client.
226 Integrating Applications into BIRT iHub Accessing the IPSE Java classes The Visualization Platform library, com.actuate.iportal.jar, contains the IPSE Java classes. This library is located in the lib subdirectory in the Visualization Platform installation. The class, com.actuate.iportal.security.iPortalSecurityAdapter, in this library provides the framework for custom authentication. A custom security adapter providing an IPSE implementation extends this class. Specifically, the JRE needs to access the following JARs: ■
Chapter 12, Using Visualization Platform security 227 authenticate( ) to retrieve the parameter from the HttpServletRequest and set the user name, password, and volumeProfile as in the following class: import javax.servlet.http.*; import com.actuate.iportal.security.iPortalSecurityAdapter; public class SecurityCode extends com.actuate.iportal.security.iPortalSecurityAdapter { private String volumeProfile = "CustomAccess"; private String userName = null; private String password = null; public SecurityCode( ) {} public boolean authenticate( HttpServletRequest httpservletrequest) { String param = httpservletrequest.getParameter("code"); boolean secured = true; if ("12345".equalsIgnoreCase( param )) { userName = "user1"; password = "user1"; } else if ("abc".equalsIgnoreCase( param )) { userName = "BasicUser"; password = ""; } else { secured = false; } return secured; } public String getUserName() { return userName; } public String getPassword() { return password; } public String getVolumeProfile() { return volumeProfile; } } If there is a user "user1" with the password "user1" on the volume configured by the volume profile "CustomAccess," a valid URL that authenticates user1 using this security adapter is as follows: http://localhost:8700/iportal/getfolderitems.do?code=12345
Deploying a custom security adapter To deploy a custom security adapter, the iHub Information Console client application must have access to the class compressed into a JAR file. To meet this requirement, compile the class, compress it into a JAR, and move it into the
228 Integrating Applications into BIRT iHub \web.xml. Finally, restart the application service running iHub Information Console client to activate this change.
How to deploy a custom security adapter to iHub Information Console client 1 Compile the IPSE application. Use a command similar to this one in a console window: javac SecurityCode.java 2 Create a JAR file to contain the IPSE application. Use a command similar to this one in a console window: jar cvf SecurityCode.jar SecurityCode.class 3 Using Windows Explorer, copy SecurityCode.jar to this directory:
Creating an upload security adapter The default security for iHub Information Console client upload functionality checks a file’s type against the value of the UPLOAD_FILE_TYPE_LIST parameter in web.xml. The iHub Information Console client upload security adapter provides additional external verification features for the file upload feature using a Java interface, com.actuate.iportal.security.IUploadSecurityAdapter. Visualization Platform upload security adapter establishes an additional layer of logic to the existing Visualization Platform authentication, as shown in Figure 12-2.
Chapter 12, Using Visualization Platform security 229 Is upload Upload No security requested configured?
Yes Is file type in UPLOAD_FILE_ No TYPE_LIST? isFileTypeAllowed( ) Yes Yes
No Yes Execute getErrorMessage( ) verifyFile( ) upload
Figure 12-2 Visualization Platform upload security system If an upload security adapter is configured, iHub Information Console client calls isFileTypeAllowed to check whether the file’s file type is allowed. If so, then it calls verifyFile to perform any additional verification steps. If either isFileTypeAllowed or verifyFile returns false, iHub Information Console client displays an error message supplied by getErrorMessage, or a generic message if getErrorMessage returns null. To create an upload security adapter, perform the following steps: ■ Ensure that your application can access the necessary Java classes. ■ Create a Java class that implements the upload security adapter interface. ■ Deploy the upload security adapter class to iHub Information Console client. Accessing the necessary Java classes The Visualization Platform library, com.actuate.iportal.jar, contains the security extension Java classes. This library is located in the lib subdirectory of the Visualization Platform installation. The upload security adapter interface, com.actuate.iportal.security.IUploadSecurityAdapter, in this library provides the framework for additional upload security. A valid upload security adapter implements this interface. Specifically, the JRE needs to access the following JARs: ■
230 Integrating Applications into BIRT iHub ■
Chapter 12, Using Visualization Platform security 231 When the upload security adapter requires file validation, iHub Information Console client copies the file temporarily into the directory specified by TEMP_FOLDER_LOCATION parameter in web.xml. Deploying an upload security adapter To deploy an upload security adapter, the iHub Information Console client application must have access to the class compressed into a JAR file. To meet this requirement, compile the class, compress it into a JAR, and move it into the
How to deploy an upload security adapter to iHub Information Console client 1 Compile the Upload security application. Use a command similar to this one in a console window: javac SecureUpload.java 2 Create a JAR file to contain the upload security application. Use a command similar to this one in a console window: jar cvf SecureUpload.jar SecureUpload.class 3 Using Windows Explorer, copy SecureUpload.jar to this directory:
232 Integrating Applications into BIRT iHub Chapter 13
Chapter 13Using Java Report Server Security Extension and iPortal Security Extension
This chapter contains the topic, About Java Report Server Security Extension (RSSE) and iPortal Security Extension (IPSE).
Chapter 13, Using Java Report Server Security Extension and iPortal Security About Java Report Server Security Extension (RSSE) and iPortal Security Extension (IPSE) By default, BIRT iHub stores information about users, user groups, and access control lists (ACLs) in the metadata database that installs with BIRT iHub. Commonly, an enterprise stores user information in an external security system, such as a Lightweight Directory Access Protocol (LDAP) or Microsoft Active Directory, with which all applications needing user information communicate. BIRT iHub provides a SOAP-based API known as Java Report Server Security Extension (RSSE), that supports creating a web service application to communicate with an external security system. Using the Java RSSE framework, a developer can create an application that provides the following security features: ■ External authentication Authenticates a user using an interface to an external security system. Users, user groups, access control lists (ACLs), and other information remain on the volume. ■ External registration Manages users, user groups, access control lists (ACLs), and other information using an interface to an external security system. The volume no longer manages this information. ■ Page-level security Controls user access to sensitive information in a BIRT report by implementing page-level security. A page-level security application requires a BIRT Page Level Security option license. By default, a user logs in to Information Console to run a design to generate visual representations of data, such as charts, graphs, and reports. When the user logs in, BIRT iHub authenticates the user. If an enterprise wants to support a user generating a report by clicking on a link in the enterprise website for example, the user should not need to authenticate again, after having already logged in to the enterprise website. BIRT iHub provides an API that supports a single sign-on (SSO) solution, known as iPortal Security Extension (IPSE). A developer can implement IPSE to accept any manner of data and convert it into a user name and password that BIRT iHub recognizes. For example, a user logs into a banking website and the banking application authenticates the user and assigns a token to the user. The token serves as proof of authentication while the user is on the banking website. The user clicks a link to generate a report showing account activity for the current month. To prevent the user having to provide a user name and password to authenticate with BIRT iHub, the bank has written an IPSE implementation to convert the user token to a user name and password that BIRT iHub recognizes. IPSE passes the user name and password to BIRT iHub, iHub authenticates the user and generates the report. Authentication with BIRT iHub is transparent to the user.
234 Integrating Applications into BIRT iHub IPSE and RSSE commonly work together.For example, an IPSE implementation might encrypt a user name and password, and pass them to an RSSE implementation. The RSSE implementation decrypts the user name and password and passes them to BIRT iHub, allowing the user to log in to Information Console. Open Text provides the following example implementations that demonstrate using RSSE and IPSE:
■ ServerIntegrationRSSEExample Shows how to integrate BIRT iHub with external security systems using RSSE. You download the folder containing the RSSE example files to the machine where your application container resides. . This document refers to the location to which you download the folder as RSSE_EXAMPLE_HOME.
■ ServerIntegrationIPSEExample Shows how to achieve single sign-on when BIRT iHub is integrated into an application using iPortal Security Extension (IPSE). You download the folder containing the IPSE example files to a machine on which a user logs in to Information Console. This document refers to the location to which you download the folder as IPSE_EXAMPLE_HOME. You can view the example RSSE and IPSE implementations at the following location: http://developer.actuate.com/resources/documentation/ihub31/ integration/
Installing the software required to run the RSSE and IPSE examples Running the RSSE and IPSE examples requires the following software: ■ Java Development Kit (JDK) version 1.7 or later ■ Apache Tomcat ■ Apache Axis2 ■ Apache Ant When deploying an RSSE application, you must use an external application server. Do not use the embedded Tomcat application server that installs with BIRT iHub. This section describes how to install these software packages.
How to install the software required to run the RSSE and IPSE examples 1 Install a Java Development Kit (JDK) by performing the following tasks:
Chapter 13, Using Java Report Server Security Extension and iPortal Security 1 Download a Java Development Kit (JDK), version 1.7 or later. The Java Development Kit is available at the following location: http://www.oracle.com/technetwork/java/javase/downloads /index.html 2 Install the Java Development Kit that is appropriate to your operating system. 3 Create an environment variable named JAVA_HOME. Assign the pathname of the folder into which you installed the JDK to this variable, for example: C:\Program Files (x86)\Java\jdk1.7.0_60 2 Install Apache Tomcat by performing the following tasks: 1 Open a new browser window and go to the following location: http://tomcat.apache.org Open the binary distribution of Apache Tomcat that is compatible with the Java release version and operating system in your environment. 2 Extract the files the Apache Tomcat archive contains. All the files download to a new folder on your machine. For example, if you extract the Tomcat files to the C:\ drive on Windows, the download creates a folder such as the following: C:\apache-tomcat-7.0.59 This section will refer to this path as TOMCAT_HOME. 3 Install Apache Axis2 by performing the following tasks: 1 Download the latest version of the Apache Axis2 WAR (Web Archive) Distribution. Apache Axis2 is available at the following location: http://axis.apache.org/axis2/java/core/download.cgi Open the WAR Distribution archive appropriate to your operating system. 2 Extract the files the Axis2 archive contains to a new folder, for example: C:\apache-axis2-WAR-distribution 3 Copy C:\apache-axis2-WAR-distribution\axis2.war to TOMCAT_HOME\webapps. 4 Restart Tomcat by performing the following tasks: 1 From a command prompt, navigate to TOMCAT_HOME\bin. 2 Execute shutdown.bat 3 Execute startup.bat. 4 Install Apache Ant by performing the following tasks:
236 Integrating Applications into BIRT iHub 1 Open a new browser window and go to the following location: http://ant.apache.org/bindownload.cgi Open the archive appropriate to your operating system. 2 Extract the files the Apache Ant archive contains. All the files download to a new folder on your machine. For example, if you extract the Ant files to the C:\ drive on Windows, the download creates a folder such as the following: C:\apache-ant-1.9.4 This section will refer to this path as ANT_HOME. 3 Add the path of the ANT_HOME\bin folder to your Path system environment variable, for example: C:\apache-ant-1.9.4\bin
Understanding the RSSE example The RSSE example demonstrates using external registration, where authentication takes place outside of BIRT iHub, and user and user group information is stored on an external security system. RSSE_EXAMPLE_HOME \src\com\actuate\rsse\example\SampleRSSE.java is the RSSE driver that BIRT iHub uses to implement RSSE. This section discusses the following topics:
■ Understanding initialization What the RSSE driver does when BIRT iHub starts
■ Understanding user log in What the RSSE driver does when a user logs in to Information Console
■ Understanding SampleRSSE.json What the data file for the RSSE example contains
■ Running the RSSE example How to run the RSSE example
Understanding initialization When BIRT iHub starts, the RSSE driver performs an initialization procedure consisting of the following method calls:
■ start(...) The start(...) method creates a response object, and calls the following methods on it:
■ setConnectionPropertyExternal(boolean parameter)
Chapter 13, Using Java Report Server Security Extension and iPortal Security start(...) always passes false to setConnectionPropertyExternal(...).
■ setExternalProperties(...) Obtains the list of user properties from static method SampleRSSE.getExternalProperties(). A user must possess all the properties SampleRSSE.getExternalProperties() returns.
■ setIntegrationLevel(...) Specifies whether iHub uses external authentication or external registration. In SampleRSSE.java, the value of SampleRSSEConst.RSSE_INTEGRATION_LEVEL is external registration.
■ setRSSEVersion(...) Specifies the RSSE version that iHub3.1 uses. Set the RSSE version to 11.
■ setSelectGroupsOfUser(boolean parameter) Indicates whether SelectGroups implements the UserName element in the RSSE driver. False indicates the element is not implemented, true indicates the element must be implemented.
■ setSelectUsersOfRole(boolean parameter) Indicates whether SelectUsers implements the RoleName element in the RSSE driver. False indicates the element is not implemented, true indicates the element must be implemented.
■ setSupportGetTranslatedUserNames(boolean parameter) Specifies whether the RSSE driver supports the GetTranslatedUserNames API. False indicates the element is not supported, true indicates the element must be supported. Must be true when integration level is set to external registration.
■ setUserACLExternal(boolean parameter) Specifies whether the user’s access control list is stored externally. Applies only if using page-level security.
■ getTranslatedUserNames(...) BIRT iHub has a default user named Administrator, who has all privileges in a volume. In an external security system, this user might be known by a different name than Administrator, for example, Pam Castillo. GetTranslatedUserNames(...) maps Administrator to Pam Castillo and returns Pam Castillo. You can think of Pam Castillo as an alias of the default BIRT iHub Administrator user. When Pam Castillo logs in to Information Console, BIRT iHub assumes Pam Castillo is Administrator.
■ getTranslatedRoleNames(...) GetTranslatedRoleNames(...) is similar to GetTranslatedUserNames(...). BIRT iHub has three default user groups; Administrators, All, and Operator. Operator is obsolete starting in iHub 3, but still exists for backward
238 Integrating Applications into BIRT iHub compatibility. In an external security system, these three user groups might be known by different names, such as Admin, Everyone, and Operations. GetTranslatedRoleNames(...) maps Administrators, All, and Operator to Admin, Everyone, and Operations, and returns Admin, Everyone, and Operations.
Understanding user log in When a user logs in to Information Console, Information Console sends a SOAP message to BIRT iHub containing the user name, user password, and the name of the volume the user wants to access. BIRT iHub calls doesUserExist(...), passing the user and volume names as parameters. iHub first checks its own list of users of the specified volume for the user name. If the name is not found, RSSE checks the RSSE cache. If the name is still not found, RSSE checks the external security system for the name. If the name is found, doesUserExist(...) returns a response object containing a value of true. Otherwise, doesUserExist(...) returns false in the response object. If doesUserExist(...) returns true, BIRT iHub calls authenticate(...), which uses the user name, password, and volume name with which the user logged in to Information Console to authenticate the user. If the user is authenticated, authenticate(...) creates an AuthenticateResponse object. If the UserSetting parameter passed to authenticate(...) has a value of true, authenticate(...) obtains the user information for the authenticated user and returns it in the AuthenticateResponse object. The last operation that the RSSE driver performs when a user logs in to Information Console is a call to getRolesOfUser(...) . This method returns any user groups to which the user belongs.
Understanding SampleRSSE.json The RSSE example implementation uses a .json file, SampleRSSE.json, containing JSON-formatted data, to represent the BIRT iHub volume information residing in an external security system. For example, SampleRSSE.json contains the following types of information, as shown in Listing 13-1:
■ Volume The volume or volumes the cluster contains, the users of each volume, and the user groups (referred to as roles in SampleRSSE.json file) existing for each volume. The volumes SampleRSSE.json contains are DEFAULT VOLUME and Volume1. Note that you must create Volume1 in System Console before running the RSSE example to log in to Information Console using Volume1. Default Volume already exists because the Information Console install program creates Default Volume.
Chapter 13, Using Java Report Server Security Extension and iPortal Security ■ User The user information for each volume, for example: ■ The users of each volume, such as Administrator, user1, and user2. The RSSE example driver uses the capitalized user names in SampleRSSE.json as keys. ■ The properties for each volume user, such as e-mail address and home folder. ■ The user group or groups to which each user belongs, and the privileges that user group or those user groups possess. The RSSE implementation reads the .json file, and for each volume, creates any users or roles that do not already exist. After running the example RSSE implementation, you can log in to Information Console as user1 using a blank password. You see the contents of Default Volume, and user1 possessing all the properties appearing under the "USER1" key, such as: ■ An e-mail address of user1@xyz.com ■ A home folder named /Home/user1, and membership in the following user groups:
❏ role1, having Read and Write privileges in Default Volume ❏ role2, having Visible and Read privileges in Default Volume Listing 13-1 Viewing SampleRSSE.json
{ "DEFAULT VOLUME": { "name": "DEFAULT VOLUME", "users": { "ADMINISTRATOR": { "volume": "DEFAULT VOLUME", "name": "Administrator", "password": "", "emailAddress": "Administrator@xyz.com", "homeFolder": "/Home/Administrator", ... }, "USER1": { "volume": "DEFAULT VOLUME", "name": "user1", "password": "", "emailAddress": "user1@xyz.com", "homeFolder": "/Home/user1", "viewPreference": "HTML", "maxJobPriority": 500,
240 Integrating Applications into BIRT iHub "sendNoticeForSuccess": true, "sendNoticeForFailure": true, "successNoticeExpiration": 7, "failureNoticeExpiration": 5, "sendEmailForSuccess": true, "sendEmailForFailure": true, "attachReportInEmail": true, "privilegeTemplate": [ { "volume": "DEFAULT VOLUME", "accessRight": "RW", "roleName": "role1" }, { "volume": "DEFAULT VOLUME", "accessRight": "VR", "roleName": "role2" } ], "roles": [ "role1", "role2" ] }, "USER2": { ... },
... } "roles": { "ADMINISTRATORS": "Administrators", "ROLE1": "role1", "ROLE2": "role2", "ROLE3": "role3" }, } "VOLUME1": { "name": "Volume1", "users": { ... } } }
Chapter 13, Using Java Report Server Security Extension and iPortal Security Running the RSSE example When the RSSE example driver program runs, it first reads the RSSE_EXAMPLE_HOME\src\SampleRSSE.properties file. This file contains the following configuration properties, which override default values in the example driver code. These properties are necessary only for the example RSSE implementation. A production RSSE implementation does not require them.
■ DATA_FOLDER Folder that contains the JSON-formatted data file containing the user information.
■ LOG_FILE_NAME Name of the log file the RSSE driver creates in DATA_FOLDER. Use the log file to follow the sequence of tasks the driver program performs.
■ JSON_STORAGE_FILE_NAME Name of the JSON-formatted data file containing the user information.
■ USER_ADMINISTRATOR Translated administrator user name. This name can be different from the default user Administrator if you require a different admin user. Note that starting with iHub3, the default user Administrator always has administrative privileges
■ ADMIN_ROLE Translated administrative user group (role) name. Supports specifying a user group name which must be assigned to all administrative users.
■ ROLE_ALL Translated user group (role) name All. BIRT iHub assigns all users to the All role implicitly.
■ LICENSE_OPTIONS_EXTERNALIZED Reserved for future use. The current sample implementation does not support externalized license options, but the implementation can be changed to support them.
How to run the RSSE example 1 Download the ServerIntegrationRSSEExample-ihub-3.1 folder. This procedure refers to the location of this folder as RSSE_EXAMPLE_HOME. 2 Navigate to the RSSE_EXAMPLE_HOME\src folder and open SampleRSSE.properties. 3 Create the folder that the DATA_FOLDER path specifies. 4 Copy the file that JSON_STORAGE_FILE_NAME specifies to the folder you created in the previous step.
242 Integrating Applications into BIRT iHub 5 Open a command prompt, and navigate to RSSE_EXAMPLE_HOME. Execute ant. Apache Ant creates RSSE_EXAMPLE_HOME\bin\SampleRSSE.aar. 6 Copy SampleRSSE.aar to TOMCAT_HOME\webapps\axis2\WEB-INF \services. 7 Copy RSSE_EXAMPLE_HOME\lib\gson-2.3.jar to TOMCAT_HOME \webapps\axis2\WEB-INF\lib. 8 Restart Tomcat. by performing the following tasks: 1 From a command prompt, navigate to TOMCAT_HOME\bin. 2 Execute shutdown.bat 3 Execute startup.bat. 9 Configure RSSE by performing the following tasks: 1 Log in to System Console. Choose Clusters. Left-click the arrrowhead icon next to the cluster containing the node on which you are running the RSSE example, and choose Edit, as shown in Figure 13-1.
Figure 13-1 Editing a cluster node 2 From the side menu, choose User Management. 3 In User Management, perform the following tasks, as shown in Figure 13-2: 1 In Select User Management, choose RSSE SOAP Service. 2 In Port Number, specify the port on which Tomcat listens, for example, 8080. In Context Path, specify the following path: /axis2/services/SampleRSSE 3 Choose Save.
Chapter 13, Using Java Report Server Security Extension and iPortal Security Figure 13-2 Configuring User Management for RSSE 10 Restart the cluster by performing the following tasks: 1 From the side menu, choose Cluster Configuration. Left-click the gear icon to display the Manage Cluster menu, and choose Stop Cluster, as shown in Figure 13-3.
Figure 13-3 Stopping the cluster 2 Choose Refresh to update the status of the services, as shown in Figure 13-4. When all services are showing red, go to the next step.
244 Integrating Applications into BIRT iHub Figure 13-4 Refresh the status of the services 3 Choose Start Cluster from the Manage Cluster menu. 4 Choose Refresh from the Manage Cluster menu to update the status of the services. When all services are showing green, the cluster is running. The example RSSE implementation program runs. The source for this program is in the following location: RSSE_EXAMPLE_HOME\src\com\actuate\rsse\example 11 Log in to Visualization Platform as user1 for example, with no password. You land in the user1 home folder, /Home/user1. For information about the RSSE API methods and data types, see Actuate API Reference. Understanding the IPSE example When you deploy an IPSE driver, you edit the Information Console web.xml file, and specify the IPSE driver name as the value for the SECURITY_ADAPTER_CLASS parameter. Then, you restart the Web service. BIRT iHub detects that its authentication mechanism has been replaced by the IPSE driver. When a user logs in to Information Console, BIRT iHub authenticates the user using the authenticate(...) method in the IPSE driver. IPSE supports processing the information a user provides when logging in to Information Console before Information Console sends the login information to BIRT iHub in a SOAP request. When a user logs in to Information Console, the IPSE authenticate(...) method receives an HttpServletRequest, and uses it to obtain the information that IPSE provides to BIRT iHub. An IPSE driver processes the information with which a user logs in to Information Console, and sets values for the following items: ■ user name ■ user password ■ volume
Chapter 13, Using Java Report Server Security Extension and iPortal Security ■ credentials The IPSE driver can assign any value to each of these items, including null. When the IPSE driver has set values for these items, the work of the IPSE driver is finished. Next, Information Console calls the following IPSE methods to retrieve the values: ■ getUserName() ■ getPassword() ■ getVolume() ■ getExtendedCredentials() Information Console creates a SOAP message containing the values these methods return and sends the message to BIRT iHub. To log a user in to Information Console, BIRT iHub must recognize the user name, the volume name, and recognize that the user belongs to the volume. Information Console creates a SOAP message containing the user name, password, and volume name the user provided when logging in and sends the message to BIRT iHub. If you are using an IPSE driver, the driver must perform the following tasks: ■ Authenticate the user ■ Map the information the user provides to a user name and volume name that BIRT iHub recognizes as a valid pair ■ Return the user name in the getUserName() method ■ Return the volume name in the getVolume() method In the scenario using the IPSE example driver, a user logs in to Information Console using a user name and password that the IPSE example driver recognizes. This user name and password pair is different than the user name and password pair that BIRT iHub recognizes for this user. The IPSE example implementation uses a .json file, SampleIPSE.json, to define the mapping between the user name and password a user uses to log in to Information Console, and the user name and password that BIRT iHub recognizes for this user. SampleIPSE.json contains the same volumes and users as SampleRSSE.json. The user logs in to Information Console using a user name and password that SampleIPSE.json contains. This user name and password is an alias of the user name and password BIRT iHub requires to log the user into Information Console. SampleIPSE.json contains the mapping between the user name and password that the user logs into Information Console with, and the user name and password that BIRT iHub recognizes as valid for this user.
246 Integrating Applications into BIRT iHub In SampleRSSE.json, the Default Volume users are Administrator, user1, and user2. In SampleIPSE.json, the same Default Volume users are Admin, a1, and a2. The IPSE example driver uses the capitalized user names in SampleIPSE.json as keys. Each user has the following properties in SampleIPSE.json, as shown in Listing 13-2:
■ name The user name that BIRT iHub recognizes. SampleRSSE.json contains all the information about the user having the name this property specifies. The RSSE example driver passes this user name to BIRT iHub.
■ authName The user name that IPSE recognizes. This is the user name with which the user logs in to Information Console.
■ authPassword The password for the user that authName specifies. This is the password with which the user logs in to Information Console. For example, Default Volume user a1 in SampleIPSE.json maps to Default Volume user user1 in SampleRSSE.json. Listing 13-2 Viewing SampleIPSE.json
{ "DEFAULT VOLUME": { "name": "Default Volume", "users": { "ADMIN": { "name": "Administrator", "authName": "Admin", "authPassword": "pass" }, "A1": { "name": "user1", "authName": "a1", "authPassword": "1" }, "A2": { "name": "user2", "authName": "a2", "authPassword": "2" } } }, "VOLUME1": { "name": "Volume1", "users": {
Chapter 13, Using Java Report Server Security Extension and iPortal Security "ADMIN": { "name": "Administrator", "authName": "Admin", "authPassword": "pass" }, "B1": { "name": "user1", "authName": "b1", "authPassword": "1" }, "B2": { "name": "user2", "authName": "b2", "authPassword": "2" }, "B3": { "name": "user3", "authName": "b3", "authPassword": "3" } } } } These properties are relevant only to the example. When the IPSE example driver program runs, it first reads the IPSE_EXAMPLE_HOME\src\SampleIPSE.properties file. This file contains the following configuration properties, which override default values in the example driver code. These properties are necessary only for the example IPSE implementation. A production IPSE implementation does not require them.
■ DATA_FOLDER Folder that contains the JSON-formatted data file containing the user credential to user name and password mappings.
■ JSON_STORAGE_FILE_NAME Name of the JSON-formatted data file containing the user credential to user name and password mappings.
■ LOG_FILE_NAME Name of the log file the IPSE driver creates in DATA_FOLDER. Use the log file to follow the sequence of tasks the driver program performs.
■ USE_EXTENDED_CREDENTIALS Specifies whether the IPSE driver uses extended credentials. The IPSE example driver uses extended credentials. The authenticate(...) method in the
248 Integrating Applications into BIRT iHub RSSE example driver consumes the extended credential that the IPSE example driver sends.
How to run the IPSE example 1 Download the ServerIntegrationIPSEExample-ihub-3.1 folder. This procedure refers to the location of this folder as IPSE_EXAMPLE_HOME. 2 Navigate to the IPSE_EXAMPLE_HOME\src folder and open SampleIPSE.properties. 3 Create the folder that the DATA_FOLDER path specifies. 4 Copy the file that JSON_STORAGE_FILE_NAME specifies to the folder you created in the previous step. 5 Using Windows Explorer, navigate to AC_SERVER_HOME\Jar. Copy the javaserver.jar file to IPSE_EXAMPLE_HOME\lib. 6 Open a command prompt and navigate to EXAMPLE_HOME. Execute ant. Apache Ant creates IPSE_EXAMPLE_HOME\bin\SampleIPSE.jar. 7 Copy the following files to AC_SERVER_HOME\web\iportal\WEB-INF\lib: ■ IPSE_EXAMPLE_HOME\bin\SampleIPSE.jar ■ All the files in IPSE_EXAMPLE_HOME\lib 8 Using Windows Explorer, navigate to AC_SERVER_HOME\web\iportal \WEB-INF. Open the web.xml file in a text editor. In web.xml, perform the following tasks: 1 Find the SECURITY_ADAPTER_CLASS
...
Chapter 13, Using Java Report Server Security Extension and iPortal Security Figure 13-5 Editing a cluster node 10 On Cluster Configuration, left-click Web, and choose Stop Service, as shown in Figure 13-6.
Figure 13-6 Stopping the Web service 11 Left-click the gear icon to display the Manage Cluster menu. Choose Refresh to update the status of the Web service, as shown in Figure 13-7.
Figure 13-7 Refreshing the status of the Web service
250 Integrating Applications into BIRT iHub Wait until Web turns red to go to the next step. When Web is red, the Web service is stopped. 12 Left-click Web, and choose Start Service, as shown in Figure 13-8.
Figure 13-8 Starting the Web service The example IPSE implementation program runs. The source for this program is in the following location: IPSE_EXAMPLE_HOME\src\com\actuate\ipse\example Use the following examples to explore the capability that the IPSE example implementation provides: ■ To log in as user 1 in Default Volume, open a browser, and enter the following URL in the address bar: http://localhost:8700/iportal Log in with the following credentials: ■ username: a1 ■ password: 1 You land in the Default Volume user1 home folder, /Home/user1. ■ To view files and folders in Information Console as user1 in Volume1 by using a URL to access Information Console: Enter the following URL in the browser address bar: http://localhost:8700/iportal /getfolderitems.do?userid=b1&volume=Volume1&password=1
■ To reload the data file and view files and folders as the Administrator user in Default Volume: (relevant to the example only. but this functionality is here to tell them by the way, re-read your user list. New users may have been added)
Chapter 13, Using Java Report Server Security Extension and iPortal Security Enter the following URL in the browser address bar: http://localhost:8700/iportal/getfolderitems.do?userid=admin &volume=Default%20Volume&password=pass&adminOperation=reload Using the IPSE example implementation , the Administrator user in Default Volume can reload user name and password pairs from the SampleIPSE.json file without restarting the Web service or iHub node. For information about the IPSE API methods and data types, see Actuate API Reference.
Using the OpenText Directory Services RSSE driver Using an RSSE driver, the iHub server can delegate user and identity management to the OpenText Directory Services (OTDS). The users, user groups, and associated organization dynamics maintained in OTDS are available through standard LDAP endpoints or at an application level through a REST API URL endpoint. While the iHub default LDAP connection feature can already work with OTDS, the feature is limited to authenticating a user using their username and password directly. A single sign-on (SSO) solution usually involves other authentication schemes which generally employ session-based tokens and need advanced logic to resolve properly. An RSSE driver can implement the correct logic to handle these schemes depending on the deployment environment and workflow of the web application. This OTDS RSSE driver is a base implementation of the RSSE API working against OTDS through its REST API endpoints. The driver is deployed as a J2EE web application using the Apache Axis 2 web service APIs. The HTTP-based REST API calls are made using Apache HTTP Client 4 libraries. The OTDS RSSE example already implements a method authenticating the user by name and password. Methods for token-based options need to implement the necessary logic to collect and validate tokens within the deployment environment. An RSSE driver working against OTDS requires the following components: ■ OTDS Server ■ iHub Server ■ Apache Ant ■ Eclipse IDE, for any additional implementation
252 Integrating Applications into BIRT iHub Configuring the OTDS RSSE driver Table 13-2 describes the parameters the OTDS RSSE driver uses for configuration. The location of these parameters is
Chapter 13, Using Java Report Server Security Extension and iPortal Security About the OTDS RSSE driver classes Table 13-3 describes the classes the example RSSE driver uses. Table 13-3 Cluster node service properties Class Description Comments com.opentext.rsse.otds The main class, Contains all operational .RSSEDriver deployed as the Axis2 code related to RSSE. web service. Implements the complete RSSE interface. com.opentext.rsse.otds Axis2 generates these Handle low level .RSSEInterface classes to process the operations such as com.opentext.rsse.otds RSSE API. message deserialization. .RSSEReceiverInOut com.opentext.rsse.otds A utility class for For adding or modifying .http.RestClient handling the HTTP HTTP operations. REST calls. Automatically reads and processes the OTDS cookies required to maintain a session with the OTDS REST API server. com.actuate.schemas.* Axis2 generates these These classes should not classes to process the be modified. They RSSE API (wsdl) implement the API's wsdl specifications.
Deploying the OTDS RSSE driver The OTDS RSSE driver uses the Apache Axis 2 libraries and is implemented as an Axis 2 web service, so you can deploy the driver on any web application server on which Axis 2 is already deployed. The following procedure describes deploying the driver to the iHub-embedded Tomcat.
How to deploy the OTDS RSSE driver 1 Configure the OTDS RSSE driver as needed by modifying the property values in RSSEDriver.properties, as shown in Table 13-2. 2 Open a command prompt, and navigate to the OTDS RSSE home directory. Execute ant. Apache Ant compiles the OTDS RSSE driver, creating
254 Integrating Applications into BIRT iHub 3 Create a new folder for the Apache Axis 2 web application, AC_SERVER_HOME\web\webapps\axis2. Obtain the Apache Axis 2 web application, axis2.war, and unzip it to this folder. Apache Axis2 is available at the following location: http://axis.apache.org/axis2/java/core/download.cgi 4 Copy OTDSRSSE.aar to the Axis 2 folder \axis2\WEB-INF\services. 5 Deploy Axis 2 and the OTDS RSSE driver by restarting the Web service in System Console. Restart the Web service by performing the following tasks: 1 Log in to System Console. Choose Clusters. Left-click the arrrowhead icon next to the cluster containing the iHub installation to which you downloaded Apache Axis 2, and choose Edit, as shown in Figure 13-9.
Figure 13-9 Editing a cluster node 2 On Cluster Configuration, left-click Web, and choose Stop Service, as shown in Figure 13-10.
Figure 13-10 Stopping the Web service
Chapter 13, Using Java Report Server Security Extension and iPortal Security 3 Left-click the gear icon to display the Manage Cluster menu. Choose Refresh to update the status of the Web service, as shown in Figure 13-11.
Figure 13-11 Refreshing the status of the Web service Wait until Web turns red to go to the next step. When Web is red, the Web service is stopped. 4 Left-click Web, and choose Start Service, as shown in Figure 13-12.
Figure 13-12 Starting the Web service 6 Open a new browser window. Verify that deployment was successful by going to http://localhost:8700/axis2/services/listServices. The OTDSRSSE service should be listed here. 7 In System Console, choose User Management from the side menu. In Select User Management, choose RSSE SOAP Service. Specify values for the following properties, as shown in Figure 13-13:
■ Search Cache Only Select if the frequency at which BIRT iHub refreshes user information from OTDS is low.
■ Server Name Server that hosts the OTDS RSSE application.
256 Integrating Applications into BIRT iHub ■ Port number Application server port. Accept the default value of 8700.
■ Context Path Context path for the OTDS RSSE application.
■ Cache Timeout Number of minutes that an object remains in memory before BIRT iHub refreshes the object from OTDS. Accept the default value of 1440.
. Figure 13-13 Setting RSSE SOAP service properties 8 Restart iHub for these settings to take effect. Users will now be able to login using their OTDS credentials.
Chapter 13, Using Java Report Server Security Extension and iPortal Security 258 Integrating Applications into BIRT iHub PartFive 5
Part 5Archiving BIRT iHub volume content
■ Aging and archiving volume items
Chapter 14
Chapter 14Aging and archiving volume items
This chapter contains the following topics: ■ Automating report archival and removal ■ Aging and archiving an item using the Archiving API
Chapter 14, Aging and archiving volume items 261 Automating report archival and removal Reports, folders, and other items accumulate in a volume unless you archive or remove them. Archiving is the process of placing a file in an archive directory. Aging an item means setting a limit on the length of time to retain the file before deleting it from the volume. When you set aging rules, you indicate whether to archive the item before deleting it. Expiring a file means removing it from the volume. When a file expires, the system either deletes it or places it in the archive directory, depending on the file archive rules. The Actuate Archiving API supports automating the aging and archiving processes for volume items. Autoarchiving is the process of archiving and removing items on a specific schedule, using the archive rules that you create. You set autoarchive rules when you create or update report files, folders, and job completion notices. For example, you can create a rule that removes all quarterly sales reports older than one year, or a rule that removes all successful job notifications older than ten days, or one that archives the oldest instance of a daily stock report when the volume contains more than five newer instances. The system administrator uses System Console to create the archive volume to hold the archived files. Each production volume has a single archive volume. About Actuate Online Archive Driver Archiving files and folders requires installation of an archive driver. You configure a single archive driver for a volume. When BIRT iHub archives a production volume file, BIRT iHub creates a copy of the file, then sends the copy to the Actuate archive driver. The driver creates an archive that retains the same folder structure as the production volume. Actuate Online Archive Driver is the Java application that copies an archive to another volume. This application copies expired volume files to the second volume that serves as a file archive. The archive created by the Online Archive Driver remains accessible as a folder in BIRT iHub System. The Actuate Online Archive Driver IDAPI provides a SOAP-based interface between BIRT iHub and external archive software. Configuring the Online Archive Driver The Online Archive Driver implementation supports retaining file attributes in an archive. In the XML configuration file, onlinearchive.cfg, you can specify that the archive retains any associated file attributes using the following settings: ■ RetainTimestamp Specifies whether to retain the time stamp. The default is False.
262 Integrating Applications into BIRT iHub ■ RetainOwner Specifies whether to retain the owner. The default is False. The online archive application attempts to match any user or user group in the file access control list (ACL) with the same name in the archive volume. ■ RetainPermission Specifies whether to preserve the permissions in the access control list (ACL). The default is False. If you do not archive the access control list (ACL) of a file, the file owner has full access. If the user or user group does not exist in the archive volume, you can configure the application to create a user or user group with the same name. ■ CopyDependOnFile Specifies whether to copy files that are dependent on the file being archived. The default is True. If the online archive application archives a file that has a dependency on another file, the application archives both files. The application does not delete the file on which the archived file has a dependency unless the application is archiving both files. In the configuration file, you can also specify the following options: ■ CreateUserRole Specifies whether to create missing users or user groups in the target volume in order to retain the owner or permissions. The default is True. The online archive application does not enable a login for a user or user group it creates. ■ ArchiveRoot Specifies the volume root folder for all archived files. The default is /. ■ CreateArchiveSubFolder Specifies whether to create the archive as a subfolder under the root folder that contains a time stamp. The default is True. The online archive application creates a folder in the archive volume and places the files from the archive session into the subfolder. In the archive, the archive driver creates a folder hierarchy identical to the one in the production volume and places the files in the hierarchy. The archive root folder name contains the start date and time of the archive session in the following format: YYYY_mm_dd.hh_mm_ss
Chapter 14, Aging and archiving volume items 263 For example, if you optionally specify the name of the archive root folder in the configuration file as /MyArchive and the archive session starts at 6:00 A.M. May 31, 2014, the application copies the archived files to the following folder: /MyArchive2014_05_31.06_00_00 If you set CreateArchiveSubFolder to False, the online archive application suppresses the creation of the time stamp folder and does not create the archive as a subfolder. The archive volume mimics the folder structure of the production volume. The CreateArchiveSubFolder option preserves the version numbers of the archived files by placing the archive folder in a separate root folder that has a time stamp. ■ LogLevel Specifies the level of detail in log file. Valid values are Summary, Detail, and Trace. The default is Summary. BIRT iHub installs an onlinearchive.cfg file in the following location: $AC_SERVER_HOME\shared\config where AC_SERVER_HOME represents the BIRT iHub home directory. In a typical Windows installation, where BIRT iHub was installed as an individual module, the default path of the home folder is: C:\Actuate3\BIRTiHubVisualization\modules\BIRTiHub\iHub The following example shows the onlinearchive.cfg code:
264 Integrating Applications into BIRT iHub
How to enable online archiving 1 Using System Console, create a new volume to contain the archived files for a production volume. For information on creating a volume, see “Adding a volume,” in Chapter 7, “Managing Clusters,” in the BIRT iHub System Administration Guide. 2 Stop the BIRT iHub cluster. For information on stopping the cluster, see "Taking the cluster offline," in Chapter 3, "Configuring BIRT iHub to use an alternative database on a Windows platform," or Chapter 4, "Configuring BIRT iHub to use an alternative database on a Linux platform," in the BIRT iHub System Administration Guide.
Chapter 14, Aging and archiving volume items 265 3 Navigate to the shared configuration directory. For example, if the system administrator created a folder for the shared configuration directory named config_cluster, then in a default BIRT iHub installation on Windows, where BIRT iHub was installed as an individual module, the path to the shared configuration directory is: C:\Actuate3\BIRTiHubVisualization\modules\BIRTiHub\iHub\shared \config_cluster Create a copy of the onlinearchive.cfg file. Rename the file to contain the archive volume name using the following syntax: aconlinearchive_
266 Integrating Applications into BIRT iHub installation, the name of the script is aconlinearchive.sh. BIRT iHub installs these scripts in the following location: $AC_SERVER_HOME\bin Each script configures the Java application run-time environment for the archive driver by performing the following tasks: ■ Specifies the Java Runtime Environment (JRE) by setting the environment variable, ARCHIVE_DRIVER_JRE, to the BIRT iHub default JRE specified by $AC_JRE_HOME. You can use a different JRE, but this version is the only JRE version which has been tested. ■ Specifies the class path for Online Archive Driver JAR file by setting the environment variable, DRIVER_JAR_PATH, to %AC_SERVER_HOME% \drivers. BIRT iHub installs aconlinearchive.jar, the application library, and aconlinearchiveDEP.jar, the dependent library files, in $AC_SERVER_HOME\drivers. ■ Starts the online archive service by making a call to execute the class, com.actuate.onlinearchivedriver.Main. 7 Start the BIRT iHub cluster. For information on performing this task, see "How to start the cluster," in Chapter 3, “Configuring BIRT iHub to use an alternative database on a Windows platform," or Chapter 4, "Configuring BIRT iHub to use an alternative database on a Linux platform," in the BIRT iHub System Administration Guide. Understanding aging and archiving rules for items in a volume You can set an expiration policy for a folder that affects all items in that folder. Alternatively, you can set the policy for an individual report. An item ages and expires according to a set of rules you apply to the item itself, to the folder that contains it, or to the entire volume. The following aging and archiving rules apply to volume items: ■ Volume archiving rules apply to every folder in the volume, including subfolders. By default, the production volume archives files and folders once a day. The system administrator can change this default setting to specify when and how often to archive files and folders. ■ Folder archiving rules apply to the entire hierarchy of reports in the folder, unless subfolders also have age or date properties. ■ Subfolder archiving rules supersede age or date properties of folders higher in the hierarchy. ■ A rule for a file overrides a rule inherited from the folder that contains the file.
Chapter 14, Aging and archiving volume items 267 ■ Folder aging and archiving properties specify the file type to which those properties apply. You can specify file types explicitly or use default values. ■ The aging process does not remove folders during archival, only their contents. ■ Archive rules determine whether the system ages dependent files along with the original files. Understanding precedence in archiving The autoarchive rule for a file takes precedence, if the file has a rule. If a file does not have an autoarchive rule, Actuate applies the next available autoarchive rule in the following order of precedence: ■ The file autoarchive rules take precedence. ■ If the file has no autoarchive rules, the system applies the rules for the file type. You set file type rules for at the folder level, so the system looks for the file type rules in the file folder hierarchy. ■ If there are no rules for a file type in the file folder hierarchy, the system applies the general autoarchive rule for folders in the file’s folder hierarchy. ■ If there are no general autoarchive rules for folders in the file folder hierarchy, the system applies the production volume settings.
Aging and archiving an item using the Archiving API Archiving and aging rules apply to BIRT reports, third-party reports, folders, and job notifications. Using the Archiving API, an application developer can create, update, view, and remove autoarchive rules for these items. A developer also can set autoarchive rules for all the files in a volume or for a particular file or file type. A user running the application must have delete and write privileges to modify autoarchive settings. Setting and updating autoarchive rules Use the following Archiving API operations to set autoarchive rules programmatically: ■ SubmitJob and UpdateFile To set archive rules when you use SubmitJob, set one or more elements of ArchiveRule.
268 Integrating Applications into BIRT iHub To add or update autoarchive rules for an existing file or folder, use the SetArchiveRules, AddArchiveRules, or RemoveArchiveRules suboperations of UpdateFile. Each of these suboperations has an ArchiveRule element. You can set the following elements of ArchiveRule, described in Table 14-1. Table 14-1 ArchiveRule elements Element Description ArchiveOnExpiration True if you want to archive the file before the system deletes it. ExpirationAge The number of minutes before expiration. If you set ExpirationAge, you cannot set ExpirationTime. ExpirationTime The time of day for the expiration. If you set ExpirationTime, you cannot set ExpirationAge. ExpireDependentFiles True if dependent files expire with the original file. FileType The file type to which the rule applies. To set the rule for a folder and its subfolders, specify Directory. InheritedFrom The source of an inherited rule. IsInherited True if the item inherits archiving rules. If this element is True, the system ignores all other elements except FileType. NeverExpire True if the file does not have an expiration date or expiration age. If this element is True, the system ignores ExpirationAge and ExpirationTime.
■ UpdateJobSchedule Use the SetParameters suboperation to change the autoarchive rules for the job output file. You can change the following archive-related elements of SetParameters, described in Table 14-2. Table 14-2 Archive-related elements of SetParameters Element Description ArchiveOnExpire True if you want to archive the file before the system deletes it ArchiveRuleInherited Indicates whether the job output file inherits archive rules ExpirationAge The number of minutes before the output file expires ExpirationDate The date on which the output file expires NeverExpire True if the file does not have an expiration date or expiration age
■ UpdateVolumeProperties Use the SetAutoArchiveSchedules suboperation to update the autoarchive schedule details for the volume.
Chapter 14, Aging and archiving volume items 269 Setting default autoarchive rules when creating a folder Use CreateFolder followed by UpdateFile to set autoarchive rules for a folder when you create the folder. In UpdateFile, set the ArchiveRule element of SetArchiveRules. In the following example, FileType $$$ indicates that the file is a folder. The autoarchive rules you set in the request apply to all file types in the folder except those that already have archive rules. When NeverExpire is False, you must set either an expiration date or an expiration age. Express the expiration age in minutes.
270 Integrating Applications into BIRT iHub
Chapter 14, Aging and archiving volume items 271 Updating autoarchive rules for a job output file Use UpdateJobSchedule to change autoarchive rules for the output of a job when you update the job schedule. For example, you can change rules about using the inherited archive policy for the document’s file type, about deleting the output, or about archiving the document before deletion. The following example updates the autoarchive rules for inheritance, expiration age, and whether to archive the file at expiration:
Updating the autoarchive rules for a file type in a folder or volume Use UpdateFile to change the default autoarchive rules for a file type in a folder or volume. Indicate the file type in the ArchiveRule element. In the NameList element, specify the folder to which the new rules apply. In the following example, the new rules apply to all files with the .rpt extension in the Inventory folder, unless individual files of that type already have autoarchive rules. Express the expiration age in minutes.
272 Integrating Applications into BIRT iHub
Setting an autoarchive schedule when updating a volume Use UpdateVolumeProperties and change properties of SetAutoArchiveSchedules to change a volume’s autoarchive schedule.
Chapter 14, Aging and archiving volume items 273 As with other Administrate operations, the response to this request is empty when the operation succeeds. If the request fails, the response is an error message. Starting an archive process for a volume Use ExecuteVolumeCommand and set the StartArchive command to start archiving the items in a volume.
Retrieving autoarchive rules for a file or folder Use GetFileDetails to retrieve the autoarchive rules for a file or folder. Identify the file, then specify ArchiveRules as a string in ResultDef, as shown in the following example:
274 Integrating Applications into BIRT iHub
Setting job notice expiration for all users Use the DefaultSuccessNoticeExpiration and DefaultFailureNoticeExpiration elements of Volume to set the job notice expiration attribute for all users whose notice expiration is not set or is set to 0. You can set the expiration time for a success notice or a failure notice when you create or update a volume. Express the expiration time in minutes. In the following example, the volume properties are updated to set the default success notices to expire in three days and default failure notices to never expire. These expiration rules apply to all users whose respective notice expiration is not set or is set to 0.
Chapter 14, Aging and archiving volume items 275
Setting job notice expiration for a user Use the User element of CreateUser to set the user job notice expiration attribute. You can set the expiration time for a success notice or a failure notice when you create or update a user. Express the expiration time in minutes. If you do not set the expiration time or set it to 0, the value specified for all users applies. To set the user notices to never expire, set the value to 0xffffffff. In the following example, the user success notices expire in three days and failure notices never expire:
276 Integrating Applications into BIRT iHub PartSix6
Part 6Using Actuate REST API in an application
■ Understanding the Actuate REST API
Chapter 15
Chapter 15Understanding the Actuate REST API
This chapter contains the following topics: ■ Accessing Actuate BIRT iHub content using the Actuate REST API ■ Deploying the iHub REST service ■ Integrating REST API and JSAPI into an application ■ Using REST API resources
Chapter 15, Understanding the Actuate REST API 279 Accessing Actuate BIRT iHub content using the Actuate REST API The Actuate REST API accesses and manages dynamic data built using Actuate BIRT technology and generates new documents for deployment. Use the REST API to deliver BIRT content and data from BIRT iHub to any mobile or web application. Using the REST API, you can: ■ Retrieve data from a BIRT document or BIRT data object for integration into other applications. ■ Build rich visualizations by integrating REST API with Actuate JavaScript API (JSAPI). ■ Build new visualization documents based on user interaction. ■ Convert a visualization into Adobe PDF or Microsoft Excel formats for download and deployment. ■ Schedule generation of new visualizations. ■ Upload files to and download files from an iHub volume. ■ Retrieve iHub volume folder and file information. Additionally, an administrator user can use the REST API to: ■ Create and modify users and user groups. ■ Control access to files and data by assigning user and group privileges. This chapter provides tutorials on using the REST API on a jQuery JavaScript platform. Java-based examples are available on github at the following location: https://github.com/ActuateBIRT/ServerIntegrationRESTAPIExample
Working with Actuate REST API The Actuate REST API is a resource extension that responds to RESTful requests. This REST API adheres to a set of principles, which constitute a strategy for developing web and mobile components that are platform- and language- independent. These REST API applications require very little time to implement and use minimal client and server resources. The REST API employs uniform resource identifiers (URIs) to convey user requests to the iHub System. URIs access iHub functionality including generating and storing reports, browsing volume contents, extracting data from files and data sources, and managing users and credentials. Applications use the REST API to send requests to the REST service, which runs on a Node.js platform. The REST server module interprets REST requests and
280 Integrating Applications into BIRT iHub forwards them as SOAP requests to a BIRT iHub node for action on a specified volume, as shown in Figure 15-1.
BIRT iHub UI REST REST Cluster App Service volume
SOAP BIRT iHub node Mobile REST REST App Service volume SOAP BIRT iHub node
Custom REST REST volume App Service
Figure 15-1 REST API tiered architecture The REST API integrates content into any web or mobile application that can connect to an Actuate BIRT iHub volume. User accounts and user groups control access to BIRT iHub resources in the volume. The volume organizes content into files and folders and controls access privileges for different users and user groups. BIRT iHub also generates new visualizations using application and report designs created by BIRT designers. You can use the Actuate REST API to access all of these features using any programming languages or tools that support REST. To view interactive visualizations, such as filtering, drill-down, and dashboards, pass information from the REST API to Actuate JSAPI, as described in Part 7, “Using Actuate JavaScript API in an application.” Using the interactive documentation Interactive documentation for REST API operations is installed with iHub and is accessible at the following URL: http://
Chapter 15, Understanding the Actuate REST API 281
Figure 15-2 REST API interactive documentation start page
How to use the interactive documentation The interactive documentation provides an interface to run and test REST API resources without writing an application. Use the following steps to try out these resources. 1 Open the interactive documentation in a browser by navigating to the following URL, replacing
282 Integrating Applications into BIRT iHub Figure 15-3 Interactive documentation login resource 4 Choose Try it out! The request and response information appear, as shown in Figure 15-4.
Figure 15-4 POST login output
Chapter 15, Understanding the Actuate REST API 283 5 Copy the AuthId value to the authId field in the top navigation bar, as shown in Figure 15-5.
Figure 15-5 Preparing the AuthId field for update The authId value is set in the HTTP headers and will be in the request messages for all resources. The authId does not appear in the authId parameter in the resources, but it is set in the HTTP headers. Trying out other resources uses this identifier. 6 To change the default volume and locale, type in the top navigation bar’s targetVolume and locale boxes. These fields set the associated HTTP headers, targetVolume and locale for all API requests in the session. 7 For any resource, type values in the required fields, which have descriptions in bold text. If desired, type values in optional fields, which have descriptions in plain text. Then choose Try it out! The request and response information for the resource appear. For example, expand folders and GET /folders. In search, type: app* Choose Try it out! The response shows information about the Applications folder as shown in the following lines: { "ItemList": { "File": [ { "Id": "800000000000", "Name": "Applications", "FileType": "Directory", "PageCount": "0", "Size": "0" } ] }, "TotalCount": "1" }
How to customize the location of interactive documentation To change the location, context root, and port numbers of the interactive documentation to match your environment, perform the following steps. 1 Open the following file in a text editor:
284 Integrating Applications into BIRT iHub 2 Locate the following lines: var url=""; if(location.protocol === "https:") url = "https://"+location.hostname+":5010/ihub/v1/api-docs"; else url = "http://"+location.hostname+":5000/ihub/v1/api-docs"; 3 To set the context root of the REST service, change ihub to the new context name in both lines starting with: url = To set the port numbers of the REST service, change 5000 and 5010 to the required HTTP and HTTPS port numbers respectively. If the REST service uses a proxy, change the url value to use the name of the proxy. For example, to use a context root of marcom and ports 1234 and 2234, change the lines to the following code: var url=""; if(location.protocol === "https:") url = "https://"+location.hostname+":1234/marcom/v1/api- docs"; else url = "http://"+location.hostname+":2234/marcom/v1/api-docs"; 4 Save and close the file. UTF-8 encoding iHub uses UTF-8 encoding. When creating HTTP requests for a REST API application, specify UTF-8 encoding support. For example, to set UTF-8 encoding support in the HTTP header for a POST request, include charset=utf-8 in the content-type field, as shown in the following code: POST /ihub/v1/folders HTTP/1.1 Host: myserver.mycompanyname.com:5000 Content-Type: application/x-www-form-urlencoded; charset=utf-8 When creating application code for a REST API application, provide UTF-8 encoding support using the language-specific content type settings. Using a special character in a REST request REST API requests use encoding for characters that a browser can misinterpret. The following example uses hexadecimal encoding in the body of the REST API request to rename a folder to a new path in the default volume:
Chapter 15, Understanding the Actuate REST API 285 PUT /ihub/v1/folders/340000000100 HTTP/1.1 Host: myserver.mycompanyname.com:5000 Content-Type: application/x-www-form-urlencoded AuthId:
286 Integrating Applications into BIRT iHub Table 15-1 Encoding sequences for use in URIs Character Encoded character substitution underscore (_) %5f
Using AuthId, Locale, and TargetVolume parameters All Actuate REST API resources except POST login use the authId URL parameter. All Actuate REST API resources use locale and targetVolume URL parameters. The HTTP header for all Actuate REST API resources provides equivalent fields for these parameters. To avoid re-use of URLs to access iHub information, use the HTTP header fields rather than URL parameters to send these values to iHub. The AuthId header field is equivalent to the authId URL parameter. In any request, you can set the value of the AuthId field in the HTTP header to the AuthId value returned by the POST login resource. The Locale header field is equivalent to the locale URL parameter. The locale value specifies a locale code, assigning a language and country to format values to match localized conventions. The format of the locale value is a two-letter language code and a two-letter country code separated by an underscore. The default value is set in the constants.js configuration file. Java defines the language and country codes. The TargetVolume header field is equivalent to the targetVolume URL parameter. The target volume value sets the name of the iHub volume to which to make requests. The default value is set in the constants.js configuration file. Using search functionality REST API requests that return a list of resources from iHub, such as /files, /folders, /jobs, /bookmarks, /users, or /usergroups, accept a search query parameter. The search value limits the results to those resources with a name that matches the specific search value. To search for names with a substring or character, use wildcard characters. For example, a search value of 'ab*' returns a resource with the name absolutevalues but not resources with the names databank or bankstatements. About privileges Privileges control the visibility and actions available to users for specific files and folders. By default, all privileges are denied. To grant privileges, a user or user group must appear in the access control list (ACL) for a file or folder. The privileges granted are listed in the Permission property of the ACL. Available privileges are Delete, Execute, Grant, Read, Secure Read, View, and Write. The Administrator user and Administrators user group have all privileges for every file and folder in the volume, even though the Administrator user and
Chapter 15, Understanding the Actuate REST API 287 Administrators user group do not appear in every ACL. Every user is a member of the All user group. If the All user group provides access to a file or folder in a volume, every user of that volume receives that access. About response codes All REST API requests respond with a standard set of HTTP response codes that identify the results of the request. The standard set of response codes for the Actuate REST API are as follows: ■ 200: Successful deletion, cancellation, retrieval of content, and updates to existing resources ■ 201: Successful creation of new resources ■ 304: Failure to update a resource or a duplicate request ■ 400: Failure to complete a request, including no privilege to perform requested operation or an incorrect value format for a parameter ■ 401: Failure to delete a resource ■ 404: Failure to find a resource The body of the response includes more information in the case of an error. For example, the following response is for a GET folders/{folderId} request that specifies a non-existent identifier: { "error": { "description": "The specified item ID does not exist in the Encyclopedia volume : 123456789012.", "parameters": "123456789012", "code": "3073", "message": "getFileDetails failed" } }
Fetching a large number of items REST API requests that return a list of resources from iHub, such as /files, /folders, /jobs, /users, or /usergroups, accept a fetchSize query parameter that limits the number of items to return at one time. When fetchSize is not specified, lists return the number of entries set in the FETCHSIZE configuration parameter in the constants.js configuration file. The number of items found is available from the TotalCount field in the response object. When the TotalCount exceeds the fetchSize, the response object also includes a fetchHandle field that provides access to the next set of data from the returned list. For example, if fetchSize is set to 1, and the total number of users found is 28, a GET users request using a fetchSize of 1 returns the following response object:
288 Integrating Applications into BIRT iHub HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 { "Users": { "User": [ { "Id": "100000000000", "Name": "Administrator", "Description": {}, "EmailAddress": {}, "HomeFolder": "/Home/administrator" }] }, "FetchHandle": "RklMRU9SRk9MREVSICx8IHRydWUgLHwgKiAsfHwgMDoxMDowOjAgLHwgKiAs fHwgMDoxOjA6MA==", "TotalCount": "28" } To request the next user from the list, use a second request for users and include the fetchHandle as the only query parameter in the request, similar to the following: GET /ihub/v1/users?fetchHandle=RklMRU9SRk9MREVSICx8IHRydWUgLHw gKiAsfHwgMDoxMDowOjAgLHwgKiAsfHwgMDoxOjA6MA== HTTP/1.1 host: myserver.mycompanyname.com:5000 AuthId:
Chapter 15, Understanding the Actuate REST API 289 If the REST service is deployed on a different machine, open a command window and navigate to the RESTAPI\server folder. To start the REST service, type the following command and press Enter: node app.js To stop the service, press Ctrl+C.
How to use System Console to control the REST service 1 Using a browser, navigate to System Console. The default URL is: http://
How to use Windows services to control the REST service 1 In the Windows Start menu, type Services. In the list that appears, select Services. 2 Select Actuate iHub 3.1 Service. Choose Action➛Stop. The service, including the REST service, stops. 3 Select Actuate iHub 3.1 Service. Choose Action➛Start. The service, including the REST service, starts. Configuring the REST API using constants.js You can configure the behavior of REST API resources by editing the constants.js configuration file. Constants.js is installed with iHub in the following path:
290 Integrating Applications into BIRT iHub Table 15-2 lists and describes the parameters in the constants.js configuration file. Table 15-2 Parameters in constants.js Parameter Description AUTH_ID_ String. Reserved. The default value is authId. HEADER CLUSTER_ Integer. The number of additional Node.js worker processes to use for WORKERS the REST service. The default value is -1, which uses a single master process and no additional worker processes. ENABLE_DOCS Boolean. Enables interactive documentation. The default value is true. FETCHSIZE Integer. The default number of entries to return for a GET request that returns a list, such as /files, /folders, /users, and /usergroups. The fetchSize parameter for these requests overrides this value. The default value is 10. GLOBALAGENT JSON string. The number of sockets and listeners to use for the REST service. To improve the performance of the REST service, increase these values. Monitor the system to check the results of the changes. The maximum number of sockets to use is dependent on the operating system. Increasing the number of listeners above 40 has no effect. The default values are: { MAXSOCKETS:15, MAXLISTENERS: 15 } HOST_NAME String. The iHub host name, which can be an IP address or a host and domain name. The default value is the full name of the server on which iHub is installed. For example: myserver.mycompanyname.com HTTPS_CERT_ String. The path to the HTTPS certificate. By default, the REST API uses LOCATION the iHub HTTPS certificate. The default value is:
Chapter 15, Understanding the Actuate REST API 291 Table 15-2 Parameters in constants.js (continued) Parameter Description LOCALE String. Localizes content, such as currency and time format, to a particular country and language as defined by Java. The default value is en_US. LOG_LEVEL String. The level of detail to send as messages about REST server activity to the logs\app.log file. Valid values are defined by the java.util.logging.Level class. The default value is INFO. SCOPE String. The context root to use for the REST API. To use interactive documentation for a non-default value of SCOPE, you must also change a configuration file, as described in “How to set up the REST service on a separate Windows node or machine.” The default value is ihub. TARGETVOLUME String. The default iHub volume for REST API requests. The targetVolume parameter in the HTTP header overrides this value. The default value is Default Volume. URIPATHS JSON string. Reserved. The default value is: { LOGIN: "/login", FOLDERS: "/folders", FILES: "/files", USERS: "/users", USERGROUPS: "/usergroups", DATAOBJECT: "/dataobject", VISUALS: "/visuals", JOBS:"/jobs" } USEHTTPS Boolean. True enables HTTPS support. False disables HTTPS support. The default value is false. VERSION String. Reserved. The default value is v1. WSDL_PATH String. The path to the WSDL definition for the axis service. The default value is:
Deploying the iHub REST service The iHub installation includes the iHub REST service, which runs by default. You can deploy the iHub REST service on a separate node or machine from iHub. A web browser can send REST requests to iHub using the separate REST service or the REST service installed with iHub, as shown in Figure 15-6.
292 Integrating Applications into BIRT iHub Port 5000 Separate Web for HTTP Port 8000 REST iHub browser Port 5010 service for HTTPS
Port 5000 REST for HTTP service Web browser Port 5010 for HTTPS Figure 15-6 Embedded and separate REST deployments
How to set up the REST service on a separate Windows node or machine To deploy the iHub REST service on a separate machine, perform the following steps. 1 Copy the RESTAPI directory and its contents from a machine on which iHub is installed to the separate node or machine. This directory is located in the following path:
❏ Set the value of the HOST_NAME parameter to the host name server where the REST service is deployed. ❏ Set the value of LOG_FILE to the name of a file to which the REST application has write access. ❏ Set the value of TMP_DIR to the name of a folder to which the REST application has write access. ❏ To support HTTPS, set the values of HTTPS_CERT_LOCATION and HTTPS_KEY_LOCATION to the certificate and key files respectively and set the value of USEHTTPS to true. 3 Save and close constants.js. constants.js then looks like the example in the following code:
Chapter 15, Understanding the Actuate REST API 293 module.exports = Object.freeze({ WSDL_PATH: "C:/myserver/iHub/RESTAPI/server/wsdl.xml", HOST_NAME: "myserver.mycompanyname.com", HTTP_PORT: 5000, HTTPS_PORT: 5010, LOG_FILE: 'C:/myserver/iHub/RESTAPI/server/logs/app.log', HTTPS_CERT_LOCATION: "C:/myserver/shared/config /credentials/birtihub.crt", HTTPS_KEY_LOCATION: "C:/myserver/shared/config /credentials/birtihub.key", TMP_DIR: "C:/myserver/iHub/RESTAPI/server/tmp/", ... 3 Update configuration settings in the wsdl.xml configuration file located at: RESTAPI/server 1 Use a text editor to open the wsdl.xml configuration file. 2 Locate the definition of the ActuateAPI service, which starts with the following line:
294 Integrating Applications into BIRT iHub
How to start the REST service on a separate Windows node or machine To enable the service to respond to REST requests, start the server component using the node command. 1 Append the folder containing the node executable file to the PATH environment variable: 1 From the Windows Start menu, choose Control Panel. 2 Choose System. 3 In System, choose Advanced System Settings. 4 In System Properties, choose Advanced. 5 Choose Environment Variables. 6 In System Variables, select Path. Choose Edit. 7 In Edit System Variable, at the end of the existing Variable value, type a semi-colon (;) followed by the path to the RESTAPI\NodeJS folder. For example, type the following text: ;C:\myApps\RESTAPI\server\NodeJS In Edit System Variable, choose OK. In Environment Variables, choose OK. 2 Open a command window and navigate to the RESTAPI\server folder. 3 Type the following command and then press Enter: node app.js The REST server starts and receives HTTP requests on TCP port 5000 and HTTPS requests on TCP port 5010. The REST server forwards requests to TCP port 8000 on the iHub server. 4 On Windows, to provide access to the REST API from another system, use the Windows Firewall advanced settings to open the ports 5000 and 5010 to TCP inbound traffic.
Chapter 15, Understanding the Actuate REST API 295 Integrating REST API and JSAPI into an application The REST API supports creating a visualization from a report design based on user input. Available formats for the visualization are Adobe PDF, Microsoft Excel, and BIRT report document. A specific viewer opens each visualization type. Typically, the browser opens PDF files in a PDF viewer and Excel spreadsheets in Microsoft Excel. To open and interact with a report document, an application uses Actuate JavaScript API (JSAPI). To access the JSAPI viewer, deploy the HTML page using REST API and JSAPI code to an application server. JSAPI provides the viewer, which supports report navigation and interactivity, as the actuate.Viewer class, as shown in Figure 15-7.
Figure 15-7 Report document in the JSAPI viewer The REST API provides a report document to a JSAPI viewer using two supported methods:
■ REST API accesses an existing report document in the iHub volume. REST API passes the full path of the report document to the JSAPI viewer. Use the following JSAPI syntax to view the temporary report document in the BIRT viewer: viewer.setReportName( "
296 Integrating Applications into BIRT iHub ■ REST API executes a report design immediately, creating a temporary report document. The POST visuals/{visualId}/execute REST API resource creates a temporary report document. The response includes an object ID number and a connection handle to access the temporary file. The iHub volume locates the temporary report document in a folder used only for these documents. Use the following JSAPI syntax to view the temporary report document in the BIRT viewer: viewer.setReportDocument( "/$$$Transient/
Using REST API resources Actuate provides REST API resources using the HTTP protocol. To make a request, use a REST-enabled markup or platform to form requests containing the following elements: ■ An HTTP method. One of GET, POST, PUT, or DELETE. ■ A resource identifier. ■ One or more parameters. For a GET request, query parameters, or for any other request, a correctly formatted input object. Actuate REST API summary Table 15-3 lists the REST API resources and the operations associated with the HTTP methods used by each resource.
Chapter 15, Understanding the Actuate REST API 297 Table 15-3 REST API resource and method quick reference Supported HTTP Resource Methods Description login POST Returns an authentication identifier and an authentication token folders GET, POST Returns a list of folders or creates a new folder folders/
298 Integrating Applications into BIRT iHub Table 15-3 REST API resource and method quick reference Supported HTTP Resource Methods Description visuals/
The following sections provide an overview of each set of resources and an example of using each resource as a curl command. The curl examples use Windows-format system variables for the REST API host server and the authentication identifier, AuthId. To use these examples on a Linux system, change the %variable% format to $variable. The curl examples demonstrate the use of the HTTP header for the authentication identifier. To use the --user parameter in the curl command, append a colon (:) character to the AuthId value. Actuate REST API syntax The first part of a REST API URI consists of the web server, context root, and port number of the REST server. The default web server is the machine on which BIRT iHub is installed. The default port is 5000. To create an HTTPS request, use port 5010. The second part of a REST URI has the following syntax:
Chapter 15, Understanding the Actuate REST API 299 /ihub/v1/
■ /ihub/v1 is the default context root and directory for REST API resources. ■
Getting authentication credentials Authentication is a standard security measure that verifies the identity of any users requesting access to server resources by requiring a user name and password. AuthId is an authentication identifier passed back from iHub after successful authentication and is required for all subsequent REST API requests. A REST API authentication identifier is valid for use on the same system and user agent only. Opening a REST API application on a different browser or other user agent requires a new AuthId. The Actuate JavaScript API (JSAPI) uses AuthId to receive a visualization from the REST API for presentation. JSAPI must receive the AuthId value within 10 minutes of its generation. To generate the AuthId value, use a POST request for the POST login resource and a username parameter. Other parameters for /login are optional. POST login This HTTPS POST request example sends the administrator credentials to iHub for authentication on the Volume1 volume: POST /ihub/v1/login HTTP/1.1 host: myserver.mycompanyname.com:5010 content-type: application/x-www-form-urlencoded; charset=utf-8 locale: en_US targetVolume: Volume1 username=Administrator&password=password
300 Integrating Applications into BIRT iHub This curl POST request example sends the administrator credentials to iHub for authentication on the default volume: curl -i https://%RESTHost%:5010/ihub/v1/login -d username=Administrator -d password=password
Tutorial 2: Logging in to an iHub volume The REST standard supports platform- and language-independent development. This tutorial and following ones in this chapter use JavaScript, JQuery, and HTML to describe basic implementation details. JQuery is a JavaScript extension library supported by most web browsers and several mobile application platforms. To use the Actuate REST API, the client must create well-formed REST requests using the HTTP protocol. The application uses JQuery JavaScript libraries and classes to form HTTP REST requests and parse iHub responses. Task 1: Prepare the HTML web page In this task, you create a BIRT application, which contains a file, index.html. Alternatively, create an HTML file using a different IDE. 1 Open BIRT Designer Professional. 2 Choose File➛New➛BIRT Project. New BIRT Project appears. 3 In Project Name, type a name for the project, such as REST App Project. Select Blank Project. Choose Finish. The new project appears in Navigator. 4 In Navigator, expand the project that you just created. Double-click index.html. The file opens in the layout editor. The file contains one line of HTML code, similar to the following heading:
REST App Project
5 Create html and body elements around the heading line, as shown in the following code:
REST App Project
6 Inside the html element, above the body element, create a head element with a meta tag to specify the UTF-8 character set, similar to the following lines:
Chapter 15, Understanding the Actuate REST API 301
...Task 2: Load the jQuery libraries To use jQuery in a web page, download the jQuery source libraries and stylesheets. Then, reference these resources in the script. Alternatively, use explicit links to jQuery on the web. 1 If you do not already have jQuery installed on your system: 1 Download the latest release of jquery.js from the following location: http://jquery.com/download/ 2 Copy the jquery-
302 Integrating Applications into BIRT iHub Task 3: Create a login script The Actuate REST API /login resource uses username and password values to authenticate a client session with iHub. The response from a login request is either success or failure, and successful requests include an authId string which is required for all other Actuate REST API requests. This example accesses only the User.Name and authId fields of the response data. You can access additional information using other fields by name. 1 Inside the body element, create nested div elements to assign values to the user name and password variables using HTML text input fields. Use the jQuery function in the body element’s onLoad attribute to clear the input field values. Prepare login and reset buttons.
REST App Project
password:
Chapter 15, Understanding the Actuate REST API 303 username = $( this ).val( ); }); // handle password field change $( '#input_password' ).keyup( function( ) { password = $( this ).val( ); }); 4 Write jQuery script to move the username and password values into the loginacc object when the user presses the login button. Assign an empty string to the password if the user does not provide a password, as shown in the following code: // process login button $( '#login' ).click( function( ){ if(password){ loginacc = { 'username':username, 'password':password } } else { loginacc = { 'username':username, 'password':'' } }; }); The administrator user in the default iHub volume has an empty password. 5 Before the closing }) line of script, write jQuery script to make a request to iHub and parse the response. The Actuate REST API accepts requests in JSON format using utf-8 encoding. Use the JSON.stringify( ) function to format the loginacc variable. An AJAX POST request sends the correctly formatted information as a login request. Set the URL attribute of the request to the resource URL for login. In the AJAX request, include a success function that saves the authId and a failure function that provides a message to the user and clears the input fields, as shown in the following code: $.ajax({ type: 'POST', data: JSON.stringify( loginacc ), url: uriLogin, contentType: 'application/json; charset=utf-8', dataType: 'json', success: function( data ) { authId = data.AuthId; $( '#output').html( "Login success
User : " + data.User.Name + "
authId: " + data.AuthId );
304 Integrating Applications into BIRT iHub }, error: function() { $( '#output').html( "Login failure
User : " + username ); $( 'input:text' ).val(""); } }); 6 Add the following function to clear all the page content: function resetAll() { $( 'input:text' ).val( "" ); $( '#output' ).empty( ); } 7 Save and run the HTML file: 1 Choose File➛Save. 2 Copy this file into a web application deployed to a web server. Then, type the URL of the page into a web browser. Alternatively, double-click the file in Windows Explorer. In username, type: Administrator 3 Choose Login. The login form appears as shown in Figure 15-8.
Figure 15-8 Logging in to iHub using the REST API 8 Copy the HTML file to login.html. Later tutorials use this file as a starting position. The complete code for this example is provided in Listing 15-1. Copy and paste this code into a text editor to create the complete example. To run the example, change mymachine to the fully qualified domain name of your REST API server.
Chapter 15, Understanding the Actuate REST API 305 Listing 15-1 An Actuate REST API sample login page using JQuery
REST App Project
password:
Managing folders A folder is a file system container for other files and folders in a volume. The iHub system identifies a folder by a folder ID number, which is unique on each volume. The REST API uses file ID numbers for most requests. Users have explicit privileges to different folders. The /folders resource provides users access to files and folders, enables them to add, modify, or remove folders, and allows
Chapter 15, Understanding the Actuate REST API 307 them to change folder privileges. iHub restricts these abilities based on a user’s privileges and access rights. The following sections provide an example of using each folders resource as a curl command and detailed information about the response returned by the resource. GET folders This example requests the list of files and folders in the root folder of the volume, returning two items per response: GET /ihub/v1/folders?fetchSize=2 HTTP/1.1 Host: myserver.mycompanyname.com:5000 AuthId:
GET folders/{folderId} This example requests the details for the folder with the folder ID 640000000100: GET /ihub/v1/folders/640000000100 HTTP/1.1 Host: myserver.mycompanyname.com:5000 AuthId:
GET folders/{folderId}/items This example requests the contents of the folder with the folder ID 640000000100 using the HTTPS protocol: GET /ihub/v1/folders/640000000100/items HTTP/1.1 Host: myserver.mycompanyname.com:5010 AuthId=
308 Integrating Applications into BIRT iHub GET folders/{folderId}/privileges The following URI requests the privileges assigned to folder ID 340000000100 when accompanied by a GET method: GET /ihub/v1/folders/340000000100/privileges HTTP/1.1 Host: myserver.mycompanyname.com:5010 AuthId=
POST folders/{folderId}/privileges The following HTTP request changes the privileges on the folder with folder ID 340000000100 for the mrfox user and the dahl user group: POST /ihub/v1/folders/340000000100/privileges HTTP/1.1 Host: myserver.mycompanyname.com:5000 Content-Type: application/json; charset=utf-8 AuthId:
POST folders This HTTP POST request example creates a new subfolder called Customers in the folder with the folder ID 340000000100: POST /ihub/v1/folders HTTP/1.1 Host: myserver.mycompanyname.com:5000 content-type: application/x-www-form-urlencoded; charset=utf-8 AuthId:
Chapter 15, Understanding the Actuate REST API 309 This curl POST request example creates a subfolder named Customers in the folder with the folder ID 340000000100 of the default volume: curl -i http://%RESTHost%:5000/ihub/v1/folders -X POST -H "AuthId:%RESTAuthId%" -d name=Customers -d parentFolderId=340000000100 -d description="Customer files"
DELETE folders/{folderId} This example deletes the folder with the folder ID 70000000100: DELETE /ihub/v1/folders/70000000100 HTTP/1.1 Host: myserver.mycompanyname.com:5000 Content-Type: application/json AuthId:
PUT folders/{folderId} The following HTTP request changes the name and path of the folder with folder ID 340000000100 to /Public/Application1: PUT /ihub/v1/folders/340000000100 HTTP/1.1 Host: myserver.mycompanyname.com:5000 Content-Type: application/x-www-form-urlencoded authId=
Managing files The /files resource accesses and controls files and file permissions. A file is stored on a volume, and contains data and visualizations for the iHub system. A unique file ID number assigned by the iHub system identifies each file. Files include report designs, raw and formatted documents, and BIRT data objects. The /files resource can also upload and download files to and from a volume. The following sections provide an example of using each files resource as a curl command.
310 Integrating Applications into BIRT iHub GET files This example requests the list of files that are not directories in the root directory of the volume: GET /ihub/v1/files HTTP/1.1 Host: myserver.mycompanyname.com:5000 AuthId:
GET files/{fileId} This example requests the details for the file with the file ID 640000000100: GET /ihub/v1/files/640000000100 HTTP/1.1 Host: myserver.mycompanyname.com:5000 AuthId:
DELETE files/{fileId} This example deletes the file with the file ID 860000000100: DELETE /ihub/v1/files/860000000100 HTTP/1.1 Host: myserver.mycompanyname.com:5000 Content-Type: application/json AuthId:
Chapter 15, Understanding the Actuate REST API 311 GET files/{fileId}/privileges This example returns the privileges assigned to file ID 640000000100: GET /ihub/v1/files/640000000100/privileges HTTP/1.1 Host: myserver.mycompanyname.com:5000 AuthId:
GET files/{fileId}/download This example downloads the content of the file with the file ID 640000000100 without base-64 encoding: GET /ihub/v1/files/640000000100/download?base64Encode=false HTTP /1.1 Host: myserver.mycompanyname.com:5000 AuthId:
POST files/{file}/upload The following HTTP request uploads the file Sales-Reps.rptdesign to the /Sales folder and replaces the existing file: POST /ihub/v1/files/Sales-Reps.rptdesign/upload HTTP/1.1 Host: myserver.mycompanyname.com:5000 AuthId:
312 Integrating Applications into BIRT iHub
PUT files/{fileId} The following HTTPS request changes the name of the file with file ID 640000000100 to /Public/Application1/Shipped Orders.rptdesign: PUT /ihub/v1/folders/640000000100 HTTP/1.1 Host: myserver.mycompanyname.com:5010 Content-Type: application/x-www-form-urlencoded AuthId:
Chapter 15, Understanding the Actuate REST API 313 This curl PUT request example changes the name and path of the file with the file ID 640000000100 to /Public/Application1/Shipped Orders.rptdesign in the default volume: curl -i http://%RESTHost%:5010/ihub/v1/files/640000000100 -X PUT -H "AuthId:%RESTAuthId%" -d newName=/Public/Application1 /Shipped%20Orders.rptdesign
POST files/{fileId}/privileges The following HTTP request changes the privileges for the file with file ID 640000000100: POST /ihub/v1/files/6400000000100/privileges HTTP/1.1 Host: myserver.mycompanyname.com:5000 Content-Type: application/json; charset=utf-8 AuthId:
Tutorial 3: Managing files and folders This tutorial shows how to access files and folders in an iHub volume and get details about these items. The resources for this task require an authId as an input parameter. The previous tutorial showed how to get an authId value. Task 1: Get the available folders Request the list of folders in the root directory in an iHub volume using the GET folders resource. For jQuery, form this request using a getJSON object. Parse the response object for the TotalCount field, which is the number of folders in the root directory. Then, create an HTML formatted string to display the number of folders in the output div. 1 Using BIRT Designer Professional, open the HTML file that you created in Tutorial 2: Logging in to an iHub volume.
314 Integrating Applications into BIRT iHub 2 Add a getfolders button after the definition of the login and reset buttons in the logintab div element, as shown in the following code:
3 After the definition of uriLogin, create a new variable for the path to the folders resource: var uriFolders = 'http://mymachine:5000/ihub/v1/folders'; 4 After the code that processes the login button click, add code to process the getfolders button click. Add the following functions to run the GET folders resource request and display the output: // Process get folders button $( '#getfolders' ).click( function(){ getFolderList()}); function getFolderList() { var request = uriFolders + '?authId=' + authId; $.getJSON(request, function(data) { buildFolderList(data)}); } function buildFolderList( data ) { $( '#output' ).html( "Found " + data.TotalCount + " folders.
" ); $.each( data.ItemList.File, function( i, item ) { $( '#output' ).append( item.Name + '
' ); }); } 5 Save and run the HTML file: 1 Choose File➛Save. 2 Copy this file into a web application deployed to a web server. Then, type the URL of the page into a web browser. Alternatively, double-click the file in Windows Explorer. In username, type: Administrator 3 Choose Login. Choose Get folder list. The list of files appears as shown in Figure 15-9. Task 2: Get details of an individual folder Create a selection list of the folders. Get the contents of the folder. Then, get its access control list. 1 Create the selection list of folders: 1 Add a label and a selection list after the definition of the getfolders button in the logintab div element, as shown in the following code:
Chapter 15, Understanding the Actuate REST API 315
Figure 15-9 Listing folders in the root folder using the REST API 2 Create a variable to hold the list of folders. Populate the selection list in the code that processes the getfolders button click, as shown in the following code: var folderIdArray = new Array(); function buildFolderList( data ) { $( '#output' ).html( "Found " + data.TotalCount + " folders.
" ); $( "#folderDropdownList" ).empty(); $.each( data.ItemList.File, function( i, item ) { $( '#output' ).append( item.Name + '
' ); folderIdArray[i] = item.Id; $( "" ).appendTo( "#folderDropdownList" ); }); }; 3 Add the following code to the resetAll( ) method to clear the folder list: $( "#folderDropdownList" ).val( -1 ); 4 Save and run the file, as in the previous task. Choose Get folder list. The selection list appears as shown in Figure 15-10. 2 Retrieve and display the contents of the folder: 1 After the code that processes the getfolders button click, handle selecting a value from the selection list, as shown in the following code:
316 Integrating Applications into BIRT iHub var folderIndex = 0; // Handle folder field change $( '#folderDropdownList' ).change( function() { folderIndex = $( this ).val(); });
Figure 15-10 Preparing to select folders using the REST API 2 Add a getfolderdetails button after the definition of the selection list in the logintab div element, as shown in the following code:
3 After the code that processes the selection from the list, add the following code to process the getfolderdetails button click: // Process get folder details button $( '#getfolderdetails' ).click( function(){ getFolderItems(); }); 4 After the function that builds the folder list, add the following functions to run the GET folders/{folderId}/items resource and display an ordered list of the folder contents: function getFolderItems() { var request = uriFolders + '/' + folderIdArray[folderIndex] + '/items?authId=' + authId; $.getJSON( request, function( data ) { buildFolderItemsList( data )}); } function buildFolderItemsList( data ) { if( JSON.stringify( data.ItemList ) === '{}' ){
Chapter 15, Understanding the Actuate REST API 317 $( '#output' ).html( "No items in folder.
" ); }else{ $( '#output' ).html( "Items in folder:
" ).append( $( '
- ' )); $.each( data.ItemList.File, function( i, item ){ $( '#output ol' ).append( $( '
- ' ).text( item.Name )); }); } } 5 Save and run the file, as in the previous task. The list of files appears as shown in Figure 15-11.
Figure 15-11 Displaying folder contents using the REST API 3 Retrieve and display the access control list of the folder: 1 After the existing div element, add the following code to create a new div to display the list of privileges for the folder:
318 Integrating Applications into BIRT iHub function buildFolderPrivs( data ) { $( 'ul' ).empty( ); $('p').html( "The folder " + data.File.Name + " was last modified on " + data.File.TimeStamp + "
" + data.File.Name + " has the following privileges:
" ); if( JSON.stringify( data.ACL ) === '{}' ){ $( 'p' ).append( "Access Control List is empty! Administrator access only.
" ); }else{ $.each( data.ACL.Permission, function( i, item ) { $( 'ul' ).append( $( ' - ' ).text(( item.UserName ? "User " + item.UserName : item.RoleName ? "User Group " + item.RoleName : '' ) + ": " + item.AccessRight )); }); } } 3 Add the following code to the resetAll( ) method to clear the privileges text and list: $( "p" ).empty(); $( "ul" ).empty(); 4 Save and run the file, as in Step 2. Select a folder from the list. Choose Get folder details. The folder details appear as shown in Figure 15-12.
Figure 15-12 Displaying folder details on iHub using the REST API
Chapter 15, Understanding the Actuate REST API 319 Task 3: Get details of the files in the selected folder If the folder contains any files, get the file size. 1 After the definition of uriFolders, create a new variable for the path to the files resource: var uriFiles = 'http://mymachine:5000/ihub/v1/files'; 2 In the buildFolderItemsList( ) function, test whether each item in the folder is a directory. Change the following line: $( '#output ol' ).append( $( '
- ' ).text( item.Name )); to: if( item.FileType === 'Directory' ){ $( '#output ol' ).append( $( '
- ' ).text( item.Name + " - a Directory" )); } 3 In the buildFolderItemsList( ) function, run a files command to find the size of an item that is not a directory. After the code you added in the previous step, add the following else clause: else{ var request = uriFiles + '/' + item.Id + '?authId=' + authId; $.getJSON( request, function( data ) { $( '#output ol' ).append( $( '
- ' ).text( item.Name + " Size: " + data.File.Size )); }); } 4 Save and run the file, as in Task 2: Get details of an individual folder. Select a folder from the list. Choose Get folder details. The folder and file details appear as shown in Figure 15-13.
Figure 15-13 Displaying file details on iHub using the REST API
320 Integrating Applications into BIRT iHub A complete set of code for this example is provided in Listing 15-2. Copy and paste this code into a text editor to create the complete example. To run the example, change mymachine to the fully qualified domain name of your REST API server. Listing 15-2 An Actuate REST API sample folder access page using JQuery
REST App Project
username:
password:
324 Integrating Applications into BIRT iHub Using visualizations Visualizations display data from BIRT documents and BIRT data objects. The REST API accesses visualizations using the /visuals resource. The /visuals resource can export visualizations to documents and spreadsheets for download, or access them directly for web and mobile applications. You can also access the data displayed in a visualization and pass that data to another application. Accessing the data provides the application developer with the ability to present the data visually in any required format. Most visuals requests use a unique file ID number obtained by the /files and /folders resources to access RPTDESIGN or RPTDOCUMENT files. Requests that use the /visuals resource can generate content from dynamic data sources, schedule recurring jobs, and convert a report document to different file formats. The /visuals resource can access the contents of a rich visualization including formatted data, bookmarked objects, and parameters. The /visuals resource can also create more rich visualizations from existing executables on a scheduled or immediate basis. The following sections provide an example of using each visuals resource as a curl command and detailed information about the response returned by the resource. GET visuals/{visualId}/bookmarks The following URI requests the bookmarks from the file with file ID 580000000100 when accompanied by a GET method: GET /ihub/v1/visuals/580000000100/bookmarks HTTP/1.1 Host: myserver.mycompanyname.com:5000 AuthId:
This curl example requests the bookmarks from the file with the file ID 580000000100 in the default volume: curl -i http://%RESTHost%:5000/ihub/v1/visuals/580000000100 /bookmarks -H "AuthId:%RESTAuthId%" GET visuals/{visualId}/bookmarks/{bookmarkName} The following URI requests the content referenced by the bookmark Revenue Table from the file with file ID 580000000100 when accompanied by a GET method: GET /ihub/v1/visuals/580000000100/bookmarks/Revenue%20Table HTTP /1.1 Host: myserver.mycompanyname.com:5000 AuthId:
Chapter 15, Understanding the Actuate REST API 325 This curl example requests content referenced by the bookmark Revenue Table from the file with the file ID 580000000100 in the default volume: curl -i http://%RESTHost%:5000/ihub/v1/visuals/580000000100 /bookmarks/Revenue%20Table -H "AuthId:%RESTAuthId%"
GET visuals/{visualId}/datasets The following URI requests the datasets from the file with file ID 650000000100 when accompanied by a GET method: GET /ihub/v1/visuals/650000000100/datasets HTTP/1.1 Host: myserver.mycompanyname.com:5000 AuthId:
This curl example requests the datasets from the file with the file ID 650000000100 in the default volume: curl -i http://%RESTHost%:5000/ihub/v1/visuals/650000000100 /datasets -H "AuthId:%RESTAuthId%" GET visuals/{visualId}/datasets/{datasetName} The following URI requests the Employee Information data set from the file with file ID 650000000100 when accompanied by a GET method: GET /ihub/v1/visuals/650000000100/datasets/Employee%20Information HTTP/1.1 Host: myserver.mycompanyname.com:5000 AuthId:
This curl example requests the Employee Information data set from the file with the file ID 650000000100 in the default volume: curl -i http://%RESTHost%:5000/ihub/v1/visuals/20100000100 /datasets/Employee%20Information -H "AuthId:%RESTAuthId%" POST visuals/{visualId}/execute This example sends a request to iHub to run the report design with the file ID 100000000100 and save the document to /Sales/myOutput.rptdocument: POST /ihub/v1/visuals/100000000100/execute?saveOutputFile=true HTTP/1.1 Host: myserver.mycompanyname.com:5000 Content-Type: application/x-www-form-urlencoded authId=
&saveOutputFile=True&requestedOutputFile=/Sales /myOutput.rptdocument¶mValues={ "ParameterValue" : [{"Name" : "param1","Value": "3"},{"Name" : "param2","Value": "33"},{"Name" : "param3","Value": "331"},{"Name" : "parama","Value": "32"},{"Name" : "paramb","Value": "321"}]} 326 Integrating Applications into BIRT iHub This curl example sends a POST request to iHub to run the report design with the file ID 100000000100 and save the document to /Sales/myOutput.rptdocument in the default volume: curl -i http://%RESTHost%:5000/ihub/v1/visuals/100000000100 /execute -X POST -H "AuthId:%RESTAuthId%" -d saveOutputFile=true -d requestedOutputFile=/Sales/ myOutput.rptdocument -d paramValues={ \"ParameterValue\" : [{\ "Name\" : \"param1\", \"Value\": \"3\"},{\"Name\" : \"param2\",\"Value\": \"33\"}, {\"Name\" : \"param3\",\"Value\": \"331\"},{\"Name\" : \"parama\",\"Value\": \"32\"},{\"Name\" : \"paramb\",\"Value\": \"321\"}]}
POST visuals/{visualId}/schedule/now This example sends a request to iHub to run a low priority job to convert the report document with the file ID 640000000100 to the output file name /Sales/Sales Analysis.pdf: POST /ihub/v1/visuals/640000000100/schedule/now HTTP/1.1 Host: myserver.mycompanyname.com:5000 Content-Type: application/x-www-form-urlencoded authId=
&fileType=rptdocument&outputFileName=/Sales /Sales%20Analysis&outputFileFormat=pdf&priority=100 This curl example sends a POST request to iHub run a job to convert the report document with the file ID 640000000100 to a PDF file in the default volume: curl -i http://%RESTHost%:5000/ihub/v1/visuals/640000000100 /schedule/now -X POST -H "AuthId:%RESTAuthId%" -d fileType=rptdocument -d outputFileName="/Sales /Sales Analysis" -d outputFileFormat=pdf -d priority=100 POST visuals/{visualId}/schedule/once This example sends a request to iHub to schedule a report job to run the report design identified by the file ID number 640000000100 once at 8:45 p.m. exactly: POST /ihub/v1/visuals/640000000100/schedule/once HTTP/1.1 Host: localhost.com:5000 Content-Type: application/x-www-form-urlencoded authId=
&priority=1000&fileType=rptdesign&outputFileName= crosstab&outputFileFormat=rptdocument&scheduleTime=20%3A45%3A00 This curl example sends a POST request to iHub to run the report design with the file ID 640000000100 as a job at 8:45 p.m. on the current day and save the output as a rptdocument file in the default volume: Chapter 15, Understanding the Actuate REST API 327 curl -i http://%RESTHost%:5000/ihub/v1/visuals/640000000100 /schedule/once -X POST -H "AuthId:%RESTAuthId%" -d fileType=rptdesign -d outputFileName="crosstab" -d outputFileFormat=rptdocument -d scheduleTime="20:45:00"
POST visuals/{visualId}/schedule/recurring This example sends a request to iHub to run the report design with the file ID 640000000100 every week on Monday and Thursday at midnight from January 1, 2014 to December 31, 2014: POST /ihub/v1/visuals/640000000100/schedule/recurring HTTP/1.1 Host: myserver.mycompanyname.com:5000 Content-Type: application/x-www-form-urlencoded AuthId:
fileType=rptdesign&outputFileName=/Sales /Revenue%20History%20by%20Product%20Line&outputFileFormat= RPTDOCUMENT&frequency=Weekly&scheduleDay="Mon,Thu"&scheduleTime =00%3A00%3A00&startDate=2014-01-01&endDate=2014-12-31 This curl example sends a POST request to iHub to run the report design with the file ID 640000000100 as a job at midnight every Monday and Thursday from January 1, 2014 through December 31, 2014 and save the output as a .rptdocument file in the default volume: curl -i http://%RESTHost%:5000/ihub/v1/visuals/640000000100 /schedule/recurring -X POST -H "AuthId:%RESTAuthId%" -d fileType=rptdesign -d outputFileName="/Sales/Revenue History by Product Line" -d outputFileFormat=RPTDOCUMENT -d frequency ="Weekly" -d scheduleDay="Mon,Thu" -d scheduleTime="00:00:00" -d startDate=2014-01-01 -d endDate="2014-12-31" GET visuals/{visualId}/parameters The following URI requests the parameters from the file with file ID 940000000100 when accompanied by a GET method: GET /ihub/v1/visuals/940000000100/parameters HTTP/1.1 Host: myserver.mycompanyname.com:5000 AuthId:
This curl example requests the parameters from the file with the file ID 940000000100 in the default volume: curl -i http://%RESTHost%:5000/ihub/v1/visuals/940000000100 /parameters -H "AuthId:%RESTAuthId%" 328 Integrating Applications into BIRT iHub GET visuals/{visualId}/parameters/picklist The following URI requests the parameter picklist for the parameter pCustomer from the file with file ID 430000000100. pCustomer is in the cascading parameter group Customer Selection. The value of the preceding parameter in the group, pCountry, is Canada: GET /ihub/v1/visuals/430000000100/parameters /picklist?cascadingGroupName=Customer%20Selection¶mName= pCustomer&precedingParamValues={"ParameterValue":[{"Name": "pCountry","Value":"Canada"}]}&fileType=RPTDESIGN HTTP/1.1 Host: myserver.mycompanyname.com:5000 AuthId:
This curl example requests the parameter picklist for the parameter pCustomer from the file with the file ID 430000000100 in the default volume: curl -i http://%RESTHost%:5000/ihub/v1/visuals/430000000100/ parameters/picklist -G -H "AuthId:%RESTAuthId%" -d cascadingGroupName="Customer%20Selection" -d paramName="pCustomer" -d precedingParamValues="{ \"ParameterValue\" : [{\"Name\":\"pCountry\",\"Value\": \"Canada\"}]}" -d fileType=RPTDESIGN GET visuals/{visualId}/pdf The following URI requests a PDF of the current page from the file with file ID 580000000100: GET /ihub/v1/visuals/580000000100/pdf HTTP/1.1 Host: myserver.mycompanyname.com:5000 AuthId:
This curl example requests a PDF of the current page from the file with the file ID 580000000100 in the default volume: curl -i http://%RESTHost%:5000/ihub/v1/visuals/580000000100/pdf -H "AuthId:%RESTAuthId%" GET visuals/{visualId}/xlsx The following URI requests an Excel spreadsheet of the first five pages from the file with file ID 580000000100: GET /ihub/v1/visuals/580000000100/xlsx?pageRange=1-5 HTTP/1.1 Host: myserver.mycompanyname.com:5000 AuthId:
This curl example requests an Excel spreadsheet of the first five pages from the file with the file ID 580000000100 in the default volume: Chapter 15, Understanding the Actuate REST API 329 curl -i http://%RESTHost%:5000/ihub/v1/visuals/580000000100/xlsx -G -H "AuthId:%RESTAuthId%" -d pageRange="1-5"
Tutorial 4: Viewing a report using JSAPI This tutorial shows how to generate a temporary document from a report design and interact with the document by passing its details to the viewer using Actuate JavaScript API (JSAPI). Task 1: Get a list of the available report designs Recursively search the volume for report design files. You start with the HTML file that you created in Tutorial 2: Logging in to an iHub volume. 1 Using BIRT Designer Professional, open the HTML file that you created in Tutorial 2: Logging in to an iHub volume. 2 Add a getdesigns button after the definition of the login and reset buttons in the logintab div element, as shown in the following code:
3 After the definition of uriLogin, create a new variable for the path to the folders resource: var uriFolders = 'http://mymachine:5000/ihub/v1/folders'; 4 After the code that processes the login button click, add code to process the getfolders button click. Add the following functions to run the GET folders resource request recursively and display the output: // Process get designs button $( '#getdesigns' ).click( function(){ getDesignList( )}); function getDesignList( ) { $( '#output' ).empty( ); var request = uriFolders + '?authId=' + authId; $.getJSON( request, function( data ) { buildDesignList( 0, data )}); } function buildDesignList( depth, data ) { $.each( data.ItemList.File, function( i, item ) { if( item.FileType === 'Directory' ){ if ( depth >= 5 ){ $( '#output' ).append( "Too many directory levels: " + depth + " " + item.Name + "
" ); return; }else{330 Integrating Applications into BIRT iHub var request = uriFolders + '/' + item.Id + '/items?authId=' + authId; $.getJSON( request, function( data ) { buildDesignList( depth + 1, data )}); } }else if( item.FileType === 'RPTDESIGN' ){ $( '#output' ).append( item.Name + '
' ); } }); } 5 Save and run the HTML file: 1 Choose File➛Save. 2 Copy this file into a web application deployed to a web server. Then, type the URL of the page into a web browser. Alternatively, double-click the file in Windows Explorer. In username, type: Administrator 3 Choose Login. Choose Get report designs. The list of files appears as shown in Figure 15-14.Figure 15-14 Listing report designs in the iHub volume using the REST API 6 Create and manage a drop-down list of the report designs discovered in the previous step: 1 After the definition of the getdesigns button in the HTML body, define a label and a drop-down list:
Chapter 15, Understanding the Actuate REST API 331 2 Before the getDesignList function, define some new variables: var designCount = 0; var designIdArray = new Array(); 3 In getDesignList, clear the drop-down list as well as the output div: // Clear design list and count designCount = 0; $( '#output' ).empty( ); $( '#designDropdownList' ).empty( ); 4 Replace the line that displays the report name: $( '#output' ).append( item.Name + '
' ); with lines that build the drop-down list of report names: designIdArray[designCount] = item.Id; $( "" ).appendTo( "#designDropdownList" ); designCount += 1; 5 In resetAll, clear the drop-down list as well as the input fields and output div: $( 'input:text' ).empty( ); $( '#designDropdownList' ).val( -1 ); $( '#output' ).empty( ); 7 Save and run the HTML file as in Step 5. The list of files appears as shown in Figure 15-15.Figure 15-15 Listing report designs as a drop-down list
332 Integrating Applications into BIRT iHub Task 2: Generate a temporary document from a report design Run a report design that has no parameters to generate a temporary document. 1 Add a viewreport button after the drop-down list for report designs. Set the text to "Run report", as shown in the following code: 2 After the definition of uriFolders, create a new variable for the path to the visuals resource: var uriVisuals = 'http://mymachine:5000/ihub/v1/visuals'; 3 After the code that processes the get designs button and before the getDesignList function, add code to process any change to the value of the new drop-down list and process the viewreport button: var designIndex = 0; // Handle design field change $( '#designDropdownList' ).change( function() { designIndex = $( this ).val(); }); // Process view report button $( '#viewreport' ).click( function(){ checkParameters( designIdArray[designIndex] ); }); 4 After the buildDesignList function, add code to run the report after checking that the report design has no parameters. The checkParameters( ) function runs a visuals parameters query and passes the result to the runReport( ) function. In runReport( ), for a report design that has no parameters, jQuery script makes an AJAX POST request to iHub and parses the response. The success function displays a message showing the report document name and the connection handle. The failure function displays a message that the report execution failed, as shown in the following code: function checkParameters( reportId ) { // Check for parameters var request = uriVisuals + '/' + reportId + '/ parameters?authId=' + authId; $.getJSON( request, function( data ) { runReport( reportId, data )}); } function runReport( reportId, data ) { $( '#output' ).empty( ); if( JSON.stringify( data ) === '{}' ){ var request = uriVisuals + '/' + reportId + '/execute?authId=' + authId;
Chapter 15, Understanding the Actuate REST API 333 // Execute the report $.ajax({ type: 'POST', url: request, success: function( data ) { $( '#output').html( "Created report document: " + data.ObjectId + ".rptdocument
Connection handle: " + data.ConnectionHandle ); }, error: function() { $( '#output').html( "Failed to execute report
Id: " + reportId ); } }); }else{ $( '#output' ).html( 'This design has parameters. Id: ' + reportId ); } } 5 Save and run the HTML file as in Task 1: Get a list of the available report designs. The result of running a report that has no parameters appears as shown in Figure 15-16.Figure 15-16 Executing a report successfully using the REST API Task 3: View the document using JSAPI Connect to a JSAPI server on an Information Console application that can access the iHub volume that contains the report designs. Set up the JSAPI viewer module and open the temporary document in the report viewer. 1 In the HTML header element, define the path to JSAPI, which is jsapi in the Information Console application, as shown in the following line:
334 Integrating Applications into BIRT iHub 2 Change the text of the viewreport button to "View report", as shown in the following code: 3 After the definition of uriVisuals, create a new variable for the path to Information Console: var iportalUrl = 'http://mymachine:8700/iportal'; 4 Set up the JSAPI environment and load the JSAPI viewer module when the login request succeeds: 1 Call the acLoad( ) function when the login succeeds. Navigate to the success function of the $.ajax call that executes uriLogin. After the assignment of the authId variable, replace the line that displays the "Login success" message with the following lines: // Load JSAPI viewer module acLoad( ); 2 Before the checkParameters( ) function, create the acLoad( ) function, which performs the following tasks: ❏ Loads the JSAPI viewer module ❏ Sets the repository type for the iHub volume ❏ Specifies the URI to the iHub server ❏ Specifies the volume to use ❏ Uses the authId returned by the login request as the authentication credentials for the JSAPI session ❏ Submits the session specification to JSAPI The following lines show a sample implementation of these items: function acLoad( ) { actuate.load( "viewer" ); var reqOps = new actuate.RequestOptions( ); reqOps.setRepositoryType( actuate.RequestOptions.REPOSITORY_ENCYCLOPEDIA ); reqOps.setIServerUrl( "http://mymachine:8000" ); reqOps.setVolumeProfile( "Default Volume" ); reqOps.setRESTAuthToken( authId ); actuate.initialize(iportalUrl, reqOps, null, null, JSAPILoaded, JSAPINotLoaded ); }
Chapter 15, Understanding the Actuate REST API 335 3 Create success and failure functions for the JSAPI submit request. These functions display appropriate messages in the output div, as shown in the following code: function JSAPILoaded( ) { $( '#output').html( "JSAPI viewer module loaded" ); } function JSAPINotLoaded( exception ) { $( '#output').html( "JSAPI viewer module not loaded b>" ); alert( "Your application encountered an exception: \n" + exception.getMessage( )); } 5 In the runReport( ) function, replace the code that displays the report name and connection handle with code to open the JSAPI viewer, which performs the following tasks: ■ Configures a browser panel that provides scrolling functionality to the report viewer ■ Sets the size of the viewer in pixels ■ Specifies the document in the transient report folder to view and the connection handle ■ Submits the request to the JSAPI viewer The code looks similar to the following lines: var panel = new actuate.viewer.BrowserPanel( ); var uiConfig = new actuate.viewer.UIConfig( ); uiConfig.setContentPanel( panel ); myviewer = new actuate.Viewer( "viewerpane", uiConfig ); myviewer.setSize( 1000, 800 ); myviewer.setReportDocument( "/$$$Transient/" + data.ObjectId + ".rptdocument", data.ConnectionHandle ); myviewer.submit( ); 6 Set up the viewerpane div element that contains the report viewer: 1 After the definition of the output div element, create the viewerpane div element, as shown in the following code: 2 In the resetAll( ) function, add the following line to clear the viewerpane element: $( '#viewerpane' ).empty( ); 7 Save the HTML file and deploy it to an application server. For example, copy the file to the folder that contains the default Information Console application:
336 Integrating Applications into BIRT iHub C:\Actuate3\BIRTiHubVisualization\modules\BIRTiHub\iHub\web \iportal 8 Type a URI that runs the file deployed in the previous step. Use the server name, not localhost for an application server on the local machine. For example, the URI for a file in the default Information Console application looks like: http://mymachine:8700/iportal/ViewReport.html The result of viewing a report that has no parameters looks similar to the page shown in Figure 15-17.
Figure 15-17 Viewing a transient report using the REST API and JSAPI
Chapter 15, Understanding the Actuate REST API 337 A complete set of code for this example is provided in Listing 15-3. Copy and paste this code into a text editor to create the complete example. To run the example, change mymachine to the fully qualified domain name of your REST API server. Listing 15-3 An Actuate REST API sample JSAPI report viewer page using JQuery
REST App Project
username:
password: