API-first development con Swagger+ Spring

In questo articolo vedremo come partire da un approccio API-first per sviluppare applicazioni lato backend ovvero come generare codice server utilizzando OpenAPI Generator. Il codice verrà generato per un’applicazione Spring Boot.

In parole povere:

  • generi le API da swagger editor e scarichi file yaml
  • aggiungi dependency e maven plugin e fai mvn clean compile
  • ora mi ha creato dei file in target (model layer e api-controller layer) che sposto togliendoli dalla cartella target alla cartella src/main/java
  • succede che ogni volta che pusho o faccio ripartire l’app il plugin mi compila ogni volta i file nel maven e da errore perché dice che già esistono allora bisogna dividere i compiti con i profiles. continua a leggere
  • se per caso devo modificare lo yaml non faccio ancora mvn clean compile ma mvn clean generate-sources -Pnomeprofilo leggi perché_:

“se sposti le cartelle generate in target in src/main/java poi quando fai i tuoi commit e push su git prende anche quei file e dopo un pò devi fare cambiamenti allo yml e devi ricompilare da zero, ti darà errore file doppi perché ricrea gli stessi file nella cartella default target.

questo è stato fatto dal plugin perché non ci sarebbe bisogno ogni volta di pushare anche i file creati da maven nella cartella target perché tanto chi scarica il tuo codice sul suo eclipse avrà anche lui il plugin maven openapi tools e li ricrea ogni volta  MA cosi facendo sei limitato alle versioni del plugin, un domani che swagger o il plugin non sono compatibili per diverse versioni rischi di trovarti nei guai.”

allora aggiungiamo dei profiles nel pom alla sezione plugin e dividiamo i compiti. cosi ogni volta anziché fare tutto il clean compile da capo, facciamo generare solo le sources di un certo pezzo di codice.

 

  • ora che abbiamo i file generati dal plugin openapi che usa il file yml di swagger devi capire che i model sono come le entità e

 

How to design your API first and how to generate code by using the OpenAPI Generator.

Fonti:

Generate Server Code Using OpenAPI Generator

 

Passaggi:

  • design the OpenAPI specification for your application: ovvero creo un file YAML con Swagger Editor 
  • creo progetto Spring da Initializr vedi es. configurazione da questo articolo
  • importo progetto su IDE es. Eclipse
  • nel pom.xml inserisco dependencies + OpenApi Maven Plugin (vedi pom.xml esempio da github di reflectoring.io)

dependency e plugin:

https://pastebin.com/KaA1vuim 

 

  1. design the OpenAPI specification for your application con SWAGGER EDITOR

La prima cosa da fare è progettare la specifica OpenAPI per la tua applicazione. Stai per progettare un’API customer. L’API consente di creare un Customer e di recuperare il Customer in base al suo ID. Un’API reale sarà più elaborata, ma questo è un esempio to
keep it simple.

L’intestazione della specifica OpenAPI contiene alcuni metadata sull’API, come title, version, server in esecuzione sull’API. I tags possono essere utilizzati per raggruppare le risorse, il che ti darà una panoramica più ordinata.

openapi: "3.0.2"
info:
title: API Customer
version: "1.0"
servers:
- url: https://localhost:8080
tags:
- name: Customer
description: Customer specific data.

 

La sezione path contiene le specifiche per le risorse. La prima risorsa che definisci è una per creare un nuovo Cliente, al path /customer il che verrà fatto tramite una POST contenente un JSON body (indicato appunto in requestBody > content). Verrà utilizzato operationIddal generator per creare il nome del metodo per questa risorsa. Per semplicità, qui viene considerata solo una response positiva. Gli schema che si riferiscono al corpo JSON, verranno trattati più avanti in questa sezione.

/customer:
post:
tags:
- Customer
summary: Create Customer
operationId: createCustomer
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Customer'
responses:
'200':
description: OK
content:
'application/json':
schema:
$ref: '#/components/schemas/CustomerFullData'

 

La seconda risorsa ci consentirà di recuperare un Customer. Questa risorsa accetta anche un parametro path {customerId} contenente l’ id del customer da recuperare. Se l’ID non esiste, verrà ritornata una risposta NOT FOUND.

/customer/{customerId}:
get:
tags:
- Customer
summary: Retrieve Customer
operationId: getCustomer
parameters:
- name: customerId
in: path
required: true
schema:
type: integer
format: int64
responses:
'200':
description: OK
content:
'application/json':
schema:
$ref: '#/components/schemas/CustomerFullData'
'404':
description: NOT FOUND

Infine, nella sezione dei components, vengono definiti gli schemas utilizzati. Lo schema Customer e lo schema CustomerFullData condividono tutte le properties, ad eccezione dell’ID.

Per una migliore manutenibilità, può essere utilizzata la properties  allOf .

components:
schemas:

Customer:
type: object
properties:
firstName:
type: string
description: First name of the customer
lastName:
type: string
description: Last name of the customer
CustomerFullData:
allOf:
- $ref: '#/components/schemas/Customer'
- type: object
properties:
customerId:
type: integer
description: The ID of the customer
format: int64
description: Full data of the customer.

 

 

Generiamo il codice da API Specification

Generazione di codice da una specifica API
Dopo aver definito un’API, creeremo ora il codice dal documento YAML che possiamo esportare da Swagger.

Ci sono due diversi approcci per generare il codice ma quello da evitare è di utilizzare l’ editor Swagger per generare codice.
Meglio utilizzare il plug-in OpenAPI Maven per generare codice da una build Maven.

Generating Code with the OpenAPI Maven plugin:

    • La nostra app sarà una semplice Spring Boot project che possiamo generare automaticamente da start.spring.io  aggiungendo la dipendenza spring web.
    • focalizziamoci sul file pom.xml from the specification module, where we configure the OpenAPI Maven plugin:
    • successivamente facciamo partire il comando mvn clean compile e facciamo startare l’app con mvn spring-boot:run
    • ATTENZIONE: solo la prima volta dobbiamo fare mvn clean compile ma se modifichiamo lo yaml poi basta fare mvn mvn clean generate-sources -Pnomedelprofiloes -Pcodegen dove nome del profilo va indicato come profiles vedi foto
    • se invece vogliamo solo pulire la cartella target facciamo mvn clean
    • ora il plugin ha generato il codice dei nostri Model (modelli, le entities) definiti precedentemente es. User e anche il layer API ovvero Controller annotato con @Controller
    • il plugin non genera solo i modelli ma anche gli endpoint che sono quelle interfacce che terminano con Delegate es. UserApiDelegate in questo delegate c’è un metodo default il quale viene chiamato se non implementiamo nulla e restituisce un notimplemented, ma qui dentro troverai anche tutti i metodi GET, POST, DELETE etc che avevamo impostato nello Swagger Editor!
    • Ovviamente, il generatore non può generare la nostra business logic per noi, ma genera interfacce come UserApiDelegate per noi da implementare. Infatti qui dentro troverai tutti i metodi che avevamo impostato nello Swagger! La logica di business però (quindi l’override dei metodi) la mettiamo nella classe UserApiDelegateImpl annotato con @Service (vedi business layer) cosi anche se ricompiliamo usando il plugin perché magari nel frattempo abbiamo modificato lo yaml, non ci va a sostituire(piallare) la nostra logica di business 🙂
    • il generatore  plugin crea anche un’interfaccia UserApi che delega le chiamate a UserApiDelegate

IN CONCLUSIONE:

il plugin ci genera i model e le api (le api sono i nostri controller) questo è un’altro approccio a differenza del tutorial di amigoscode che abbiamo visto in questo articolo 

 

	4.0.0
	
		org.springframework.boot
		spring-boot-starter-parent
		2.6.6
		 
	
	com.example
	games
	0.0.1-SNAPSHOT
	games
	Demo project for Spring Boot
	
		11
	
	
		
			org.springframework.boot
			spring-boot-starter-web
		

		
			org.springframework.boot
			spring-boot-starter-test
			test
		


		
			javax.validation
			validation-api
			2.0.1.Final
		


		
			org.openapitools
			jackson-databind-nullable
			0.2.1
		


		
			io.springfox
			springfox-swagger2
			2.9.2
		


		
			org.springdoc
			springdoc-openapi-ui
			1.6.4
		

		
			org.springdoc
			springdoc-openapi-ui
			1.6.4
		

	

	
		
			
				org.springframework.boot
				spring-boot-maven-plugin
			

			
				org.openapitools
				openapi-generator-maven-plugin
				5.1.0
				
					
						
							generate
						
						
							${project.basedir}/src/main/resources/openapi.yaml
							spring
							com.example.games.api
							com.example.games.model
							ApiUtil.java 
							
								true
								
							
						
					
				
			
		
	

 

nuovo swagger 3.0

schemas sono i parametri che serrvono alle API
non sono classi java

una post vedila come una lettera
#LETTERA fuori ci sono i parametri ovveroc’è id che è indirizzo a cui mando la lettera e il contenuto dentro la lettera è il requestBody

SWAGGER: 13/04/2022
GET
query: solo nella get
POST, PUT, DELETE
body: passare e prendere cose come array json e poi dall’altra parte nel java usiamo map chiave valore
swagger gestione risorse identificate con id

pensare per risorse identificate con id

GET OTTIENI la fetch
POST CREA RISORSA
PUT modifichi

da swagger posso generare del codice con librerie
bean di trasporto da swagger jackson
CONVERTE formato in oggetto java

da swagger creo codice json serve portare oggetto dentro java o
implementare business logic: scelgo mossa etc..

arena
i bot si registrano nell’arena
il bot chiamaa post macth su di lui (e mi darà id)
poi chiamo postmatch su di te (e mi darà id)

quando io chiamo

partita a curl:
ti arriva oggetto nel contesto di una risorsa
match id serve e basta

https://reflectoring.io/spring-boot-openapi/

manven strumenti di build quando passi dalle classi scritte in java
a jar in mezzo c0’è maven.

plugin di maven su eclipse prende lo swqagger lo legge e dice c’è un sulla risosrsa match

con la funzione get match annnotata con get

etc etrc
tutti gli artefatti da quell’insieme

pom punto rif trasformazione java in qulcosa che esegue
governa passaggio dal codice java all’artefatto eseguibile (jar,war, ear)

pom > maven metto il plugin
quando lancio:
maven install
compila progetto lo impaccchetta e lo emtte dispnibile sul repository locale.

studiare concetto:
REST > risorsa

cdi cosa abbiamo aprlato

1.

INTERNO OGGETTO MOSSA ()
ha senso nello swagger dire guarda che ogni oggetto ticatcamove avraà interno oggetto match.
perchè a noi serve sapere se questa move è di quel match , quindi ci basta id match

nella business logic

da ongi mossa posso accedere al match corrispondente-

2. POST CONNECT FOUR /matchid/ moves
in post sto facendo mossa

3. a livello api rest i model sotto NON sono delle classi.
NON devo pensare a mappare le classi java.
quindi l’id non sempre mi serve ma lo genero poi nella business logic.
a parte quando /tic-tac-toe/matches/{matchId}/moves perchè glielo chiedo come PATH PARAM {matchId}

*************
CONSUMES sono i parametri (quellao che ricevi) (attraverso body path query)
cosa ricevo lo spiego nei PARAMETERS
invece quando produci è nella response

Il nostro voto
Clicca per votare questo articolo!
[Voti: 0 Media: 0]

2 commenti su “API-first development con Swagger+ Spring”

Lascia un commento