The goal of this article series is to share our experience of building a new system for processing small-scale transactions within the Y Soft product suite. This article will discuss the main system requirements and high-level architecture decisions we made. Following articles will describe how we used the chosen technologies and the challenges we faced.

Back in 2011, YSoft SafeQ (the main Y Soft product dealing with print management) contained a component that limited users’ consumption based on their account balance and printing costs. However, it was tightly coupled with YSoft SafeQ and its maintenance; further development and customizations were too expensive to continue in this manner. So in 2012, we made the decision to create a separate system for payment transaction processing. At that time, Y Soft opened a new development branch in Prague and hired a new team to build this green field project.


The main requirements for Payment System were the following:

  • Compatibility – it had to be able to do what the old solution did, obviously 🙂
  • Strong data consistency (among all cluster nodes) – we would be dealing with money and many of our customers would not like it if their users continued printing for free once they hit 0 on their account or if any money transactions had been lost.
  • Deployment in the customer environment – we do not host our products ourselves rather our products run in the customer’s environment. This means that the environments vary from big data centers with plenty of resources (think big banks and universities) to every day workstations (small businesses).
  • Extensibility – some of our customers have their own payment processing systems that manage monetary accounts. There are also plenty of different payment gateways in various countries for money deposits. We had to be able to integrate Payment System with all of them at a minimal cost (ideally offloading the cost to a 3rd party).
  • YSoft Payment Machines – Y Soft also develops its own hardware for depositing money – the YSoft Payment Machine so we had to support those as well.

We also imposed some requirements of our own:

  • Fast development – the project must be simple to build and simple to run with as few steps as possible to start developing. New developers should not have to spend several days in order to build and run the solution. Nobody should be made to memorize 30-step manuals to build or run anything!
  • Simple design – everybody hates to write (and read) documentation, therefore, we wanted to design the system according to KISS principles so that we could concentrate on programming and not on explaining complex design to our co-workers.
  • Flexible UI – we have seen our share of Java web frameworks and we cannot say it has ever been a pleasant experience. Especially if something does not work as it is supposed to, or if you need just some little extra that the framework does not provide out of the box. Therefore, we wanted the UI to be simple but flexible.

How We Addressed the Requirements


One of the challenges was to find out what the old solution really did since there was not much documentation (hardly any at all :-)). We gathered requirements from various sources, mainly company board members and QA analysts (since we did not have product management at that time) and prepared a sizable business analysis. That way we were quite confident that we understood the requirements and that all of the participants had the same notion of the system to be delivered.


The main requirements boiled down to a system that manages monetary accounts and provides the means to create 2-step and multi-step transactions on those accounts (which map to the print and copy processes of YSoft SafeQ). The system should also provide means to manipulate account balances by a cash desk operator.

We wanted to create a more general purpose payment transaction processing system so we analyzed existing systems like PayPal, Google Wallet and Amazon Payments, to avoid reinventing the wheel, regarding naming and the functionality of different operations. The result is a system that is being deployed in production and tested as standalone without YSofr SafeQ, sometimes in surprising setups, e.g., machines for selling candy in Switzerland :-).

Data Consistency

Since we needed to keep the data consistent, we chose a straightforward solution – one shared database and multiple stateless application servers. There were also other options, like a fully distributed solution or a single application. But we wanted failover, so a single application was not an option. On the other hand, a fully distributed solution would be a lot more complex and would have many necessary limitations during network partition (there are plans for a different system that will be fully distributed, but for different use cases, and we will achieve consistency in a different way).

NoSQL databases are currently very popular, but they are mostly targeted at cloud provider infrastructure with reliable networks. Environments where partitions happen on a daily basis (e.g., nodes are online only when the owner of the machine is at work) are not ideal for them.

Therefore, we chose a traditional SQL database as the database solution. YSoft SafeQ supports PostgreSQL and MSSQL, so that was the minimal set of supported DBs for us as well. We delegate database failover to the chosen database installation.

Support Multiple Database Vendors

We need to support multiple databases and of course we do not want to duplicate code for each vendor. Besides PostgreSQL and MSSQL we use H2 for development since it does not need complex installation, it can be easily bundled with the application or used in tests and it is very flexible (in memory, persistent and server mode).

We chose tools that grant us database portability. For database structure and minimal data set insertion, we use Liquibase (more details will follow in a separate article). For querying, we use Hibernate and we have successfully avoided the need for stored procedures so far (yes, there are times when they are handy, but they come at a cost, especially when you need to support multiple DB vendors).

Deployment in the Customer Environment

The sizes and needs of our customers vary dramatically, so we provide several different deployment options. They range from a single application server with a schema on existing database installation to a clustered solution with multiple application servers behind a load balancer.


We achieved this by implementing the main transaction processing logic as stateless. So you can start a transaction using one node and finish it using another.

Many customers have security policies that do not allow us very good access to the installed solution and descriptive logs are a must. We have cooperated with our colleagues from the Customer Support Services department (CSS), who act as the first line of support, on reviews of log messages. The results are simple and clear log messages (usually one descriptive message per business operation), so CSS consultants can deal with many issues without our assistance.


There are four kinds of extension points in our system:

  • REST API – We chose REST mainly because it is well supported in most languages and platforms and because it is simpler to use than alternatives (like traditional web services). This way, anyone can easily integrate with us. You can even create Payment System transactions from the command line if you like. This API comes in 2 flavors:
    • Merchant API, which is used by merchants to create payment transactions.
    • Administration API, which is used for account and system management.
  • Java API for external payment processing systems – this is an extension point where either developers or CSS consultants write adapters for existing customer-specific payment processing systems. In this case, Payment System acts as a proxy for SafeQ, so SafeQ does not have to deal with the specifics of customer specific systems. Implementations have to be in Java (or another JVM language), but of course we count on providing Java adapters for payment processing systems that provide, for example, REST interfaces.
  • REST “API” for payment gateways – we have defined a REST contract that has to be implemented by an integration application. This decoupling made the internal Payment System’s design much simpler, since we do not have to care about all of the different workflows that different payment gateways use. The workflow is separated in the integration application, which is HTTP based, since most of the payment gateways we support have either HTTP POST or REST based APIs. Multiple payment gateway integrations can be configured at the same time.
  • User management API – this is an API for retrieving information about users. Currently, we rely on SafeQ as the provider of user-related information in our deployments. This is, however, impractical during development, so we have isolated this functionality in an API and have a simple DB-backed development version.

YSoft Payment Machines

YSoft Payment Machines (our own hardware for money deposits) have limited hardware – e.g., 64MB of memory for the operating system and device firmware. This was a big limitation for choosing a messaging solution, so a simple and straightforward solution like (RESTful) web services was out of reach.

We have ended up with Google Protocol Buffers on top of TCP (we use Netty on the server side). Google Protocol Buffers have a C implementation – nanopb, as well as a Java implementation and its memory footprint in C was low enough that we could use them on our devices (we could not even use a C++ version because there was not enough spare memory for C++ runtime).

Fast Development

We use Maven as our build system. We were happy using Maven on previous projects and it is fully sufficient for our needs on this project as well. The main benefit of using Maven is that developers familiar with it can build and modify the build configuration of our project easily. They do not have to learn the build specifics when switching from one project to another, which reduces the risk of making an error.

Our deployables are war files bundled with the default configuration so you can run the system just by dropping them in a web container, and you can then access Payment System right away. The defaults, which make use of the H2 database, can be changed along with other configuration options in a separate configuration file, which contains overrides.

We also provide a pre-configured version of Tomcat that we use as our production web container. We also have a Maven Cargo plugin configured so that you can start Payment System without a container installed (more on that in a separate article).

Simple Design

The design is the usual View, Controller, Service and DAO. Everybody is familiar with it and there are no surprises there. The main point here is consistency so developers do not have to think too hard about where to put the code, and they can concentrate on solving business problems. The knowledge transfer to new co-workers about the database schema, Liquibase usage, business logic and REST APIs took less than 1 hour.

Flexible UI

We use Jade4j as our templating technology with Twitter Bootstrap and jQuery all on top of Spring MVC. The templates are concise and you can see right away what HTML code will be generated. No JavaScript is generated on the server. To lessen problems associated with a double submit, we follow the POST-REDIRECT-GET idiom and try to avoid state in the view as much as possible (again more on that will follow in a separate article).


To sum it all up – by using battle-tested technologies (Hibernate, Spring, Maven, Tomcat, Liquibase, Netty) cleverly, having a simple straight-forward design and data model, we have achieved our goals and satisfied all of the requirements. We have a working and extensible system, proven in several installations, and more installations will come soon. But, of course, everything was not always easy and simple, so stay tuned…

Qt Installer Framework is a quite new framework which is currently still in development. The current version contains set of tools and utilities to create installers. The most significant feature is that the framework itself is multiplatform, it supports Windows, Mac OS X and Linux.

Great feature of QT Installer Framework is that it can download the required files from the server. That means it is not required to provide files with the installer. It works with the so called “repositories”. Thanks to this it is also able to update the files without having to download the installer again, because it creates maintenance tool which can update or uninstall the files. However the documentation is not perfect, it is missing a lot of details.

The framework is an open source project. It is built on top of the Qt (it requires static built of Qt).

The framework is really easy to use. For the basic features the user needs to know to work with XML, that is all. For advanced features the knowledge of javascript (QtScript) is required (C++ might be required for the most advanced features).


Whole installer creation process starts with creating the required folder structure.

Screen Shot 2015-01-28 at 09.16.11

There are two main folders. The config and the packages folder.


The config folder contains the installer configuration file (config.xml) and images used in the installer. There are various things that can be configured – Supported Configuration Settings. This is the example what the configuration file could look like:

<?xml version="1.0" encoding="UTF-8"?>
 <Name>YSoft SafeQ Mac Client</Name>
 <Title>YSoft SafeQ Mac Client Installer</Title>
 <Publisher>Y Soft</Publisher>


The second folder is the package folder. It contains all components that will be installed by the installer. Every component consists of two folders, the data and the meta folder.

The data folder contains all the files that will be installed on the target machine. Installer archives all data to the 7z format and extracts it on installation.

The meta folder contains configuration file(package.xml) for the component and the installation script that will be called when the component is loaded.

This is the example file of component configuration file

<?xml version="1.0" encoding="UTF-8"?>
 <DisplayName>CUPS Backend</DisplayName>
 <Description>CUPS Backend</Description>

and here is the full list of possible configuration values – Summary of Package Information File Settings.

The next file is the installation script file (installscript.js). The script is called when the installer is executed and the component is loaded. The script can add new installer wizard pages, prompt user for custom path for the component etc. This is example of a script that extracts component to the /tmp folder and moves it to the Application. Then it adds new item (log out checkbox) to the final page of the installer (the page items or pages have to be designed in Qt designer).

function Component(){
	//Connect signals to functions
	component.loaded.connect(this, componentLoaded);
	installer.finishButtonClicked.connect(this, finishClicked);

Component.prototype.createOperationsForArchive = function(archive){
	//Extract and move .app file
	component.addOperation("Extract", archive, "/tmp");
	component.addElevatedOperation("Execute","mv", "/tmp/YSoft\ SafeQ\", "/Applications", 
								   "UNDOEXECUTE", "rm", "-rf", "/Applications/YSoft\ SafeQ\");

componentLoaded = function(){
	//If this is installer load checkbox from .ui file
		installer.addWizardPageItem(component, "LogOutCheckBoxForm", QInstaller.InstallationFinished);	

finishClicked = function(){
	//If the installation was succesful, let the user log out
	if(installer.isInstaller() && installer.status == QInstaller.Success){
		var isLogOutChecked = component.userInterface("LogOutCheckBoxForm").LogOut.checked;
        if (isLogOutChecked) {
			//Todo - logout

Here is the documentation for the Component scripting.

The installer is created by executing the Qt Installer tool

binarycreator -c config/config.xml -p packages installer

where -p is path to the packages folder and -c is path to the config.xml file. The last part is the name of the installer. 

This is the look of the final installer on Mac OS X:

Screen Shot 2015-01-28 at 09.48.00

It’s quite easy to install Docker on Windows. Just download installer and follow instructions.

You might encounter following error message when starting Docker image: VT-X is not available.


The cause of this failure is enabled Hyper-V Windows Feature. We described this issue in previous article.

Here is the quick fix.

Search for “windows feature” and open “Turn Windows features on or off

Search for “Hyper-V” in Windows features and uncheck it.

hyper-v-disableClick OK and reboot the machine.

When you work with queries that involve a LEFT JOIN on a 1:n relation, you usually want to map the parent to a collection of its child elements. Imagine a simple example, a result set with two columns, daddy and kiddo (order by daddy). Try solving this problem with some pseudo-code before you read any further.

Quite commonly, result sets are processed in a simple while( {...} cycle. However, in this scenario, you would need some state variables (e.g. lastDaddy) as well as a post-cycle operation. Even if such contraption is error-free, it’s rather unreadable for your coworkers. I tried a different approach. In java, it should work with any valid ResultSet implementation. For the simple example, it looks like:

Map<String, Collection<String>> result = new HashMap<>();
boolean hadNext =;

while (hadNext) {
    String group = rs.getString("daddy");
    Collection<String>; elements = new ArrayList<>();

    do {
    } while (hadNext = && 

    result.put(group, elements);

The main advantage of this approach is readability. Result set is only iterated in the inner cycle, so you need to initialize first: hadNext = The outer cycle contains the whole life cycle of daddy (a great win for readability). The inner cycle quite interesting: I hardly ever use the do-while cycle, but here it shines. The first child must be read before iterating the result set any further. The condition causes the inner cycle to stop both when the parent changes and when the result set ends.

In most scenarios, two levels of hierarchy are still one too many (separate queries are used instead). However, this approach can handle even multiple levels of hierarchy while staying readable. In this case, all the inner cycles use a do-while cycle, matching the whole parental line of an element. Only the innermost cycle iterates the result set.

On the January 15, we will have a pleasure to host Zdenek Nemec from Apiary as a main speaker at the first Technology Hour in 2015. Zdenek will be showing us how to model great APIs using REST architecture on a real-world sample of iPhone application. With that, Kyle Fuller will assist him.


As you might expect, he will show us how to use the tools provided by Apiary for this purpose, especially the platform-agnostic language for describing REST APIs called Blueprint. After the event, as usual, there will be a ton of food and drinks to support everyone in staying a bit longer and to enjoy free discussions on any topics you like.

If you are interested in the topic, or just want to hang out with smart people, you are more than welcomed to join us at Y Soft offices at Prague 4. More information and RSVP at Thank you very much for sharing on twitter, facebook or wherever you know like-minded people.

See you all there.