Friday, March 07, 2008

ETL: Practical Example of Data Transformation Using Kettle

I’ve written about Kettle before. I personally think it is a great tool, and its easy to tell that this was written by someone who works with annoying data formats on a consistent basis. Well, Kettle is now known as the Pentaho Data Integration Project, and its now up to version 3. For brevity’s sake, I will just refer to it as Kettle going forward. Of course, none of this changes the functionality of the tool. In this article I am going to show a practical application of how I have been using Kettle to assist in the generation and transformation of annoying data formats.

I recently had to work with a feed from an entertainment vendor who distributes DVD, music CDs, and such. To the stores that use these files, they provide a rather confusing set of flat, tab delimited files, in a very un-userfriendly format. Since the store I was working for has a predefined format they want vendor files in to work with their search and navigation backend, we needed to transform these files to that format. This is where Kettle comes in.

The first file I need to deal with from them is their Products file. The file contains roughly 28 fields with various numbers that make no sense to me what so ever. The only fields I need to concern myself with are the Product ID, Product Name, Internal ID (used for mapping with the other files), a Category ID, the Artist, Price, and Availability Date. The other fields I can ignore. Since I am dealing with Categories I also need their Category file. Categories are going to be handled in a special way. I don’t need this in my actual file, but in a separate file, or files rather, that will be appended to a separate set of files only once. And the final file I need out of their set is their Attributes file, which will contain information about products such as if the product is Widescreen, Dubbed, Subtitled, etc. These are handled in a special way in the search backend, so I just need to provide them.

Figure 1. Conceptual Model of Data

What I need to do is transform this data into the format in Figure 2.

Figure 2. The Data Feed Format

The Artist field will go into Search Field 1, and the first two attributes I come across will go into search fields 2 and 3. Everything else will be a simple 1 to 1 mapping.

To get started, the first thing I need to do is start Kettle.exe, and create a new transformation. If you are using a repository, great, otherwise, choose No Repository at the startup screen. When you are in Kettle, go to File/New/Transformation.

Figure 3. New Transform

With the new file created, drag over 3 new Text File Inputs, located under the Core Objects/Input section, to the transformation area.

Figure 4. New Text Inputs

With the three text file inputs in the transformation, I need to set them up to read my data files. The first thing is to add the file to the input file list. Do this by clicking on Browse, then when you select your file, click on add. With the file selected, I now need to set up the delimiting information. These files are all tab delimited, with no text qualifiers (meaning no quotes around Strings), and no header row. So I click on the content and set the appropriate options. Since this is a tab delimited file, I need to click on the Insert Tab button to add in the tab.

Figure 5. Delimeter Options

Now I need to select the fields. To do that, since I have my file, all I need to do is click on the Get Fields button under the Fields tab. For developments sake, I will just name the fields that I need, and leave the field names alone for the remaining fields. Also, since I am just using these fields as description fields, I change the Date fields back to Strings.

Figure 6. Field selection

That’s it for Products, I do the same for the Categories and Attributes Tables. Now that the text inputs are set up, I need to do the transformations. The hardest part will be to denormalize and join the attributes into my input stream to feed into my output text file. The first step I need to take care of is sorting my data for the field row delimeter. So, I drag over a Sort Rows object from under the Transformation section. I need to connect the Attribute text data source to the Sort Rows object in order to edit it correctly. In order to do the connection, I need to hold down the Shift key on my keyboard, and drag my mouse from the Attibutes object to the Sort Rows object. This will indicate to the transformation that a “hop” in steps needs to occur between these two objects. Now, I edit my sort to sort based on the Product ID.

Figure 7. Sort Row Options

Next, I drag over a Select Values object and connect the Sort Rows object to it. In the Select/Alter tab, I click on Get Fields and leave everything default. Since I wont be using the non-named fields, I go over to the Remove tab, and select those fields.

Figure 8. Remove Fields

That was the easy part. Now I need to denormalize the data. What I want to do is have the first 3 attributes for each product to show up in consecutive columns. I tried using the Denormlizer here, with no success. So I ended up using the row flattener. The way the row flattener works is you define a single field that will contain the consecutive data. You then define additional columns. The flattener will then copy to each column in the order it receives data. So for example, lets say you have the following data defined in a field in your incoming data stream:

-Wide Screen

-Sub Titled

-Spanish

And in your row flattener, you defined the following target fields:

-FieldOne

-FieldTwo

-FieldThree

The flattener would assign the values like so:

-FieldOne = Wide screen

-FieldTwo = Sub Titles

-FieldThree = Spanish

It also seems that once unique values have been exhausted, it will just finish filling out the columns with the last unique value it encountered. For my purposes this is just fine. I define my field flattener with my values for Attribute Name in the following figure.

Figure 9. Field Flattener

So, with this final step in my transformation, my data stream for attribute will look something like:

-ProductID

-InternalID

-AttributeName

-Search_Field_1

-Search_Field_2

-Search_Field_3

-Search_Field_4

Now, I need to join it to my Products data stream. To do this I pull over a Join object. I need to join on my Internal ID or my Product ID since they both uniquely identify my product. So I will set that as the join. I also need to set this join type to Left Outer Join, since I need Products to show up even if there are no Attributes to join with. I also will set Products as my Primary feed with Attributes as my secondary feed. It is important that when you do the connections in the Transformation editor that you connect both the Products Text Input and the Row Flattener object.

Figure 10. Join

The final thing I need to do to my transformation is modify the Product ID. Since this is for a test feed, I need the product ID to be unique. I will do this with Java Script. I also need to modify the attribute field to remove any pipes in the data field, since my output file needs to be a pipe delimted text file. So, I will drag over a Java Script component, and in Javascript I will write the appropriate code to add in increments of 10 million to the product ID (which I will modify in sequential runs), and use the string replace method to replace any pipes.

Figure 11. Javascript Code.

The final part of this is to output my text file. I need to set my file name for output, delimiting options, and fields I will use in my Output File object.

Figure 12. Output Text Filename

Figure 13. Output Text Delimeter

Figure 14. Output text fields

You will notice in Figure 13 I have Append set. This will append every run of the transformation to the end of the output text file. I also have Price in twice since the Display Price and Actual Price are the same.

Now, the final part of this transformation is the Categories. The only thing I need special for Categories is a hard coded entry for my Super Category mapping in the internal search appliance for my categories in the vendor data feed. I accomplish this through a JavaScript component between the Categories Text Input and the Output files. I won’t show the Output files for Categories since it isn’t relevant to my main transformation with the Attributes and Products. The final figure shows my finished Transformation.

Figure 15. Finished Transformation

Now, I can create my dummy feed and add to it at the click of a button. Of course, this is applicable to actual production data transformations as well. Kettle does run a little slower than a hand coded solution, but not enough to rule it out due to the amount off time it saves in development and the amount of time saved in modifying it when necessary.

Tuesday, March 04, 2008

Wii: Error Code 209552 After System Update

So I got my Wii back online after a long period of neglect in that area. Since the wife and I have been playing a lot more, I decided it was time to get it back online. I'm also waiting to see if they ever release the original Super Smash Bros on the Virtual Console (no luck so far).

So, I get my Wii online, do the system update, and lo and behold, I can't connect to the Wii Store Channel. I kept getting an error 209552. I am not sure what caused this, since I have also recently changed wireless routers, but the dang thing wouldn't connect after the system update (had enough connectivity beforehand to at least get a system update).

To fix this, I ended up having to change the broadcast channel on my wireless router from 6 to 1. Once I changed that, everything worked like a charm again.

Saturday, March 01, 2008

Book: Press Release

Design and create reports quickly with the Eclipse-based Business Intelligence and Reporting Tools system using new book


Packt is pleased to announce a new book on Business Intelligence and Reporting Tools (BIRT) that provides understanding and structure in a fast paced, task driven and tutorial style. Practical Data Analysis and Reporting with BIRT focuses on the most visible and familiar product built with the BIRT framework, which is the BIRT Report Designer.


BIRT, which stands for Business Intelligence and Reporting Tools, is an Eclipse-based open source software project that provides reporting and business intelligence capabilities for rich client and web applications, especially those based on Java and J2EE. BIRT is in fact a collection of development tools and technologies used for developing reports utilizing the BIRT runtime framework component on an application server. BIRT has two main components: a visual report designer within the Eclipse IDE for creating BIRT Reports, and a runtime component for generating reports that can be deployed to any Java environment.


This book has a fast-paced, task-driven, tutorial style, which provides understanding and structure, not just lists of steps to follow. The focus is on the most visible and familiar product built with the BIRT framework, which is the BIRT Report Designer. The BIRT Report Designer is an Eclipse plug-in that utilizes BIRT technologies to allow users to design reports in the BIRT document format. Also covered is the BIRT charting engine, which lets you add charts to your application.


Java developers who want to get reporting as quickly as possible will find this book useful. The book is published by Packt and is available now. For more information, please visit: http://www.packtpub.com/practical-data-analysis-reporting-with-birt/book

Thursday, February 28, 2008

DB2: Remote Client Connection

I had a hard time connecting to a DB2 server after the remote client was installed. I'm not an expert on DB2, so I decided to notate this for others.

-From a command prompt, export a environment variables needed to run:

export DB2INSTANCE=db2inst1
export INSTHOME=/export/home/db2inst1

-Run DB2 and set the database catalog to the remove connection:


db2 => CATALOG TCPIP NODE UNIQUENODENAME REMOTE 192.168.1.10 SERVER 50000;

-Now, set database name to connect through the new node:

db2 => catalog database mydatabase as mydatabase at node UNIQUENODENAME

-And finally, connect to the database:

db2 => connect to mydatabase user username using password

Monday, February 25, 2008

Announcement: Release of "Practical Data Analysis and Reporting with BIRT"

I am pleased to announce the release of my first book "Practical Data Analysis and Reporting with BIRT". Also available from Amazon. After a long an grueling process, I am glad that it is finally complete and out. It is definitely a learning experience to write a book, so I hope you enjoy it.

Wednesday, February 20, 2008

BIRT: BIRT Reporting for Microsoft Access Using JDBC-ODBC Bridge

I'm speaking at EclipseCon 2008

Occasionally the question comes up asking how can one access a Microsoft Access database within BIRT. There are a number of different ways of doing this. The easiest is to use the Java JDBC-ODBC bridge, set up a ODBC connection on your system, and access it this way. This is the way that we will illustrate in this article. Additionally, you can also use a third part JDBC Access driver, and set it up as you would any other JDBC driver in BIRT. I have yet to find a good, free driver for this, although I haven’t looked either. If you were really looking for punishment, you could write your own driver, but that is a road I have no desire to go down since the simpler solution exists. Keep in mind, the limitation is that the Access database in question needs to be in a path that is accessible for the ODBC hosting system.

For this example, I am using the Northwind Sample Database located at http://www.microsoft.com/downloads/details.aspx?FamilyID=C6661372-8DBE-422B-8676-C632D66C529C&displaylang=EN.s

I installed the database to C:\TEMP\

Setting Up ODBC

Now I need to set up an ODBC connection to the Access database. I am using Windows XP Pro, so my instruction will reflect that, using the Classic theme. First, I go to the Start menu, under Control Panel. Under Control Panel, I click on the Administrative Tools icon. Then I click on the Data Sources (ODBC) Icon.

Now, because I want this to be accessible through to the System, I click on the System DSN Tab.

Next, I click on the Add button. In the dialog that pops up, I click on Microsoft Access Driver (*.mdb).

In the following dialog, I fill out the information. I name my database NorthWind, and put in a simple description.

Next, I click on the select button. This will bring up an older Windows 3.1 style file browser. I navigate to the C:\Temp folder, and choose the Northwind Sample Database.

From that point I am done, and hit OK and save this configuration. I test that this setup is valid by creating a dummy .UDL file on my desktop, and using the wizard to do a test connection.

Configuring BIRT

Now that I have an ODBC entry made, I need to configure BIRT to use the JDBC-ODBC bridge and connect it to this database. I create a new BIRT Report Project called JDBC-ODBC Access. Under this project, I create a new report called northwindEmployees.rptdesign.

In the report, I create a new Data Source by opening the Data Explorer tab, and right-mouse clicking on Data Sources and choosing New Data Source.

I name the Data Source NorthWind and specify that I want to use JDBC.

Next, I am presented with the JDBC Driver dialog. I need to configure the ODBC driver, which I have not done yet. Remember, that drivers are persistent in BIRT, so once I create it once, I don’t have to do this again, unless I wipe out my BIRT installation and delete the Eclipse folder. So I click on the Manage Drivers button.

From the Manage Drivers dialog, I click on the Add button.

BIRT needs a JAR file to work with. It is possible to use just the package path, but you would need to custom write something for that. Fortunatly, Sun does have the JAR containing the JDBC bridge in the JRE. Since I have JRE installed to C:\Program Files\Java\jre, I need to go to the lib folder there and find the rt.jar file. The rt.jar file contains the JDBC-ODBC bridge.

Now, I click OK and can see it has been added. Now I want to configure the default JDBC URL and Display name, so I click on the Drivers tab.

As you can see from the above screenshot, I already configured my defaults and display name. I used jdbc:odbc:mydb;UID=me;PWD=secret as my URL Template, and the name of my choosing. Now, I just click OK.

From my list of available drivers, I choose NorthWind, and for the URL, I change it to jdbc:odbc:NorthWind and test my connection.

Now, I create a simple Data Set to test this out. I just select the ID, name, and title of the employees from the Employee table. As you can see below, the table browser is available, so I know my connection is good.

Next, I drag my data set to the report designer, add a little bit of formatting, and I am done.