Difference between revisions of "BIRT/FAQ/Scripting"

From Eclipsepedia

< BIRT‎ | FAQ
Jump to: navigation, search
(Added where to put classes for scripted data source)
(Q: Where do I have to put my classes in order to access them by JavaScript?)
 
(14 intermediate revisions by 7 users not shown)
Line 1: Line 1:
Back to [[BIRT/FAQ|BIRT FAQ Index]]
+
{{Backlink|BIRT/FAQ}}
 +
 
 
== Aggregates (Totals) ==
 
== Aggregates (Totals) ==
 
=== Q: What aggregate operations does BIRT support? ===
 
=== Q: What aggregate operations does BIRT support? ===
Line 5: Line 6:
 
"Aggregate" is the fancy word to describe totals. BIRT supports a wide variety of totals: sum, running sum, average, minimum, maximum, count, count distinct, and many more. See the ROM Scripting Specification for details.
 
"Aggregate" is the fancy word to describe totals. BIRT supports a wide variety of totals: sum, running sum, average, minimum, maximum, count, count distinct, and many more. See the ROM Scripting Specification for details.
  
=== Q: Is it possible to use cell.setProperty( ) to set the width of cells? ===
 
  
Answered by Stanley Wang
 
You can not set column width dynamically for now. Runtime scripting is limited to property access and data-manipulations for this release. More will come in BIRT 2.0.
 
  
 
=== Q: Does BIRT support look-ahead (two-pass) aggregates? ===
 
=== Q: Does BIRT support look-ahead (two-pass) aggregates? ===
Line 22: Line 20:
 
TBD
 
TBD
  
=== Q: Does BIRT support page totals? ===
 
  
Some reports may want to display totals over data displayed on a page of the report. For example, a count of employees on that page, and sum of their salaries.
 
 
BIRT release 1.0 delivers reports as a single web page, so the question is moot for this release. BIRT reports are paginated when printed as PDF, but BIRT uses Apache FOP to do the formatting, and so BIRT does not have visiblity into the pagination.
 
 
That said, if there is sufficient interest, the BIRT team will consider page totals for a future release.
 
  
 
== Scripting ==
 
== Scripting ==
Line 64: Line 56:
  
 
Suppose our logic is in a Java package called com.company.AppLogic. We'd import it into JavaScript as follows:
 
Suppose our logic is in a Java package called com.company.AppLogic. We'd import it into JavaScript as follows:
  importPackage( "com.company.AppLogic" );
+
  importPackage( Packages.com.company.AppLogic );
 
   
 
   
importPackage is not suported in BIRT 1.0, so the previous line will not work: To use outside packages, you will need to use the fully qualified name of the object var abc;
+
Let's assume that MyClass is a class within the AppLogic package, and it provides business logic for working with, say, customer orders:
abc = new Packages.com.company.AppLogic();
+
+
The report's initialize method is the best place to put the import. Then, we can access objects and methods as if they were JavaScript objects. let's assume that MyClass is a class within the AppLogic package, and it provides business logic for working with, say, customer orders:
+
  
 
  obj = new MyClass( );
 
  obj = new MyClass( );
Line 75: Line 64:
  
 
=== Q: Where do I have to put my classes in order to access them by JavaScript? ===
 
=== Q: Where do I have to put my classes in order to access them by JavaScript? ===
With BIRT 2.1 there are several ways to include your custom classes into BIRT's scripting classpath.
+
With BIRT there are several ways to include your custom classes into BIRT's scripting classpath.
* If you are using the BIRT Designer, you have to add your classes to the classpath of the BIRT Viewer Plugin: org.eclipse.birt.report.viewer. To do this you have two choices:
+
* If you are using the BIRT Designer, create a Java Project which includes the custom classes and then set the BIRT Report project classpath in Windows-Preferences-Report Design-Classpath. Note that this classpath can be configured per project (see [http://birtworld.blogspot.com/2009/12/birt-designer-classpath-changes.html BirtWorld post]).  You can also add specific classes to a report's classpath by importing a jar containing the classes into the resource folder and then add the jar to the report in the resources tab of report properties.  If you use this approach the jar will need to be in the resource folder of the deployed environment as well.
*# Put your .class files into the birt/WEB-INF/classes subfolder of the Viewer-plugin. Don't forget to apply the correct directory structure according to your package name.
+
 
*# Package your classes into one or more jar-files and put them into the birt/scriptlib subfolder of the Viewer-plugin.
+
* When using the BIRT Viewer to run reports outside the Designer, package your custom classes into a jar-file and put them into the WEB-INF/lib or in the scriptlib esubfolder of the BIRT Viewer distribution.
 +
 
 
* When using the BIRT Runtime to run reports outside the Designer, package your custom classes into a jar-file and put them into the ReportEngine/lib subfolder of the BIRT Runtime distribution.
 
* When using the BIRT Runtime to run reports outside the Designer, package your custom classes into a jar-file and put them into the ReportEngine/lib subfolder of the BIRT Runtime distribution.
 +
 +
* If using the Report Engine API set the APPCONTEXT_CLASSLOADER_KEY as shown below.
 +
 +
I think, it can use path set in projects by using:
 +
<pre>config = new EngineConfig();
 +
HashMap hm = config.getAppContext();
 +
hm.put( EngineConstants.APPCONTEXT_CLASSLOADER_KEY, MyClass.class.getClassLoader());
 +
config.setAppContext(hm); </pre>
 +
If additional classpath entries are desired when using the Report Engine API, use code similar to:
 +
<pre>
 +
System.setProperty( EngineConstants.WEBAPP_CLASSPATH_KEY, "c:/classpath/jar1.jar;c:/classpath/jar2.jar" );
 +
</pre>
 +
'''NOTE''': Note also that the new Preferences setting does not yet appear to work correctly with Classpath variables -- I had to specify the jar files as "external" and give absolute paths.  See [https://bugs.eclipse.org/bugs/show_bug.cgi?id=332056 bug 332056].
 +
 +
== Logging ==
 +
=== Q: Where can I find logs? ===
 +
When using BIRT Designer the logs can be found in the directory $ECLIPSE_HOME/plugins/org.eclipse.birt.report.viewer_version/birt/logs. The logging can be configured in  the file $ECLIPSE_HOME/plugins/org.eclipse.birt.report.viewer_version/birt/WEB-INF/web.xml, namely the properties BIRT_VIEWER_LOG_DIR and BIRT_VIEWER_LOG_LEVEL. Available values are SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST and OFF.
 +
 +
=== Q: How can I log javascript? ===
 +
You can use standard Java logging package. First initialize the Logger:
 +
<pre>importPackage(Packages.java.util.logging);
 +
var fileHandler = new FileHandler("/tmp/birt.log", true);
 +
var rootLogger = Logger.getLogger("");
 +
rootLogger.addHandler(fileHandler);</pre>
 +
and then you can log the string with <code>Logger.getAnonymousLogger().info(str);</code>
 +
 +
 +
[[Category:BIRT]]
 +
[[Category:BIRT FAQ]]

Latest revision as of 13:55, 2 June 2011

< To: BIRT/FAQ

Contents

[edit] Aggregates (Totals)

[edit] Q: What aggregate operations does BIRT support?

"Aggregate" is the fancy word to describe totals. BIRT supports a wide variety of totals: sum, running sum, average, minimum, maximum, count, count distinct, and many more. See the ROM Scripting Specification for details.


[edit] Q: Does BIRT support look-ahead (two-pass) aggregates?

Look-ahead aggregates are of the form "this value as a percentage of an overall total". For example, a customer's sales as a percentage of overall sales for a sales rep, sales region, and so on. These are often called two-pass aggregates becuase they require the reporting tool to make one pass over the data to compute totals, then another pass to compute the percentages for each record.

BIRT does provide support for such totals. Just enter the calculation and BIRT figures out the right way to compute it:

Total.percent( row.Sales, Total.sum( row.Sales ) )

[edit] Q: Is an example of simple calculations like count, sum, max, min?

TBD


[edit] Scripting

[edit] Q: Can I add custom logic (scripting) to my report?

Yes. BIRT uses JavaScript (also known as EcmaScript) for expressions, business logic, and integration with application-specific Java classes.

[edit] Q: JavaScript? Does that mean my code runs in the browser?

When someone hears "JavaScript" the assumption is that JS is being used to script a browser. While browser scripting is a key use of JS, the language itself (when separated from the browser DOM framework) is a nice little tool that is well integrated with Java. Our goal in using JS is that a report developer can very quickly write business logic. JS tends to be easier to learn than Java for people who are accustomed to Visual Basic, SQL and similar scripting solutions. Because JS is well integrated with Java, it is easy to call from business logic into Java classes to do more advanced tasks, or if you prefer, to write your code using Java. Further, JS allows BIRT to support aggregate expression such as:

sum( row.orderTotal )

This summarizes the orderTotal column over all rows. This makes aggregates look like other expressions, even though the BIRT report engine needs to "rewrite" them.

[edit] Q: Where can I learn about JavaScript?

JavaScript (also known as EcmaScript) is a popular language for browser scripting, and a wide range of books exist that describe JavaScript in that context. An excellent one is JavaScript: the Definitive Guide by David Flanagan, published by O'Reilly. This book has two sections: Core JavaScript and Client-Side JavaScript. Use the Core section a general reference for the JavaScript language independent of whether it is in a client or server. VisiBone provides a useful on-line reference.

[edit] Q: Good, but most report developers don't like to write code.

In BIRT, typical tasks should require no code. Application-specific tasks should require as little code as possible; preferably just a business expression when possible. For more complex logic, we expect a Java application developer to either create the logic, or point the report developer to existing Java code. The report developer then calls into the Java code from an expression. JavaScript allows all three:

1. Simple expressions: row.Price * row.Quantity 2. Business expressions: choose a salutation (Mr., Mrs., Ms., etc.) depending on a database code, and concatenate the salutation, first name and last name. 3. Complex logic written in Java: Compute the recommendation rating for a stock based on factors in the database, and proprietary stock-rating algorithms.

Simple tasks require no code. This includes conditional formatting (make negative numbers red, for example), data transformations (filters, sorting, totals), conditional display (hide certain fields for certain types of customers), and so on.

[edit] Accessing Java Classes

[edit] Q: Can BIRT access existing Java code or objects?

Yes. BIRT uses the Mozilla Rhino JavaScript engine which provides excellent integration with Java. See the Mozilla Rhino Scripting Java article for information about how to call Java from JavaScript.

A BIRT report developer could use JavaScript to access functionality of pre-existing Java classes that may hold significant business logic that we would like to access within the report.

Suppose our logic is in a Java package called com.company.AppLogic. We'd import it into JavaScript as follows:

importPackage( Packages.com.company.AppLogic );

Let's assume that MyClass is a class within the AppLogic package, and it provides business logic for working with, say, customer orders:

obj = new MyClass( );
result = obj.calculate( row.balance, row.dueDate );

[edit] Q: Where do I have to put my classes in order to access them by JavaScript?

With BIRT there are several ways to include your custom classes into BIRT's scripting classpath.

  • If you are using the BIRT Designer, create a Java Project which includes the custom classes and then set the BIRT Report project classpath in Windows-Preferences-Report Design-Classpath. Note that this classpath can be configured per project (see BirtWorld post). You can also add specific classes to a report's classpath by importing a jar containing the classes into the resource folder and then add the jar to the report in the resources tab of report properties. If you use this approach the jar will need to be in the resource folder of the deployed environment as well.
  • When using the BIRT Viewer to run reports outside the Designer, package your custom classes into a jar-file and put them into the WEB-INF/lib or in the scriptlib esubfolder of the BIRT Viewer distribution.
  • When using the BIRT Runtime to run reports outside the Designer, package your custom classes into a jar-file and put them into the ReportEngine/lib subfolder of the BIRT Runtime distribution.
  • If using the Report Engine API set the APPCONTEXT_CLASSLOADER_KEY as shown below.

I think, it can use path set in projects by using:

config = new EngineConfig();
HashMap hm = config.getAppContext();
hm.put( EngineConstants.APPCONTEXT_CLASSLOADER_KEY, MyClass.class.getClassLoader());
config.setAppContext(hm); 

If additional classpath entries are desired when using the Report Engine API, use code similar to:

 
System.setProperty( EngineConstants.WEBAPP_CLASSPATH_KEY, "c:/classpath/jar1.jar;c:/classpath/jar2.jar" );

NOTE: Note also that the new Preferences setting does not yet appear to work correctly with Classpath variables -- I had to specify the jar files as "external" and give absolute paths. See bug 332056.

[edit] Logging

[edit] Q: Where can I find logs?

When using BIRT Designer the logs can be found in the directory $ECLIPSE_HOME/plugins/org.eclipse.birt.report.viewer_version/birt/logs. The logging can be configured in the file $ECLIPSE_HOME/plugins/org.eclipse.birt.report.viewer_version/birt/WEB-INF/web.xml, namely the properties BIRT_VIEWER_LOG_DIR and BIRT_VIEWER_LOG_LEVEL. Available values are SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST and OFF.

[edit] Q: How can I log javascript?

You can use standard Java logging package. First initialize the Logger:

importPackage(Packages.java.util.logging);
var fileHandler = new FileHandler("/tmp/birt.log", true);
var rootLogger = Logger.getLogger("");
rootLogger.addHandler(fileHandler);

and then you can log the string with Logger.getAnonymousLogger().info(str);