Thursday, June 7, 2012

Font Extensions


One issue in a system that I work on that was kind of side stepped around for awhile is the issue of custom fonts in reports, specifically reports built with the Jasper Reports framework. For a while we were just building all our reports in a standard font which was included in the build so this worked fine.

However, when we build custom reports for customers, they sometimes want text to be in specific fonts to match their branding. This is a completely reasonable requirement, but we just needed a sure fire way to deal with it.

In past times we would just take the font and install it on the customer's server however this was brittle since as soon as you would move the customer to another server, it would break their custom reports. Also this approach was problematic in rendering the PDFs correctly on any machine.

So the best way is to just include the fonts in the build. Fortunately Jasper Reports includes something called font extensions that make this very easy. Basically you just put a properties file in the default package called "jasperreports_extension.properties" and Jasper will automatically find the file. This file just sets a couple properties and tells Jasper where to find the font XML configuration file.

Example jasperreports_extension.properties:


net.sf.jasperreports.extension.registry.factory.fonts=net.sf.jasperreports.engine.fonts.SimpleFontExtensionsRegistryFactory
net.sf.jasperreports.extension.simple.font.families.frsfamily=fonts/frsfontsfamily.xml

Next you create a "fonts" directory, place your True Type Format fonts in there, and create an XML file that configures the fonts.

Example XML font config file:

xml version="1.0" encoding="UTF-8"?>
<fontFamilies>

   <fontFamily name="NewsGothicBT-Roman">
       <normal>fonts/News Gothic.ttfnormal>
       <bold>fonts/News Gothic Bold.ttfbold>
       <pdfEmbedded>truepdfEmbedded>
   fontFamily>

   <fontFamily name="Planer">
       <normal>fonts/Planer_Reg.ttfnormal>
       <bold>fonts/planerdemibold.ttfbold>
       <pdfEmbedded>truepdfEmbedded>
   fontFamily>

fontFamilies>

Jasper reads the above XML and registers the fonts. Whenever the above font names are referenced in a report, the TTF fonts are used and embedded in the PDF itself (notice pdfEmbedded=true above) so that the PDF will be rendered correctly on any system that opens it.

So from now on whenever a custom font is needed, we just drop the TTF font files in the fonts directory, configure them in frsfontsfamily.xml and they are available everywhere.

Our next step might be to create a way to dynamically load fonts onto a live system allowing for more flexibility but for now we are happy with being able to include fonts in the build guaranteeing that they will be available and embedded in the PDFs.

Monday, February 27, 2012

Transparent Field Encryption/Decryption

Recently I have been working on expanding FRS integration with QuickBooks to include the Online Edition. While working on the transport pipe for QBOE (QuickBooks Online Edition), a realized requirement was the need to store a QBOE connection ticket. Something like this is usually a very simple task involving adding a new field to the appropriate domain object.

However in this case, one of the security rules that QBOE requires of an application is to store the connection ticket in an encrypted state. This is a common security requirement. Since the ticket acts as a key to QBOE, we don't want anybody with database access to get their hands on the actual ticket.

The first thought was to simply create a utility class to handle the encryption/decryption, possibly in a getter or setter. Another thought was to create a custom hibernate type that would handle the encryption/decryption by making use of an encryption utility class.

Upon doing some searching I came upon this: http://www.jasypt.org/  Basically Jasypt is just a java library that makes encryption extremely easy at the data layer. In fact all you need to do is get the appropriate jars on the classpath and do just a little configuration in the hibernate configuration, and voilĂ  encryption/decryption just works.

Here is an example of setting up the custom type in the hibernate configuration:

<typedef name="quickbooksEncryptedString" class="org.jasypt.hibernate3.type.EncryptedStringType">
      <param name="algorithm">PBEWithMD5AndDESparam>
      <param name="password">encyption-passwordparam>
      <param name="keyObtentionIterations">1000param>
typedef>

And the corresponding property mapping:

<property column="qb_online_connection_ticket" name="quickbooksOnlineConnectionTicket" type="quickbooksEncryptedString" length="1000"/>

Besides getting the Jasypt jars on the classpath, that is really all there is to it. With the above configuration the "quickbooksOnlineConnectionTicket" property is automatically encrypted when it is saved to the database and then automatically decrypted when it is retrieved. So from a coding perspective nothing changes. You can simply "set" the ticket and "get" the ticket whenever you need to.