An Oracle blog about BI Publisher

Quick Quips on QR Codes

Yes, I'm an alliterating all-star; I missed my calling as a newspaper headline writer.
I have recently received questions from several folks on support for QR codes. You know them they are everywhere you look, even here!

How does Publisher handle QR codes then? In theory, exactly the same way we handle any other 2D barcode font. We need the font file, a mapping entry and an encoding class. With those three pieces we can embed QR codes into any output.

To test the theory, I went off to IDAutomation, I have worked with them and many customers over the years and their fonts and encoders have worked great and have been very reliable.
They kindly provide demo fonts which has made my life so much easier to be able to write posts like this. Their QR font and encoder is a little tough to find. I started here and then hit the Demo Now button. On the next page I hit the right hand Demo Now button. In the resulting zip file you'll need two files:
 AdditionalFonts.zip >> Automation2DFonts >> TrueType >> IDAutomation2D.ttf
 Java Class Encoder >> IDAutomation_JavaFontEncoder_QRCode.jar - the QRBarcodeExample.java is useful to see how to call the encoder.

The font file needs to be installed into the windows/fonts directory, just copy and paste it in using file explorer and windows will install it for you. Remember, we are using the demo font here and you'll see if you get your phones decoder to looks a the font above there is a fixed string 'DEMO' at the beginning. You want that removed? Go buy the font from the IDAutomation folks.

The Encoder

Next you need to create your encoding wrapper class. Publisher does ship a class but its compiled and I do not recommend trying to modify it, you can just build your own. I have loaded up my class here. You do not need to be a java guru, its pretty straightforward. I'd recommend a java IDE like JDeveloper from a convenience point of view. I have annotated my class and added a main method to it so you can test your encoders from JDeveloper without having to deploy them first. You can load up the project form the zip file straight into JDeveloper.

Next, take a look at IDAutomation's example java class and you'll see:

QRCodeEncoder qre=new QRCodeEncoder();
 String DataToEncode = "IDAutmation Inc.";
 boolean ApplyTilde = false;
 int EncodingMode = 0;
 int Version = 0;
 int ErrorCorrectionLevel = 0;
 System.out.println( qre.FontEncode(DataToEncode, ApplyTilde,
EncodingMode, Version, ErrorCorrectionLevel) );

You'll need to check what settings you need to set for the ApplyTilde, EncodingMode, Version and ErrorCorrectionLevel. They are covered in the user guide from IDAutomation here. If you do not want to hard code the values in the encoder then you can quite easily externalize them and read the values from a text file. I have not covered that scenario here, I'm going with IDAutomation's defaults and my phone app is reading the fonts no problem.

Now you know how to call the encoder, you need to incorporate it into your encoder wrapper class. From my sample class:

      Class[] clazz = new Class[] { "".getClass() };  
      ENCODERS.put("code128a",mUtility.getClass().getMethod("code128a", clazz));
      ENCODERS.put("code128b",mUtility.getClass().getMethod("code128b", clazz));
      ENCODERS.put("code128c",mUtility.getClass().getMethod("code128c", clazz));
      ENCODERS.put("qrcode",mUtility.getClass().getMethod("qrcode", clazz));

I just added a new entry to register the encoder method 'qrcode' (in red). Then I created a new method inside the class to call the IDAutomation encoder.

/** Call to IDAutomations QR Code encoder. Passing the data to encode
     Returning the encoded string to the template for formatting **/
public static final String qrcode (String DataToEncode)
  QRCodeEncoder qre=new QRCodeEncoder();
   boolean ApplyTilde = false;
   int EncodingMode = 0;
   int Version = 0;
   int ErrorCorrectionLevel = 0;
return qre.FontEncode(DataToEncode, ApplyTilde, EncodingMode, Version, ErrorCorrectionLevel);

Almost the exact same code in their sample class. The DataToEncode string is passed in rather than hardcoded of course.

With the class done you can now compile it, but you need to ensure that the IDAutomation_JavaFontEncoder_QRCode.jar is in the classpath.
In JDeveloper, open the project properties >> Libraries and Classpaths and then add the jar to the list. You'll need the publisher jars too. You can find those in the jlib directory in your Template Builder for Word directory.

Note! In my class, I have used

package oracle.psbi.barcode;

As my package spec, yours will be different but you need to note it for later.

Once you have it compiling without errors you will need to generate a jar file to keep it in.
In JDeveloper highlight your project node >> New >> Deployment Profile >> JAR file. Once you have created the descriptor, just take the defaults. It will tell you where the jar is located. Go get it and then its time to copy it and the IDAutomation jar into the Template Builder for Word directory structure.

Deploying the jars

On your windows machine locate the jlib directory under the Template Builder for Word install directory. On my machine its here, F:\Program Files\Oracle\BI Publisher\BI Publisher Desktop\Template Builder for Word\jlib. Copy both of the jar files into the directory.

The next step is to get the jars into the classpath for the Word plugin so that Publisher can find your wrapper class and it can then find the IDAutomation encoder. The most consistent way I have found so far, is to open up the RTF2PDF.jar in the same directory and make some mods.

First make a backup of the jar file then open it using winzip or 7zip or similar and get into the META-INF directory. In there is a file, MANIFEST.MF. This contains the classpath for the plugin, open it in an editor and add the jars to the end of the classpath list. In mine I have:

Manifest-Version: 1.0
Class-Path: ./activation.jar ./mail.jar ./xdochartstyles.jar ./bicmn.jar ./jewt4.jar
./share.jar ./bipres.jar ./xdoparser.jar ./xdocore.jar ./xmlparserv2.jar
./xmlparserv2-904.jar  ./i18nAPI_v3.jar ./versioninfo.jar
./barcodejar.jar ./IDAutomation_JavaFontEncoder_QRCode.jar

Main-Class: RTF2PDF

I have put in carriage returns above to make the Class-Path: entry more readable, make sure yours is all on one line. Be sure to use the ./ as a prefix to the jar name. Ensure the file is saved inside the jar file 7zip and winzip both have popups asking if you want to update the file in the jar file.
Now you have the jars on the classpath, the Publisher plugin will be able to find our classes at run time.

Referencing the Font

The next step is to reference the font location so that the rendering engine can find it and embed a subset into the PDF output. Remember the other output formats rely on the font being present on the machine that is opening the document. The PDF is the only truly portable format.

Inside the config directory under the Template Builder for Word install directory, mine is here,
F:\Program Files\Oracle\BI Publisher\BI Publisher Desktop\Template Builder for Word\config.
You'll find the file, 'xdo example.cfg'. Rename it to xdo.cfg and open it in a text editor.
In the fonts section, create a new entry:

       <font family="IDAutomation2D" style="normal" weight="normal">
             <truetype path="C:\windows\fonts\IDAutomation2D.ttf" />

Note, 'IDAutomation2D' (in red) is the same name as you can see when you open MSWord and look for the QRCode font. This must match exactly. When Publisher looks at the fonts in the RTF template at runtime it will see 'IDAutomation2D' it will then look at its font mapping entries to find where that font file resides on the disk. If the names do not match or the font is not present then the font will not get used and it will fall back on Helvetica.

Building the Template

Now you have the data encoder and the font in place and mapped; you can use it in the template. The two commands you will need to have present are:

<?register-barcode-vendor:'ENCODER WRAPPER CLASS'; 'ENCODER NAME'?> 

for my encoder I have:

<?register-barcode-vendor:'oracle.psbi.barcode.BarcodeUtil'; 'MyBarcodeEncoder'?>

Notice the two parameters for the command.
The first provides the package 'path' and class name (remember I said you need to remember that above.)
The second is the name of the encoder, in my case 'MyBarcodeEncoder'. Check my full encoder class in the zip linked below to see where I named it. You can change it to something else, no problem.
This command needs to be near the top of the template.

The second command is the encoding command:


for my command I have

DATATEXT is the XML element that contains the text to be encoded. If you want to hard code a piece of text just surround it with single quotes.

qrcode is the name of my encoder method that calls the IDAutomation encoder. Remember this.
MyBarcodeEncoder is the name of my encoder. Repetition? Yes but its needed again.

Both of these commands are put inside their own form fields.

Do not apply the QRCode font to the second field just yet. Lets make sure the encoder is working. Run you template with some data and you should get something like this for your encoded data:


Grooovy huh? If you do not get the encoded text then go back and check that your jars are in the right spot and that you have the MANIFEST.MF file updated correctly.
Once you do get the encoded text, highlight the field and apply the IDAutomation2D font to it. Then re-run the report and you will hopefully see the QR code in your output. If not, go back and check the xdo.cfg entry and make sure its in the right place and the font location is correct.

That's it, you now have QR codes in Publisher outputs. Everything I have written above, has been tested with the 5.6.3, codelines. I'll be testing the 11g code in the next day or two and will update you with any changes.

One thing I have not covered yet and will do in the next few days is how to deploy all of this to your server. Look out for a follow up post.

One note on the apparent white lines in the font (see the image above). Once printed they disappear and even viewing the code on a screen with the white lines, my phone app is still able to read and interpret the contents no problem.

I have zipped up my encoder wrapper class as a JDeveloper project here. Just dig into the src directories to find the BarcodeUtil.java file if you just want the code. I have put comments into the file to hopefully help the novice java programmer out.

Happy QR'ing!

Join the discussion

Comments ( 6 )
  • guest Wednesday, November 21, 2012

    Hi Tim,

    I have done all the necessary steps, but I am getting a blank column. Can you show the screen shots how you wrote the commands in RTF template.

    I have generated the BarcodeUtil.jar and .class files and placed them in the appserver/classes path successfully.

  • guest Monday, February 24, 2014

    I am following the same procedure as per given above. The font name is: IDAutomationDMatrix Regular. When I try to preview my RTF to PDF, I get error saying that : 'Could not find main class: RTF2PDF. Program will exit'. Kindly help on the same.

  • Ariel Friday, February 28, 2014

    Hi Tim:

    We are experiencing a problem when bi publisher call to encode method in our enterprise server (linux OS), it raise an exception. But when we test the method from a external program or into a desktop Winword Bi Publisher plugin it works well.

    We activated the xdo.log (bi publisher) and appears this exception into the encode routine: I'm afraid that there are some restrictions i don't know, because the parameters are correct, and testing in our desktop it works well. I would like comment that our enterprise server are supported in linux platform..

    Can you tell me what's going on? Because we are interested into buy the font, but we are not making it work. I will appreciate your response

    Here you have a extract of log with the exception:

    [022714_174511772][][STATEMENT] XSLT temporary file (/tmp/cxmlwWGJvet48W8384302606065119879.dat) is set.


    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

    at java.lang.reflect.Method.invoke(Method.java:597)

    at oracle.xdo.common.xml.XSLT10gR1.invokeProcessXSL(XSLT10gR1.java:917)

    at oracle.xdo.common.xml.XSLT10gR1.transform(XSLT10gR1.java:609)

    at oracle.xdo.common.xml.XSLT10gR1.transform(XSLT10gR1.java:327)

    at oracle.xdo.common.xml.XSLTWrapper.transform(XSLTWrapper.java:187)

    at oracle.xdo.template.fo.util.FOUtility.generateFO(FOUtility.java:1181)

    at oracle.xdo.template.fo.util.FOUtility.generateFO(FOUtility.java:276)

    at oracle.xdo.template.FOProcessor.createFO(FOProcessor.java:1973)

    at oracle.xdo.template.FOProcessor.generate(FOProcessor.java:1117)

    at com.jdedwards.xmlp.templates.RtfTemplate.generateReport(Unknown Source)

    at com.jdedwards.xmlp.base.XmlpProxy.generateReport(Unknown Source)

    Caused by: java.lang.NullPointerException

    at com.idautomation.fontencoder.qrcode.QRCodeEncoder.FontEncode(com/idautomation/fontencoder/qrcode/QRCodeEncoder)

    at oracle.apps.xdo.template.rtf.util.barcoder.BarcodeUtil.codeqr(BarcodeUtil.java:111)

    And this is our portion of code

    /** This is the complete method for Code128a */

    public static final String codeqr( String DataToEncode )


    Logger.log("ARCOR BEGIN codeqr: "+DataToEncode, 5); // here the data to encode is " La Serrana in our execution"

    QRCodeEncoder qre=new QRCodeEncoder();

    boolean ApplyTilde = false;

    int EncodingMode = 0;

    int Version = 0;

    int ErrorCorrectionLevel = 0;

    String Printable_string = qre.FontEncode(DataToEncode, ApplyTilde, EncodingMode, Version, ErrorCorrectionLevel);

    Logger.log("ARCOR END codeqr: "+Printable_string, 5);

    return Printable_string;


    Operating System: Linux

    Application: Embedded Bi Publisher from EnterpriseOne

  • Tony Thomas Saturday, October 18, 2014

    Dear Tim,

    I am trying to print QR code on My Oracle Apps R12 Report, but i am stucked at halfway point.

    steps done

    1. created the BarcodeUtil.java file and place in $JAVA_TOP/oracle/apps/xdo/template/util directory(my Package Name is oracle/apps/xdo/template/util/barcoder)

    2. copied the IDAutomation_JavaFontEncoder_QRCode.jar to $JAVA_TOP/oracle/apps/xdo/template/util

    3. run javac -g BarcodeUtil.java

    here errors getting created

    Have no idea what to do, Please help as i got Zero Java knowledge



  • Tim Monday, October 20, 2014

    Hi Tony

    There are no errors in the text. Have you logged an SR with support to get some formal help? Blog comments are not the best way to tackle this.

    I think you jars are not going to be picked up by the java executables. Log that SR for some help where to put them.



  • Tony Thomas Friday, October 24, 2014

    Hi Tim,

    I got Barcodes working fine in R12.(Have to Implement this for my client soon)

    Steps as you mentioned in your blog only



    1. Open the Encoder class file provided by vendor(eg using JDeveloper) and see the package name for our encoder class

    for eg: package com.idautomation

    2. Create directory under $JAVA_TOP/classes

    in our eg. Create com directory and idautomation subdirectory under classes directory ie classes/com/idautomation

    3. The Encoder class has to be placed in this subdirectory (Mistake made by me here by placing the jar file here instead of class file)

    4. Created BarcodeUtil.java , which will have an import pointing to the encoder.class in the subdirectory we created. placed BarcodeUtil.java in

    $JAVA_TOP/oracle/apps/xdo/template/rtf/util directory

    5. Compile and create BarcodeUtil.class

    All step is as per your blog, just a little breakup for Java Beginner like me



Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.