March 31, 2024

Sleep Method in Java Multi-Threading

Thread.sleep() method in Java multi-threading causes the currently executing thread to suspend execution for a specified period.

In Java Thread class there are two overloaded sleep() methods-

  1. static void sleep(long millis) throws InterruptedException- Causes the currently executing thread to sleep for the specified number of milliseconds.
  2. static void sleep(long millis, int nanos) throws InterruptedException- Causes the currently executing thread to sleep for the specified number of milliseconds plus the specified number of nanoseconds.

Important points about sleep() method in Java

  1. If the value of milliseconds is negative then IllegalArgumentException is thrown.
  2. If the value of nanoseconds is not in the range 0-999999 then IllegalArgumentException is thrown.
  3. Though you provide the duration thread is supposed to sleep as an argument in sleep method but that depends on the precision and accuracy of system timers and how schedulers are implemented in underlying OS.
  4. If thread is holding any lock, ownership of that lock is not released when thread is paused using sleep() method.
  5. A sleeping thread can also be interrupted thus terminating the sleep period.

Advantage of using sleep() method

sleep() method in Java helps in making processor time available to the other threads of an application or other applications that might be running on a computer system.

While developing your multi-threading application, using sleep() method, you can simulate some delay that may occur in production environment when your application is accessed by many users and executing many threads. That will help you to find out some of the errors that may crop up later.

Example using sleep() method

public class InterruptDemo implements Runnable {
  @Override
  public void run() {
    for(int i = 0; i < 5; i++){
      try {
        Thread.sleep(500);
      } catch (InterruptedException e) {
        System.out.println("Thread " + Thread.currentThread().getName() + " interrupted, reason " + e.getMessage());        
        throw new RuntimeException("Thread interrupted", e);
      }
    }	
  }

  public static void main(String[] args) {
    Thread t = new Thread(new InterruptDemo());
    long startTime = System.currentTimeMillis();
    t.start();
    try {
      t.join();
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
      System.out.println("Total thread pause time - " + (System.currentTimeMillis() - startTime));
  }
}
Output
Total thread pause time – 2527

As you can see loop in the run() method runs for 5 times so total sleep time would be 2500 ms but it is not that duration precisely.

That's all for the topic Sleep Method in Java Multi-Threading. If something is missing or you have something to share about the topic please write a comment.


You may also like

March 30, 2024

Daemon Thread in Java

Daemon thread in Java is a thread that runs in background to perform some tasks for the program as long as the program is running. Even if daemon threads are running that doesn’t prevent JVM from shutting down.

Features of daemon thread in Java

  1. The Java Virtual Machine exits when the only threads running are all daemon threads. So, the JVM waits only for the non-demon threads in a program to complete.

    That is why daemon threads in Java are suitable for performing general tasks like clearing the in-memory cache which may be essential to a program but not the main part of the program. Even the JVM, when it starts, creates daemon threads for garbage collection and other book keeping tasks and a non-daemon main thread for executing the program. That is also the reason why JVM doesn’t wait for daemon threads to finish as daemon thread in Java is supposed to perform some background tasks for the user threads. If user threads have completed there is no sense in executing the daemon thread.

  2. Whether a thread is daemon or not that property is inherited from the thread that spawned the other thread. Since main thread in Java is non-daemon so any thread spawned in main thread will be non-daemon.
  3. Same way any thread created by a daemon thread is automatically a daemon thread.
  4. If you want to mark a thread as either a daemon thread or a user thread that can be done using setDaemon(boolean on) method of the Thread class in Java. This method can only be called before the thread has been started i.e. before calling thread.start() method. Otherwise IllegalThreadStateException is thrown.
  5. Another method of the Thread class isDaemon() tests if thread is a daemon thread. Returns true is calling thread is a daemon thread; false otherwise.

Daemon thread Java example

In the example code there are two thread classes DaemonThread and AnotherDaemon. Initially when a DaemonThread instance is created it would be a non-daemon thread as it is created in main thread which itself is non-daemon, later it is changed to a daemon thread using setDaemon() method. On the other hand instance of AnotherDaemon would be a daemon thread as it is created in DaemonThread which is now a daemon thread.

class DaemonThread extends Thread{
  public void run() {
    // Creating another thread from a demon thread
    Thread ad = new AnotherDaemon();
    System.out.println("DaemonThread daemon -- " + isDaemon());
    System.out.println("AnotherDaemon daemon -- " + ad.isDaemon());
  }
}

class AnotherDaemon extends Thread{
  public void run() {
    System.out.println("AnotherDaemon thread run() method");
  }
}

public class TestThread {
	
  public static void main(String[] args) {
    Thread dt = new DaemonThread();
    System.out.println("DaemonThread daemon -- " + dt.isDaemon());
    // marking as daemon thread
    dt.setDaemon(true);
    dt.start();
    try {
      // delay to let the daemon thread execute, 
      // otherwise JVM exits after completing the
      // execution of the main thread.
      Thread.sleep(1000);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}
Output
DaemonThread daemon -- false
DaemonThread daemon -- true
AnotherDaemon daemon -- true

That's all for the topic Daemon Thread in Java. If something is missing or you have something to share about the topic please write a comment.


You may also like

March 29, 2024

Thread Priority in Java With Examples

In a multi-threaded environment, the order in which threads will get CPU cycle is decided by the thread scheduler and it uses thread priority to decide that order. Though that doesn’t mean that the low priority threads will never get a chance to run, that is thread priority in Java won’t lead to a deadlock but low priority threads will get fewer CPU cycles. Higher priority thread can also preempt a lower-priority thread.

Java thread priority

Every thread in Java has a priority assigned to it. When you create a thread in Java it inherits the priority of the thread that created it. You can change thread’s priority at any time after its creation using the setPriority() method of the Thread class. If you want to check the thread’s priority you can check it using getPriority() method of the Thread class.

  • setPriority(int newPriority)- Changes the priority of this thread. Here newPriority is the priority to set this thread to. If the priority is not in the range MIN_PRIORITY to MAX_PRIORITY, IllegalArgumentException is thrown.
  • getPriority()- Returns the priority of the thread that has called this method.

Java thread priority is in the range 1 to 10 where 1 being the lowest and 10 being the highest thread priority in Java.

In Java Thread class there are three static int fields defining min, max and default priority of a thread.

  • MAX_PRIORITY- The maximum priority that a thread can have. Its value is 10.
  • MIN_PRIORITY- The minimum priority that a thread can have. Value of this field is 1.
  • NORM_PRIORITY- The default priority that is assigned to a thread. Its value is 5.

Java thread priority example

Here is an example program showing the thread priorities in Java. Three threads are created here and initially the original priority of those threads is displayed using the getPriority() method then the priority is changed using the setPriority() method.

class NumThread implements Runnable{
  @Override
  public void run() {
    System.out.println("Priority of " + Thread.currentThread().getName() + " is " + Thread.currentThread().getPriority());
    for (int i = 0; i < 5; i++) {
      System.out.println(Thread.currentThread().getName() + " : " + i);
    } 
  }
}

public class ThreadPriority {
  public static void main(String[] args) {
    // Creating threads
    Thread t1 = new Thread(new NumThread(), "Thread-1");
    Thread t2 = new Thread(new NumThread(), "Thread-2");
    Thread t3 = new Thread(new NumThread(), "Thread-3");
    
    System.out.println("Original priority of Thread-1: " + t1.getPriority());
    System.out.println("Original priority of Thread-2: " + t2.getPriority());
    System.out.println("Original priority of Thread-3: " + t3.getPriority());
    // Changing thread's priority
    t1.setPriority(Thread.MIN_PRIORITY);
    t2.setPriority(3);
    t3.setPriority(Thread.MAX_PRIORITY);
    
    t1.start();
    t2.start(); 
    t3.start();
  }
}
Output
Original priority of Thread-1: 5
Original priority of Thread-2: 5
Original priority of Thread-3: 5
Priority of Thread-3 is 10
Thread-3 : 0
Thread-3 : 1
Thread-3 : 2
Thread-3 : 3
Thread-3 : 4
Priority of Thread-2 is 3
Thread-2 : 0
Thread-2 : 1
Thread-2 : 2
Thread-2 : 3
Thread-2 : 4
Priority of Thread-1 is 1
Thread-1 : 0
Thread-1 : 1
Thread-1 : 2
Thread-1 : 3
Thread-1 : 4

You can see in the output that the thread with the highest priority is executed first. But that may not always be the case and you may get different output too as the platform Java is running on is also one of the factor as that platform may have a different implementation for multi-tasking.

Thread priority is platform dependent

The platform, Java is running on may have different priority levels for threads resulting in more or less priority levels than the thread priority level in Java. In that case JVM tries to map the Java thread priority to the priority level of the OS.

That's all for the topic Thread Priority in Java With Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like

March 28, 2024

Java Stream limit() Method with Examples

limit(long maxSize) method in the Java Stream API truncates the stream so that it is no longer than maxSize in length and returns the new stream with limited elements.

limit method in Java Stream

Syntax of the method is as given below.

Stream<T> limit(long maxSize)

Here maxSize is the limit on the number of elements stream should be truncated to. If you pass maxSize as negative then IllegalArgumentException is thrown.

Points about limit method

  1. It is a short-circuiting stateful intermediate operation which means it will return a new Stream. An intermediate operation is short-circuiting if, when presented with infinite input, it may produce a finite stream as a result.
  2. limit() is generally a cheap operation on sequential stream pipelines.
  3. limit() can be quite expensive on ordered parallel pipelines, if n is a fairly large values, because of the constraint to skip first n elements in the encounter order.

limit() Java Example

1. In the following example we’ll generate 10 random numbers. Initially generate() method of the java.util.stream is called to create an infinite Stream which generates random numbers of type double. Using map operation of Stream API these random numbers are then transformed to type int and having two digits. limit() method is then used to limit the stream to 10 elements.

import java.util.stream.Stream;

public class LimitDemo {
  public static void main(String[] args) {
    Stream.generate(Math::random).map(n -> (int)(n * 100)).limit(10).forEach(System.out::println);
  }
}
Output
16
64
17
97
18
5
16
74
50
87

2. In this example we’ll try to get a sublist from a List using limit() method to truncate the original list. Method getSubList() is a generic method that can work with any type of List, second argument passed to the method is the number of elements list should be limited to. Results of the stream returned by limit() method are collected to a list and that new list is returned.

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class LimitDemo {
  public static void main(String[] args) {
    LimitDemo ld = new LimitDemo();
    // Used with list of Strings
    List<String> cityList = Arrays.asList("Delhi", "Mumbai", "London", "New York","Bengaluru");
    List<String> newList = ld.getSubList(cityList, 3);
    System.out.println("List after limiting elements- " + newList);
    // Used with list of Integers
    List<Integer> numList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    List<Integer> tempList = ld.getSubList(numList, 6);
    System.out.println("List after limiting elements- " + tempList);
  }
  
  // This method uses skip method to skip n elements
  public <T> List<T> getSubList(List<T> originalList, long maxSize){
    return originalList.stream().limit(maxSize).collect(Collectors.toList());
  }
}
Output
List after limiting elements- [Delhi, Mumbai, London]
List after limiting elements- [1, 2, 3, 4, 5, 6]

That's all for the topic Java Stream limit() Method with Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like

March 27, 2024

Java Stream - Convert a Stream to List

In this tutorial you’ll see how to convert a Stream to list using collector method and utility methods like toList() and toCollection() of Collectors class in Java Stream API.

1. A simple example to collect Stream elements into an ArrayList.

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamToList {

  public static void main(String[] args) {
    Stream<String> streamElem = Stream.of("A", "B", "C", "D");
    List<String> listFromStream = streamElem.collect(Collectors.toList());
    System.out.println(listFromStream.getClass().getName());
    System.out.println("Elements in the list- " + listFromStream);
  }
}
Output
java.util.ArrayList
Elements in the list- [A, B, C, D]

As you can see type of the List returned is ArrayList.

2. If you want to convert the Stream into a LinkedList then you can use Collectors.toCollection() method.

public class StreamToList {

  public static void main(String[] args) {
    Stream<String> streamElem = Stream.of("A", "B", "C", "D");
    List<String> listFromStream = streamElem.collect(Collectors.toCollection(LinkedList :: new));
    System.out.println(listFromStream.getClass().getName());
    System.out.println("Elements in the list- " + listFromStream);
  }
}
Output
java.util.LinkedList
Elements in the list- [A, B, C, D]

As you can see now the type of the List is LinkedList.

3. Converting Stream to List while filtering some of the elements by providing a condition. For example if you want to store only those elements in the List which are greater than 10 then you can filter other elements.

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StreamToList {
  public static void main(String[] args) {
    List<Integer> numList = Arrays.asList(6, 10, 5, 6, 7, 8, 12, 22);
    List<Integer> listFromStream = numList.stream().filter(e -> e > 10).collect(Collectors.toList());
    System.out.println("Elements in the list- " + listFromStream);
  }
}
Output
Elements in the list- [12, 22]

4. An example with custom object to store only those Students in the List who have scored more than 90.

Student class used is as follows-
public class Student {
  private int rollNo;
  private String name;
  private String stream;
  private int marks;
  Student(int rollNo, String name, String stream, int marks){
    this.rollNo = rollNo;
    this.name = name;
    this.stream = stream;
    this.marks = marks;
  }
  public int getRollNo() {
    return rollNo;
  }
  public String getName() {
    return name;
  }

  public String getStream() {
    return stream;
  }

  public int getMarks() {
    return marks;
  }

  @Override
  public String toString() {
    return "Roll Number: " +  getRollNo() 
        + " Name: " + getName() + " Marks: " + getMarks();
  }
}
public class StreamToList {
  public static void main(String[] args) {
    List<Student> studentList = Arrays.asList(new Student(1, "Mercy", "Science", 75),
              new Student(2, "Ram", "Science", 99),
              new Student(3, "Priscilla", "Art", 68),
              new Student(4, "Jacques", "Maths", 97),
              new Student(5, "Peter", "Science", 75));
    List<Student> listFromStream = studentList.stream().filter(s -> s.getMarks() > 90).collect(Collectors.toList());
    System.out.println("Elements in the list- " + listFromStream);
  }
}
Output
Elements in the list- [Roll Number: 2 Name: Ram Marks: 99, Roll Number: 4 Name: Jacques Marks: 97]

5. If you want to get only the student names in the list then you can use map method along with collect.

public class StreamToList {
  public static void main(String[] args) {
    List<Student> studentList = Arrays.asList(new Student(1, "Mercy", "Science", 75),
              new Student(2, "Ram", "Science", 99),
              new Student(3, "Priscilla", "Art", 68),
              new Student(4, "Jacques", "Maths", 97),
              new Student(5, "Peter", "Science", 75));
    List<String> listFromStream = studentList.stream().map(s -> s.getName()).collect(Collectors.toList());
    System.out.println("Elements in the list- " + listFromStream);
  }
}
Output
Elements in the list- [Mercy, Ram, Priscilla, Jacques, Peter]

That's all for the topic Java Stream - Convert a Stream to List. If something is missing or you have something to share about the topic please write a comment.


You may also like

March 26, 2024

How to Convert double to String in Java

This post shows how you can convert double to String in Java.

1. Converting double to String using Double.toString() method

Wrapper class Double in Java has a toString() method that returns a string representation of the passed double argument which can be used to convert double to String in Java.

public class DoubleToString {
	public static void main(String[] args) {
	    double num = 3785.8945d;
	    String str = Double.toString(num);
	    System.out.println("Converted String value = " + str);
	}
}
Output
Converted String value = 3785.8945

2. Convert using String.valueOf() method

String.valueOf(double d)- Returns the string representation of the double argument.

public class DoubleToString {
  public static void main(String[] args) {
    double val = -134.76d;
    String str = String.valueOf(val);
    System.out.println("Converted String value = " + str);
  }
}
Output
Converted String value = -134.76

3. Converting using String concatenation

You can concatenate the double value with an empty string ("") using + operator, that will return the result as a String.

public class DoubleToString {
	public static void main(String[] args) {
	    double val = 26.89;
	    String str = val + "";
	    System.out.println("Type of str is- " + str.getClass().getSimpleName());
	}
}
Output
Type of str is- String

4. Converting using append method of StringBuilder or StringBuffer class

Both StringBuilder and StringBuffer classes have append() method where you can pass double as an argument. The append() method will append the string representation of the double argument to the sequence.

public class DoubleToString {
  public static void main(String[] args) {
    double val = -826.89;
    StringBuilder sb = new StringBuilder();
    sb.append(val);
    System.out.println("Converted String value = " + sb.toString());
  }
}
Output
Converted String value = -826.89

That's all for the topic How to Convert double to String in Java. If something is missing or you have something to share about the topic please write a comment.


You may also like

March 25, 2024

Java throw Keyword With Examples

In the post try-catch block we have already seen some examples of exceptions but all those exceptions are thrown by Java run time. You may choose to throw an exception explicitly in your Java code, that can be done using throw statement in Java.

General form of Java throw statement

The throw statement requires a single argument; a throwable object.

throw throwableObj;

Here throwableObj must be an instance of Throwable class or any of its subclass.

How to get Throwable class instance

If you want to throw an exception explicitly you can get this Throwable class instance in two ways-

  1. You can create an instance using new operator. See example.
  2. You can use the exception parameter of the catch block and rethrow the exception. See example.

If there is a throw statement in a Java code then execution stops as soon as throw statement is encountered. Nearest catch block is checked for the matching exception type, if catch block has the matching exception type then that block handles the thrown exception. If matching exception type is not found then the next higher context is checked and so on.

Throw statement example with new exception instance

As stated above one of the way you can throw exception in your code is by creating an exception instance using new operator.

public class ThrowDemo {
  public static void main(String[] args) {
    try{
      if(args.length != 2){
        throw new IllegalArgumentException("Two parameters should be passed");
      }
    }catch(IllegalArgumentException exp){
      System.out.println("Exception in the code " + exp.getMessage());
      exp.printStackTrace();
    }
  }
}
Output
Exception in the code Two parameters should be passed
java.lang.IllegalArgumentException: Two parameters should be passed
at com.knpcode.ThrowDemo.main(ThrowDemo.java:8)

In the above code exception is thrown if 2 arguments are not passed. The constructor used while creating exception instance is the one that takes String argument. That way you can pass a clear reason why exception is thrown. There is a method getMessage() method in Exception classes that can be used to display that message.

Java throw statement example when same exception is rethrown

You can also rethrow the exception that is caught in a catch block. One of the common reason to do that is to see if there is any exception handler for that specific exception which is thrown. As example if you have a catch block with Exception as exception type it will catch most of the exceptions since Exception is higher up in the exception hierarchy . You can rethrow that exception to be caught by an exception handler with the specific exception type.

public class ExceptionDemo {
  public static void main(String[] args) {
    ExceptionDemo ed = new ExceptionDemo();
    try{
      ed.division(7, 0);
    }catch(ArithmeticException exp){
      System.out.println("Exception occurred while dividing" + exp.getMessage());
      exp.printStackTrace();
    }
  }
	
  private void division(int num1, int num2){
    double result;
    try{
      result = num1/num2;
      System.out.println("Result" + result);
    }catch(Exception exp){
      System.out.println("Exception occurred while dividing" + exp.getMessage());
      throw exp;
    }	
  }
}
Output
Exception occurred while dividing/ by zero
java.lang.ArithmeticException: / by zero
	at com.knpcode.ExceptionDemo.division(ExceptionDemo.java:18)
	at com.knpcode.ExceptionDemo.main(ExceptionDemo.java:8)
Exception occurred while dividing/ by zero
java.lang.ArithmeticException: / by zero
	at com.knpcode.ExceptionDemo.division(ExceptionDemo.java:18)
	at com.knpcode.ExceptionDemo.main(ExceptionDemo.java:8)

In the above code division method has a catch block with parameter of class Exception. From there you are rethrowing the caught exception. In the calling method it is caught again by the catch block which has parameter of type ArithmeticException.

Rethrowing a different exception

You can also catch one type of exception and rethrow exception of another type using Java throw keyword. Actually it is a best practice for exception handling to do that when you are propagating exception through separate layers. That helps in preserving loose coupling of your code.

For example, in your DB layer SQLException is caught there is no sense in letting the same exception propagate to your business layer. In this case best thing to do is catch the SQLException which is a checked exception in your DAO layer and rethrow another exception (unchecked) that should propagate to business layer. You should send the original exception instance as a parameter.

catch(SQLException ex){
  throw new RuntimeException("Error in DB layer", ex);
}

That's all for the topic Java throw Keyword With Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like

March 24, 2024

Multiple Catch Blocks in Java

If hearing the term try-catch block is giving you an idea that you can have a try block and a single associated catch block then that is a wrong idea. You can have multiple catch blocks associated with a try block. In this post we’ll see examples of multiple catch blocks in Java exception handling.

Refer Multi-Catch Exception in Java to seen another way of grouping multiple catch blocks using multi-catch statement available from Java 7.

You enclose the code that may throw an exception in try block but the enclosed code may throw more than one exception too. In order to handle these exceptions you can provide multiple catch blocks in Java. If an exception is thrown the exception handling mechanism looks for the catch block with an argument that matches the type of the exception thrown. Only the matching catch clause out of the multiple catch blocks is executed. After the matching catch block is executed, execution continues after the try-catch block.

Example of multiple catch blocks in Java

In this example program there is an array of length 3 in the method calculateValue(). Index of the array is passed as an argument to the method. Since the array has value 0 at index 1 so passing 1 as an index will result in ArithmeticException because of the division by zero.

Same way passing 4 as an index will result in ArrayIndexOutOfBoundsException as the length of array is 3. To handle these multiple exception scenarios there are multiple catch blocks associated with the try block.

public class MultipleCatch {
  private void calculateValue(int i){
    int arr[] = {6, 0, 3};
    try{
      int num = 7/arr[i];
    }catch(ArithmeticException exp){
      exp.printStackTrace();
    }catch(ArrayIndexOutOfBoundsException exp){
      exp.printStackTrace();
    }catch(Exception exp){
      exp.printStackTrace();
    }
    System.out.println("After the try-catch block");
  }

  public static void main(String[] args) {
    MultipleCatch obj = new MultipleCatch();
    obj.calculateValue(1);
    obj.calculateValue(4);
  }
}
Output
java.lang.ArithmeticException: / by zero
	at com.knpcode.MultipleCatch.calculateValue(MultipleCatch.java:7)
	at com.knpcode.MultipleCatch.main(MultipleCatch.java:21)
After the try-catch block
java.lang.ArrayIndexOutOfBoundsException: 4
	at com.knpcode.MultipleCatch.calculateValue(MultipleCatch.java:7)
	at com.knpcode.MultipleCatch.main(MultipleCatch.java:22)
After the try-catch block

Maintaining exception hierarchy in multiple catch blocks

While using multiple catch blocks in Java you will have to keep exception hierarchy in mind, which means you will have to ensure that any exception super class doesn’t come before its exception sub-classes.

This should be ensured because a catch statement having an exception super class as an argument will be able to catch exception of its type and any of its subclass too. Thus, placing a catch statement having sub-class as an argument after the catch statement with super class as argument would mean the catch statement with sub-class is unreachable. Moreover unreachable code causes compile time error in Java so you will get compilation error for any such misplaced catch statement.

In the previous example the last catch statement has Exception class object as an argument to catch any other type of exception. Since Exception class is super class of both the ArithmeticException and ArrayIndexOutOfBoundsException so placing that catch statement first will result in compile time error. Just tweak the above example and place the catch statement with Exception class object as argument before the other catch blocks.

public class MultipleCatch {
  private void calculateValue(int i){
    int arr[] = {6, 0, 3};
    try{
      int num = 7/arr[i];
    }
    catch(Exception exp){
      exp.printStackTrace();
    }catch(ArithmeticException exp){
      exp.printStackTrace();
    }catch(ArrayIndexOutOfBoundsException exp){
      exp.printStackTrace();
    }
    System.out.println("After the try-catch block");
  }

  public static void main(String[] args) {
    MultipleCatch obj = new MultipleCatch();
    obj.calculateValue(1);
    obj.calculateValue(4);
  }
}

That will result in compile time error with compiler complaining about the unreachable code.

Unresolved compilation problems: 
	Unreachable catch block for ArithmeticException. It is already handled by the catch block for Exception
	Unreachable catch block for ArrayIndexOutOfBoundsException. It is already handled by the catch block for Exception

	at com.knpcode.MultipleCatch.calculateValue(MultipleCatch.java:11)
	at com.knpcode.MultipleCatch.main(MultipleCatch.java:21)

Important points

  1. There may be multiple catch blocks after a try block.
  2. If an exception is thrown in try block the catch block with matching exception type is executed.
  3. Only one of the multiple catch blocks is executed.
  4. Multiple catch blocks must be placed in the order specific to general.

That's all for the topic Multiple Catch Blocks in Java. If something is missing or you have something to share about the topic please write a comment.


You may also like

March 23, 2024

How to Create a Deadlock in Java

If you are asked what is deadlock in Java it is almost always accompanied by the question how to create a deadlock in Java.

Deadlock in multi-threading is a scenario where two or more threads are waiting for each other to release the resources to make any further progress and blocked forever in the process.

Java program for creating deadlock

You may get deadlock in Java when you have nested synchronized blocks with reverse ordering of objects.

In the example two threads are created to run two separate runnable tasks. In each runnable task there are nested synchronized blocks acquiring object locks in reversed order thus creating a deadlock.

class ThreadA implements Runnable{
  private Object obj1;
  private Object obj2;
  ThreadA(Object obj1, Object obj2){
    this.obj1 = obj1;
    this.obj2 = obj2;
  }
  @Override
  public void run() {
    synchronized(obj1){
      System.out.println(Thread.currentThread().getName() + " acquired " + "obj1 lock");
      System.out.println(Thread.currentThread().getName() + " waiting for " + "obj2 lock");
      synchronized(obj2){
        System.out.println(Thread.currentThread().getName() + " acquired " + "obj2 lock");
      }
    }       
  }  
}
 
class ThreadB implements Runnable{
  private Object obj1;
  private Object obj2;
  ThreadB(Object obj1, Object obj2){
    this.obj1 = obj1;
    this.obj2 = obj2;
  }
  @Override
  public void run() {
    synchronized(obj2){
      System.out.println(Thread.currentThread().getName() + " acquired " + "obj2 lock");
      System.out.println(Thread.currentThread().getName() + " waiting for " + "obj1 lock");
      synchronized(obj1){
        System.out.println(Thread.currentThread().getName() + " acquired " + "obj1 lock");
      }
    }   
  }
}

public class DLDemo {
  public static void main(String[] args) {
    Object obj1 = new Object();
    Object obj2 = new Object();
    Thread t1 = new Thread(new ThreadA(obj1, obj2));
    Thread t2 = new Thread(new ThreadB(obj1, obj2));
    t1.start();
    t2.start();
  }
}
Output
Thread-0 acquired obj1 lock
Thread-0 waiting for obj2 lock
Thread-1 acquired obj2 lock
Thread-1 waiting for obj1 lock

You can see in run() method of ThreadA synchronized block acquires lock on obj1 and then tries to acquire lock on obj2. Same way in run() method of ThreadB synchronized block acquires lock on obj2 and then tries to acquire lock on obj1. This hangs the program by creating a deadlock as t1 thread is waiting to acquire lock on obj2 which is currently acquired by t2 thread and t2 thread is waiting to acquire lock on obj1 which is currently acquired by the t1 thread.

Creating deadlock by calling one synchronized method from another

Here is another example of creating deadlock in Java. It is similar to the first example here rather than having nested synchronized blocks there are two synchronized methods. The objects which are used to call the method and the object which are passed as an argument to these methods are reversed thus creating deadlock.

public class DLDemo {
  public synchronized void method1(DLDemo obj){
    System.out.println(Thread.currentThread().getName() + " In Method1");
    try {
      Thread.sleep(100);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    //Calling another synchronized method
    obj.method2(this);
  }
			  
  public synchronized void method2(DLDemo obj2){
    System.out.println("In Method2");
  }
 
  public static void main(String[] args) {
    DLDemo obj1 = new DLDemo();
    DLDemo obj2 = new DLDemo();
   
    new Thread(new Runnable() {
      public void run() { obj1.method1(obj2); }
    }).start();

    //Thread 2  
    new Thread(new Runnable() {
      public void run() { obj2.method1(obj1); }
    }).start();
  }
}
Output
Thread-0 In Method1
Thread-1 In Method1

From one thread synchronized method method1 is called using obj1 so this thread acquires a lock on obj1 then another synchronized method method2 is called using obj2.

From another thread synchronized method method1 is called using obj2 so this thread acquires a lock on obj2 then another synchronized method method2 is called using obj1.

That's all for the topic How to Create a Deadlock in Java. If something is missing or you have something to share about the topic please write a comment.


You may also like

March 22, 2024

Producer-Consumer Problem Java Program

In this post we’ll see Java program for producer-consumer problem using threads.

Producer consumer problem

Producer consumer is a classic concurrency problem where synchronization and inter thread communication is required for proper execution.

In producer-consumer problem there are two processes Producer and Consumer sharing a common bounded buffer known as queue.

  • Producer process generates data and inserts it into the shared queue.
  • Consumer process consumes data from the shared queue.

The requirement here is that Producer should not try to add data to the shared buffer if it is already full, it should rather wait for the queue to have space for new elements. Same way, Consumer should not try to consume data from an empty buffer, it should wait for data to be inserted in the queue.

Producer-consumer Java program

Since inter-thread communication is required for the proper implementation of Producer-Consumer so this program can be written using wait-notify methods.

You can also make use of the Java concurrency package where many queue implementations are added. Using ArrayBlockingQueue you can easily implement the Producer-Consumer program in Java.

Java program for Producer-consumer using wait-notify

In the Java program a shared buffer is required that is used by both producer and consumer processes for that a LinkedList instance can be used.

There also two Runnable tasks for producer and consumer which are executed by two separate threads. Once a value is added to the queue producer should notify consumer task to wake up and should go to wait state itself.

Same way consumer task should be in wait state if queue is empty.

import java.util.LinkedList;
// Producer task
class Producer implements Runnable{
  LinkedList<Integer> list;
  Producer(LinkedList<Integer> list){
    this.list = list;
  }
  @Override
  public void run() {
    for(int i = 1; i <= 5; i++){
      synchronized(list) {
        // If there is already an element in the list wait
        while(list.size() >= 1){
          System.out.println("Waiting as queue is full..");
          try {
            list.wait();
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
        System.out.println("Adding to queue- " + Thread.currentThread().getName() + " " + i);
        list.add(i);
        list.notify();    
      }
    }		
  }
}
//Consumer task
class Consumer implements Runnable{
  LinkedList<Integer> list;
  Consumer(LinkedList<Integer> list){
    this.list = list;
  }
  @Override
  public void run() {
    for(int i = 1; i <= 5; i++){
      synchronized(list) {
        // if there is no element in the list wait
        while(list.size() < 1){
          System.out.println("Waiting as queue is empty..");
          try {
            list.wait();
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
        // if there is element in the list then retrieve it
        System.out.println("Consuming from queue- " + Thread.currentThread().getName() + " " + list.remove());
        list.notify();  
      }
    }		
  }
}

public class ProducerConsumer {
  public static void main(String[] args) {
    // shared list
    LinkedList<Integer> list = new LinkedList<Integer>();
    Thread t1 = new Thread(new Producer(list), "Producer");
    Thread t2 = new Thread(new Consumer(list), "Consumer");
    t1.start();
    t2.start(); 
  }
}
Output
Adding to queue- Producer 1
Waiting as queue is full..
Consuming from queue- Consumer 1
Waiting as queue is empty..
Adding to queue- Producer 2
Waiting as queue is full..
Consuming from queue- Consumer 2
Waiting as queue is empty..
Adding to queue- Producer 3
Waiting as queue is full..
Consuming from queue- Consumer 3
Waiting as queue is empty..
Adding to queue- Producer 4
Waiting as queue is full..
Consuming from queue- Consumer 4
Waiting as queue is empty..
Adding to queue- Producer 5
Consuming from queue- Consumer 5

Java program for Producer-consumer using BlockingQueue

Using a BlockingQueue implementation like ArrayBlockingQueue you can easily implement the Producer-Consumer program in Java.

BlockingQueue has put() method for adding to the queue which blocks if the queue capacity is full. Same way there is a take() method for retrieving from the head of the queue which blocks if there is no element available.

In the code ArrayBlockingQueue of capacity 1 is created so queue will have only one element and the insertion will be blocked until that element is retrieved.

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
// Producer task
class Producer implements Runnable{
  BlockingQueue<Integer> queue;
  Producer(BlockingQueue<Integer> queue){
    this.queue = queue;
  }
  @Override
  public void run() {
    for(int i = 1; i <= 5; i++){           
      try {
        queue.put(i);
        System.out.println("Adding to queue- " + i);
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }   
    }
  }		
}
//Consumer task
class Consumer implements Runnable{
  BlockingQueue<Integer> queue;
  Consumer(BlockingQueue<Integer> queue){
    this.queue = queue;
  }
  @Override
  public void run() {
    for(int i = 1; i <= 5; i++){
      try {
        // if there is element in the list then retrieve it
        System.out.println("Consuming from queue- "  + queue.take());
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }            
  }
}

public class ProducerConsumer {
  public static void main(String[] args) {
    BlockingQueue<Integer> bQueue = new ArrayBlockingQueue<Integer>(1);
    Thread t1 = new Thread(new Producer(bQueue), "Producer");
    Thread t2 = new Thread(new Consumer(bQueue), "Consumer");
    t1.start();
    t2.start(); 
  }
}
Output
Adding to queue- 1
Consuming from queue- 1
Adding to queue- 2
Consuming from queue- 2
Adding to queue- 3
Consuming from queue- 3
Adding to queue- 4
Consuming from queue- 4
Adding to queue- 5
Consuming from queue- 5

As you can see using ArrayBlockingQueue you don’t need to write logic for synchronizing threads and call wait and notify explicitly making it very simple to write producer-consumer Java program. It can be made more compact using Lambda expression.

public class ArrayBQ {
  public static void main(String[] args) {
    // BlockingQueue of capacity 1
    BlockingQueue<Integer> bQueue = new ArrayBlockingQueue<Integer>(1);
    // Producer 
    new Thread(()->{
      for(int i = 0; i < 5; i++){
        try {
          bQueue.put(i);
          System.out.println("Added to queue-" + i);  
          
        } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
    }).start();
        
    // Consumer
    new Thread(()->{
      for(int i = 0; i < 5; i++){
        try {
          System.out.println("Consumer retrieved- " + bQueue.take());
        } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
    }).start();
  }
}

That's all for the topic Producer-Consumer Problem Java Program. If something is missing or you have something to share about the topic please write a comment.


You may also like

March 21, 2024

HashMap Internal Implementation in Java

HashMap internal implementation in Java or how does HashMap work internally in Java is a very important interview question. Some of the important points that you should know are-

  1. Where does HashMap store its elements internally?
  2. What is the term "bucket" in HashMap?
  3. What is hashing concept and how does it relate to HashMap?
  4. How does put() method work in HashMap?
  5. What happens if same hash is calculated for the keys or how are elements stored in case of hash collision?
  6. What happens if the null key is added.
  7. How does get() method work in HashMap?
  8. How does remove() method work in HashMap?

In this post we’ll go through the HashMap internal implementation in Java and try to explain the above mentioned points. Note that all the code snippet of the HashMap class provided in this post are from JDK 17.

Where does HashMap store its elements

Internally HashMap class in Java uses an Array (named table) of type Node to store its elements. Where Node<K, V> is an inner class with in HashMap class. Array is defined as follows in the HashMap class.

transient Node<K,V>[] table;
In a HashMap elements are stored as (key, value) pair and this (key, value) pair is represented by an interface Map.Entry. The Node class is an implementation of Map.Entry interface.

What is the term bucket in HashMap

When a (key, value) pair is added to a HashMap, using that key a hash is calculated which gives the index in the array where that (key, value) pair will be added.

The term bucket used here is actually each index of the array. By default HashMap array is of length 16 so there are 16 buckets in a HashMap. Since the array is named table so table[0] is bucket0, table[1] is bucket1 and so on till bucket15.

When an element is added to the HashMap it is not added to that index in the array directly. Every bucket of the HashMap has an associated linked list and each array index holds reference to that linked list. Once the bucket to which the element has to be added is decided based on the calculated hash, a new node is created in the linked list which will have the (key, value) pair.

Following image shows how buckets and stored elements in the linked list will look like in the internal implementation of HashMap.

HashMap internal implementation in Java

hashCode() and equals() method

For calculating hash, hashCode() method is called. equals() method is used to compare objects for equality.

Both of these methods are defined in the Object class in Java so available to all the classes, as Object class is super class for all the classes in Java. If you are using any custom object as key, ensure that these two methods hashCode() and equals() are implemented.

In HashMap hash is calculated using the key so it is very important that hashCode() is properly implemented for the fair distribution of the keys among all the buckets and there are less hash collisions. For example suppose you are using a custom object as key and the hashCode() implementation is not good. If you add 50 elements to the HashMap and same hash is calculated for 30 of them then the linked list associated with that bucket will have 30 elements where as other buckets will be relatively empty affecting the overall performance of HashMap.

equals() method implementation is used to verify if the inserted key is equal to any of the already inserted keys. Thus it is important to implement equals() method properly to ensure that an object is uniquely identified.

How does put() method work in HashMap

With all the groundwork done till now by going through buckets, hashing and hashCode() and equals() method it will be easy for you now to understand the internal implementation of HashMap in Java.

When you add a new (key,value) pair using put() method, first of all using key a hash will be calculated which will determine the bucket the (key, value) pair will go to.

If that bucket is empty a new linked list will be created, where first node of the linked list will be your (key, value) pair and the bucket (that array index) will hold the reference to that linked list.

If the bucket is not empty, that means linked list is already there. In that case equals() method is used to verify if such a key already exists in that bucket, if not found then a new node is created in the already existing linked list. In case equals() method returns true, that means key already exists in the bucket. In that case, the new value for the matching key will overwrite the old value.

In HashMap class implementation put() method is written as follows-

public V put(K key, V value) {
  return putVal(hash(key), key, value, false, true);
}

As you can see first thing it is doing is to calculate hash by passing key.

This explanation of put() method also covers the scenario when same hash is calculated for more than one key (Hash Collision scenario).

What happens when the null key is added

In HashMap adding one null key is permitted. When a (key, value) pair is added where key is null, hash calculation is not done and that (key, value) pair is always added to bucket 0.

You can see it from the internal implementation of the hash() method.

static final int hash(Object key) {
  int h;
  return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

How does get() method work in HashMap

In Java HashMap get() method is called with key as argument. Using that key, hash is calculated to determine the bucket where that element is stored. If the linked list associated with that bucket has more than one node then iteration of the linked list is done to match the stored keys with the passed key using equals method. When the matching key is found the associated value is returned.

In HashMap class implementation get() method is implemented as follows-

public V get(Object key) {
  Node<K,V> e;
  return (e = getNode(hash(key), key)) == null ? null : e.value;
}

How does remove() method work in HashMap

Implementation of remove() method is similar to get() method. Using the passed key, hash is calculated to determine the bucket where that element is stored. If the linked list associated with that bucket has more than one node then iteration of the linked list is done to match the stored keys with the passed key using equals method. When the matching key is found that node of the linked list is dereferenced.

HashMap changes in Java 8

HashMap implementation is designed to provide constant-time performance for the basic operations (get and put). But the performance of the HashMap may degrade if hashCode() is not properly implemented and there are lots of hash collisions.

As we have already seen in case of hash collisions one of the bucket will have more load and more (key, value) pairs will be added to the linked list associated with that bucket. For searching (get() method) in a linked list linear iteration of the linked list is done which will mean a worst case performance of O(n) if the searched key is the last node of the linked list.

To counter that problem of a particular linked list having more elements HashMap implementation is changed in Java 8. After a certain threshold is reached linked list is replaced by balanced tree to store elements. This change ensures performance of O(log(n)) in worst case scenarios rather than O(n) in the case of linked list.

That's all for the topic HashMap Internal Implementation in Java. If something is missing or you have something to share about the topic please write a comment.


You may also like

March 20, 2024

throw Vs throws in Java Exception Handling

In Java five keywords are used for exception handling namely – try, catch, finally, throw and throws. Out of these five, throw and throws keywords sound quite similar causing confusion thus the question what are the differences between throw and throws in Java exception handling.

Throw vs Throws in java

1- throws clause is used to declare an exception with in the method signature where as throw is used with in the code to actually throw an exception.

Exception declaration with in the method signature using throws
private void readFile() throws IOException {
  ....
  ....
}
Throwing exception using throw keyword
try{
  if(args.length != 2){
    throw new IllegalArgumentException("Two parameters should be passed");
  }
}

2- With throws clause multiple exceptions can be declared as a comma separated list. Where as throw can throw only a single instance of exception.

Declaring multiple exception with throws clause
private void readFile() throws FileNotFoundException, IOException, ArithmeticException {
  ....
  ....
}

3- With throws clause you can declare all the exceptions that may be thrown by your method code. You are not actually throwing an exception, just declaring them so the caller method can provide exception handling for the declared exceptions.

With throw you are actually throwing an exception that looks for the nearest catch block with the matching exception type.

4- With throws, while declaring exceptions you use the name of the exception classes itself.
With throw keyword you use an instance of the Throwable class or any of its sub-class, you don’t use the exception class itself.

With throws-
private void readFile() throws IOException
With throw
catch(IOException exp){   
 // throwing object of IOException class
 throw exp;
}
or you create an exception class object and throw it-
throw new IOException();
Class name (IOException) itself is given with the throws clause.

5- There is a restriction with throws clause that it has to be used with the method signature where as throw statement has to be part of the code where it may come anywhere inside the method, throw statement can be used with in a static block too.

Using throw with static block
static {
 try{
  ...
  ...
 }catch(Exception exp){
  System.out.println("Initialization error " + exp.getMessage());
  throw exp;
 }
}

That's all for the topic throw Vs throws in Java Exception Handling. If something is missing or you have something to share about the topic please write a comment.


You may also like

super in Java With Examples

Super keyword in Java is used to refer to the immediate parent class of the sub class. You can use super keyword in Java in following ways-

  • You can invoke the constructor of the parent class, doing that using super makes your code more compact and classes are better encapsulated. See example.
  • You can also use super keyword to access the field or method of the parent class that has been hidden by the child class. See example.

Using super to invoke constructor of super class

To see how super keyword in Java can be used to invoke constructor of the immediate parent class and how it helps in having better encapsulation and in reducing duplication of code, first let’s see a code where super is not used.

class A {
  int x;
  int y;
  public A(){
    
  }
  A(int x, int y){
    this.x = x;
    this.y = y;		
  }
}

public class B extends A{
  int z;
  public B(int x, int y, int z) {
    // x and y from parent class
    this.x = x;
    this.y = y;
    this.z = z;
  }
  public static void main(String[] args) {
    B obj = new B(5, 6, 7);
    System.out.println("x=" + obj.x + " y= "+ obj.y + " z= "+ obj.z);
  }
}
Output
x=5 y= 6 z= 7

In the code, class B extends class A. If you notice, the constructor of class B again initializes the fields it inherits from class A (x and y). Same initialization is also done in constructor of class A leading to duplication of code.

Another problem here is the fields in class A can’t be marked as private as the fields have to be accessed in the child class B that means class A is not properly encapsulated.

Using super keyword

Let’s see the same example again when super keyword is used to invoke the constructor of the parent class.

class A {
  private int x;
  private int y;
  public A(){
    
  }
  A(int x, int y){
    this.x = x;
    this.y = y;		
  }
}

public class B extends A{
  int z;
  public B(int x, int y, int z) {
    //invoking parent class constructor
    super(x, y);
    this.z = z;
  }
  public static void main(String[] args) {

  }
}

In the code you can see that the super is used to invoke the constructor of the parent class which initializes the fields in parent class. That way, x and y fields can be marked as private so class A has better encapsulation. Also the same initialization is not needed in constructor of class B so no duplication of code.

Note that call to super() must be the first statement in the subclass constructor otherwise there will be a compilation error "Constructor call must be the first statement in a constructor".

Using super to access the field and method of the parent class

Another use of super keyword in Java is to access the field or method of the parent class. In child class if you have a field or method having the same name as in the parent class then the child class member overrides the parent class member of the same name. In that case if you want to access the member of the parent class then you can use super keyword.

Example code

In the example there is a display() method in class A and again display() method in the child class B which overrides the method of the parent class. In order to display the fields of class A if you want to invoke the display method of class A, you can do it using the super keyword.

class A {
  private int x;
  private int y;
  public A(){
    
  }
  A(int x, int y){
    this.x = x;
    this.y = y;		
  }
  public void display() {
    System.out.println("In display method of super class");
    System.out.println("x= " + x + " y= " + y);
  }
}

public class B extends A{
  int z;
  public B(int x, int y, int z) {
    //invoking parent class constructor
    super(x, y);
    this.z = z;
  }
  public void display() {
    // invoking display method of parent class
    super.display();
    System.out.println("In display method of child class");
    System.out.println("z= " + z);
  }
  public static void main(String[] args) {
    B obj = new B(5, 6, 7);
    obj.display();		
  }
}
Output
In display method of super class
x= 5 y= 6
In display method of child class
z= 7

That's all for the topic super in Java With Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like

March 18, 2024

HTTP POST Method in React - fetch, Axios

In this post we'll see how to use HTTP POST method from React applications in order to create resources using API. We'll see usage of both fetch method in Fetch API and Axios with the help of examples.

  • fetch()- This method is used to call APIs across the network. GET is the default for fetch method.

    With fetch() method you pass the URI and the body in case of POST and it returns a promise that resolves with a Response object.

  • Axios- It is a promise-based HTTP Client for node.js and the browser.

For API calls JSONPlaceholder is used which is a free fake API for testing and prototyping.

POST request in React using fetch returning Promise

fetch() method takes one mandatory argument; path to the resource (API), it also accepts a second parameter, an init object that allows you to control a number of different settings. Here is the fetch method format for a POST request where you need to explicitly specify the method you are using and the object that you want to send.

fetch(url, {
    method: "POST", // *GET, POST, PUT, DELETE, etc.
    mode: "cors", // no-cors, *cors, same-origin
    cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
    credentials: "same-origin", // include, *same-origin, omit
    headers: {
      "Content-Type": "application/json",
      // 'Content-Type': 'application/x-www-form-urlencoded',
    },
    body: JSON.stringify(data), // body data type must match "Content-Type" header
  });

In our example there is a Component named AddPost. With in the component there is a form to add new post data (userId, title and body). When the form is submitted, using fetch method a POST request is sent with the post data to the given URI. JSONPlaceholder returns the added post by including id (Post ID) to it.

AddPost.js

import { useState } from "react";

const AddPost = () => {
  const [formFields, setFormFields] = useState({
    title: '',
    body: '',
    userId: ''
  });
  const handleInputChange = (event) => {
    const target = event.target;
    const value = target.value;
    const name = target.name;

    setFormFields((prevState) => {
        return {...prevState, [name]: value};
    });
  }
  const formSubmitHandler = (event) => {
    event.preventDefault();
    fetch('https://jsonplaceholder.typicode.com/posts', {
      method: 'POST',
      // adding userId as a random int between 0-99
      body: JSON.stringify({...formFields, userId:Math.floor(Math.random() * 100)}),
      headers: {                
          'Content-type': 'application/json',                 
      },
    })    
    .then((response) => response.json())
    .then((resData) => console.log('Post added with id ', resData.id))
    .catch((error) => console.log(error.message))
  }
  return(
    <div className="container">
      <h2>Post</h2>
      <form onSubmit={formSubmitHandler}>
        <div className="mb-3 mt-3">
          <label className="form-label" htmlFor="title">Title: </label>
          <input className="form-control" type="text" placeholder="Enter Title" name="title" id="title" onChange={handleInputChange}></input>
        </div>
        <div className="mb-3">
          <label className="form-label" htmlFor="body">Body: </label>
          <input className="form-control" type="text" placeholder="Enter Post Content" name="body" id="body" onChange={handleInputChange}></input>
        </div>
        <button className="btn btn-info" type="submit" onClick={formSubmitHandler}>Add Post</button>
      </form>
    </div>
  )
}

export default AddPost;

In the code-

  1. useState() hook is used to maintain form data.
  2. fetch() method is called when the form is submitted, method is set as ‘POST’ and as the body form data is sent. Note that in the form title and post body is entered, user ID is added later.
  3. Content-Type is set as application/json which means that the request body format is JSON.
  4. When you create a resource in JSONPlaceholder, inserted post object is returned by the API which includes title, body, userId and also id (post ID, which is always 101).
  5. fetch() method returns a Promise, using promise chaining first the response object is converted to JSON data and then id is extracted from the returned post data.
  6. To handle any error there is also a catch method, which just logs the error message.
  7. Note that Bootstrap 5 is used for styling here. Refer Installing Bootstrap in React to know how to install Bootstrap in your React application.
React HTTP POST example

POST request using fetch with async/await

Using async/await is easier than using Promise with .then chaining so that is the preferred way. You can use try/catch to handle errors with async/await.

import { useState } from "react";

const AddPost = () => {
  const [formFields, setFormFields] = useState({
    title: '',
    body: '',
    userId: ''
  });
  const handleInputChange = (event) => {
    const target = event.target;
    const value = target.value;
    const name = target.name;

    setFormFields((prevState) => {
      return {...prevState, [name]: value};
    });
  }
  const formSubmitHandler = async (event) => {
    event.preventDefault();
    try{
      const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
        method: 'POST',
        // adding userId as a random int between 0-99
        body: JSON.stringify({...formFields, userId:Math.floor(Math.random() * 100)}),
        headers: {                
          'Content-type': 'application/json',                 
        },
      });
  
      const responseData = await response.json();   
      if(!response.ok){
        throw new Error('Error while fetching post data');
      } 
      console.log('Post added with id ', responseData.id);
    }catch(error){
      console.log(error.message);
    }
  }
  return(
    <div className="container">
      <h2>Post</h2>
      <form onSubmit={formSubmitHandler}>
        <div className="mb-3 mt-3">
          <label className="form-label" htmlFor="title">Title: </label>
          <input className="form-control" type="text" placeholder="Enter Title" name="title" id="title" onChange={handleInputChange}></input>
        </div>
        <div className="mb-3">
          <label className="form-label" htmlFor="body">Body: </label>
          <input className="form-control" type="text" placeholder="Enter Post Content" name="body" id="body" onChange={handleInputChange}></input>
        </div>
        <button className="btn btn-info" type="submit" onClick={formSubmitHandler}>Add Post</button>
      </form>
    </div>
  )
}

export default AddPost;

Few points to note in the code-

  1. formSubmitHandler() method is async now.
  2. You need to wait for the response so await is used with the fetch method.
  3. Await is also used while converting response data to json.
  4. Check for the response status and throw an error if response status is not ok.
  5. Code is enclosed in try/catch block to handle the thrown error.

Showing error message With React fetch example

In the above React fetch method example with async/await, error message is logged to the console. If you want to display the error to the user then you can create one more component for Error. In the AddPost component have the state for Error and set the Error in case one is thrown.

You can also create a more generic Notification component that can show both success and error messages.

ErrorMessage.js

Uses the Bootstrap alert to show the error message.

const ErrorMessage = (props) => {
  return(
    <>
      <div className="alert alert-warning alert-dismissible fade show" role="alert">
        <p>{props.message}</p>
              
        <button type="button" className="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
      </div>
    </>
  )
}
export default ErrorMessage;

AddPost.js

Updated to have Error state variable and the logic to show error.

import { useState } from "react";
import ErrorMessage from "./ErrorMessage";

const AddPost = () => {
  const [formFields, setFormFields] = useState({
    title: '',
    body: '',
    userId: ''
  });
  const [error, setError] = useState();
  const handleInputChange = (event) => {
    const target = event.target;
    const value = target.value;
    const name = target.name;

    setFormFields((prevState) => {
      return {...prevState, [name]: value};
    });
  }
  const formSubmitHandler = async (event) => {
    event.preventDefault();
    try{
      const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
          method: 'POST',
          // adding userId as a random int between 0-99
          body: JSON.stringify({...formFields, userId:Math.floor(Math.random() * 100)}),
          headers: {                
              'Content-type': 'application/json',                 
          },
        });
    
        const responseData = await response.json();   
        if(!response.ok){
          throw new Error('Error while fetching post data');
        } 
        console.log('Post added with id ', responseData.id);
    }catch(error){
      setError(error);
      //console.log(error.message);
    }
  }
  if(error){
    return (
      <ErrorMessage message={error.message}></ErrorMessage>
    )
  }
  return(
    <div className="container">
      <h2>Post</h2>
      <form onSubmit={formSubmitHandler}>
        <div className="mb-3 mt-3">
          <label className="form-label" htmlFor="title">Title: </label>
          <input className="form-control" type="text" placeholder="Enter Title" name="title" id="title" onChange={handleInputChange}></input>
        </div>
        <div className="mb-3">
          <label className="form-label" htmlFor="body">Body: </label>
          <input className="form-control" type="text" placeholder="Enter Post Content" name="body" id="body" onChange={handleInputChange}></input>
        </div>
        <button className="btn btn-info" type="submit" onClick={formSubmitHandler}>Add Post</button>
      </form>
    </div>
  )
}

export default AddPost;

Using HTTP POST method in React with Axios

If you want to use Axios library to make HTTP calls then the first thing is to install the Axios library.

Using npm

$ npm install axios

Using yarn

$ yarn add axios

POST request using Axios returning Promise - React Example

import axios from "axios";
import { useState } from "react";
import ErrorMessage from "./ErrorMessage";

const AddPost = () => {
  const [formFields, setFormFields] = useState({
    title: '',
    body: '',
    userId: ''
  });
  const [error, setError] = useState();
  const handleInputChange = (event) => {
    const target = event.target;
    const value = target.value;
    const name = target.name;

    setFormFields((prevState) => {
      return {...prevState, [name]: value};
    });
  }
  const formSubmitHandler = (event) => {
    event.preventDefault();
    // adding userId as a random int between 0-99
    const data = {...formFields, userId: Math.floor(Math.random() * 100)};
    axios.post('https://jsonplaceholder.typicode.com/posts', data)
    .then(response => console.log('Post added with id ', response.data.id))
    .catch((error) => setError(error));
  }
  if(error){
    return (
      <ErrorMessage message={error.message}></ErrorMessage>
    )
  }
  return(
    <div className="container">
      <h2>Post</h2>
      <form onSubmit={formSubmitHandler}>
        <div className="mb-3 mt-3">
          <label className="form-label" htmlFor="title">Title: </label>
          <input className="form-control" type="text" placeholder="Enter Title" name="title" id="title" onChange={handleInputChange}></input>
        </div>
        <div className="mb-3">
          <label className="form-label" htmlFor="body">Body: </label>
          <input className="form-control" type="text" placeholder="Enter Post Content" name="body" id="body" onChange={handleInputChange}></input>
        </div>
        <button className="btn btn-info" type="submit" onClick={formSubmitHandler}>Add Post</button>
      </form>
    </div>
  )
}

export default AddPost;

Some points to note here-

  1. With Axios, post method automatically serializes the data to JSON format before sending it so no need to do it explicitly.
  2. Axios returns a Promise that resolves to a response object which has a data property containing the fetched data. That is why ID is extracted from response.data
    console.log('Post added with id ', response.data.id)
    
  3. With Axios default behavior is to reject every response that returns with a status code that falls out of the range of 2xx and treat it as an error.
  4. Error message gives a quick summary of the error message and the status it failed with.
  5. There is no change in ErrorMessage component. Please refer the above example to get the code for this component.

Using async/await with Axios Post - React Example

import axios from "axios";
import { useState } from "react";
import ErrorMessage from "./ErrorMessage";

const AddPost = () => {
  const [formFields, setFormFields] = useState({
    title: '',
    body: '',
    userId: ''
  });
  const [error, setError] = useState();
  const handleInputChange = (event) => {
    const target = event.target;
    const value = target.value;
    const name = target.name;

    setFormFields((prevState) => {
      return {...prevState, [name]: value};
    });
  }
  const formSubmitHandler = async (event) => {
    event.preventDefault();
    // adding userId as a random int between 0-99
    const data = {...formFields, userId: Math.floor(Math.random() * 100)};
    try{
      const response = await axios.post('https://jsonplaceholder.typicode.com/posts', data);
      console.log('Post added with id ', response.data.id);
    }catch(error) {
      setError(error)
    }
  }
  if(error){
    return (
      <ErrorMessage message={error.message}></ErrorMessage>
    )
  }
  return(
    <div className="container">
      <h2>Post</h2>
      <form onSubmit={formSubmitHandler}>
        <div className="mb-3 mt-3">
          <label className="form-label" htmlFor="title">Title: </label>
          <input className="form-control" type="text" placeholder="Enter Title" name="title" id="title" onChange={handleInputChange}></input>
        </div>
        <div className="mb-3">
          <label className="form-label" htmlFor="body">Body: </label>
          <input className="form-control" type="text" placeholder="Enter Post Content" name="body" id="body" onChange={handleInputChange}></input>
        </div>
        <button className="btn btn-info" type="submit" onClick={formSubmitHandler}>Add Post</button>
      </form>
    </div>
  )
}

export default AddPost;

That's all for the topic HTTP POST Method in React - fetch, Axios. If something is missing or you have something to share about the topic please write a comment.


You may also like