Additional Blogs by SAP
cancel
Showing results for 
Search instead for 
Did you mean: 
ted_ueda
Employee
Employee
0 Kudos

Earlier this week, I needed to do a quick test.  A test involving reporting off of a Plain Old Java Object (POJO)  (http://en.wikipedia.org/wiki/POJO) collection within Web Intelligence.  How to do it?  And quickly.

Flash forward a hour and change, and I'm logging onto my

Web Intelligence Rich Client

and dropping in Universe objects backed by a POJO collection.

So how did I accmplish this - and quickly?  No mad coding skills were used in the production of this blog entry...

Hint: I used (1) Universe Data Access Driver Development Kit (DDK)  (http://help.sap.com/businessobject/product_guides/boexir31/en/ddk_java_dg_12_en.zip) SDK, and (2)

Crystal Reports Java (CRJ)

SDK.    CRJ -> DDK -> Universe -> WebI.  Not exactly the intended use for the SDK, but it did get the job done - without my having to write a lot of hairy adapters.

I'll describe what I did - first, a brief description of the two SDKs:

Universe Data Access Driver Development Kit (DDK) SDK

The DDK SDK - new with XI 3.x - allows a developer to create programmatic Java interfaces to data sources for a Universe Data Connection.    There are two interfaces available - the Open Connectivity and the JavaBean Connectivity. 

The Open Connectivity presents a RDBMS Table-like API for Java code - it's the coder's responsibility to present schema details to the Universe, interpret SQL statements sent by the Universe and return the correct data set.

The JavaBean Connectivity presents a RDBMS Stored-Procedure-like API for Java code - it's the coder's responsibility to create a JavaBean with a getter method that returns a java.sql.ResultSet instance to the Universe.

In this task, I'll use the JavaBean Connectivity.

Crystal Report Java (CRJ) SDK

Crystal Reports for Eclipse has built-in support for reporting off of POJO data via the CRJ API. Internally, there's a POJO ResultSet Factory method that translates POJO class primitive properties into a java.sql.ResultSet Java object.

In this task, I'll use the CRJ POJO Factory inside the DDK JavaBean to consume POJO and return a ResultSet.

Sample Code

Implementation involves three Java codes and config settings in the Universe javabean.sbo file.  The code consists of: (1) the POJO definition, (2) the JavaBean definition, and (3) the JavaBean Info definition.

I'll use a simple POJO here - a Person class with very basic properties - name, birthdate and ID:

Person.java POJO class definition

package com.sap.ddk.javabean.sample;public class Person { private int id; private String lastName; private String firstName; private java.sql.Date birthDate; public int getId() {  return id; } public void setId(int id) {  this.id = id; } public String getLastName() {  return lastName; } public void setLastName(String lastName) {  this.lastName = lastName; } public String getFirstName() {  return firstName; } public void setFirstName(String firstName) {  this.firstName = firstName; } public java.sql.Date getBirthDate() {  return birthDate; } public void setBirthDate(java.sql.Date birthDate) {  this.birthDate = birthDate; }}

The JavaBean class defines the getPOJOResultSet() getter method that returns a java.sql.ResultSet.  A POJO collection of Person instances is generated internally, passed to the CRJ POJOResultSetHelper class instance to transform to a java.sql.ResultSet:

POJOJavaBean.java class JavaBean definition

package com.sap.ddk.javabean.sample;

import java.sql.ResultSet;

import java.util.Calendar;

import java.util.Properties;

import com.businessobjects.connectionserver.CSException;

import com.businessobjects.connectionserver.datasources.ddk.Context;

import com.businessobjects.connectionserver.datasources.ddk.javabean.Bean;

import com.crystaldecisions12.sdk.occa.report.application.internal.POJOResultSetHelper;

/*

  • Universe Data Access Driver Kit (DDK) SDK JavaBean Data Source from a Crystal Reports

  • Java SDK Plain Old Java Object (POJO) Data Source

*/

public class POJOJavaBean implements Bean {

     public void initialize(Context context, String url, Properties properties) throws CSException {}

     public void close() {}

     /*

  • Return java.sql.ResultSet generated from POJO using Crystal Reports Java SDK.

      */

     public ResultSet getPOJOResultSet() throws Exception {

          java.util.List pojos;

          Person person;

          java.util.Calendar calendar;

          POJOResultSetHelper pojoResultSetHelper;

          calendar = Calendar.getInstance();

          /*

  • Create collection of Person POJOs.

           */

          pojos = new java.util.ArrayList();

          calendar.clear();

          calendar.set(1954,10,3);

          person = new Person();

          person.setId(1);

          person.setLastName("Ant");

          person.setFirstName("Adam");

          person.setBirthDate(new java.sql.Date(calendar.getTime().getTime()));

          pojos.add(person);

          calendar.clear();

          calendar.set(1930,7,9);

          person = new Person();

          person.setId(2);

          person.setLastName("Boop");

          person.setFirstName("Betty");

          person.setBirthDate(new java.sql.Date(calendar.getTime().getTime()));

          pojos.add(person);

          calendar.clear();

          calendar.set(1451,7,26);

          person = new Person();

          person.setId(3);

          person.setLastName("Columbus");

          person.setFirstName("Christopher");

          person.setBirthDate(new java.sql.Date(calendar.getTime().getTime()));

          pojos.add(person);

          /*

  • Use CRJ SDK internal class POJOResultSetHelper to generate ResultSet

  • from the POJO collection.

           */

          pojoResultSetHelper = new POJOResultSetHelper(Person.class);

          return pojoResultSetHelper.createResultSet(pojos);

     }

}

The Universe DDK JavaBean Connectivity looks for a getter returning a java.sql.ResultSet.  To find one, it uses the JavaBean convention of instantiating a JavaBean Info class.  Here, the POJOJavaBeanInfo defines the BeanInfo:

POJOJavaBeanInfo.java class Bean Info for POJOJavaBean

package com.sap.ddk.javabean.sample;

import java.beans.BeanDescriptor;

import java.beans.MethodDescriptor;

import java.beans.ParameterDescriptor;

import java.beans.SimpleBeanInfo;

import java.util.Properties;

public class POJOJavaBeanInfo extends SimpleBeanInfo {

     public POJOJavaBeanInfo() {

          super();

     }

     @Override

     public BeanDescriptor getBeanDescriptor() {

          BeanDescriptor beanDescriptor;

          beanDescriptor = new BeanDescriptor(POJOJavaBean.class);

          beanDescriptor.setName("POJOJavaBean");

          beanDescriptor.setShortDescription("JavaBean from a POJO");

          return beanDescriptor;

     }

     @Override

     public MethodDescriptor[] getMethodDescriptors() {

          MethodDescriptor[] methodDescriptors = null;

          try {

               methodDescriptors = new MethodDescriptor[] {

                    new MethodDescriptor (POJOJavaBean.class.getDeclaredMethod ("initialize",

                        new Class[] {com.businessobjects.connectionserver.datasources.ddk.Context.class,

                                     String.class, Properties.class}),

                       new ParameterDescriptor[] {new ParameterDescriptor (), new ParameterDescriptor (), new ParameterDescriptor ()}),

                new MethodDescriptor(POJOJavaBean.class.getDeclaredMethod("close", (Class[])null)),

                new MethodDescriptor(POJOJavaBean.class.getDeclaredMethod("getPOJOResultSet", (Class[])null))     

               };

               methodDescriptors[0].setShortDescription ("initialize JavaBean");

               methodDescriptors[0].getParameterDescriptors ()[0].setName ("context");

               methodDescriptors[0].getParameterDescriptors ()[0].setShortDescription ("context of JavaBean *IGNORED*");

               methodDescriptors[0].getParameterDescriptors ()[1].setName ("url");

               methodDescriptors[0].getParameterDescriptors ()[1].setShortDescription ("url of JavaBean *IGNORED*");

               methodDescriptors[0].getParameterDescriptors ()[2].setName ("properties");

               methodDescriptors[0].getParameterDescriptors ()[2].setShortDescription ("properties for JavaBean *IGNORED*");

               methodDescriptors[1].setShortDescription ("finalize JavaBean");

               methodDescriptors[2].setShortDescription ("Retrieve POJO ResultSet");

          } catch(Exception e_ignore_at_your_peril){}

          return methodDescriptors;

     }

}

The DDK will scan the MethodDescriptor[] for appropriate POJOJavaBean method to call.

Compile all three Java codes, ensuring you have the CRJ jar file CrystalReportsRuntime.jar and the DDK jar file ConnectionServer.jar (found by default in the <Enterprise Install>classes folder) in the ClassPath, and jar them up.

Deployment

Deploying the driver involves making the jar file you've created above accessible to the Universe, and configuring the javabean.sbo with the Class and ClassPath info.

On Windows deployment, the Universe config files are found by default in the <Enterprise Install>win32_x86dataAccessconnectionServer folder.  On my deployment, I jar my files to beans ean_pojo.jar file.   I then add a new Database element into the Databases element in the +javabean/javabean.sbo +file to specify the JavaBean class and the ClassPath:</p>bq. The javabean.sbo file Database element entry for POJOJavaBeanThis is a nice, simple way of injecting POJO data into a Web Intelligence document.  It's very handy for testing, since one can easily convert most data streams into a POJO collection.

But I'm thinking as I write this that there's more practical uses for this trick.

(Insert pregnant pause here). So I'm back.  I went away for a bit, to create a RSS  (http://cyber.law.harvard.edu/rss/rss.html) Feed connectivity for Universes using the DDK.

Universe from a RSS Feed

So here's a snapshot of a Web Intelligence document reporting off of a RSS Feed - specifically, the SCN RSS Feed from the Business Objects SDK Development Forum:

!https://weblogs.sdn.sap.com/weblogs/images/251913699/RSSSCNForums.JPG|height=412|alt=image|width=694...!</body>

2 Comments