Why do I get ArrayIndexOutOfBoundsException in Java?

The ArrayIndexOutOfBoundsException exception is thrown to indicate that an array has been accessed with an illegal index. The index is either negative or greater than or equal to the size of the array.

Array with 10 elements

For example see the code snippet below:

String[] vowels = new String[]{"a", "i", "u", "e", "o"}
String vowel = vowels[10]; // throws the ArrayIndexOutOfBoundsException

Above we create a vowels array with five elements. This will make the array have indexes between 0..4. On the next line we tried to access the tenth element of the array which is illegal. This statement will cause the ArrayIndexOutOfBoundsException thrown.

We must understand that arrays in Java are zero indexed. The first element of the array will be at index 0 and the last element will be at index array-size - 1. So be careful with your array indexes when accessing array elements. For example if you have an array with 5 elements this mean that the index of the array is from 0 to 4.

If you are trying to iterate an array using for loop. Make sure the index start from 0 and execute the loop while the index is less than the length of the array, you can get the length of the array using the array length property. Let’s see the code snippet below:

for (int i = 0; i < vowels.length; i++) {
    String vowel = vowels[i];
    System.out.println("vowel = " + vowel);
}

Or if you don’t need the index you can simplify your code using the for-each or enhanced for-loop statement instead of the classic for loop statement as shown below:

for (String vowel : vowels) {
    System.out.println("vowel = " + vowel);
}

How to create a read-only MySQL user?

Introduction

There are times when you need to create a user only to have read-only access to a database. The user can view or read the data in the database, but they cannot make any changes to the data or the database structure.

Creating a New User Account

To create a read-only database user account for MySQL do the following steps:

  • First, login as a MySQL administrator from your terminal / command prompt using the following command:
mysql -u root -p
  • You’ll be prompted to enter the password. Type the password for the root account.
  • Create a new MySQL user account.
CREATE USER 'report'@'%' IDENTIFIED BY 'secret';

The % in the command above means that user report can be used to connect from any host. You can limit the access by defining the host from where the user can connect. Omitting this information will only allow the user to connect from the same machine.

  • Grant the SELECT privilege to user.
GRANT SELECT ON kodejava.* TO 'report'@'%';
  • Execute the following command to make the privilege changes saved and take effect.
FLUSH PRIVILEGES;
  • Type quit to exit from the MySQL shell.

Test the New User Account

  • Now we can try the newly created user account. Start by login with the new user account and provide the corresponding password.
mysql -u report -p
  • Try executing the DELETE command:
mysql> USE kodejava;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> DELETE FROM authors;
ERROR 1142 (42000): DELETE command denied to user 'report'@'localhost' for table 'authors'
mysql> UPDATE authors SET name = 'Wayan Saryada' WHERE id = 1;
ERROR 1142 (42000): UPDATE command denied to user 'report'@'localhost' for table 'authors'
mysql>

How do I define access modifiers in Lombok’s @Getter and @Setter annotations?

By default, when we use the Lombok’s @Getter and @Setter annotations the getters and setters will be created with public access modifier. We can however change the access modifier by setting the AccessLevel of the @Getter and @Setter annotations. The available choices for the access level are AccessLevel.PUBLIC, AccessLevel.PROTECTED, AccessLevel.PACKAGE, AccessLevel.PRIVATE. These enum values correspond to Java’s access modifier. While the AccessLevel.NONE will disable the getter and setter method generation.

package org.kodejava.lombok.support;

import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class Person {
    @Setter(AccessLevel.PROTECTED)
    private String firstName;

    private String lastName;
    private String gender;

    @Getter(AccessLevel.PRIVATE)
    private int age;
}

How we use the Person class show in the snippet below:

package org.kodejava.lombok;

import org.kodejava.lombok.support.Person;

public class PersonDemo {
    public static void main(String[] args) {
        Person person = new Person();
        person.setLastName("Bar");
        person.setGender("M");
        person.setAge(20);

        System.out.println(person.getFirstName());
        System.out.println(person.getLastName());
        System.out.println(person.getGender());
    }
}

If we try to see the generated class of the Person class we can run the following command to disassemble the class.

javap -p -cp . org.kodejava.lombok.support.Person

And we got the following output of the javap command. As we can see that the setFirstName() method have a protected access modifier and the getAge() method have a private access modifier. The other mutator and accessor method all set to public access modifier.

public class org.kodejava.lombok.support.Person {
    private java.lang.String firstName;
    private java.lang.String lastName;
    private java.lang.String gender;
    private int age;
    public org.kodejava.lombok.support.Person();
    public java.lang.String getFirstName();
    public java.lang.String getLastName();
    public java.lang.String getGender();
    public void setLastName(java.lang.String);
    public void setGender(java.lang.String);
    public void setAge(int);
    protected void setFirstName(java.lang.String);
    private int getAge();
}

Maven Dependencies

<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.28</version>
    </dependency>
</dependencies>

Maven Central

How do I generate getters and setters with Lombok?

The following code snippet show you how to use Project Lombok‘s @Getter and @Setter annotations to generate getters and setters method in your POJO (plain old java objects) classes. Using these annotations remove the need to manually implements the mutator and accessor methods. Although most IDE allows you to generate these methods, using Lombok makes your classes look cleaner, especially when you have a long list of fields.

Here is a simple User class with a handful fields. We will use the @Getter and @Setter annotations on the class level. This will generate the getters and setters method for any non-static fields in the class.

package org.kodejava.lombok.support;

import lombok.Getter;
import lombok.Setter;

import java.time.LocalDate;

@Getter
@Setter
public class User {
    private Long id;
    private String username;
    private String password;
    private LocalDate lastLogin;
    private boolean active;
}

Each fields in the class will have its corresponding getter and setter. For example the username field will have the getUsername() and setUsername() method. If the field type is boolean such as active it will generate the method setActive() and isActive() method.

Because the accessor and mutator already handled by Lombok, we can use the User class as if we manually implement the getters and setters method.

package org.kodejava.lombok;

import org.kodejava.lombok.support.User;

import java.time.LocalDate;

public class UserDemo {
    public static void main(String[] args) {
        User user = new User();
        user.setId(1L);
        user.setUsername("foo");
        user.setPassword("secret");
        user.setLastLogin(LocalDate.now());
        user.setActive(true);

        System.out.println(user.getId());
        System.out.println(user.getUsername());
        System.out.println(user.getPassword());
        System.out.println(user.getLastLogin());
        System.out.println(user.isActive());
    }
}

If for some reasons you want to disable the getter and setter on specific field, or you want the change the access level, you can use the AccessLevel enums value for the @Getter and @Setter annotations. For example in the code snippet below the username will have no getter and setter while the lastLogin getter and setter will have protected access modifier. The AccessLevel enums includes PUBLIC, MODULE, PROTECTED, PACKAGE, PRIVATE and NONE.

package org.kodejava.lombok.support;

import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;

import java.time.LocalDate;

@Getter
@Setter
public class User {
    private Long id;
    @Getter(AccessLevel.NONE)
    @Setter(AccessLevel.NONE)
    private String username;
    private String password;
    @Getter(AccessLevel.PROTECTED)
    @Setter(AccessLevel.PROTECTED)
    private LocalDate lastLogin;
    private boolean active;
}

Maven Dependencies

<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.28</version>
    </dependency>
</dependencies>

Maven Central

How do I write JSON string using JSON-Java (org.json) library?

The following code snippet show you how to create JSON string using JSON-Java library. Create an instance of JSONObject and use the put() method to create a key-value pair for the JSON string. The JSONArray object can be used to create an array of list of values to the JSON string, we also use the put() method to add value to the list.

The JSONObject.toString() method accept parameter called indentFactor, this set the indentation level of the generated string, which also make the JSON string generated easier to read and look prettier.

package org.kodejava.json;

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

public class WriteJSONString {
    public static void main(String[] args) {
        JSONObject object = new JSONObject();
        object.put("id", 1L);
        object.put("name", "Alice");
        object.put("age", 20);

        JSONArray courses = new JSONArray();
        courses.put("Engineering");
        courses.put("Finance");
        courses.put("Chemistry");

        object.put("courses", courses);

        String jsonString = object.toString(2);
        System.out.println(jsonString);
    }
}

The result of the code snippet above is:

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

Maven Dependencies

<dependencies>
    <dependency>
        <groupId>org.json</groupId>
        <artifactId>json</artifactId>
        <version>20240303</version>
    </dependency>
</dependencies>

Maven Central