Thursday, May 26, 2022

Simple SpringWebflux example request/response and Reactive Stream

 Before reading this blog, make sure to refer to my previous blog on Reactive programming

http://siddharathadhumale.blogspot.com/2022/05/reactive-programming-concepts.html

Now, let's try to understand the main difference between traditional REST and reactive programming concept. Here we are using the springwebflux as it is build on Project reactor so has all reactive specification implemented for us.

We will see both the REST and Reactive way of programming in one application only.

Please follow below steps for creating Springwebflux project. I am using Spring STS as IDE.

Click on finish button.

This will be our pom.xml

1- Pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<?xml version="1.0" encoding="UTF-8"?>
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.siddhu</groupId>
    <artifactId>springboot-webflux</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-webflux</name>
    <description>This example shows Reactive example using springwebflux</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
 
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
 
</project>
Now lets create few of the folder

1- Controller
2- Dao
3- Service
4- dto

create a dto class as Employee
1- Employee

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/**
 *
 */
package com.siddhu.dto;
 
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
 
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
 
/**
 *
 */
package com.siddhu.dto;
 
import java.io.Serializable;
 
/**
 * @author Siddhartha
 *
 */
public class Employee implements Serializable{
 
    @Override
    public String toString() {
        return "Employee [id=" + id + ", name=" + name + "]";
    }
 
    /**
     * @return the id
     */
    public int getId() {
        return id;
    }
 
    /**
     * @param id the id to set
     */
    public void setId(int id) {
        this.id = id;
    }
 
    /**
     * @return the name
     */
    public String getName() {
        return name;
    }
 
    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }
 
    private int id;
    private String name;
     
    public Employee(int id, String name)
    {
        this.id = id;
        this.name = name;
    }
 
}

Now lets create dao class EmployeeDao

1- EmployeeDao

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.siddhu.dao;
 
import java.time.Duration;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
 
import org.springframework.stereotype.Component;
 
import com.siddhu.dto.Employee;
 
import reactor.core.publisher.Flux;
 
@Component
public class EmployeeDao {
 
     private static void sleepExecution(int i){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
 
        public List<Employee> getEmployees()  {
            return IntStream.rangeClosed(1, 5)
                    .peek(EmployeeDao::sleepExecution)
                    .peek(i -> System.out.println("processing Iteration count : " + i))
                    .mapToObj(i -> new Employee(i, "Employee" + i))
                    .collect(Collectors.toList());
        }
 
 
        public Flux<Employee> getEmployeesStream()  {
            return Flux.range(1,5)
                    .delayElements(Duration.ofSeconds(1))
                    .doOnNext(i -> System.out.println("processing Iteration count in stream flow : " + i))
                    .map(i -> new Employee(i, "Employee" + i));
        }
 
       
}

Now create Service
1- EmployeeService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package com.siddhu.service;
 
import java.util.List;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
import com.siddhu.dao.EmployeeDao;
import com.siddhu.dto.Employee;
 
import reactor.core.publisher.Flux;
 
@Service
public class EmployeeService {
 
 
    @Autowired
    private EmployeeDao dao;
 
    public List<Employee> loadAllEmployees() {
        long start = System.currentTimeMillis();
        List<Employee> employees = dao.getEmployees();
        long end = System.currentTimeMillis();
        System.out.println("Total execution time : " + (end - start));
        return employees;
    }
 
 
 
    public Flux<Employee> loadAllEmployeesStream() {
        long start = System.currentTimeMillis();
        Flux<Employee> employees = dao.getEmployeesStream();
        long end = System.currentTimeMillis();
        System.out.println("Total execution time : " + (end - start));
        return employees;
    }
}

Now create controller class

1- EmployeeController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.siddhu.controller;
 
import java.util.List;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
import com.siddhu.dto.Employee;
import com.siddhu.service.EmployeeService;
 
import reactor.core.publisher.Flux;
 
 
@RestController
@RequestMapping("/employees")
public class EmployeeController {
 
    @Autowired
    private EmployeeService service;
 
 
    @GetMapping
    public List<Employee> getAllEmployees() {
        return service.loadAllEmployees();
    }
 
    @GetMapping(value = "/stream",produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<Employee> getAllEmployeesStream() {
        return service.loadAllEmployeesStream();
    }
     
}

Start the Springboot application

You can see the server started on Netty server.

Now execute below url and you will find following output
REST base approach:-

http://localhost:8080/employees

Now lets execute belwo url
http://localhost:8080/employees/stream

As this is Reactive behaviour we will see the output as soon as it is comming from the Microservice. It is not like that all the five record are generated on the server and then the response is send back to Client it is like as soon as the data is generated by the server/microservice you will be able to see the output

You can download the code from
https://github.com/shdhumale/springboot-webflux.git

No comments: