Dependency Scope for Lombok

Lombok is a popular Java library that simplifies development by automating boilerplate code generation.

Lombok is only required during compile time, not runtime. If you don’t specify the correct scope, Lombok might be included in your runtime environment.

To avoid that, we use the “provided” scope when including Lombok in your pom.xml file. This scope indicates that the dependency is required for compilation but not for runtime. By specifying “provided”, you ensure that Lombok is only used during compilation and not packaged in your final artifact.

<dependencies>
	<dependency>
		<groupId>org.projectlombok</groupId>
		<artifactId>lombok</artifactId>
		<version>1.18.32</version>
		<scope>provided</scope>
	</dependency>
</dependencies>

Reference:

For more information on setting up Lombok with Maven, refer to the official Lombok documentation: https://projectlombok.org/setup/maven

Tunneling HTTP Verbs in REST API

If you have a REST API that can only support GET and POST methods but you need to incorporate DELETE or PATCH functionality, you can use HTTP tunneling as a solution.

HTTP tunneling allows you to “tunnel” or encapsulate the DELETE request within a GET or POST request. By doing so, you can work around the limitations of your API and still achieve the desired DELETE functionality.

To tunnel any HTTP request through a POST, you can send a POST request and include an additional header called “X-HTTP-Method-Override” with the desired HTTP method you want to invoke. This special header instructs the server to treat the request as the specified method rather than a POST.

For example, if you want to delete an order using an orderId but if the DELETE verb is blocked, then you can use the POST method and include X-HTTP-Method-Override as DELETE.
Upon seeing this header, the server will invoke the DELETE method to delete the given orderId.

POST /orders/{orderId}
Host: mywebsite.com
X-HTTP-Method-Override: DELETE

Reference: https://learn.microsoft.com/en-us/onedrive/developer/rest-api/concepts/http-verb-tunneling?view=odsp-graph-online

How to fix Lombok cannot find symbol issue

After utilizing the Lombok Builder annotation in one of my model classes, I encountered an issue where the builder method could not be resolved when attempting to use it.

I encountered the following error:

To resolve the issue of Maven being unable to find symbols when accessing Lombok annotated methods, it is necessary to explicitly configure the annotationProcessorPaths in the maven-compiler-plugin.

I have added the below configuration to the pom.xml to fix the issue.

cannot find symbol
[ERROR] symbol: method builder()
[ERROR] location: class Person
 <build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>

Asciidoc – Writing Technical Documentation

AsciiDoc is a plain text markup language for writing technical documentation.

As an alternative to Markdown, AsciiDoc offers additional features and capabilities specifically designed for technical writers and documentation needs.

Unlike Markdown, which focuses on simplicity and ease of use, AsciiDoc provides a more robust and flexible syntax. It supports a wide range of formatting options, including headings, lists, tables, code blocks, and more. This versatility allows technical writers to create complex and structured documentation with ease.

You can refer to this site for more information about Asciidoc: https://asciidoc.org/

In this post, I’m going to show how you can write a simple document that can be converted to various formats.

Before doing that, please install https://asciidoctor.org/ which is a fast text processor and publishing toolchain for converting AsciiDoc to HTML5, DocBook, and more.

You can refer to this page to learn about the various options used when running the asciidoctor command: https://docs.asciidoctor.org/asciidoctor/latest/cli/man1/asciidoctor/

Create a README.md file with the following content:

Doc Writer <doc@example.com>

An introduction to http://asciidoc.org[AsciiDoc].

== First Section

* item 1
* item 2

[source,ruby]
puts "Hello, World!"

The next step is to run the following command to convert the above README file into an HTML format:

asciidoctor -b html5 README.md

Below is the sample HTML file generated by the Asciidoctor

If you want to convert the above file to DocBook, then run the following command:

asciidoctor -b docbook5 README.md

The above will create a README.xml file in the same location. Please refer to the following code block to know the generated README.xml

<?xml version="1.0" encoding="UTF-8"?>
<?asciidoc-toc?>
<?asciidoc-numbered?>
<article xmlns="http://docbook.org/ns/docbook" xmlns:xl="http://www.w3.org/1999/xlink" version="5.0" xml:lang="en">
<info>
<title>Hello, AsciiDoc!</title>
<date>2023-11-06</date>
<author>
<personname>
<firstname>Doc</firstname>
<surname>Writer</surname>
</personname>
<email>doc@example.com</email>
</author>
<authorinitials>DW</authorinitials>
</info>
<simpara>An introduction to <link xl:href="http://asciidoc.org">AsciiDoc</link>.</simpara>
<section xml:id="_first_section">
<title>First Section</title>
<itemizedlist>
<listitem>
<simpara>item 1</simpara>
</listitem>
<listitem>
<simpara>item 2</simpara>
</listitem>
</itemizedlist>
<programlisting language="ruby" linenumbering="unnumbered">puts "Hello, World!"</programlisting>
</section>
</article>

Lombok Sneakythrows Annotation

Lombok Sneakythrows Annotation is used to throw checked exceptions from a method without actually declaring them in the method declaration.

In this post, I’m going to show you can use that annotation.

Include the below dependency in your maven pom.xml file. Refer to this page to get the latest Lombok dependency (https://search.maven.org/artifact/org.projectlombok/lombok)

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.24</version>
</dependency>

In the below example, We have a method called “validateName” and it’s used to validate the given argument and if it’s null or empty, then it throws an InvalidNameException exception. Because of the SneakyThrows annotation, the actual exception is not required to be declared in the method declaration. Actually, Lombok does not hide this exception but it fakes out the compiler.


import lombok.SneakyThrows;

import java.util.Scanner;

/**
 * @SneakyThrows can be used to sneakily throw checked exceptions without actually declaring this in your method's throws clause.
 * The code generated by lombok will not ignore, wrap, replace, or otherwise modify the thrown checked exception; it simply fakes out the compiler
 */

public class SneakyThrowExample {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("Enter Name: ");

        String name = scanner.nextLine();
        validateName(name);
        System.out.println("Hello " + name);
    }

    @SneakyThrows
    private static void validateName(String str) {
        if (str == null || str.isBlank()) throw new InvalidNameException("name is either null or blank");
    }

    static class InvalidNameException extends Exception {
        public InvalidNameException(String message) {
            super(message);
        }
    }
}
Enter Name: 


Exception in thread "main" SneakyThrowExample$InvalidNameException: name is either null or blank
	at SneakyThrowExample.validateName(SneakyThrowExample.java:22)
	at SneakyThrowExample.main(SneakyThrowExample.java:16)

Scala Nested Methods

Scala supports Nested methods. In this page, I’m going to provide an example of the nested methods.

Refer to the example code. As you can see, we have a method called “operation” which takes 3 input arguments. The first two arguments are operands and the last argument is the actual operation type.

Inside this method, we have defined 3 nested methods and each can do a particular operation. Based on the operation type, the right method would be invoked.

def operation(a: Int, b: Int, operationType: String): Int = {
  def add(a: Int, b: Int): Int = {
    a + b
  }

  def subtract(a: Int, b: Int): Int = {
    a - b
  }

  def multiply(a: Int, b: Int): Int = {
    a * b
  }

  if(operationType == "add"){
    add(a, b)
  } else if(operationType == "subtract"){
    subtract(a, b)
  } else if(operationType == "multiply") {
    multiply(a, b)
  } else {
    println(s"operationType: ${operationType} is not supported")
    0
  }
}

println("Add(12, 3):" + operation(12, 3, "add"))
println("Subtract(12, 3):" + operation(12, 3, "subtract"))
println("Multiply(12, 3):" + operation(12, 3, "multiply"))
println("Invalid Operation:" + operation(12, 3, "Invalid"))

The output of the above program is as below.

Add(12, 3):15
Subtract(12, 3):9
Multiply(12, 3):36
operationType: Invalid is not supported
Invalid Operation:0

Running a program continuously in Java

If you want to run a Java program continuously, then we can make use of the Thread.Join Method.

Refer to the below code.

public class Main {

    public static void main(String[] args) throws InterruptedException {
        System.out.println("Starting and running continuously");
        Thread.currentThread().join();
    }
  
}

How to set Initial heap size and Max Heap size with InitialRAMPercentage and MaxRAMPercentage and MinRAMPercentage

Most of the time, we set these parameters Xms and Xmx for setting up the initial heap size and maximum heap size for our java application.

In JAVA 8, they introduced new parameters that allow us to specify a percentage value.

-XX:InitialRAMPercentage -> Set initial heap size as a percentage of total memory.

-XX: MaxRAMPercentage -> Set Maximum heap size as a percentage of total memory.

Let’s say a java container is running and its memory size is 1GB, then if you want to set the initial heap size to ~250 MB and the max heap size to ~500 MB and also you don’t want to calculate these values by yourself and let the JVM handle these, you should set the XX:InitialRAMPercentage as 25.00 and XX:MaxRAMPercentage as 50.00

docker run -m 1GB openjdk:8 java -XX:MaxRAMPercentage=50.0 -XX:InitialRAMPercentage=25.0 -XX:+PrintFlagsFinal -version  | grep -iE 'HeapSize'

The output is given below

    uintx ErgoHeapSizeLimit                         = 0                                   {product}
    uintx HeapSizePerGCThread                       = 87241520                            {product}
    uintx InitialHeapSize                          := 268435456                           {product}
    uintx LargePageHeapSizeThreshold                = 134217728                           {product}
    uintx MaxHeapSize                              := 536870912                           {product}

openjdk version "1.8.0_332"
OpenJDK Runtime Environment (build 1.8.0_332-b09)
OpenJDK 64-Bit Server VM (build 25.332-b09, mixed mode)

We have another parameter called MinRAMPercentage which is used to set the maximum heap size for a JVM running with a small amount of memory(Less than 200 MB).

If a JVM is running with less than 200 MB, then we don’t have to set the MaxRAMPercentage, and setting the MinRAMPercentage is more than enough. Let’s see an example.

docker run -m 200m openjdk:8 java -XX:MaxRAMPercentage=90.0 -XX:MinRAMPercentage=50.0 -XX:+PrintFlagsFinal -version  | grep -iE 'HeapSize'

The output is given below

   uintx ErgoHeapSizeLimit                         = 0                                   {product}
    uintx HeapSizePerGCThread                       = 87241520                            {product}
    uintx InitialHeapSize                          := 8388608                             {product}
    uintx LargePageHeapSizeThreshold                = 134217728                           {product}
    uintx MaxHeapSize                              := 104857600                           {product}
openjdk version "1.8.0_332"
OpenJDK Runtime Environment (build 1.8.0_332-b09)
OpenJDK 64-Bit Server VM (build 25.332-b09, mixed mode)

If you look at the above example, we set the MaxRAMPercentage as 90, so it should suppose to assign the max heap size to more than 130 MB but the value is 104 MB only. It’s because the MaxRAMPercentage is not going to be used when the JVM memory is less than 200 MB. So only the MinRAMPercentage parameter is used.

Refer to the below example:

docker run -m 200m openjdk:8 java -XX:MinRAMPercentage=90.0 -XX:+PrintFlagsFinal -version  | grep -iE 'HeapSize'
   uintx ErgoHeapSizeLimit                         = 0                                   {product}
    uintx HeapSizePerGCThread                       = 87241520                            {product}
    uintx InitialHeapSize                          := 8388608                             {product}
    uintx LargePageHeapSizeThreshold                = 134217728                           {product}
    uintx MaxHeapSize                              := 132120576                           {product}
openjdk version "1.8.0_332"
OpenJDK Runtime Environment (build 1.8.0_332-b09)
OpenJDK 64-Bit Server VM (build 25.332-b09, mixed mode)

We set the XX:MinRAMPercentage to 90.0 and because of that, the max heap size is set to 132 MB. Please be aware that not the whole memory will be allocated to the heap.

How to get the VM.flags of a docker container running inside a Kubernetes pod

If you have a docker container(Java application) running inside a pod and want to check the VM.flags of that container, then follow the below steps.

Get a bash to the running container

 kubectl exec -i -t -n NAMESPACE POD_NAME -c CONTAINER NAME -- sh -c bash

Run the below command to get all the running processes.

jps

The above command lists out all the running processes. You have to find the java process for which you want to get the VM flags and get the process id.

Run the below command and put that processid to see all VM flags.

jcmd JPS_PROCESS_ID VM.flags