Java Developer? Przejdź na wyższy poziom wiedzy 🔥💪  Sprawdź

Team Leader? Podnieś efektywność swojego zespołu 👌 Sprawdź

Generowanie klienta i serwera REST z użyciem OpenAPI oraz Feign

utworzone przez 1 kwietnia 2024Java, Mikroserwisy i Integracje, Spring Framework, Tip and Tricks

Współczesny rozwój aplikacji internetowych często opiera się na architekturze mikrousług, gdzie kluczową rolę odgrywają interfejsy API REST. Aby usprawnić tworzenie takich interfejsów oraz ich konsumpcję, możemy wykorzystać specyfikację OpenAPI w połączeniu z Feign – deklaratywnym klientem HTTP dla Spring Boot. W tym artykule przedstawiamy, jak zintegrować te narzędzia, aby zautomatyzować proces generowania kodu serwera i klienta w Java 17 i Spring Boot 3, a także zaprezentujemy przykład tworzenia i pobierania danych użytkownika.

Czym jest OpenAPI i Feign?

OpenAPI to otwarta specyfikacja do opisu interfejsów API REST, umożliwiająca automatyczne generowanie dokumentacji oraz kodu klienta i serwera. Feign to biblioteka Spring Cloud, która pozwala tworzyć deklaratywne klienty HTTP, upraszczając komunikację między mikrousługami. Korzystanie z Feign bardzo ułatwia pracę. Wystarczy do posiadanego kontraktu (opisanego w pliky yaml) wygenerować api klienckie i serwerowe. Ma to dodatkową, ogromną zaletę – nasz klient, czy serwer bazuje na kontrakcie. Na tym samym kontrakcie bazuje strona przeciwna (ta, z którą się komunikujemy). Jeśli obie strony komunikacji bazują na wspólnym kontrakcie, pozbywamy się ryzyka zmian w strukturze danych, które mogą wprowadzić błędy integracji. Olbrzymią zaletą jest również możliwość zastosowania testów kontraktowych. Otóż, przy budowaniu aplikacji, jeśli jesteśmy niezgodni z kontraktem – testy wysypią. Więcej o testach kontraktowych pisał Piotrek Pelczar – zachęcam gorąco do przeczytania artykułu – https://softwareskill.pl/consumer-driven-contract

Konfiguracja środowiska

Zacznijmy od przygotowania naszego środowiska deweloperskiego. Upewnij się, że masz zainstalowane:

  • JDK 17
  • Maven 3.6+
  • Spring Boot 3

Generowanie serwera REST z OpenAPI

Aby wygenerować serwer należy zdefiniować kontrakt, na podstawie którego będzie generowany sam serwer. Dodamy potrzebne zależności do Mavena, aby na samym końcu zaimplementować interfejs wygenerowany przez OpenApi.

1. Tworzenie specyfikacji OpenAPI

Zdefiniuj specyfikację OpenAPI dla naszego API. Załóżmy, że tworzymy API użytkownika z endpointami do tworzenia i pobierania danych użytkownika. Specyfikację zapiszemy w pliku YAML (src/main/resources/user-api.yaml):

openapi: 3.0.1
info:
  title: User API
  version: 1.0.0
paths:
  /user:
    post:
      summary: Create a new user
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/User'
      responses:
        '201':
          description: Successfully created user
    get:
      summary: Get user data
      responses:
        '200':
          description: A user object
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
components:
  schemas:
    User:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        email:
          type: string

2. Konfiguracja Maven do generowania kodu

Użyj pluginu openapi-generator-maven-plugin w pom.xml, aby wygenerować kod źródłowy na podstawie specyfikacji OpenAPI:

<plugin>
    <groupId>org.openapitools</groupId>
    <artifactId>openapi-generator-maven-plugin</artifactId>
    <version>5.2.1</version>
    <executions>
        <execution>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <inputSpec>${project.basedir}/src/main/resources/user-api.yaml</inputSpec>
                <generatorName>spring</generatorName>
                <apiPackage>pl.softwareskill.user.api</apiPackage>
                <modelPackage>pl.softwareskill.user.model</modelPackage>
                <configOptions>
                    <interfaceOnly>true</interfaceOnly>
                </configOptions>
            </configuration>
        </execution>
    </executions>
</plugin>

Uruchom mvn clean package, aby wygenerować kod.

3. Implementacja serwera

Zaimplementuj serwer, korzystając z wygenerowanych interfejsów. Dodaj logikę biznesową dla tworzenia i pobierania użytkownika:

package com.example.user.api;

import com.example.user.model.User;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;

@RestController
public class UserController implements UserApi {

    @Override
    public ResponseEntity<User> createUser(User user) {
        user.setId(UUID.randomUUID().toString()); // Przykładowa implementacja
        return ResponseEntity.status(201).body(user);
    }

    @Override
    public ResponseEntity<User> getUser() {
        User user = new User(); // Przykładowe dane
        user.setId(UUID.randomUUID().toString());
        user.setName("Jan Kowalski");
        user.setEmail("jan.kowalski@example.com");
        return ResponseEntity.ok(user);
    }
}

Mamy już część serwerową, serwującą API na podstawie dostarczonego kontraktu. Teraz pora na utworzenie części klienckiej, którą również wygenerujemy na podstawie tego samego kontraktu.

Psst… Interesujący artykuł?

Jeżeli podoba Ci się ten artykuł i chcesz takich więcej – dołącz do newslettera. Nie ominą Cię materiały tego typu.

.

Integracja z Feign do tworzenia klienta REST

1. Dodaj zależności Spring Cloud OpenFeign

W pom.xml projektu dodaj zależność do Spring Cloud OpenFeign:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2. Włącz Feign w aplikacji

Dodaj adnotację @EnableFeignClients do głównej klasy aplikacji:

@SpringBootApplication
@EnableFeignClients
public class UserApplication {

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

Zdefiniuj klienta Feign, wykorzystując interfejs wygenerowany przez OpenAPI (generowanie interfejsu odbywa się dokładnie tak samo jak w poprzednim przypadku), lub stwórz nowy interfejs z adnotacją @FeignClient:

@FeignClient(name = "userClient", url = "http://localhost:8080")
public interface UserClient extends UserApi {
}

3. Wykorzystanie klienta Feign

Użyj klienta Feign w swojej aplikacji, aby komunikować się z API użytkownika:

@RestController
@RequestMapping("/api")
public class UserFeignController {

    private final UserClient userClient;

    public UserFeignController(UserClient userClient) {
        this.userClient = userClient;
    }

    @PostMapping("/users")
    public User createUser(@RequestBody User user) {
        return userClient.createUser(user).getBody();
    }

    @GetMapping("/users")
    public User getUser() {
        return userClient.getUser().getBody();
    }
}

Podsumowanie

Dzięki wykorzystaniu OpenAPI i Feign w Spring Boot możemy efektywnie generować kod serwera i klienta, co znacząco przyspiesza rozwój aplikacji opartych o architekturę mikrousług. Integracja tych narzędzi umożliwia nie tylko automatyzację wielu aspektów tworzenia oprogramowania, ale także zapewnia spójność i łatwość w utrzymaniu kodu. Wprowadzenie przykładu z użytkownikiem pokazuje, jak można zastosować te technologie do praktycznych zastosowań, umożliwiając szybkie tworzenie i pobieranie danych użytkownika w nowoczesnej aplikacji internetowej. Bazując na wspólnym kontrakcie pomiędzy klientem a serwerem, wykorzystując przy tym testy kontraktowe, zabezpieczamy naszą integrację przed omyłkowymi zmianami, które mogłyby zerwać kompatybilność integracji.

Gdybyś potrzebował jeszcze więcej:

Jesteś Java Developerem?

Przejdź na wyższy poziom wiedzy 
„Droga do Seniora” 🔥💪

Jesteś Team Leaderem? Masz zespół?

Podnieś efektywność i wiedzę swojego zespołu 👌

Dyskusja