<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Dayananda</title>
    <description>The latest articles on Forem by Dayananda (@dayanandaeswar).</description>
    <link>https://forem.com/dayanandaeswar</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1292601%2F67ca96e1-477a-4699-a218-16bb08db1dc1.png</url>
      <title>Forem: Dayananda</title>
      <link>https://forem.com/dayanandaeswar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/dayanandaeswar"/>
    <language>en</language>
    <item>
      <title>Overview of Lock API in java</title>
      <dc:creator>Dayananda</dc:creator>
      <pubDate>Thu, 26 Dec 2024 07:21:13 +0000</pubDate>
      <link>https://forem.com/dayanandaeswar/overview-of-lock-api-in-java-5d4f</link>
      <guid>https://forem.com/dayanandaeswar/overview-of-lock-api-in-java-5d4f</guid>
      <description>&lt;p&gt;Managing access to shared resources is important in concurrent programming to ensure data consistency. Traditional synchronized keyword lacks flexibility for complex scenarios like fairness, acquire lock immediately, wait for a specific time to acquire lock, etc. Lock, ReadWriteLock, and StampedLock APIs are introduced in Java 1.5 to addresses these limitation and provides great control to developers to handle shared resources access. They are part of &lt;code&gt;java.util.concurrent&lt;/code&gt; package.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lock API
&lt;/h2&gt;

&lt;p&gt;Lock API is an interface and provides below methods to handle thread synchronization.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;code&gt;void lock()&lt;/code&gt; It is used to acquire the lock. If the lock is not available, the thread will be blocked until the lock is acquired.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;void lockInterruptibly()&lt;/code&gt; It is same as &lt;code&gt;lock()&lt;/code&gt;, but this thread can be interrupted.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;boolean tryLock()&lt;/code&gt; It returns true if the lock is acquired; otherwise, false. The thread will not be blocked if the lock is not granted.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;boolean tryLock(long timeout, TimeUnit unit)&lt;/code&gt; It is same as &lt;code&gt;tryLock()&lt;/code&gt; but waits for a specified amount of time only.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;void unlock()&lt;/code&gt;Releases the lock.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Condition newCondition()&lt;/code&gt; Provides the ability for a thread to wait for some condition to occur while executing the critical part.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;ReentrantLock&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ReentrantLock class implements the Lock interface. &lt;/li&gt;
&lt;li&gt;A reentrant lock allows a thread to acquire a lock multiple times and release it multiple times.&lt;/li&gt;
&lt;li&gt;If you want &lt;code&gt;fairness&lt;/code&gt; policy, use parameterized constructor of ReentrantLock.&lt;/li&gt;
&lt;li&gt;If &lt;code&gt;fairness&lt;/code&gt; is enabled, It makes sure that the longest waiting thread is given access to the lock.&lt;/li&gt;
&lt;li&gt;Use finally block to release the lock to avoid deadlock situation.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ReentrantLock lock = new ReentrantLock(true); //fair lock
public void methodExecution() {
    lock.lock();
    try {
        // Critical section here
    } finally {
        lock.unlock();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ReadWriteLock API
&lt;/h2&gt;

&lt;p&gt;ReadWriteLock API is an interface and maintains a pair of locks to maintain read and write scenarios. The read lock can be held simultaneously by multiple threads if there are no writers. The write lock is exclusive.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Lock readLock()&lt;/code&gt; - Returns the lock used for reading.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Lock writeLock()&lt;/code&gt; - Returns the lock used for writing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key Rules&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you have a read lock, you can't acquire a write lock.&lt;/li&gt;
&lt;li&gt;If you have a write lock, you can't acquire a read lock in any other thread.&lt;/li&gt;
&lt;li&gt;If you have a write lock, you can acquire another write lock in the same thread.&lt;/li&gt;
&lt;li&gt;A write lock is allowed when no other read or write lock is active.&lt;/li&gt;
&lt;li&gt;While waiting for a write lock, no new read locks from other threads are allowed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ReentrantReadWriteLock
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;ReentrantReadWriteLock class implements the ReadWriteLock interface.&lt;/li&gt;
&lt;li&gt;Useful if we have more read compare to write.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example: In micro-service communication, assume Service B expects a JWT from Service A. JWT is generated by Service A and can be cacheable for couple of minutes. In this scenarios ReentrantReadWriteLock will be more useful. We can renew the token if it is expired or about to expire. I am not acquiring read lock here to avoid read starvation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;String jwt = JwtUtil.generateJwt();
ReadWriteLock lock = new ReentrantReadWriteLock();
Lock writeLock = lock.writeLock();
Lock readLock = lock.readLock();

public String getJwt(String key, String value) {
    if (StringUtils.hasLength(jwt)) {
        if (JwtUtil.isJwtEligibleToRenew(jwt)) {
            generateJwt();
        }
    } else {
        generateJwt();
    }
    return this.jwt;
}

public void generateJwt() {
    this.writeLock.lock(); //write lock
    try {
        if (JwtUtil.isJwtEligibleToRenew(jwt)) {
            this.jwt = JwtUtil.generateJwt();
        }
    } finally {
        this.writeLock.unlock(); //release write lock
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  StampedLock API
&lt;/h2&gt;

&lt;p&gt;StampedLock was introduced in Java 8 and it is a class. It supports three modes of locking and returns a stamp that is used to release the lock. It allows lock upgradation.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;Read Lock&lt;/code&gt; Allows multiple threads to read concurrently.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Write Lock&lt;/code&gt; Returns a lock used for writing.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Optimistic Read Lock&lt;/code&gt; Allows a thread to read without acquiring a traditional read lock, which improves performance as it avoids contention.&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;long writeLock()&lt;/code&gt; Acquires the exclusive lock, blocking if necessary until available.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;void unlockWrite(long stamp)&lt;/code&gt; Releases the write lock.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;long readLock()&lt;/code&gt; Acquires the read lock, blocks if a write lock is in progress.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;void unlockRead(long stamp)&lt;/code&gt; Releases the read lock.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;long tryOptimisticRead()&lt;/code&gt; Returns a stamp that can later be validated, or zero if exclusively locked.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;boolean validate(long stamp)&lt;/code&gt; Returns &lt;code&gt;true&lt;/code&gt; if the lock has not been exclusively acquired (write lock) since the issuance of the given stamp; otherwise, &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;long tryConvertToWriteLock(long stamp)&lt;/code&gt; Upgrades a read or optimistic lock to a write lock. Blocks until it is available.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key Points:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is &lt;strong&gt;not reentrant&lt;/strong&gt;, meaning a thread holding a lock cannot acquire it again.
&lt;/li&gt;
&lt;li&gt;It doesn’t support conditions.
&lt;/li&gt;
&lt;li&gt;It doesn’t support fairness.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public void readAndWrite() {
    long l = this.stampedLock.readLock();
    try {
        //critical section
    } finally {
        this.stampedLock.unlock(l);
    }

    long w = this.stampedLock.writeLock();
    try {
        //critical section
    } finally {
        this.stampedLock.unlock(w);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Optimistic read example. This allows a thread to read without acquiring a traditional read lock, which improves performance as it avoids lock contention. If any write lock acquired after acquiring optimistic read lock time, validate() will return &lt;code&gt;false&lt;/code&gt; otherwise it will be &lt;code&gt;true&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class StampedLockExample {
    private StampedLock stampedLock = new StampedLock();
    private int cachedValue = 0;
    private long optimisticLock = stampedLock.tryOptimisticRead();

    public int readWithOptimisticLock() {
        if (!stampedLock.validate(optimisticLock)) {
            System.out.println(" Optimistic lock is invalid");
            optimisticLock = stampedLock.readLock();
            try {
            } finally {
                stampedLock.unlock(optimisticLock);
            }
            this.optimisticLock = stampedLock.tryOptimisticRead();
        } else {
            System.out.println("Optimistic lock is still valid");
        }
        return cachedValue;
    }

    public static void main(String[] args) {
        StampedLockExample threadsExample = new StampedLockExample();
        threadsExample.readWithOptimisticLock();
        long l = threadsExample.stampedLock.writeLock();
        threadsExample.stampedLock.unlock(l);
        threadsExample.readWithOptimisticLock();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Happy Coding and Learning !!!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Please drop a comment if you have any question.&lt;/p&gt;

</description>
      <category>java</category>
      <category>springboot</category>
      <category>concurrency</category>
      <category>javaconcurrency</category>
    </item>
    <item>
      <title>Overview of Executor Service in Java</title>
      <dc:creator>Dayananda</dc:creator>
      <pubDate>Tue, 24 Dec 2024 12:46:07 +0000</pubDate>
      <link>https://forem.com/dayanandaeswar/overview-of-executor-service-in-java-40nm</link>
      <guid>https://forem.com/dayanandaeswar/overview-of-executor-service-in-java-40nm</guid>
      <description>&lt;p&gt;&lt;code&gt;Executor&lt;/code&gt; and &lt;code&gt;ExecutorService&lt;/code&gt; API is a crucial tool for managing and controlling thread execution. They are part of &lt;code&gt;java.util.concurrent&lt;/code&gt; package. They simplifies the process of concurrent programming by abstracting the complexities of thread creation, management, and synchronization. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;Executors&lt;/code&gt; is a utility class from &lt;code&gt;java.util.concurrent&lt;/code&gt; package provides factory methods for creating and managing different types of ExecutorService instances. It simplifies the process of creating thread pools and allows us to easily create and manage executor instances with different configurations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Executor API&lt;/strong&gt; It is an interface available since Java 1.5. It provides &lt;code&gt;execute(Runnable command)&lt;/code&gt; method.  This is base interface and ExecutorService extends this interface. The given command will be executed in future time by new thread or thread from thread pool or same thread and doesn't returns void.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ExecutorService API&lt;/strong&gt; It is an interface available since Java 1.5. It provides multiple methods to control the execution of tasks in concurrent programming. It support both Runnable and Callable tasks. It returns Future for task status. Below are the most frequent used methods. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;submit()&lt;/code&gt; accepts a Callable or a Runnable task and returns Future type result.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;invokeAny()&lt;/code&gt; accepts a collection of tasks to run, and returns the result of a successful execution of any one task.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;invokeAll()&lt;/code&gt; accepts a collection of tasks to run, and returns the result of all tasks in the form of a list of Future objects type.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;shutdown()&lt;/code&gt; it doesn't stop executor service immediately but doesn't accept new tasks. Once all current running tasks finished, it shutdown the executor service.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;shutdownNow()&lt;/code&gt; it tries to stop the executor service immediately, but it doesn't guarantee that all the running tasks will be stopped at the same time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;awaitTermination(long timeout, TimeUnit unit)&lt;/code&gt; blocks/waits until all tasks are completed or timeout occurs or current thread is interrupted, whichever happens first. The current thread will be blocked. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Types of ExecutorService&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;FixedThreadPool&lt;/code&gt; It crates fixed size thread pool with specified number of threads. Tasks submitted are executed concurrently. If there are no tasks, threads will be idle until task is arrived. If threads are busy, tasks will be added queue.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ExecutorService fixedThreadPool = Executors.newScheduledThreadPool(5);
Future&amp;lt;String&amp;gt; submit = fixedThreadPool.submit(() -&amp;gt; {
    System.out.println("Task executed by " + Thread.currentThread().getName());
    return Thread.currentThread().getName();
});
fixedThreadPool.shutdown();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CachedThreadPool&lt;/code&gt; Creates pool of threads and automatically adjust number of threads required in the pool based on workload. If thread is idle, for more than 60 seconds, will be terminated. This works well for dynamic loads. As threads will be killed after idle timeout, resources are better utilized here.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ExecutorService fixedThreadPool = Executors.newCachedThreadPool();
Future&amp;lt;String&amp;gt; submit = fixedThreadPool.submit(() -&amp;gt; {
    System.out.println("Task executed by " + Thread.currentThread().getName());
    return Thread.currentThread().getName();
});
fixedThreadPool.shutdown();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;SingleThreadExecutor&lt;/code&gt; Creates single thread and tasks are executed sequentially. There is no parallel processing here.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ExecutorService fixedThreadPool = Executors.newSingleThreadExecutor();
Future&amp;lt;String&amp;gt; submit = fixedThreadPool.submit(() -&amp;gt; {
    System.out.println("Task executed by " + Thread.currentThread().getName());
    return Thread.currentThread().getName();
});
fixedThreadPool.shutdown()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ScheduledThreadPool/ScheduledExecutor&lt;/code&gt; It creates a thread or trhead pool which will have a capability to run the tasks at regular interval or run after certain delay.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); // Single-threaded scheduler
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(5); // Multi-threaded scheduler
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scheduler.schedule(task, 10, TimeUnit.SECONDS); // Schedule task to run after 10 seconds.

scheduler.scheduleAtFixedRate(task, 5, 10, TimeUnit.SECONDS);
    //It schedules a task to run every 10 seconds with an initial delay of 5 seconds.
scheduler.scheduleWithFixedDelay(task, 5, 10, TimeUnit.SECONDS);
   //It schedules a task to run with a fixed delay of 10 seconds between the end of one execution and the start of the next, with an initial delay of 5 seconds.
scheduler.schedule(() -&amp;gt; scheduler.shutdown(), 20, TimeUnit.SECONDS);
   //It schedules a shutdown of the scheduler after 20 seconds to stop the example.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Submitting Tasks to ExecutorService&lt;/strong&gt;&lt;br&gt;
Tasks can be submitted to the ExecutorService using the execute() and submit() methods. The execute() method is used for Runnable tasks, while submit() can handle both Runnable and Callable tasks."&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; executor.execute(new RunnableTask()); //fire-and-forgot
 executor.submit(new CallableTask()); //returns the status of task
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Shutting Down ExecutorService&lt;/strong&gt;&lt;br&gt;
It's important to shut down the ExecutorService to release resources. You can do this using the shutdown() and shutdownNow() methods.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;executor.shutdown(); // Initiates an orderly shutdown"
executor.shutdownNow(); // Attempts to stop all actively executing tasks.
executor.awaitTermination(long timeout, TimeUnit unit); //blocks the thread until all tasks are completed or timeout occurs or current thread is interrupted, whichever happens first. Returns `true `is tasks completed, otherwise `false`.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Recommended approach to shutdown&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;executor.shutdown();
try {
    // Wait for tasks to complete or timeout
    if (!executor.awaitTermination(120, TimeUnit.SECONDS)) {
        // If the timeout occurs, force shutdown
        executor.shutdownNow();      
    }
} catch (InterruptedException ex) {
    executor.shutdownNow();
    Thread.currentThread().interrupt();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;About Runnable&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Runnable is an interface and represents a task that can run by threads.&lt;/li&gt;
&lt;li&gt;We can run Runnable tasks by using Threads or Executor service. &lt;/li&gt;
&lt;li&gt;Runnable is having run() method and doesn't return any data.&lt;/li&gt;
&lt;li&gt;We can't throw checked exception.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;About Callable&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is introduced in 1.5 &lt;/li&gt;
&lt;li&gt;It is having call() method and returns type V.&lt;/li&gt;
&lt;li&gt;It contains throws Exception meaning, we can throw checked exception.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;About Future&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It represents a future result of any task.&lt;/li&gt;
&lt;li&gt;The result will eventually appear in the Future after request processing is completed.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;boolean isDone()&lt;/code&gt; Returns the status of request processing. True if completed otherwise false.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;boolean cancel(boolean mayInterruptIfRunning)&lt;/code&gt; Cancels the submitted task. if we pass mayInterruptIfRunning as false, then it won't cancel already started task. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;boolean isCancelled()&lt;/code&gt; returns task is cancelled or not.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;V get()&lt;/code&gt; returns result of task. Blocks the thread if task is not completed.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;V get(long timeout, TimeUnit unit)&lt;/code&gt; Waits if necessary for at most the given time for the computation to complete, and then retrieves its result. TimeoutException will be thrown after specified time if computation is not completed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Happy Coding and Learning !!!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Please drop a comment if you have any question.&lt;/p&gt;

</description>
      <category>java</category>
      <category>javaconcurrency</category>
      <category>executorservice</category>
    </item>
    <item>
      <title>How to estimate Java object size</title>
      <dc:creator>Dayananda</dc:creator>
      <pubDate>Mon, 25 Nov 2024 07:14:12 +0000</pubDate>
      <link>https://forem.com/dayanandaeswar/how-to-estimate-java-object-size-1jgp</link>
      <guid>https://forem.com/dayanandaeswar/how-to-estimate-java-object-size-1jgp</guid>
      <description>&lt;p&gt;In Java, objects are the basic building blocks of any applications. When an object is created, memory is allocated from the heap to store its instance variables. Understanding how much memory an object consumes is important for optimizing memory usage and preventing OutOfMemoryErrors. It is important to optimize the memory consumption especially in cloud solutions. &lt;/p&gt;

&lt;p&gt;Object size is calculated as &lt;strong&gt;&lt;code&gt;Object Header size + variable size(for primitives) or refence size(for objects)&lt;/code&gt;&lt;/strong&gt;. But it is not that simple. Actual memory size consumed depends on data type, architecture, variable object refereed by other object or not(P1 &amp;amp; P2 refers to same country object), String/primitive pools etc...  &lt;/p&gt;

&lt;p&gt;In Java, primitive member variables are recommended and it consumes less space compare to wrappers. We will do the comparison and see how much memory can be saved with primitive data types.&lt;/p&gt;

&lt;p&gt;Object memory size is always multiple of 8. JVM adds padding bytes to make it multiple of 8 if required. If object memory size comes as 12 byte length, then JVM adds 4 padding byte to make it multiple of 8. &lt;code&gt;12 byte + 4 byte = 16 byte&lt;/code&gt;. In this I will be using HotSpot JVM specification for measuring the sizes. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;u&gt;Size Metrics&lt;/u&gt;
&lt;/h2&gt;

&lt;p&gt;To analyze size we use three metrics. Shallow size, Deep size, Retained size.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Shallow size&lt;/code&gt; In this metrics, we consider object size itself. If it is having reference to other objects, we consider reference size while calculating size metric.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Deep Size&lt;/code&gt; In this metrics, we consider object size and size of reference objects. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;Retained Size&lt;/code&gt; In this metrics, we consider object's shallow size and the objects are only referenced from this object. In other words, the retained size is the amount of memory that can be reclaimed by garbage-collecting this object. We don't consider objects if it is referred by more than one object.  &lt;/p&gt;

&lt;p&gt;In real, Retained Size metric is very important and it is purely depends on data and object reference structure. It is tricky to calculate and complicate tasks if object(s) are referred by different instances. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx2hj77rmzv4ut4rnjs8g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx2hj77rmzv4ut4rnjs8g.png" alt="Size Types Image" width="800" height="232"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;u&gt;Elements influences object size&lt;/u&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Object Header&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Every object will have object header and it is based on &lt;code&gt;oopDesc&lt;/code&gt; data structure. Object header will contain &lt;code&gt;mark word&lt;/code&gt; and &lt;code&gt;klass pointer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Mark Word&lt;/code&gt; will contain information related to hash code, locking and GC information. The size of this is &lt;code&gt;4 byte and 8 byte&lt;/code&gt; in &lt;code&gt;32 and 62 bit architecture&lt;/code&gt; respectively. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;Klass pointer&lt;/code&gt; will contain information related to class, modifiers and super class. The size of this is &lt;code&gt;4 byte&lt;/code&gt; in both architecture. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Object Header&lt;/em&gt; size would be &lt;code&gt;8 byte and 16 byte&lt;/code&gt; in &lt;code&gt;32-bit and 62-bit&lt;/code&gt; architecture respectively.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9gjw67ce413n8qbquptx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9gjw67ce413n8qbquptx.png" alt="Normal Object Header size" width="640" height="295"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Member Variables&lt;/strong&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Primitive data types&lt;/em&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Primitive data types consumes fixed amount of memory size. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk1q1vr53epy05veyf0hk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk1q1vr53epy05veyf0hk.png" alt="Primitive data types size" width="670" height="113"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Primitive Wrappers&lt;/em&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Primitive Wrappers will consumes additional memory size. For primitive wrappers memory size calculation is &lt;code&gt;Primitive data type size + Object Header size + Padding bytes if required&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2sbvzesy8m77scarh68y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2sbvzesy8m77scarh68y.png" alt="Primitive Wrappers size" width="800" height="561"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Arrays&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Arrays can be primitive or non primitive arrays. Memory size for arrays is sum of &lt;code&gt;Object Header + (number of elements * reference for objects /primitive size for primitives) + length field (4 byte always)&lt;/code&gt;. Reference is &lt;code&gt;4 byte&lt;/code&gt; size always. &lt;code&gt;Length field&lt;/code&gt; will store the length of the array.&lt;/p&gt;

&lt;p&gt;If we have &lt;code&gt;Person[]&lt;/code&gt; with 36 length, then size is &lt;code&gt;12 + (36 * 4 (reference size) ) + 4 = 160 byte&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9zkyb011pjengcq3ulos.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9zkyb011pjengcq3ulos.png" alt="Array size non primitive" width="800" height="64"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we have &lt;code&gt;byte[]&lt;/code&gt; with 36 length, then size is &lt;code&gt;12 + (36 * 1 (byte size)) + 4 =  52 + 4 padding = 56 byte&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3fnqs13l302z7qxtsr9g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3fnqs13l302z7qxtsr9g.png" alt="Array size primitive" width="800" height="39"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;String&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The size (shallow) of this String instance is &lt;code&gt;16 byte and 24 byte&lt;/code&gt; in &lt;code&gt;32 and 62 bit architecture&lt;/code&gt; respectively. It includes the 4 byte of cached hash code, 4 byte of char[] reference, and object header. &lt;/p&gt;

&lt;p&gt;The actual string is stored as byte array and size of it is &lt;code&gt;(1 (byte size) * number of characters) + 12 ( Object header) + 4 (length)&lt;/code&gt;. For 36 length string will have &lt;code&gt;(1*36) + 8 + 4 + 4 =  52 + 4 padding = 56 byte&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Total Retained/Deep size of String (of 36 length) is &lt;code&gt;24 byte + 56 byte = 80 byte&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frdz4k8uwq26dv6fmp6pp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frdz4k8uwq26dv6fmp6pp.png" alt="String total size" width="800" height="195"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;u&gt;Lets look into an example&lt;/u&gt;
&lt;/h2&gt;

&lt;p&gt;We will first look into class without variables and later get into with variable. We will also look into member variables with wrappers and primitives. We will estimate the size and see how much memory we can save with primitive data types. I will be using VisualVM for profiling the data and 64-bit architecture system. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. With out any member variables&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Consider simple &lt;code&gt;Person&lt;/code&gt; class without any variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Person{ 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we will create 1000 objects of this and put it array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class MemoryMgmtController {
    int count = 1000;
    Person[] persons = new Person[count]; 
    public MemoryMgmtController() {
        for (int i = 0; i &amp;lt; count; i++) {
            persons[i] = new Person();
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we know array memory size is sum of &lt;code&gt;Object Header + (array size * 4 byte)&lt;/code&gt;, So  size of &lt;code&gt;Person[]&lt;/code&gt; would be &lt;code&gt;16 byte (with 4 padding byte) + (1000 * 4 byte) = 4016 byte&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;In addition to this, we have created 1000 Person objects which will have  Object Header information (16 byte with 4 padding byte) by default. So it would be &lt;code&gt;16 * 1000 = 16000 byte&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;So without any data, for simply creating 1000 objects itself has occupied &lt;code&gt;4016 + 16000 = 20016 byte (~20KB)&lt;/code&gt; memory. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0cq8wzhz4ib81gag4crt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0cq8wzhz4ib81gag4crt.png" alt="Object without variables" width="800" height="184"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. With wrappers as member variables&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Consider simple &lt;code&gt;Person&lt;/code&gt; class with wrappers as member variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Person{ 
    public Boolean active;
    public Short country; 
    public Character gender; 
    public Integer id; 
    public Float salary;
    public Long pk; 
    public Double bonus; 
    public String name; 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we will create 1000 objects with data and assign it to array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class MemoryMgmtController {
    int count = 1000;
    Person[] persons = new Person[count]; 
    public MemoryMgmtController() {
        for (int i = 0; i &amp;lt; count; i++) {
            Person person = new Person();
            person.setActive(Boolean.TRUE);
            person.setCountry((short) 12);
            person.setGender(GENDER);
            person.setId((int) i);
            person.setSalary((float) i);
            person.setPk((long) i);
            person.setBonus((double) i);
            person.setName(UUID.randomUUID().toString());
            persons[i] = person;
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Size of &lt;code&gt;Person[]&lt;/code&gt; would be same as earlier i.e &lt;code&gt;16 byte (with 4 padding byte) + (1000 * 4 byte) = 4016 byte&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But if we look at size of 1000 objects, it would increase. The reason we have added member variables which will occupy the size. We have added wrappers as member variable so &lt;code&gt;Person&lt;/code&gt; object will hold the reference to wrapper objects. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Even though we say object header is 16 byte in 64-bit architecture, that is with 4 padding byte. While estimating, we consider 12 byte for object header, if required padding byte are added. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fys2hsw8u0x8d0jrrqmkg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fys2hsw8u0x8d0jrrqmkg.png" alt="Size with wrapper member variables" width="800" height="309"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Total Memory estimation&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl4bb23pda746d4pem9v5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl4bb23pda746d4pem9v5.png" alt="Total Estimation with wrappers" width="800" height="466"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. With primitives as member variables&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When we use primitives they will consumer fixed size and directly part of  &lt;code&gt;Person&lt;/code&gt;. Person will not have any reference except String in our scenario. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh6mipn8qoktj66rff4jx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh6mipn8qoktj66rff4jx.png" alt="With primitive variables" width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Using primitives instead of wrappers has saved nearly 45% memory in this scenario. This will vary based on variables and object structure.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Actual memory consumed will depend on so many other factors like retained size, duplicate strings, JVM implementation and many others. Having idea on high level estimation will help us to develop memory optimized applications. &lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use primitives instead of wrappers where ever possible.&lt;/li&gt;
&lt;li&gt;Use Trove library to have collections with primitives. &lt;/li&gt;
&lt;li&gt;Consider UseCompressedOops java flag to improve the performance in 64-bit architecture.&lt;/li&gt;
&lt;li&gt;Use Java Object Layout (&lt;a href="https://openjdk.org/projects/code-tools/jol/" rel="noopener noreferrer"&gt;JOL&lt;/a&gt;) tool to inspect memory layouts of object.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Happy Coding and Learning !!!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Please drop a comment if you have any question.&lt;/em&gt; &lt;/p&gt;

</description>
      <category>java</category>
      <category>architecture</category>
      <category>spring</category>
      <category>memory</category>
    </item>
    <item>
      <title>Mask logs using logstash logback in java with regex</title>
      <dc:creator>Dayananda</dc:creator>
      <pubDate>Mon, 11 Nov 2024 10:02:57 +0000</pubDate>
      <link>https://forem.com/dayanandaeswar/mask-logs-with-logstash-logback-in-java-using-regex-2g0p</link>
      <guid>https://forem.com/dayanandaeswar/mask-logs-with-logstash-logback-in-java-using-regex-2g0p</guid>
      <description>&lt;p&gt;In today's data-driven world, data security is most important. Logging frameworks play a crucial role in application monitoring and debugging, but they can inadvertently expose sensitive information which should not have been. Log masking is a technique that effectively obfuscates sensitive data in log messages, safeguarding confidential information. &lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Logback
&lt;/h2&gt;

&lt;p&gt;Logback is a powerful and mostly used logging framework in Java applications. It offers flexible configuration options, including the ability to format log events as JSON objects. It is a successor to the Log4j framework, has quickly gained popularity due to its features and ease of use. It is comprised of Logger, Encoders, Layout, Appender, Encoder.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Logger:&lt;/strong&gt; Logger is a context for log messages. Applications will interact with this class to create log messages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Encoders:&lt;/strong&gt; Encoders are introduced in &lt;code&gt;logback&lt;/code&gt; 0.9.91 and responsible for transforming an event into a byte array as well as writing out that byte array into an &lt;code&gt;OutputStream&lt;/code&gt;. Encoders introduced as Layouts are only capable to transform an event into a String which restricts their scope to non-binary output. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layout:&lt;/strong&gt; The layout is responsible for formatting the logging request according to the user's wishes, whereas an appender takes care of sending the formatted output to its destination. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Appenders:&lt;/strong&gt;  In logback speak, an output destination is called an appender. This places log messages in their final destinations. A Logger can have more than one Appender. Currently, appenders exist for the console, files, remote socket servers, to MySQL, PostgreSQL, Oracle and other databases, JMS, and remote UNIX Syslog daemons.&lt;/p&gt;

&lt;h2&gt;
  
  
  About Logstash Logback Encoder
&lt;/h2&gt;

&lt;p&gt;The logstash-logback-encoder library is a valuable tool for enhancing your Spring Boot applications' logging capabilities. It provides a convenient way to format log messages in a structured JSON format, making them readily consumable by log aggregation and analysis tools like Logstash. JSON format provides a structured and machine-readable way to log information, making it ideal for advanced log analysis and security measures. Benefits of logstash &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;JSON Customization&lt;/code&gt; Logstash allows you to customize the JSON output to include specific fields and metadata. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Dynamically Fields&lt;/code&gt; It also allows Dynamically add fields to log events based on application context.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Improved Readability&lt;/code&gt; JSON format offers a clear and human-readable structure for log events.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Enhanced Search and Analysis&lt;/code&gt; Log aggregation tools can easily parse and query JSON logs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Machine Parsing&lt;/code&gt; JSON logs are ideal for automated analysis and alerting systems.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Solution to mask the data in logs
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Here main goal is to provide a solution to mask the data which is customizable and configurable at runtime. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here is our simple requirement to &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;mask password completely in log.&lt;/li&gt;
&lt;li&gt;mask phone number  and login name except last 5 in log.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt;&lt;br&gt;
Create spring boot application. This solution will work with any java based application with little customization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt;&lt;br&gt;
Configure all regular expressions to mask the data. Please remember regex are costly in terms of resource utilization. Make sure you are tuning your regex. Regex groups will allows us to select required substring from string. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhjamtrxivdq3j48zhwu9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhjamtrxivdq3j48zhwu9.png" alt="Props configuration" width="800" height="80"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3&lt;/strong&gt;&lt;br&gt;
Create a class and implement &lt;code&gt;MessageJsonProvider&lt;/code&gt;. This interface is from logstash and allows us to customize the message before printing to the appender. &lt;code&gt;writeTo&lt;/code&gt; method in this interface will be called for every log message. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;in &lt;code&gt;start()&lt;/code&gt; method read all regex and prepare &lt;code&gt;LogMasker&lt;/code&gt; which contains all &lt;code&gt;MaskingRule&lt;/code&gt;. This method is from &lt;code&gt;AbstractJsonProvider&lt;/code&gt; and simply marks the process started as true. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;MaskingRule&lt;/code&gt; will hold regex pattern and a function. This function replaces the identified string from in the log.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Data
public class MaskingMessagingProvider extends MessageJsonProvider {

    public static final String DEFAULT_RULES_DELIMITER = ",";
    private LogMasker logMasker;
    private String rules;

    public MaskingMessagingProvider() {
        super();
    }

    @Override
    public void start() {
        super.start();
        this.logMasker = LogMasker.create(StringUtils.tokenizeToStringArray(rules, DEFAULT_RULES_DELIMITER));
    }

    @Override
    public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOException {

        if (isStarted()) {
            JsonWritingUtils.writeStringField(generator, getFieldName(), logMasker.mask(event.getFormattedMessage()));
        }
    }
}

class LogMasker {

    private MaskingRule[] masks;

    public LogMasker(MaskingRule[] masks) {
        super();
        this.masks = masks.clone();
    }

    public static LogMasker create(String[] rules) {

        return new LogMasker(Arrays.stream(rules).map(rule -&amp;gt; MaskingRule.create(rule)).toArray(MaskingRule[]::new));
    }

    public String mask(String input) {
        String transformed = input;
        for (MaskingRule m : masks) {
            transformed = m.mask(transformed);
        }
        return transformed;
    }
}

class MaskingRule {
    public static final int REG_EX_DEFAULT_GROUP_SELECTOR = 2;
    public static final String DEFAULT_REPLACEMENT = "*";

    private Pattern pattern;
    private UnaryOperator&amp;lt;String&amp;gt; replacement;

    public MaskingRule(Pattern maskPattern, UnaryOperator&amp;lt;String&amp;gt; replacement) {
        super();
        this.pattern = maskPattern;
        this.replacement = replacement;
    }

    public static MaskingRule create(String rule) {
        return new MaskingRule(Pattern.compile(rule), (in) -&amp;gt; MaskingRule.maskDataWithReplacement(in, DEFAULT_REPLACEMENT));
    }

    public String mask(String transformed) {
        Matcher matcher = pattern.matcher(transformed);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, replacement.apply(getDataToBeMasked(matcher)));
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    private static String maskDataWithReplacement(String input, String replacement) {
        int repetition = !StringUtils.hasLength(input) ? 0 : input.length();
        return String.join("", Collections.nCopies(repetition, replacement));
    }

    private static String getDataToBeMasked(Matcher matcher) {
        if (matcher.groupCount() &amp;gt; 1) {
            return matcher.group(REG_EX_DEFAULT_GROUP_SELECTOR);
        }
        return matcher.groupCount() &amp;gt; 0 ? matcher.group(1) : "";
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Step 4&lt;/strong&gt;&lt;br&gt;
Configure class in logback-spring.xml file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;configuration&amp;gt;
    &amp;lt;springProperty scope="context" name="rules" source="app.logging.masking.rules"
                    defaultValue=""/&amp;gt;
    &amp;lt;appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"&amp;gt;
        &amp;lt;encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder"&amp;gt;
            &amp;lt;providers&amp;gt;
                &amp;lt;provider class="com.daya.logging.logstash.MaskingMessagingProvider"&amp;gt;
                    &amp;lt;rules&amp;gt;${rules}&amp;lt;/rules&amp;gt;
                    &amp;lt;rulesDelimiter&amp;gt;${rulesDelimiter}&amp;lt;/rulesDelimiter&amp;gt;
                    &amp;lt;ruleDelimiter&amp;gt;${ruleDelimiter}&amp;lt;/ruleDelimiter&amp;gt;
                &amp;lt;/provider&amp;gt;
                &amp;lt;threadName/&amp;gt;
                &amp;lt;timestamp/&amp;gt;
                &amp;lt;logLevel/&amp;gt;
                &amp;lt;loggerName/&amp;gt;
                &amp;lt;mdc/&amp;gt;
                &amp;lt;version/&amp;gt;
                &amp;lt;stackTrace/&amp;gt;
            &amp;lt;/providers&amp;gt;
        &amp;lt;/encoder&amp;gt;
    &amp;lt;/appender&amp;gt;
    &amp;lt;root level="INFO"&amp;gt;
        &amp;lt;appender-ref ref="CONSOLE"/&amp;gt;
    &amp;lt;/root&amp;gt;
&amp;lt;/configuration&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Steps 5&lt;/strong&gt;&lt;br&gt;
Run the application. For simplicity, i have taken a string which is holding data and printing it at application start up.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@SpringBootApplication
@Slf4j
public class LogDataMaskingApplication {

    public static void main(String[] args) {
        SpringApplication.run(LogDataMaskingApplication.class, args);
        LogDataMaskingApplication.maskingTest();
    }

    public static void maskingTest() {
        String data = "{\"loginName\":\"maskingtest\",\"phoneNumber\":\"9898981212\",\"password\":\"Masking@123\"}";
        log.info(data);
    }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fefy4gmusmf38r6pbq16e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fefy4gmusmf38r6pbq16e.png" alt="Log Masked" width="800" height="194"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is very basics solution and having lot of scope for enhancement as per requirement like &lt;code&gt;message digest&lt;/code&gt; etc...&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can find code at &lt;a href="https://github.com/dayanandaeswar/log-masking-using-logback-logstash" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Please drop a comment if you have any question.&lt;/p&gt;

</description>
      <category>java</category>
      <category>architecture</category>
      <category>logging</category>
      <category>springboot</category>
    </item>
    <item>
      <title>Content projection in Angular</title>
      <dc:creator>Dayananda</dc:creator>
      <pubDate>Mon, 04 Nov 2024 12:39:06 +0000</pubDate>
      <link>https://forem.com/dayanandaeswar/content-projection-in-angular-3dol</link>
      <guid>https://forem.com/dayanandaeswar/content-projection-in-angular-3dol</guid>
      <description>&lt;p&gt;Content projection, a powerful technique in Angular, allows developers to create highly reusable and customizable components. This approach enhances component reusability, flexibility, leading to cleaner, and more maintainable Angular applications.&lt;/p&gt;

&lt;p&gt;In this article, we will delve into what content projection is, types,  how to use it, with below &lt;strong&gt;real-world&lt;/strong&gt; scenario for multi-slot content projection.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3qyov4qd0z7ah8fpf59d.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3qyov4qd0z7ah8fpf59d.gif" alt="Multi Select Picker Demo" width="600" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Content Projection
&lt;/h2&gt;

&lt;p&gt;Content projection is a pattern enables us to insert or project content from a parent component into a child(s) component. This approach makes it possible to design flexible components that can accommodate a wide range of content, making them more reusable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Content Projection types
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Single-Slot Content Projection&lt;/strong&gt; Single-slot content projection uses a single &lt;code&gt;&amp;lt;ng-content&amp;gt;&lt;/code&gt; directive, allowing the insertion of content in a specific place.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multi-Slot Content Projection&lt;/strong&gt; Multi-slot content projection allows projecting different sections of content into different parts of the template. Multi-slot content projection uses the select attribute (&lt;code&gt;&amp;lt;ng-content select="[card-subtitle]"&amp;gt;&amp;lt;/ng-content&amp;gt;&lt;/code&gt;) to specify which content need to go where.&lt;/p&gt;

&lt;h2&gt;
  
  
  Few key concepts to be aware
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;ng-content&amp;gt;&lt;/code&gt; in a component template defines a placeholder area(s). When a parent component uses this component, it pass content between the  tags, customizing the child component's behavior.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;ng-container&amp;gt;&lt;/code&gt; is an directive that allows to group elements in a template that doesn’t interfere with styles or layout and not rendered into Angular DOM.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;ng-template&amp;gt;&lt;/code&gt; is a template element that Angular uses with structural directives. These template elements work in the presence of structural directives and help us to define a template that doesn’t render anything by itself, but conditionally renders them to the DOM.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example of Single-Slot Content Projection
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Create child/reusable component&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Component({
  selector: 'app-single-slot-projection',
  template: `&amp;lt;mat-toolbar&amp;gt;
        &amp;lt;ng-content&amp;gt; &amp;lt;/ng-content&amp;gt;
         &amp;lt;/mat-toolbar&amp;gt;`,
  styles: ``
})
export class SingleSlotProjectionComponent {

}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Use Single-slot component in a Parent Component&lt;/p&gt;

&lt;p&gt;All the content inside &lt;code&gt;&amp;lt;app-single-slot-projection&amp;gt;&lt;/code&gt; will be projected at  &lt;code&gt;&amp;lt;ng-content&amp;gt;&lt;/code&gt; place of child component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Component({
  selector: 'app-root',
  template: `
  &amp;lt;app-single-slot-projection&amp;gt;
      &amp;lt;span&amp;gt;Content Projection Example&amp;lt;/span&amp;gt;
    &amp;lt;/app-single-slot-projection&amp;gt;
  `,
  styleUrl: './app.component.scss'
})
export class AppComponent {
  title = 'angular-multi-select-picker';  
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Example of Multi-Slot Content Projection
&lt;/h2&gt;

&lt;p&gt;Let's look at real time application scenario. Consider you are working on dynamic reports generation application which allows user to select required fields in the report. To select required fields in report, we have a screen like above where all available column names will appear in left box, selected column names will appear in the right box. Actions will appear in the middle. You can select required columns from left menu and move it to right side. You will have an option to move all towards right and left.&lt;/p&gt;

&lt;p&gt;As part of core team we decide to define standard sections and consuming application can decide what has to go inside of those sections. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Making it more reusable component with all conditional projections will be published soon in another post&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt;  Create child/reusable component&lt;/p&gt;

&lt;p&gt;As part of this example i am considering 5 places for content project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;mat-card appearance="outlined"&amp;gt;
    &amp;lt;mat-card-header class="mb-2"&amp;gt;
        &amp;lt;mat-card-title&amp;gt;
            &amp;lt;ng-content select="[card-title]"&amp;gt;&amp;lt;/ng-content&amp;gt;
        &amp;lt;/mat-card-title&amp;gt;
        &amp;lt;mat-card-subtitle class="mt-2"&amp;gt;
            &amp;lt;ng-content select="[card-subtitle]"&amp;gt;&amp;lt;/ng-content&amp;gt;
        &amp;lt;/mat-card-subtitle&amp;gt;
    &amp;lt;/mat-card-header&amp;gt;
    &amp;lt;mat-card-content&amp;gt;
        &amp;lt;div class="list_builder"&amp;gt;
            &amp;lt;ng-content select="[source-items]"&amp;gt;&amp;lt;/ng-content&amp;gt;
            &amp;lt;ng-content select="[action-items]"&amp;gt; &amp;lt;/ng-content&amp;gt;
            &amp;lt;ng-content select="[target-items]"&amp;gt;&amp;lt;/ng-content&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/mat-card-content&amp;gt;
&amp;lt;/mat-card&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Use Multi-slot component in a Parent Component&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;card-title:&lt;/strong&gt; displays some static content.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;card-subtitle:&lt;/strong&gt; displays static content wit number of columns available in right side table.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;source-items:&lt;/strong&gt; displays all the available columns available for our requirement. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;action-items:&lt;/strong&gt; displays all actions that can be performed on left and right side tables.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;target-items:&lt;/strong&gt; displays all the selected columns to present in out report.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;main class="main"&amp;gt;
  &amp;lt;div class="content"&amp;gt;
    &amp;lt;!-- Single Slot Projection --&amp;gt;
    &amp;lt;app-single-slot-projection&amp;gt;
      &amp;lt;span&amp;gt;Content Projection Example&amp;lt;/span&amp;gt;
    &amp;lt;/app-single-slot-projection&amp;gt;

    &amp;lt;!-- Multi Slot Projection --&amp;gt;
    &amp;lt;app-multi-select-picker&amp;gt;

      &amp;lt;!-- card-title section --&amp;gt;
      &amp;lt;ng-container card-title&amp;gt;Multi Select Picker&amp;lt;/ng-container&amp;gt;

      &amp;lt;!-- card-subtitle section --&amp;gt;
      &amp;lt;ng-container card-subtitle&amp;gt;Selected Items Count: {{targetItems.length}}&amp;lt;/ng-container&amp;gt;

      &amp;lt;!-- source-items section --&amp;gt;
      &amp;lt;ng-container source-items&amp;gt;
        &amp;lt;mat-card class="source_items"&amp;gt;
          &amp;lt;mat-card-content&amp;gt;
            &amp;lt;mat-list role="list"&amp;gt;
              @for (data of sourceItems; track $index) {
              &amp;lt;mat-list-item role="listitem" class="selectable_item" [ngClass]="{selected_item: data.selected}"
                (click)="itemSelected(data)"&amp;gt;
                {{data.value}}
              &amp;lt;/mat-list-item&amp;gt;
              }
            &amp;lt;/mat-list&amp;gt;
          &amp;lt;/mat-card-content&amp;gt;
        &amp;lt;/mat-card&amp;gt;
      &amp;lt;/ng-container&amp;gt;

      &amp;lt;!-- action-items section --&amp;gt;
      &amp;lt;ng-container action-items&amp;gt;
        &amp;lt;mat-card class="action_items"&amp;gt;
          &amp;lt;mat-card-content class="action_buttons_container"&amp;gt;
            &amp;lt;button mat-icon-button class="action_buttons" (click)="moveAll('right')"&amp;gt;
              &amp;lt;mat-icon aria-hidden="false" aria-label="Move All Right"
                fontIcon="keyboard_double_arrow_right"&amp;gt;&amp;lt;/mat-icon&amp;gt;
            &amp;lt;/button&amp;gt;
            &amp;lt;button mat-icon-button class="action_buttons" (click)="moveSelected('right')"&amp;gt;
              &amp;lt;mat-icon aria-hidden="false" aria-label="Move Right" fontIcon="chevron_right"&amp;gt;&amp;lt;/mat-icon&amp;gt;
            &amp;lt;/button&amp;gt;
            &amp;lt;button mat-icon-button class="action_buttons" (click)="moveSelected('left')"&amp;gt;
              &amp;lt;mat-icon aria-hidden="false" aria-label="Move Left" fontIcon="chevron_left"&amp;gt;&amp;lt;/mat-icon&amp;gt;
            &amp;lt;/button&amp;gt;
            &amp;lt;button mat-icon-button class="action_buttons" (click)="moveAll('left')"&amp;gt;
              &amp;lt;mat-icon aria-hidden="false" aria-label="Move All Left" fontIcon="keyboard_double_arrow_left"&amp;gt;&amp;lt;/mat-icon&amp;gt;
            &amp;lt;/button&amp;gt;
          &amp;lt;/mat-card-content&amp;gt;
        &amp;lt;/mat-card&amp;gt;
      &amp;lt;/ng-container&amp;gt;

      &amp;lt;!-- target-items section --&amp;gt;
      &amp;lt;ng-container target-items&amp;gt;
        &amp;lt;mat-card class="target_items"&amp;gt;
          &amp;lt;mat-card-content&amp;gt;
            &amp;lt;mat-list role="list"&amp;gt;
              @for (data of targetItems; track $index) {
              &amp;lt;mat-list-item role="listitem" class="selectable_item" [ngClass]="{selected_item: data.selected}"
                (click)="itemSelected(data)"&amp;gt;
                {{data.value}}
              &amp;lt;/mat-list-item&amp;gt;
              }
            &amp;lt;/mat-list&amp;gt;
          &amp;lt;/mat-card-content&amp;gt;
        &amp;lt;/mat-card&amp;gt;
      &amp;lt;/ng-container&amp;gt;
    &amp;lt;/app-multi-select-picker&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/main&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use consistent naming conventions for select attributes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;ngProjectAs&lt;/code&gt; supports only static values and not the dynamic expressions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We need to avoid overcomplicating component with too many slots.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find code at &lt;a href="https://github.com/dayanandaeswar/angular-multi-select-picker/tree/using-content-projection" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Please drop a comment if you have any question.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>contentprojection</category>
      <category>reusablecomponent</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Cross Field validation with Reactive Forms in Angular</title>
      <dc:creator>Dayananda</dc:creator>
      <pubDate>Thu, 31 Oct 2024 14:46:35 +0000</pubDate>
      <link>https://forem.com/dayanandaeswar/cross-field-validation-with-reactive-forms-in-angular-46oa</link>
      <guid>https://forem.com/dayanandaeswar/cross-field-validation-with-reactive-forms-in-angular-46oa</guid>
      <description>&lt;p&gt;Cross-field validation is a important aspect of form validation in Angular applications. It involves checking the relationship between multiple fields to ensure data consistency and accuracy. By implementing strong cross-field validation, we can prevent invalid data from being submitted thus improving the overall user experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing Cross-Field Validation in Angular
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Lets see how we can add dynamic validation on postal code length based on selected country in customer details page.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create custom validator&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Validator takes country field name, postal code field name and data which is holding postal code length of countries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function validatePostCodeLengh(firstControl: string, matcherControl: string, postalCodeLength: PostCodeLength[]): ValidatorFn {

  return (control: AbstractControl): ValidationErrors | null =&amp;gt; {

    const sourceValue = control.get(firstControl)?.value;
    const targetValue = control.get(matcherControl)?.value;
    if (sourceValue &amp;amp;&amp;amp; targetValue) {
      const matchedRecord = postalCodeLength.find(el =&amp;gt; el.key === sourceValue);
      if (matchedRecord?.value !== targetValue.length) {
        control.get(matcherControl)?.setErrors({ invalidLength: "Postal code length must be " + matchedRecord?.value });
      }
    }
    return null
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Create component using reactive form&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use the &lt;em&gt;FormBuilder&lt;/em&gt; service to create a reactive form. Apply custom validator to the form.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Component({
  selector: 'app-address',
  templateUrl: './address.component.html',
  styleUrl: './address.component.scss'
})
export class AddressComponent implements OnInit {

  private formBuilder = inject(FormBuilder);
  profileForm!: FormGroup;
  countries!: Country[];
  postalCodeLenght!: PostCodeLength[];
  ngOnInit(): void {
    //You get this from API
    this.countries = JSON.parse('[{"name":"United States","code":"US"},{"name":"India","code":"IN"}]');
    //You get this from API
    this.postalCodeLenght = JSON.parse('[{"value":5,"key":"US"},{"value":6,"key":"IN"}]');

    this.profileForm = this.formBuilder.group({
      firstName: ['', Validators.required],
      lastName: ['', Validators.required],
      address: this.formBuilder.group({
        country: ['', Validators.required],
        postalCode: ['', [Validators.required]],
      }, { validators: validatePostCodeLengh('country', 'postalCode', this.postalCodeLenght) }),
    });
  }

  profileFormSubmit() {
    if (this.profileForm.valid) {
      alert('Data validation is successful');
    } else {
      console.log(this.profileForm.get('address.postalCode')?.getError('invalidLength'));
      alert('Please fill all required details');
    }
  }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Create angular template&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Angular Material is used for styling purpose.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;mat-card appearance="outlined"&amp;gt;
    &amp;lt;mat-card-content&amp;gt;
        &amp;lt;form [formGroup]="profileForm" class="profile-form" (submit)="profileFormSubmit()"&amp;gt;
            &amp;lt;mat-form-field class="profile-full-width"&amp;gt;
                &amp;lt;mat-label&amp;gt;First Name&amp;lt;/mat-label&amp;gt;
                &amp;lt;input matInput placeholder="First Name" formControlName="firstName"&amp;gt;
                @if (profileForm.get('firstName')?.hasError('required')) {
                &amp;lt;mat-error&amp;gt;Required&amp;lt;/mat-error&amp;gt;
                }
            &amp;lt;/mat-form-field&amp;gt;
            &amp;lt;mat-form-field class="profile-full-width"&amp;gt;
                &amp;lt;mat-label&amp;gt;Last Name&amp;lt;/mat-label&amp;gt;
                &amp;lt;input matInput placeholder="Last Name" formControlName="lastName"&amp;gt;
                @if (profileForm.get('lastName')?.hasError('required')) {
                &amp;lt;mat-error&amp;gt;Required&amp;lt;/mat-error&amp;gt;
                }
            &amp;lt;/mat-form-field&amp;gt;
            &amp;lt;div formGroupName="address"&amp;gt;
                &amp;lt;mat-form-field class="profile-full-width"&amp;gt;
                    &amp;lt;mat-label&amp;gt;Country&amp;lt;/mat-label&amp;gt;
                    &amp;lt;mat-select formControlName="country"&amp;gt;
                        @for (country of countries; track country) {
                        &amp;lt;mat-option [value]="country.code"&amp;gt;{{country.name}}&amp;lt;/mat-option&amp;gt;
                        }

                    &amp;lt;/mat-select&amp;gt;
                    @if (profileForm.get('address.country')?.hasError('required')) {
                    &amp;lt;mat-error&amp;gt;Required&amp;lt;/mat-error&amp;gt;
                    }
                &amp;lt;/mat-form-field&amp;gt;
                &amp;lt;mat-form-field class="profile-full-width"&amp;gt;
                    &amp;lt;mat-label&amp;gt;Postal Code&amp;lt;/mat-label&amp;gt;
                    &amp;lt;input matInput placeholder="Postal Code" formControlName="postalCode"&amp;gt;
                    @if (profileForm.get('address.postalCode')?.hasError('required')) {
                    &amp;lt;mat-error&amp;gt;Required&amp;lt;/mat-error&amp;gt;
                    }
                    @if (profileForm.get('address.postalCode')?.hasError('invalidLength')) {
                    &amp;lt;mat-error&amp;gt;{{profileForm.get('address.postalCode')?.getError('invalidLength')}}&amp;lt;/mat-error&amp;gt;
                    }
                &amp;lt;/mat-form-field&amp;gt;
            &amp;lt;/div&amp;gt;
            &amp;lt;button mat-raised-button style="float: right; "&amp;gt;Submit&amp;lt;/button&amp;gt;
        &amp;lt;/form&amp;gt;
    &amp;lt;/mat-card-content&amp;gt;
&amp;lt;/mat-card&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Lets see how it works&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F517ussqr1p8cg4ruco3l.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F517ussqr1p8cg4ruco3l.gif" alt="Image description" width="600" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Considerations
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Use debounceTime and distinctUntilChanged operators to optimize real-time validation and prevent excessive API calls.&lt;/li&gt;
&lt;li&gt;Use asynchronous validators for complex checks that require external data or API calls.&lt;/li&gt;
&lt;li&gt;Provide clear and concise error messages to guide the user in correcting invalid input.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can find code at &lt;a href="https://github.com/dayanandaeswar/angular-cross-field" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Please drop a comment if you have any question.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>angularforms</category>
      <category>angularcustomvalid</category>
      <category>angularvalidation</category>
    </item>
    <item>
      <title>How to detect blocking calls in Spring Webflux</title>
      <dc:creator>Dayananda</dc:creator>
      <pubDate>Mon, 28 Oct 2024 17:27:31 +0000</pubDate>
      <link>https://forem.com/dayanandaeswar/detect-blocking-calls-using-blockhound-in-spring-webflux-51jc</link>
      <guid>https://forem.com/dayanandaeswar/detect-blocking-calls-using-blockhound-in-spring-webflux-51jc</guid>
      <description>&lt;p&gt;Spring WebFlux, a reactive framework built on Project Reactor, is a powerful tool for building non-blocking, asynchronous applications. However blocking operations can inadvertently creep in, degrading performance and responsiveness. BlockHound is a library designed to detect and potentially mitigate blocking operations in the application, making it a valuable tool for optimizing Spring WebFlux applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Understanding Blocking Operations in Reactive Systems&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In a reactive programming, blocking operations are those that halt the thread of execution until a task is completed. This can significantly impact performance, especially in high-throughput scenarios. Common blocking operations in Spring WebFlux application includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Database Access&lt;/strong&gt; Synchronous database operations will block threads, especially while using traditional JDBC or ORM frameworks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Network I/O&lt;/strong&gt; Blocking network calls, such as traditional HTTP requests, can block the thread and downgrade performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;File I/O&lt;/strong&gt; Synchronous file operations also leads to blocking the thread.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Thread sleep&lt;/strong&gt; If you have added thread sleep in your code, it will also result to blocking the thread. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;External library&lt;/strong&gt; Some of your external libraries also may add blocking nature&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;How BlockHound Works&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;BlockHound operates by instrumenting the JVM at runtime to detect blocking operations. It can be configured to either throw an exception when a blocking operation is detected. By identifying and addressing these blocking points, developers can significantly improve the performance and scalability of their Spring WebFlux applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enabling BlockHound&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt; Add maven dependency.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;io.projectreactor.tools&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;blockhound&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;MENTION_LATEST_VERSION&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt; Pass &lt;strong&gt;-XX:+AllowRedefinitionToAddDeleteMethods&lt;/strong&gt; JVM option if using Java 13+. Here i passing args through file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6j7rfb8rmsu90wlp0d9r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6j7rfb8rmsu90wlp0d9r.png" alt="Image description" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3&lt;/strong&gt; Instrument BlockHound to the application&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import reactor.blockhound.BlockHound;

@SpringBootApplication
public class WebfluxExApplication {

    static {
        BlockHound.install();
    }

    public static void main(String[] args) {
        SpringApplication.run(WebfluxExApplication.class, args);
    }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you will see an exception logged into console and request will be stopped further processing if any blocking calls present in your request flow. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Points to remember&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;It is not a code scan tool which scans and tell you where blocking call present.&lt;/em&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;It will throw exception if it find any blocking call in your request flow.&lt;/em&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;It is advised to not to deploy the code with BlockHound to production as it will result into throwing an error if blocking call is found.&lt;/em&gt; &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By understanding the potential pitfalls of blocking operations and leveraging tools like BlockHound, you can build highly responsive and efficient Spring WebFlux applications.&lt;/p&gt;

&lt;p&gt;Please leave a comment if you have any question. &lt;/p&gt;

</description>
      <category>springboot</category>
      <category>blockhound</category>
      <category>java</category>
      <category>springwebflux</category>
    </item>
    <item>
      <title>data masking and disable cut copy paste in angular using directives</title>
      <dc:creator>Dayananda</dc:creator>
      <pubDate>Wed, 23 Oct 2024 10:14:10 +0000</pubDate>
      <link>https://forem.com/dayanandaeswar/data-masking-and-disable-cut-copy-paste-in-angular-using-directives-3km3</link>
      <guid>https://forem.com/dayanandaeswar/data-masking-and-disable-cut-copy-paste-in-angular-using-directives-3km3</guid>
      <description>&lt;p&gt;Masking is a technique that is used to hide sensitive information, such as card numbers, account numbers, phone numbers, ssn etc. This can help to protect against fraud and identity theft. In addition to this we may be asked to disable the cut-copy-paste options too. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ga7l59h9fxbwce1p841.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ga7l59h9fxbwce1p841.gif" alt="Image description" width="426" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article, I will show you how to create an Angular directives that can be used to mask data and disable cut-copy-paste. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Create a disable cut-copy-paste directive&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Directive, HostListener } from '@angular/core';

@Directive({
  selector: '[ftp-disable-ccp]'
})
export class DisableCcpDirective {

  constructor() { }

  @HostListener("copy", ["$event"])
  blockCopy(e: KeyboardEvent) {
    e.preventDefault();
  }

  @HostListener("paste", ["$event"])
  blockPaste(e: KeyboardEvent) {
    e.preventDefault();
  }

  @HostListener("cut", ["$event"]) blockCut(e: KeyboardEvent) {
    e.preventDefault();
  }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2: Create data masking directive&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I am masking the except last 4 characters data with 'X'. If you want to change this behavior to particular case you can pass those as input props.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Directive, ElementRef, HostListener, Input } from '@angular/core';

@Directive({
  selector: '[ftp-masking]'
})
export class MaskingDirective {

  @Input() maskwith = "X";
  @Input() maskRegex = /.(?=.{4})/g;

  private value: string = '';

  private element!: HTMLInputElement;

  constructor(private el: ElementRef) {
    this.element = el.nativeElement;
  }

  ngonInit(): void {
    this.value = this.element.value;
  }

  @HostListener('input')
  @HostListener('change')
  onValueChange() {
    this.value = this.element.value;
  }

  @HostListener('blur')
  onBlur() {
    this.maskData()
  }

  @HostListener('focus')
  onFocus() {
    this.unmaskData();
  }

  maskData() {
    //masking the data except last 4 digits using X. 
    //You can customize this as it is input to the directive
    this.element.value = this.element.value.replace(this.maskRegex, this.maskwith);
  }
  unmaskData() {
    this.element.value = this.value;
  }

}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3: Use the Directive&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, we can use our directive in our Angular template. Please refer Account Number field&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;mat-card appearance="outlined"&amp;gt;
            &amp;lt;mat-card-content&amp;gt;
                &amp;lt;form [formGroup]="profileForm" (ngSubmit)="onSubmit()"&amp;gt;
                    &amp;lt;mat-form-field class="example-full-width"&amp;gt;
                        &amp;lt;mat-label&amp;gt;First Name&amp;lt;/mat-label&amp;gt;
                        &amp;lt;input matInput placeholder="First Name" value="" formControlName="firstName"&amp;gt;
                    &amp;lt;/mat-form-field&amp;gt;
                    &amp;lt;mat-form-field class="example-full-width"&amp;gt;
                        &amp;lt;mat-label&amp;gt;Last Name&amp;lt;/mat-label&amp;gt;
                        &amp;lt;input matInput placeholder="Last Name" value="" formControlName="lastName"&amp;gt;
                    &amp;lt;/mat-form-field&amp;gt;
                    &amp;lt;mat-form-field class="example-full-width"&amp;gt;
                        &amp;lt;mat-label&amp;gt;Account Number&amp;lt;/mat-label&amp;gt;
                        &amp;lt;input matInput placeholder="Account Number" value="" formControlName="accountNumber" ftp-disable-ccp
                            ftp-masking&amp;gt;
                    &amp;lt;/mat-form-field&amp;gt;
                    &amp;lt;button mat-raised-button [disabled]="profileForm.invalid" style="float: right; "&amp;gt;Submit&amp;lt;/button&amp;gt;
                &amp;lt;/form&amp;gt;
            &amp;lt;/mat-card-content&amp;gt;
        &amp;lt;/mat-card&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Data masking is an important security measure. By using an Angular directives, we can easily implement masking in our applications.&lt;/p&gt;

&lt;p&gt;Please leave a comment if you have any question. &lt;/p&gt;

</description>
      <category>angular</category>
      <category>directive</category>
      <category>datamasking</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Strategy Design Pattern in Spring</title>
      <dc:creator>Dayananda</dc:creator>
      <pubDate>Mon, 21 Oct 2024 11:57:27 +0000</pubDate>
      <link>https://forem.com/dayanandaeswar/strategy-design-pattern-in-spring-2l12</link>
      <guid>https://forem.com/dayanandaeswar/strategy-design-pattern-in-spring-2l12</guid>
      <description>&lt;p&gt;In enterprise applications, it is common to have different implementations to our business requirements. At run time we need to execute one of those based on conditions. Common examples are sorting algorithms, data encryption, notification services, authentication services, payment services and much more.&lt;/p&gt;

&lt;p&gt;Instead of using if-else conditions, we can use a strategy design pattern to implement it. Strategy design pattern will help us to run/use different implementations at run time. Strategy approach provides code &lt;strong&gt;reusability&lt;/strong&gt;, &lt;strong&gt;flexibility&lt;/strong&gt;, &lt;strong&gt;separation of concerns&lt;/strong&gt; and &lt;strong&gt;extensibility&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Consider you have developed a unified authentication service which will receive requests from different channels/clients. At run time, based on configuration, you need to decide the implementation used for authentication purposes (This could be request forward too). Your implementations can be okta, Azure Ad, or Your Own IAM. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; We need to implement providers as independent modules and add it to the main project as dependency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strategy Interface&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public interface Authentication {

    AuthenticationRes authentication(AuthenticationReq authenticationReq);
    OtpDevicesRes otpDevices(OtpDevicesReq otpDevicesReq);
    SendOtpRes sendOtp(SendOtpReq sendOtpReq);
    VerifyOtpRes verifyOtp(VerifyOtpReq verifyOtpReq);

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Concrete Strategies&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Component("oktaAuthentication")
@Slf4j
public class OktaAuthentication implements Authentication {
    --------------
    --------------
    --------------
}

@Component("ferAuthentication")
@Slf4j
public class FerAuthentication implements Authentication {
      --------------
      --------------
      --------------
}

@Component("eapAuthentication")
@Slf4j
public class EapAuthentication implements Authentication {
      --------------
      --------------
      --------------
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Service&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Service
@Slf4j
public class AuthenticationService {

    public Map&amp;lt;String, Authentication&amp;gt; authenticationProvidersMap;
    public Set&amp;lt;String&amp;gt; availableAuthProviders;

    public AuthenticationService(Map&amp;lt;String, Authentication&amp;gt; authenticationProvidersMap) {
        this.authenticationProvidersMap = authenticationProvidersMap;
        this.availableAuthProviders = this.authenticationProvidersMap.keySet();
        log.info("Available Auth providers:{}", this.availableAuthProviders);
    }

    public AuthenticationRes getAuthentication(AuthenticationReq authenticationReq, ClientDetails clientDetails) {

        //This method will identify authentication provider based on client details
        // and returns oktaAuthentication/eapAuthentication/ferAuthentication
        String authProvider = getAuthProviderDetails(clientDetails);

        if (this.availableAuthProviders.contains(authProvider)) {
            return this.authenticationProvidersMap.get(authProvider)
                    .authentication(authenticationReq);
        } else {
            throw new AuthProviderUnavailable(authProvider);
        }

    }


    public String getAuthProviderDetails(ClientDetails clientDetails) {
        // implement your business logic to return the provider that need to be used. 
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have any question please leave a question in comments section. &lt;/p&gt;

</description>
      <category>spring</category>
      <category>designpatterns</category>
      <category>java</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Large JSON file processing in Java</title>
      <dc:creator>Dayananda</dc:creator>
      <pubDate>Mon, 21 Oct 2024 06:33:06 +0000</pubDate>
      <link>https://forem.com/dayanandaeswar/large-json-file-processing-in-java-1fo9</link>
      <guid>https://forem.com/dayanandaeswar/large-json-file-processing-in-java-1fo9</guid>
      <description>&lt;p&gt;Efficient JSON data processing is important in modern applications. If JSON data is large in size, we need to handle it properly to avoid heap out of memory error and heavy resource consumption.&lt;/p&gt;

&lt;p&gt;GSON is one of the best library available in Java to process JSON data. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It provides thread safe instance to reuse the same object to process multiple requests. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It doesn't expect any annotations to be available to serialization and deserialization unless there is a special need.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It provides &lt;code&gt;toJson()&lt;/code&gt; and &lt;code&gt;fromJson()&lt;/code&gt; methods to serialize and deserialize.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It provides support to read the content using stream readers. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Below is the code snippet to read the file using java stream readers and convert to Java object. I am applying my business logic for every 100 records. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Assumption&lt;/strong&gt; JSON file is having array of data like below.&lt;br&gt;
&lt;code&gt;&lt;br&gt;
[&lt;br&gt;
  {&lt;br&gt;
    "id": 1,&lt;br&gt;
    "firstName": "Emily",&lt;br&gt;
    "lastName": "Johnson"&lt;br&gt;
  }&lt;br&gt;
]&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;Java Code&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private Optional&amp;lt;Boolean&amp;gt; readFile(String path) {
    try (InputStream inputStream = Files.newInputStream(Path.of(path));
         JsonReader reader = new JsonReader(new InputStreamReader(inputStream))) {
        Instant start = Instant.now();
        reader.beginArray();
        List&amp;lt;User&amp;gt; users = new ArrayList&amp;lt;&amp;gt;();
        while (reader.hasNext()) {
            users.add(gson.fromJson(reader, User.class));
            if (users.size() &amp;gt;= 100) {
                //Initiate your records processing
                //You can consider processing it in async with properly handling failure scenarios 
                users.clear();
            }
        }
        reader.endArray();
        LOGGER.info("Total time taken to process file:{}, Duration:{} (millis)", path, Duration.between(start, Instant.now()).toMillis());
    } catch (Exception e) {
        LOGGER.error("", e);
        return Optional.of(false);
    }
    return Optional.of(true);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have any question please leave a question in comments section.&lt;/p&gt;

</description>
      <category>java</category>
      <category>spring</category>
      <category>json</category>
      <category>gson</category>
    </item>
  </channel>
</rss>
