Right Outer Join

28 May 2010

Jaspersoft v3 Font Extensions

Filed under: iReport, JasperReports, JasperServer — Tags: , , , , — mdahlman @ 14:38

Jaspersoft Font Extensions

Background

To get reports to display exactly the way that you want them to display you need to ensure that you have exactly the font that you want. Jaspersoft makes this relatively easy through the mechanism of “Font Extensions”. To understand the technical workings of font extensions well, your best resources is the JasperReports Ultimate Guide. If you are working with JasperReports you owe it to yourself to buy a subscription to this resources; it’s great.

I’m not writing about the details of how font extensions work.

In the past creating font extensions was relatively difficult. I wrote about it in this post. It wasn’t really overly difficult if you refer to the documentation and took your time, but it involves creating XML files and is certainly not a point-and-click process. With the release of iReport 3.7 it’s much easier. For details on how to use the wizard to create font extensions, take a look at the iReport Ultimate Guide. It has a whole chapter on “Fonts and Styles”. It’s great.

I’m not trying to replace the content already included in the iReport premium documentation.

So what is the point of this article? This is an example of the complete process of creating a new report, specifying fonts, confirming that the report works well, then deploying the report to a server where the font doesn’t already exist and configuring that server correctly.

Create a report and specify fonts

In the attached report “FontExtensions.jrxml” you can see that I have selected 4 different fonts for the 4 different text fields. The title is set to “DejaVu Serif”. I chose this because it is already installed as a font extension by default in iReport (and JasperServer). How do I know that it’s already installed? You can see the installed fonts from the menu Tools -> Options -> Fonts. You can also tell by looking at the dropdown list of fonts in the property “Font name” for the field. DejaVu Serif is above the line. That means it’s installed. The fonts below the line are on my machine, but they aren’t registered as font extensions, so there could be trouble at deployment time.

Tools -> Options -> Fonts

Tools -> Options -> Fonts

Font dropdown

Dropdown list of available fonts

Next, I want to set the subtitle to Microsoft’s Comic Sans font. (Please note: I forbid you to use this font in your own reports. It’s terrible. Maybe if you’re creating a report on preschool statistics it would be OK. I only chose it for this article because it’s well known and distinctive.) Oh no! This font appears only below the line! (as “Comic Sans MS”)

Family Details

Family Details

Select a TrueType Font

Select a TrueType Font

Don’t worry: installing a font is simple. From the Tools -> Options -> Fonts screen shown above click “Install Font”. On the first step of the wizard browse to the font file. On the second step specify the separate file with the bold version of the font. The final steps of the wizard are described in detail in the iReport Ultimate Guide, so I won’t bother with details here. For our purposes we can skip through these steps with no changes.

Hooray. Now Comic Sans MS appears “above the line” as well as on the window Tools -> Options -> Fonts. It can safely be selected as the font for the subtitle field.

Code2000 PDF Encoding

Code2000 PDF Encoding

Next, I created a field for my group header. I included the Japanese characters “日本語” in this field to test support for non-ascii characters. Of course I need to select a font that includes support for these characters. I chose Code2000. It’s not a particularly elegant font visually. But it supports lots and lots of characters. As before, the next step is to install Code2000 as a font extension.

This time be sure to set the PDF Encoding to “Identity-H”. If you forget to set it during the initial run of the wizard, you can edit the font details later as shown in the screenshot here. Embedding the font in the PDF document is not required, but I recommend it. Without that option you are at the mercy of the machine viewing the PDF document to supply the font. With the font embedded you are sure to get what you’re expecting. The file size will be larger, but it’s really not a big difference. The PDF creation process is smart enough to embed only the characters that are required; you don’t get the entire font file embedded into the document.

My final text field is in the detail band. For this field I went with the simple option of using the Java logical font “SansSerif”. This logical font will get translated to some physical font by the JVM when the report gets run. It’s impossible for the report designer to know what font will be selected, so this option is appropriate only when you don’t need a precise font. As a practical matter, one can make a good guess. I see that my JVM on Windows XP is configured to use Arial for its SansSerif font. I see that my JVM on CentOS will use lucidasans. These are common default values, but they are not guaranteed.

Run the report in iReport

Now that the report is created, I’ll run it to confirm that all fonts are working as expected. But to make the details perfectly clear I first deleted my font extensions. Let’s see what this report looks like without the font extensions defined in iReport.

No font extensions

With no font extensions defined the output is somewhat surprising

The good news is that the report looks good without the font extensions. The bad news is that the report looks good without the font extensions. It’s bad news because it can make you think that things are configured correctly. Only the PDF export of the report shows the problems caused by not defining the needed font extensions.

Now I put the font extensions back and re-run the report. The internal preview and HTML were already fine before, so they remain fine. But with the font extensions PDF is working well too.

PDF with font extensions

With the fonts installed the PDF is now good

The sharp-eyed reader may notice that the Japanese characters in the detail band still do not display well. I’m willing to ignore this for now. It happens because my JVM translates SansSerif to Arial, and Arial does not include support for Japanese characters. I could solve the problem by updating my JVM properties to use another font or by modifying my report to use Code2000 or Arial Unicode MS or another font with support for these characters.

Deploy the Report to JasperServer

From iReport use the Repository Navigator to deploy the report to JasperServer. Open a browser, find the report, and woo hoo! Everything is good: the title uses DevaVu Serif, the subtitle uses MS Comic Sans, the group header shows Japanese characters correctly using Code2000, and the detail band shows Japanese characters correctly using some unspecified sans serif font.

HTML Report on JasperServer

HTML Report on JasperServer

Just to be sure, let’s take a look at the report in PDF format. On no! It looks exactly like it did in iReport before we defined the font extensions. Japanese characters are missing and it uses the wrong fonts.

If you have been following along closely, you should already know what is wrong. Although we defined the font extensions in iReport, we have not deployed them to JasperServer. That’s the final step we need before the reports will work exactly as intended.

Export and upload the font extensions

We need to get the font extension from iReport over to JasperServer. In JasperServer 3.5 this required tracking down (or creating) the relevant XML files, properties files, and TTF font files. I wrote about font extensions in JasperServer 3.5 previously. In JasperServer 3.7 it’s a single click to export the extension and only a few more clicks to load it up to JasperServer.

Return to the window Tools -> Options -> Fonts and click the button “Export as extension”. That was easy.

In the Repository Navigator pane right-click a folder and choose Add -> Jar Archive. Then on the report unit add a reference to this JAR file. It is possible to add the JAR Archive directly into the report unit. But it’s better to add the JAR independently so that it may be referenced by many reports. In the screenshot below you can see that MyFontExtensions.jar has already been added, and now I am just adding a reference link from my report unit to this resource.

Add JAR Archive

Add JAR Archive and a reference to the JAR Archive

Success

Now that the font extensions have been loaded up into JasperServer—and the report makes use of it—the report works perfectly. HTML, XLS, OpenOffice.org spreadsheets and text documents, and even PDF are all rendered as intended. Don’t forget that most formats, like the ODS file below, refer to the correct font but do not embed it. So these will not render as intended on client machines lacking the relevant font. But PDF with its font embedding can be counted on to produce a pixel-perfect output.

ODS report

The same report in ODS with correct fonts

Appendix

One way to be more certain that your reports are well defined is to tell JasperServer to more rigorously enforce fonts. By default JasperServer makes a best guess and substitutes another font in place of one that cannot be found. This is helpful in some respects, but I find that it promotes laziness. I much prefer to set the following option in …/WEB-INF/classes/jasperreports.properties:

# ignore missing fonts in reports
net.sf.jasperreports.awt.ignore.missing.font=false

The default value is true. By setting it to false JasperServer will throw an exception when it cannot find the font that it needs. Here’s what the user sees when running the above report before deploying the font extensions when JasperServer does not ignore missing fonts:

net.sf.jasperreports.engine.util.JRFontNotFoundException: Font 'Comic Sans MS' is not available to the JVM. See the Javadoc for more details.
	at net.sf.jasperreports.engine.util.JRFontUtil.checkAwtFont(JRFontUtil.java:321)
	at net.sf.jasperreports.engine.util.JRStyledText.getAwtAttributedString(JRStyledText.java:226)
	at net.sf.jasperreports.engine.fill.TextMeasurer.measure(TextMeasurer.java:362)
	at net.sf.jasperreports.engine.util.JdkGlyphFixTextMeasurer.measure(JdkGlyphFixTextMeasurer.java:133)
	at net.sf.jasperreports.engine.fill.JRFillTextElement.chopTextElement(JRFillTextElement.java:1008)
	at net.sf.jasperreports.engine.fill.JRFillTextField.prepare(JRFillTextField.java:539)
	at net.sf.jasperreports.engine.fill.JRFillElementContainer.prepareElements(JRFillElementContainer.java:327)
	at net.sf.jasperreports.engine.fill.JRFillBand.fill(JRFillBand.java:402)
	...

or in other languages you get the equivalent error like this:

標楷體 is not available to the jvm.

Of course you wouldn’t want to let errors like this creep into a production system. But that’s why we have testing. During testing it’s far better to see these errors. Without this error I might not have noticed that a report was rendering without Comic Sans MS. This way I see exactly what the problem is, so I can take steps to fix it.

16 April 2010

Fonts in JasperServer 3.7

Filed under: JasperServer — Tags: , , , , , , — mdahlman @ 12:05

You can’t display fonts that you don’t have

The Problem

I have written about fonts in JasperServer in the past, but I’m revisiting it now. It’s popular topic because fonts are very important to the look of your reports, but it’s easy to get things setup wrong (or incompletely). Let’s start with the “Sales by Month” report which ships with JasperServer Professional and Enterprise 3.7.

Sales by Month report in Japanese

Sales by Month report in Japanese

Let me be the first to say, “Hey! didn’t those Jaspersoft guys improve anything in v3.7? Why doesn’t my chart correctly display the legend characters in Japanese by default!?”

The Solution

The issue—as is common with font issues—turns out to be more subtle than one might expect. First we have the somewhat confusing situation that some Japanese characters display well. It’s only the chart that has a problem. This is because my local Windows XP machine has appropriate Japanese fonts. So things like this render nicely: “キー:  低い値    高い値”. That’s because they get rendered by my browser. But the chart gets created on the server. A bad choice of font must be happening there.

In JasperServer v3.5 the problem was that the report specified Verdana as the font. Verdana doesn’t include glyphs for Japanese characters, so it wasn’t really JasperServer’s fault that it couldn’t render things well. It was the report designer’s fault. In JasperServer v3.7 all of the sample reports have been updated to use Java logical fonts like SansSerif, Monospaced, etc. This means that JasperServer pushes the job of selecting the exact physical font down to the JVM which works with the underlying OS to find an appropriate font.

Aha! this means we have a new culprit to point fingers at: Java. What font is the JVM deciding to use? I’m running JasperServer in the cloud on a CentOS Linux box. What font faces are available? Let’s see:

# fc-list
#

That’s right. No fonts at all are available. That is likely the root of my problem. Are there fonts available to install? Let’s see:

# yum list | grep japanese
fonts-japanese.noarch                    0.20061016-4.el5       base
m17n-db-japanese.noarch                  1.3.3-48.el5           base

There are fonts available. It takes only a few seconds to install them:

# yum install fonts-japanese.noarch

Now I have lots of fonts available:

# fc-list
fxd:style=Bold semicondensed
sys:style=Bold
hlv:style=Bold Italic
Fixed:style=Bold
goth_p:style=Bold
sys:style=Bold Italic
...

Finally, I need to restart Tomcat. Now when I log back into JasperServer I see everything rendered correctly. Woo hoo! The report was good. JasperServer was good. Tomcat was good. Everything was good… except the underlying operating system didn’t have any appropriate fonts.

Sales by Month report in Japanese

Sales by Month correctly displaying all Japanese characters

Other Fonts

What about when you want to specify the precise font that you need? That’s a good question. I ignored it in this article. The short answer is that you need to use Font Extensions. I wrote about it previously in my article “Fonts in JasperServer“.

In general the use of Java logical fonts makes things more flexible. That’s what made it the ideal choice for sample reports that ship with JasperServer. But it’s possible that different systems will map the logical fonts to different physical fonts. These fonts may have slightly different metrics, so the results in the report can be slightly unpredictable.

In many reports, you simply don’t care about the minor font metric differences. On one machine a particular value fits on a single line. On another machine it overflows into a second line. So what?

In other reports you have more precise positioning requirements. Your title fits nicely on a single line at design time. But when the report is deployed the final word in the title overflows into a second line. That won’t look impressive. Worse: that field isn’t allowed to expand, so you don’t see the final word anywhere. Bummer. In cases like this you need to specify the precise font that gets used. Of course it therefore becomes your responsibility to make sure that the server has the font that you want to use. For these situations Font Extensions are your savior.

13 May 2009

Fonts in JasperServer

Filed under: JasperServer — Tags: , , , , , , — mdahlman @ 18:00

Article updated

Most folks should refer to my updated article on Fonts in JasperServer 3.7 instead of the article below. But I’m leaving the old article here for cases where someone needs to run the older version of JasperServer.

JasperServer 3.5.1 released

JasperServer Professional 3.5.1 from Jaspersoft will be released shortly. One of the more anticipated features for me will be the inclusion of a localized Chinese GUI. I got a sneak peek at it this morning. The menus and user interface are completely in Chinese (if I choose the appropriate locale). Hooray! But I ran one of the sample reports, and this is what I saw:

The report is not completely localized

The report is not completely localized

What’s wrong with this picture? The text that stands by itself is fine, but the text that gets rendered as part of the chart image doesn’t display correctly at all. How can this be? Everything is Java-based, so I shouldn’t have localization issues. The problem is that the report specifies Verdana as its font for nearly everything, but Verdana doesn’t include support for Chinese characters. (Interestingly, the text that displays well was also specified as Verdana. But the browser realizes the specified font doesn’t have the correct characters, so it automatically substitutes another font. It’s a useful feature, but it made understanding the underlying problem more difficult.) The solution is to select appropriate fonts.

Fixing the fonts

Fortunately it’s not any sort of JasperServer bug; it’s just an issue with the sample reports. Now that I see what’s causing the problem, it should be easy to fix:

  1. Update the report to use an appropriate font
  2. Deploy the font to JasperServer

Updating the report should be easy. Open iReport, connect to JasperServer, get the reports, set the font. But the devil is in the details. The sample report with the problem is/supermart/salesByMonth/SalesByMonthReport. I open it, find the chart, find the property “Legend font” and see that the current font is “Verdana”. I change this to “Arial Unicode MS”. I save the report back to JasperServer and see what it looks like now. No change. This isn’t be surprising because the server doesn’t have the font in its classpath anywhere.

I’ve never deployed a font to JasperServer before. So it took a little poking around in the documentation and the samples to see what was needed. The key concept is the need for JasperReports Font Extensions. The JasperReports Ultimate Guide has a good explanation and tutorial, so I was off to a good start. Three files are needed:

  1. jasperreports_extension.properties
  2. fonts.xml
  3. The actual font file (This might be multiple files… but in my case it was just one.)

All of the files need to be in the Java classpath, so this is a good place to put them given that I’m using Apache Tomcat: …\Tomcat 5.5\webapps\jasperserver-pro-3.5\WEB-INF\classes

jasperreports_extension.properties

The name of this file is important. JasperReports knows to load the file based on its name. Its contents are simple. I copied it unmodified from the documented example:

net.sf.jasperreports.extension.registry.factory.fonts=net.sf.jasperreports.extensions.SpringExtensionsRegistryFactory
net.sf.jasperreports.extension.fonts.spring.beans.resource=fonts.xml

fonts.xml

This file can take any name; it just needs to match what is specified above. The contents are only minimally updated from the sample provided:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
 <bean id="myFontFamily" class="net.sf.jasperreports.engine.fonts.SimpleFontFamily">
   <property name="name" value="Arial Unicode MS"/>
   <property name="normal" value="fonts/ARIALUNI.TTF"/>
   <property name="pdfEncoding" value="Identity-H"/>
   <property name="pdfEmbedded" value="true"/>
 </bean>
</beans>

I chose the font Arial Unicode MS because it includes Chinese characters, and it ships with MS Office. There are other downloadable fonts available for people that don’t have access to this one.

The font file(s)

In fonts.xml the font file is specified as fonts/ARIALUNI.TTF. I did this so I could put all of my fonts into a subdirectory under the classes directory. I’m using default locations for everything, so this was the copy command:

copy C:\WINDOWS\Fonts\ARIALUNI.TTF "C:\Program Files\Apache Software Foundation\Tomcat 5.5\webapps\jasperserver-pro-3.5\WEB-INF\classes\fonts"

Enjoy the corrected reports

After restarting JasperServer, the report now looks like this:

Now everything is correctly localized into Simplified Chinese

Everything is correctly localized into Simplified Chinese

The process is simple, but it’s not entirely intuitive. And you need to get things exactly right. Hopefully this will be an aid to anyone encountering localization issues with the charts (JFreeChart) in JasperServer.

Additional Details

I described the step-by-step process only for the chart legend. But there are a few more properties that need to be set for anyone that wants the complete demo dashboard to display correctly.

In the report /supermart/salesByMonth/SalesByMonthReport you need to set both the “Legend font” and the “Category Axis Tick Label Font”. There are two charts (one on top of the other), so be sure to set both properties for both charts.

In the report /supermart/revenueAndProfit/SalesGaugesReport it’s the “Value Font” that needs to be changed. This property should be set for all four dial gauges.

Create a free website or blog at WordPress.com.