April 10, 2024

Race Condition in Java With Examples

Race condition in Java may occur in a multi-threaded language like Java when two or more threads try to access a shared resource. If all the threads are just reading a shared object that poses no problem but modifying or writing a value may lead to incorrect results because of race condition.

In a multi-threaded environment, a thread after executing few steps may be preempted by another thread. That may leave the shared data in an inconsistent state. For example take the simple task of incrementing a counter– counter++;

This simple task of incrementing a counter is actually comprised of three steps-

  1. Read the value of counter variable.
  2. Increment the value by 1.
  3. Store the value of counter variable.

If there are two threads sharing this variable then the following scenario may happen-

int counter = 0;
counter = counter + 1; // Thread 1
counter = counter + 1; // Thread 2 started before thread 1 could save the new 
                      //value of counter, so Thread 2 also got the initial value of counter as 0.
store counter value // Thread 1
store counter value // Thread 2

So you end up with the counter value as 1 rather than the correct value 2 because of the interleaving threads. That’s what race condition can do to a shared object in a multi-threaded environment.

Error scenarios because of race condition

Because of the race condition, executing thread may read a stale value of shared object which may result in any of the following scenario.

  1. If a thread has to execute some logic based on the value of the variable. Because thread may end up reading a wrong value it may not act the way it was supposed to. This scenario is known as check-then-act race condition.
  2. A thread has to read the current value, modify it and store the new value. Again because of the race condition thread may end up reading and modifying a stale value. This scenario is known as read-modify-write race condition.

Example of race condition in Java

Here is a simple example where a shared integer variable is incremented and the value is displayed. Ten threads are created and each thread increments and then displays the value of the variable. Expected behavior is that each thread should get a unique value between 1-9.

public class RaceConditionDemo {
  int counter = 0;
  public  void incrementCounter(){
    try {
      Thread.sleep(100);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    counter++;
  }
  public int getCounter(){
    return counter;
  }
  public static void main(String[] args) {
    RaceConditionDemo rc = new RaceConditionDemo();
    for(int i = 0; i < 10; i++){
      new Thread(new Runnable() {			
        @Override
        public void run() {
          rc.incrementCounter();
          System.out.println("value for " + Thread.currentThread().getName() + " - " + rc.getCounter());
        }
      }).start();
    }	
  }
}
Output
value for Thread-0 - 1
value for Thread-2 - 2
value for Thread-1 - 3
value for Thread-4 - 4
value for Thread-5 - 6
value for Thread-3 - 6
value for Thread-6 - 6
value for Thread-9 - 8
value for Thread-8 - 9
value for Thread-7 – 8

In one of the run the output came as above (note that the output may vary). As you can see Thread 5, 3 and 6 have got the same value 6, Thread 7 and 9 have also got the same value 8.

Avoiding race condition in Java

Now when you know what is race condition and seen an example too where interleaving threads read the same value of the shared object. That brings us to the question how to avoid race condition in Java.

It is clear that you need to restrict access to the critical section (code where shared resource is modified). In Java that’s what synchronized keyword does; synchronizes the access to the shared resource. Using synchronization ensures that the atomic operations are executed as a single operation without thread interference.

In the example showed above synchronizing the method call should avoid the race condition.

public class RaceConditionDemo {
  int counter = 0;
  public  void incrementCounter(){
    try {
      Thread.sleep(100);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    counter++;
  }
  public int getCounter(){
    return counter;
  }
  public static void main(String[] args) {
    RaceConditionDemo rc = new RaceConditionDemo();
    for(int i = 0; i < 10; i++){
      new Thread(new Runnable() {			
        @Override
        public void run() {
          synchronized(rc){
            rc.incrementCounter();
            System.out.println("value for " + Thread.currentThread().getName() + " - " + rc.getCounter());
          }
        }
      }).start();
    }	
  }
}
Output
value for Thread-0 - 1
value for Thread-8 - 2
value for Thread-7 - 3
value for Thread-9 - 4
value for Thread-6 - 5
value for Thread-4 - 6
value for Thread-5 - 7
value for Thread-3 - 8
value for Thread-2 - 9
value for Thread-1 – 10

As you can see now every thread gets a unique value.

That's all for the topic Race Condition 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

Deadlock in Java With Examples

In a multi-threaded environment there may come a situation when one thread is waiting for a resource that is locked by another thread, which in turn is waiting for another thread and so on until this dependency loops back to the first waiting thread. Thus all the threads are waiting for each other to release the resources to make any further progress and blocked forever in the process. This scenario is called deadlock in multi-threading.

Deadlock example

To explain deadlock in Java we can take a simple scenario of two threads Thread1 and Thread2, where Thread1 holds a lock on obj1 and waiting to acquire a lock on obj2. At the same time Thread2 has a lock on obj2 and waiting to acquire lock on obj1. Here both threads are blocked in a circular loop where Thread1 is waiting to acquire lock on obj2 and Thread2 is waiting to acquire lock on obj1 thus creating a deadlock.

Deadlock in Java

Deadlock in Java scenarios

You may get deadlock in Java because of the improper use of the synchronized keyword. Scenarios when deadlock may happen are as follows.

  1. Nested synchronized blocks with reverse ordering of objects.
  2. Calling one synchronized method from another where methods are not using the same object to synchronize.

Deadlock in Java example

First example shows the scenario when there are nested synchronized blocks with reverse ordering of objects.

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");
      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");
      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-1 acquired obj2 lock

In ThreadA’s run method synchronization is first done on obj1 and later on obj2. In ThreadB’s run method synchronization is reversed, it is first done on obj2 and later on obj1. That may result in a deadlock where t1 gets a lock on obj1 and waiting to acquire a lock on obj2. At the same time obj2 has acquired a lock on obj2 and waiting to acquired a lock on obj1.

Another deadlock Java example shows the scenario where one synchronized method is called from another.

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

In the code there are two instances of DLDemo class, one thread calls the synchronized method method1 using obj1 and another thread calls it using obj2. Which means Thread1 holds a lock on obj1 and Thread2 holds a lock on obj2.

With in the synchronized method method1 there is a call to another synchronized method method2, both of the threads are trying to call method2 with the object whose lock is held by another object thus leading to a deadlock.

How to avoid deadlock in Java

With multi-threading programming deadlock may occur and there is no language support as such to prevent deadlocks. You will have to write your code used by multiple threads carefully to avoid deadlocks. Here we’ll go through the scenarios shown above and see how deadlocks can be avoided in those scenarios.

1. As shown in the previous scenarios one of the reason for the deadlock in Java is the way locks are acquired, if you have nested synchronization then you can acquire the object locks in the same order rather than in reverse order for both threads.

Changed nested synchronization code

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");
        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(obj1){
      System.out.println(Thread.currentThread().getName() + " acquired " + "obj1 lock");
      synchronized(obj2){
        System.out.println(Thread.currentThread().getName() + " acquired " + "obj2 lock");
      }
    }   
  }
}
Output
Thread-0 acquired obj1 lock
Thread-0 acquired obj2 lock
Thread-1 acquired obj1 lock
Thread-1 acquired obj2 lock

As you can see from the output now the deadlock is avoided.

2. Using synchronized block to minimize the synchronization to the critical section code only will also help in avoiding the deadlock in Java.

In the second scenario rather than synchronizing the whole method synchronized block can be used.

public class DLDemo {
  public 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();
    }
    synchronized(this){
      //Calling another synchronized method
      obj.method2(this);
    }
  }
		  
  public void method2(DLDemo obj2){
    System.out.println("In Method2");
    synchronized(this){
      System.out.println("In Method2 synchronized block");
    } 
  }

  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();
  }
}

3- By using static synchronization in Java. If two object instances are used two threads using two separate objects can still enter a synchronized method or block with their separate object locks. Static synchronization helps in this case because the lock will be acquired at the class level then.

How to debug a deadlock in Java

Detecting a deadlock in Java is not easy, even logs may be of little help. If you observe that your multi-threaded code is not performing as well as it was then it may be due to a deadlock and best thing is to get a thread dump of the application and analyze it.

You can use jstack utility to get a thread dump by providing the pid of the Java application. That pid can be obtained by running jps command. For example, if I run the program where deadlock was created due to nested synchronization, then I can get the thread dump using following steps.

1- By using jps command I can get the pid of the Java application.

Jps

5968
7408 DLDemo
13960 Jps

2- Run the jstack command with the pid as argument.

Jstack 7408

3- Get the thread dump and analyze it. Here some of the relevant portion of the thread dump is displayed.

"Thread-1" #11 prio=5 os_prio=0 tid=0x000000001b3e1000 nid=0x145c waiting for monitor entry [0x000000001bade000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.knpcode.ThreadB.run(DLDemo.java:33)
        - waiting to lock <0x00000000d5bfaff0> (a java.lang.Object)
        - locked <0x00000000d5bfb000> (a java.lang.Object)
        at java.lang.Thread.run(Unknown Source)

"Thread-0" #10 prio=5 os_prio=0 tid=0x000000001b3e0000 nid=0x379c waiting for monitor entry [0x000000001b9de000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.knpcode.ThreadA.run(DLDemo.java:15)
        - waiting to lock <0x00000000d5bfb000> (a java.lang.Object)
        - locked <0x00000000d5bfaff0> (a java.lang.Object)
        at java.lang.Thread.run(Unknown Source)



"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x0000000004d4c800 nid=0x2b34 in Object.wait() [0x000000001acee000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000000d5b88ec0> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(Unknown Source)
        - locked <0x00000000d5b88ec0> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(Unknown Source)
        at java.lang.ref.Finalizer$FinalizerThread.run(Unknown Source)

"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x0000000004d42000 nid=0x6cc in Object.wait() [0x000000001abef000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000000d5b86b68> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Unknown Source)
        at java.lang.ref.Reference.tryHandlePending(Unknown Source)
        - locked <0x00000000d5b86b68> (a java.lang.ref.Reference$Lock)
        at java.lang.ref.Reference$ReferenceHandler.run(Unknown Source)


Found one Java-level deadlock:
=============================
"Thread-1":
  waiting to lock monitor 0x0000000004d47868 (object 0x00000000d5bfaff0, a java.lang.Object),
  which is held by "Thread-0"
"Thread-0":
  waiting to lock monitor 0x0000000004d4a0f8 (object 0x00000000d5bfb000, a java.lang.Object),
  which is held by "Thread-1"

Java stack information for the threads listed above:
===================================================
"Thread-1":
        at com.knpcode.ThreadB.run(DLDemo.java:33)
        - waiting to lock <0x00000000d5bfaff0> (a java.lang.Object)
        - locked <0x00000000d5bfb000> (a java.lang.Object)
        at java.lang.Thread.run(Unknown Source)
"Thread-0":
        at com.knpcode.ThreadA.run(DLDemo.java:15)
        - waiting to lock <0x00000000d5bfb000> (a java.lang.Object)
        - locked <0x00000000d5bfaff0> (a java.lang.Object)
        at java.lang.Thread.run(Unknown Source)

Found 1 deadlock.

That's all for the topic Deadlock 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

April 9, 2024

HTTP PUT Method in React - fetch, Axios

In this post we'll see how to use HTTP PUT method from React applications in order to update resources on a server. We'll see how to make PUT requests using 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 PUT and it returns a promise that resolves with a Response object.

Fetch syntax for PUT method

fetch('url', {
  method: 'PUT',
  body: JSON.stringify(DATA),
  headers: {                
    'Content-type': 'application/json',                 
  },
}) 
.then(response => response.json())
.then(data => console.log(data))
.catch((error) => console.log(error.message));

Axios- It is a promise-based HTTP Client for node.js and the browser. To make a PUT request using Axios, you can use the axios.put() method.

axios.post(url[, data[, config]])

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

PUT request in React with fetch returning Promise

In the example there is a Component named UpdatePost. With in the component there is a form to fill post data (id, userId, title and body) to update an existing post. When the form is submitted, using fetch method a PUT request is sent with the post data to the given URI (Where postId is added to the URI 'https://jsonplaceholder.typicode.com/posts/:id'). JSONPlaceholder returns the updated post.

UpdatePost.js

import { useState } from "react";

const UpdatePost = () => {
  const [formFields, setFormFields] = useState({
    id: 0,
    title: '',
    body: '',
    userId: 0
  });
  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();
    const url = 'https://jsonplaceholder.typicode.com/posts/' + formFields.id;
    const putOptions = {
      method: 'PUT',
      body: JSON.stringify({...formFields}),
      headers: {'Content-type': 'application/json'}
    }
    fetch(url, putOptions)    
    .then((response) => response.json())
    .then((resData) => console.log('Updated Post ', resData))
    .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="id">ID: </label>
          <input className="form-control" type="text" placeholder="Enter ID" name="id" id="id" onChange={handleInputChange}></input>
        </div>
        <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>
        <div className="mb-3">
          <label className="form-label" htmlFor="userId">User ID: </label>
          <input className="form-control" type="text" placeholder="Enter UserID" name="userId" id="userId" onChange={handleInputChange}></input>
        </div>
        <button className="btn btn-info" type="submit" onClick={formSubmitHandler}>Update Post</button>
      </form>
    </div>
  )
}

export default UpdatePost;

In the code-

  1. useState() hook is used to maintain form data.
  2. fetch() methos is called when the form is submitted, method is set as ‘PUT and as the body form data is sent (Which is the modified data for an existing post).
  3. Content-Type is set as application/json which means that the request body format is JSON.
  4. When you update a resource in JSONPlaceholder, updated post object is returned by the API.
  5. fetch() method returns a Promise, using promise chaining first the response object is converted to JSON data and then that is displayed on the console.
  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 Bootstrap with React to know how to install Bootstrap in your React application.
PUT request React example

PUT request using async/await with fetch

Here is the same example which uses async/await to wait for completion of PUT request rather than using Promise with .then chaining. You can use try/catch to handle errors with async/await.

import { useState } from "react";

const UpdatePost = () => {
  const [formFields, setFormFields] = useState({
    id: 0,
    title: '',
    body: '',
    userId: 0
  });
  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 url = 'https://jsonplaceholder.typicode.com/posts/' + formFields.id;
      const putOptions = {
        method: 'PUT',
        body: JSON.stringify({...formFields}),
        headers: {'Content-type': 'application/json'}
      }
      const response = await fetch(url, putOptions);
      if(!response.ok){
        throw new Error('Error while fetching post data');
      } 
      const resData = await response.json(); 
      console.log('Updated Post ', resData)
    }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="id">ID: </label>
          <input className="form-control" type="text" placeholder="Enter ID" name="id" id="id" onChange={handleInputChange}></input>
        </div>
        <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>
        <div className="mb-3">
          <label className="form-label" htmlFor="userId">User ID: </label>
          <input className="form-control" type="text" placeholder="Enter UserID" name="userId" id="userId" onChange={handleInputChange}></input>
        </div>
        <button className="btn btn-info" type="submit" onClick={formSubmitHandler}>Update Post</button>
      </form>
    </div>
  )
}

export default UpdatePost;

Few points to note in the code-

  1. formSubmitHandler method is async.
  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.

PUT request using async/await with error message

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 UpdatePost component have the state for Error and set the Error in case one is thrown.

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;

UpdatePost.js

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

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

const UpdatePost = () => {
  const [formFields, setFormFields] = useState({
    id: 0,
    title: '',
    body: '',
    userId: 0
  });
  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 url = 'https://jsonplaceholder.typicode.com/post/' + formFields.id;
      const putOptions = {
        method: 'PUT',
        body: JSON.stringify({...formFields}),
        headers: {'Content-type': 'application/json'}
      }
      const response = await fetch(url, putOptions);
      if(!response.ok){
        throw new Error('Error while fetching post data');
      } 
      const resData = await response.json(); 
      console.log('Updated Post ', resData)
    }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="id">ID: </label>
          <input className="form-control" type="text" placeholder="Enter ID" name="id" id="id" onChange={handleInputChange}></input>
        </div>
        <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>
        <div className="mb-3">
          <label className="form-label" htmlFor="userId">User ID: </label>
          <input className="form-control" type="text" placeholder="Enter UserID" name="userId" id="userId" onChange={handleInputChange}></input>
        </div>
        <button className="btn btn-info" type="submit" onClick={formSubmitHandler}>Update Post</button>
      </form>
    </div>
  )
}

export default UpdatePost;

Now in case something goes wrong while updating an existing post you'll get an error message.

PUT Method in React - fetch, Axios

Using HTTP PUT 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

Put request using Axios returning Promise - React Example

Uses the same example as used with fetch where we have a Component named UpdatePost. With in the component there is a form to fill post data (id, userId, title and body) to update an existing post. When the form is submitted, using axios a PUT request is sent with the post data to the given URI (Where postId is added to the URI 'https://jsonplaceholder.typicode.com/posts/:id'). JSONPlaceholder returns the updated post.

Axios serializes JavaScript objects to JSON by default so no need to explicitly do it when using Axios.

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

const UpdatePost = () => {
  const [formFields, setFormFields] = useState({
    id: 0,
    title: '',
    body: '',
    userId: 0
  });

  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();
    const url = 'https://jsonplaceholder.typicode.com/post/' + formFields.id;
    axios.put(url, formFields)
    .then(resData => console.log('Updated Post ', resData.data))
    .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="id">ID: </label>
          <input className="form-control" type="text" placeholder="Enter ID" name="id" id="id" onChange={handleInputChange}></input>
        </div>
        <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>
        <div className="mb-3">
          <label className="form-label" htmlFor="userId">User ID: </label>
          <input className="form-control" type="text" placeholder="Enter UserID" name="userId" id="userId" onChange={handleInputChange}></input>
        </div>
        <button className="btn btn-info" type="submit" onClick={formSubmitHandler}>Update Post</button>
      </form>
    </div>
  )
}

export default UpdatePost;

Some points to note here-

  1. Axios returns a Promise that resolves to a response object which has a data property containing the fetched data.
  2. 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.
  3. Error message gives a quick summary of the error message and the status it failed with.
  4. There is no change in ErrorMessage component. Please refer the above example to get the code for ErrorMessage component.

Using async/await with Axios PUT request - React Example

Here is the same example which uses async/await rather than using Promise with .then chaining. You can use try/catch to handle errors with async/await.

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

const UpdatePost = () => {
  const [formFields, setFormFields] = useState({
    id: 0,
    title: '',
    body: '',
    userId: 0
  });

  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 url = 'https://jsonplaceholder.typicode.com/posts/' + formFields.id;
      const resData = await axios.put(url, formFields)
      console.log('Updated Post ', resData.data)
    }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="id">ID: </label>
          <input className="form-control" type="text" placeholder="Enter ID" name="id" id="id" onChange={handleInputChange}></input>
        </div>
        <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>
        <div className="mb-3">
          <label className="form-label" htmlFor="userId">User ID: </label>
          <input className="form-control" type="text" placeholder="Enter UserID" name="userId" id="userId" onChange={handleInputChange}></input>
        </div>
        <button className="btn btn-info" type="submit" onClick={formSubmitHandler}>Update Post</button>
      </form>
    </div>
  )
}

export default UpdatePost;

That's all for the topic HTTP PUT 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

April 8, 2024

Can we Override start() Method in Java

In some Java interviews there is a question asked can we override start() method in Java. Since this is something you will hardly need to do, so some people do get confused that is it actually possible to override start() method of Thread class or not. Also there is a follow up question will your overridden start() method actually execute the thread and call the run() method or not.

Overriding start method in Java

Yes it is possible to override start() method of the Thread class in Java. Though it is hardly required to do that except for some rare scenarios where you do need some logic to be executed before calling the run() method.

From your overridden start() method ensure that you call super.start() method as Thread class’ start() method is a native method and has the logic to communicate with the OS to schedule the thread to run. Failing to call super.start() will mean run() method won’t be called.

Overriding start method example code

public class MyThread extends Thread {
  @Override
  public void start(){
    System.out.println("In overridden start method");
    // calling parent class start method
    super.start();
  }

  @Override
  public void run() {
    System.out.println("In run method " + "Thread Name - " 
        + Thread.currentThread().getName());
  }

  public static void main(String[] args) {
    Thread t1 = new MyThread();
    t1.start();
  }
}
Output
In overridden start method
In run method Thread Name - Thread-0

That's all for the topic Can we Override start() Method in Java. If something is missing or you have something to share about the topic please write a comment.


You may also like

April 7, 2024

Thread Interruption in Java

Thread interrupt is an indication to a thread that it should stop doing what it is currently doing and either terminate or do something else. What a thread does after being interrupted is up to you but the convention is that a thread should be terminated once interrupted.

How thread interruption in Java works

In Java Thread class there is a method interrupt() which interrupts the calling thread. Once the thread is interrupted its interrupt status is set to true and then based on whether the thread is currently blocked or not following activity takes place-

  1. If this thread is blocked in an invocation of the wait(), wait(long), or wait(long, int) methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long, int), methods of this class, then its interrupt status will be cleared (set to false again) and it will receive an InterruptedException.
  2. If this thread is blocked in an I/O operation upon an InterruptibleChannel then the channel will be closed, the thread's interrupt status will be set, and the thread will receive a ClosedByInterruptException.
  3. If this thread is blocked in a Selector then the thread's interrupt status will be set and it will return immediately from the selection operation, possibly with a non-zero value, just as if the selector's wakeup method were invoked.
  4. If a thread that is not blocked is interrupted, then the thread's interrupt status will be set.

Methods related to thread interruption in Java Thread class

Apart from the method interrupt() already discussed above there are two more methods in java.lang.Thread class related to thread interruption interrupted() and isInterrupted().

  • void interrupt()- Interrupts this thread.
  • static boolean interrupted()- Checks whether the current thread has been interrupted. Also clears the interrupted status of the thread.
  • boolean isInterrupted()- Tests whether this thread has been interrupted. This method doesn't change the interrupted status of the thread in any way.

Thread interruption examples

Thread interruption in Java is generally used to terminate a blocking thread. So you can choose to just return after interrupting a sleeping or waiting thread.

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

  public static void main(String[] args) {
    Thread t = new Thread(new InterruptDemo());
    t.start();
    t.interrupt();
    System.out.println("In main method - Interrupted status " + t.isInterrupted());
  }
}
Output
In main method - Interrupted status true
Value - 0
Thread Thread-0 interrupted, reason sleep interrupted
Interrupted status- false

In the thread’s run method there is a loop to print number from 1 to 5, after each number display, sleep method is called on the thread. Thread’s interrupt method is also called in the mean time which interrupts the blocked thread. Also you can see that the interrupt status is true after the interrupt() method is called and later the interrupt status is cleared (set to false).

Wrapping and rethrowing the InterruptedException

Rather than just returning as done in the previous example you may choose to wrap the InterruptedException and rethrow it.

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

  public static void main(String[] args) {
    Thread t = new Thread(new InterruptDemo());
    t.start();
    t.interrupt();
    System.out.println("In main method - Interrupted status " + t.isInterrupted());
  }
}
Output
In main method - Interrupted status true
Value - 0
Thread Thread-0 interrupted, reason sleep interrupted
Interrupted status- false
Exception in thread "Thread-0" java.lang.RuntimeException: Thread interrupted
	at com.knpcode.InterruptDemo.run(InterruptDemo.java:14)
	at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at com.knpcode.InterruptDemo.run(InterruptDemo.java:10)
	... 1 more

Interrupting a non-blocking thread

If you interrupt a thread that is not blocking then just the interrupt status of the thread changes. Using the isInterrupted() method you can check the interrupt status of the thread and choose to execute some logic in that condition.

public class InterruptDemo implements Runnable {
  @Override
  public void run() {
    for(int i = 0; i < 5; i++){
      System.out.println("Value - " + i);
      if(Thread.currentThread().isInterrupted()){
        System.out.println("Interrupted status- " + Thread.currentThread().isInterrupted());
      }
    }	
  }

  public static void main(String[] args) {
    Thread t = new Thread(new InterruptDemo());
    t.start();
    t.interrupt();
    System.out.println("In main method - Interrupted status " + t.isInterrupted());
  }
}
Output
In main method - Interrupted status true
Value - 0
Interrupted status- true
Value - 1
Interrupted status- true
Value - 2
Interrupted status- true
Value - 3
Interrupted status- true
Value - 4
Interrupted status- true

As you can see in this case interrupt status remains true, not cleared to false as happens for the blocked threads which are interrupted.

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


You may also like

April 4, 2024

How to Read Delimited File in Java

If you have to read delimited file in Java and parse it then you can do it using the following two ways-

  1. Using Scanner class with useDelimiter() method.
  2. Read file using BufferedReader line by line and then split each line using split() method.

1. Using Scanner class to read delimited file in Java

A Scanner breaks its input into tokens using a delimiter pattern, which by default matches white space. The scanner can also use delimiters other than white space for that useDelimiter() method is used. Let’s see some examples of using Scanner class to read delimited file in Java.

Reading CSV file using Scanner in Java

Here is an example CSV file which denotes Account From, Account To and Amount Transferred.

1001,1003,2000
1006,2004,3000
1005,1007,10000

Which you want to read using Scanner class and parse it to display the fields.

import java.io.File;
import java.io.IOException;
import java.util.Scanner;

public class ReadDelimited {
  public static void main(String[] args) {
    Scanner sc = null;
    try {
      sc = new Scanner(new File("D:\\acct.csv"));

      // Check if there is another line of input
      while(sc.hasNextLine()){
        String str = sc.nextLine();
        // parse each line using delimiter
        parseData(str);
      }
    } catch (IOException  exp) {
      // TODO Auto-generated catch block
      exp.printStackTrace();
    }finally{
      if(sc != null)
        sc.close();
    }	  		
  }
	
  private static void parseData(String str){	
    String acctFrom, acctTo, amount;
    Scanner lineScanner = new Scanner(str);
    lineScanner.useDelimiter(",");
    while(lineScanner.hasNext()){
      acctFrom = lineScanner.next();
      acctTo = lineScanner.next();
      amount = lineScanner.next();
      System.out.println("Account From- " + acctFrom + " Account To- " + acctTo + 
       " Amount- " + amount);  
    }
    lineScanner.close();
  }
}
Output
Account From- 1001 Account To- 1003 Amount- 2000
Account From- 1006 Account To- 2004 Amount- 3000
Account From- 1005 Account To- 1007 Amount- 10000

Reading pipe (|) delimited file in Java using Scanner

Here is another example Java program showing how you can read pipe delimited data using Scanner in Java.

1001|1003|2000
1006|2004|3000
1005|1007|10000

import java.io.File;
import java.io.IOException;
import java.util.Scanner;

public class ReadDelimited {
  public static void main(String[] args) {
    Scanner sc = null;
    try {
      sc = new Scanner( new File("D:\\test.txt"));
      
      // Check if there is another line of input
      while(sc.hasNextLine()){
        String str = sc.nextLine();
        // parse each line using delimiter
        parseData(str);
      }
     
    } catch (IOException  exp) {
      // TODO Auto-generated catch block
      exp.printStackTrace();
    }finally{
      if(sc != null)
        sc.close();
    }	  		
  }
	
  private static void parseData(String str){	
    String acctFrom, acctTo, amount;
    Scanner lineScanner = new Scanner(str);
    lineScanner.useDelimiter("\\|");
    while(lineScanner.hasNext()){
      acctFrom = lineScanner.next();
      acctTo = lineScanner.next();
      amount = lineScanner.next();
      System.out.println("Account From- " + acctFrom + " Account To- " + acctTo + 
         " Amount- " + amount);  
    }
    lineScanner.close();
  }
}
Output
Account From- 1001 Account To- 1003 Amount- 2000
Account From- 1006 Account To- 2004 Amount- 3000
Account From- 1005 Account To- 1007 Amount- 10000

Since pipe symbol is a reserved character you do need to escape it, that is why lineScanner.useDelimiter("\\|"); is used.

2. Using split() method to split delimited data

Another way to read delimited file in Java is to read file line by line, you can use BufferedReader to read the file and then split delimited data using split method. If we take the same pipe delimited file as used above then the Java example is as follows.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class ReadDelimited {
  public static void main(String[] args) {
    BufferedReader br = null;
    try{
      String strLine;
      //FileReader instance wrapped in a BufferedReader
      br = new BufferedReader(new FileReader("D:\\test.txt"));
       
      while((strLine = br.readLine()) != null){
        parseData(strLine);
      }
    }catch(IOException exp){
      System.out.println("Error while reading file " + exp.getMessage());
    }finally {
      try {
        // Close the stream
        if(br != null){
          br.close();
        }
      } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }  		
  }
	
  private static void parseData(String str){	
    String acctFrom, acctTo, amount;
    // parsing using split method
    String[] data = str.split("\\|");
    System.out.println("Account From- " + data[0] + " Account To- " + data[1] + 
         " Amount- " + data[2]);  
  }
}
Output
Account From- 1001 Account To- 1003 Amount- 2000
Account From- 1006 Account To- 2004 Amount- 3000
Account From- 1005 Account To- 1007 Amount- 10000

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


You may also like

April 3, 2024

How to Create And Start Thread in Java

In order to create a thread in Java you need to get an instance of java.lang.Thread class. You can do it in two ways.

  1. By implementing Runnable interface.
  2. By Extending Thread class.

Whichever of these two ways is chosen by you to create a thread in Java you need to override run() method and provide the code that will run in that thread. Thread’s run() method will be executed once you call start() method on the created thread.

Creating and starting thread in Java involves the following steps.

  1. Get an instance of the Thread class.
  2. Call start method on the created thread object- thread.start();
  3. Once the thread is started run method will be executed.

Creating thread by implementing Runnable interface

One of the ways to create a thread in Java is to implement the Runnable interface.

Runnable interface is a functional interface in Java with a single method run() which has to be implemented. That's how Runnable interface is defined in java.lang package.

@FunctionalInterface
public interface Runnable {
  public abstract void run();
}
Example code using Runnable
public class TestThread implements Runnable {
  @Override
  public void run() {
    System.out.println("Executing run method");
  }
}

At this stage you have a class of type Runnable (not yet of type Thread). Thread class has constructors where you can pass Runnable as a parameter, using one of those constructors you can get a thread instance.

Two of those constructors which are normally used to create a thread are as follows-

  • Thread(Runnable target)
  • Thread(Runnable target, String name)

You need to pass the Runnable instance to one of these constructors to create a thread. Following code shows how you can do it.

public class ThreadDemo {
  public static void main(String[] args) {
    // Passing an instance of type runnable 
    Thread thread = new Thread(new TestThread());
    thread.start();
  }
}

Running this code will instantiate a thread and start it. Ultimately the run() method will be executed by the thread.

Output
Executing run method

Creating thread by extending Thread class

Another way to create thread in Java is to subclass the Thread class and override the run method. Then you can create an instance of that class and call start() method.

public class TestThread extends Thread {
  @Override
  public void run() {
    System.out.println("Executing run method");
  }
  public static void main(String[] args) {
    TestThread thread = new TestThread();
    thread.start();
  }
}
Output
Executing run method

Which of these approach to choose

Since there are two ways to create thread in Java so the question arises which of these two approach should be used. The preferred way is to implement Runnable interface.

When you implement Runnable interface you still have a choice to extend another class as you are not extending Thread class. Note that in Java you can extend only one class.

Thread class has many other methods except run() method but mostly you will just override run() method and provide the code that has to be executed by the Thread. Same thing can be done by implementing Runnable interface. If you are not modifying or enhancing any other method of the Thread class then why extend it.

Using anonymous class to implement run() method

When creating thread in Java by extending Thread class or implementing Runnable interface, you can also use anonymous class to implement run method.

When extending Thread class

We can have an anonymous inner class that extends a class without actually extending that class. You can create an anonymous inner class and provide run method implementation there.

public class TestThread {
  public static void main(String[] args) {
    //  anonymous inner class
    Thread thread = new Thread(){
      @Override
      public void run() {
        System.out.println("Executing run method");
      }
    };
    thread.start();
  }
}
When implementing Runnable interface
public class TestThread {
  public static void main(String[] args) {
    new Thread(new Runnable() {
      @Override
      public void run() {
        System.out.println("Executing run method");
      }
    }).start();
  }
}
Implementing Runnable as a lambda expression

Since Runnable is a functional interface it can also be implemented as a lambda expression Java 8 onward.

public class TestThread {
  public static void main(String[] args) {
    Runnable r = () -> {System.out.println("Executing run method");};
    // passing runnable instance
    new Thread(r).start();
  }
}

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


You may also like