Main

BI Publisher Enterprise Archives

May 3, 2006

It's here ... XML Publisher Enterprise is released ...

After a lot of hard work and heartache the standalone XML Publisher Enterprise was released this morning via the edelivery site on oracle.com. Its a fully featured enterprise reporting application.
Some highlights:


  • You can run the server on any mid tier
  • You can manage users, reports, delivery channels from a centralized web interface
  • You can build reports very quickly using an advanced web interface accessing multiple datasources (multiple db's, web services, http, data template) in each report
  • Users can run, schedule and deliver reports down multiple delivery channels.
  • Excel Integration - users can log in from the Excel interface and run reports bring data back into Excel for further analysis
  • ... the list goes on.


You can download a copy from  http://edelivery.oracle.com
1. Pick your language and continue
2. Enter your details and check the agreements, continue
3. Choose 'Oracle Application Server Products'
4. Pick your platform, we have ported for Windows and Linux but it can run on any platform any App Server and 'Go'
5. Look for the 'Oracle® XML Publisher Release 5.6.2 Media Pack for X' in the list.
6. There is a server side and client side component, download them and follow the readme's

Its fast and easy to set up and get going ... let us know how you get on.

June 5, 2006

Connecting to SQL Server with XMLP Enterprise

We have had a few enquiries recently asking how to hook up XMLP Enterprise with a SQL Server db, heres the steps you need to follow to get it working.



  • Download the SQL Server 2000 Driver for JDBC Service Pack 3 - we had some issues with the 2005 jdbc driver we are investigating whether this is an XMLP or MS issue ... you can still access the SQL Server 2005 edition with the 2000 driver sucessfully.
  • Once installed look in the <<INSTALL DIR>>/lib directory there will be 3 jars
    mssqlserver.jar
    msbase.jar
    msutil.jar
    Copy them into your $OC4J_HOME/j2ee/home/applib if you have installed XMLP under OC4J otherwise put them in the common apps libraries directory of your J2EE container.

  • Now bounce your server, the jdbc libraries will be loaded automatically for all applications on the instance. If you only want them loaded for the xmlpserver application then copy the jars to OC4J_HOME/j2ee/home/applications/xmlpserver/xmlpserver/WEB-INF/lib and bounce.
  • Now login as Administrator in the Enterprise server and go to the Admin -> JDBC page and enter the details required for the data connection:


    • Data Source Name - give the connection a name 
    • URL the url to connect to the db, standard MSSQL stuff, basically   jdbc:sqlserver://server:port;databaseName=dbname e.g. jdbc:sqlserver://111.11.1.111:1133;databaseName=AdventureWorks
    • Username  - simple stuff 
    • Password - even simpler  
    • Database Driver Class - this needs to be com.microsoft.jdbc.sqlserver.SQLServerDriver
    • Now hit the test button to check the connection works. If it fails check your connection string is valid and the class definition above.
    • The data source will now be available in the report builder to builder queries against.

You're now ready to start writing reports against SQL Server!

July 18, 2006

Accessing XMLP Enterprise Reports via a URL

I have seen several questions around accessing a report via a URL for the XMLP Enterprise release, some of you have teased apart the mechanism and gotten it working, heres the 101 for the rest of you. Now Im assuming that you are trying to call a report via a URL from another application, that might be from a portal or maybe an APEX application.


Security


As you know the reports are placed in folders and those folders are then secured to a role and a role assigned to a user. So first off you're going to need to ensure that a user actually has access to a report in the first place and if they do then you'll need to call XMLP to render it. There are two options.
1. Use the Guest folder - this can be enabled via the server configuration file, any report in this folder is open for all to see and run. Not the best solution but if the report is not sensitive then it will work no problem.
2. Use SSO - you can hook the XMLP server up to an SSO server as a partner application to the calling application and use LDAP for both application to minimize the user maintenance. This way you call any report via a URL and as long as the user has rights to see/run the report then XMLP will render it without the need for the user to log in. Setting up LDAP and SSO are covered in the user guide now available on OTN.


Building the URL


So the basic URL for a report is as follows:
http://server:port/xmlpserver/ReportDirectory/ReportName.xdo


where


  • server:port - is the name of the server and port number where xmlp is running
  • xmlpserver - a required string, this is the name of the application
  • ReportDirectory - the folder path to the report
  • ReportName - the name of the report

This will render the complete report inside the XMLP page with all the report controls. The default template, output and parameters will be used to render the report.
For example:
http://xdopf.us.oracle.com/xmlpserver/Private/Salary+Report/Salary+Report.xdo

URL1:

If you want some more control then we need to start adding some name/value pairs to the URL. The easiest way to generate the URLs is too just export the report, the URL generated will look similar to the basic URL but the name/value pairs will be added. For example:

http://xdopf.us.oracle.com/xmlpserver/Private/Salary Report/Salary Report.xdo?_xpf=&_xpt=1&_xdo=%2FPrivate%2Fkfabian%2FSalary+Report%2FSalary+Report.xdo&dep=10&_xt=Standard&_xf=html


Lets ignore the first part of the URL, its the same as before, so we have:

?_xpf=&_xpt=1&_xdo=%2FPrivate%2Fkfabian%2FSalary+Report%2FSalary+Report.xdo&dept=10&_xt=Standard&_xf=html

Breaking this string up we have the following parameters on the URL:


  • _xpf - for internal use - just leave it as is
  • _xpt - defines whether the report output should be rendered in the full XMLP window (as above) use a value of 0 or a 1 for just the document itself.
  • _xdo - this provides the path to the current report, its optional so you can leave it out.
  • dept - this is a parameter value for the report, in this case the department for the data, notice it takes the department id. The parameter definition is to show the user the department name and then pass the id to the query. Of course you can have multiple parameters and their values on the URL
  • _xt - this controls the template to be used, this is the template name i.e. Standard not the template file name.
  • _xf - this controls the format of the output to be generated e.g. PDF, HTML, etc


Of course you'll need the obligatory '?' for the first parameter and '&' for the subsequent ones. So you can now create a URL to point to the required report and pass parameter values, output format and template.


Good Luck!
 



 

July 19, 2006

Open World is coming to town ... with lots of XMLP

Its coming ... its even bigger I hear rumors of Oracle taking over a block of Howard Street in San Francisco to "extend" the Moscone Center for the week :o)
This year there will be two XMLP events for EBS and PeopleSoft customers at the Extreme Weekend - lots of hands on stuff to dip your proverbial toes in the XMLP water. Places are limited so book early.
There are also over 20 sessions related to XMLP and its use throughout the all of Oracle including EBS, JDE, PeopleSoft and Enterprise. The sessions are not just from development, we have customer and a partner sessions lined up. Last year they were turning folks away from the doors so get there early too.
Of course the demo pod will be swamped all week but drop by, hang out, have a chat and get a demo or three!













































































Session ID Session Title

S281400
Oracle XML Publisher - Enterprise Reporting and Delivery Platform

S281401
Customer Case Study: XML Publisher Live with all the Bells and Whistles

S281461
Implementing XML Publisher for PeopleSoft Enterprise

S281593
Oracle XML Publisher for E-Business Suite, with Customer (City of West Palm Beach) as a Case Study

S281725
Developing XML Applications using Oracle Fusion Middleware

S281740
Leverage Fusion Middleware Technologies Now with PeopleSoft Financial Management Release 9

S281765
Financial Reporting in Oracle E-Business Suite Financials

S281903
Oracle Enterprise Planning & Budgeting -- What's New

S282107
Understanding the EnterpriseOne Reporting tools and choosing the best tool for your needs

S282232
Oracle E-Business Public Sector Financials in Release 12

S282284
Better Enterprise Reporting through XML Publisher

S282444
Oracle Inventory & Warehouse Management: What's New in Release 12

S282562
Oracle E-Business Suite Release 12 CRM Overview

S282771
Technology Trends in Primary/Secondary/K-12 Education

S282878
E-Business Suite: Tools and Technology

S282881
PeopleSoft Enterprise: Tools and Technology

S282964
Enterprise HCM 9.0 Common Components

S283007
Fusion Technology in PeopleSoft SCM and SRM Products

S283117
Fax, Print and Email from Oracle E-Business Suite Using XML Publisher  

S283151
The Impact of Oracle Fusion Middleware on Implementation Project Strategies for Data Cleanup, Conversion, Integration, Business Intelligence, and Instance Management  

S283168
OAUG XML Publisher SIG  

S283183
JD Edwards EnterpriseOne Tools and Technology X-treme Weekend Program


The above sessions are of course subject to some change but you get the idea.

November 1, 2006

Web Service Datasources for XMLP Enterprise

A recent enquiry about web service support for Enterprise has promted me to spend some time writing up how to do it here ... our docs are somewhat lacking :o( we'll address that in the next release.
Firstly, it can be done, secondly its pretty simple once you understand the limitations and the of course what the WSDL behind the service can actually do.


Im going to use the service described here, http://www.webservicex.net/stockquote.asmx?WSDL. In the WSDL there is a getQuote method that we canuse to get stock quote information. It requires of course a quote parameter value such as 'orcl'. Today it will return:-

  <StockQuotes>
 <Stock>
  <Symbol>ORCL</Symbol>
  <Last>18.47</Last>
  <Date>11/1/2006</Date>
  <Time>4:23pm</Time>
  <Change>0.00</Change>
  <Open>18.56</Open>
  <High>18.65</High>
  <Low>18.34</Low>
  <Volume>31724216</Volume>
  <MktCap>95.960B</MktCap>
  <PreviousClose>18.47</PreviousClose>
  <PercentageChange>0.00%</PercentageChange>
  <AnnRange>11.75 - 19.25</AnnRange>
  <Earns>0.666</Earns>
  <P-E>27.73</P-E>
  <Name>ORACLE CORP</Name>
 </Stock>
</StockQuotes>

.....  nice run up Oracle has had recently!

Anyhoo, how do you get this working in Enterprise.
Step 1: Create a new report

So give the report a name, description, etc then add a new Data Model

Step 2: Define the data model 




Give it a name, the type should be set to 'Web Service', the Details section will update for you. now enter:


WSDL URL - http://www.webservicex.net/stockquote.asmx?WSDL
Method - GetQuote

At this point we can not add the parameter, we need to create in the UI first andthen add it later.

Step3: Add the quote parameter
Click on Parameters and click New to create a new parameter.


Enter the following:


Identifer - whatever you wish
Data Type - String
Default Value - if you want
Parameter Type - Text
Display Label - the user will see this so make it something obvious
Text Field Size - I guess 4 is going to be the max you'll need


Step 4: Add the parameter to the Data Model

Save your work and go back to your new Data Model and click on the 'Add' link next to the Parameters label. The drop box will default in the new parameter.

You're done. Now click on the 'View'link and enter a stock quote and hit the 'View' button and the quote XML will appear. Now all you need is a layout template.

Of course you can create multiple data sources adding a query to the web service and then combine the result into a single report. For those of you with Enterprise installed you can get the report definition here so you can load it to your instance. Remember that the URL is going to be outside of your company firewall so you'll want to start the server up with the proxy parameters.

-DproxySet=true -DproxyHost=www-proxy.us.oracle.com -DproxyPort=80

November 3, 2006

Let's Date ...

Date formatting in XML Publisher is very powerful, it can provide a variety of formats from simple 03/12/99 to 'Friday, December 31, 1999 6:15 PM GMT' ... notice the timestamp and the timezone components. All very neat but how do you get there?


Get the right format ...


Well the first hurdle is to get your dates in the XSD date-time format:
                  YYYY-MM-DDThh:mm:ss+HH:MM
Looks straightforward and you ought to be able to get the database 'to_char' function to serve it up no problem, but there is a wrinkle in there in the form of that 'T' character its used as a separator between date and time components. Try and use that format mask with the to_char and the database will choke ... the format is not recognised. There is hope, even for Oracle Reports under EBS users :)


1. If you are not interested in the time and zone info then just use the 'YYYY-MM-DD' format mask, no need for the 'T'. Oracle Reports and the db support this mask. XMLP will then format the date appropriately. any timestamp is going to be 12:00:00 AM and the timezone will default to GMT
2. Use the XMLP extraction engine - the engine will extract all dates using the XSD mask - simple
3. If you're using Oracle Reports or your own plsql/sql extraction routine and want the timestamp and zone then only way I have found to construct the mask is to use something like:

    to_char(sysdate,'YYYY-MM-DD')||'T'||to_char(sysdate,'hh:mm:ss+HH:MM')


this will at least get the date into the right format.





I stand corrected on this thanks to an anonymous comment, I was playing with masks in the 
db while writing and could not get the format to work, however our anonymous friend has:
to_char(sysdate, 'YYYY-MM-DD"T"hh:mm:ss+HH:MM') which works perfectly ... apologies!

Date formatting and calculations


Now you have date in the right format you can apply masks in the layout very easily. You can either use the MSWord formats or XMLP provides a format-date function ... there is a complete section devoted to the formatting in the user guide. Page 118 is the start and covers all XMLP flavors.
The other advantage of the mask is that calculations on dates become possible with XSLT 2.0, prior to this all dates were treated as strings not much use when it comes to calculating the number of days between two dates. Thats another article in itself ... there are plenty of resources out there now.

November 8, 2006

Introducing Data Templates

Another series of articles on the way ... this time concerning the relatively new data extraction engine from XML Publisher that is currently available in the Enterprise and E Business Suite flavors.


First a little history ... 


Why build another extraction tool, there are others that can generate XML, Oracle Reports, various solutions from the database folks, the list goes on. To answer why you have to understand the volumes of data we are trying to handle here and the furture of reporting for Oracle Applications. For EBS in particular we had multiple reporting solutions, the majority of which were based on Oracle Reports. The plan going forward is to remove Oracle Reports from the techstack in the fusion timeframe. Therefore we needed an extraction engine that offered all that Oracle Reports offers and was just as fast - Oracle Reports is danged fast at generating XML data. On top of that we are not talking about extracting data for a 2 page invoice, the engine needs to extract millions of rows to build tens of thousands of pages for some reports. 
We looked at what was out there, SQL XML provided fast extraction for large data sets but we needed among others, event triggers and flexfield user exits, plus users would need to learn the wrapper functions used to generate the hierarchies. After a lot of research we decided to build an engine ourselves with all the bells and whistles needed to cover the Oracle Reports replacement requirements.


Features ... features ... features


To dig in a little to the features the engine provides:


Fast, scalable extractions - its fast, faster than Oracle Reports. We worked closely with the Oracle Performance team and had to re-write it a couple of times to get their approval. It needs to be fast too, those of you that use Oracle Reports EBS know that out of the box we generate flat text character based output. With XMLP we're generating highfidelity output ... that requires more processing time so the more time we save on the extraction the more we have for formatting without slowing the report generation.


Oracle Reports Features - if its going to replace OR in EBS then it has to match OR on features:


  • Multiple Queries/Joins -  enabling master/detail extractions
  • Event Triggers - pre- and post- fetch for business rule processing. Currently plsql support but will add java
  • Flexfield Support - gotta get that natural account description with out the select statement - this is an EBS feature.
  • Formula/summary columns -  again similar to Oracle Report functionality allowing you to create aggregation values and pl/sql based formula columns in your extraction
  • Data Structure - this allows you to build a hierarchy into your XML data similar to the grouping abilities in Oracle Reports
  • Group filters - a la Oracle Reports
  • etc


on top of that its also has:




  • Rich Java API layer - call a data template from your jsp or java app
  • Distributed Queries - this is neat. You're not tied to a single db nor even to an Oracle db. You can construct a data template that, for example hits an MSSQL instance for customer data and an Oracle db for their invoices. the engine will generate a single result set of hierarchical XML i.e. Customer1
     Invoice1
     Invoice2
    Customer2
     Invoice1
     Invoice2

  • Static XML File support - query across a db and an XML file. Text and XLS support coming.
  • Pluggable Data Templates - not here yet but theidea here is that you can build a core data template and then allow a plugin DT to be applied over the top to get more data from other sources.

Some of you will have wondered what the heck a Data Template is? this is the name we give to the extraction definition, its an XML representation of the queries, joins, data structure, etc.

Thats the brief overview, next Im going to cover some sample Data templates over the next few articles from the most basic to an all singing all dancing EBS DT, I'll also post a jsp appyou can use to test DTs and some help on how to build them.

November 9, 2006

How about another date?

Im interrupting the Data Template flow with a really great question and answer from the forum that I wanted to share on time zone formatting. For those of you that want to include a timezone portion into your output dates XMLP can help but you might not find what you expect!


Let's assume we have the following date element in our data stream:


 2006-07-27T12:48:00.000+02:00

Notice the timezone offset from GMT i.e. Paris, France.
Using 
       <?format-date:DATE_TEST; 'LONG_TIME_TZ'?>
we  get
 Thursday, July 27, 2006 10:48 PM GMT

The GMT appears incorrect we were expecting 'Paris' ... hey thats a bug! Look closer and you'll notice that the time component has been adjusted back by 2 hrs. So it is actually correct for the GMT timezone.
So how do we stop the adjustment and see 'Paris' i.e. Thursday, July 27, 2006 12:48 PM Paris
This can be achieved using:
    <?format-date:DATE_TEST; 'LONG_TIME_TZ';'Europe/Paris'?>
that 'Europe/Paris' is a java time zone specification. The list can be gotten here, http://www.thescripts.com/forum/thread15954.html
This is in the user docs but  a little tough to grasp(;o). If you are in EBS then there is a profile option, more details in the user guide. If you are using APIs the java time zone can be passed into the template as a parameter.  Neat!
 

November 29, 2006

Data Templates by Example

Apologies for the delay ... I have lots of content and examples for you but I did not have a means for you to test your data templates. I have now rectified that and have taken one of our internal testbeds and packaged it up so you can test to your hearts content. The test bed is a web application that runs inside OC4J, I have not tested it with any other mid tier flavors but if you're game.


Before we start on the content lets install the app and test a sample data template.


  1. Download the EAR file here. Well you would be able to download it if I can find somewhere that can host it. for now drop me a mail and I'll get it to you. 

    Finally found a home for the file on my website, you can get the file here, http://www.banzel.com/download/DTTestBed.ear
     
  2. I have tested with OC4J 9.0.4, 10.1.2 and 10.1.3 so once you have the EAR its a simple case of deploying it. If you do not have OC4J installed, go for the latest 10.1.3 release and have a nice UI to help you deploy the app.
  3. Once installed you just need to point your browser to http://yourserver:port/DTTestBed/DT1.jsp
    4. The first page you'll see is:
    DTTB1:


    I have created a small data template that will run against the scott/tiger schema, so download it from here. Then use the browse button to find it and hit Upload.


  4. You'll then get a page like this:


    DTTB2:

    Heres where the fun starts, so in the page you have a parameter section, these are the parameters parsed out of the data template in this case we only have one, pDeptNo. You can fill in a value or leave it blank to get the complete data set.
    Then we have the runtime options:


    • Generate XML Schema  - fairly obvious but very useful if you are going to be doing some PDF template mapping
    • Generate Default Layout - this will generate an RTF template for you based on the data structure of the data template, again useful to get you started
    • Layout Template - if you have already developed an RTF template (no it does not support PDF templates yet) then you can load it to be applied to the resulting data. If you choose this option then a default template will not be generated.
    • Database - we need a connect string to the database, hostname:port:sid
    • User Name - obvious
    • Password - obvious if you have it
    • ORG ID - this is for EBS customers that want to test data templates running against the EBS db - its not required.


  5. So fill in some values so you have something like this:


    DTTB3:


    and hit Submit
    7. If all went well then you'll get a page of results similar to this:


    DTTB4:


    There will be links to the various objects that XMLP has generated. These are all created in a temp directory under the root of the web app in mycase

    D:Oc4j10.1.3j2eehomeapplicationsDTTestBedDTTestBedtemp
    . Be sure to clean that directory up regularly it will fill your disk all to quickly.


So thats the test bed we are going to use in the coming articles ... get it up and running and you'll be able to try your first data template.  

December 13, 2006

Hello Data Templates

Hopefully you have downloaded and installed the Data Template Test Bed I provided in my last post, you may have even loaded and run the sample I provided ... hopefully sucessfully. You may have even gone off and got started on your own. Well we are going to take a step back here and get back to basics and then move up to the more powerful stuff like filters, triggers and flexfields ... we're going to get there quickly so please be patient.


Being the consumate geek and not wanting to break tradition when it comes to starting out with a new technology we're going to build and test a Hello World data template ... now known as 'DTs' for brevity. First lets take a look at the anatomy of a DT, it'll help later.

<dataTemplate name="EMPLOYEES" defaultPackage="" description="Employee Data">
   <properties>
      <property name="include_parameters" value="true"/>
      <property name="include_null_Element" value="true"/>
      <property name="xml_tag_case" value="upper"/>
      <property name="db_fetch_size" value="500"/>
      <property name="scalable_mode" value="off"/>
      <property name="include_rowsettag" value="false"/>
      <property name="debug_mode" value="off"/>
   </properties>
   <parameters>
      <parameter name="pDeptNo" dataType="number" defaultValue=""/>
   </parameters>
   <lexicals/>
   <dataQuery>
  <sqlStatement name="Q1" dataSourceRef=""><![CDATA[SELECT DEPTNO,DNAME,LOC
from dept where deptno = nvl(:p_DeptNo,deptno)
order by deptno]]>
</sqlStatement>
  <sqlStatement name="Q2" dataSourceRef=""><![CDATA[SELECT  EMPNO,ENAME,JOB
,MGR,HIREDATE,SAL,nvl(COMM,0) COMM 
from EMP
WHERE DEPTNO = :DEPTNO]]>
</sqlStatement>
  </dataQuery>
   <dataStructure>
  <group name="G_DEPT" source="Q1" groupFilter="">
   <element name="DEPT_NUM" value="DEPTNO" function=""/>
   <element name="DEPT_NAME" value="DNAME" function=""/>
   <element name="LOCATION" value="LOC" function=""/>
   <group name="G_EMP" source="Q2" groupFilter="">
    <element name="EMPNO" value="EMP_NUM" function=""/>
    <element name="EMP_NAME" value="ENAME" function=""/>
    <element name="JOB_TITLE" value="JOB" function=""/>
    <element name="MANAGER" value="MGR" function=""/>
    <element name="HIRE_DATE" value="HIREDATE" function=""/>
    <element name="SALARY" value="SAL" function=""/>
    <element name="COMMISSION" value="COMM" function=""/>
   </group>
  </group>
 </dataStructure>
</dataTemplate> 

I have highlighted the main players in a DT:




  • dataTemplate - header element where you provide a name and description for your DT. The name will be used as the root name of the element.
  • properties - these are the runtime switches for the extraction engine:

    • include_parameters - should the parameter values be extracted to the XML or not
    • include_null_Element - if a value when extracted is null do you want an empty element in the xml
    • xml_tag_case - upper or lower case tag names
    • db_fetch_size - maximum number of records to fetch
    • scalable_mode - if you know this is going to be a large dataset or an intensive extract then set this to true
    • include_rowsettag - for simple XML with no hierarchy do you want ROWSET as the root element
    • debug_mode - generate a debug file while processing or not. The test bed I posted will always do this for you.
Moving into the main section:

  • parameters - these are the runtime parameters for the DT
  • lexicals - these are EBS specific and will allow you to fetch flexfield values ... more on these later
  • dataQuery - heres where we start to define the
    sqlStatement - this is where we define the query(s)
  • group - this section defines the structure of the data we want to see and contains
  • element - the reference to the column in a specific query. These also have a name for the resulting XML element and you can include functions here.

So thats a quick overview, lets do the HelloWorld ... its as simple as it gets when it comes to DTs.

<dataTemplate name="HELLOWORLD" defaultPackage="" description="Hello World DT">
   <properties>
      <property name="include_parameters" value="true"/>
      <property name="include_null_Element" value="true"/>
      <property name="xml_tag_case" value="upper"/>
      <property name="db_fetch_size" value="500"/>
      <property name="scalable_mode" value="off"/>
      <property name="include_rowsettag" value="false"/>
      <property name="debug_mode" value="off"/>
   </properties>
   <parameters/>
   <lexicals/>
   <dataQuery>
  <sqlStatement name="Q1" dataSourceRef=""><![CDATA[select 'Hello World!' WELCOME from dual]]></sqlStatement>
 </dataQuery>
   <dataStructure>
  <group name="HELLO" source="Q1">
   <element name="WELCOME" value="WELCOME"/>
  </group>
   </dataStructure>
</dataTemplate>
Running it thru the test bed, this is going to generate the following XML:
<?xml version="1.0" encoding="UTF-8"?>
<HELLOWORLD>
 <HELLO>
  <WELCOME>Hello World!</WELCOME>
 </HELLO>
</HELLOWORLD>
Simple stuff, you can see the relationship now between the DT name - HELLOWORLD, group - HELLO and element name WELCOME.
So thats the basics, next we'll build on the HR schema and introduce some more features.

February 16, 2007

Joining Queries a la Francais

Bonjour mes ami!


I have just got back from a conference in the warmer climes of the French Riviera. Its been quite a shock; after nearly a week of mid 60s temperatures and blue seas coming back to somewhat chilly and mid 30s Colorado has taken some getting used to again. Thankfully the promised thaw is upon us and the piles of snow in my yard are now dwindling, much to my sons' chagrin the snowboard run we had in our back yard is becoming a distant memory. Ahh c'est la vie ... so to another article in the fragmented data template series.

I have spent some time looking at our documentation on data templates, its pretty good so please check it out. Im picking on a series of some of the tougher features to get your head around. for this article its creating and joining multiple queries.


There are two methods to join queries, lets assume we have the following queries:






SELECT DEPTNO,
DNAME,
LOC
FROM DEPT
ORDER BY DEPTNO
SELECT  DEPTNO,
EMPNO,
ENAME,
JOB,
MGR,
HIREDATE,
SAL,
NVL(COMM,0) COMM
FROM EMP


we want to create a data template that will use the DEPT query as the master and the EMP as the child. We need to link the two queries.


Method 1: Query Link

We can create a link similar to Oracle Reports, like this:

<link name="DEPTEMP_LINK" parentQuery="Q1" parentColumn="DEPTNO" childQuery="Q_2" childColumn="DEPTNO"/>


We name the link and then specify the queries and the linking columns, so the <dataQuery> section of our data template will look like:


<dataQuery>
 <sqlStatement name="Q1">
 <![CDATA[
    SELECT DEPTNO,DNAME,LOC from scott.dept
    order by deptno ]]>
 </sqlStatement>
 <sqlStatement name="Q2">
  <![CDATA[
     SELECT  DEPTNO, EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,nvl(COMM,0) COMM
     from scott.EMP ]]>
 </sqlStatement>
<link name="DEPTEMP_LINK" parentQuery="Q1" parentColumn="DEPTNO" childQuery="Q_2" childColumn="DEPTNO"/>
</dataQuery>


It works fine but we have to duplicate the DEPTNO column in the child query. Plus on a more real world query its going to be slower than taking ...

Method 2: Bind Variables


We did alot of testing on the joining of queries and found that usng bind variables was consistently faster then query links, so if you can, and there should not be a reason why you should not, use binds. What do I mena by bind variables, well taking our two queries we are able to have a master-detail relationship between the two i.e. the dept based query is the master and the emp the detail. We can join them quite easily using 'dept_id' as our joingin criteria:

<dataQuery>
 <sqlStatement name="Q1">
 <![CDATA[
    SELECT DEPTNUM,DNAME,LOC
from scott.dept
    order by deptno ]]>
 </sqlStatement>
 <sqlStatement name="Q2">
  <![CDATA[
     SELECT  DEPTNO, EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,nvl(COMM,0) COMM
     from scott.EMP
where DEPTNO = :DEPTNUM ]]>
 </sqlStatement>
</dataQuery>

Notice, I have changed the column names a little just to make the join clearer (dont cut 'n' paste this one.) We use :DEPTNUM from the first query in the where clause of the second, et voila we have two queries joined. Its simpler, less typing and even better its faster!
Salut!

February 19, 2007

Data Templates without grouping

While I have been away I provided two days on in depth techie training to Oracle Consulting in EMEA, they worked me hard (very hard) ranging from inserting barcodes to bursting, all good fun and informative I hope. The second day we spent some time sharing experiences of developing extractions, templates, etc and Im indebted to Serge Vervaet from Oracle Belgium for some great tips. The first of which was on building a data template. The XMLP extraction engine is fast, you can migrate your Oracle Reports to the format relatively easily but there is currently no tool to help you build them so once you have your query sorted out its off to Notepad or an XML editor. For big extracts with lots of columns even I have to admit its very tedious typing out those grouping structures, Serge came up with a way to reduce the tedium and speed up the process by doing away with the grouping section all together - use inline CURSORS in your queries. This creates all the hierarchy you need in your query without the need for the grouping section.


Lets take our old friends the EMP and DEPT queries:







SELECT DEPTNO,
DNAME,
LOC
FROM DEPT
ORDER BY DEPTNO
SELECT  DEPTNO,
EMPNO,
ENAME,
JOB,
MGR,
HIREDATE,
SAL,
NVL(COMM,0) COMM
FROM EMP


To get a hierachical XML output we need to add the following data structure.  


<dataStructure>
  <group name="G_DEPT" source="Q1" groupFilter="">
   <element name="DEPT_NUM" value="DEPTNO" function=""/>
   <element name="DEPT_NAME" value="DNAME" function=""/>
   <element name="LOCATION" value="LOC" function=""/>
   <group name="G_EMP" source="Q2" groupFilter="">
    <element name="EMPNO" value="EMP_NUM" function=""/>
    <element name="EMP_NAME" value="ENAME" function=""/>
    <element name="JOB_TITLE" value="JOB" function=""/>
    <element name="MANAGER" value="MGR" function=""/>
    <element name="HIRE_DATE" value="HIREDATE" function=""/>
    <element name="SALARY" value="SAL" function=""/>
    <element name="COMMISSION" value="COMM" function=""/>
   </group>
  </group>
 </dataStructure>
This is not too bad but imagine a real world data template with 3 or 4 levels ... without that tool its a long and arduous slog! Yes, we need a builder for you, working on it! We can avoid the grouping altogether by combining our queries.


SELECT DEPTNO,
  DNAME,
  LOC,
  CURSOR(SELECT  EMPNO,
           ENAME,
           JOB,
           MGR,
           HIREDATE,
           SAL,
           nvl(COMM,0) COMM 
      from EMP ) as EMP
  from dept
  where deptno = nvl(:p_DeptNo,deptno)


Notice the CURSOR command and the 'as EMP' the latter will create the group G_EMP in the XML data:


<EMPLOYEES>
 <PDEPTNO>10</PDEPTNO>
 <LIST_DEPT>
 <DEPT>
  <DEPTNO>10</DEPTNO>
  <DNAME>ACCOUNTING</DNAME>
  <LOC>NEW YORK</LOC>
  <LIST_G_EMP>
   <G_EMP>
    <EMPNO>7369</EMPNO>
    <ENAME>SMITH</ENAME>
    <JOB>CLERK</JOB>
    <MGR>7902</MGR>
    <HIREDATE>1980-12-17T00:00:00.000-08:00</HIREDATE>
    <SAL>800</SAL>
    <COMM>0</COMM>
   </G_EMP>
    ...
   <LIST_G_EMP>
  </DEPT>
 </LIST_DEPT>
</EMPLOYEES>


So we saved some time and effort and still got structure we needed. Sample DT here. I have to say we have not exhaustively tested the performance but Serge is getting good results and reducing his development time :o)

February 20, 2007

Whats in a name?

Many of you will have noticed, maybe even been confused by another product that has hit the Oracle streets namely 'Business Intelligence Publisher', BI Publisher for short and now affectionately know as 'BIP' by the cognoscenti.
Its not a new product, its XML Publisher with a new identity for its place in the BIEE suite of products, where it now generates the 'high fidelity' output from the BI Suite (more on this in a later posting.) Its also the new name for the recently released 10.1.3.2 Enterprise release, BIP Enterprise, again, more on that later too.
For now it remains as 'XML Publisher' under E Business Suite PeopleSoft Enterprise and JD Edwards EnterpriseOne and World products. Have no fear they may have different names but under the covers its the same core engine at work. 


Update on versions ...


Yeah, things are getting complex on our numbering system  so here's the low down. Im mapping ERP releases to the original XMLP release numbers ...


Applications
EBS 11.5.10  - baseline release comes with R4.5
EBS 11.5.10 RUP2 - comes with R5.0
         Of course for EBS 11i you can apply the latest XMLP release from metalink 5.6.2. The 5.6.3 release is coming soon.
EBS R12 - baseline release comes with release 5.6.3
PeopleTools 8.48 - comes with release 5.6
JD Edwards - comes with 5.6

BI EE & Standalone

BIEE Release 10.1.3.2 - contains BI Publisher 5.6.3
BI Publisher Enterprise 10.1.3.2 - based on 5.6.3 release.

February 21, 2007

Empower your users ...

Our marketing and I would have you believe that XML Publisher can empower your end users to build their own layouts and for the majority of your reports I still think thats true; creating listing reports with sub totals, re-grouping and page breaks are well within the capability (after a little training) of all but the most ardent technophobe. But when it comes to more complicated documents, usually the customer facing types, invoices, purchase orders, etc they very quickly need to get into some more advanced features which the template builder does not yet support and IT needs to step in. But IT does not need to do it all and revert to the slow report development seen before the advent of XMLP.


Another great tip from Serge in EMEA consulting came out at last weeks training event. Give the user a blank MSWord document and one formfield ... now ask them to design the complete layout of a report use the formfield to position the data and put in some sample data into the fields and even go as far as formatting them i.e. date, string or number. Then have them mark up the document with the look and feel they want, logos, colors, etc. If they think an invoice is going to stretch across multiple pages have them design the second and possible subsequent pages. Once they are happy with it, get them to sign off on it, you can then enable the template putting required data tags and for-each structures. Before handing back to the user for testing with some sample data Serge goes as far as to hide the form fields that contain the logic for the report from the user. This is simple enough, just mark the control fields and then set the font to hidden, you can use the ¶  to show/hide the fields. If the user needs to move data about, they can without getting worried about 'breaking' the report. Word of caution here thou, they could move things around just that little too far.


So even on the tougher templates the end user can still be involved in the design and get what their users want in the output and get that report out and into production much faster <:o) 

February 22, 2007

More Charts Anyone?

Charts charts charts ... yep XMLP/BIP can do em ... in fact it can do about 30 different types but the Insert Chart dialog of the template builder now only exposes about 6 of them, with a few bells and whistles ... if you want to go further then you have to get coding. I've covered some alternatives for the coding in previous posts but Im now posting what I hope is going to be a useful 'cheat sheet' for some of the tougher chart styles. Again, thanks to another Oracle Consulting star, Kan Nishida who put the samples together you can now quickly grasp how to put together the following chart types:



  • Multi Bar Chart
  • Dual Y Bar Chart
  • Split Dual Bar chart
  • Vertical Bar Stack
  • Line Chart
  • Dual Line Chart
  • Pie chart
  • Pie Ring Chart
  • Multi Pie Charts
  • Area Chart
  • Area Vertical Stack

Some easy ones, some not so easy, Kan has provided some useful hints in the template on whats needed for a specific chart type and of course you can always take a look at the web properties for the dummy chart images to get a better idea. RTF template, XML data and PDF output available here.


Update
Got a request for a multi bar/line combo chart ... here it is.

March 1, 2007

BI Publisher Enterprise 10.1.3.2. comes out of hiding

The name is a bit of a mouthful when combined with the release version but  some of you may have noticed but maybe not? that there is a new version of the BIP Enterprise server out there. Not 'hot off the presses' news I know ... its been here for a few weeks now but hidden under the skirts of the latest BIEE release.  It has alot of new functionality across the board and I'll cover some of that over coming entries.


Today, BIEE Integration points, a lazy post for me because thanks to Abhinav on the BI Blog there is already content out there on the BIEE Integration - you can now use BIP to generate those high fidelity outputs based on Answers, direct BI server queries or from other sources and then embed them directly inside a dashboard page for your users. Check out the integration details here.


As of today you can only get the BIP release from the BIEE download details available here. We are working on posting the standalone release to OTN asap.


 

March 12, 2007

Getting started with BIP APIs

Had a request today asking how to get started with the BIP API layer. I think the use of the APIs is straightforward enough, there are lots of examples to get you started in the developer sections of the user guide. The tough bit is, what libraries and jars need to be in the class path to be able to work with the APIs without annoying compile errors? So heres the list:


  • xdocore.jar  - the core BIP/XMLP library
  • aolj.jar - this is an Oracle EBS library, we need it whether you're developing in EBS or not
  • i18nAPI_v3.jar - this is the i18n library used for localization functions
  • xdoparser.jar  - this is the scalable XML parser and XSLT 2.0 engine
  • xmlparserv2-904.jar  - the main XML parser/XSLT engine - these will come together again in a coming version.
  • bipres.jar - charting library
  • bicmn.jar - charting library
  • jewt.jar - charting support library
  • share.jar - charting support library
  • collections.jar - you only need this if you are working with the delivery APIs or bursting engine.

Now if you're using JDeveloper then the charting and XML Parser libraries will already be available to you. I'd recommend creating a directory with all of the above thou and using them as custom libraries in your project. That way you'll know when it comes to deployment you're not going to get any unexpected surprises at runtime.

Where to get the libraries:
1. EBS - you can point your java project to the JAVA_TOP directory  - not the simplest solution
2. Download the BIP Server and open the EAR file and find the jars
3. Download the Template Builder for Word, install and check the jlib library under the install directory.


So now you know what you need and where to get it.


Need a quick start ... how about applying an RTF template to some XML and generating PDF output ...

package xdotestbed;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import oracle.apps.xdo.XDOException;
import oracle.apps.xdo.template.FOProcessor;
import oracle.apps.xdo.template.RTFProcessor;

public class XDOTest
{
  public XDOTest()
  {
  // Need to use a try-catch block
  try
  {
    // Set the RTF template
    FileInputStream fiS = new FileInputStream("c:\\temp\\check.rtf");
    //Instntiate the RTFProcessor
    RTFProcessor rtfP = new RTFProcessor(fiS);
    // Set the output XSL
    rtfP.setOutput("c:\\temp\\check.xsl");
    // Process
    rtfP.process();
  }
  catch (FileNotFoundException ex)
  {
    ex.printStackTrace();
   }
  catch (IOException ex)
  {
    ex.printStackTrace();
   }
  catch (XDOException ex)
  {
  ex.printStackTrace(); 
   }
  
   //Now process the XSLFO template against the XML data
      // Instantiate the FOprocessor
      FOProcessor processor = new FOProcessor();
      // set XML input file
      processor.setData("c:\\temp\\check_data.xml");
      // set XSL input file
      processor.setTemplate("c:\\temp\\check.xsl");
      // set the output format
      processor.setOutputFormat(FOProcessor.FORMAT_PDF);
      //set output file
      processor.setOutput("c:\\temp\\check.pdf");
    // Now we process, have to surround with a try-catch block thou
    try
    {
      // Process !
      processor.generate();
    }
    catch (XDOException e)
    {
      e.printStackTrace();
    }

  }

   // Heres the main method to run the class.
// You could of course add arguments for the RTF, XML

// and output PDF and avoid hard coding them in the class.
// Sorry, Im being lazeeee ...

public static void main(String[] args) {
        XDOTest xDOTest = new XDOTest();
    }
}



Not too tough right ? With a little effort you can get the whole thing streaming rather than writing to disc, bolt on a call to the Data Template engine to fetch the data, use the FormProcessor to stick multiple outputs together ... the list goes on.

March 22, 2007

Setting Organizations for Data Templates

Quick one today, trying to work on the bursting series ...
You have developed Data Templates for your EBS instance, but what about setting the org id. In good ol Oracle Reports you just added the following command in your before report trigger:


srw.user_exit('FND SRWINIT')


and it was all done for you. In the world of BIP we go one step further. The executable that runs your data template sets the org id for you so you do not have to do anything.

Now there is a caveat to this, as long as you are using the BIP delivered executable (XDODTEXE) in EBS to call the data engine to run your data templates you're fine ... if you are accessing the data engine via the java APIs or the BIP Enterprise release then its your responsibility to set the org id before the query executes. The simplest way to do it is to call a pl/sql package in the pre-fetch trigger and in there set the org id:


fnd_client_info.setOrgContext(ORG_ID)


then you're set and you'll get the data you are expecting ... well as long as you wrote the query correctly of course ... been there done that, got the T shirt :o)

March 27, 2007

Anatomy of a Template I - Fixed Row Enumeration

The bursting articles are still in process ... I did some work a while back for a training course on the 'anatomy of an invoice template' ... there are some useful 'bits' that I thought you might like to see. 


One of the most requested features on the forum for RTF templates is to show a fixed number of rows per page. Maybe you have pre-printed stationary that can only take a certain number of lines, maybe you have a functional requirement for it. For whatever the reason id the functional folks have given it to you to implement.  Up until now there has been a template floating around that I think I let loose that shows how this can be done for invoices. There is little explanation of whats going on and how it's done. I'll try and make ammends to those of you that may have gotten a little lost but plugged it in anyway and it worked so what the heck.


I have started off small and we'll build this template up into a full invoice format that can run against the standard AR Oracle Report in 11i (RAXINV) ... those of you that are not EBSer's or are not interested in the invoice format, dont worry, you can follow along and apply the same principles to any data set. Here's the features out template is going to have.

1. A fixed number of rows per page,
2. 'Filler' space for lines, because that last page may only have 3 lines but you want to maintain the layout
3. Page totals or 'Continued' in place of a total
4. Last page only content
5. Header and page number resetting as we hit each new invoice in the batch.


For all of the explanations we are going to use the attached XML. Its a full invoice batch, thats multiple invoices having multiple lines.

The Data


Lets start with number 1, for the fixed row enumeration we are only interested in the lines section of the XML, so we can focus on this portion Im going to ignore the rest of the XML. We are only interested in the G_LINES group of the XML structure:

<G_LINES>
 <LINE_NUMBER>1</LINE_NUMBER>
 <LINE_CUSTOMER_TRX_ID>1903</LINE_CUSTOMER_TRX_ID>
 <LINE_CUSTOMER_TRX_LINE_ID>1801</LINE_CUSTOMER_TRX_LINE_ID>
 <LINE_CHILD_INDICATOR>0</LINE_CHILD_INDICATOR>
 <LINE_TYPE>LINE>LINE</LINE_TYPE>
 ...
</G_LINES>
<G_LINES>
 <LINE_NUMBER>2</LINE_NUMBER>
 <LINE_CUSTOMER_TRX_ID>1903</LINE_CUSTOMER_TRX_ID>
 <LINE_CUSTOMER_TRX_LINE_ID>1817</LINE_CUSTOMER_TRX_LINE_ID>
 <LINE_CHILD_INDICATOR>1</LINE_CHILD_INDICATOR>
 <LINE_TYPE>LINE>LINE</LINE_TYPE>
 ...
</G_LINES>


There are obviously a lot more elements and a lot more lines but all we are interested in is, the grouping and the line type for now.


The Template


Now take a look at the template; if you just look at the table and nothing else it all looks pretty normal. We have a for-each, some fields followed by an end for-each ... straightforward stuff right. You'll notice the for-each has a little more going on thou and there's that 'if' condition:

<?for-each:$invLines?>
<?if:position()>=$start and position()<$start+$lpp?> 

I'll come back to these, lets look first at the fields above the table:

LinesPerPageVariable - this does what it says on the can and sets up the number of lines we want to see per page and assigns it to a variable 'lpp'. Now remember native XSL 'variables' are not like other language variables, think of them more as constants.
        
        <xsl:variable name="lpp" select="number(15)"/>

LinesTreeVariable - this holds not just a single value but a complete tree of values. Word of caution here, if you are going to do this you need to be aware that the XSLT engine is going to load this tree into memory ... so do not load huge trees. In our completed invoice template we will only load the lines tree for each invoice. In this example we are loading all the lines in the XML regardless of invoice ... thats OK thou, our XML is small, just be aware of what are doing here.
We have a variable 'invLines' and we are loading the members of the G_LINES group where the TYPE is equal to 'LINE'. Notice we use an XPATH expression to do this. We also use the 'incontext' command to ensure we are picking up the lines only for the current position i.e. within the current invoice. For this example remember we have no invoice header so we pick up all lines into the tree.

          <xsl:variable xdofo:ctx="incontext" name="invLines" select=".//G_LINES[LINE_TYPE='LINE']"/>

FEinvLines - this is the first loop we need to to go over the G_LINES group we created earlier. Although there is only a single group we need to iterate over it so we can set up a variable to hold the starting line position.
The if statement is checking if the record position we have reached modulizing with the line per page count equals zero i.e. we have reached the first record
 the create a variable (constant) called 'start' and initialize it with '0'.

<?for-each:$invLines?>  
 <?if:(position()-1) mod $lpp=0?>  
   <xsl:variable name="start" xdofo:ctx="incontext" select="position()"/>


Now we get into the table, the first field in their is another for-each but this time we are going to loop over the members of the invLines tree. Notice the use of the '$' to reference the variable.


<?for-each:$invLines?>
 <?if:position()>=$start and position()<$start+$lpp?>

The if statement here is checking that the current record pointer 'position()' is either greater than 'start' ie the first record or less the 'lpp' value we set up earlier. If it is then show the record otherwise not. the rest of the table is standard stuff.

Now we wanted a fixed number of rows per page and the logic above will provide that but of course the template needs to signify the need for a page break after the alloted number of rows have been shown. Looking at the 'Page Break' field:


<xsl:if xdofo:ctx="inblock" test="$start+$lpp<=count($group)">
 <xsl:attribute name="break-before">page</xsl:attribute>
</xsl:if>

We have an 'if' statement wrapped around the page break instruction. This is just like the if in the table, if the specified number of rows has been met then insert a page break.

So thats fixed row enumeration, hope things are a little clearer. Next we'll add in the header for th invoices so we can then ensure we have a fixed layout per page of each invoice. Complete template, data and PDF are here.

March 28, 2007

Anatomy of a Template II - Headers and Filler

Continuing on from yesterday, today we'll add in the repeating header and a filler for the invoice lines. Imagine you have pre-printed stationary, yesterday we tacled how to get X number of lines on each page, now assume that on the last page of the document you need a summary at the bottom of the page. If that last page only has 5 rows of data and we were printing 20 rows on the previous pages then once the 5 rows are rendered the summary will then render directly under the five rows i.e. not at the bottom of the last page ... still with me? With 5.6.2 we introduced the concept of a last page only command; we could use that here but I want to continue with the idea of filler rows and we'll tackle the last page only option later.


Taking a batch invoices as our example we can add the header and the filler rows.


Reset your Head


For the header we want to have say an invoice header with page numbering, etc. As we hit a new invoice we want the header information to change and the page numbering to reset. To do this we can use the '@section' option for the for-each command. We create the header layout in the MSWord header.


InvoiceHeader:


Notice we can not put formfields in to the MSWord header section so we either need to type in the commands or use a header template and reference it.
The only extra fields added are:a
FE G_INVOICE - this starts the looping over each invoice using the @section to reset the header information as each new invoice is reached.
         <?for-each@section:LIST_G_INVOICE?>
EFE - this closes out the loop above

Running this template (Inv_Header.rtf) gives us two invoices with a repeating header on each page with page numbering per invoice.

Spaced Out

Now lets add the logic for the filler rows, you can see the new fields and empty table just below the lines table in the Inv_Header_Spacer.rtf template. There are two new fields
Filling Out Space - this contains the logic to check if the number of rows rendered above equals the lines per page variable. If not then insert the table row until it does.
<?if:not(count($invLines) mod $lpp=0) and ($start+$lpp>count($invLines))?>
  <?for-each:$invLines?>
     <?if:positio