Choosing the Right Integration Approach 766
The BusinessObjects Enterprise SDK 769
BusinessObjects Enterprise SDK Object Model 772
Report Browsing Using InfoObject Queries 790
Creating Objects and Capturing Their IDs 790
Users and Group Management 793
Using Reports As a Datasource 793
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.
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
.
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.2 shows the component integration approaches and the platforms they support.
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.
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.
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:
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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:
Query
method, returning InfoObjectsA 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:
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.
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.
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.
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.
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.
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.
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:
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
.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.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.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.
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:
These two, however, will work:
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.4–30.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.
Although not shown, Folder
objects can be referenced from all three table contexts.
Several other kinds of objects require more sophisticated query statements to access. They include destination and security plugins.
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.
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:
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.
This function returns property objects that fall into one of three categories:
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.
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.
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!
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.
For more information on these composite properties, consult the documentation and use the property bag recurser function to explore them yourself.
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.
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.
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.
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:
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:
However, this works:
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.
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:
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.
Rights can also be checked individually. Please consult the product documentation for more information.
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.
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.
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.
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:
SI_ANCESTOR
can only be used in the WHERE clause.
SELECT SI_NAME FROM CI_INFOOBJECTS WHERE SI_ANCESTOR=6319 AND SI_INSTANCE=0
SELECT * FROM CI_APPOBJECTS WHERE SI_KIND='Universe' ORDER BY SI_NAME ASC
SELECT SI_ID FROM CI_APPOBJECTS WHERE SI_PARENTID=95 AND SI_NAME='Universes'
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
SI_SCHEDINFO
forces selection of job objects.SELECT SI_SCHEDINFO FROM CI_INFOOBJECTS WHERE SI_OWNERID='WRichards'
SELECT * FROM CI_INFOOBJECTS WHERE SI_OWNERID='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
SELECT * FROM CI_INFOOBJECTS WHERE SI_PARENTID=215 AND SI_INSTANCE=1
SELECT * FROM CI_INFOOBJECTS WHERE SI_RUNNABLE_OBJECT=1
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.
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.
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.
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:
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.
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.
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).
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:
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.
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:
resultCursor.getRowset().getXMLData()
method.Listing 30.6 shows how to use the RowsetController to extract data from a Crystal Report.
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.