Deutsch English Français Italiano |
<2imdnULqbvFsBr_7nZ2dnZfqn_qdnZ2d@giganews.com> View for Bookmarking (what is this?) Look up another Usenet article |
Path: ...!Xl.tags.giganews.com!local-1.nntp.ord.giganews.com!news.giganews.com.POSTED!not-for-mail NNTP-Posting-Date: Fri, 19 Apr 2024 16:29:37 +0000 Newsgroups: comp.lang.java.programmer X-Mozilla-News-Host: snews://giganews.com:443 From: Ross Finlayson <ross.a.finlayson@gmail.com> Subject: Java HTTP API Signatures, schemas, XML and JSON, Pojo's and Poji's, Java and Spring and schema Date: Fri, 19 Apr 2024 09:30:13 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.6.0 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Message-ID: <2imdnULqbvFsBr_7nZ2dnZfqn_qdnZ2d@giganews.com> Lines: 654 X-Usenet-Provider: http://www.giganews.com X-Trace: sv3-elVjsZS9/qjKlY5Cp0LbQO87UztaKs9x7zfnLg1NEcvO416dt/ps/3EMk2sdGwK+1Rhb5M1z85nla9g!csSgApj8eBPL5xd2gnzROFN0kmXzCOJnucXsBk6OQSC+BsWPSEg1UErunpcgmVF/BfyqZK9df8pu!iQ== X-Complaints-To: abuse@giganews.com X-DMCA-Notifications: http://www.giganews.com/info/dmca.html X-Abuse-and-DMCA-Info: Please be sure to forward a copy of ALL headers X-Abuse-and-DMCA-Info: Otherwise we will be unable to process your complaint properly X-Postfilter: 1.3.40 Bytes: 22281 Signature API ccc.api ccc.api.exception ccc.api.fault ccc.api.client ccc.springsup.web ccc.serdes Api ApiMapping ApiFlt ApiHardFlt OtherCauseFault CovariantFault Pth Hdr Qpa Req Rsp Flt Err The other day I was writing a Spring Boot server, and the implementation of the Api looks like this For a service Srv, group of APIs Grp, and API Api public interface Srv { interface Grp { interface Api extends ccc.api.Api { static class Pth{} static class Qpa{} static class Hdr{} static class Req{} static class Rsp{} static class Flt{} static class Err{} Rsp api( @Valid @NotNull Pth pth, @Valid @NotNull Qpa qpa, @Valid @NotNull Hdr hdr, @Valid @NotNull Req req ) throws ApiFlt; } } } The validation annotations have to be on the root type, so, they go on the Api. public interface SrvMapping { interface Grp { @RequestMapping interface Api extends Srv.Grp.Api, ApiMapping { @Override @GetMapping("/api/{pth}") @ResponseBody Rsp api( @PathVariable Pth pth, @QueryParam Qpa qpa, @RequestHeader Hdr hdr, @RequestBody Req req ) throws ApiFlt; } } } The request mapping and also the openapi or documentation interfaces have to be on the interface the controller implements, and they don't mean anything to the Api, so they go on the ApiMapping. @Controller public class SrvController implements SrvMapping.Grp.Api { @Override Srv.Grp.Rsp api( Srv.Grp.Pth pth, Srv.Grp.Qpa qpa, Srv.Grp.Hdr hdr, Srv.Grp.Req req ) throws ApiFlt; } The controller just implements the Api, Spring Web wires it up and Openapi documents it up. And it results sort of thusly a very simple organization of APIs. public interface Srv { interface Grp1 { interface Api1 { /* */ } interface Api2 { /* */ } interface Api3 { /* */ } interface Api4 { /* */ } } interface Grp@ { interface Api1 { /* */ } interface Api2 { /* */ } interface Api3 { /* */ } interface Api4 { /* */ } } /* */ } The key is that given those, the Api and ApiMapping an entire Signature, of the mapping, sort of results, with adding this sort of ApiStatusMapping, to relate the HTTP status codes, with, the covariant return bodies, then it's sort of all one thing. ("a functional interface may still have multiple default methods ...") The idea is that the interfaces carry very well down from these. For most often usual "APIs" these days it'd often look: @Data static class MyGrp { } public interface Srv { interface Grp { interface Get1 extends ccc.api.Api { static class Pth{ String myGrpId;} static class Req extends MyGrp{}; static class Rsp{} static class Flt{} static class Err{} Rsp get1( @Valid @NotNull Pth pth, @Valid @NotNull Req req ) throws ApiFlt; } interface Put1 extends ccc.api.Api { static class Pth{ String myGrpId;} static class Req extends MyGrp{} static class Rsp{} static class Flt{} static class Err{} Rsp put1( @Valid @NotNull Pth pth, @Valid @NotNull Req req ) throws ApiFlt; } } } public interface SrvMapping { interface Grp { @RequestMapping interface Api extends Srv.Grp.Get1, ApiMapping { @Override @GetMapping("/grp/{myGrpId}") @ResponseBody Rsp get1( @PathVariable("myGrpId") Pth pth, @RequestBody Req req ) throws ApiFlt; } ========== REMAINDER OF ARTICLE TRUNCATED ==========