Av Alexander Mjøs
Er du lei av å skrive haugevis av DTO-er (Data transfer object) og implementere mange metoder bare for å gjøre API kall?
Fyller models mappen din seg opp med mange POJO klasser som ikke brukes i prosjektet ditt, men du må ha de der for å motta data fra et API?
Da bør du ta en titt på OpenAPI generator. Dette lar seg best forklares med et eksempel i Java med Spring Boot.
Se for deg at du ønsker å kalle et endepunkt fra et API som heter Petstore, https://petstore.swagger.io/.
Du ønsker å kalle endepunktet /pet/findByStatus for å finne alle "available pets". Først må du finne ut hva endepunktet returnerer, og implementere de to klassene Pet.java og Category.java.
Deretter må du implementere API kallet
private final RestClient restClient; public JuleKalenderService(RestClient.Builder builder) { this.restClient = builder.baseUrl("https://petstore.swagger.io/v2").build(); } public void luke25_v1(){ List<Pet> petsByStatus = restClient.get() .uri(uriBuilder -> uriBuilder .path("/pet/findByStatus") .queryParam("status", "available") .build()) .accept(MediaType.APPLICATION_JSON) .retrieve() .body(new ParameterizedTypeReference<List<Pet>>() { }); petsByStatus.forEach(pet -> System.out.println(pet.getName())); }
Det er her magien til OpenAPI generatoren kommer inn. I dette eksempelet har vi valgt å bruke openapi-generator-maven-plugin
Først må vi hente ut OpenAPI spesifikasjonen til API-et. Disse finner du ofte linken til i swaggeren enten som json eller yaml. https://petstore.swagger.io/v2/swagger.json
Legg denne f.eks under src/main/resources
Deretter sette opp plugin i pom.xml
Mer konfigurasjonsparametre finner du her: https://github.com/OpenAPITools/openapi-generator/tree/master/modules/openapi-generator-maven-plugin
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>7.17.0</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/src/main/resources/petstore.json</inputSpec>
<generatorName>java</generatorName>
<apiPackage>com.kraftlauget.julekalender.api</apiPackage>
<modelPackage>com.kraftlauget.julekalender.model</modelPackage>
<invokerPackage>com.kraftlauget.julekalender.invoker</invokerPackage>
<configOptions>
<useJakartaEe>true</useJakartaEe>
<library>resttemplate</library>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
Neste gang du kjører mvn clean install så vil alle modellene og API klientene genereres i target mappen.
Deretter gjenstår det bare å sette opp API klienten i en av confiuration klassene i Spring boot prosjektet hvor du definerer "basepath" som du gjerne vil hente fra ekstern config.
@Configuration
public class ClientConfiguration {
@Bean
public PetApi petApi() {
ApiClient apiClient = new ApiClient();
apiClient.setBasePath("https://petstore.swagger.io/v2");
return new PetApi(apiClient);
}
}
Det første eksempelet kan nå implementeres på denne måten. Mye kortere, og mer lesbart. API-et kan nå brukes nesten som et java bibliotek eller som om du skulle ha implementert alle rest kall i en egen klasse.
public class JuleKalenderService {
PetApi petApi;
public JuleKalenderService(PetApi petApi) {
this.petApi = petApi;
}
public void luke25_v2(){
List<Pet> petsByStatus = petApi.findPetsByStatus(List.of(Pet.StatusEnum.AVAILABLE.getValue()));
petsByStatus.forEach(pet -> System.out.println(pet.getName()));
}
Mer informajon finner du på github, https://github.com/OpenAPITools/openapi-generator og https://github.com/OpenAPITools/openapi-generator/tree/master/modules/openapi-generator-maven-plugin
En liten disclaimer: Har ikke tatt med feilhåndtering og autentisering for å holde eksempelet enkelt
God jul :)