feature: #2542 Dynamic proxy pattern (#2814)

* #2542 First commit

* #2542 Fixing comments

* #2542 Refactoring code

* #2542 Update Readme

* #2542 Add mockito dependencies

* #2542 Add unit test

* #2542 Fixes for testing

* #2542 Fixing typos

* #2542 Fixing SonarLint issues

* #2542 Fixing code review

---------

Co-authored-by: Sashir Estela <sashirestela@yahoo.com>
Co-authored-by: Ilkka Seppälä <iluwatar@users.noreply.github.com>
This commit is contained in:
Sashir Estela
2024-03-23 05:34:32 -05:00
committed by GitHub
parent 4b704c807f
commit f65bb820d8
22 changed files with 1542 additions and 0 deletions
@@ -0,0 +1,46 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.dynamicproxy;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* This class represents an endpoint resource that
* we are going to interchange with a Rest API server.
*/
@Data
@AllArgsConstructor
@NoArgsConstructor(force = true)
@Builder
public class Album {
private Integer id;
private String title;
private Integer userId;
}
@@ -0,0 +1,61 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.dynamicproxy;
import com.iluwatar.dynamicproxy.tinyrestclient.TinyRestClient;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.net.http.HttpClient;
import lombok.extern.slf4j.Slf4j;
/**
* Class whose method 'invoke' will be called every time that an interface's method is called.
* That interface is linked to this class by the Proxy class.
*/
@Slf4j
public class AlbumInvocationHandler implements InvocationHandler {
private TinyRestClient restClient;
/**
* Class constructor. It instantiates a TinyRestClient object.
*
* @param baseUrl Root url for endpoints.
* @param httpClient Handle the http communication.
*/
public AlbumInvocationHandler(String baseUrl, HttpClient httpClient) {
this.restClient = new TinyRestClient(baseUrl, httpClient);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
LOGGER.info("===== Calling the method {}.{}()",
method.getDeclaringClass().getSimpleName(), method.getName());
return restClient.send(method, args);
}
}
@@ -0,0 +1,87 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.dynamicproxy;
import com.iluwatar.dynamicproxy.tinyrestclient.annotation.Body;
import com.iluwatar.dynamicproxy.tinyrestclient.annotation.Delete;
import com.iluwatar.dynamicproxy.tinyrestclient.annotation.Get;
import com.iluwatar.dynamicproxy.tinyrestclient.annotation.Path;
import com.iluwatar.dynamicproxy.tinyrestclient.annotation.Post;
import com.iluwatar.dynamicproxy.tinyrestclient.annotation.Put;
import java.util.List;
/**
* Every method in this interface is annotated with the necessary metadata to represents an endpoint
* that we can call to communicate with a host server which is serving a resource by Rest API.
* This interface is focused in the resource Album.
*/
public interface AlbumService {
/**
* Get a list of albums from an endpoint.
*
* @return List of albums' data.
*/
@Get("/albums")
List<Album> readAlbums();
/**
* Get a specific album from an endpoint.
*
* @param albumId Album's id to search for.
* @return Album's data.
*/
@Get("/albums/{albumId}")
Album readAlbum(@Path("albumId") Integer albumId);
/**
* Creates a new album.
*
* @param album Album's data to be created.
* @return New album's data.
*/
@Post("/albums")
Album createAlbum(@Body Album album);
/**
* Updates an existing album.
*
* @param albumId Album's id to be modified.
* @param album New album's data.
* @return Updated album's data.
*/
@Put("/albums/{albumId}")
Album updateAlbum(@Path("albumId") Integer albumId, @Body Album album);
/**
* Deletes an album.
*
* @param albumId Album's id to be deleted.
* @return Empty album.
*/
@Delete("/albums/{albumId}")
Album deleteAlbum(@Path("albumId") Integer albumId);
}
@@ -0,0 +1,109 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.dynamicproxy;
import java.lang.reflect.Proxy;
import java.net.http.HttpClient;
import lombok.extern.slf4j.Slf4j;
/**
* Application to demonstrate the Dynamic Proxy pattern. This application allow us to hit the public
* fake API https://jsonplaceholder.typicode.com for the resource Album through an interface.
* The call to Proxy.newProxyInstance creates a new dynamic proxy for the AlbumService interface and
* sets the AlbumInvocationHandler class as the handler to intercept all the interface's methods.
* Everytime that we call an AlbumService's method, the handler's method "invoke" will be call
* automatically, and it will pass all the method's metadata and arguments to other specialized
* class - TinyRestClient - to prepare the Rest API call accordingly.
* In this demo, the Dynamic Proxy pattern help us to run business logic through interfaces without
* an explicit implementation of the interfaces and supported on the Java Reflection approach.
*/
@Slf4j
public class App {
static final String REST_API_URL = "https://jsonplaceholder.typicode.com";
private String baseUrl;
private HttpClient httpClient;
private AlbumService albumServiceProxy;
/**
* Class constructor.
*
* @param baseUrl Root url for endpoints.
* @param httpClient Handle the http communication.
*/
public App(String baseUrl, HttpClient httpClient) {
this.baseUrl = baseUrl;
this.httpClient = httpClient;
}
/**
* Application entry point.
*
* @param args External arguments to be passed. Optional.
*/
public static void main(String[] args) {
App app = new App(App.REST_API_URL, HttpClient.newHttpClient());
app.createDynamicProxy();
app.callMethods();
}
/**
* Create the Dynamic Proxy linked to the AlbumService interface and to the AlbumInvocationHandler.
*/
public void createDynamicProxy() {
AlbumInvocationHandler albumInvocationHandler = new AlbumInvocationHandler(baseUrl, httpClient);
albumServiceProxy = (AlbumService) Proxy.newProxyInstance(
App.class.getClassLoader(), new Class<?>[]{AlbumService.class}, albumInvocationHandler);
}
/**
* Call the methods of the Dynamic Proxy, in other words, the AlbumService interface's methods
* and receive the responses from the Rest API.
*/
public void callMethods() {
int albumId = 17;
int userId = 3;
var albums = albumServiceProxy.readAlbums();
albums.forEach(album -> LOGGER.info("{}", album));
var album = albumServiceProxy.readAlbum(albumId);
LOGGER.info("{}", album);
var newAlbum = albumServiceProxy.createAlbum(Album.builder()
.title("Big World").userId(userId).build());
LOGGER.info("{}", newAlbum);
var editAlbum = albumServiceProxy.updateAlbum(albumId, Album.builder()
.title("Green Valley").userId(userId).build());
LOGGER.info("{}", editAlbum);
var removedAlbum = albumServiceProxy.deleteAlbum(albumId);
LOGGER.info("{}", removedAlbum);
}
}
@@ -0,0 +1,98 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.dynamicproxy.tinyrestclient;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
/**
* Utility class to handle Json operations.
*/
@Slf4j
public class JsonUtil {
private static ObjectMapper objectMapper = new ObjectMapper();
private JsonUtil() {
}
/**
* Convert an object to a Json string representation.
*
* @param object Object to convert.
* @param <T> Object's class.
* @return Json string.
*/
public static <T> String objectToJson(T object) {
try {
return objectMapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
LOGGER.error("Cannot convert the object " + object + " to Json.", e);
return null;
}
}
/**
* Convert a Json string to an object of a class.
*
* @param json Json string to convert.
* @param clazz Object's class.
* @param <T> Object's generic class.
* @return Object.
*/
public static <T> T jsonToObject(String json, Class<T> clazz) {
try {
return objectMapper.readValue(json, clazz);
} catch (IOException e) {
LOGGER.error("Cannot convert the Json " + json + " to class " + clazz.getName() + ".", e);
return null;
}
}
/**
* Convert a Json string to a List of objects of a class.
*
* @param json Json string to convert.
* @param clazz Object's class.
* @param <T> Object's generic class.
* @return List of objects.
*/
public static <T> List<T> jsonToList(String json, Class<T> clazz) {
try {
CollectionType listType = objectMapper.getTypeFactory()
.constructCollectionType(ArrayList.class, clazz);
return objectMapper.reader().forType(listType).readValue(json);
} catch (JsonProcessingException e) {
LOGGER.error("Cannot convert the Json " + json + " to List of " + clazz.getName() + ".", e);
return List.of();
}
}
}
@@ -0,0 +1,182 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.dynamicproxy.tinyrestclient;
import com.iluwatar.dynamicproxy.tinyrestclient.annotation.Body;
import com.iluwatar.dynamicproxy.tinyrestclient.annotation.Http;
import com.iluwatar.dynamicproxy.tinyrestclient.annotation.Path;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.util.UriUtils;
/**
* Class to handle all the http communication with a Rest API.
* It is supported by the HttpClient Java library.
*/
@Slf4j
public class TinyRestClient {
private static Map<Method, Annotation> httpAnnotationByMethod = new HashMap<>();
private String baseUrl;
private HttpClient httpClient;
/**
* Class constructor.
*
* @param baseUrl Root url for endpoints.
* @param httpClient Handle the http communication.
*/
public TinyRestClient(String baseUrl, HttpClient httpClient) {
this.baseUrl = baseUrl;
this.httpClient = httpClient;
}
/**
* Creates a http communication to request and receive data from an endpoint.
*
* @param method Interface's method which is annotated with a http method.
* @param args Method's arguments passed in the call.
* @return Response from the endpoint.
* @throws IOException Exception thrown when any fail happens in the call.
* @throws InterruptedException Exception thrown when call is interrupted.
*/
public Object send(Method method, Object[] args) throws IOException, InterruptedException {
var httpAnnotation = getHttpAnnotation(method);
if (httpAnnotation == null) {
return null;
}
var httpAnnotationName = httpAnnotation.annotationType().getSimpleName().toUpperCase();
var url = baseUrl + buildUrl(method, args, httpAnnotation);
var bodyPublisher = buildBodyPublisher(method, args);
var httpRequest = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Content-Type", "application/json")
.method(httpAnnotationName, bodyPublisher)
.build();
var httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
var statusCode = httpResponse.statusCode();
if (statusCode >= HttpURLConnection.HTTP_BAD_REQUEST) {
var errorDetail = httpResponse.body();
LOGGER.error("Error from server: " + errorDetail);
return null;
}
return getResponse(method, httpResponse);
}
private String buildUrl(Method method, Object[] args, Annotation httpMethodAnnotation) {
var url = annotationValue(httpMethodAnnotation);
if (url == null) {
return "";
}
var index = 0;
for (var parameter : method.getParameters()) {
var pathAnnotation = getAnnotationOf(parameter.getDeclaredAnnotations(), Path.class);
if (pathAnnotation != null) {
var pathParam = "{" + annotationValue(pathAnnotation) + "}";
var pathValue = UriUtils.encodePath(args[index].toString(), StandardCharsets.UTF_8);
url = url.replace(pathParam, pathValue);
}
index++;
}
return url;
}
private HttpRequest.BodyPublisher buildBodyPublisher(Method method, Object[] args) {
var index = 0;
for (var parameter : method.getParameters()) {
var bodyAnnotation = getAnnotationOf(parameter.getDeclaredAnnotations(), Body.class);
if (bodyAnnotation != null) {
var body = JsonUtil.objectToJson(args[index]);
return HttpRequest.BodyPublishers.ofString(body);
}
index++;
}
return HttpRequest.BodyPublishers.noBody();
}
private Object getResponse(Method method, HttpResponse<String> httpResponse) {
var rawData = httpResponse.body();
Type returnType = null;
try {
returnType = method.getGenericReturnType();
} catch (Exception e) {
LOGGER.error("Cannot get the generic return type of the method " + method.getName() + "()");
return null;
}
if (returnType instanceof ParameterizedType) {
Class<?> responseClass = (Class<?>) (((ParameterizedType) returnType)
.getActualTypeArguments()[0]);
return JsonUtil.jsonToList(rawData, responseClass);
} else {
Class<?> responseClass = method.getReturnType();
return JsonUtil.jsonToObject(rawData, responseClass);
}
}
private Annotation getHttpAnnotation(Method method) {
return httpAnnotationByMethod.computeIfAbsent(method, m ->
Arrays.stream(m.getDeclaredAnnotations())
.filter(annot -> annot.annotationType().isAnnotationPresent(Http.class))
.findFirst().orElse(null));
}
private Annotation getAnnotationOf(Annotation[] annotations, Class<?> clazz) {
return Arrays.stream(annotations)
.filter(annot -> annot.annotationType().equals(clazz))
.findFirst().orElse(null);
}
private String annotationValue(Annotation annotation) {
var valueMethod = Arrays.stream(annotation.annotationType().getDeclaredMethods())
.filter(methodAnnot -> methodAnnot.getName().equals("value"))
.findFirst().orElse(null);
if (valueMethod == null) {
return null;
}
Object result;
try {
result = valueMethod.invoke(annotation, (Object[]) null);
} catch (Exception e) {
LOGGER.error("Cannot read the value " + annotation.annotationType().getSimpleName()
+ "." + valueMethod.getName() + "()", e);
result = null;
}
return (result instanceof String strResult ? strResult : null);
}
}
@@ -0,0 +1,39 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.dynamicproxy.tinyrestclient.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to mark a method's parameter as a Body parameter.
* It is typically used on Post and Put http methods.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface Body {
}
@@ -0,0 +1,45 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.dynamicproxy.tinyrestclient.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to mark an interface's method as a DELETE http method.
*/
@Http
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Delete {
/**
* Set the url for this http method.
*
* @return Url address.
*/
String value() default "";
}
@@ -0,0 +1,45 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.dynamicproxy.tinyrestclient.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to mark an interface's method as a GET http method.
*/
@Http
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Get {
/**
* Set the url for this http method.
*
* @return Url address.
*/
String value() default "";
}
@@ -0,0 +1,38 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.dynamicproxy.tinyrestclient.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to mark other annotations to be recognized as http methods.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Http {
}
@@ -0,0 +1,44 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.dynamicproxy.tinyrestclient.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to mark a method's parameter as a Path parameter.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface Path {
/**
* Path parameter to be replaced in the url.
*
* @return Path parameter.
*/
String value();
}
@@ -0,0 +1,45 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.dynamicproxy.tinyrestclient.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to mark an interface's method as a POST http method.
*/
@Http
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Post {
/**
* Set the url for this http method.
*
* @return Url address.
*/
String value() default "";
}
@@ -0,0 +1,45 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.dynamicproxy.tinyrestclient.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to mark an interface's method as a PUT http method.
*/
@Http
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Put {
/**
* Set the url for this http method.
*
* @return Url address.
*/
String value() default "";
}