Sunday, November 07, 2010

Blah

Getting focus back. Being pulled in way too many directions again. Got EclipseCon presentations I'm waiting to see if they get accepted. Got a lot of really cool projects I am working on. And I've got a ton of notes to pour through and write up to post...

Tuesday, September 21, 2010

Eclipse: WindowBuilder Pro and GWT Designer now free.

I've been a user of GWT Designer and Window Builder Pro for a few years now. In terms of a WYSIWYG interface for any Eclipse based development and GWT interface development, they are really second to none. Earlier this year the company that makes the products, Instantiations, was purchased by Google. I was curious to see what would become of these tools. In a surprising move, Google has released them for free. Thats right, their entire product lineup, for free, including their code testing tools WindowTester Pro and CodePro AnalytiX. While everyone was excited about Instant Search, to me this is much bigger news if your a Java Developer, or an Eclipse developer specifically. Its like its my birthday or something.

Tuesday, September 07, 2010

Review of BIRT 2.6 Data Analysis and Reporting

I was pleasantly surprised to find a review of my recent edition of the BIRT book online here. I'm very excited to have gotten such a favorable review from another author. =)

Wednesday, August 25, 2010

BIRT: All About Crosstabs

It was recently brought to my attention that I overlooked discussing Data Cubes and Crosstabs in the new edition of Data Analysis and Reporting. While I remember writing it, the content might have been cut due to size constraints.

So, to help the user understand what these features are, I will discuss them here. Cross Tabs are typically a way to illustrate data in a 3 dimensional, sliceable manner. What does that mean exactly? Well, lets say, for example, that we have the following table:

(City)C1 (State)C2 (Country)C3 Sales Figure(C4)

Austin Texas USA 10

Dallas Texas USA 20

New York New York USA 30

R4 Toronto Ontario Canada 15

Now, lets say we want to slice this up in such a way that we take out rows, and we want to slice this up to show sales figures across State. If this were multi country, we might want an output with something like:

Texas New York Toronto

USA 30 30 0

Europe 0 0 0

Canada 0 0 15

There are multiple variations of the above we could slice this into, but that is the basic idea. So the next question is, what is a Data Cube in BIRT? To give a simple answer, a Data Cube is a Data Source for Cross Tabs. Data Cubes define the slice axis used in the above example. A Cross Tab would be the visual representation used in a report to display your slices. In the following examples, we will look at some uses of cross tabs, and show some real world examples of how cross tabs have been used, including the little discussed uses of Attributes for groups.

Lets walk through an example.

  1. Create a new empty report called CrossTabExample.rptDesign
  2. Connect to the Classic Models sample database, and use the following query:

select

CUSTOMERS.CITY,

CUSTOMERS.STATE,

CUSTOMERS.COUNTRY,

(ORDERDETAILS.PRICEEACH * ORDERDETAILS.QUANTITYORDERED) salesSum

from

CUSTOMERS,

ORDERDETAILS,

ORDERS

where

ORDERS.ORDERNUMBER = ORDERDETAILS.ORDERNUMBER

and ORDERS.CUSTOMERNUMBER = CUSTOMERS.CUSTOMERNUMBER


In the Data Explorer, create a new Data Cube

  1. In the data cube, create the following groupings by dragging and dropping fields. For example, in the Available Fields box, drag the City column over to the Groups, where it says Drop a field here to create a group, and call that grouping GroupByCity.

  2. Drag the newly created Cube to the report designer. This will automatically create a Crosstab Report Item.

  3. Drag the State grouping to the Column area.

  4. Delete the City grouping (this will just save space for this example).
  5. Preview the report.

That is a pretty simplistic example. A more relevant one would be a display of quarter sales per country. So, lets modify the above example.

  1. Modify the query to the following, adding the date field:
       1. select

    CUSTOMERS.CITY,

    CUSTOMERS.STATE,

    CUSTOMERS.COUNTRY,

    (ORDERDETAILS.PRICEEACH * ORDERDETAILS.QUANTITYORDERED) salesSum,

    CLASSICMODELS.ORDERS.ORDERDATE

    from

    CUSTOMERS,

    ORDERDETAILS,

    ORDERS

    where

    ORDERS.ORDERNUMBER = ORDERDETAILS.ORDERNUMBER

    and ORDERS.CUSTOMERNUMBER = CUSTOMERS.CUSTOMERNUMBER


    1. In the Data Cube, add the ORDERDATE as a group, and set the grouping to Quarter. This prompt is unique to dates.

    2. Remove the State column from the Crosstab.
    3. Drag the ORderDate Group to the newly empty Column.

    4. Preview the report

    Now that is a cross tab that is a little more usable. Here we can see sales for each country based on Quarter of the year.

    Cross tabs also have some really interesting uses that are not very apparent. For example, lets say you want to display the values of rows as columns. This works just fine. In the following example, lets say we want the names of employees to show as column, with tables below each name showing their customers.

    1. Create a new report called EmployeeCustomers.rptDesign.

    2. Create a Data Source connecting to the Classic Models example database, and a new data set using the following query:
    select

    CLASSICMODELS.EMPLOYEES.EMPLOYEENUMBER,

    CLASSICMODELS.EMPLOYEES.LASTNAME,

    CLASSICMODELS.EMPLOYEES.FIRSTNAME

    from

    CLASSICMODELS.EMPLOYEES

    3. Create a new Data Cube. Drag over the LastName as a grouping.

    4. Double click on the LastName grouping to open the editor. For the display field use the following expression:

    5. Click on the Add for Attributes. Add in the EmployeeNumber. The reason for this is that we will need to be able to access the EmployeeNumber in the crosstab to filter the child tables.



    6. Drag the newly created Data Cube to the report designer. Drag the LastName column over to the Column Area. This will display all employee names as columns instead of rows.



    7. Create a new Data Set. Use the following query. Be sure to leave the parameter as empty, as it will be set by our Crosstab.

    select

    CUSTOMERS.CUSTOMERNAME

    from

    CUSTOMERS

    where

    CUSTOMERS.SALESREPEMPLOYEENUMBER = ?

    8. From the outline view, select the cell that the LastName element is in for the cross tab, right-mouse click, and choose Insert/Table.

    9. Create the table as 1 row, 1 column, and Data Set to the employeeCustomers table that was create in step 2.

    10. Now, we need to do something a little tricky here to filter this table. Select the table in the Report Editor. In the Property view, select Bindings.



    11. Open the Data Set Parameter Binding dialog by clicking on the button.

    12. select Param_1, and click Edit.

    13. Click on the Function button in the Edit Data Set Parameter Binding dialog

    14. We will need to add a new data binding for our cross tab. So Select edit bindings.

    15. From the Edit Data Binding dialog, click on Add.

    16. Set the name to employeeNumber, type to Integer, and expression to dimension["GroupByLastName"]["LASTNAME"]["EMPLOYEENUMBER"]. You can use the Expression Editor to set this expression. When you go through the navigation, you will notice that EmployeeNumber is listed under the group. The reason being, we added it as an attribute for the LAstName grouping.

    17. Now that the crosstab binding has been created, we can hit OK for the dialogs until we get back to the Expression Editor for the Parameter Binding. The employeeNumber field is now available.

    18. Now, drag the CustomerName field into the detail section of the table.


    And once you apply some formatting, you are set. You are now using the rows of a table as columns, and driving a detail table with that.

Thursday, August 05, 2010

BIRT: My New Book is Out

My new book, covering up to BIRT 2.6, has been released.

https://www.packtpub.com/birt-2-6-data-analysis-and-reporting/book

Right now, they are running a special, 33.74 for the book, 30 for the eBook, and 39 for the pair!!!

Saturday, July 17, 2010

BIRT: Articles Posted

If you've noticed I've been silent, its because I've been busy updating the BIRT book to cover 2.3.x, 2.5.x, and now 2.6. Due to page number constraints, we had to cut two chapters from the book. But their loss is your gain. Those two chapters have now been released, free of charge, to the public thanks to my publisher. These chapters cover how to build stylesheets, templates, libraries in one article, and building a Bugzilla reporting site in the other (unrelated to my jobs BIRT demo site, BIRT4Bugz).

Check out the articles here:
http://www.packtpub.com/article/use-stylesheets-report-designing-using-birt
http://www.packtpub.com/article/creating-reporting-site-birt

Thursday, June 17, 2010

Droid: Using a Wii Controller on an Android Phone

Busy period for me again, thats why posts have been few and far between. I have a whole stack of posts slated to write, I just need time to do them.

Since I have been doing so much traveling lately, it leaves me with a lot of idle time in places like airports. while I always have my trusty Nintendo Ds with me, there are times where I don't want to lug around the carrying case with all my games. This is where my cell phone, a Motorola Droid, has come into play. Once again, I can't help but marvel at how powerful these devices have become.

I have gotten a interest in retro gaming. I grew up on the old school NES, SNES, and Sega Genesis games. And since the Droid is powerful enough, it can run emulators of these old school systems at full speed. The only problem is the control scheme leaves a little something to be desired. the onscreen controls just suck since you have no tactile feedback that you pushed a button (except for a vibration). the keyboard is awkward, so a gaming controller would be ideal here.

Well, there are a few options. First is the Game Gripper. This looks promising. I ordered one, but it hasn't arrived yet. There are two drawbacks to this. First, it only supports the Droid and the Backflip. Second, since it is basically a plastic insert that just pushes the buttons on your keyboard for you, I wonder if it will eventually wear down the thin plastic cover on the keyboard, or leave indentations.

The second option is the Zeemote. While the Droid is not explicitly listed on their site, there is a app in the marketplace called Gamepro that will interface with it.

The option I am using right now is the Nintendo Wii controller. There is an app in the Market called Wii Controller IME. This interfaces with the Wii controller (and the Wii Remotes Classic Controller) to allow you to use a Wii remote on the Droid. You assign keypresses to keyboard buttons, and your good to go. I tested it with NESoid and it worked flawlessly as long as I had the "Use Input Device" option selected. It even processed two button presses at the same time, something the keyboard had a hard time with. This is important if your playing a game that requires diagonal movement. the only drawback is that I have to carry a Wii remote with me, and that it uses Bluetooth, so battery life is much lower. One thing to keep in mind, it is reported that this app has a hard time with HTC phones, or phones using HTC Sense. So the Incredible, EVO, and Eris might have a hard time with it. Now I just need a phone with video out like the EVO and I'd be all set for when I travel =)

Wednesday, February 17, 2010

BIRT: BIRT Report Item Extensions Released by Innovent Solutions

As part of its commitment and involvement with the BIRT project Innovent Solutions, the company I work for, has created a project that offers a few graphical controls to illustrate BIRTs report item extension point. There are two extensions offered in these libraries. The first one is a Dot Bar. The Dot bar provides a quick visual representation of numeric values. This is useful for a quick, at a glance, representation, rather than overwhelm users with numbers everywhere in a report. The second is a Rotating Text graphic element, based off the original rotating text example illustrated in “Integrating and Extending BIRT”. The rotating text is useful when you are trying to conserve space on a report.

These extension elements are available at http://code.google.com/p/birt-controls-lib/.

Installation instructions are provided on the above link, but we will cover this real quick. There are two components necessary to install these into the BIRT Report Designer. There is a bb.birt.controls.xxx.jar, and a bb.birt.controler.ui.xxx.jar. The UI component is necessary for the BIRT report designer to show these new elements in the palette. The other jar contains the necessary runtime libraries for BIRT to know how to use these elements in a report.

The easiest installation method is to use the update site. The update site is provided in the instructions.

Once installed, you will have the two new components available on the Palette.

So, lets say I want to demonstrate these. In the following example, I will create a simple report that will show the offices and employee count for the Classic Cars sample database. Assume I already have the above components installed, and I am using BIRT 2.5.1.

1. Create a new report called newComponentTest.rptDesign.

2. Create a new Data Source using the Classic Cars example database.

3. Create a new dataset from the following query:

select

CLASSICMODELS.OFFICES.OFFICECODE,

CLASSICMODELS.OFFICES.CITY,

(select count('1') from employees where officecode = CLASSICMODELS.OFFICES.OFFICECODE) officecount

from

CLASSICMODELS.OFFICES

4. Right-mouse click on the data set, and choose Insert in Layout.

The report will look like so:

5. Now, select the OfficeCount detail data component, and delete it.

6. Insert a DotBar in the OfficeCount detail cell.

7. In the DotBar dialog, use the following details:

8. Now, remove the OfficeCode column (1st column).

9. In the City Detail cell, remove the City data component.

10. Insert a Rotated Text component into the cell.

11. Use the following properties:

The final report will look something like this:

And when you run the report, it should look like so:

The source for these components are available to be extended as well from the above linked Google Code site.

Tuesday, February 09, 2010

VOIP: Set Up Asterisk and LinkSys 3102 to work with SIPDroid.

My most recent project has been to set up a VOIP setup on my Droid so that I can VPN into my home network using either my 3G service or WiFi and use the unused landline that I have so that I don’t burn minutes. As a secondary objective, I’d also like to be able to have calls made to my house ring on my cell phone after a few rings on my house phone.

In order to accomplish this task, I needed 2 things:

A means to connect my landline to my Asterisk server

An old machine to run Asterisk on

The old machine was easy. I have an old Compaq that has been sitting idle since the early 2006 or 2007. It had Ubuntu Dapper Drake. Although I would have liked to have put something newer, it appears that most newer distributions don’t agree with the hardware, and I really don’t have time to mess around with passing in various kernel parameters in a trial and error manner since the error messages were non-existent. Since this was the case, I enabled the universe repository under /etc/apt/sources.list, and ran the following command to get Asterisk running:

apt-get –f install asterisk

I didn’t change any of the configuration files, I want to keep them stock since I will use a special configuration wizard.

Now, the hardware I used to connect the phone was a Linksys 3102 ATA. I also did not do anything in configuration outside of enabling configuration through the outside WAN since this is only connected to my Intranet.

Configuration, despite how confusing all this looked initially, turned out to be a piece of cake, thanks to this handy dandy configuration utility, courtesy of the nice folks at Voxilla. I simply followed the wizard, which automatically configured the 3102 to work with Asterisk. To configure Asterisk, I made a backup of the sip.conf, voicemail.conf, and extensions.conf, removed them, and copy and pasted in the appropriate configuration sections from the wizard into the appropriate files. So, to do that, it looked something like:

root@cloya-desktop:/etc/asterisk# mkdir backup

root@cloya-desktop:/etc/asterisk# cp sip.conf backup/

root@cloya-desktop:/etc/asterisk# cp extensions.conf backup/

root@cloya-desktop:/etc/asterisk# cp voicemail.conf backup/

root@cloya-desktop:/etc/asterisk# rm sip.conf

root@cloya-desktop:/etc/asterisk# nano sip.conf

root@cloya-desktop:/etc/asterisk# rm voicemail.conf

root@cloya-desktop:/etc/asterisk# nano voicemail.conf

root@cloya-desktop:/etc/asterisk# rm extensions.conf

root@cloya-desktop:/etc/asterisk# nano extensions.conf

root@cloya-desktop:/etc/asterisk# cat sip.conf

[digiassn]

type=friend

host=dynamic

context=home

secret=secretPassword

mailbox=digiassn

dtmfmode=rfc2833

disallow=all

allow=ulaw

[pstn]

; If you're using Asterisk, this goes into the Incoming settings

; For your Trunk

type=friend

host=dynamic

; If using Asterisk@home, change the below line to context=from-internal

context=home

secret= secretPassword

dtmfmode=rfc2833

disallow=all

allow=ulaw

insecure=very

[pstn-spa3k]

; If you're using Asterisk, this section goes into the Outgoing Settings

; for your trunk.

type=peer

auth=md5

host=192.168.1.110

port=5061

secret= secretPassword

username=asterisk

fromuser=asterisk

dtmfmode=rfc2833

; If using Asterisk@home, change the below line to context=from-internal

context=home

insecure=very

root@cloya-desktop:/etc/asterisk# cat voicemail.conf

[default]

digiassn => digiassn,John Ward,user.com,user-pager.com,tz=pacific

root@cloya-desktop:/etc/asterisk# cat extensions.conf

[home]

exten => digiassn,1,Ringing

exten => digiassn,2,Dial(SIP/digiassn,20,T)

exten => digiassn,3,Voicemail(udigiassn)

exten => digiassn,4,Hangup

exten => 911,1,Dial(SIP/911@pstn-spa3k,60,)

exten => 911,2,Congestion

exten => _XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _XXXXXXX,2,Congestion

exten => _1800XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _1800XXXXXXX,2,Congestion

exten => _1888XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _1888XXXXXXX,2,Congestion

exten => _1877XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _1877XXXXXXX,2,Congestion

exten => _1866XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _1866XXXXXXX,2,Congestion

Then, I need to edit the /etc/default/asterisk file to change the line that says

RUNASTERISK=no

to say

RUNASTERISK=yes

Now, before I actually start this up, I needed to make one final change. When I actually started this up and played with it, the dial in from my land line did not ring the VOIP setup on my Droid the way I wanted. The reason is the extension.conf file was not set up correctly from the script. The way it works by default is that any calls coming in the digiassn extension would ring the digiassn extension for 20 seconds then go to voice mail. This is not what I want. I want calls coming in the pstn extension to ring the pstn extension for 20 seconds (which would be the physical home phone line), then ring my VOIP setup on my cell (digiassn) for 10 seconds, then go to voicemail. Most normal configurations won’t require this, but I included it here to show my final configuration. First, go into the SPA configuration utility, and under Voice/Line 1/Proxy and Registration, change the value of Use Outbound Proxy to true. I don’t know why, but the handset wouldn’t ring without this set. Then change the below configuration for extensions.conf:

[home]

exten => pstn,1,Ringing

exten => pstn,2,Dial(SIP/digiassn,20,T) #ring the handset first

exten => pstn,3,Dial(SIP/pstn,15,T) #then ring the SIPDroid

exten => pstn,4,Voicemail(udigiassn)

exten => pstn,5,Hangup

exten => 911,1,Dial(SIP/911@pstn-spa3k,60,)

exten => 911,2,Congestion

exten => _XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _XXXXXXX,2,Congestion

exten => _1800XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _1800XXXXXXX,2,Congestion

exten => _1888XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _1888XXXXXXX,2,Congestion

exten => _1877XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _1877XXXXXXX,2,Congestion

exten => _1866XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _1866XXXXXXX,2,Congestion

Now, I can start up Asterisk by running /etc/init.d/asterisk restart.

Now, I need a VOIP client. I am using SIPDroid to make my connections. To do this, I configure SIPDroid as follows:

Under SIP Account Settings:

Authorization Username: pstn

Password:

Server: 192.168.1.111 (The address of the Asterix box).

Port: 5060

Protocol: UDP

Everything else I leave default. That’s it. When I’m connected to my WiFi network, I can use the VoIP setup to connect directly to my landline.

So, after using this for a day, there were some definite things I wanted to change. The dial plan that is on by default sucked. Since I am using Android and SIPVoice to dial, and by default SIPDroid uses the full number mask stored in contacts (XXX-XXX-XXXX), Asterisk refused to dial. I would see SIPDroid try to dial but hang up immediately without completing the call. Took me a while to figure out what was going on, so some new dial masks needed to be created. Voicemail was not set up correctly. Since I don’t have an answering machine on my landline, I figured Asterisk can play double duty and serve as an answering machine as well. The wizard doesn’t create a workable voicemail password, so that needed to be fixed. Also, after some investigation, it turns out that Asterisk also has a little feature that works just like the Telezapper, and will play the “out of service” tone when you answer a phone so telemarketers and such will register you in the Do Not Call database. This is a feature that I need to have since the National Do Not Call database is such a joke. There are also all sorts of neat scripts you can run to forward telemarketers to annoying endless voice prompt loops, or just hang up on them, but I won’t cover them here.

So, to accomplish what I wanted, I modified all three configuration files like so.

Voicemail.conf:

[default]

digiassn => 1234,John Ward,john@email,tz=pacific

Note the 1234. This is the 4 digit numeric password you need to enter to check and manage your voicemailbox.

Extensions.conf:

[home]

exten => pstn,1,Ringing

#add zapateller

exten => pstn,2,Zapateller(answer)

exten => pstn,3,Dial(SIP/digiassn,15,T)

exten => pstn,4,Dial(SIP/pstn,10,T)

exten => pstn,5,Voicemail(udigiassn)

exten => pstn,6,Hangup

exten => 911,1,Dial(SIP/911@pstn-spa3k,60,)

exten => 911,2,Congestion

#dialing 9999 will get me my voicemail box

exten => 9999,1,VoiceMailMain(digiassn)

#dialmasks, local calls

exten => _XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _XXXXXXX,2,Congestion

#if coming from cell phone, only take the phone number, minus the 1 and the area code

exten => _1210XXXXXXX,1,Dial(SIP/${EXTEN:-7}@pstn-spa3k,60,)

exten => _1210XXXXXXX,2,Congestion

#same as above, only without the 1. this is for local calls

exten => _210XXXXXXX,1,Dial(SIP/${EXTEN:-7}@pstn-spa3k,60,)

exten => _210XXXXXXX,2,Congestion

#Any other number, with the 1

exten => _1XXXXXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _1XXXXXXXXXX,2,Congestion

#without the 1

exten => _XXXXXXXXXX,1,Dial(SIP/1${EXTEN}@pstn-spa3k,60,)

exten => _XXXXXXXXXX,2,Congestion

#dont believe the rest need to be here, but I will leave them jic

exten => _1800XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _1800XXXXXXX,2,Congestion

exten => _1888XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _1888XXXXXXX,2,Congestion

exten => _1877XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _1877XXXXXXX,2,Congestion

exten => _1866XXXXXXX,1,Dial(SIP/${EXTEN}@pstn-spa3k,60,)

exten => _1866XXXXXXX,2,Congestion

Wednesday, January 27, 2010

BIRT: Get Access to Chart Element and Modify Properties from ReportRunnable in BIRT 2.5

Helping someone out from the forums on BIRT Exchange. The question was how can you get access to a chart in a ReportRunnable object, modify its properties, and run the report with the modified properties. While I have given pieces of how to do that here and here, I have never put them together in a single example. Below is an example of how to do this.

package com.digiassn.blogspot.birt;

import java.util.logging.Level;

import org.eclipse.birt.chart.model.ChartWithoutAxes;
import org.eclipse.birt.chart.model.attribute.ChartDimension;
import org.eclipse.birt.core.exception.BirtException;
import org.eclipse.birt.core.framework.Platform;
import org.eclipse.birt.report.engine.api.EngineConfig;
import org.eclipse.birt.report.engine.api.EngineException;
import org.eclipse.birt.report.engine.api.HTMLRenderOption;
import org.eclipse.birt.report.engine.api.IReportEngine;
import org.eclipse.birt.report.engine.api.IReportEngineFactory;
import org.eclipse.birt.report.engine.api.IReportRunnable;
import org.eclipse.birt.report.engine.api.IRunAndRenderTask;
import org.eclipse.birt.report.model.api.ExtendedItemHandle;
import org.eclipse.birt.report.model.api.extension.ExtendedElementException;

public class ModifyChart {

/**
* @param args
*/
public static void main(String[] args) {
try {
IReportEngine engine = null;
EngineConfig config = null;

// Configure the Engine and start the Platform
config = new EngineConfig();
config
.setEngineHome("C:/Libraries/birt-runtime-2_5_1/ReportEngine");
// set log config using ( null, Level ) if you do not want a log file
config.setLogConfig("C:/temp", Level.FINE);

//start birt platform and create factories
Platform.startup(config);
IReportEngineFactory factory = (IReportEngineFactory) Platform
.createFactoryObject(IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY);
engine = factory.createReportEngine(config);
engine.changeLogLevel(Level.WARNING);

//open report design
IReportRunnable design = engine
.openReportDesign("C:/contracts/BirtExamples/BirtReportEngine/PieChart.rptdesign");

//get chart element handle called "PieChart"
ExtendedItemHandle eih = (ExtendedItemHandle) design.getDesignHandle()
.getDesignHandle().findElement("PieChart");

//get the actual chart instance since Charts are extended item handles
ChartWithoutAxes cwa = (ChartWithoutAxes) eih.getReportItem().getProperty(
"chart.instance");

//set title of chart to New Label
cwa.getTitle().getLabel().getCaption().setValue("New Label");

//set 2d with depth
cwa.setDimension(ChartDimension.TWO_DIMENSIONAL_WITH_DEPTH_LITERAL);

// Create task to run and render the report,
IRunAndRenderTask task = engine.createRunAndRenderTask(design);

// Set rendering options - such as file or stream output,
// output format, whether it is embeddable, etc
HTMLRenderOption options = new HTMLRenderOption();
options.setBaseURL("http://localhost/");
options.setBaseImageURL("http://localhost/myimages");
options.setImageDirectory("C:/xampplite/htdocs/myimages");
options.setSupportedImageFormats("JPG;PNG;BMP;SVG");

options.setOutputStream(System.out);

// Set output format
options.setOutputFormat("html");
task.setRenderOption(options);

// run the report and destroy the engine
// Note - If the program stays resident do not shutdown the Platform or
// the Engine
task.run();
task.close();

task.close();
Platform.shutdown();
System.out.println("Finished");
} catch (ExtendedElementException e) {
e.printStackTrace();
} catch (EngineException e) {
e.printStackTrace();
} catch (BirtException e) {
e.printStackTrace();
}

}

}


The thing to remember about charts in BIRT reports is that they are Chart types stored withing a ExtendedItemHandler. So you need to find the ExtendedItemHandler first, then get the chart inside of it. Charts can be ChartsWithAxis (bar charts, lines charts), or ChartsWithoutAxis (pie charts). Reference on the chart types can be found here.

ChartWithAxes
ChartWithoutAxes

Musing: Mobile Technology

One of the things that is always on my mind is how can I keep myself mobile, without the need to carry around a laptop. For a few years I have kept it in the back of my mind that my smartphone would be perfect for this, however previous models didn't quite do everything that I needed. I can say, this is no longer the case with the Droid.

I am writing this sitting in a Chipotle and using my foldout keyboard on my Motorola Droid. I am using the wireless tether that I hacked previously to connect my iPod Touch online so I can play Scrabble (until there is a native Droid version that is). I am using the GDocs application to write this (although I have a few other text editors that save locally instead of "in the cloud"). Using the Droid Meebo app, I can stay connected to coworkers via IM. Since the Droid multitasks, I can have the IM, email, tether app, and a few other things running simultaneously. The only thing I lack here is VOIP via WiFi, which I suspect will be simplified enough soon enough. I think my next tasks here are to try to run a modified BIRT Designer. Then I can do some rudimentary troubleshooting on BIRT reports when not at my desk.

I couldn't do all this 5 years ago on the Razr, or last year with the Touch/Vogue. The difference between mobile and desktop is closing. I wonder how businesses deal with the security issues with this new found mobility?

Monday, January 25, 2010

Droid: WiFi Tethering/Hotspot on the Droid

Since the announcement of the Pre+ for Verizon would have WiFi hotspot built in, I have been salivating for the wireless hotspot functionality. Of course, I kicked myself because I just bought a Droid. Well, I can hold off my wanting because some clever hackers figured out how to do the same thing with the Droid. That’s right, the Droid is capable of being a WiFi hotspot.

So how is this feat accomplished?

That’s it. Pretty easy. Took me about 20 minutes to do. Although not indicated in the article because it assumes prior understanding, the “ADB” application refered to requires the Android SDK, and is a tool located under the “tools” folder. Also, the step to “flash_image” was actually not needed since this is part of the Android Root Helper application. Also, during the WirelessTetherPather programs final stages, it asks you to “login, and run the tether app”. This actually refers to running the “Wireless tether for Root users” application under your applications menu on the Droid, not running it using Busybox using ADB. That step confused me for some reason.

If your having problems finding the “Droid Root Helper” application, you can use the one I found here. Apparently, it is also in the Marketplace.

That’s it, the last little void from my HTC Touch has been filled. Seriously, how could Verizon NOT want this? This is just so freaking awesome, it should be a standard feature.

Monday, January 18, 2010

Getting HP Foldable Bluetooth Keyboard FA287A Working on Motorola Droid

I’ve had an old Bluetooth keyboard I used to use with my HP Ipaq. It is a model number FA287A. I’ve always had a fondness for this keyboard and using it with my mobile devices. It has a number pad on the top, and it has a nice feel to the keys. I managed to get this keyboard working on my HTC Touch Vogue with some help from this driver.

I am happy to discover that this keyboard, which has served me well for years, lives on with my Motorola Droid. That’s right, this oddball keyboard that was designed specifically for the HP Ipaq, works with my Android based mobile phone. How is this possible? Thanks to a little application called KeyPro available in the Android Marketplace, and at http://www.mymobilegear.com/AndroidKBDriver.php (note, this site was down at the time of this writing, the URL comes from Google).

To get this working, I used the following steps.

  • Installed KeyPro from the Marketplace.
  • Opened up Droids settings app.
  • Went into Language and Keyboard, and clicked on the check next to KeyPro.
  • Clicked Back.
  • Clicked on Wireless and Networks.
  • Turned on Bluetooth.
  • Went into Bluetooth Settings
  • Clicked on Scan for Devices, it found “BT-FoldableKB”
  • Paired with it, and put in Passcode “0000”
  • Pushed the Home button
  • Opened the apps menu, started KeyPro
  • Opened the Settings menu.
  • Changed the Keyboard Model to “Freedom Universal”
  • Clicked on the Scan next to Keyboard Address textbox.
  • It found the “BT-FoldableKB”.
  • Scrolled down and clicked on Save.

Keypro then showed status at bottom of app saying “initialized”, then “connecting”, then “connected”. With it connected, I clicked on the Search button. Nothing happened. So I held my finger up to the search text box for a second, and a dialog poped up for Input Method. I clicked on Input Method, and selected KeyPro. And guess what. Now what I typed showed up. I can use my Bluetooth keyboard on my Android. This works out great when I want to take notes in a meeting and I don’t want to bring my laptop with me, and another reason to leave my IPod Touch at home.

Saturday, January 02, 2010

Squid: Watching Hulu on your PS3 using HTTP_HEADER User Agent modification

Some time ago, probably about a year, I watched “Terminator, The Sarah Conner Chronicles” on Hulu over the PS3. I had reached a certain level of euphoria as I realized my media center in my theater room was complete. I tried this recently, only to be greeted with a message letting me know that the PS3 platform was no longer supported for Hulu content. Seriously? Filtering based on platform now? I'll tolerate the limited commercials, but I don't like being told what platforms I can watch content on.

Fortunately, I found this little gem with a workaround using Squid, one of my favorite tools, to replace the HTTP header en-route, making Hulu think the request is coming from a Windows machine. And old trick, and Firefox even has a plugin that will replace the HTTP header for you, but the PS3 doesn’t have that ability. I remember an article I wrote several years ago talking about using Squid and SSH to get around filtering proxies within a corporate LAN. I’ve also used Squid to simulate slower bandwidth using delay pools for UAT testing. Right up there with Netcat and SSH as useful tools to have on your machine.