Hi Romain, you are right with your points and I've tried to apply them. The Request.parameters() method might be solvable more elegantly. Only streams were a bit unclear to me, but I did it as I understood it for now (correct me if I got it wrong): the user writes/casts his intended output to a ByteArrayInputStream, which is handed over to netty that transforms it to its actual output (maybe ChannelBufferOutputStream, but I have yet to figure it out). Let me know what you think of the current state, please. Once again the repo link, just for convenience. https://github.com/a-rekkusu/owb-centric-microserver
Thanks and best regards, Alex On 18.06.2020 15:26, Romain Manni-Bucau wrote: > Should matching be an array? If so how would you impl it? (it is associated > with "url" or another parameter for its config, for instance EXACT + path > so i don't see how it would work to support EXACT and WILDCARD at the same > time for ex). > In Request ensure to return Map<String, List<String>> and not > HashMap<String, String> (it is not a hashmap cause headers are case > insensitive for ex, a TreeMap(String.CASE_INSENSITIVE) is better IMHO but > no need to expose the impl). > Parameters should likely be split in body parameters (form data) and query > parameters (so getParameter(String) would be a facade to 2 get in query and > form maps). > Kind of the same remark on the response (for HashMap) + payload is an > InputStream. This one requires some explanation: > > 1. Using a ByteArrayOutputStream is quite limiting since you drop all > decorations and oversized payload support > 2. An outputstream requires the server to know how to map this object to > something readable (input stream or the reactive equivalent) > 3. output stream will likely require the server to inject the instance once > 1 is fixed which is something we should try to avoid > > Now if you move to an Inputstream you can consumer it easily from the > server point of view, wrap it easily (in a filter for ex) and setting the > output is as easy: > > setOutput(new ByteArrayInputStream(...)); > + the user friendly flavor(s): setOutput(String) (which does the > setoutput(inputStream) + setHeader(content-length)) > > Romain Manni-Bucau > @rmannibucau <https://twitter.com/rmannibucau> | Blog > <https://rmannibucau.metawerx.net/> | Old Blog > <http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> | > LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book > <https://www.packtpub.com/application-development/java-ee-8-high-performance> > > > Le jeu. 18 juin 2020 à 14:58, Alexander Fischer <fische...@mailbox.org> a > écrit : > >> Hey Romain, >> >> thanks for the feedback! I have implemented the API feedback now, please >> take another look: >> https://github.com/a-rekkusu/owb-centric-microserver >> >> Are there functionalities that you miss? >> Else, the Netty implementation ist next. >> >> Best regards, >> Alex >> >> On 16.06.2020 14:04, Romain Manni-Bucau wrote: >>> Hi Alex, >>> >>> I don't think you need the HttpHandler annotation to be a qualifier (will >>> typically end up on a method not producing any bean at some point I think >>> as in the example at the end of this answer). >>> I guess Request/Response models are not yet done? Side note before you >> work >>> on them: maybe don't copy servlet API, content-type, content-length etc >> are >>> just headers, no need to make them specific, also prefer to set the >> payload >>> (as an inputstream or reactive stream) rather than encapsulating >> read/write >>> methods, it enables a better composition and decoration in general and >>> bypasses to go through a provider/factory to create requests/responses. >>> Last thing is you probably want to create a package for that work and not >>> use the default one ;). >>> >>> Typically it is a good start IMHO and once this works I'd do another >> small >>> iteration to end up on: >>> >>> public class HelloWorldHandlerFuture >>> { >>> @HttpHandler(method = {HttpMethod.GET, HttpMethod.POST}, url = "/hello", >>> matching = Matching.EXACT) >>> public CompletionStage<Response> apply(Request request) >>> { >>> return CompletableFuture.supplyAsync(() -> >>> { >>> Response response = new Response(); >>> response.setStatus(200); >>> response.write("Hello World from " + getClass().getName()); >>> return response; >>> }); >>> } >>> } >>> >>> Small side note (fully related to CompletionStage more than your current >>> work: if you want a synchronous impl of a CompletionStage you can use >>> CompletionFuture.completedFuture(response) - avoid the sypplyAsync - and >> if >>> you want to be async (sypplyAsync) ensure you pass an executor as second >>> parameter otherwise you end up being in default ForkJoinPool which has a >>> lot of side effects and limitations. >>> >>> Anyway, very good first iteration, it is pretty close to what I was >>> envisioning and it looks as smooth as I was thinking. >>> >>> Small tip for the impl phase (don't know if it is the next one or not): >> for >>> the handler registration, ensure to enable to do it programmatically: >>> register(Function<Request, CompletionStage<Response>>). It will enable to >>> use other models than the annotated one which is just a simplified API of >>> the actual one the server uses internally. >>> >>> Romain Manni-Bucau >>> @rmannibucau <https://twitter.com/rmannibucau> | Blog >>> <https://rmannibucau.metawerx.net/> | Old Blog >>> <http://rmannibucau.wordpress.com> | Github < >> https://github.com/rmannibucau> | >>> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book >>> < >> https://www.packtpub.com/application-development/java-ee-8-high-performance >>> >>> >>> Le mar. 16 juin 2020 à 13:08, Alexander Fischer <fische...@mailbox.org> >> a >>> écrit : >>> >>>> Hi Romain, >>>> >>>> I have made a first draft for the API and example showcase: >>>> https://github.com/a-rekkusu/owb-centric-microserver >>>> >>>> Please take a look and let me know what you think. >>>> CompletionStage is supported, but right now for all requests on a >>>> handler. If you would want a CompletableFuture only for POST for >>>> example, and not on GET, how do you think we should handle that? >>>> We could do it with a second HttpHandler on the same url but with the >>>> respective HttpMethod (e. g. HelloWorldHandlerGet / >> HelloWorldHandlerPost). >>>> Kind regards, >>>> Alex >>>> >>>> On 06.06.2020 15:44, Romain Manni-Bucau wrote: >>>>> Hi Alex, >>>>> >>>>> Nothing is written in the stone but here is how I would approach that: >>>>> >>>>> 1. Write a HTTP server able to call a handler to answer a request - you >>>> can >>>>> start by giving a hardcoded handler but in terms of design, ensure you >>>> get >>>>> something taking a Request abstracting as input and a Response >>>> abstraction >>>>> as output. >>>>> Netty has these abstraction but we don't want to depend on netty so you >>>>> should duplicate it making it even more user friendly (netty stays low >>>>> level). >>>>> 2. Make this server CDI friendly, basically a CDI bean and nice to >> have, >>>>> configurable (port, ssl, ...) with MP-Config (or equivalent - if you >>>> take a >>>>> Map<String, String> as input you won here), >>>>> 3. Now you have to abstract the handler and make the default handler a >>>>> facade for user handlers. User handlers are CDI beans. I would start by >>>>> making them with something between servlet and jaxrs: >>>>> >>>>> @HttpHandler(method = {GET, POST}, url = "/foo", mathing = >>>> Matching.EXACT) >>>>> method being the http method handled, url the urlpattern matched thanks >>>> the >>>>> matching algo (i used an enum but it can be anything equivalent). EXACT >>>>> means request path == url, we can envision wildcard matching (as in >>>>> servlet), regex matching etc... >>>>> >>>>> The signature can start to be the exact expected one >>>>> (CompletionStage<Response> onRequest(Request)) while validated in the >> cdi >>>>> extension grabbing the handlers, then you can relax the CompletionStage >>>>> requirement (Response onReq(Request)) and finally you can go closer to >>>>> jaxrs adding @PathParam/@QueryParam/... like annotations but if Request >>>> API >>>>> is nice enough it is not required in this layer - it can be a layer on >>>> top >>>>> as jaxrs is on top of servlet. What's important here is to be reactive >>>>> friendly by design - I'll let you play with the threading strategies to >>>>> have an useful CompletionStage and how to link it - or not ;) - to >> netty >>>>> executors. >>>>> >>>>> Once handlers well done, it is easy to add filters on top of it, same >>>> kind >>>>> of API but it takes another optional parameter: >>>>> >>>>> CompletionStage<Response> onRequest(Request request, >>>>> Supplier<CompletionStage<Response>> proceed); >>>>> >>>>> with proceed the call to filter N+1 and finally the handler (check out >>>> OWB >>>>> interceptor impl, it is exactly the same. >>>>> >>>>> Last important point: ensure to handle @Priority (or add priority = int >>>>> in @HttpHandler) cause when you will implement the matching chain you >>>> will >>>>> need an order normally. >>>>> >>>>> Bonus: you can make the matching strategies pluggable if you want and >>>> just >>>>> provide some defaults OOTB. >>>>> >>>>> Hope it makes sense. >>>>> >>>>> Romain Manni-Bucau >>>>> @rmannibucau <https://twitter.com/rmannibucau> | Blog >>>>> <https://rmannibucau.metawerx.net/> | Old Blog >>>>> <http://rmannibucau.wordpress.com> | Github < >>>> https://github.com/rmannibucau> | >>>>> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book >>>>> < >> https://www.packtpub.com/application-development/java-ee-8-high-performance >>>>> >>>>> Le jeu. 4 juin 2020 à 15:35, Alexander Fischer <fische...@mailbox.org> >> a >>>>> écrit : >>>>> >>>>>> Hello everyone, >>>>>> >>>>>> in the last month I have spent most of my time getting to know coding >>>>>> basics of Maven, Netty, CDI/OWB and Servlets/Tomcat. I got to know CDI >>>>>> extensions which will be the technological foundation for the server. >>>>>> >>>>>> Next up will be defining and implementing the HTTP API, which will >> bring >>>>>> CDI and Netty together. Feel free to contribute your thoughts on the >>>>>> matter here on the mailing list or in the respective Jira issue: >>>>>> https://issues.apache.org/jira/projects/OWB/issues/OWB-1319 >>>>>> >>>>>> @Romain: can you share some ideas, annotations, interfaces for how you >>>>>> see the API roughly? Any kind of formal requirement-proposal would be >>>>>> helpful to start with. >>>>>> >>>>>> Thanks and best regards, >>>>>> Alexander >>>>>> >>>>>>