Chapter 30 Using the BusinessObjects Enterprise APIs

In this chapter

Overview 766

Choosing the Right Integration Approach 766

The BusinessObjects Enterprise SDK 769

BusinessObjects Enterprise SDK Object Model 772

Querying the InfoStore 774

Report Browsing Using InfoObject Queries 790

Creating Objects and Capturing Their IDs 790

Deleting Objects 791

Scheduling Reports 792

Users and Group Management 793

Using Reports As a Datasource 793

Where to Go from Here 795

Overview

As you have seen in prior chapters, Business Objects XI is a ready-to-run web-centric enterprise reporting solution that includes a self-service portal called InfoView and, with the purchase of the Application Foundation and/or the Performance Manager suite, a more advanced dashboarding capability. InfoView runs on Java application servers or on the .NET framework and requires no coding. It can be installed and configured in less than one hour. Basic customization including changing images and stylesheets can be done with minimal effort.

With the maturing of web technology over the past several years, organizations of all sizes have invested in home-grown or commercial off-the-shelf (COTS) portals. They have dabbled with single sign-on and spent sleepless nights worrying about the appropriate presentation of corporate logos and style sheets and being concerned with other usability standards. In many of these environments, InfoView might simply not fit in out of the box. It might not look right. It might not fit into the start page you have built, or perhaps, in its full, unbridled, feature-packed glory, your users are simply confused. Less is sometimes more.

This chapter will help you integrate BusinessObjects Enterprise using the SDK.

Note

The code samples shared in this chapter are part of a white-box portal application you can download from www.usingcrystal.com. The portal is ready to run and most of the code listed here is in a single utility class, BOEUtil.java.

Choosing the Right Integration Approach

The most flexible approach to integrating BusinessObjects Enterprise XI (or its sister product, Crystal Reports Server) is to use a software development kit (SDK) for COM, .NET, or Java. The InfoView portal and portions of the Central Management Console (CMC) are built using these SDKs. By implication, the SDKs are full-featured, and this chapter is devoted to understanding them. The Unified Web Services, described in Chapter 32, “Using the Web Service’s SDK,” is also very useful especially where CORBA network connectivity is not possible. However, the Web Services SDK is not full-featured.

Before continuing down the code-from-scratch/samples road, you might want to skip ahead to Chapter 31, “Using the Web Components,” and see if any of the approaches described there are sufficient for your project. They include the ability to view, create, and edit reports simply by calling URLs; integrating components visually using Java Server Faces (JSF); or simply deploying prebuilt catalog browsing and viewing portlets into Microsoft SharePoint, WebSphere Portal, or any other JSR-168–compliant Java portal.

Before diving into the BusinessObjects Enterprise SDK, Table 30.1 enumerates each of the integration approaches and which platforms they support.

Table 30.1. SDK Platform Support

image

Table 30.2 shows the component integration approaches and the platforms they support.

Table 30.2. Component Integration Platform support

image

In addition, you will want to determine the quickest and easiest way to provide the customized functionality you desire. The CMC is the 100% zero client web-based administration console that is provided out of the box with BusinessObjects Enterprise and Crystal Reports Server. This application is used in conjunction with each of the other products. Table 30.3 is a comparison matrix to help you determine what administrative functionality you may access with no custom coding.

Table 30.3. Out-of-the-Box Capabilities Matrix

image

image

The BusinessObjects Enterprise SDK

As described in Table 30.3, the BusinessObjects Enterprise SDK provides the developer with the ability to create client and administrative applications leveraging the entire functionality of the suite. Here you’ll begin to learn how to install and use the Enterprise SDK.

Installing the Java SDK

The BusinessObjects Enterprise Java SDK consists of a set of Java classes packaged up in a set of JAR files. These JAR files can be found in the following directory:

C:Program FilesCommon FilesBusiness Objects3.0javalib

Most Java application servers have the following folder structure for web applications:

image

To make the classes contained in these JAR files available for use, copy them to the lib folder of your web application.

The naming convention for the Java SDK is almost exactly the same as the COM SDK, which makes it easy for developers working on multiple development platforms. The exception to the naming is that rather than dealing with Java objects directly, interfaces are exposed. These interfaces begin with the letter I, for instance, IEnterpriseSession, IInfoStore, and so forth.

Note

BusinessObjects Enterprise XI represents the next generation of the Crystal Enterprise 10 infrastructure. For backward compatibility, program management decided to keep “Crystal” in existing API and package names. New packages for XI will use the “BusinessObjects” namespace.

Business Objects product documentation is actually quite good. Deploying_webintelligence_applications.pdf is beneficial for deployment and customizing_webintelligence.pdf is good for general application development. Please note that not all documentation is actually installed with the product (to make for a faster and smaller footprint install); go to the docs directory on the CD to find the rest! Additionally, Java developers ought to consider consulting the COM windows Help file. This format facilitates finding information fast and the API calls are quite similar to those used in Java.

Installing the .NET SDK

Business Objects has been supporting Microsoft’s .NET development platform since its inception. BusinessObjects Enterprise XI provides full .NET support through COM interop assemblies. Fully managed .NET code is planned for future releases. This SDK is intended for use within Microsoft Visual Studio .NET but can also work in other tools, such as Borland C# Builder.

The .NET SDK consists of a set of .NET classes. Like Java, these classes are organized into namespaces. The BusinessObjects Enterprise .NET SDK is contained in the CrystalDecisions.Enterprise namespace. The naming of all the objects is exactly the same as the COM SDK; for instance, SessionMgr and EnterpriseSession. The .NET assemblies (.dll files) that make up the SDK can be found in the following folder:

Program FilesCommon FilesBusiness Objects3.0managed

Unlike Java, these files don’t need to be copied anywhere in order to be able to program with them. A developer simply needs to bring up the Project References dialog and select which assemblies he wants to use. Although there is only a single namespace, there are multiple physical DLL files. The naming convention is CrystalDecisions.Enterprise.Module.dll where Module is one of a set of modules that comprise the full Crystal Enterprise SDK. Following are the common assemblies a developer uses:

  • CrystalDecisions.Enterprise.Framework.dll
  • CrystalDecisions.Enterprise.InfoStore.dll
  • CrystalDecisions.Web.dll

CrystalDecisions.Web.dll does not conform to the naming convention of the other assemblies. This is because it is a shared component across Crystal Reports and Crystal Enterprise.

Note

The examples provided in this chapter use the Java SDK. The syntax for .NET SDK is very similar. For .NET developers, many of the snippets shown here have been translated and are available for download at www.usingcrystal.com. Before coding from scratch, .NET developers ought to investigate the .NET component libraries covered in Chapter 31 and in the excellent product documentation.

Creating an Enterprise Session

Accessing the BusinessObjects Enterprise SDK begins with the Session Manager object, SessionMgr, that returns a valid session. The user must authenticate against one or more directory services, including the default, built-in directory whose authentication plugin is called secEnterprise. When using the secEnterprise authentication plugin, user credentials (passwords) are stored as encrypted strings in users’ respective InfoObject files in the BusinessObjects Enterprise repository. Excepting secEnterprise, authentication occurs against the directory service, and users and groups flagged for replication within the CMS are replicated on-demand with corresponding objects in the BusinessObjects Enterprise repository.

  • secEntrprise—No external directory required
  • secLDAP—Customizable LDAP directory adapter
  • secNT—Under Internet Information Server (IIS)/COM/.NET, transparent Single Sign-On from the user’s Windows desktop is supported
  • secAD—Works the same way as with secNT

In step with the drive to provide transparent cross-platform Single Sign-On (SSO), BusinessObjects Enterprise XI also supports CA SiteMinder. In the future, Business Objects plans to support other vendors such as RSA ClearTrust and Tivoli WebSeal. These can be used today through simple modifications of the InfoView application using the SDK.

Additional security plugins, such as secSAP and secPeopleSoft, are installed with the various BusinessObjects Enterprise solution kits for Enterprise Resource Planning (ERP) packages.

Note

These authentication snippets, as well as other code listed or described in this chapter, can be found at www.usingcrystal.com in the Java SDK white-box portal. Authentication code is in a file called _check_authentication.jsp.

The following code logs in the user and captures her BusinessObjects Enterprise session token.

image

Enterprise sessions may also be recreated from a token created from an active session. Typically, such a token is created immediately after logging in the user, subsequently storing it in session or in a token, as shown in the following code.

image

The logon token can theoretically be used by anyone to access the BusinessObjects Enterprise system, so there are some controls on how long and how many times it can be used. The first argument is the number of seconds the token should live (here, 8 minutes) and the number of times it can be used to reinstantiate the session (here, 100 times). By keeping the EnterpriseSession in application server session memory, the logon token need not be used at all.

The following code shows how to log back onto BusinessObjects Enterprise with the token. This technique is especially useful when session management is on one platform (or application server context) and the BI application is on another. Additionally, as described in Chapter 31, this token can be used to view a document using openDocument without prompting for credentials.

IEnterpriseSession es = sm.logonWithToken(logonToken);

After a user is logged on using either the logon or logonWithToken methods, you need to persist the Enterprise Session in application server memory and then create and persist a logon token in a cookie.

Note

In your application, you might not have a logon page at all. Rather, you have some kind of SSO logic that grabs a username and/or password from the environment and uses it to create a new BusinessObjects Enterprise session. If no password is available, one work-around is to reset the users’ password with every logon attempt—thereby making entry through a backdoor impossible.

Retrieving Services

After logging on to the SessionMgr with a user credential, the current users’ EnterpriseSession object is returned. EnterpriseSession is the key that unlocks the rest of the system. From it, several services may be instantiated by calling the getService method:

  • PSServer—Crystal Page Server, the highest performance option for serving reports on demand
  • RASReportService—Crystal RAS Server, most useful for introspecting report file (parameters, for example)
  • ReportEngine—WebIntelligence Reporting Server
  • InfoStore—The BusinessObjects Enterprise repository, which is queried using the Query method, returning InfoObjects

A best practice is to retrieve and cache these services in session during the logon routine if you intend on using them more than once in your code. Otherwise, be sure to cache the service upon creation and check for it the next time as follows:

image

After you have created a BusinessObjects Enterprise session, the entire SDK is open for business. The EnterpriseSession created with the previous code exposes several useful getter methods for returning the PluginManager, the SystemInfo (which includes descriptive and diagnostic properties), and the current UserInfo (which contains the user profile and related information), as seen in the previous code sample.

BusinessObjects Enterprise SDK Object Model

As shown in Figures 30.1 and 30.2, the BusinessObjects Enterprise SDK object model describes relationships between top-level objects and methods in the system.

Figure 30.1 The BusinessObjects Enterprise SDK object model.

image

Figure 30.2 The InfoObject detail from the BusinessObjects Enterprise SDK object model.

image

In many respects BusinessObjects Enterprise is an object-oriented SDK. However, some developers will find some of the design patterns unusual. How to interact with the objects should become clear in the following pages.

Querying the InfoStore

For most everything else that cannot be invoked from the EnterpriseSession object, you need to query the InfoStore first. This includes creating objects, scheduling them, updating them, or simply retrieving them.

InfoStore objects include reports, users, groups, folders, categories, dashboards, schedules, license keys, server registrations, Universes, and Business Views—every bit of information that is presented through the portal and which the system needs to function. Regardless of type, they are all InfoObjects that implement the InfoObject interface. Every InfoObject has certain common properties, such as an ID, name, and kind. Other properties are stored as name-value pairs in a property bag datastructure.

Objects are all stored physically in the Business Objects repository database in both primitive (common properties) and composite binary fields (the rest of the bag). If you like, you can inspect the CMS_InfoObjects4 table in a database browser. The model is highly denormalized for performance. In BusinessObjects Enterprise XI, additional tables were added to speed up alias and hierarchy access associated with the inclusion of many-to-many object categorization in the design.

Note

Did you know that the original Seagate Info had more than 20 physical tables? Its successor, Crystal Enterprise 8.0, implemented a new InfoStore service that made much greater use of binary fields in the database and eliminated reliance on database-enforced referential integrity. Smart engineers in Vancouver found that performance increased considerably and that linear scalability was now attainable.

Now that you understand that certain properties are represented physically and indexed in the database and others are buried in binary fields, please forget that there is a physical database behind InfoStore. You will never access this or any of the other tables in the system directly. Rather, you will retrieve objects using an SQL-style syntax executed against an API object called the InfoStore.

The statement below returns a list of all user-names in the system. This code snippet, like others in this chapter, assumes that valid local IInfoStore (iStore) and EnterpriseSession (es) instances have been instantiated.

image

Under the covers, the Central Management Server (CMS) service sometimes runs a query against the physical tables, but more often it runs a query against in-memory datastructures it maintains as the system is used.

Note

If you want to speed up your InfoStore queries, you can put a loop in your application initialization code that requests a bunch of the objects from the InfoStore. There are obviously short-term performance implications in doing this.

The InfoStore functions much like an object-relational persistence tier with its own proprietary methods of accessing and updating objects. Here are some unusual characteristics that will help you understand some of the other examples in this chapter and the product documentation:

  • Everything is an IInfoObject—The InfoStore contains many objects of many types or classes. However, they all inherit from the common IInfoObject class that permits them to be queried and persisted in a common manner and allows them to share certain common properties and methods. Casting is the conversion of one data type to another. When retrieving an IInfoObject object, it is sometimes necessary to cast it to a more specific object type, such as IReport. At a minimum, when iterating through IInfoObjects returned by an InfoStore query, objects must be cast to an IInfoObject.
  • Creating an object with Plugins—When you create an object, you won’t find a CreateThisTypeOfObject() method in the API. Rather, you need to look up the object type in the InfoStore and first get a reference to a system object called the Plugin interface. Similarly, if you want to schedule to a destination such as e-mail, you must get a destination plugin from the InfoStore. This design is flexible, in that new object types and destinations may be added without affecting the API, but it can be awkward to use.
  • Embedded objects—Certain objects have what appear to be embedded objects. Job scheduling or report processing objects are accessed from their container objects through the SI_SCHEDULEINFO and SI_PROCESSINFO properties respectively. For instance, iStore.query("SELECT SI_SCHEDULEINFO FROM CI_INFOSTORE WHERE SI_NAME='World Sales Report'") will return each of the schedules created for the World Sales Report. Embedded objects, such as scheduling or processing information, must be cast before they can be accessed.
  • Committing changes to objects—There is, in fact, no way to commit changes to one object. Every change to an InfoStore object starts with selecting all objects that meet certain criteria, iterating through the collection, modifying one or more InfoObject, and then committing all of the originally retrieved objects to the InfoStore.

Knowing what types of objects and their properties that are available for selection and/or for filtering the InfoStore will help you understand what you can do with BusinessObjects Enterprise. These topics are covered next.

BusinessObjects Enterprise Categories, Kinds, and Casting

InfoStore objects live virtually in one of three categories which are accessed in the FROM clause of an InfoStore query. Different types of objects belong to different categories. In fact, several objects, such as Folder, belong to more than one category. In BusinessObjects Enterprise XI you no longer need to use the CI_PROGID identifier to find a certain type of object, but rather you use the more friendly CI_KIND property. Kinds can be accessed literally or through the com.crystaldecisions.sdk.plugin.CeKinds enumeration. Note that sometimes the enumerated constant is not the same as the literal value. The following query string will return no values:

image

These two, however, will work:

image

This is because the literal value "CRYSTAL_REPORT" is not a SI_KIND. However, com.

crystaldecisions.sdk.plugin.CeKinds.CRYSTAL_REPORT evaluates to 'CrystalReport'.

Tables 30.430.7 list what kinds of objects can be found in each category, as well as the interface objects to which they must be cast for all of their properties to be accessible. Certain object types specific to the Application Foundation and Performance Management suite of products are unpublished.

Table 30.4 CI_INFOOBJECTS Kinds

image

Table 30.5. CI_SYSTEMOBJECTS Kinds

image

Table 30.6. CI_APPOBJECTS Kinds

image

Table 30.7. Other Object Kinds

image

Although not shown, Folder objects can be referenced from all three table contexts.

  • CI_INFOOBJECTS—Contains portal content
  • CI_SYSTEMOBJECTS—Contains system objects required for the system to function and that are displayed and managed in the user interface
  • CI_APPOBJECTS—Other objects stored in the repository but managed through client-server tools or add-ons to the system

Several other kinds of objects require more sophisticated query statements to access. They include destination and security plugins.

BusinessObjects Enterprise Object Properties

Object properties are discussed next, organized first by common, indexed properties, and then by the types of objects or functions for which they are used. These properties can be found in the CePropertyID enumerated list and a complete list can be found in the SDK documentation itself. Usage notes are provided inline and several of the more commonly used ones will reappear in the sections and samples that follow.

Property Bags

All InfoObject properties—both indexed and nonindexed—are accessible from the object’s property bag interface, properties(). These properties are accessed with their CePropertyID identifier as shown here:

image

However, certain indexed properties have direct accessor methods as noted. For instance, getID() saves a few keystrokes on obj.properties().getProperty(CePropertyID.SI_ID).getValue(). Should you want to list everything in an IInfoObject, you could use call a function to recursively display the object property bags. This is such a useful function that it is provided in Listing 30.1 in its entirety.

Listing 30.1. Recursively Listing IInfoObject Properties

image

This function returns property objects that fall into one of three categories:

  • Top-level properties that contain values such as strings and integers
  • Composite properties that contain other properties that require casting
  • Composite properties that actually represent embedded objects with their own identifiers in the system

The SI_SCHEDINFO property, for instance, contains a collection of job objects that spawn new instances on a schedule. Listing 30.2 shows many of the properties for the Product Category report, which has not been assigned to any corporate or personal categories, scheduled, or had its default processing options modified; Microsoft Access requires none and the system default printer is assigned by default. The listing shows the output properties for the Product Catalog sample report shipping with BusinessObjects Enterprise. Properties such as SI_FILE are composite properties. There are no embedded objects in this listing as the report has not been scheduled.

Listing 30.2. Product Catalog Report Property Listing

image

image

Indexed Properties

Every property in the property bag can be supplied in the SELECT clause (but not necessarily in the WHERE clause) of an InfoView query. Embedded object properties make no sense in the WHERE clause, but the full path to embedded object properties might. Querying for IInfoObjects WHERE SI_FILES.SI_NUM_FILES > 1 is a bogus, but valid, example. However, when querying the InfoStore, it is vital to include at least one common, indexed property to help reduce the working set. These properties exist physically in the repository database and can be queried at will without degrading system performance. Filtering exclusively on a nonindexed property forces the InfoStore API to open and examine every object in the InfoStore table to find a match. Such fields must be read, parsed, and loaded into the InfoStore memory cache before they can be used by the system, which can take time and precious CPU cycles.

Note

Don’t worry about the order of fields in the WHERE clause—BusinessObjects Enterprise will reorder evaluation from indexed to nonindexed properties appropriately prior to execution.

Table 30.8 lists all of the indexed properties. The boolean properties SI_HIDDEN_OBJECT, SI_NAMED_USER, and SI_PLUGINOBJECT are rarely used and have been omitted from this table. Certain job-specific properties might be null. Especially in Java, you must always test for nulls to avoid the dreaded and never specific Null Pointer Exception. Code defensively!

Table 30.8. Indexed Properties

image

image

image

Composite Properties, Embedded Objects

As discussed earlier, certain properties contain other properties and, in the case of SI_SCHEDINFO, have identifiers that permit individual retrieval and manipulation. A simple example is that SI_PATH, which is for folder objects, returns the property bag that includes the IDs, names, and types of every folder ancestor for the object. The function folderBreadCrumbs(String folderID, IInfoStore iStore) found in BOEUtil.java on www.usingcrystal.com shows how this is used.

Table 30.9 highlights some other composite properties that contain both primitive and composite values. Subproperties can be queried using dot notation. For instance, the following code retrieves the names of all the users who scheduled the World Sales Report.

image

Table 30.9. Composite Properties (Incomplete List)

image

image

For more information on these composite properties, consult the documentation and use the property bag recurser function to explore them yourself.

Property Enumerations

In Listing 30.3 and in ones that follow, property values are represented as numeric constants or codes. Fortunately, there is an easy way to decode these values—the static method on CePropertyID called idToName(java.lang.Integer id). This function will work for every property, although you might want to write your own based on the appropriate SDK property enumeration.

Listing 30.3. Schedule Status Decoder

image

Other enumerations to familiarize yourself with include CeEvents, CeKind, and CeScheduleType. Enumerations in the ISchedulingInfo interface include GroupChoice, ScheduleFlags, ScheduleOutcome, and ScheduleStatus. For a complete list of enumerations, please consult the API documentation.

Note

The etymology of the CI and SI in table and property names might reflect the company heritage of the product, first in Seagate Software’s Seagate Info, and then in Crystal Decisions, Crystal Enterprise. The C could also stand for Catalog. This kind of legacy name pollution is common in the software industry.

System Objects and Root Folders

As you get into more advanced SDK programming, it will help to know the addresses of well-known system objects and root folders. There are more than 100 such objects installed by default with BusinessObjects Enterprise. Only their enumerations are listed here for brevity:

  • CeSecurityID.Folder—The IDs of the BusinessObjects Enterprise system folders.
  • CeSecurityID.Limit—The IDs of the BusinessObjects Enterprise system security limits.
  • CeSecurityID.Right—The IDs of the BusinessObjects Enterprise system security rights.
  • CeSecurityID.User—Common user and group IDs.
  • CeSecurityCUID.AppConfigObject—Identifies the unique CUIDs that are used in a query to specify the application configuration components. Remember, these are in the CI_SYSTEMOBJECTS category.
  • CeSecurityCUID.Relation—Identifies the unique CUIDs that are used in a query to retrieve related, dynamically generated objects.
  • CeSecurityCUID.RootFolder—Identifies the unique CUIDs that are used in a query to specify the root folder. The following SELECT statement can be used to return top level folders:

    image

  • CeSecurityCUID.SystemObject—Identifies the unique CUIDs that are used in a query to specify the system objects. Remember, these are in the CI_SYSTEMOBJECTS category.

Note

Please note that the identifiers provided in these enumerations are the CUID unique identifiers, not numeric identifiers. As a result, filters such as SI_ANCESTOR that expect a numeric ID will not work.

This statement fails:

image

However, this works:

image

Remember, Universe objects are in the CI_APPOBJECTS category.

Certain system objects, unfortunately, are not in any enumeration. For instance, the only way to schedule objects to e-mail is to get a handle on an SMTP destination plugin, which is a child of the object known by its CUID as CeSecurityCUID.SystemObject.PLUGIN. You can iterate through these children yourself and see that the SMTP destination plugin has an ID of 29.

Permissions

Another set of constants is the rights registered for each object type. Global security rights are in the CeSecurityID.Right enumeration. Certain objects cannot be scheduled, so schedule-oriented rights naturally do not apply to those objects. System administrators will be familiar with the following enumerated rights from the CMC console:

  • CeSecurityID.Right—ADD, COPY, DELETE, DELETE_INSTANCE, EDIT, MODIFY_RIGHTS, OWNER_DELETE, OWNER_DELETE_INSTANCE, OWNER_EDIT, OWNER_MODIFY_RIGHTS, OWNER_PAUSE_RESUME_SCHEDULE, OWNER_RESCHEDULE, OWNER_SECURED_MODIFY_RIGHTS,OWNER_VIEW, OWNER_VIEW_INSTANCE, PAUSE_RESUME_SCHEDULE, PICK_MACHINES, RESCHEDULE, SCHEDULE, SCHEDULE_ON_BEHALF_OF, SECURED_MODIFY_RIGHTS, SET_DESTINATION, VIEW, VIEW_INSTANCE
  • CeReportRightID—DOWNLOAD, EXPORT, PRINT, REFRESH_ON_DEMAND
  • CeWebiRightID—DOWNLOAD_FILES, EDIT_QUERY, EXPORT_REPORT_DATA, REFRESH_LIST_OF_VALUES, RUN_AND_REFRESH_DOC, USE_LIST_OF_VALUES, VIEW_SQL

Using the permissions model fully is very complicated because BusinessObjects Enterprise supports cascading, inherited rights on folders and from groups, as well as explicit denials. The most basic permissions (viewing a folder or report), are resolved transparently within an InfoStore query. Objects that cannot be seen by the user are not returned. However, for more advanced rights, you need to use the ISecurityInfo.checkCustomRights method. Listing 30.4 shows how to determine a user’s WebI viewing rights.

Listing 30.4. Determining User Permissions

image

Rights can also be checked individually. Please consult the product documentation for more information.

Setting Custom Properties

The BusinessObjects Enterprise InfoObject is a very versatile container that easily persists properties for every type of object. The following code shows how you can add custom properties to InfoObjects. Remember the process for updating a document: query for objects, choose an object, set properties on that object, commit (all) objects.

image

Note that custom properties cannot be accessed directly using syntax such as SI_MY_CUSTOM_PROPERTY. To access them you must use the asterix (*) in the SELECT clause when searching for custom properties and then use the getProperty() method used in the recursive property bag lister.

Using * and Top N

As discussed, queries that return all properties using the asterisk operator (*) might actually return many objects. It is conceivable that a report could have 1,000 schedules associated with it. Selecting the SI_SCHEDINFO project might return 1,000 rows for 1 report alone.

Another must-know tip is how to use Top N. In BusinessObjects Enterprise, SELECT * returns an upper-limit of 1,000 objects. You can specifically ask for more or fewer objects using SELECT TOP N. You can see whether you are looking at all of the records that satisfy your query by comparing the resultInfoObjcts.getResultSize() method to the actual number of records found through the resultInfoObjcts.size() method.

Query Examples

Now that you understand the syntax of querying the InfoStore, some of the properties, and how they are nested, look at the following examples harvested from the documentation and the author’s own BusinessObjects Enterprise projects. The example includes only the query statement itself and an explanation of what is returned by the query. The InfoStore only returns the objects that the user is permitted to view:

  • Report templates in the Report Samples folder or subfolders. SI_ANCESTOR can only be used in the WHERE clause.

    SELECT SI_NAME FROM CI_INFOOBJECTS WHERE SI_ANCESTOR=6319 AND SI_INSTANCE=0

  • List of universe meta-layers.

    SELECT * FROM CI_APPOBJECTS WHERE SI_KIND='Universe' ORDER BY SI_NAME ASC

  • Parent folder of all universes.

    SELECT SI_ID FROM CI_APPOBJECTS WHERE SI_PARENTID=95 AND SI_NAME='Universes'

  • Scheduled jobs submitted by WRichards for World Sales Report.

    image

  • Get recurring scheduled jobs owned by WRichards. SI_RECURRING will be null for nonjobs and 0 for one-time jobs.

    SELECT * FROM CI_INFOOBJECTS WHERE SI_OWNERID='WRichards' AND SI_RECURRING=1

  • Get all scheduled jobs owned by WRichards. Note how selecting SI_SCHEDINFO forces selection of job objects.

    SELECT SI_SCHEDINFO FROM CI_INFOOBJECTS WHERE SI_OWNERID='WRichards'

  • Get all objects owned by WRichards.

    SELECT * FROM CI_INFOOBJECTS WHERE SI_OWNERID='WRichards'

  • Get report templates owned by WRichards. SI_INSTANCE will return null for nonreport objects, 1 for report instances, and 0 for templates.

    SELECT * FROM CI_INFOOBJECTS WHERE SI_OWNERID='WRichards' AND SI_INSTANCE=0

  • Returns instances of report identified by 215.

    SELECT * FROM CI_INFOOBJECTS WHERE SI_PARENTID=215 AND SI_INSTANCE=1

  • Returns top-level report templates that have been scheduled to run.

    SELECT * FROM CI_INFOOBJECTS WHERE SI_RUNNABLE_OBJECT=1

Report Browsing Using InfoObject Queries

Now that you are familiar with the structure of the InfoStore and how it is queried, you can now build portals that use it. In an effort to keep this book a manageable weight, you will need to download many of the code samples discussed here from www.usingcrystal.com. The directory.jsp page provides users with the ability to browse and drill through BusinessObjects Enterprise folders and view the reports contained therein. This file brings together several concepts: querying the InfoStore, iterating through InfoObjects, opening reports using the OpenDocument dispatcher (covered in greater depth in Chapter 31), showing Crystal Report thumbnails (Web Intelligence documents have none), and using JavaScript in your user interface.

Creating Objects and Capturing Their IDs

As discussed earlier, creating objects using the BusinessObjects Enterprise SDK requires first instantiating an object factory called the plugin manager. In programming, a factory provides users a place for instantiating several types of objects. The IPluginMgr factory uses a method named getPluginInfo that takes the object’s internal program ID identifier type. This is the PROG_ID property found in every object.

As noted earlier, objects may be created, but not submitted, individually to the InfoStore. An InfoObject collection must be created first and then new objects can be added to it. The ID of the object is available immediately after it is added to the collection using the standard getID() accessor method. Most objects require setting their title (name) and parent object identifier. Some, such as users and groups, do not. Please consult the documentation before creating new document types—many require implementing interfaces that are beyond the scope of this book. Listing 30.5 shows how to create a new folder object using the PluginMgr and capture its unique identifier.

Listing 30.5. Creating a Folder

image

Deleting Objects

Deleting objects is much like creating them. The InfoStore must be queried and multiple objects (often just one) retrieved. The collection of InfoObjects is iterated or accessed using the collection’s get(index number) accessor method. Then, the collection’s delete(IInfoObject) method is called and, finally, the entire collection is committed.

The following function deletes a specific recurring job (or subscription) for a specific user. Supplying the user ID is optional in this case.

image

Scheduling Reports

BusinessObjects Enterprise solves three broad problem classes for Crystal Reports users: security, scalability, and distribution. The distribution capability includes the abilities to send a report once or on a recurring schedule, in any supported output format (there are deltas between Crystal Reports and Web Intelligence), and to a variety of destinations:

  • Default—BusinessObjects Enterprise file output server. Scheduled instances will be retained according to site-wide or folder-level retention policies configurable in the CMC. Users can view these documents by retrieving the instance and using one of the export or DHTML viewers.
  • SMTP—E-mail server. E-mailing a link or PDF document is a common use-case.
  • File—Local or mapped file path. Publishing a PDF document to a network webserver is a common use-case.
  • FTP—Remote FTP server that accepts an active FTP connection.

By default, these destinations are turned off in the CMC. After turning them on, it is a good idea to go into the job server configuration console and set system-wide default parameters. For instance, you could set the default SMTP server name, domain, and port number.

You will find a very powerful function scheduleReportToEmail(IInfoStore iStore, int reportID, HttpServletRequest request, HashMap paramMap, String frequency, int periodDays, String destinationFormat, String dependentEventName, String fromEmailAddress, String toEmailAddresses, String emailSubject, String emailMessage, String emailAttachmentName) in the BOEUtil on www.usingcrystal.com. If a schedule includes a dependent event, it will wait until the event is fired before running the job. Additionally, scheduling and formatting can be controlled with far more granularity than what you will find in this function. In the product documentation and support site, you can find code samples that more fully exercise discrete pieces of the scheduling API.

Capturing the New Scheduled Job Identifier

It is sometimes important to capture the identifier of the job as soon as it is created. This could be for status reporting or complex scheduling front-ends with their own persistence. Immediately after a job is created, its parent InfoObject will contain a property called SI_NEW_JOB_ID that disappears after the InfoObject falls out of scope. For a nonrecurring scheduled InfoObject, its value corresponds to the SI_ID of the new instance that is to be created. For a recurring, scheduled InfoObject, it refers to the SI_ID of the recurrence parent object.

Capturing Parameters

Whenever most reports are displayed or scheduled, parameters need to be captured and supplied. When a report is viewed, it can be convenient to build a parameter fields collection and supply it to the viewer. Setting the parameters on the IInfoObject is the only viable approach when a report is scheduled. The getCrystalReportParameterFields(IReport report, HttpServletRequest request, HashMap paramMap, boolean bFailSilently) function captures parameter values from the request scope as well as a map object, and updates the InfoObject itself and a Fields collection. It supports multiple, range, and discrete values of any data type. The dummy function setCrystalReportParameters invokes the other and simply throws away the Fields collection. As these are quite long and complicated code listings, you will them online at www.usingcrystal.com.

For information on how to fill prompt values for scheduling a Web Intelligence document, consult customizing_webintelligence.pdf which installs in the help/language directory of BusinessObjects Enterprise (and should also be available for download from www.usingcrystal.com).

Users and Group Management

For customers who store users and groups in a relational database or use a nonsupported Single Sign-On (SSO) product, implementing BusinessObjects Enterprise poses the following challenges:

  • Replicating users and groups—To fully exercise BusinessObjects Enterprise security and logging, users and groups must be replicated using batch scripts. Batch scripts themselves can be scheduled through BusinessObjects Enterprise.
  • Logging in without a password—SSO web server plugins expect down-stream providers to accept usernames in the request header as valid and authorized. BusinessObjects Enterprise expects a password and setting it as an empty string creates a security hole. Resetting the user password every time the user logs in is one work-around.
  • Getting and setting user preferences—Accessing user preferences and setting custom ones is easy with the getProfileString and setProfileString methods.

In BOEUtil you will find several functions that handle adding and removing users and groups; setting user properties, including arbitrary properties on the user profile; resetting user passwords; and managing group membership, including subgroups.

Using Reports As a Datasource

Because Crystal Reports access so many datasources and often include high-value business logic, customers increasingly request to use their Crystal Reports as datasources.

Access is provided through the RAS getRowsetController cursor. It is advisable to consult the API documentation, but here are some tips to get you started:

  • Set batch size—Unless you have the ability to request records in batches, set the batch size to the total number of data rows in the report.
  • Rowcount is the last column in the record datastructure—The number of columns in the metadata fields datastructure is one less column than the records datastructure. You can ignore the last column; it is just the row number.
  • Description is the only unique column—It is possible for reports to contain many formulas and summaries. To ensure uniqueness, use the description rather than the name.
  • ADO.NET XML available—if you prefer extracting an ADO.NET recordset, use the resultCursor.getRowset().getXMLData() method.

Listing 30.6 shows how to use the RowsetController to extract data from a Crystal Report.

Listing 30.6. Extracting Data from a Crystal Report

image

image

Where to Go from Here

The BusinessObjects Enterprise SDK is the most flexible and powerful way to access BusinessObjects Enterprise. Using the SDK, you can do create custom BI applications that meet the look, feel, and integration requirements of your project. The focus of this chapter was to understand the InfoStore—the object-relational repository where all BusinessObjects Enterprise assets are persisted, related, and secured. This is the most complex and least understood part of the API. To accelerate your development effort, please go to www.usingcrystal.com and download the white-box sample portal, in either JSP or .NET, which is ready-to-run and customize. After looking through the code-base, you should feel confident and comfortable stepping out on your own.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset