Effective Advice on Spring @Async : Final Part .


In my previous articles, I discussed the Spring Async concept and How to use it effectively. If you want to revisit,  below are the links, Also for new visitors I recommend,  please go through previous parts after reading this one.


Part 1::  How Spring Async work internally, and how to use wisely so it assigns a task to a new thread.
Part2::  How to handles Exception, If something goes wrong while executing a task.

In this part, we will discuss How Spring Async work with the web.
I am very excited to share an experience with you about Spring Async and HttpRequest, as an interesting incident happened in one of my projects, and I believe by sharing it I can save some valuable time of yours in future.
Let me try to depict the scenario in Crisp word, 
Objective: The  objective was to pass some information from UI  to a backend controller, which will do some work and eventually calls an async mail service for triggers a mail.
One of my Juniors did the following code(Try to replicate the code intention with below code snippet, not the actual code ), can you spot where the problem lies?
The Controller:: Which collect information from UI as a form  HTTP Servelet request, do some operation and pass it to async Mail service.
package com.example.demo; 

import javax.servlet.http.HttpServletRequest; 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GreetController {

@Autowired
private AsyncMailTrigger greeter;
@RequestMapping(value = "/greet", method = RequestMethod.GET)
public String greet(HttpServletRequest request) throws Exception {
String name = request.getParameter("name");
greeter.asyncGreet(request);
System.out.println(Thread.currentThread() + " Says Name is " + name);
System.out.println(Thread.currentThread().getName() + " Hashcode" + request.hashCode());
return name;
}
}
The Async Mail Service, I marked it as @Component you can easily change it to @Service. Here I have one method called asyncGreet which takes the HttpRequest, fetch the information from there and say, trigger the mail(this part is omitted for simplicity). Notice I put a Thread.sleep() here for a purpose, I will discuss the same later.
package com.example.demo;


import java.util.Map; 
import javax.servlet.http.HttpServletRequest; 
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Component
public class AsyncMailTrigger {

@Async
public void asyncGreet(HttpServletRequest request) throws Exception {
System.out.println("Trigger mail in a New Thread :: "  + Thread.currentThread().getName());
System.out.println(Thread.currentThread().getName() + " greets before sleep" + request.getParameter("name"));
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + " greets" + request.getParameter("name"));
System.out.println(Thread.currentThread().getName() + " Hashcode" + request.hashCode());
} 

}

Now the main class
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

@SpringBootApplication
@EnableAsync
public class SpringAsyncWebApplication {

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

}
If I run this program output will very similar to below
Thread[http-nio-8080-exec-1,5,main] Says Name is Shamik
http-nio-8080-exec-1 Hashcode 821691136
Trigger mail in a New Thread:: task-1
task-1 greets before sleep Shamik
task-1 greets null task-1 Hashcode 821691136

Pay attention to the output, the request has the information still before sleep but after that, it magically disappears? Strange isn't?  But It is the same request object hashcode proves the same.
What happened ? what is the reason behind the disappearance of the information from Request? That was happening to my junior, the mail recipients, recipients name disappear from the request and mail is not triggered.
Let's put Sherlock hats to investigate the problem.
It is a very common problem with the request, to understand the problem have a look, how a request lifecycle works.
The request is created by the servlet container right before the call to servlet service method, In Spring then request passes through dispatcher servlet, in the Dispatcher servlet identifies the controller by request mapping and calls the desired method in the controller, and when the request has been served, servlet container either delete the request object or reset the state of the request object. (This totally depends on the container implementation, actually it maintains a pool of request). However, I am not going to the deep dive how container maintains the request object. 
But keep one thing in mind once the request has been served and response is committed, container reset its state or destroy the request object. 
Now put Spring Async part into the consideration, What async did,  it picks one thread from the thread pool and assigns the task to it, In our case, we pass the request object to the async thread and in the asyncGreet method, we are trying to extract info directly from the request.
But as this is async our main thread (Controller part)  will be not waiting for this thread to complete, so it's print the statement and commits the response, and refresh the state of the request object.
Ironically we pass the request object directly to the async thread, still, the point where the response is not committed in the main thread, request holds the data, I explicitly put a sleep a statement  so in main thread response can be committed and refresh the request state, so after sleep we experience there is no data in the request, it vanishes, a great experiment to prove the incident.

What we will learn from this experiment?
Never pass Request object or any object related to Request/Response(headers), directly while using async you never know when your response will be committed and refresh the state If you do you will face an intermittent error.

What can be done?
If you need to pass a bunch of information from request create a value object and set the information and pass the value object to Spring Async, in this manner, you can create a concrete solution.
RequestVO Object
 package com.example.demo; 
public class RequestVO {

String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
} 

}
Async Mail service
 package com.example.demo;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Component
public class AsyncMailTrigger {

@Async
public void asyncGreet(RequestVO reqVO) throws Exception {
System.out.println("Trigger mail in a New Thread :: "  + Thread.currentThread().getName());
System.out.println(Thread.currentThread().getName() + " greets before sleep" + reqVO.getName());
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + " greets" + reqVO.getName());

} 

}
Greet Controller
package com.example.demo; 

import javax.servlet.http.HttpServletRequest; 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GreetController {

@Autowired
private AsyncMailTrigger greeter;
@RequestMapping(value = "/greet", method = RequestMethod.GET)
public String greet(HttpServletRequest request) throws Exception {
String name = request.getParameter("name");
RequestVO vo = new RequestVO();
vo.setName(name);
//greeter.asyncGreet(request);
greeter.asyncGreet(vo);
System.out.println(Thread.currentThread() + " Says Name is " + name);
System.out.println(Thread.currentThread().getName() + " Hashcode" + request.hashCode());
return name;
}
}
Output
Thread[http-nio-8080-exec-1,5,main] Says Name is Shamik
http-nio-8080-exec-1 Hashcode 1669579896
Trigger mail in a New Thread:: task-1
task-1 greets before sleep Shamik
task-1 greets Shamik

Conclusion: Hope you enjoyed the article If you have questions, please put your questions on the comment box.



Effective Advice on Spring @Async (ExceptionHandler): Part 2

In this article, I am going to discuss, how to catch Exception while you are using @Async annotation with Spring boot. Before deep diving to Exception handler I hope everyone who is reading this article, read my first part, If not I encourage you to do so, here is the link.

While you are forking thread from the main thread possibly you have two options.

1. Fire and forget :: you just fork a thread , assign some work to that thread, and just forget, at this moment,  you do not bother with the outcome as you do not need this information in order to execute next business logic, generally it's return type is void, let's understand with an example, Say you are in a process of  sending salary to the employees,  as a part of that you send an email to each employee attaching respective salary slip, and you do it asynchronously. Obviously sending salary slip via email to the employee is not a part of your core business logic, it is a cross-cutting concern, it is a good to have a feature(Some cases it is must have, then you adopt retrying, or schedule mechanism) rather than must to have.

2. Fire with Callback:: Here you fork a thread from the main thread and assign some work to that thread then attach a Callback. After that, the main thread proceeds with other tasks but the main thread keeps checking the callback for the result. The main thread needs that outcome from sub-thread as a form of callback to execute further.

Say you are preparing an Employee report,  Your software stores employee information in different backends based on the data category. , say General Service hold Employees general data (name, birthday, sex, address) and financial service holds(Salary, Tax, PF related data), so you fork two threads parallelly one for general service one for financial service, but you need both data to proceed further as in the report you need to combine both the data. So in the main thread, you want those results as a callback from subthreads, generally, we do it by CompletebleFuture(read Callable with Future).

In the above scenarios, if all is well that is the ideal case, but in the real-time exception can happen, then how you will handle Exception in the above two scenarios?

In the second scenario, It is very easy as result comes as a callback, whatever the result it is(Success or Failure), in case of failure,  Exception wrapped inside CompltebleFuture you can check the same and handle it in the main thread. Not a big deal,  basic java code. So I will skip that.

But Scenario one is tricky, you fork a thread with some business case,  how you can be sure that is a success, or if that is failure how you will debug it, how you will get a trace that something goes wrong?

The solution is very simple, You need to inject your own Exception handler so that if an exception occurs while you are executing an Async method it should pass the control to that handler and then handles what to do with that,  very Simple isn't it.

To achieve that we need to follow below steps.

1. AsyncConfigurer::  AsyncConfigurere is an Interface provided by Spring, It provides two methods one is if you want to override the TaskExecutor(Threadpool) another is an Exception handler where you can inject your exception handler so it can catch the uncaught exceptions. You can create your own class and implements that one directly. but I will not do that, as an alternative, I will use Spring  AsyncConfigurerSupport class which annotates by @Configuration and @EnableAsync, and provides a default implementation.


package com.example.ask2shamik.springAsync;

import java.lang.reflect.Method;
import java.util.concurrent.Executor;

import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.lang.Nullable;
import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
import org.springframework.scheduling.annotation.EnableAsync;



@Configuration
@EnableAsync
public class CustomConfiguration extends AsyncConfigurerSupport {
@Override
public Executor getAsyncExecutor() {
return new SimpleAsyncTaskExecutor();
}


@Override
@Nullable
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {

return (throwable, method, obj)->{
System.out.println("Exception Caught in Thread - " + Thread.currentThread().getName());
System.out.println("Exception message - " + throwable.getMessage());
System.out.println("Method name - " + method.getName());
for (Object param : obj) {
System.out.println("Parameter value - " + param);
}
};
}

}

Please note that, In case of, getAsyncExecutor method, I am not going to create any new Executor as I do not want to use my own task executor so I use Spring default SimpleAsyncExecutor.

But  I need my custom uncaught exception handler to handle any uncaught Exception so I create a lambda expression which actually extends  AsyncUncaughtExceptionHandler class and overrides handleuncaughtexception method.

In this way, I instruct Spring while loading, use my application specific AsyncConfugurer(CustomConfiguration)  and use my lambda expression as an Exception handler.



Now I create an async method which will throw an Exception.

package com.example.ask2shamik.springAsync.demo;

import java.util.Map;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Component
public class AsyncMailTrigger {

@Async
public void senMailwithException() throws Exception{
throw new Exception("SMTP Server not found :: orginated from Thread :: " + Thread.currentThread().getName());

}

}

Now, Create a caller method.
package com.example.ask2shamik.springAsync.demo;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Component
public class AsyncCaller {

@Autowired
AsyncMailTrigger asyncMailTriggerObject;

public void rightWayToCall() throws Exception {
System.out.println("Calling From rightWayToCall Thread " + Thread.currentThread().getName());
asyncMailTriggerObject.senMailwithException();

}

}

Now let's run this Application using Spring boot, to see How it catch the Exception thrown by the method sendMailwithException.

package com.example.ask2shamik.springAsync;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableAsync;

import com.example.ask2shamik.springAsync.demo.AsyncCaller;

@SpringBootApplication
public class DemoApplication {

@Autowired
AsyncCaller caller;

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

}
 @Bean
 public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
        return args -> {
        caller.rightWayToCall();
         };
    }


}

And the output is

Calling From rightWayToCall Thread main
Exception Caught in Thread - SimpleAsyncTaskExecutor-1
Exception message - SMTP Server not found:: originated from Thread:: SimpleAsyncTaskExecutor-1
Method name - senMailwithException

Conclusion: Hope you like the tutorial, If you have a question please put it in the comment box and stay tuned for part 3.

Java:: What is invokeDynamic

In my previous article, I discussed --How JVM determines which methods to call at runtime?Also, we learned that In bytecode level, java compiler uses 4 special opcodes for method invoking
invokestatic,invokeinterface,invokevirtual,invokespecial.

Now, the question arises if all types of methods invoking (interface, static method, instance method, constructor etc.) are covered by 4 opcodes, why there is another opcode invokeDynamic has been introduced?
Why invokeDynamic?
To understand why invokedymic is required let dig down to a real problem,  for a moment think you are building a framework where based on the command passed from UI you load a class runtime and invoke a particular method of that class.
Say you are building a Web framework like Struts -- Now based on the URL you have to map a java class and invoke a specific method so you will create an XML(like struts-config.xml) where developer explicitly put the strategy -- which URL map to which class and which method to be called.
Let's see the prototype of the XML.

<controller url="/employee" class="com.java.example.EmployeeController">
<param key="add" method="executeAdd">
<param key="update" method="executeUpdate">
<param key="delete" method="executeDelete">
<goto key="success"  path="/success.jsp">
<goto key="faliure"  path="/error.jsp">
</controller>
Seeing, this configuration XML one thing is clear, based on the action taken by the user in UI, different method will be called for EmployeController class, If user performs an add then internally an 'add' parameter will be passed and framework checks that which method has to call for 'add' parameter and found it is executeAdd. Until  User does not take an action no one can tell which method will be called, so all the decision has to be taken at runtime based on the parameters passed(add, edit, delete).
Think how you can design the same in java, what is the weapon available in java to implement the same, Of course, by the Reflection mechanism-- By the reflection you are able to load the Employee controller class and based on the parameter you can invoke the appropriate method.

Pseudocode will be like that.

Class controller = Class.forname("com.example.EmployeeController");
Controller empController = controller.newInstance();
Class inputParams[] = {javax.servlet.http.HttpRequest,javax.servlet.http.HttpResponse};
String methodSuffix = makeFirstLetterCapital(empController.getParam());//add to Add
Method tobeInvoked= Class.declaredMethod("execute"+methodSuffix,inputParams);
tobeInvoked.invoke(empController,request,response);
This runs very well, It will take the decision on runtime except for one problem. Reflection has huge performance penalties because it is always checking security constraints like what is the method access specifiers, is the caller has permission to call the method etc, so for this reflection is bit slow.
This is the one reason to introduce invokeDynamic in the place of reflection, it facilitates dynamic programming -- where type checking and method resolution done at runtime. So by that you can add remove methods programmatically -- You can do bytecode engineering runtime I mean, you can insert a new method which is not in the class definition !!! or override a method runtime!!! invokeDynamic provides this type of flexibility, unlike reflection.
invokeDynamic is as fast as other opcodes, but to introducing invoke dynamic in Java is not an easy task.
Java is a statically type so type checking is done at compile time also compiler checks a method is available in the class or not if the method is not available it throws compiler error so the questions is
How can we trick compiler in such a way where we can introduce a new method at runtime to be specific type checking and method resolution done at run-time?

How invokeDyamic works internally?
To work the invokeDynamic opcode correctly two important components are MethodHandle and CallSite
MethodHandle: Method handles wraps the metadata about a method-- It holds the method signature so by invoking it you can invoke a method on an Object at runtime.
CallSite : Callsite can hold Method handle and if the Call site is mutable we can change the Method handle time to time, so based on the parameter we can change the MethodHandle and as Method handle holds the method so runtime we can change the method call without altering the bytecode instruction that is invoked dynamic, so same method invocation can execute different methods based on the parameters.
Actually when the invokeDynamic instruction is read by the interpreter following procedure happens underhood--  invokedynamic instruction is associated with a special method called the bootstrap method (BSM). When the invokedynamic instruction is read by the interpreter, the BSM is invoked. It returns an object called Callsite (hold a method handle) that indicates which method actually execute.

So, Calliste works like the subline in the Train track-- Trani always runs on a straight track but when it needs to change it's direction Line Engineers are pull the liver of subline so it joins with another line according to the needs and Train just pass on that line and change the track, Calliste mimic the same methodology when based on parameter it changes the underlying method handle and same method invocation call diffrent method at runtime.
Let see the diagram,



Conclusion: invokeDynamic is a valuable inclusion in terms of framework level developer, By invokedynamic we can get the real essence of Dynamic programming in JVM, Many languages which run on JVM uses the invokedynamic to achieve dynamic type checking also Lamda uses invokedynamic, In my next tutorial I will show you how to write Callsite and MethodHandle and How you can changeMethodHandle under Callsite dynamically.




How does method dispatch happen in Java?

 Have you ever wondered when you call a method like a list.add("Shamik"), How the actual method invoke in runtime?
If you want to discover the How part then you are in the right place else you can easily skip the article as it is not related to coding perspective. we know in Java we maintain two steps process
Compiler compiles and make the bytecodes
The interpreter takes bytecode and changes the instruction to machine code.
But think, When your code compiles to bytecode how the method call looks like and in the runtime how the dynamic linking happens, In a simple word how JVM find the actual method and call that method.
In this tutorial, we will discuss the same.
In java(till Java7) we have four types of method

1. Static methods.
2. private, package private or public methods
3. Interface methods declaration.
4. Some special methods like the constructor, super etc.

Now, as the actual method call happens at runtime, somehow at compile time(bytecode) we have to instruct JVM where to find the method or location of the method. But for some cases it is not possible to tell earlier(compile time) which method will be invoked( like in case of overriding, Polymorphism) so compiler has to defer the lookup of the method until runtime, so there are different types of opcodes are used by compiler to tell JVM what to do in runtime.
At runtime, JVM maintains a runtime table called vtable where each entry represents the precise location of the method. The help of this vtable, JVM actually dispatches the call to an actual method.
opcodes
In bytecode, java uses 4 opcodes still java6 but in java7 there is a new opcode introduced called invokedynamic, I will write a separate article on invokedynamic opcode but in this article, we will discuss the other opcodes.
invokestatic: invokestatic opcode is used at compile time to dispatch static methods.
invokevirtual: invokevirtual used to dispatch instance methods.
invokespecial: invokespecial is used to dispatch special methods like constructor or super or for the private method.
invokeinterface: invokeinterface is used to dispatch a method call via an interface.
Now, we will write a java example and try to see the bytecode representation of that example.

package com.example.methodcall;

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

public class MethodCall {

public void addCity() {
List<String> city = new ArrayList<String>();
city.add("Kolkata");

}


public void addState() {
ArrayList<String> state = new ArrayList<String>();
state.add("WestBengal");

}

public static void main(String[] args) {
MethodCall target = new MethodCall();
target.addCity();
target.addState();
}

}




Now I want to see the bytecode representation of the above java program so I will run the following command 

javap -c MethodCall.class 


Bytecode will look like following

 public class com.example.methodcall.MethodCall {
  public com.example.methodcall.MethodCall();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public void addCity();
    Code:
       0: new           #15                 // class java/util/ArrayList
       3: dup
       4: invokespecial #17                 // Method java/util/ArrayList."<init>":()V
       7: astore_1
       8: aload_1
       9: ldc           #18                 // String Kolkata
      11: invokeinterface #20,  2           // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
      16: pop
      17: return

  public void addState();
    Code:
       0: new           #15                 // class java/util/ArrayList
       3: dup
       4: invokespecial #17                 // Method java/util/ArrayList."<init>":()V
       7: astore_1
       8: aload_1
       9: ldc           #31                 // String WestBengal
      11: invokevirtual #33                 // Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
      14: pop
      15: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #1                  // class com/example/methodcall/MethodCall
       3: dup
       4: invokespecial #39                 // Method "<init>":()V
       7: astore_1
       8: aload_1
       9: invokevirtual #40                 // Method addCity:()V
      12: aload_1
      13: invokevirtual #42                 // Method addState:()V
      16: return
}


Deep dive into the bytecode Representation :
In the above bytecode representation, except invokestatic all opcodes has been used.
If you noticed the bytecode minutely you can explore that for each method a section is entitled and each java line converted to a command. Let go through each method section

com.example.methodcall.MethodCall(): This is the constructor of MethodCall class, here you can find an invokespecial call because this opcode is used for calling a special method like constructor or super etc. if you pay attention to the commented line beside the invokespecial call you will find the method details
// Method java/lang/Object."<init>":() V: This says constructor can be found in java.lang.object which is detonated by a special symbol <init> and it takes nothing as an argument

 public void addCity() In this section bytecode use invokeinterface opcode for  the line
List<String> city = new ArrayList<String>();
city.add("Kolkata");
and it is commented
as

// InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z which means add is an interface method  which is in java.util.List and it takes Object as an input argument.

Here invokeInterface opcode is used because, as we did the polymorphic assignment so at the compile time there is no way to know where is the actual add method implementation, so compiler has to put such opcode which will instruct JVM to dispatch the call to exact method from Vtable at runtime, so method resolution happens at runtime.

 public void addState():
In this section bytecode use invokevirtual opcode for  the line
ArrayList<String> state = new ArrayList<String>();
state.add("WestBengal");
and it is commented as

// Method java/util/ArrayList.add:(Ljava/lang/Object;)Z which means add can be found in java.util.ArrayList and it takes Object as an input argument.

There, is very subtle difference in coding -- we use ArrayList instead of List so it is not a polymorphic assignment so it creates a huge difference in bytecode now bytecode knows the exact class where to find the add method at compile-time but still call will be dispatched in runtime as if some other class can extend ArrayList. But it uses Invokevirtual opcode which is used for calling an instance method.

public static void main(java.lang.String[]): The last section is entitled to the main method where we call two instance methods addCity and addState so it uses invokevirtual opcode.

Conclusion : In this article we have a fair bit of an idea how method call is happened using different opcodes, But in Java7 an important opcode has been added that is invokeDynamic, which opens the door to allow dynamic type language in JVM, so other languages which run on top of JVM uses this invokeDynamic opcode to make them dynamic language certain extent also Lambda Expression in Java8 uses the invokedynamic opcode, In my next tutorial I will give a detailed overview on -- invokeDynamic opcode.


Java8: Oogways more advice on Optional.

Oogway's previous talk clears the confusions about Why Optional is added on java8? But PO is a Dragon warrior he is the finest Java warrior so he wants more, He wants to know when is the right time to use Optional. What are the best practices so he again went to Oogways and I am very lucky PO called me to take the note of the talk.
Here is the Conversation.

PO: Master Oogway, I completely understood why we use Optional, the crux of the Optional is -- it gives the caller a hint that output may not be available so, design your code accordingly. So it is a Conceptual improvement which force caller to tackle maybe scenario and the outcome -- less null pointer exception. But How to use it efficiently.

Oogways: PO, Listen carefully Optional is created to check a return value is present or not, So it is the one and the only purpose you should use Optional nothing else. Optional act as a container it wraps the return value and then applies different functions on it to determine value is present or not in an advance if the value is present it can take necessary functions on it in a functional way. but whatever the case Optional must be used with method return type. Use Optional<T> as a Composition or pass it is an input is a very lame idea and should be avoided.

PO: What is the problem to pass Optional as an input suppose I have a program to search a name so if I pass the name as Optional<String> developer don't have to do the null check.
see the below program.

package com.example.optional;

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

public class OptionalTest {

private static List<String>nameList = new ArrayList<String>();

static {
nameList.add("shamik");
nameList.add("samir");
nameList.add("swastika");
}

Optional<String> findName(Optional<String> name){
return name.isPresent()?Optional.of(nameList.get(nameList.indexOf(name.get().toLowerCase()))):Optional.empty();
}

public static void main(String[] args) {
OptionalTest optionalTest = new OptionalTest();
Optional<String> searchedNameOptional = optionalTest.findName(Optional.of("Shamik"));
Optional<String> searchedNameOptionalSecond  = optionalTest.findName(Optional.ofNullable(null));
searchedNameOptional.ifPresent(System.out::println);
searchedNameOptionalSecond.ifPresent(System.out::println);
}

}

Here, I create a method called findName which takes an Optional<String >, So that developer can check if the value is present or not if present same returns an Otional<String> else returns an Empty optional, So no null check involved and passing Optional caller signal to the developer that passing parameter may be present or absent so deal accordingly. Nice way to tackle input parameters. Master then why you are telling passing an Optional in the input is a bad idea?

Oogways: PO, There is a subtle conceptual error in your thinking,
You are right Optional is used for signaling value can be present or absent, But think about who signaling to whom, here caller signaling to the author of the code, The author is the creator of the code, author is very sure about nature of method input and returns value. As he wrote the method. So here signalling is meaningless, if caller only pass the name , the author knows value may be null as default value of String is null, so he can take care of it , So here use of Optional is redundant-- here Optional means Developer of the code reminds himself passing parameter may be present or absent-- just nonsense. Optional works fine for the client of the method as the client does not know about what the method is doing inside he only knows by call findName I can get an Optional<String >, So this method may give a blank result so I need to tackle it. But the reverse perspective is just absurd. There is no need to signal developer as he controls the implementation he knows what to do with inputs, so in this case null check is better than Optional, Another thing is -- by passing an Optional you create a wrapper on a value so it takes more memory space an unnecessary complex the code violation of KISS(keep it simple stupid), Also caller has to create Optional container which is break of encapsulation. So the best way to represent your code is like that

package com.example.optional;

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

public class OptionalTest {

private static List<String>nameList = new ArrayList<String>();

static {
nameList.add("shamik");
nameList.add("samir");
nameList.add("swastika");
}

Optional<String> findName(String name){
return name !=null?Optional.of(nameList.get(nameList.indexOf(name.toLowerCase()))):Optional.empty();
}




public static void main(String[] args) {
OptionalTest optionalTest = new OptionalTest();
Optional<String> searchedNameOptional = optionalTest.findName("Shamik");
Optional<String> searchedNameOptionalSecond  = optionalTest.findName(null);
searchedNameOptional.ifPresent(System.out::println);
searchedNameOptionalSecond.ifPresent(System.out::println);
}

}

By this, Developer put the null check, Always remember Optional is not an option for replace null or apply some functional fancy methods apply on value like (filter/map) etc. The Optional is for signaling a value is present or not. So don't use it in composition or input variables for just sake for using Optional.
PO: Now, I understood the same master, Now please tell some of the operation we can do using Optional?

Oogways: Yes PO Now we are in a position where we can use some of the Optional 's utility methods.

orElse and orElseGet: Sometimes, you are sure about what would be the default value if a value is not present in that case you can use orElse on the Optional. Suppose if the name is not found we show "NA" as default value, in that case, we can change the findName method as following

package com.example.optional;

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

public class OptionalTest {

private static List<String>nameList = new ArrayList<String>();

static {
nameList.add("shamik");
nameList.add("samir");
nameList.add("swastika");
}



public String findName(String name){
return Optional.ofNullable(name).map(val->nameList.get(nameList.indexOf(val.toLowerCase()))).orElse("NA");

}





public static void main(String[] args) {
OptionalTest optionalTest = new OptionalTest();
String blankName = optionalTest.findName(null);
String name = optionalTest.findName("Shamik");
System.out.println("Name is :: " + blankName);
System.out.println("Name is :: " + name);

}

}

Here I use a map function which will check the name is in name List or not if it is not found it will return "NA" as in orElse I provide the default value as "NA".
Now, If the default value fetched from Database or from a locale based properties file then we need to write a separate method which returns the default value, in that case, we can use that separate method as a reference and pass a supplier interface in the orElseGet method. See the following example.

isPresent and ifPresent : Optional has two utility functions called isPresent and ifPresent, former returns true if a value present later takes a callback function which will apply on the value if the value is present. So when you see a code block like following

if(optional.isPresent()){
 doSomething();
}

replace the same with ifPresent

optional.ifPresent(val->doSomething())

see the below Example,

package com.example.optional;

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

public class OptionalTest {

private static List<String>nameList = new ArrayList<String>();

static {
nameList.add("shamik");
nameList.add("samir");
nameList.add("swastika");
}

Optional<String> findName(Optional<String> name){
return name.isPresent()?Optional.of(nameList.get(nameList.indexOf(name.get().toLowerCase()))):Optional.empty();
}

public static void main(String[] args) {
OptionalTest optionalTest = new OptionalTest();
Optional<String> searchedNameOptional = optionalTest.findName(Optional.of("Shamik"));
if(searchedNameOptional.isPresent()) {
System.out.println(searchedNameOptional.get());
}
searchedNameOptional.ifPresent(System.out::println);

}

}
Here, I replace isPresent with ifPresent.

flatMap: The flatmap function works same as map function, i.e change one data structure to another data structure but if the return  data structure holds an Optional it does not create a nested Optional Structure Optional<Optional<T>> it  just returns only Optiona<T>
see the example

package com.example.optional;

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

public class OptionalTest {

public void flatMapTest(String name) {
Optional<String> retName = Optional.of(name).flatMap(val->Optional.of(val));
System.out.println(retName);
}


public static void main(String[] args) {
OptionalTest optionalTest = new OptionalTest();
optionalTest.flatMapTest("Shamik");
}

}

in FlatMap fuction I delibaretly return Optional.of(val) and as flatMap returns Otional<T> it should be then Optional<Optional<String>> but it returns only
Optional<String> if we use map function we got Optional<Optional<String>>

filter: we can use filter function on Optional so we can filter the value based on some criteria

package com.example.optional;

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

public class OptionalTest {

private static List<String>nameList = new ArrayList<String>();

static {
nameList.add("shamik");
nameList.add("samir");
nameList.add("swastika");
}

Optional<String> findName(Optional<String> name){
return name.isPresent()?Optional.of(nameList.get(nameList.indexOf(name.get().toLowerCase()))):Optional.empty();
}


public static void main(String[] args) {
OptionalTest optionalTest = new OptionalTest();
Optional<String> searchedNameOptional = optionalTest.findName(Optional.of("Shamik"));
searchedNameOptional.filter(val->val.contains("am")).ifPresent(System.out::println);

}

}



PO: Master I learned all the important functions is anything still left to know about Optional?

OogWays: Yes, PO we have covered 90% but one more thing is still pending why Optional is not Serializable, I will give you the answer but I want you to think about it. Tomorrow I will give the answer if you are not able to answer it.

PO: Ok Master.