From 224c7c117be1a9a331e7c86f9fdc465f98e976b4 Mon Sep 17 00:00:00 2001 From: Sashir Estela Date: Fri, 22 Mar 2024 21:36:00 +0000 Subject: [PATCH 1/3] Add Event class for handling SSE --- .../sashirestela/cleverclient/Event.java | 13 ++++++++++ ...r.java => HttpAsyncStreamEventSender.java} | 14 ++++++---- .../sender/HttpSenderFactory.java | 4 +-- ...er.java => HttpSyncStreamEventSender.java} | 14 ++++++---- .../cleverclient/support/CleverClientSSE.java | 19 +++++++++----- .../cleverclient/support/ReturnType.java | 26 +++++++++++-------- .../cleverclient/http/HttpProcessorTest.java | 14 +++++----- .../sashirestela/cleverclient/http/ITest.java | 5 ++-- .../support/CleverClientSSETest.java | 5 ++-- .../cleverclient/support/ReturnTypeTest.java | 17 ++++++------ 10 files changed, 81 insertions(+), 50 deletions(-) create mode 100644 src/main/java/io/github/sashirestela/cleverclient/Event.java rename src/main/java/io/github/sashirestela/cleverclient/sender/{HttpAsyncStreamObjectSender.java => HttpAsyncStreamEventSender.java} (70%) rename src/main/java/io/github/sashirestela/cleverclient/sender/{HttpSyncStreamObjectSender.java => HttpSyncStreamEventSender.java} (74%) diff --git a/src/main/java/io/github/sashirestela/cleverclient/Event.java b/src/main/java/io/github/sashirestela/cleverclient/Event.java new file mode 100644 index 0000000..30d865f --- /dev/null +++ b/src/main/java/io/github/sashirestela/cleverclient/Event.java @@ -0,0 +1,13 @@ +package io.github.sashirestela.cleverclient; + +import lombok.Builder; +import lombok.Value; + +@Value +@Builder +public class Event { + + String name; + Object data; + +} diff --git a/src/main/java/io/github/sashirestela/cleverclient/sender/HttpAsyncStreamObjectSender.java b/src/main/java/io/github/sashirestela/cleverclient/sender/HttpAsyncStreamEventSender.java similarity index 70% rename from src/main/java/io/github/sashirestela/cleverclient/sender/HttpAsyncStreamObjectSender.java rename to src/main/java/io/github/sashirestela/cleverclient/sender/HttpAsyncStreamEventSender.java index c97eb3f..1430755 100644 --- a/src/main/java/io/github/sashirestela/cleverclient/sender/HttpAsyncStreamObjectSender.java +++ b/src/main/java/io/github/sashirestela/cleverclient/sender/HttpAsyncStreamEventSender.java @@ -1,5 +1,6 @@ package io.github.sashirestela.cleverclient.sender; +import io.github.sashirestela.cleverclient.Event; import io.github.sashirestela.cleverclient.support.CleverClientSSE; import io.github.sashirestela.cleverclient.support.CleverClientSSE.LineRecord; import io.github.sashirestela.cleverclient.support.ReturnType; @@ -10,7 +11,7 @@ import java.net.http.HttpResponse.BodyHandlers; import java.util.stream.Stream; -public class HttpAsyncStreamObjectSender extends HttpSender { +public class HttpAsyncStreamEventSender extends HttpSender { @Override public Object sendRequest(HttpClient httpClient, HttpRequest httpRequest, ReturnType returnType) { @@ -22,17 +23,20 @@ public Object sendRequest(HttpClient httpClient, HttpRequest httpRequest, Return throwExceptionIfErrorIsPresent(response, Stream.class); final var lineRecord = new LineRecord(); - final var eventsWithHeader = returnType.getClassByEvent().keySet(); + final var events = returnType.getClassByEvent().keySet(); return response.body() .map(line -> { logger.debug("Response : {}", line); lineRecord.updateWith(line); - return new CleverClientSSE(lineRecord, eventsWithHeader); + return new CleverClientSSE(lineRecord, events); }) .filter(CleverClientSSE::isActualData) - .map(item -> JsonUtil.jsonToObject(item.getActualData(), - returnType.getClassByEvent().get(item.getMatchedEvent()))); + .map(item -> Event.builder() + .name(item.getMatchedEvent()) + .data(JsonUtil.jsonToObject(item.getActualData(), + returnType.getClassByEvent().get(item.getMatchedEvent()))) + .build()); }); } diff --git a/src/main/java/io/github/sashirestela/cleverclient/sender/HttpSenderFactory.java b/src/main/java/io/github/sashirestela/cleverclient/sender/HttpSenderFactory.java index b767855..25da3c2 100644 --- a/src/main/java/io/github/sashirestela/cleverclient/sender/HttpSenderFactory.java +++ b/src/main/java/io/github/sashirestela/cleverclient/sender/HttpSenderFactory.java @@ -22,14 +22,14 @@ public class HttpSenderFactory { private HttpSenderFactory() { sendersMap = new EnumMap<>(Category.class); - sendersMap.put(Category.ASYNC_STREAM_OBJECT, HttpAsyncStreamObjectSender::new); + sendersMap.put(Category.ASYNC_STREAM_EVENT, HttpAsyncStreamEventSender::new); sendersMap.put(Category.ASYNC_STREAM, HttpAsyncStreamSender::new); sendersMap.put(Category.ASYNC_LIST, HttpAsyncListSender::new); sendersMap.put(Category.ASYNC_GENERIC, HttpAsyncGenericSender::new); sendersMap.put(Category.ASYNC_CUSTOM, HttpAsyncCustomSender::new); sendersMap.put(Category.ASYNC_BINARY, HttpAsyncBinarySender::new); sendersMap.put(Category.ASYNC_PLAIN_TEXT, HttpAsyncPlainTextSender::new); - sendersMap.put(Category.SYNC_STREAM_OBJECT, HttpSyncStreamObjectSender::new); + sendersMap.put(Category.SYNC_STREAM_EVENT, HttpSyncStreamEventSender::new); sendersMap.put(Category.SYNC_STREAM, HttpSyncStreamSender::new); sendersMap.put(Category.SYNC_LIST, HttpSyncListSender::new); sendersMap.put(Category.SYNC_GENERIC, HttpSyncGenericSender::new); diff --git a/src/main/java/io/github/sashirestela/cleverclient/sender/HttpSyncStreamObjectSender.java b/src/main/java/io/github/sashirestela/cleverclient/sender/HttpSyncStreamEventSender.java similarity index 74% rename from src/main/java/io/github/sashirestela/cleverclient/sender/HttpSyncStreamObjectSender.java rename to src/main/java/io/github/sashirestela/cleverclient/sender/HttpSyncStreamEventSender.java index c031405..af55b07 100644 --- a/src/main/java/io/github/sashirestela/cleverclient/sender/HttpSyncStreamObjectSender.java +++ b/src/main/java/io/github/sashirestela/cleverclient/sender/HttpSyncStreamEventSender.java @@ -1,5 +1,6 @@ package io.github.sashirestela.cleverclient.sender; +import io.github.sashirestela.cleverclient.Event; import io.github.sashirestela.cleverclient.support.CleverClientException; import io.github.sashirestela.cleverclient.support.CleverClientSSE; import io.github.sashirestela.cleverclient.support.CleverClientSSE.LineRecord; @@ -12,7 +13,7 @@ import java.net.http.HttpResponse.BodyHandlers; import java.util.stream.Stream; -public class HttpSyncStreamObjectSender extends HttpSender { +public class HttpSyncStreamEventSender extends HttpSender { @Override public Object sendRequest(HttpClient httpClient, HttpRequest httpRequest, ReturnType returnType) { @@ -23,17 +24,20 @@ public Object sendRequest(HttpClient httpClient, HttpRequest httpRequest, Return throwExceptionIfErrorIsPresent(httpResponse, Stream.class); final var lineRecord = new LineRecord(); - final var eventsWithHeader = returnType.getClassByEvent().keySet(); + final var events = returnType.getClassByEvent().keySet(); return httpResponse.body() .map(line -> { logger.debug("Response : {}", line); lineRecord.updateWith(line); - return new CleverClientSSE(lineRecord, eventsWithHeader); + return new CleverClientSSE(lineRecord, events); }) .filter(CleverClientSSE::isActualData) - .map(item -> JsonUtil.jsonToObject(item.getActualData(), - returnType.getClassByEvent().get(item.getMatchedEvent()))); + .map(item -> Event.builder() + .name(item.getMatchedEvent()) + .data(JsonUtil.jsonToObject(item.getActualData(), + returnType.getClassByEvent().get(item.getMatchedEvent()))) + .build()); } catch (IOException | InterruptedException e) { Thread.currentThread().interrupt(); diff --git a/src/main/java/io/github/sashirestela/cleverclient/support/CleverClientSSE.java b/src/main/java/io/github/sashirestela/cleverclient/support/CleverClientSSE.java index a8d37d5..371f8dd 100644 --- a/src/main/java/io/github/sashirestela/cleverclient/support/CleverClientSSE.java +++ b/src/main/java/io/github/sashirestela/cleverclient/support/CleverClientSSE.java @@ -5,28 +5,28 @@ public class CleverClientSSE { - public static final String EVENT_HEADER = "event: "; + private static final String EVENT_HEADER = "event: "; private static final String DATA_HEADER = "data: "; private static final String SEPARATOR = ""; private LineRecord lineRecord; private List endsOfStream; - private Set eventsWithHeader; + private Set events; public CleverClientSSE(LineRecord lineRecord) { this.lineRecord = lineRecord; this.endsOfStream = Configurator.one().getEndsOfStream(); - this.eventsWithHeader = Set.of(SEPARATOR); + this.events = Set.of(SEPARATOR); } - public CleverClientSSE(LineRecord lineRecord, Set eventsWithHeader) { + public CleverClientSSE(LineRecord lineRecord, Set events) { this.lineRecord = lineRecord; this.endsOfStream = Configurator.one().getEndsOfStream(); - this.eventsWithHeader = eventsWithHeader; + this.events = events; } public boolean isActualData() { - return eventsWithHeader.contains(lineRecord.previous()) && lineRecord.current().startsWith(DATA_HEADER) + return isMatchedEvent() && lineRecord.current().startsWith(DATA_HEADER) && endsOfStream.stream().anyMatch(eos -> !lineRecord.current().contains(eos)); } @@ -34,8 +34,13 @@ public String getActualData() { return lineRecord.current().replace(DATA_HEADER, "").strip(); } + private boolean isMatchedEvent() { + return events.stream() + .anyMatch(ev -> lineRecord.previous().equals((ev.equals(SEPARATOR) ? SEPARATOR : EVENT_HEADER + ev))); + } + public String getMatchedEvent() { - return eventsWithHeader.contains(lineRecord.previous()) ? lineRecord.previous() : null; + return isMatchedEvent() ? lineRecord.previous().replace(EVENT_HEADER, "").strip() : null; } public static class LineRecord { diff --git a/src/main/java/io/github/sashirestela/cleverclient/support/ReturnType.java b/src/main/java/io/github/sashirestela/cleverclient/support/ReturnType.java index b2b8d15..0ba7b30 100644 --- a/src/main/java/io/github/sashirestela/cleverclient/support/ReturnType.java +++ b/src/main/java/io/github/sashirestela/cleverclient/support/ReturnType.java @@ -14,7 +14,7 @@ public class ReturnType { private static final String LIST = "java.util.List"; private static final String INPUTSTREAM = "java.io.InputStream"; private static final String STRING = "java.lang.String"; - private static final String OBJECT = "java.lang.Object"; + private static final String EVENT = "io.github.sashirestela.cleverclient.Event"; private static final String REGEX = "[<>]"; private static final String JAVA_PCK = "java"; @@ -38,6 +38,10 @@ public ReturnType(String fullClassName) { public ReturnType(Method method) { this(method.getGenericReturnType().getTypeName()); + setClassByEventIfExists(method); + } + + private void setClassByEventIfExists(Method method) { if (method.isAnnotationPresent(StreamType.List.class)) { this.classByEvent = calculateClassByEvent( method.getDeclaredAnnotationsByType(StreamType.List.class)[0].value()); @@ -51,7 +55,7 @@ private Map> calculateClassByEvent(StreamType[] streamTypeList) Map> map = new ConcurrentHashMap<>(); Arrays.stream(streamTypeList).forEach(streamType -> { Arrays.stream(streamType.events()) - .forEach(event -> map.put(CleverClientSSE.EVENT_HEADER + event, streamType.type())); + .forEach(event -> map.put(event, streamType.type())); }); return map; } @@ -96,8 +100,8 @@ public Category category() { private Category asyncCategory() { if (isStream()) { - if (isObject()) { - return Category.ASYNC_STREAM_OBJECT; + if (isEvent()) { + return Category.ASYNC_STREAM_EVENT; } else { return Category.ASYNC_STREAM; } @@ -118,8 +122,8 @@ private Category asyncCategory() { private Category syncCategory() { if (isStream()) { - if (isObject()) { - return Category.SYNC_STREAM_OBJECT; + if (isEvent()) { + return Category.SYNC_STREAM_EVENT; } else { return Category.SYNC_STREAM; } @@ -156,7 +160,7 @@ private boolean isGeneric() { } private boolean isCustom() { - return !isInputStream() && !isString() && !isObject() && (size == 1 || (size == 2 && isAsync())); + return !isInputStream() && !isString() && !isEvent() && (size == 1 || (size == 2 && isAsync())); } private boolean isBinary() { @@ -175,19 +179,19 @@ private boolean isString() { return STRING.equals(returnTypeArray[lastIndex]); } - private boolean isObject() { - return OBJECT.equals(returnTypeArray[lastIndex]); + private boolean isEvent() { + return EVENT.equals(returnTypeArray[lastIndex]); } public enum Category { - ASYNC_STREAM_OBJECT, + ASYNC_STREAM_EVENT, ASYNC_STREAM, ASYNC_LIST, ASYNC_GENERIC, ASYNC_CUSTOM, ASYNC_BINARY, ASYNC_PLAIN_TEXT, - SYNC_STREAM_OBJECT, + SYNC_STREAM_EVENT, SYNC_STREAM, SYNC_LIST, SYNC_GENERIC, diff --git a/src/test/java/io/github/sashirestela/cleverclient/http/HttpProcessorTest.java b/src/test/java/io/github/sashirestela/cleverclient/http/HttpProcessorTest.java index 4884ad7..eec3823 100644 --- a/src/test/java/io/github/sashirestela/cleverclient/http/HttpProcessorTest.java +++ b/src/test/java/io/github/sashirestela/cleverclient/http/HttpProcessorTest.java @@ -208,7 +208,7 @@ void shouldThrownExceptionWhenMethodReturnTypeIsAStream() throws IOException, In } @Test - void shouldReturnAStreamSyncWhenMethodReturnTypeIsAStreamObject() throws IOException, InterruptedException { + void shouldReturnAStreamSyncWhenMethodReturnTypeIsAStreamEvent() throws IOException, InterruptedException { when(httpClient.send(any(HttpRequest.class), any(HttpResponse.BodyHandlers.ofLines().getClass()))) .thenReturn(httpResponseStream); when(httpResponseStream.statusCode()).thenReturn(HttpURLConnection.HTTP_OK); @@ -217,8 +217,8 @@ void shouldReturnAStreamSyncWhenMethodReturnTypeIsAStreamObject() throws IOExcep "data: {\"id\":100,\"description\":\"Description\",\"active\":true}")); var service = httpProcessor.createProxy(ITest.SyncService.class); - var actualStreamObject = service.getStreamObject(new ITest.RequestDemo("Descr", null)); - var actualObject = actualStreamObject.findFirst().get(); + var actualStreamObject = service.getStreamEvent(new ITest.RequestDemo("Descr", null)); + var actualObject = actualStreamObject.findFirst().get().getData(); var expectedObject = new ITest.Demo(100, "Description", true); assertEquals(expectedObject, actualObject); @@ -231,7 +231,7 @@ void shouldThrownExceptionWhenMethodReturnTypeIsAStreamObject() throws IOExcepti var service = httpProcessor.createProxy(ITest.SyncService.class); var requestDemo = new ITest.RequestDemo("Descr", null); - assertThrows(CleverClientException.class, () -> service.getStreamObject(requestDemo)); + assertThrows(CleverClientException.class, () -> service.getStreamEvent(requestDemo)); } @Test @@ -325,7 +325,7 @@ void shouldReturnAStreamAsyncWhenMethodReturnTypeIsAStream() { } @Test - void shouldReturnAStreamAsyncWhenMethodReturnTypeIsAStreamObject() { + void shouldReturnAStreamAsyncWhenMethodReturnTypeIsAStreamEvent() { when(httpClient.sendAsync(any(HttpRequest.class), any(HttpResponse.BodyHandlers.ofLines().getClass()))) .thenReturn(CompletableFuture.completedFuture(httpResponseStream)); when(httpResponseStream.statusCode()).thenReturn(HttpURLConnection.HTTP_OK); @@ -334,8 +334,8 @@ void shouldReturnAStreamAsyncWhenMethodReturnTypeIsAStreamObject() { "data: {\"id\":100,\"description\":\"Description\",\"active\":true}")); var service = httpProcessor.createProxy(ITest.AsyncService.class); - var actualStreamObject = service.getStreamObject(new ITest.RequestDemo("Descr", null)).join(); - var actualObject = actualStreamObject.findFirst().get(); + var actualStreamObject = service.getStreamEvent(new ITest.RequestDemo("Descr", null)).join(); + var actualObject = actualStreamObject.findFirst().get().getData(); var expectedObject = new ITest.Demo(100, "Description", true); assertEquals(expectedObject, actualObject); diff --git a/src/test/java/io/github/sashirestela/cleverclient/http/ITest.java b/src/test/java/io/github/sashirestela/cleverclient/http/ITest.java index a0daedd..d054a2c 100644 --- a/src/test/java/io/github/sashirestela/cleverclient/http/ITest.java +++ b/src/test/java/io/github/sashirestela/cleverclient/http/ITest.java @@ -1,5 +1,6 @@ package io.github.sashirestela.cleverclient.http; +import io.github.sashirestela.cleverclient.Event; import io.github.sashirestela.cleverclient.annotation.Body; import io.github.sashirestela.cleverclient.annotation.GET; import io.github.sashirestela.cleverclient.annotation.Header; @@ -86,7 +87,7 @@ interface AsyncService { @POST @StreamType(type = Demo.class, events = { "created", "completed" }) @StreamType(type = String.class, events = { "delta" }) - CompletableFuture> getStreamObject(@Body RequestDemo request); + CompletableFuture> getStreamEvent(@Body RequestDemo request); @Multipart @POST @@ -122,7 +123,7 @@ interface SyncService { @POST @StreamType(type = Demo.class, events = { "created" }) - Stream getStreamObject(@Body RequestDemo request); + Stream getStreamEvent(@Body RequestDemo request); } diff --git a/src/test/java/io/github/sashirestela/cleverclient/support/CleverClientSSETest.java b/src/test/java/io/github/sashirestela/cleverclient/support/CleverClientSSETest.java index 924efb0..1e3ee90 100644 --- a/src/test/java/io/github/sashirestela/cleverclient/support/CleverClientSSETest.java +++ b/src/test/java/io/github/sashirestela/cleverclient/support/CleverClientSSETest.java @@ -10,7 +10,7 @@ class CleverClientSSETest { - Set events = Set.of("event: process", "event: process2"); + Set events = Set.of("process", "process2"); @BeforeAll static void setup() { @@ -52,8 +52,7 @@ void shouldReturnCleanDataWhenRawDataMeetsConditions() { @Test void shouldReturnExpectedMatcheEventWhenRawDataMeetsConditions() { Object[][] testData = { - { new CleverClientSSE(new LineRecord("event: process", "data: Actual data."), events), - "event: process" }, + { new CleverClientSSE(new LineRecord("event: process", "data: Actual data."), events), "process" }, { new CleverClientSSE(new LineRecord("event: other", "data: Actual data."), events), null }, { new CleverClientSSE(new LineRecord("", "data: Actual data.")), "" } }; diff --git a/src/test/java/io/github/sashirestela/cleverclient/support/ReturnTypeTest.java b/src/test/java/io/github/sashirestela/cleverclient/support/ReturnTypeTest.java index bae5b3d..4f9a7b0 100644 --- a/src/test/java/io/github/sashirestela/cleverclient/support/ReturnTypeTest.java +++ b/src/test/java/io/github/sashirestela/cleverclient/support/ReturnTypeTest.java @@ -1,5 +1,6 @@ package io.github.sashirestela.cleverclient.support; +import io.github.sashirestela.cleverclient.Event; import io.github.sashirestela.cleverclient.annotation.StreamType; import org.junit.jupiter.api.Test; @@ -28,14 +29,14 @@ void shouldReturnBaseClassForAMethod() throws NoSuchMethodException, SecurityExc @Test void shouldReturnCategoryAccordingToTheMethodType() throws NoSuchMethodException, SecurityException { var testData = Map.ofEntries( - Map.entry("asyncStreamObjectMethod", ReturnType.Category.ASYNC_STREAM_OBJECT), + Map.entry("asyncStreamEventMethod", ReturnType.Category.ASYNC_STREAM_EVENT), Map.entry("asyncStreamMethod", ReturnType.Category.ASYNC_STREAM), Map.entry("asyncListMethod", ReturnType.Category.ASYNC_LIST), Map.entry("asyncGenericMethod", ReturnType.Category.ASYNC_GENERIC), Map.entry("asyncMyClassMethod", ReturnType.Category.ASYNC_CUSTOM), Map.entry("asyncBinaryMethod", ReturnType.Category.ASYNC_BINARY), Map.entry("asyncStringMethod", ReturnType.Category.ASYNC_PLAIN_TEXT), - Map.entry("syncStreamObjectMethod", ReturnType.Category.SYNC_STREAM_OBJECT), + Map.entry("syncStreamEventMethod", ReturnType.Category.SYNC_STREAM_EVENT), Map.entry("syncStreamMethod", ReturnType.Category.SYNC_STREAM), Map.entry("syncListMethod", ReturnType.Category.SYNC_LIST), Map.entry("syncGenericMethod", ReturnType.Category.SYNC_GENERIC), @@ -64,13 +65,13 @@ void shouldReturnNullCategoryWhenMethodReturnTypeIsNotExpected() throws NoSuchMe @Test void shouldReturnMapClassByEventWhenTheMethodIsAnnotatedWithStreamType() throws NoSuchMethodException, SecurityException { - var method = TestInterface.class.getMethod("asyncStreamObjectMethod", new Class[] {}); + var method = TestInterface.class.getMethod("asyncStreamEventMethod", new Class[] {}); var returnType = new ReturnType(method); var actualMap = returnType.getClassByEvent(); var expectedMap = new ConcurrentHashMap<>(); - expectedMap.put(CleverClientSSE.EVENT_HEADER + "first.create", First.class); - expectedMap.put(CleverClientSSE.EVENT_HEADER + "first.complete", First.class); - expectedMap.put(CleverClientSSE.EVENT_HEADER + "second.create", Second.class); + expectedMap.put("first.create", First.class); + expectedMap.put("first.complete", First.class); + expectedMap.put("second.create", Second.class); assertEquals(Boolean.TRUE, expectedMap.equals(actualMap)); } @@ -78,7 +79,7 @@ static interface TestInterface { @StreamType(type = First.class, events = { "first.create", "first.complete" }) @StreamType(type = Second.class, events = { "second.create" }) - CompletableFuture> asyncStreamObjectMethod(); + CompletableFuture> asyncStreamEventMethod(); CompletableFuture> asyncStreamMethod(); @@ -94,7 +95,7 @@ static interface TestInterface { CompletableFuture> asyncSetMethod(); - Stream syncStreamObjectMethod(); + Stream syncStreamEventMethod(); Stream syncStreamMethod(); From 983d9714c4def72b308d3422b55cd07013411139 Mon Sep 17 00:00:00 2001 From: Sashir Estela Date: Fri, 22 Mar 2024 21:36:19 +0000 Subject: [PATCH 2/3] Update Readme --- README.md | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 94bd9db..b752b2c 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Library that makes it easy to use the Java HttpClient to perform http operations [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=sashirestela_cleverclient&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=sashirestela_cleverclient) [![codecov](https://codecov.io/gh/sashirestela/cleverclient/graph/badge.svg?token=PEYAFW3EWD)](https://codecov.io/gh/sashirestela/cleverclient) ![Maven Central](https://img.shields.io/maven-central/v/io.github.sashirestela/cleverclient) -![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/sashirestela/cleverclient/maven.yml) +![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/sashirestela/cleverclient/build_java_maven.yml) ### Table of Contents - [Description](#-description) @@ -162,7 +162,7 @@ var cleverClient = CleverClient.builder() | PUT | Method | PUT endpoint's url | optional | One | | DELETE | Method | DELETE endpoint's url | optional | One | | Multipart | Method | (None) | none | One | -| StreamType | Method | type class and events array | mandatory both | Many | +| StreamType | Method | class type and events array | mandatory both | Many | | Path | Parameter | Path parameter name in url | mandatory | One | | Query | Parameter | Query parameter name in url | mandatory | One | | Query | Parameter | (None for Pojos) | none | One | @@ -172,7 +172,7 @@ var cleverClient = CleverClient.builder() * ```Header``` Used to include more headers (pairs of name and value) at interface or method level. It is possible to have multiple Header annotations for the same target. * ```GET, POST, PUT, DELETE``` are used to mark the typical http methods (endpoints). * ```Multipart``` is used to mark an endpoint with a multipart/form-data request. This is required when you need to upload files. -* ```StreamType``` is used with methods whose return type is Stream of Objects. Commonly you will use more than one to indicate what class (type) is related to what events (array of Strings). +* ```StreamType``` is used with methods whose return type is Stream of [Event](./src/main/java/io/github/sashirestela/cleverclient/Event.java). Commonly you will use more than one to indicate what class (type) is related to what events (array of Strings). * ```Path``` is used to replace the path parameter name in url with the matched method parameter's value. * ```Query``` is used to add a query parameter to the url in the way: [?]queryValue=parameterValue[&...] for scalar parameters. Also it can be used for POJOs using its properties and values. * ```Body``` is used to mark a method parameter as the endpoint's payload request, so the request will be application/json at least the endpoint is annotated with Multipart. @@ -180,7 +180,7 @@ var cleverClient = CleverClient.builder() ### Supported Response Types -The reponse types are determined from the method responses. We don't need any annotation for that. We have six response types: [Stream](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/stream/Stream.html) of elements, [List](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/List.html) of elements, [Generic](https://docs.oracle.com/javase/tutorial/java/generics/types.html) type, Custom type, [Binary](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/InputStream.html) type, [String](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/String.html) type and Stream of [Object](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Object.html), and all of them can be asynchronous or synchronous. For async responses you have to use the Java class [CompletableFuture](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/CompletableFuture.html). +The reponse types are determined from the method responses. We don't need any annotation for that. We have six response types: [Stream](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/stream/Stream.html) of elements, [List](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/List.html) of elements, [Generic](https://docs.oracle.com/javase/tutorial/java/generics/types.html) type, Custom type, [Binary](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/InputStream.html) type, [String](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/String.html) type and Stream of [Event](./src/main/java/io/github/sashirestela/cleverclient/Event.java), and all of them can be asynchronous or synchronous. For async responses you have to use the Java class [CompletableFuture](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/CompletableFuture.html). | Method's Response Type | Sync/Async | Description | |------------------------------------|------------|-----------------------------| @@ -196,12 +196,14 @@ The reponse types are determined from the method responses. We don't need any an | InputStream | Sync | Binary type | | CompletableFuture\ | Async | String type | | String | Sync | String type | -| CompletableFuture> | Async | SSE (*) as Stream of Object | -| Stream\ | Sync | SSE (*) as Stream of Object | +| CompletableFuture> | Async | SSE (*) as Stream of Event | +| Stream\ | Sync | SSE (*) as Stream of Event | (*) SSE: Server Sent Events -```CompletableFuture>``` and ```Stream``` are used for handling SSE with multiple events and classes. +* ```CompletableFuture>``` and ```Stream``` are used for handling SSE without events and data of the class ```T``` only. +* ```CompletableFuture>``` and ```Stream``` are used for handling SSE with multiple events and data of different classes. +* The [Event](./src/main/java/io/github/sashirestela/cleverclient/Event.java) class will bring the event name and the data object. ### Interface Default Methods @@ -211,6 +213,12 @@ You can create interface default methods to execute special requirements such as @Resource("/v1/chat/completions") interface Completions { + @POST + Stream createSyncStreamBasic(@Body ChatRequest chatRequest); + + @POST + CompletableFuture> createAsyncStreamBasic(@Body ChatRequest chatRequest); + default Stream createSyncStream(ChatRequest chatRequest) { var request = chatRequest.withStream(true); return createSyncStreamBasic(request); @@ -221,12 +229,6 @@ interface Completions { return createAsyncStreamBasic(request); } - @POST - Stream createSyncStreamBasic(@Body ChatRequest chatRequest); - - @POST - CompletableFuture> createAsyncStreamBasic(@Body ChatRequest chatRequest); - } ``` From d016bdb97ac091780615fc00e4b50bb1378711a1 Mon Sep 17 00:00:00 2001 From: Sashir Estela Date: Fri, 22 Mar 2024 21:36:38 +0000 Subject: [PATCH 3/3] Deploy release 1.3.1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4a33887..0576368 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ io.github.sashirestela cleverclient - 1.3.0 + 1.3.1 jar cleverclient