Avez-vous déjà ajusté le correctif au maître? Non?! Mais j'ai réussi!
Cette histoire raconte comment j'ai oublié de mettre à jour la documentation. En conséquence, j'ai écrit un plugin pour Swagger (la deuxième fois). Et comment je me suis emporté avec ça pour que j'oublie mon congé de maladie et que je me remette!
Et un peu plus sur Facultatif
pas de Java 8.
Nous utilisons
Swagger pour créer une documentation interactive.
Par conséquent, lorsque vous créez une méthode dans l'API, alors:
0. Ajoutez les annotations nécessaires, telles que @RequestMapping et ainsi de suite.
1. Ajoutez @ErrorCodes (notre propre annotation) et répertoriez les codes d'erreur de chaîne que cette méthode peut renvoyer dans la réponse.
2. Ajoutez @ApiOperation et dupliquez des informations sur ces erreurs dans le champ des notes.
3. Ajoutez le reste des annotations ...
Cela ressemblait à quelque chose comme ça (supprimé inutile et simplifié):
@ApiOperation( value = "Some description.", notes = "List of possible error codes:" + "<ul>" + " <li>sms.verification.code.fail</li>" + "</ul>") @PostMapping("/security/confirmation/check") @ErrorCodes(values = {"sms.verification.code.fail"}) public ResponseDto check(@ApiParam @RequestBody @Valid RequestDto request) {... }
Le point 2 a été la source de mon échec lorsque j'ai ajouté @ErrorCodes, mais j'ai oublié de répertorier les codes d'erreur de chaîne dans @ApiOperation. Satisfait de moi-même, mais avec un léger sentiment d'anxiété, j'ai donné ma demande de retrait à l'examen du code. Et ici, ils m'ont informé que j'avais oublié les notes! Ils ont également expliqué que Swagger ne récupère pas les informations de @ErrorCodes et c'est pourquoi vous devez les enregistrer manuellement. Ce soir-là, tout s'est terminé joyeusement. Corrigé son défaut et pris un congé de maladie.
Il serait peut-être normal de prendre et de passer à autre chose. Mettez une coche sur l'étagère pour les autres comme ils disent, Max, soyez prudent, faites attention ...
Mais je n'ai pas réussi. Toute la soirée et le lendemain matin ont été consacrés à apprendre à Swagger à lire notre annotation et à ajouter indépendamment ces mêmes codes dans les notes.
Étape 1. Quelqu'un était là ...
À partir d'une recherche superficielle, j'ai réussi à découvrir que quelqu'un avait déjà
essayé de se faire des amis Swagger avec leur annotation. Il y avait aussi un lien vers la documentation SpringFox qui disait que vous pouvez écrire un plugin!
Le bonheur heureux m'a tellement couvert que j'ai même oublié le congé de rhume et de maladie! Dans mon futur article,
«Comment ne pas quitter l'entreprise trois fois», je partage trois histoires de sauvetage de noyades. L'un d'eux concerne la façon dont j'ai réussi à écrire un plugin pour Chrome + Firefox, qui a accéléré le travail avec Jenkins plusieurs fois. J'étais tellement amusant de l'écrire! Après tout, c'est un microprojet! Ma startup très, très simple, mais avec de vraies personnes qui l'utilisent. Puis je suis sorti de la routine et j'ai trouvé l'inspiration. L'épuisement professionnel a disparu. Mais je ferai mieux d'en parler dans un prochain article. En attendant, revenons au plugin pour Swagger.
Action 2. Ça marche!
Écrire quelque chose qui fonctionne s'est avéré être facile. J'ai pris un exemple de plugin de la documentation officielle de SpringFox, supprimé tout ce qui n'était pas nécessaire et ajouté le bon.
Plugin. Version 1 @Component @Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1) public class SwaggerErrorCodesConfiguration implements OperationBuilderPlugin { @Override public void apply(OperationContext context) { Method operationMethod = context.getHandlerMethod().getMethod();
J'ai commencé à tester avec une méthode qui ne spécifie pas de valeur pour les notes dans @ApiOperation.
@ApiOperation(value = "Some description.") @PostMapping("/security/confirmation/check") @ErrorCodes(values = {"sms.verification.code.fail"}) public ResponseDto check(@ApiParam @RequestBody @Valid RequestDto request) { ... }
Lancement et ... Le résultat! Hourra, ça marche! Le code de chaîne
sms.verification.code.fail est apparu dans les notes!

Étape 3. Cela fonctionne, mais cela ne fonctionne pas.
Ensuite, j'ai ajouté quelques mots aux notes et j'ai obtenu ce code:
@ApiOperation(value = "Some description.", notes = "Some initial note.") @PostMapping("/security/confirmation/check") @ErrorCodes(values = {"sms.verification.code.fail"}) public ResponseDto check(@ApiParam @RequestBody @Valid RequestDto request) { ... }
Lancé à nouveau. Le résultat était ... inattendu. Le plugin SpringFox écrase la valeur des notes lors de la génération de la documentation (O_o)!
Je regarde comment
context.operationBuilder (). Notes (String) fonctionne et je vois ce qui suit:
public OperationBuilder notes(String notes) { this.notes = (String)BuilderDefaults.defaultIfAbsent(notes, this.notes); return this; }
Hum ... Ok, alors nous prendrons la valeur actuelle des notes et ajouterons les codes d'erreur. Reste à obtenir l'annotation @ApiOperation, à prendre la valeur souhaitée et à ajouter à ce que je forme moi-même.
Donc, la version finale (
disponible sur gist.github.com )
Plugin. Version 2 @Component @Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1) public class SwaggerErrorCodesConfiguration implements OperationBuilderPlugin { @Override public void apply(OperationContext context) { Method operationMethod = context.getHandlerMethod().getMethod();
Maintenant, cela s'est avéré comme il se doit!

Étape 4. Qu'en est-il de l'option non de Java 8?
Au tout début du travail sur le plugin, je ne pouvais pas comprendre ce qui n'allait pas avec l'Optional, qui est retourné lors de la recherche d'annotations. Cette classe ne disposait pas des méthodes standard utilisées pour travailler avec
java.util.Optional . Par exemple, il n'y a pas de méthode
ifPresent , mais il existe une méthode
orNull .
Il s'est avéré que SpringFox utilise
Facultatif de
Guava .
TL; DR
J'ai écrit un plugin pour SpringFox, qui est un composant Spring et est appelé au stade de la génération de documentation pour lire les valeurs de notre annotation @ErrorCodes.
Code du plugin @Component @Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1) public class SwaggerErrorCodesConfiguration implements OperationBuilderPlugin { @Override public void apply(OperationContext context) { Method operationMethod = context.getHandlerMethod().getMethod();