How do I create JSONArray object?

A JSONArray object represent an ordered sequence of values. We use the put() method to add or replace values in the JSONArray object. The value can be of the following types: Boolean, JSONArray, JSONObject, Number, String or the JSONObject.NULL object.

Beside using the put() method we can also create and add data into JSONArray in the following ways:

  • Using constructor to create JSONArray from string wrapped in square bracket [], where the values are separated by comma. JSONException maybe thrown if the string is not a valid JSON string.
  • Creating JSONArray by passing an array as an argument to its constructor, for example an array of String[].
  • Using constructor to create JSONArray from a Collection, such as an ArrayList object.

The following example show you how to create JSONArray object.

package org.kodejava.json;

import org.json.JSONArray;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

public class CreateJSONArray {
    public static void main(String[] args) {
        // Create JSONArray and put some values
        JSONArray jsonArray = new JSONArray();
        jsonArray.put("Java");
        jsonArray.put("Kotlin");
        jsonArray.put("Go");
        System.out.println(jsonArray);

        // Create JSONArray from a string wrapped in bracket and
        // the values separated by comma. String value can be 
        // quoted with single quote.
        JSONArray colorArray = new JSONArray("[1, 'Apple', 2022-02-07]");
        System.out.println(colorArray);

        // Create JSONArray from an array of String.
        JSONArray stringArray =
                new JSONArray(new String[]{"January", "February", "March"});
        System.out.println(stringArray);

        // Create JSONArray by passing a List to its constructor
        List<String> list = new ArrayList<>();
        list.add("Red");
        list.add("Green");
        list.add("Blue");
        JSONArray listArray = new JSONArray(list);
        System.out.println(listArray);

        // Using for loop to get each value from the array
        for (int i = 0; i < listArray.length(); i++) {
            System.out.println("Color: " + listArray.get(i));
        }

        // Put JSONArray into a JSONObject.
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("colors", listArray);
        System.out.println(jsonObject);
    }
}

Running the code above produces the following result:

["Java","Kotlin","Go"]
[1,"Apple","2022-02-07"]
["January","February","March"]
["Red","Green","Blue"]
Color: Red
Color: Green
Color: Blue
{"colors":["Red","Green","Blue"]}

Maven Dependencies

<dependencies>
    <!-- https://search.maven.org/remotecontent?filepath=org/json/json/20211205/json-20211205.jar -->
    <dependency>
        <groupId>org.json</groupId>
        <artifactId>json</artifactId>
        <version>20211205</version>
        <type>bundle</type>
    </dependency>
</dependencies>

Maven Central

How do I read values from JSONObject?

A JSONObject is an unordered collection of key-value pairs. To read values from the JSONObject we can use the get(String key) and opt(String key) methods. These generic methods return an Object, which you can cast to a certain type.

There are also typed get and opt methods to read value in specific type such as getString(), getInt(), getDouble(), optString(), optFloat(), optBigInteger(), optBoolean(), optEnum(), etc. For more detail, you can check the JSONObject API documentation.

The get methods throws JSONException when the key is not found in the JSONObject, while the opt methods does not throw exception but return null, and we can also pass a default value argument that will be returned when the key is not found.

The code below give you a simple example to read values from JSONObject.

package org.kodejava.json;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class ReadJSONValue {
    public static void main(String[] args) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("id", 1L);
        jsonObject.put("name", "Alice");
        jsonObject.put("age", 20);
        jsonObject.put("courses",
                new JSONArray(new String[] {"Engineering", "Finance"}));
        System.out.println(jsonObject);

        // Using get() and opt() methods we need to cast
        // the returned value to the type its store.
        long id1 = (long) jsonObject.get("id");
        String name1 = (String) jsonObject.get("name");
        int age1 = (int) jsonObject.get("age");
        JSONArray courses1 = (JSONArray) jsonObject.get("courses");

        // This will throw exception because JSONObject
        // does not have the address key in it.
        String address1;
        try {
            address1 = (String) jsonObject.get("address");
        } catch (JSONException e) {
            e.printStackTrace();
        }

        // Using opt() method to read address, does not throw
        // exception
        address1 = (String) jsonObject.opt("address");

        System.out.println("id1      = " + id1);
        System.out.println("name1    = " + name1);
        System.out.println("age1     = " + age1);
        System.out.println("address1 = " + address1);
        System.out.println("courses1 = " + courses1);
        System.out.println();

        // Using data type specific get() and opt() methods.
        // We don't have to cast the return from the getXXX()
        // and optXXX() methods.
        long id2 = jsonObject.getLong("id");
        String name2 = jsonObject.getString("name");
        int age2 = jsonObject.optInt("age");

        // Using optString() to read address and provide default
        // value when address is not found.
        String address2 = jsonObject.optString("address", "No Address");
        JSONArray courses2 = jsonObject.optJSONArray("courses");

        System.out.println("id2      = " + id2);
        System.out.println("name2    = " + name2);
        System.out.println("age2     = " + age2);
        System.out.println("address2 = " + address2);
        System.out.println("courses2 = " + courses2);
    }
}

Running this code produces the following results:

{"courses":["Engineering","Finance"],"name":"Alice","id":1,"age":20}
org.json.JSONException: JSONObject["address"] not found.
    at org.json.JSONObject.get(JSONObject.java:580)
    at org.kodejava.json.ReadJSONValue.main(ReadJSONValue.java:28)

id1      = 1
name1    = Alice
age1     = 20
address1 = null
courses1 = ["Engineering","Finance"]

id2      = 1
name2    = Alice
age2     = 20
address2 = No Address
courses2 = ["Engineering","Finance"]

Maven Dependencies

<dependencies>
    <!-- https://search.maven.org/remotecontent?filepath=org/json/json/20211205/json-20211205.jar -->
    <dependency>
        <groupId>org.json</groupId>
        <artifactId>json</artifactId>
        <version>20211205</version>
        <type>bundle</type>
    </dependency>
</dependencies>

Maven Central

How do I convert Java Object to JSON?

To convert Java objects or POJOs (Plain Old Java Objects) to JSON we can use one of JSONObject constructor that takes an object as its argument. In the following example we will convert Student POJO into JSON string. Student class must provide the getter methods, JSONObject creates JSON string by calling these methods.

In this code snippet we do as follows:

  • Creates Student object and set its properties using the setter methods.
  • Create JSONObject called object and use the Student object as argument to its constructor.
  • JSONObject use getter methods to produces JSON string.
  • Call object.toString() method to get the JSON string.
package org.kodejava.json;

import org.json.JSONObject;
import org.kodejava.json.support.Student;

import java.util.Arrays;

public class PojoToJSON {
    public static void main(String[] args) {
        Student student = new Student();
        student.setId(1L);
        student.setName("Alice");
        student.setAge(20);
        student.setCourses(Arrays.asList("Engineering", "Finance", "Chemistry"));

        JSONObject object = new JSONObject(student);
        String json = object.toString();
        System.out.println(json);
    }
}

Running this code produces the following result:

{"courses":["Engineering","Finance","Chemistry"],"name":"Alice","id":1,"age":20}

The Student class use in the code above:

package org.kodejava.json.support;

import java.util.List;

public class Student {
    private Long id;
    private String name;
    private int age;
    private List<String> courses;

    // Getters and Setters removed for simplicity
}

Maven Dependencies

<dependencies>
    <!-- https://search.maven.org/remotecontent?filepath=org/json/json/20211205/json-20211205.jar -->
    <dependency>
        <groupId>org.json</groupId>
        <artifactId>json</artifactId>
        <version>20211205</version>
        <type>bundle</type>
    </dependency>
</dependencies>

Maven Central

How do I create JSON from a Map?

In the previous example we use JSONObject to directly put key-value pairs to create JSON string, using the various put() methods. Instead of doing that, we can also create JSON from a Map object. We create a Map with some key-value pairs in it, and pass it as an argument when instantiating a JSONObject.

These are the steps for creating JSON from a Map:

  • Create a Map object using a HashMap class.
  • Put some key-value pairs into the map object.
  • Create a JSONObject and pass the map as argument to its constructor.
  • Print the JSONObject, we call object.toString() to get the JSON string.

Let’s try the following code snippet.

package org.kodejava.json;

import org.json.JSONObject;

import java.util.HashMap;
import java.util.Map;

public class JSONFromMap {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("id", "1");
        map.put("name", "Alice");
        map.put("age", "20");

        JSONObject object = new JSONObject(map);
        System.out.println(object);
    }
}

Running this code produces the following output:

{"name":"Alice","age":"20","id":"1"}

Maven Dependencies

<dependencies>
    <!-- https://search.maven.org/remotecontent?filepath=org/json/json/20211205/json-20211205.jar -->
    <dependency>
        <groupId>org.json</groupId>
        <artifactId>json</artifactId>
        <version>20211205</version>
        <type>bundle</type>
    </dependency>
</dependencies>

Maven Central

Filtering JList Component Models

Filter items in a long list are often accomplished using the JTextField component. As the user inputs into the JTextField component, the set of items shown in the list is narrowed to just those things that correspond to the input received from the user.

It is necessary to utilize two elements to implement this function of the JList component, one of which is a model that filters a set of elements based on some text. The other executes the filter method when the user enters text.

Implementing the input field is a simpler job, so let’s start with it in our review of the implementation process. The JTextField component model is a document used with a Swing set of components. It is necessary to implement the DocumentListener interface in the model in order to monitor input to a Document. Text input, updating, and deletion are tracked using three methods defined below:

  • public void insertUpdate (DocumentEvent event)
  • public void changedUpdate (DocumentEvent event)
  • public void removeUpdate (DocumentEvent event)

When the model attributes are updated, the changedUpdate() method is used to update the model. It is possible that it will not be realized. In order to avoid duplicating filtering actions across all three methods, the generic method generated in the custom model is simply called by the other two. A detailed explanation of the JTextField component, which is used for filtering in the JList component, may be found in the following section:

JTextField input = new JTextField(); 
String lastSearch = ""; 

DocumentListener listener = new DocumentListener() { 
    public void insertUpdate(DocumentEvent event) { 
        Document doc = event.getDocument(); 
        lastSearch = doc.getText(0, doc.getLength()); 
        ((FilteringModel)getModel()).filter(lastSearch); 
    } 

    public void removeUpdate(DocumentEvent event) { 
        Document doc = event.getDocument(); 
        lastSearch = doc.getText(0, doc.getLength()); 
        ((FilteringModel)getModel()).filter(lastSearch); 
    }

    public void changedUpdate(DocumentEvent event) {
    } 
}; 

input.getDocument().addDocumentListener(listener);

In order to avoid being restricted to just using the JTextField component that was generated using the JList, the installJTextField() method is used, which attaches the event listener to the component that was built using the JList in the first place. In addition, a mechanism is provided to eliminate this match. Through the usage of these methods, the user of a filtering JList may choose to use their own JTextField in place of the default one.

public void installJTextField(JTextField input) { 
    input.getDocument().addDocumentListener(listener); 
} 

public void unnstallJTextField(JTextField input) { 
    input.getDocument().removeDocumentListener(listener); 
}

After that, the filtering model is taken into consideration. This case implements the filter() function, which is invoked by methods that implement the DocumentListener interface, as seen below. To put this strategy into action, you’ll need to have two lists of objects on hand: a source list and a filtered list of items. Because you are inheriting from the AbstractListModel class, you must implement some of the methods listed below in your code:

  • Constructor
  • Method for adding items to the model is being implemented in this project.
  • getElementAt() is used to get an element.
  • getSize() is used to retrieve sizes.
  • The constructor produces two instances of the List objects. The type of objects that are stored as List elements does not matter. Therefore List objects are generated to carry items of the following types:
List<Object> list; 
List<Object> filteredList; 

public FilteringModel() { 
    list = new ArrayList<>(); 
    filteredList = new ArrayList<>(); 
}

Model elements are added by adding them to the original model and then filtering the resulting model with the previously added elements. Optimization of this approach may be achieved by using a method to filter a single element when it is added; however, in this implementation, the filter() function is invoked when an element is added, which is also used to filter the whole list. (It should be noted that the event implementation in the DocumentListener also invokes the filter() method.) As a result, even when only one item is added to the list, the whole list is filtered, with each item that matches the search parameters being added to the filtered list.

public void addElement(Object element) { 
    list.add(element); 
    filter(); 
}

The size of the returned model is the same as the size of the filtered list, but not the same as the original:

public int getSize() { 
    return filteredList.size(); 
}

Similar to the technique for obtaining the size of a model, the method for obtaining an item from a list returns elements from the filtered list rather than the original list. In order to avoid having to go through the complete list, it has been implemented as follows:

public Object getElementAt(int index) { 
    Object returnValue; 
    if (index < filteredList.size()) { 
        returnValue = filteredList.get(index); 
    } else { 
        returnValue = null;
    } 
    return returnValue; 
}

Finally, the filter() method is responsible for most of the work. Because you have no way of knowing whether the new search string will broaden or limit the set of items, the quickest and most straightforward solution is to remove the whole filtered list and replace it with items that fit your search criteria from the original list. A match may be discovered at the beginning of a line as well as at any point throughout it. An example of searching for the letter “A” is shown below. This function enables you to locate items in a string that begin with the capital letter “A” or contain the letter “A” at any point in the string.

void filter(String search) {
    filteredList.clear();
    for (Object element: list) {
        if (element.toString().contains(search)) {
            filteredList.add(element); 
        } 
    } 
    fireContentsChanged(this, 0, getSize()); 
}

It is important to note that the search in this approach is case-sensitive. You may alter the method to implement a case-insensitive search and start the search at the beginning of the string.

After you have added entries to the filtered list, you may also sort the results. This operation requires your familiarity with the model’s contents. The function toString() is currently used by search, which does not indicate that it may include elements of a suitable type that can also be sorted when it is performed.

Here is a full implementation of the JList filter element with an inner class ListModel, as seen in the accompanying code sample. This class implements the DocumentListener interface, which the text component uses to listen for new documents. Although the addition of this class may seem needless at first look, given that filtering is only done for this model, the specification of behavior in this implementation is the most accurate.

package org.kodejava.swing;

import javax.swing.AbstractListModel;
import javax.swing.JList;
import javax.swing.JTextField;
import javax.swing.ListModel;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import java.util.ArrayList;
import java.util.List;

public class FilteringJList extends JList<Object> {
    private JTextField input;

    public FilteringJList() {
        setModel(new FilteringModel());
    }

    public void installJTextField(JTextField input) {
        if (input != null) {
            this.input = input;
            FilteringModel model = (FilteringModel) getModel();
            input.getDocument().addDocumentListener(model);
        }
    }

    public void uninstallJTextField(JTextField input) {
        if (input != null) {
            FilteringModel model = (FilteringModel) getModel();
            input.getDocument().removeDocumentListener(model);
            this.input = null;
        }
    }

    public void setModel(ListModel<Object> model) {
        if (!(model instanceof FilteringModel)) {
            throw new IllegalArgumentException();
        } else {
            super.setModel(model);
        }
    }

    public void addElement(Object element) {
        ((FilteringModel) getModel()).addElement(element);
    }

    private static class FilteringModel extends AbstractListModel<Object> implements DocumentListener {
        List<Object> list;
        List<Object> filteredList;
        String lastFilter = "";

        public FilteringModel() {
            list = new ArrayList<>();
            filteredList = new ArrayList<>();
        }

        public void addElement(Object element) {
            list.add(element);
            filter(lastFilter);
        }

        public int getSize() {
            return filteredList.size();
        }

        public Object getElementAt(int index) {
            Object returnValue;
            if (index < filteredList.size()) {
                returnValue = filteredList.get(index);
            } else {
                returnValue = null;
            }
            return returnValue;
        }

        void filter(String search) {
            filteredList.clear();
            for (Object element : list) {
                if (element.toString().contains(search)) {
                    filteredList.add(element);
                }
            }
            fireContentsChanged(this, 0, getSize());
        }

        public void insertUpdate(DocumentEvent event) {
            Document doc = event.getDocument();
            try {
                lastFilter = doc.getText(0, doc.getLength());
                filter(lastFilter);
            } catch (BadLocationException ble) {
                System.err.println("Bad location: " + ble);
            }
        }

        public void removeUpdate(DocumentEvent event) {
            Document doc = event.getDocument();
            try {
                lastFilter = doc.getText(0, doc.getLength());
                filter(lastFilter);
            } catch (BadLocationException ble) {
                System.err.println("Bad location: " + ble);
            }
        }

        public void changedUpdate(DocumentEvent event) {
        }
    }
}

It is now necessary to develop a test program. The following six lines will be crucial in the event. They build a JList component, attach it to the JScrollPane component, and then attach a text box to it as seen in the code:

FilteringJList list = new FilteringJList();
JScrollPane pane=new JScrollPane(list);
frame.add(pane,BorderLayout.CENTER);
JTextField text=new JTextField();list.installJTextField(text);
frame.add(text,BorderLayout.NORTH);

To the model, new components are introduced in the program’s primary body. The model shown below includes a list of Christmas gifts, the names of Santa’s reindeer, the names of London Underground lines, and the letters of the Greek alphabet.

package org.kodejava.swing;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import java.awt.BorderLayout;
import java.awt.EventQueue;

public class JListFiltersDemo {
    public static void main(String[] args) {
        Runnable runner = () -> {
            JFrame frame = new JFrame("Filtering List");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            FilteringJList list = new FilteringJList();
            JScrollPane pane = new JScrollPane(list);
            frame.add(pane, BorderLayout.CENTER);
            JTextField text = new JTextField();
            list.installJTextField(text);
            frame.add(text, BorderLayout.NORTH);
            String[] elements = {
                    "Partridge in a pear tree", "Turtle Doves", "French Hens",
                    "Calling Birds", "Golden Rings", "Geese-a-laying",
                    "Swans-a-swimming", "Maids-a-milking", "Ladies dancing",
                    "Lords-a-leaping", "Pipers piping", "Drummers drumming",
                    "Dasher", "Dancer", "Prancer", "Vixen", "Comet", "Cupid",
                    "Donner", "Blitzen", "Rudolf", "Bakerloo", "Center",
                    "Circle", "District", "East London", "Hammersmith and City",
                    "Jubilee", "Metropolitan", "Northern", "Piccadilly Royal",
                    "Victoria", "Waterloo and City", "Alpha", "Beta", "Gamma",
                    "Delta", "Epsilon", "Zeta", "Eta", "Theta", "Iota", "Kappa",
                    "Lambda", "Mu", "Nu", "Xi", "Omicron", "Pi", "Rho", "Sigma",
                    "Tau", "Upsilon", "Phi", "Chi", "Psi", "Omega"};
            for (String element : elements) {
                list.addElement(element);
            }
            frame.setSize(500, 500);
            frame.setVisible(true);
        };
        EventQueue.invokeLater(runner);
    }
}
Filtering JList Component Models Demo

Filtering JList Component Models Demo

Because this filtering strategy is based on the JList component and its accompanying JTextField component, it will operate successfully if your list’s entries are appropriately displayed when you use the function toString(). Creating a Filter interface that is provided to the model when filtering operations are performed might be useful for doing more complicated filtering tasks.

In this example, the only item that is not addressed is the process of selection. By default, when the contents of the model list change, the JList does not update the selection of the model list. Filtering may be used to either retain the chosen item or emphasize the first item in the list, depending on the desired behavior.

Even though the original JList component does not explicitly offer the functionality, there are techniques to implement filtering. Overriding the getNextMatch() function allows you to alter the default behavior if you so want.

How do I connect to ssh server using JSch?

JSch is a pure Java implementation of SSH-2. SSH (Secure Shell) is a cryptographic network protocol for operating network services securely over an unsecured network. The following code snippet shows you how to open a connection to an ssh server.

package org.kodejava.jsch;

import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;

public class SSHConnect {
    public static void main(String[] args) {
        try {
            JSch jSch = new JSch();

            Session session = jSch.getSession("admin", "192.168.56.201", 22);
            session.setPassword("s3cret##");
            session.setConfig("StrictHostKeyChecking", "no");
            session.connect();

            System.out.println("Connected...");
        } catch (JSchException e) {
            e.printStackTrace();
        }
    }
}

Maven Dependencies

<dependencies>
    <!--https://search.maven.org/remotecontent?filepath=com/jcraft/jsch/0.1.55/jsch-0.1.55.jar-->
    <dependency>
        <groupId>com.jcraft</groupId>
        <artifactId>jsch</artifactId>
        <version>0.1.55</version>
    </dependency>
</dependencies>

Maven Central

How do I mail merge Word document in Java?

The following example will show you how to use the E-iceblue‘s free Spire.Doc for Java to perform mail merge operations on MS Word documents.

Create Maven Project and Add Dependencies

Create a maven project and add the following dependencies and repositories in your project’s pom.xml file.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    ...
    ...

    <dependencies>
        <dependency>
            <groupId>e-iceblue</groupId>
            <artifactId>spire.doc.free</artifactId>
            <version>3.9.0</version>
        </dependency>
    </dependencies>

    <repositories>
        <repository>
            <id>com.e-iceblue</id>
            <name>e-iceblue</name>
            <url>http://repo.e-iceblue.com/nexus/content/groups/public/</url>
        </repository>
    </repositories>
</project>

Create Mail Merge Template in Microsoft Word

  • Create a new Word document.
  • Place your cursor where you want to add a merge field.

MS Word Mail Merge Template

  • Click the Insert menu, Quick Parts, Fields…
  • In the Field names select MergeField and enter the field name and press OK.

Merge Field

  • To create merge field for image you need to prefix the field name with Image:
  • When finished save the document.

The Mail Merge Code Snippet

The code snippet reads the mail merge template from a file called Receipt.docx. For the image we use a duke.png. Both of these files must be placed in the /src/main/resources directory in your maven project so that the code can read it.

package org.kodejava.example.spire;

import com.spire.doc.Document;
import com.spire.doc.FileFormat;
import com.spire.doc.reporting.MergeImageFieldEventArgs;
import com.spire.doc.reporting.MergeImageFieldEventHandler;

import java.awt.Dimension;
import java.io.FileOutputStream;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class MailMergeExample {
    public static final Locale LOCALE = new Locale("id", "ID");
    public static final DateFormat DATE_FORMAT = new SimpleDateFormat("dd-MMMM-yyyy", LOCALE);
    public static final NumberFormat NUMBER_FORMAT = NumberFormat.getCurrencyInstance(LOCALE);

    public static void main(String[] args) {
        String[] fieldNames = new String[]{
                "academicYear",
                "registrationNumber",
                "fullName",
                "gender",
                "telephone",
                "address",
                "paymentAmount",
                "inWords",
                "paymentDate",
                "receivedBy",
                "picture"
        };
        String[] fieldValues = new String[]{
                "2021/2022",
                "0001/REG/2021",
                "Foo Bar",
                "M",
                "081234567890",
                "Sudirman Street 100",
                NUMBER_FORMAT.format(1575000),
                "One Million Five Hundred Seventy Five Thousand",
                DATE_FORMAT.format(new Date()),
                "John Doe",
                "/duke.png"
        };

        try {
            Document document = new Document();
            document.loadFromStream(MailMergeExample.class.getResourceAsStream("/Receipt.docx"), FileFormat.Auto);
            document.getMailMerge().MergeImageField = new MergeImageFieldEventHandler() {
                @Override
                public void invoke(Object o, MergeImageFieldEventArgs field) {
                    field.setPictureSize(new Dimension(66, 88));

                    String path = field.getImageFileName();
                    if (path != null && !path.isEmpty()) {
                        try {
                            field.setImage(MailMergeExample.class.getResourceAsStream(path));
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            };
            document.getMailMerge().execute(fieldNames, fieldValues);

            String fileName = "Receipt.pdf";
            FileOutputStream fos = new FileOutputStream(fileName);
            document.saveToStream(fos, FileFormat.PDF);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Running the code will create a file called Receipt.pdf with the content as shown in the image below.

Mail Merge Result Document

Java Performance Tuning Books for Students To Read

Java development requires more than just experience. Learning from the experiences of other people is an invaluable habit that will propel your programming career to another level.

Photo by Markus Spiske from Pexels

Luckily for Java lovers, some developers have offered their best insights on Java programming in books. Here are the top Java performance books that will enlighten your craft.

Java Performance: The Definitive Guide



These 400 pages will transform your mentality as a Java engineer. It focuses on approaches that form the foundation of a successful project. Some concepts addressed by Scotts Oaks include response time, throughput, and micro-benchmarking. Other areas covered in detail include memory optimization, multi-thread concept, and garbage collection analysis. You will admit that these are the pivotal elements of any programming exercise. Learning from this Java guru offers the best insights into one of the most promising programming languages.

Java Performance



The book is co-authored by Binu John and Charlie Hunt. It provides some of the most comprehensive views of performance tuning tools and JVM. It is unique because the author has focused on Oracle products, helping developers to understand this area in depth. Among the areas covered include performance tuning, performance benchmarking, and profiling. The book featured more text and less code. The technique helps you to use imagination and get into an intense understanding of coding.

Java Performance Tuning



Jack Shirazi demonstrates his mastery of Java performance by including his life experiences in the process of development. He has also provided excellent demonstrations of real-life projects. The tips mentioned in the book will also help developers kick-start their projects. For beginners, this is a book that will outline the expected journey, especially from seasoned programmers who have walked the road. Some areas given prominence include exceptions, I/O, and object creation. It is an eye-opener for any Java lover.

Systems Performance: Enterprise and the Cloud



Brendan Gregg is a certified performance architect for Java. Brendan has given a general view of performance as opposed to specific Java issues. For engineers, this is the kind of material you would want for your upcoming project because it does not restrict your thinking. It goes into incredible depth using very simple language. This makes the book easy to understand.

Books on Java programming are an eye-opener for amateurs and seasoned developers alike. They provide a chance to learn from the mistakes and successes of other people. You have an invaluable start to your programming journey.

How do I format EditText for currency input in Android?

The following Android code snippet shows you how to customize the input value format of an EditText component for accepting currency number. To format the input value we will create a text watcher class called MoneyTextWatcher, this class implements of the android.text.TextWatcher interface. In the MoneyTextWatcher class we implement the afterTextChanged(EditText s) method, in this method the currency formatting takes place.

To apply this text watcher class we call the the addTextChangedListener() method of the EditText object of the currency input and pass an instance of MoneyTextWatcher. Below is the working example of the activity class and the text watcher.

package org.kodejava.android;

import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;

import java.math.BigDecimal;

public class MainActivity extends AppCompatActivity {
    private EditText editText;
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        editText = findViewById(R.id.editText);
        editText.addTextChangedListener(new MoneyTextWatcher(editText));

        textView = findViewById(R.id.textView);
    }

    public void doGetValue(View view) {
        BigDecimal value = MoneyTextWatcher.parseCurrencyValue(editText.getText().toString());
        textView.setText(String.valueOf(value));
    }
}

When the EditText input is changed the afterTextChanged() method of the text watcher will be called. In this method we’ll take the input text and format the input value with currency symbol and a number, this is done by the NumberFormat.getCurrencyInstance() object. The static helper method parseCurrencyValue() will get the number part of the EditText by removing the currency symbol and return the input number.

package org.kodejava.android;

import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.widget.EditText;

import java.lang.ref.WeakReference;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.util.Locale;
import java.util.Objects;

public class MoneyTextWatcher implements TextWatcher {
    public static final NumberFormat numberFormat = NumberFormat.getCurrencyInstance(new Locale("id", "ID"));
    private final WeakReference<EditText> editTextWeakReference;

    public MoneyTextWatcher(EditText editText) {
        editTextWeakReference = new WeakReference<>(editText);
        numberFormat.setMaximumFractionDigits(0);
        numberFormat.setRoundingMode(RoundingMode.FLOOR);
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
    }

    @Override
    public void afterTextChanged(Editable s) {
        EditText editText = editTextWeakReference.get();
        if (editText == null || editText.getText().toString().equals("")) {
            return;
        }
        editText.removeTextChangedListener(this);

        BigDecimal parsed = parseCurrencyValue(editText.getText().toString());
        String formatted = numberFormat.format(parsed);

        editText.setText(formatted);
        editText.setSelection(formatted.length());
        editText.addTextChangedListener(this);
    }

    public static BigDecimal parseCurrencyValue(String value) {
        try {
            String replaceRegex = String.format("[%s,.\\s]", Objects.requireNonNull(numberFormat.getCurrency()).getDisplayName());
            String currencyValue = value.replaceAll(replaceRegex, "");
            return new BigDecimal(currencyValue);
        } catch (Exception e) {
            Log.e("MyApp", e.getMessage(), e);
        }
        return BigDecimal.ZERO;
    }
}

The following animation is the result of our code snippet above.

Currency Format EditText Demo

Currency Format EditText Demo

How do I get Android Device ID or IMEI?

The following code snippets shows you how to get a Device ID of an Android phone. To be able to read the Device ID you need to update the AndroidManifest.xml file and add the READ_PHONE_STATE permission.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="org.kodejava.android">

    <uses-permission android:name="android.permission.READ_PHONE_STATE" />

    ...
    ...
</manifest>
package org.kodejava.android;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

public class MainActivity extends AppCompatActivity {

    private static final int PERMISSIONS_READ_PHONE_STATE = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_PHONE_STATE}, PERMISSIONS_READ_PHONE_STATE);
        }

        String deviceId = null;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            deviceId = Settings.Secure.getString(getApplicationContext().getContentResolver(), Settings.Secure.ANDROID_ID);
        } else {
            TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
            if (telephonyManager.getImei() != null) {
                deviceId = telephonyManager.getImei();
            } else if (telephonyManager.getMeid() != null) {
                deviceId = telephonyManager.getMeid();
            }
        }

        Log.d("MyApp", "Device ID: " + deviceId);
    }
}