æ¦è¦
åãã¦è§¦ããã¬ã¼ã ã¯ã¼ã¯ãªã®ã§èª¿ã¹ããã¨ãã¾ã¨ã¾ããªãæ¸ãã¦ããã
諸å
- Quarkus: 3.15.1
- Java: 21
ãªãã¡ã¬ã³ã¹
- å ¬å¼ã¬ã¤ã: https://ja.quarkus.io/guides/
- RedHatã®SAã®æ¹ã®è¨äº: https://rheb.hatenablog.com/entry/microprofile_openapi
- æ¦è¦
- 諸å
- ãªãã¡ã¬ã³ã¹
- REST APIå®è£
ç·¨
- ã¨ã³ããã¤ã³ãã«å ±éã®ãã¹ãä»ä¸ããã
- ãªã¯ã¨ã¹ããã©ã¡ã¿ã®ã³ã³ããã¯ã©ã¹ã«Recordã¯ã©ã¹ã使ããã(ãã©ã§ããªã)
- ãã¹ãã©ã¡ã¿ãã¯ã¨ãªãã©ã¡ã¿ã®åãæ£è¦è¡¨ç¾ã§è¡¨ããã
- ã¬ã¹ãã³ã¹ãJsonã§è¿ãããã
- ä»»æã®ã¹ãã¼ã¿ã¹ã³ã¼ãã¨ã¬ã¹ãã³ã¹ã§è¿ããã
- Servlet Filterçãªãã®ãã»ãã
- OpenAPIç·¨
- èªåãã¹ãç³»(T.B.D.)
- ãã®ä»
REST APIå®è£ ç·¨
ã¨ã³ããã¤ã³ãã«å ±éã®ãã¹ãä»ä¸ããã
package org.acme.rest; import jakarta.ws.rs.ApplicationPath; import jakarta.ws.rs.core.Application; @ApplicationPath("/api") public static class MyApplication extends Application {}
ã¿ããã«ããã¨ãã¹ã¦ã®ã¨ã³ããã¤ã³ãã®é ã« /api
ãã¤ããããã
ãªã¯ã¨ã¹ããã©ã¡ã¿ã®ã³ã³ããã¯ã©ã¹ã«Recordã¯ã©ã¹ã使ããã(ãã©ã§ããªã)
è¤æ°ã®ãªã¯ã¨ã¹ããã©ã¡ã¿ãã°ã«ã¼ãããã«ã¹ã¿ã ã¯ã©ã¹ãå®è£ ãããã¨ãã§ãããããã¯BeanParamãå©ç¨ãã¦ããã
@Path("/cheeses/{type}") public class Endpoint { public static class Parameters { @RestPath String type; // ...snip... @RestForm String smell; } @POST public String allParams(@BeanParam Parameters parameters) { // <- ココ! return parameters.type + "/" + parameters.variant + "/" + parameters.age + "/" + parameters.level + "/" + parameters.secretHandshake + "/" + parameters.smell; } }
ref: ã«ã¹ã¿ã ã¯ã©ã¹ã§ãã©ã¡ã¼ã¿ãã°ã«ã¼ãå
ãã®ã«ã¹ã¿ã ã¯ã©ã¹ãRecordã¯ã©ã¹ã§å®è£ ããããªãããJava Beanã®è¦ç´ã«æºæ ãã¦ããªãããæ®å¿µãªãã使ããªãæ§åã
- https://github.com/jakartaee/rest/issues/913
- https://blogs.oracle.com/javamagazine/post/diving-into-java-records-serialization-marshaling-and-bean-state-validation
ãã¹ãã©ã¡ã¿ãã¯ã¨ãªãã©ã¡ã¿ã®åãæ£è¦è¡¨ç¾ã§è¡¨ããã
@Path("{name}/{age:\\d+}") @GET public String personalisedHello(String name, int age) { return "Hello " + name + " is your age really " + age + "?"; } @GET public String genericHello() { return "Hello stranger"; }
{age:\\d+}
ãªã©ã¨ããã¨ãã©ã¡ã¿åãæ£è¦è¡¨ç¾ã§ãã¿ã¼ã³ãããã³ã°ãã¤intçã«å¤æããç¶æ
ã§ã¡ã½ããã«æ¸¡ããã¨ãã§ããã
ãããããªãå ´åã¯ãã©ã¼ã«ããã¯ã§ããã¡ã½ãããããã°ãã¡ãã«ããã
ãªã¼ãã¼ãã¼ãã®ãããªåä½ãå®ç¾ã§ããããæå³ããªãåãã«ç¹ãããããªã®ã§ãããªãã»ããããã¨æã£ãã
@Path("{name}/{age:\\d+}") @GET public String personalizedHello(String name, int age) { return String.format("%s is your age really %d?", name, age); } @Path("{name}/{comeFrom}") @GET public String personalizedHello(String name, String comeFrom) { return String.format("Are %s from %s?", name, comeFrom); }
ã¬ã¹ãã³ã¹ãJsonã§è¿ãããã
quarkus-rest-jackson
ã®extensionãå
¥ããã¨JSONã§èªåçã«è¿ãããã«ãªãã
ref: https://quarkus.io/guides/rest#json-serialisation Â
ä»»æã®ã¹ãã¼ã¿ã¹ã³ã¼ãã¨ã¬ã¹ãã³ã¹ã§è¿ããã
WebApplicationException
(ããã¯Jakartaã®è³ç£)ãç¶æ¿ããå種ä¾å¤ãthrowããã¨å¯¾å¿ããã¹ãã¼ã¿ã¹ã³ã¼ãã«ãªãã
@GET public String findCheese(String cheese) { if(cheese == null) // send a 400 throw new BadRequestException(); if(!cheese.equals("camembert")) // send a 404 throw new NotFoundException("Unknown cheese: " + cheese); return "Camembert is a very nice cheese"; }
ref: - ä¾å¤ã®ãããã³ã° - java - WebApplicationException vs Response - Stack Overflow
ã¾ãã¯ãã¡ã½ããã®åã Response
ã«ãã以ä¸ã®ãããªå½¢ã§ä»»æã®HTTPã¹ãã¼ã¿ã¹ã³ã¼ãã¨ä»»æã®ãªãã¸ã§ã¯ããè¿ãããå
¬å¼ã¬ã¤ãã«å¯ãã°âã®å®è£
ãæåã¨ã®ãã¨ã
@Path("{id}") @GET public Response getPerson(Long id) { var p = new Person(id, "foo", "bar", "Brick Lane"); return Response.status(Response.Status.NOT_FOUND).entity(p).build(); }
(OpenAPIå®ç¾©ã«ã¨ã©ã¼ãåæ ãããæ¹æ³ã¯?)
Servlet Filterçãªãã®ãã»ãã
@ServerRequestFilter
ã¢ããã¼ã·ã§ã³ããã³ @ServerResponseFilter
ã¢ããã¼ã·ã§ã³ã§å®è£
ã§ããã
ref: ãªã¯ã¨ã¹ãã¾ãã¯ã¬ã¹ãã³ã¹ãã£ã«ã¿ã¼
OpenAPIç·¨
OpenAPIå®ç¾©ãçæããã
quarkus-smallrye-openapi
æ¡å¼µãå°å
¥ãããã¨ã§ã /q/openapi?format=json
ããOpenAPIå®ç¾©ãæã«å
¥ãããã¨ãã§ããã
ref: https://ja.quarkus.io/guides/openapi-swaggerui#expose-openapi-specifications
info
ã tags
ãªã©ã追å ã§å®ç¾©ãããå ´åã¯2ã¤ã®æ¹æ³ãããã1ã¤ã¯ @OpenAPIDefinition
ã¢ããã¼ã·ã§ã³ãå©ç¨ããæ¹æ³ããã1ã¤ã¯è¨å®ãã¡ã¤ã« application.{properties|yaml}
ãå©ç¨ããæ¹æ³ã
ã©ã£ã¡ããããã¯å¥½ã¿ã? ã¤ãã§ã«Swagger-uiãçããã http://localhost:8080/q/swagger-ui
ref: ã¢ããªã±ã¼ã·ã§ã³ã¬ãã«ã®OpenAPIã¢ããã¼ã·ã§ã³ã®æä¾
OpenAPIå®ç¾©ããçæãããã¡ã½ããåãããæãã«ãã¦æ¬²ãã
OpenAPIå®ç¾©ããçæãããå®è£
ã¯ãOperationID
ãå
ã«ã¡ã½ããåã決ãã(ãã¨ãä»æ§?)ãã¡ã½ããæ¯ã« @OperationID
ã¢ããã¼ã·ã§ã³ãå©ç¨ãããã¨ãã§ããããè¨å®ãã¡ã¤ã«ã«ä»¥ä¸ã®ããã«æ¸ãã¨ã¡ã½ããåããã®ã¾ã¾å©ç¨ã§ããã
mp.openapi.extensions.smallrye.operationIdStrategy=METHOD
ãã®è¾ºã®OpenAPIã®å®è£ 㯠SmallRye ã¨ããããã¸ã§ã¯ãã®è³ç£ãæµç¨ãã¦ããã£ã½ãã®ã§æ·±æãå ´åã¯ãã¡ããã
ref:
èªåãã¹ãç³»(T.B.D.)
quarkus-junit5
æ¡å¼µã«ãããã¹ããã¬ã¼ã ã¯ã¼ã¯ãå°å
¥åºæ¥ãã£ã½ããBDDå³ãããã®ã¨ãQuarkusãWAFã§ããããã¨ã³ããã¤ã³ãåä½ã®ãã¹ããã¹ã³ã¼ãã£ã½ãã
ãã®ä»
æ§é åãã°ãåºåããã
DataDogãCloud Loggingã«ãã°ãåºããªããæ§é åãã°ã«ãããã¨ãæã¾ããã
quarkus-logging-json
æ¡å¼µãå°å
¥ããã¨èªåçã«æ§é åãã°ãåºåããããç´°ããè¨å®ã¯ã¬ã¤ãè¨äºãè¦ã¦ã»ããã
æ¡å¼µãç°¡åã«æ¢ããã
IntelliJã使ã£ã¦ããå ´åã¯pom.xmlã®dependenciesãããã¤ã¢ãã°ãå¼ã³åºããã¨ãã§ããã