Ad Hoc Launcher Java API

This section describes functionality that can be restricted by the software license for JasperReports Server. If you don’t see some of the options described in this section, your license may prohibit you from using them. To find out what you're licensed to use, or to upgrade your license, contact Jaspersoft.

When users want to create a new view in the Ad Hoc Editor, they are normally presented with a page that allows them to choose the Topic, Domain, or OLAP client connections that will form the basis of the view. The selected Topic or Domain provides a query and a list of fields that can be used in the new view.

The Ad Hoc Launcher API allows a developer to replace the Source dialog with an alternative user interface for selecting data. This replacement for the Source dialog is referred to as an Ad Hoc launcher because the user can launch the Ad Hoc Editor interface after selecting and setting up the data. Whereas the Source dialog can only give users a choice of the queries previously stored in the repository, an Ad Hoc launcher implementation enables them to have full control over the data source, query, and fields to be used. This gives developers a wide latitude for creating data selection interfaces tailored to the needs of their users.

Creating an Ad Hoc launcher involves modifying the JasperReports Server web application by adding one or more servlet pages that gather user input for the setup required by the Ad Hoc Editor. When the user is ready to start laying out the view, the Ad Hoc launcher starts up the Ad Hoc Editor by redirecting to its URL.

Examples of possible Ad Hoc launcher applications include the following:

A generic SQL query builder which allows the user to choose a JDBC data source, view the tables available from it, and build a query against one or more of the tables. This approach is demonstrated in browseDB, the sample Ad Hoc launcher that is described below.
A query builder based on application-specific metadata, such as a list of pre-defined queries maintained in its own table.
An interface for constructing queries against a custom data source that has metadata facilities, such as Hibernate.
A “dumb” query builder in which the user chooses a data source from the repository and enters query text and field definitions manually. This would be analogous to creating a JasperReport by editing the JRXML.

The details of the setup required in an Ad Hoc launcher are described in the next section.

Communicating with the Ad Hoc Editor using AdhocTopicMetadata

This section describes how the Ad Hoc Editor initializes its reporting data, both when a Topic is selected and when an Ad Hoc launcher is active.

The Ad Hoc Editor uses the AdhocTopicMetadata Java class to represent an Ad Hoc Topic. Topics are typically stored in the repository as ReportUnits, but they can also be created by an Ad Hoc Launcher implementation. If the user starts the Ad Hoc Editor from the Topics page, AdhocTopicMetadata is set up as follows:

1. A new instance of AdhocTopicMetadata is created.
2. The report representing the selected Topic is read.
3. AdhocTopicMetadata.initDatasource() is called with the URI of the data source used by the Topic.
4. The JRXML resource for the Topic’s report is read.
5. AdhocTopicMetadata.setQueryText() is called with the query from the JRXML.
6. AdhocTopicMetadata.setQueryLanguage() is called with the query language from the JRXML.
7. The list of fields defined in the JRXML is read.
8. Each field is turned into an AdhocField instance and passed to AdhocTopicMetadata.addField().
9. If the user is creating a new view, the desired Ad Hoc type (table, crosstab, chart) is passed to AdhocTopicMetadata.setReportType().

If an Ad Hoc launcher is being used, it needs to place an instance of AdhocTopicMetadata in the servlet session, where the Ad Hoc Editor can use it. The following code examples are from the source file from the browseDB example in A Sample Ad Hoc Launcher.

To initialize an instance of the AdhocTopicMetadata class for use by the Ad Hoc Editor:

1. Create a new AdhocTopicMetadata instance, then initialize the data source by calling initDatasource() with the URI of a data source in the repository (which in this example is coming from an HTTP request parameter). Use SessionAttributeManager to create a new client key and store the AdhocDate instance in the session:
String datasourceURI = req.getParameter(DATASOURCE_URI);
AdhocTopicMetadata data; 
long clientKey;
// if you have a datasource URI, you just started...
// so we need to init AdhocTopicMetadata and put it in session
if (datasourceURI != null) {
  data = engine.getAdhocMetadataFactory().getTopicMetadata();
  data.initDatasource(engine, datasourceURI);
  // get new client key for Ad Hoc
  clientKey = SessionAttributeManager.getInstance().createClientKey();
    AdhocConstants.ADHOC_DATA, data, clientKey, req);
} else {
  // code to handle existing view
2. Initialize the query to be used for the Topic by calling setQueryText() and setQueryLanguage():
String tableName = dbdata.getSelectedTable().getName();
StringBuffer query = new StringBuffer("select * from " + tableName);
Iterator sfi = dbdata.getSelectedTable().getFieldList().iterator();
while (sfi.hasNext()) {
  DBField f = (DBField);
  DBField jf = f.getJoinField();
  if (jf != null) {
    String fromField = f.getTable().getName() + "." + f.getName();
    String toField = jf.getTable().getName() + "." + jf.getName();
    query.append("join " + jf.getTable().getName() + 
      " on (" + fromField + " = " + toField + ")");
3. Add field definitions by creating new AdhocField instances and calling addField():
if (jf != null) {
  Iterator jtfi = jf.getTable().getFieldList().iterator();
  while (jtfi.hasNext()) {
    DBField jtf = (DBField);
    AdhocField af = new AdhocField(jtf.getName(), getJRType(jtf.getDbType()));

AdhocField instances require the following information:

Name. The name of the field (set in the AdhocField constructor, or by calling setName()).
Type. The name of the Java class representing the type of the field's data (set in the AdhocField constructor, or by calling setType()).
Display. The string used as a label for the field in the Ad Hoc Editor (set by calling setDisplay()).
4. Set the type by calling AdhocTopicMetadata.setAdhocReportType(). Valid values are table, crosstab, and chart:
String viewType = req.getParameter(AdhocAction.REPORT_TYPE);
if (viewType != null) {

Integration with JasperReports Server

You can register your launcher with the Ad Hoc Editor so that, if the user starts a view with your launcher and later saves it, the launcher can be started again when the new view is edited.

To register an Ad Hoc launcher:

1. Choose a reference name for the Ad Hoc Launcher; this example assumes the name is test.
2. Define a Spring bean that registers the launcher’s name and URI. The following shows a portion of the
<js-install>\samples\customAdHoc\webapp\WEB-INF\applicationContext-adhoc-custom.xml file:
<bean class="com.jaspersoft.jasperserver.api.common.util.spring.GenericBeanUpdater">
  <property name="definition" ref="setCustomAdhocProps"/>
  <property name="key" value="test"/>
  <property name="valueType" value="idRefMap"/>
  <property name="value">
    <idref bean="sampleAdHocLauncher"/>
<util:map id="sampleAdHocLauncher">
  <entry key="editorURI" value="browseDB/browseDB.html?action=displayTables"/>

In this example, note the property named key with the value test; this element defines the name described in step 1.

3. Before you launch the Ad Hoc Editor, call AdhocTopicMetadata.setCustomType()with the name used to register the application.
AdhocTopicMetadata data = (AdhocTopicMetadata) 
  AdhocConstants.ADHOC_DATA, req);

The launcher can also be used to store custom data in a saved Ad Hoc view, so that when you relaunch the view, you can retrieve the data conveniently. The data is persisted as a byte stream resource in the Ad Hoc view.

To store data in a view:

1. Create an implementation of CustomAdhocDataHandler, which tells the Ad Hoc Editor how to create, serialize, and deserialize the object you want to persist.
2. Call AdhocTopicMetadata.setCustomDataHandler() with an instance of your implementation:
data.setCustomDataHandler(new BrowseDBDataHandler());
BrowseDBData dbdata = (BrowseDBData) data.getCustomData();
3. Call AdhocTopicMetadata.getCustomData() to access your custom data object.