Warning: mysqli::__construct(): (HY000/1203): User howardkn already has more than 'max_user_connections' active connections in D:\Inetpub\vhosts\howardknight.net\al.howardknight.net\includes\artfuncs.php on line 21
Failed to connect to MySQL: (1203) User howardkn already has more than 'max_user_connections' active connections
Warning: mysqli::query(): Couldn't fetch mysqli in D:\Inetpub\vhosts\howardknight.net\al.howardknight.net\index.php on line 66
Article <2imdnULqbvFsBr_7nZ2dnZfqn_qdnZ2d@giganews.com>
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 ==========