Skip to content

IT related

Generating PDF with Apache FOP and Maven. An example and some tricks.

This January (and, actually, February) I worked on generating PDF files. During the investigation process, we’ve chosen Apache FOP as a free powerful tool for this task.

Firstly I wanted to write a step by step guide on how to generate a PDF file from a Java object. But eventually, I decided to keep it short, as the original documentation contains almost all you need.

So in this blog I’ll describe some interesting moments that I met during the development phase.

Also, I’ve prepared an example project, feel free to clone and play around:
https://github.com/savva-k/apache-fop-example

Adding custom fonts to FOP

Adding fonts is pretty simple. I used an XML config, so I will show how to do that in XML:

<?xml version="1.0"?>
<fop version="1.0">
    <!-- Simple FOP XML config -->
    
    <base>.</base>
    <strict-validation>false</strict-validation>
    <strict-configuration>false</strict-configuration>
    <source-resolution>72</source-resolution>
    <target-resolution>72</target-resolution>
    <default-page-settings height="11.00in" width="8.50in"/>
    <renderers>
        <renderer mime="application/pdf">
            <fonts>
                <font kerning="yes" embed-url="path/to/Roboto-Regular.ttf" embedding-mode="subset">
                    <font-triplet name="Roboto" style="normal" weight="normal"/>
                </font>
                <font kerning="yes" embed-url="path/to/Roboto-Bold.ttf" embedding-mode="subset">
                    <font-triplet name="Roboto" style="normal" weight="Bold"/>
                </font>
            </fonts>
        </renderer>
    </renderers>
</fop>

Then we can use the font by setting the font-family attribute:

<fo:root font-family="Roboto">
    <someContent>
        This font is regular.
        <fo:inline font-weight="bold">This font is bold.</fo:inline>
    </someContent>
</fo:root>

How to use WOFF fonts with Apache FOP?

I didn’t find the answer to this question. But I’ve found a good WOFF to OTF conversion tool! Here it is: https://github.com/hanikesn/woff2otf
OTF fonts work fine with FOP.

How to access fonts from resources in a JAR?

At some time I realized that all the fonts are placed in a JAR file and other resources like images from external servers are not. To solve this problem I have created a custom ResourceResolver implementation:

    public final class CustomPathResolver implements ResourceResolver {
        private static final String FONTS_FOLDER = "/fonts/";

        private ResourceResolver defaultResourceResolver = ResourceResolverFactory.createDefaultResourceResolver();

        @Override
        public Resource getResource(URI uri) throws IOException {
            if (uri.toString().contains(FONTS_FOLDER)) {
                return new Resource(PdfGenerator.class.getResourceAsStream(FONTS_FOLDER + FilenameUtils.getName(uri.toString())));
            } else {
                return new Resource(uri.toURL().openStream());
            }
        }

        @Override
        public OutputStream getOutputStream(URI uri) throws IOException {
            return defaultResourceResolver.getOutputStream(uri);
        }
    }

This ResourceResolver checks whether the requested resource is in the “fonts” folder and if so, we are looking for a resource in the classpath.
To use this ResourceResolver we should manually specify it during the FopFactoryBuilder creation.

DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
try {
    Configuration config = cfgBuilder.build(PdfGenerator.class.getResourceAsStream(CONFIG_FOP_XML));
    FopFactoryBuilder factoryBuilder = new FopFactoryBuilder(new File(CURRENT_DIR).toURI(), new CustomPathResolver()).setConfiguration(config);
    fopFactory = factoryBuilder.build();
} catch (Exception e) {
    // handling the error
}

Apache FOP cannot load images via HTTPS

In my case, the root cause was the SSLHandshakeException. My server didn’t trust the server that hosted the image. I wouldn’t do that neither!

This problem has at least three solutions: the best, a good one and the one I had to use.

The best solution: use a certificate issued by a well known CA on the server that hosts your images.

A good solution: add the server’s certificate to your keystore.

The last solution is to disable checking certificate validity at all. This is not recommended, as you become vulnerable to man-in-the-middle attacks.
To do this, you should implement a new TrustManager and a HostnameVerifier, initialize an SSLContext and set the HostnameVerifier to the HttpsURLConnection (which is used internally by Apache FOP).

static {
    TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }
        public void checkClientTrusted(X509Certificate[] certs, String authType) {
        }
        public void checkServerTrusted(X509Certificate[] certs, String authType) {
        }
        }
    };

    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, new java.security.SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

    HostnameVerifier allHostsValid = new HostnameVerifier() {
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    };
    HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
}

I think that’s it and I hope this helps. 🙂

Possible class names in Java

What would be the result of execution of the following code?

package com.imsavva;

public class Test {
    public static void main(String[] args) {
        System.out.println(new _成分$().getGreeting());
    }
}

class _成分$ {
    public String getGreeting() {
        return "Hello";
    }
}

If your answer is “Hello”, then you’re right!
You can use any characters from the Unicode charset, in any case, to name classes (as well as variables and methods), except some preserved words like “null”, “volatile”, “public”, etc.

However, it’s strongly recommended to stick with the Java code conventions. The rules related to the class names are on page 10.

First two reasons to use the code conventions to me are:

  • Readability – I would love to meet class names like “Eyjafjallajökull” from time to time. But, the rarer the better.
  • Convenience for programmers from different countries – imagine the situation when you have to work with the code where class names contain symbols that are missing on your keyboard? 🙈

Switch case and default

int i = 0;

switch (i) {
    default:
        System.out.println("1");
    case 1:
        System.out.println("2");
    case 2:
        System.out.println("3");
}

This snippet will compile and run without issues. It might be dubious whether it’s okay to put the “default” block at the first place, but you can place it anywhere. In this case, the result would be:

1
2
3

However there is a good practice to put the “default” block at the end of the switch statement. Or avoid using switch statements at all. 🙂

Variables and fields instantiation

package com.imsavva;

public class Test {
    private String testField;
    
    public static void main(String[] args) {
        String testVariable;
        System.out.println(testVariable);
    }
}

This code won’t compile because of line 4:

When we declare a local variable, it must be initialized before use. Class fields don’t have to be initialized. In case we didn’t specify any value, a default value will be used.

The following list represents default field values:

    private byte b;     // 0
    private short s;    // 0
    private int i;      // 0
    private long l;     // 0
    private float f;    // 0.0f
    private double d;   // 0.0
    private char c;     // '\u0000'
    private String str; // null

1Z0-808 Preparation notes

The process of studying Java Core. The picture was taken from Unsplash.com.

During the preparation time, I was making notes to remember little tricks that I didn’t know or forgot. Although I would never recommend using some of the pieces of code from the notes in production, they might be helpful for those who are preparing for the exam.

So, as I mentioned in this post, I will do my best to keep my New Year’s resolution and post the most useful notes in my blog. Along with the main topic I will try to explain why some of the code examples should never appear in your production code.

All the posts related to this topic will be marked with a tag 1Z0-808.

Passed the Oracle 1Z0-808 certification

Good news, everyone!

Even though this is the first blog in 2018, I’m still alive and I’m happy to say that I have passed the Oracle Certified Associate exam with 94% of correct answers (I still can’t believe it 😱).

It took about a month to prepare and I was spending all my free the time after work to read a book and write and test code examples.

While preparing, I have made more than a hundred of small notes, and I hope to find time and motivation in the next two months to post them here.

See you in 2019 🙂🎄

Using StringBuilder instead of usual concatenation. When is it appropriate?

You might know that using string concatenation in Java is not a good practice as it might affect performance. In this short article, I will try to describe when it is necessary to use StringBuilder and when we can afford using concatenation (+ sign).

Let’s start with a simple example:

package com.imsavva;

public class ConcatenationTestApp {

    public static void main(String[] args) {
        String str = "abc";
        str = str + "def";
        str += "12" + "34" + str;

        System.out.println(str);
    }
}

To see how it works under the hood, let’s compile and decompile it. I tried this using Java 6 and Java 8.

Compiling the code:

javac src/com/imsavva/ConcatenationTestApp.java

Decompiling the class:

javap -c src/com/imsavva/ConcatenationTestApp

Continue reading to see what happens next.

Read More →

Logging in ATG: how to send error reports to Elasticsearch and display them with Kibana

 

Oracle ATG logging: sending reports to Elasticsearch, displaying errors with KibanaIn this article, I’m going to share my experience with Oracle ATG logging system and such great tools like Elasticsearch and Kibana. Imagine that we have a big ATG-based project and our task is to store and list all the users who met (explicitly or not) errors. To solve this task we will add a new event listener to filter errors, will face a problem with resolving users’ profile from the listener, will send an error report to an Elasticsearch server and finally display the data with Kibana.

Although this article describes creating ATG-specific logging feature, it will be quite easy to adjust this tutorial for using with Slf4j or whatever you want.

Elasticsearch and Kibana are part of so-called ELK stack. Letter “L” stands for Logstash, which is a great tool that crawls data from multiple sources, transforms it and sends to a target (e.g. file or Elasticsearch). However, I decided not to use Logstash here, because Elasticsearch provides a good API which is enough for this task.

So, let’s get started.

Read More →