Deutsch   English   Français   Italiano  
<S3ednfNU6sAbRb_7nZ2dnZfqnPqdnZ2d@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 20:48:06 +0000
Subject: Re: Java HTTP API Signatures, schemas, XML and JSON, Pojo's and
 Poji's, Java and Spring and schema
Newsgroups: comp.lang.java.programmer
References: <2imdnULqbvFsBr_7nZ2dnZfqn_qdnZ2d@giganews.com>
 <WqWdnZlV5tCGNb_7nZ2dnZfqnPSdnZ2d@giganews.com>
 <q4idnSKRjoEVIb_7nZ2dnZfqn_adnZ2d@giganews.com>
From: Ross Finlayson <ross.a.finlayson@gmail.com>
Date: Fri, 19 Apr 2024 13:48:59 -0700
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101
 Thunderbird/38.6.0
MIME-Version: 1.0
In-Reply-To: <q4idnSKRjoEVIb_7nZ2dnZfqn_adnZ2d@giganews.com>
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: 7bit
Message-ID: <S3ednfNU6sAbRb_7nZ2dnZfqnPqdnZ2d@giganews.com>
Lines: 1040
X-Usenet-Provider: http://www.giganews.com
X-Trace: sv3-wlY3y4b5ff9DZj4bNgC3TR7Hx6j4mDdD5xcRWGCjiC5zTla7KW6nYjVxSoQ3dPTPVtuXrxBKmfMi/Sg!2r0zxyPu/46X4b7Avgs0aR3uS7fS17wzHkJc/E4F0Rybufgk2UmuG2OSxqrNR7nfmbh/g9hdA0Lp!8g==
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: 41091

On 04/19/2024 11:49 AM, Ross Finlayson wrote:
> On 04/19/2024 10:22 AM, Ross Finlayson wrote:
>> On 04/19/2024 09:30 AM, Ross Finlayson wrote:
>>> 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
========== REMAINDER OF ARTICLE TRUNCATED ==========