Skip to Content
Publication is a process that collects many reports (Crystal Reports or WebIntelligence + External Documents), personalizes and distributes them to a mass audience. An overview of the publication functionality can be found in my previous blog: Introduction into the SAP BusinessObject Intelligence Platform Publication
While publications are very powerful in itself; sometimes they still don’t provide all the functionality that our customers are looking for.  This is where publication extensions come into place. Publication extensions let you customize the publication process by writing custom java code. For example, you can use a pre-delivery publication extension to password protect your publication artifacts before delivery. Or you can use a post-delivery publication extension to store the publication artifacts in an additional destination that is currently not supported by the BI platform.
There are two types of publication extensions:
  • Post-processing (pre-delivery) plugins, which allow you to add processing logic after publication contents have been personalized.
  • Distribution complete (post-delivery) plugins, which allow you to add processing logic after publication contents have been delivered.
    
In this blog I will give you an overview about the different types of publication extensions and how to create, deploy, and invoke them programmatically. I will focus primarily on post-processing (pre-delivery)  plugin as they are slightly more powerful than distribution complete (post-delivery) plugins, but a lot of the concepts are similar.
 

Building and deploying custom post-processing (pre-delivery) publication extensions

In order to build a publication extension, you must include pub_common.jar in your class path in addition to the standard SAP BusinessObjects Business Intelligence platform SDK libraries. This file is located by default in <Enterprise Dir>\java\lib. If you are creating a post-processing plugin and you are using the PostProcessingPluginHelper class, then you have to also include pub_processing.jar in your class path. This library is located in the same directory as the pub_common.jar.
A custom post-processing plugin consists of a Java class that implements the  com.businessobjects.publisher.postprocessing.IPublicationPostProcessingPlugin interface. This interface contains two methods, which must be implemented by the plugin class:
Method Description
handle
This method is invoked one time for each destination and scope. It must return an IInfoObjects collection containing the artifacts created by the plugin that will be delivered to the recipients associated with the current destination and scope. The parameter is a com.businessobjects.publisher.postprocessing.IPublicationPostProcessingContext object, which contains information about the context, including the current scope and destination, and any parameters that were used to invoke the plugin.
getTargetDestinations
This method must return a collection of com.businessobjects.publisher.postprocessing.PluginTargetDestination representing the destinations for which the plugin will be invoked.
The com.businessobjects.publisher.postprocessing.IPublicationPostProcessingContext contains information about the context, including the current scope and destination, and any parameters that were used to invoke the plugin.  Below is a list of the methods that  can be used in post-processing plugins.
Method Description
getAdminLogAdapter() This method returns a logger that can be used to log information during post-processing
getDestination() This method returns the current destination.
getDocuments() This method returns the static documents and schedulable document artifacts for the current scope and destination.
getEnterpriseSession() This method returns the session associated with the current user.
getInfoStore() This method returns an InfoStore object that can be used to query the BusinessObjects Enterprise repository.
getOptions() This method returns the generic parameter value, that was passed in through the CMC UI.
getPluginArtifacts() This method returns all artifacts that have been generated during the publishing process.
getPublication() This method returns the publication that invoked this plugin.
getScopeFilter(IInfoObject doc) This method returns IScopeFilter object that can be used to obtain personalization information
getScopeID() This method returns the ID of the current scope.
getTempDirectory() This method returns the path of the directory on the processing server that is used by BusinessObjects Enterprise for storing temporary files.

The com.businessobjects.publisher.postprocessing.PostProcessingPluginHelper provides several static methods that can be used in post-processing plugins. For example, to add new artifacts, use createInfoObject method. The following code creates a text file info object.

ITxt textInfoObject = (ITxt) PostProcessingPluginHelper.createInfoObject(context, ITxt.PROGID, “text/plain”, null, null);

For detailed information on IPublicationPostProcessingPlugin, IPublicationPostProcessingContext, PluginTargetDestination, and PostProcessingPluginHelper, see the SAP BusinessObjects Business Intelligence Platform Java API Reference .

 

An example publication extension is posted at this blog post: Sample Publication Extension: Deliver shortcut to a BI platform folder based on personalization . This post processing publication extension creates a shortcut of the publication artifact in a folder based on the personalization. For example if you personalize on Country and have a folder for USA and Canada, then a shortcut for the publication artifact filtered to USA will be created in a USA folder, and a shortcut for the Canada document will be created in a Canada folder.  

After the publication extension is built into a jar file, it needs to be deployed in the publication extensions directory. The default location of this directory is <Enterprise Dir>\java\lib\publishingPlugins. Once the extension was added, you have to restart the Adaptive Processing Server.

Adding a publication extensions to a publication

A publication extension can be added to a publication either programmatically or from the Central Management Console (CMC). The BI launch pad application does not allow you to specify publication extensions for a publication through the UI.

At this point it is assumed that you have already deployed the publication extension as described above on all computers that run the Adaptive Processing Server.

 

Below are the steps to add a publication extension via the CMC:

  1. Double-click a publication to open it. The “Properties” dialog box appears.
  2. Expand Additional Options, and click Publication Extension.
  3. In the Publication Extension Name box, type a name for the extension.
  4. In the Class Name box, type the fully qualified class name for the extension.
  5. (Optional) In the Parameter box, type a serialized string that your extension requires. What the parameter is would depend on how the extension was designed.
  6. To use the extension after processing but before delivery, above the Before Publication Delivery list, click the Add button. The extension is added to the Before Publication Delivery list.
  7. To use the extension after delivery, above the After Publication Delivery list, click the Add button. The extension is added to the After Publication Delivery list.
  8. Click Save.
  9. Repeat steps 2 to 8 for each extension you want to add.

To define the order in which to execute publication extensions, click Move Up or Move Down under the Before Publication Delivery list or the After Publication Delivery list.

pub extension.png

To report this post you need to login first.

13 Comments

You must be Logged on to comment or reply to a post.

  1. G Gena

    Great and helpful article. I’ve created a basic publication extension that works. However, when I added additional functionality to it that requires external .JARs from a third-party, I can’t seem to get things to work. The publication log shows that it’s not able to find the necessary class. Short of putting the additional .JARs directly in to the <drive>\Program Files\Business Objects\common\4.0\java\lib\publishingPlugins directory I can’t seem to get it to work.

    When I package my the third-party jars in my publishing plugin jar, it appears to ignore the class path and jars there. Is there any way to set the classpath for BO or have it find those jars without dumping them in the publishingPlugins directory?

    (0) 
    1. Derrick Wan

      It’s recommended to put all the custom jars (and dependencies) in <drive>\Program Files\Business Objects\common\4.0\java\lib\publishingPlugins  because BOE will load all jars in that folder. This is how we avoid having to change the classpath. 

      Thanks,

      Derrick

      (0) 
      1. Derrick Wan

        Also for the question on “When I package my the third-party jars in my publishing plugin jar, it appears to ignore the class path and jars there”, we only load classes inside jars inside the publishingPlugins folder.  If you package 3rd party jars inside the publishing jars, it won’t be loaded.  You can just put multiple jars (including the 3rd party ones) inside the publishingPlugins folder and it should work 🙂 . 

        Cheers,
        Derrick

        (0) 
  2. Sam Aderogba

    In my publication I define output file name as %SI_NAME%_%SI_OWNER%.%EXT% . Please how do I capture SI_NAME, SI_OWNER (from profile) and EXT in publication extension? I already have a functional publication extension using online examples but these examples captures artifact titles internal to cms. I am interestes in the physical file names of the publications. Thanks.

    (0) 
  3. Jeff Wei

    Hi Christina,

    We are in the process of updating our CE Enterprise ver 10 Server to BOBJ 4.1 SP2 (using BOE Xi 3.1 as the intermediate as one cannot migrate directly) and encountered a puzzling issue in the test environment when using BOBJ 4.1 SP2.

    I am new to Crystal as a whole relatively speaking (~ 1 year) and so am  finding this daunting, especially when I’m not familiar with java. 

    Here’s our issue:

    A former staff many moons ago must have set up a custom SDK coding for the Crystal Enterprise ver 10 where there is a “hidden” parameter that would automatically pass the value of the User security groups (ie. If you belong to Security Group A), then “A” will pass to the “vUsername” parameter automatically when an individual runs a Crystal Report.  The report would, based on this, only show Group A’s data.  User belonging to Group B would then only see Group B’s data, etc.  This is working fine in Crystal Enterprise ver 10, but on the newly set up BOBJ 4.1 SP2 CMS server, we could not get the value to pass automatically.

    I’m assuming we need to add this with a publication extension somehow.  Would you be able to assist or direct me on how to get this set up as we’ve been puzzling over this for awhile now and we need to get this resolved asap.

    thx!

    (0) 
    1. Christina Obry Post author

      Hi Jeff,

      I no longer work on this area. I suggest to contact support about this or post it as a discussion for others to see, not as a comment on a blog.

      Thanks,

        Christina

      (0) 
  4. mohammed shoaib

    Am getting an error such as cannot instantiate the class. Class not found.

    Any suggstions would be much appreciated.

    Java Code:

    import java.io.FileWriter;

    import java.util.ArrayList;

    import java.util.Collection;

    import java.util.Iterator;

    import com.businessobjects.publisher.postprocessing.IPublicationPostProcessingContext;

    import com.businessobjects.publisher.postprocessing.IPublicationPostProcessingPlugin;

    import com.businessobjects.publisher.postprocessing.PluginTargetDestination;

    import com.crystaldecisions.sdk.occa.infostore.IDestinationPluginArtifactFormat;

    import com.crystaldecisions.sdk.occa.infostore.IInfoObject;

    import com.crystaldecisions.sdk.occa.infostore.IInfoObjects;

    import com.crystaldecisions.sdk.plugin.CeProgID;

    public class TestPublishingPostProcessingPlugin implements

    IPublicationPostProcessingPlugin

    {

    public Collection getTargetDestinations() throws Exception

    {

        Collection pluginTargetDestinations = new ArrayList();

    pluginTargetDestinations.add(new PluginTargetDestination(CeProgID.DISKUNMANAGED,

    IDestinationPluginArtifactFormat.CeDistributionMode.FILTER_NONE));

    pluginTargetDestinations.add(new PluginTargetDestination(null,

    IDestinationPluginArtifactFormat.CeDistributionMode.FILTER_NONE));

    return pluginTargetDestinations;

    }

    public IInfoObjects handle(IPublicationPostProcessingContext context) throws

    Exception

    {

    FileWriter outFile = new FileWriter(“C:\\test\\PPLog” +

    System.currentTimeMillis()+”.log”);

    outFile.write(“hello!\n”);

    ArrayList docs = context.getDocuments();

    Iterator docIt = docs.iterator();

    IInfoObjects objs = context.getInfoStore().newInfoObjectCollection();

    while (docIt.hasNext())

    {

    IInfoObject obj = (IInfoObject)docIt.next();

    outFile.write(obj.getTitle() + “\n”);

    String newName = “Artifact – ” + System.currentTimeMillis();

    outFile.write(“Renaming ‘” + obj.getTitle() + “‘ to ” + newName);

    obj.setTitle(newName);

    objs.add(obj);

    }

    outFile.close();

    return objs;

    }

    }

    (0) 

Leave a Reply