Pernahkah Anda menyesuaikan selama perbaikan terbaru ke master? Tidak ?! Tetapi saya berhasil!
Cerita ini tentang bagaimana saya lupa memperbarui dokumentasinya. Sebagai hasilnya, saya menulis sebuah plugin untuk Swagger (yang kedua kalinya). Dan bagaimana saya terbawa dengan itu sehingga saya lupa tentang cuti sakit saya dan terus membaik!
Dan sedikit lagi tentang Opsional
bukan dari Java 8.
Kami menggunakan
Swagger untuk membuat dokumentasi interaktif.
Karena itu, ketika Anda membuat metode di API, maka:
0. Tambahkan anotasi yang diperlukan, seperti @RequestMapping dan sebagainya.
1. Tambahkan @ErrorCodes (anotasi kami sendiri), dan daftarkan kode kesalahan string yang dapat dikembalikan oleh metode ini.
2. Tambahkan @ApiOperation dan duplikat informasi tentang kesalahan ini di bidang catatan.
3. Tambahkan sisa anotasi ...
Itu terlihat seperti ini (dihapus tidak perlu dan disederhanakan):
@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) {... }
Poin 2 adalah sumber kegagalan saya ketika saya menambahkan @ErrorCodes, tetapi lupa untuk menuliskan kode kesalahan string dalam @ApiOperation. Puas dengan diri saya sendiri, tetapi dengan sedikit rasa cemas, saya memberikan Permintaan Tarik ke Peninjauan Kode. Dan di sini mereka memberi tahu saya bahwa saya lupa tentang catatan! Mereka juga menjelaskan bahwa Swagger tidak mengambil informasi dari @ErrorCodes dan itulah sebabnya Anda harus mendaftarkannya secara manual. Malam itu, semuanya berakhir dengan bahagia. Memperbaiki cacatnya dan pergi cuti sakit.
Mungkin akan normal untuk mengambil dan melanjutkan. Beri tanda centang di rak untuk orang lain sama seperti yang mereka katakan, Max, hati-hati, perhatikan itu ...
Tetapi saya tidak berhasil. Sepanjang sore dan pagi berikutnya dihabiskan untuk mengajar Swagger untuk membaca anotasi kami dan secara mandiri menambahkan kode yang sama ini dalam catatan.
Langkah 1. Seseorang ada di sini ...
Dari pencarian sepintas, saya berhasil mengetahui bahwa seseorang telah
mencoba membuat teman-teman Swagger dengan penjelasan mereka. Ada juga tautan ke dokumentasi SpringFox yang mengatakan bahwa Anda dapat menulis plugin!
Kebahagiaan yang membahagiakan telah menyelimuti saya sehingga saya bahkan lupa tentang flu biasa dan sakit! Dalam artikel saya di masa depan,
"Bagaimana tidak keluar dari perusahaan tiga kali", saya berbagi tiga cerita tentang menyelamatkan orang yang tenggelam. Salah satunya adalah tentang bagaimana saya berhasil menulis plugin untuk Chrome + Firefox, yang dipercepat bekerja dengan Jenkins beberapa kali. Saya sangat senang menulisnya! Bagaimanapun, ini adalah proyek mikro! Startup saya yang sangat, sangat sederhana, tetapi dengan orang-orang nyata yang menggunakannya. Kemudian saya keluar dari rutinitas lagi dan menemukan inspirasi. Burnout hilang. Tapi saya lebih baik membicarakannya di artikel mendatang. Sementara itu, kembali ke plugin untuk Swagger.
Aksi 2. Berhasil!
Menulis sesuatu yang bekerja ternyata mudah. Saya mengambil contoh plugin dari dokumentasi resmi SpringFox, menghapus semua yang tidak perlu dan menambahkan yang benar.
Plugin. Versi 1 @Component @Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1) public class SwaggerErrorCodesConfiguration implements OperationBuilderPlugin { @Override public void apply(OperationContext context) { Method operationMethod = context.getHandlerMethod().getMethod();
Saya mulai menguji dengan metode yang tidak menentukan nilai untuk catatan di @ApiOperation.
@ApiOperation(value = "Some description.") @PostMapping("/security/confirmation/check") @ErrorCodes(values = {"sms.verification.code.fail"}) public ResponseDto check(@ApiParam @RequestBody @Valid RequestDto request) { ... }
Luncurkan dan ... Hasilnya! Hore, itu berhasil! Kode string
sms.verification.code.fail muncul di catatan!

Langkah 3. Berhasil, tetapi tidak berhasil.
Lalu saya menambahkan beberapa kata ke catatan dan saya mendapat kode ini:
@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) { ... }
Diluncurkan lagi. Hasilnya ... tidak terduga. Plugin SpringFox menimpa nilai catatan saat membuat dokumentasi (O_o)!
Saya melihat bagaimana
context.operationBuilder (). Notes (String) berfungsi dan saya melihat yang berikut di sana:
public OperationBuilder notes(String notes) { this.notes = (String)BuilderDefaults.defaultIfAbsent(notes, this.notes); return this; }
Um ... Ok, maka kita akan mengambil nilai catatan saat ini dan menambahkan kode kesalahan. Tetap mendapatkan anotasi @ApiOperation, mengambil nilai yang diinginkan dan menambahkan apa yang saya bentuk sendiri.
Jadi, versi final (
tersedia di gist.github.com )
Plugin. Versi 2 @Component @Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1) public class SwaggerErrorCodesConfiguration implements OperationBuilderPlugin { @Override public void apply(OperationContext context) { Method operationMethod = context.getHandlerMethod().getMethod();
Sekarang ternyata seperti yang seharusnya!

Langkah 4. Bagaimana dengan Opsional bukan dari Java 8?
Pada awal bekerja pada plugin, saya tidak bisa mengerti apa yang salah dengan Opsional, yang dikembalikan saat mencari anotasi. Kelas ini tidak memiliki metode standar yang digunakan untuk bekerja dengan
java.util.Optional . Misalnya, tidak ada metode
ifPresent , tetapi ada metode
orNull .
Ternyata SpringFox menggunakan
Opsional dari
Guava .
TL; DR
Saya menulis sebuah plugin untuk SpringFox, yang merupakan komponen Spring dan dipanggil pada tahap pembuatan dokumentasi untuk membaca nilai dari penjelasan @ErrorCodes kami.
Kode plugin @Component @Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1) public class SwaggerErrorCodesConfiguration implements OperationBuilderPlugin { @Override public void apply(OperationContext context) { Method operationMethod = context.getHandlerMethod().getMethod();