Multi Language Java Desktop Applications

I don’t like to work with the large files of Resource Bundles when I write multi-language desktop applications with Java Swing or JavaFX. So I wanted to use a resource file for each module in my rich client applications. I’ve written an util class which has an enum set, please see below. Now I can use this I18n helper in every module.

I18n enum with application modules:

package com.cemikta.customersfx.util;

import java.text.MessageFormat;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;

 * Resource Bundle helper.
 * <p>
 * Each module has its own resource bundle file for i18n strings. Always read
 * default locale from <code>Locale.getDefault()</code>.
 * </p>
 * <pre>
 *      I18n.MODULE_NAME.getString("stringKey");
 *      I18n.MODULE_NAME.getString("stringKey", param);
 * </pre>
 * @see ResourceBundle
 * @author Cem Ikta
public enum I18n {


    private final static Logger logger = Logger.getLogger(I18n.class.getName());
    private static final String DEFAULT_LOCATION = "i18n.";
    private final ResourceBundle resourceBundle;

    I18n(String bundleFile) {
        resourceBundle = ResourceBundle.getBundle(DEFAULT_LOCATION + bundleFile);

     * Gets a string for the given key from resource bundle.
     * @param key the key for the desired string
     * @return the string for the given key
    public String getString(String key) {
        try {
            return resourceBundle.getString(key);
        } catch (MissingResourceException ex) {
            logger.log(Level.SEVERE, null, ex);
            return "err#";
     * Gets a string for the given key from resource bundle and formats 
     * with parameters.
     * @param key the key for the desired string
     * @param params parameters for message formats
     * @return the string for the given key
    public String getString(String key, Object... params) {
        try {
            return MessageFormat.format(resourceBundle.getString(key), params);            
        } catch (MissingResourceException ex) {
            logger.log(Level.SEVERE, null, ex);
            return "err#";


Here is a sample use of I18n helper:

// set default locale english  
Locale.setDefault(new Locale("en", "EN"));  
// set default locale for German  
// Locale.setDefault(new Locale("de", "DE"));  
AppView appView = new AppView();  

Do you need a working project with multi languages? I have implemented Customers Java Swing Application Demo with I18n helper. You can get full source code from BitBucket.


* Image credit: Designed by Freepik

Base Entity Class in JPA

In JPA entities there are repeated fields and methods. Don’t repeat yourself and write a base class with @MappedSuperclass.

Base entity common fields:

id: Table id column, auto increment. In entity model with @Id annotation.

version: Version column for Optimistic Lock has default ’0′ in table and managed from your database and EntityManager. In entity model with @Version annotation.

Common methods:

hashCode() and equals() very important. If you don’t implement the methods you get problems later.

toString(): Optional method, default I use class name and id. You can override this method in your entities.

package com.cemikta.entitydemo.model;


import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Version;

 * Base entity
 * @author Cem Ikta
public abstract class BaseEntity implements Serializable {

    private static final long serialVersionUID = 1L;

    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id", nullable = false, columnDefinition = "BIGINT UNSIGNED")
    protected Long id;

    @Column(name = "version")
    private Long version;

    public Long getId() {
        return id;

    public Long getVersion() {
        return version;

    public int hashCode() {
        int hash = 0;
        hash += (this.getId() != null ? this.getId().hashCode() : 0);

        return hash;

    public boolean equals(Object object) {
	if (this == object)
            return true;
        if (object == null)
            return false;
        if (getClass() != object.getClass())
            return false;

        BaseEntity other = (BaseEntity) object;
        if (this.getId() != other.getId() && (this.getId() == null || ! {
            return false;
        return true;

    public String toString() {
        return this.getClass().getName() + " [ID=" + id + "]";

Base entity audit fields:

It is sometimes important to know when and by whom the table data were saved. I save creation date, modification date and user informations in the table. I have String for user informations, I save only username without foreign key, then I have no relations with user table. With @PrePersist and @PreUpdate you don’t need to set the date manual every time. Set the user informations(createdBy and updatedBy) in your controllers/service but not in models! Business logic must always remain in the right place.

If you need more flexible auditing/versioning of your tables, history of changes, you can use Hibernate Envers.

package com.cemikta.entitydemo.model;

import java.util.Date;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.Size;

 * Base entity audit
 * @author Cem Ikta
public abstract class BaseEntityAudit extends BaseEntity {

    @Column(name = "created_at")
    private Date createdAt;

    @Size(max = 20)
    @Column(name = "created_by", length = 20)
    private String createdBy;

    @Column(name = "updated_at")
    private Date updatedAt;

    @Size(max = 20)
    @Column(name = "updated_by", length = 20)
    private String updatedBy;

    public Date getCreatedAt() {
            return createdAt;

    public void setCreatedAt(Date createdAt) {
            this.createdAt = createdAt;

    public String getCreatedBy() {
            return createdBy;

    public void setCreatedBy(String createdBy) {
            this.createdBy = createdBy;

    public Date getUpdatedAt() {
            return updatedAt;

    public void setUpdatedAt(Date updatedAt) {
            this.updatedAt = updatedAt;

    public String getUpdatedBy() {
            return updatedBy;

    public void setUpdatedBy(String updatedBy) {
            this.updatedBy = updatedBy;

     * Sets createdAt before insert
    public void setCreationDate() {
        this.createdAt = new Date();

     * Sets updatedAt before update
    public void setChangeDate() {
        this.updatedAt = new Date();



Sample usage of EntityBaseAudit:

If you use your table id columns with table name prefix e.g customer_id then use @AttributeOverride. Without table name prefix remove @AttributeOverride.

@Table(name = "customers")
@AttributeOverride(name = "id", column = @Column(name = "customer_id",
        nullable = false, columnDefinition = "BIGINT UNSIGNED"))
public class Customer extends BaseEntityAudit {

    // fields without id column ...

    public Customer() {

    // getter and setter ...



* Tree structure icon credit

Install JDK 8 on Ubuntu

Installing step by step Oracle JDK 8 on Ubuntu GNU/Linux:

Step 1: Download the Oracle JDK 8 tar file from here.

Step 2: Open the terminal and extract the tar file.

tar -xvzf jdk-8-linux-x64.tar.gz

Step 3: Create jvm folder in /usr/lib, if jvm folder not exist.

sudo mkdir /usr/lib/jvm

Step 4: Move extracted JDK 8 folder to this location.

sudo mv jdk1.8.0 /usr/lib/jvm/jdk1.8.0

Step 5: Install new Java source in system.

sudo update-alternatives --install /usr/bin/javac javac /usr/lib/jvm/jdk1.8.0/bin/javac 1
sudo update-alternatives --install /usr/bin/java java /usr/lib/jvm/jdk1.8.0/bin/java 1
sudo update-alternatives --install /usr/bin/javaws javaws /usr/lib/jvm/jdk1.8.0/bin/javaws 1

Step 6: Choose default Java.

sudo update-alternatives --config javac
sudo update-alternatives --config java
sudo update-alternatives --config javaws

Step 7: Test the Java version.

java -version

# java version "1.8.0"
# Java(TM) SE Runtime Environment (build 1.8.0-b132)
# Java HotSpot(TM) 64-Bit Server VM (build 25.0-b70, mixed mode)

Step 8: Verify the symlinks all point to the new Java location.

ls -la /etc/alternatives/java*

Step 9: Enable Java plugin for Mozilla Firefox (even for Chrome)

# for 64-Bit JDK
sudo ln -s /usr/lib/jvm/jdk1.8.0/jre/lib/amd64/ /usr/lib/mozilla/plugins
# for 32-Bit JDK
sudo ln -s /usr/lib/jvm/jdk1.8.0/jre/lib/i386/ /usr/lib/mozilla/plugins

Step 10: Some tools require JAVA_HOME variable. You can set JAVA_HOME variable on Ubuntu with following options (1. option recommended!)

  1. Option with /etc/environment:
    sudo gedit /etc/environment
    # add the following line, save and exit
    # Load the variables
    source /etc/environment
  2. Option with .bashrc: in your home directory
    sudo gedit .bashrc
    # add the following lines, save and exit
    export JAVA_HOME=/usr/lib/jvm/jdk1.8.0
    export PATH=$JAVA_HOME/bin:$PATH


Original post is from my old blog!

Practical Notes of RESTful API Design

Coding Style in RESTful:

JSON: JavaScript naming conventions: camelCase
Rest clients in Java: camelCase
Rest clients in Python and Ruby: snake_case

RESTful URL Mapping:

GET /customers  Retrieves a list of customers.
GET /customers/{id}  Retrieves a specific customer with id.
GET /customers/5

POST /customers  Creates a new customer.

PUT /customers/{id}  Updates customer with id.
PUT /customers/5

PATCH /customers/{id}  Partially updates customer with id.
PATCH /customers/5

DELETE /customers/{id}  Deletes customer with id.
DELETE /customers/5

RESTful URL Mapping with Relations:

GET /customers/{id}/orders  Retrieves list of orders for customer with id.
GET /customers/5/orders
GET /customers/{id}/orders/{id}  Retrieves order with id for customer with id.
GET /customers/5/orders/23

POST /customers/{id}/orders  Creates a new order in customer with id.
POST /customers/5/orders

PUT /customers/{id}/orders/{id}  Updates order with id for customer with id.
PUT /customers/5/orders/23

PATCH /customers/{id}/orders/{id}  Partially updates order with id for customer with id.
PATCH /customers/5/orders/23

DELETE /customers/{id}/orders/{id}  Deletes order with id for customer with id.
DELETE /customers/5/orders/23

RESTful URL Mapping with Parameters:


GET /customers?key=value  Retrieves list of customers with key value query parameter.
GET /customers?state=active  Here, state is a query parameter that implements a filter.


GET /customers?sort=value  Retrieves a list of customers with sort parameter.
GET /customers?sort=last_name

GET /customers?sort=value1, value2  Sort parameter with list of comma separated fields.
GET /customers?sort=last_name, created_at

GET /customers?sort=last_name&dir=DESC  Sorting with two parameters.


GET /customers/recently_registered  Simple query.
GET /customers?q=Berlin&state=active&sort=last_name&dir=DESC  Complex query with search, state, sort, dir parameters.


GET /customers?page=3&per_page=20  Paging with parameters.
GET /customers/search/name_starts_with?name=K&sort=name&dir=desc  Paging and sorting with parameters.


Original post is from my old blog!


* Image credit: Designed by Freepik

Customers Java Swing Application Demo

I have developed the Customers Java Swing Application Demo. This application may be useful for developers who want to use Flamingo, Substance and SwingX.

Technology stack:


Model View Controller (MVC) vs Model View Presenter (MVP):

The Customers Java Swing Application Demo is built on MVC design pattern like Java Swing. MVP is also popular for Desktop and RIA. Which is best, there are many discussions. Martin Fowler has written very good explanations for GUI Architectures. You may like to read.

Models and Services:

I have written entities with NamedQueries in JPA and Hibernate. The services are very simple with Generic AbstractService.

You can get full source code and project resources from Bitbucket!

Original post is from my old blog!


* Customers Java Swing Application images and icons credits: and


New Home

Hi everybody,

I have a new homepage for my blog posts. I will write more often about application development, project management, tutorials and book reviews. My old homepage is still available.

Have fun while reading.




* Photo: Hobbiton, New Zealand Copyright © Cem Ikta