Deutsch   English   Français   Italiano  
<q4idnSKRjoEVIb_7nZ2dnZfqn_adnZ2d@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 18:48:40 +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>
From: Ross Finlayson <ross.a.finlayson@gmail.com>
Date: Fri, 19 Apr 2024 11:49:30 -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: <WqWdnZlV5tCGNb_7nZ2dnZfqnPSdnZ2d@giganews.com>
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: 7bit
Message-ID: <q4idnSKRjoEVIb_7nZ2dnZfqn_adnZ2d@giganews.com>
Lines: 780
X-Usenet-Provider: http://www.giganews.com
X-Trace: sv3-JJT6qqb5CS+wmLXoAh/TDPugsFvjoTuyaOljMiS1IQT7Lx8CV/g75S5/wFBuALDwgV/WIPvG97/LXP8!nwode08Ja7Jo7FpbjMElMbEBPU3Z2f3aVaVFFO6emt0Bh9BcrTOvJwuaOEtv4OWn4aLtPH/dmT2g!ow==
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: 30270

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
>>              Rsp get1(
>>                  @PathVariable("myGrpId") Pth pth,
========== REMAINDER OF ARTICLE TRUNCATED ==========