Skip to content

Using sed in Jenkins Groovy pipeline

I spent some time trying to figure out how to fix unexpected slash char error in my pipeline.

My aim was to change some value in a config file after checking out a Git repository. I have a Jenkins pipeline and I used sed to perform the substitution.

The pipeline wouldn’t even compile because of Groovy’s way of handling slashes. I was constantly getting “unexpected slash char” error.

Eventually, I made it work this way:

stage('Some stage) {
    steps {
        sh script: $/
        sed -i 's/^\(SOME_VAR=*\).*$/\1SOME_VAL/' ./config/default.conf

Having the following default.conf:

SOME_VAR=Literally any string value

The pipeline’s step will turn it into:


Good job, I think 🙂

Configuring Mach3 for a CNC milling machine on Windows 7

Long time no posts, huh? I have a lot of interesting news and I hope to have some time to write it here. However, this post was inspired by my yesterday’s experience.

My dad bought a CNC milling machine and the responsibility of connecting and configuring it became mine. So we have an old PC with an LPT port, Windows 7 on it, Mach3 software and a CNC milling machine. Let’s connect it together and run, seems easy.

Read More →

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:

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 -->
    <default-page-settings height="11.00in" width="8.50in"/>
        <renderer mime="application/pdf">
                <font kerning="yes" embed-url="path/to/Roboto-Regular.ttf" embedding-mode="subset">
                    <font-triplet name="Roboto" style="normal" weight="normal"/>
                <font kerning="yes" embed-url="path/to/Roboto-Bold.ttf" embedding-mode="subset">
                    <font-triplet name="Roboto" style="normal" weight="Bold"/>

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

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

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:
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();

        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());

        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 =;
    FopFactoryBuilder factoryBuilder = new FopFactoryBuilder(new File(CURRENT_DIR).toURI(), new CustomPathResolver()).setConfiguration(config);
    fopFactory =;
} 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[] 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;

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

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) {
    case 1:
    case 2:

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:


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;

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

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.

A review of the 2018

I think it is the first review of the past year I ever wrote, but it might become a good tradition 😊
So, below I list some highlights from the outgoing year. Let’s start from a funny pic of my cat :3

Winter 2018

I bought a new phone on January 4 and this time it was Android. It is my first Android phone, before that I used Apple. Everything is fine and I even fell more comfortable with some features iPhones don’t have. However, I think Apple makes more secure phones and I miss iPhone’s camera quality. I broke its screen somewhen in summer when I was helping my friend to move house. No photos here. 📱

Usually, I don’t like cold weather, snow and so forth, but this year I tried mountain skis and then snowboarding. Now I like winter and mountains. We spent our vacation at Sochi’s Rosa Khutor ski resort in April, participating at Quicksilver New Star Camp festival, which was fantastic.

In Spring, I participated in my first hackathon. We were developing an application in a team of 5 people for almost 24 hours without sleep! Our application was intended to track parking places on a car park and display which place is taken and which one is free on a mobile phone. On the back-end side, we used Tensor Flow to analyse a video stream from a camera, Java and PostgreSQL to handle and store the data. On the front-end side, we used React, GraphQL and PWA to fetch and display the data on a mobile phone.

Meanwhile, a Vietnamese cafe opened in my hometown. We often visit it with friends and have some good food there.

I visited many beautiful places and events.

We spent a great time in Konstantinovo near Ryazan (actually it wasn’t so great because of a ton of mosquitoes!)

We went rafting for 3 days!

We visited a sober party of free travellers and hitchhikers. It was cool to listen to people who crossed the whole Russia on suburb trains, lived in different countries for months, travelled to Africa and Sri Lanka, not just to stay in a 3, 4 or 5 stars hotels, but to live among other people from those countries. I walked away with a conclusion: if you have to walk for several hours, please, wear some comfy shoes next time!

We had a great summer party with our colleagues. We played different games, swam in a river and chilled.

In August we had our second vacation. Our friends came to visit us in Ryazan. Yes, my haircut definitely proves that I’m on vacation. 😁

Suddenly we decided to go to the seaside by car in a few days. We packed our luggage and covered about 3000 km in the next ten days. We stayed in campings, it was my first experience living at the sea in a tent. A good experience!

Are you still reading? Wow. You should know that I am already tired writing this post 😃. I think my year was really cool! So, this was the summer.
In autumn we also had two interesting trips and new experiences. We visited Yaroslavl, a beautiful city where my grandmother lived before getting married.
It was my first time staying in a hostel. It wasn’t very comfortable because of small children crying. 🙄
I’ve already written about Yaroslavl here.

About 13 years ago (omg really), I played an MMORPG called Lineage II. One of my friends invited us to visit a festival dedicated to this game. One of my favourite music bands who play power metal 🤘🏻were there.

In October, we spent a night in nature, built a banya, had a steam bath, swam in the Oka river, walked to a “drunk forrest” and had a lot of fun (we even had problems with the police, but eventually everything was fine).

To continue the topic about PC games, I visited a Dota 2 tournament in Moscow. I play it occasionally, but I’m not a professional. It was interesting to see how the teams were smashing each other to get a prize.

Huh, that’s it about traveling in 2018. I didn’t know I visited so many places! 😃

In 2018 I became modern and bought a wearable device. It’s the Xiaomi Amazfit Bip smart watch. Now I count my steps and measure the deep sleep phase. What’s the most amazing about it – I can set up a countdown timer right on my hand when I boil eggs! 🐣

I also started doing yoga and running. However, I prefer running outside and when it’s warm, so I plan to continue running in Spring 2019. Yoga is fine anytime!

I played as many tabletop games as I never played before. I think the number is more than 10!

We met really nice guys and we still keep in touch – Kostya, Dima, Anya and Nastya. They visited us in Ryazan and created a funny local meme about one of the cafes we visited. 💇🏻

I held a snake! I’m afraid of them. Actually, I can’t say it was a try to overcome one of my phobias, as it was not poisonous and dangerous. It was really cute and friendly. Meet the corn snake:

A few words about my plans that didn’t have a chance to be brought to life.

I haven’t tried hitchhiking
I haven’t had a several-days-long ride on a bicycle
I haven’t run my own pet project (but sometimes I commit there 🙂)

I hope to turn these into reality next year.

Happy New Year! 🎉🎄
2018 was very good, wasn’t it?
I wish you all the best in 2019!

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;


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/

Decompiling the class:

javap -c src/com/imsavva/ConcatenationTestApp

Continue reading to see what happens next.

Read More →