diff --git a/domino-rest-client/pom.xml b/domino-rest-client/pom.xml
index f00b87d..c712a49 100644
--- a/domino-rest-client/pom.xml
+++ b/domino-rest-client/pom.xml
@@ -5,7 +5,7 @@
domino-rest
org.dominokit
- 2.0.0-RC1
+ 2.0.0-RC2
4.0.0
@@ -84,7 +84,6 @@
jakarta.ws.rs-api
${jax.rs.version}
-
org.dominokit
domino-rest-jaxrs
diff --git a/domino-rest-client/src/main/java/org/dominokit/rest/DominoRestConfig.java b/domino-rest-client/src/main/java/org/dominokit/rest/DominoRestConfig.java
index c7204a6..86217f9 100644
--- a/domino-rest-client/src/main/java/org/dominokit/rest/DominoRestConfig.java
+++ b/domino-rest-client/src/main/java/org/dominokit/rest/DominoRestConfig.java
@@ -19,7 +19,9 @@
import static java.util.Objects.nonNull;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import org.dominokit.jackson.JacksonContextProvider;
import org.dominokit.rest.js.DefaultServiceRoot;
import org.dominokit.rest.js.ServerEventFactory;
@@ -69,6 +71,10 @@ public class DominoRestConfig implements RestConfig {
private static NullQueryParamStrategy nullQueryParamStrategy = NullQueryParamStrategy.EMPTY;
+ private static final Map globalPathParams = new HashMap<>();
+ private static final Map globalHeaderParams = new HashMap<>();
+ private static final Map> globalQueryParams = new HashMap<>();
+
/**
* Gets and initialize the instance with the default configurations
*
@@ -270,4 +276,78 @@ public UrlTokenRegexMatcher getUrlTokenRegexMatcher() {
return url;
};
}
+
+ @Override
+ public Map getGlobalPathParameters() {
+ return globalPathParams;
+ }
+
+ @Override
+ public Map getGlobalHeaderParameters() {
+ return globalHeaderParams;
+ }
+
+ @Override
+ public Map> getGlobalQueryParameters() {
+ return globalQueryParams;
+ }
+
+ @Override
+ public RestConfig setGlobalPathParameter(String name, String value) {
+ getGlobalPathParameters().put(name, value);
+ return this;
+ }
+
+ @Override
+ public RestConfig setGlobalPathParameters(Map pathParameters) {
+ getGlobalPathParameters().putAll(pathParameters);
+ return this;
+ }
+
+ @Override
+ public RestConfig setGlobalHeaderParameter(String name, String value) {
+ getGlobalHeaderParameters().put(name, value);
+ return this;
+ }
+
+ @Override
+ public RestConfig setGlobalHeaderParameters(Map headerParameters) {
+ getGlobalHeaderParameters().putAll(headerParameters);
+ return this;
+ }
+
+ @Override
+ public RestConfig setGlobalQueryParameter(String name, String value) {
+ getGlobalQueryParameters().put(name, new ArrayList<>());
+ addGlobalQueryParameter(name, value);
+ return this;
+ }
+
+ @Override
+ public RestConfig addGlobalQueryParameter(String name, String value) {
+ if (getGlobalQueryParameters().containsKey(name)) {
+ getGlobalQueryParameters().get(name).add(value);
+ } else {
+ setGlobalQueryParameter(name, value);
+ }
+ return this;
+ }
+
+ @Override
+ public RestConfig setGlobalQueryParameters(Map> parameters) {
+ parameters
+ .keySet()
+ .forEach(
+ name -> parameters.get(name).forEach(value -> addGlobalQueryParameter(name, value)));
+ return this;
+ }
+
+ @Override
+ public RestConfig addGlobalQueryParameters(Map> parameters) {
+ parameters.forEach(
+ (key, values) -> {
+ values.forEach(value -> addGlobalQueryParameter(key, value));
+ });
+ return this;
+ }
}
diff --git a/domino-rest-jaxrs/pom.xml b/domino-rest-jaxrs/pom.xml
index 453126a..9defd34 100644
--- a/domino-rest-jaxrs/pom.xml
+++ b/domino-rest-jaxrs/pom.xml
@@ -5,7 +5,7 @@
org.dominokit
domino-rest
- 2.0.0-RC1
+ 2.0.0-RC2
domino-rest-jaxrs
diff --git a/domino-rest-jvm/pom.xml b/domino-rest-jvm/pom.xml
index e65e0c5..291f6a0 100644
--- a/domino-rest-jvm/pom.xml
+++ b/domino-rest-jvm/pom.xml
@@ -5,7 +5,7 @@
domino-rest
org.dominokit
- 2.0.0-RC1
+ 2.0.0-RC2
4.0.0
diff --git a/domino-rest-jvm/src/main/java/org/dominokit/rest/DominoRestConfig.java b/domino-rest-jvm/src/main/java/org/dominokit/rest/DominoRestConfig.java
index eaab975..d6d96aa 100644
--- a/domino-rest-jvm/src/main/java/org/dominokit/rest/DominoRestConfig.java
+++ b/domino-rest-jvm/src/main/java/org/dominokit/rest/DominoRestConfig.java
@@ -20,7 +20,9 @@
import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
@@ -70,6 +72,10 @@ public class DominoRestConfig implements RestConfig {
private static NullQueryParamStrategy nullQueryParamStrategy = NullQueryParamStrategy.EMPTY;
+ private static final Map globalPathParams = new HashMap<>();
+ private static final Map globalHeaderParams = new HashMap<>();
+ private static final Map> globalQueryParams = new HashMap<>();
+
/**
* Gets and initialize the instance with the default configurations
*
@@ -270,4 +276,78 @@ public UrlTokenRegexMatcher getUrlTokenRegexMatcher() {
return url;
};
}
+
+ @Override
+ public Map getGlobalPathParameters() {
+ return globalPathParams;
+ }
+
+ @Override
+ public Map getGlobalHeaderParameters() {
+ return globalHeaderParams;
+ }
+
+ @Override
+ public Map> getGlobalQueryParameters() {
+ return globalQueryParams;
+ }
+
+ @Override
+ public RestConfig setGlobalPathParameter(String name, String value) {
+ getGlobalPathParameters().put(name, value);
+ return this;
+ }
+
+ @Override
+ public RestConfig setGlobalPathParameters(Map pathParameters) {
+ getGlobalPathParameters().putAll(pathParameters);
+ return this;
+ }
+
+ @Override
+ public RestConfig setGlobalHeaderParameter(String name, String value) {
+ getGlobalHeaderParameters().put(name, value);
+ return this;
+ }
+
+ @Override
+ public RestConfig setGlobalHeaderParameters(Map headerParameters) {
+ getGlobalHeaderParameters().putAll(headerParameters);
+ return this;
+ }
+
+ @Override
+ public RestConfig setGlobalQueryParameter(String name, String value) {
+ getGlobalQueryParameters().put(name, new ArrayList<>());
+ addGlobalQueryParameter(name, value);
+ return this;
+ }
+
+ @Override
+ public RestConfig addGlobalQueryParameter(String name, String value) {
+ if (getGlobalQueryParameters().containsKey(name)) {
+ getGlobalQueryParameters().get(name).add(value);
+ } else {
+ setGlobalQueryParameter(name, value);
+ }
+ return this;
+ }
+
+ @Override
+ public RestConfig setGlobalQueryParameters(Map> parameters) {
+ parameters
+ .keySet()
+ .forEach(
+ name -> parameters.get(name).forEach(value -> addGlobalQueryParameter(name, value)));
+ return this;
+ }
+
+ @Override
+ public RestConfig addGlobalQueryParameters(Map> parameters) {
+ parameters.forEach(
+ (key, values) -> {
+ values.forEach(value -> addGlobalQueryParameter(key, value));
+ });
+ return this;
+ }
}
diff --git a/domino-rest-processor/pom.xml b/domino-rest-processor/pom.xml
index 47d1871..44375c0 100644
--- a/domino-rest-processor/pom.xml
+++ b/domino-rest-processor/pom.xml
@@ -4,7 +4,7 @@
domino-rest
org.dominokit
- 2.0.0-RC1
+ 2.0.0-RC2
4.0.0
diff --git a/domino-rest-processor/src/main/java/org/dominokit/rest/processor/RequestFactorySourceWriter.java b/domino-rest-processor/src/main/java/org/dominokit/rest/processor/RequestFactorySourceWriter.java
index b1c86c7..11bc147 100644
--- a/domino-rest-processor/src/main/java/org/dominokit/rest/processor/RequestFactorySourceWriter.java
+++ b/domino-rest-processor/src/main/java/org/dominokit/rest/processor/RequestFactorySourceWriter.java
@@ -48,6 +48,7 @@
import org.dominokit.jackson.processor.deserialization.FieldDeserializersChainBuilder;
import org.dominokit.jackson.processor.serialization.FieldSerializerChainBuilder;
import org.dominokit.rest.shared.MultipartForm;
+import org.dominokit.rest.shared.Response;
import org.dominokit.rest.shared.request.*;
import org.dominokit.rest.shared.request.service.annotations.*;
import org.dominokit.rest.shared.request.service.annotations.Request;
@@ -668,6 +669,10 @@ private TypeMirror getMappingType(TypeMirror returnType) {
return elements.getTypeElement(Void.class.getCanonicalName()).asType();
}
+ if (processorUtil.isAssignableFrom(returnType, jakarta.ws.rs.core.Response.class)) {
+ return elements.getTypeElement(Response.class.getCanonicalName()).asType();
+ }
+
if (Type.isArray(returnType)) {
return returnType;
}
@@ -959,6 +964,12 @@ private Optional getResponseReader(ServiceMethod serviceMethod) {
"setResponseReader(response -> new $T().read(response))",
TypeName.get(readerType)));
return Optional.of(builder.build());
+ } else if (isGenericResponse(serviceMethod)) {
+
+ builder.addStatement(
+ "setResponseReader(response -> new $T().read(response))",
+ TypeName.get(GeneralResponseReader.class));
+ return Optional.of(builder.build());
} else if (producesJson(serviceMethod)) {
TypeMirror responseBeanType = getResponseBeanType(serviceMethod);
@@ -997,6 +1008,10 @@ private Optional getResponseReader(ServiceMethod serviceMethod) {
return Optional.empty();
}
+ private boolean isGenericResponse(ServiceMethod serviceMethod) {
+ return processorUtil.isAssignableFrom(getResponseBeanType(serviceMethod), Response.class);
+ }
+
private boolean producesJson(ServiceMethod serviceMethod) {
String acceptResponse = getAcceptResponse(serviceMethod);
return acceptResponse.contains(MediaType.APPLICATION_JSON)
diff --git a/domino-rest-shared/pom.xml b/domino-rest-shared/pom.xml
index 64681eb..a7bffaf 100644
--- a/domino-rest-shared/pom.xml
+++ b/domino-rest-shared/pom.xml
@@ -5,7 +5,7 @@
domino-rest
org.dominokit
- 2.0.0-RC1
+ 2.0.0-RC2
4.0.0
@@ -33,6 +33,7 @@
org.dominokit
domino-rest-jaxrs
${project.version}
+ provided
@@ -45,11 +46,6 @@
domino-aggregator-shared
${domino.aggregator.version}
-
- org.dominokit
- domino-history-shared
- ${domino.history.version}
-
javax.annotation
javax.annotation-api
diff --git a/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/GeneralResponseReader.java b/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/GeneralResponseReader.java
new file mode 100644
index 0000000..d99d8ab
--- /dev/null
+++ b/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/GeneralResponseReader.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright © 2019 Dominokit
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.dominokit.rest.shared.request;
+
+import org.dominokit.rest.shared.Response;
+
+/** Reads the response body as a {@link String} */
+public class GeneralResponseReader implements ResponseReader {
+ @Override
+ public Response read(Response response) {
+ return response;
+ }
+}
diff --git a/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/RestConfig.java b/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/RestConfig.java
index 85e7dc1..da3917b 100644
--- a/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/RestConfig.java
+++ b/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/RestConfig.java
@@ -17,6 +17,7 @@
import java.util.Date;
import java.util.List;
+import java.util.Map;
import org.dominokit.rest.shared.request.service.annotations.DateFormat;
/** The global configurations for domino rest. */
@@ -176,6 +177,28 @@ default NullQueryParamStrategy getNullQueryParamStrategy() {
UrlTokenRegexMatcher getUrlTokenRegexMatcher();
+ Map getGlobalPathParameters();
+
+ Map getGlobalHeaderParameters();
+
+ Map> getGlobalQueryParameters();
+
+ RestConfig setGlobalPathParameter(String name, String value);
+
+ RestConfig setGlobalPathParameters(Map pathParameters);
+
+ RestConfig setGlobalHeaderParameter(String name, String value);
+
+ RestConfig setGlobalHeaderParameters(Map headerParameters);
+
+ RestConfig setGlobalQueryParameter(String name, String value);
+
+ RestConfig addGlobalQueryParameter(String name, String value);
+
+ RestConfig setGlobalQueryParameters(Map> parameters);
+
+ RestConfig addGlobalQueryParameters(Map> parameters);
+
/** Formatter to format the date parameter based on a patter */
@FunctionalInterface
interface DateParamFormatter {
diff --git a/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/ServerRequest.java b/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/ServerRequest.java
index 4488f91..681fb2e 100644
--- a/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/ServerRequest.java
+++ b/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/ServerRequest.java
@@ -314,7 +314,10 @@ public void normalizeUrl() {
(isNull(this.serviceRoot) || this.serviceRoot.isEmpty())
? ServiceRootMatcher.matchedServiceRoot(path)
: (this.serviceRoot + path);
- UrlFormatter urlFormatter = new UrlFormatter(pathParameters);
+ Map combinedParams = new HashMap<>();
+ combinedParams.putAll(DominoRestContext.make().getConfig().getGlobalPathParameters());
+ combinedParams.putAll(pathParameters);
+ UrlFormatter urlFormatter = new UrlFormatter(combinedParams);
this.setUrl(urlFormatter.formatUrl(root));
}
}
diff --git a/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/ServicePath.java b/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/ServicePath.java
new file mode 100644
index 0000000..2782754
--- /dev/null
+++ b/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/ServicePath.java
@@ -0,0 +1,394 @@
+/*
+ * Copyright © 2019 Dominokit
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.dominokit.rest.shared.request;
+
+import static java.util.Objects.isNull;
+import static java.util.Objects.nonNull;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+public class ServicePath {
+
+ private static final String QUERY_REGEX = "\\?";
+ private static final String FRAGMENT_REGEX = "\\#";
+ private final String rootPath;
+ private List paths = new LinkedList<>();
+ private List queryParameters = new LinkedList<>();
+ private List fragments = new LinkedList<>();
+
+ /** @param token String, a URL token */
+ public ServicePath(String token) {
+ this("", token);
+ }
+
+ /**
+ * @param rootPath String, the root path token
+ * @param token String, a URL token
+ */
+ public ServicePath(String rootPath, String token) {
+ if (isNull(token)) throw new IllegalArgumentException();
+ this.rootPath = isNull(rootPath) ? "" : rootPath.trim();
+ String rebasedToken = rebaseToken(rootPath, token);
+ this.paths.addAll(asPathsList(rebasedToken));
+ this.queryParameters.addAll(asQueryParameters(rebasedToken));
+ this.fragments.addAll(parseFragments(rebasedToken));
+ }
+
+ private String rebaseToken(String rootPath, String token) {
+ if (isNull(rootPath) || rootPath.trim().isEmpty() || !token.startsWith(rootPath)) {
+ return token;
+ }
+ return token.substring(rootPath.length());
+ }
+
+ private List parseFragments(String token) {
+ if (token.contains("#") && token.indexOf("#") < token.length() - 1)
+ return asPathsList(token.split(FRAGMENT_REGEX)[1]);
+ return new LinkedList<>();
+ }
+
+ /**
+ * @param path The path to check for
+ * @return true if the path part of the url ends with the specified path otherwise returns
+ * false
+ */
+ public boolean endsWithPath(String path) {
+ if (isEmpty(path)) return false;
+ return endsWith(paths(), asPathsList(path));
+ }
+
+ private boolean endsWith(List paths, List targets) {
+ if (isValidSize(paths, targets)) return matchEnds(paths, targets);
+ return false;
+ }
+
+ private boolean matchEnds(List paths, List targets) {
+ int offset = paths.size() - targets.size();
+ return IntStream.range(0, targets.size())
+ .allMatch(i -> targets.get(i).equals(paths.get(i + offset)));
+ }
+
+ /**
+ * @return a list of Strings representing all paths of a url, e.g
+ * http://localhost:8080/a/b/c will return a list contains a, b,
+ * c,
+ */
+ public List paths() {
+ return paths;
+ }
+
+ /**
+ * @return a list of Strings representing all fragments of a url, e.g
+ * http://localhost:8080/a/b/c#d/e/f will return a list contains d, d,
+ * f,
+ */
+ public List fragments() {
+ return fragments;
+ }
+
+ /**
+ * @return the path part of a url, e.g http://localhost:8080/a/b/c will return a/b/c
+ */
+ public String path() {
+ return String.join("/", paths());
+ }
+
+ /** @return the string representing the whole query part of a token */
+ public String query() {
+ return queryParameters.stream().map(Parameter::asQueryString).collect(Collectors.joining("&"));
+ }
+
+ /**
+ * @param name name of the query parameter
+ * @return True if the token has a query param that has the specified name, otherwise
+ * returns false.
+ */
+ public boolean hasQueryParameter(String name) {
+ Optional param =
+ queryParameters.stream().filter(parameter -> parameter.key.equals(name)).findFirst();
+
+ if (param.isPresent()) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Adds a query parameter with specified name and value to the current token, if a query parameter
+ * with same name already exists, then replaces its value with the new one
+ *
+ * @param name query parameter name
+ * @param value query parameter value
+ * @return {@link ServicePath} that contains the new query parameter.
+ */
+ public ServicePath setQueryParameter(String name, String value) {
+ if (hasQueryParameter(name)) {
+ removeParameter(name);
+ }
+ appendParameter(name, value);
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ public ServicePath setQueryParameter(String name, List values) {
+ if (hasQueryParameter(name)) {
+ removeParameter(name);
+ }
+ appendParameter(name, values);
+ return this;
+ }
+
+ private Parameter getParameter(String name) {
+ Optional param =
+ queryParameters.stream().filter(parameter -> parameter.key.equals(name)).findFirst();
+
+ if (param.isPresent()) {
+ return param.get();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Appends a new query parameter to the end of the token query parameters part.
+ *
+ * @param name of the query parameter
+ * @param value of the query parameter
+ * @return {@link ServicePath} with the new query parameter appended to the end of query part.
+ */
+ public ServicePath appendParameter(String name, String value) {
+ return appendParameter(name, asList(value));
+ }
+
+ /** {@inheritDoc} */
+ public ServicePath appendParameter(String name, List values) {
+ if (nonNull(name) && !name.trim().isEmpty()) {
+ if (hasQueryParameter(name)) {
+ getParameter(name).addValues(values);
+ } else {
+ this.queryParameters.add(new Parameter(name, values));
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Replaces the first occurrence of a path segment with the replacement
+ *
+ * @param path The path segment to be replaced
+ * @param replacement the new path segment
+ * @return {@link ServicePath} with path segment replaced by the replacement
+ */
+ public ServicePath replacePath(String path, String replacement) {
+ List paths = asPathsList(path());
+ if (paths.contains(path)) {
+ int i = paths.indexOf(path);
+ paths.add(i, replacement);
+ paths.remove(i + 1);
+ this.paths = paths;
+ }
+ return this;
+ }
+
+ private List asList(String value) {
+ List values = new ArrayList<>();
+ values.add(value);
+ return values;
+ }
+
+ /**
+ * Removes the query parameter with the specified name
+ *
+ * @param name of the parameter to be removed
+ * @return {@link ServicePath} with the query parameter with the specified name being removed
+ */
+ public ServicePath removeParameter(String name) {
+ Parameter parameter = getParameter(name);
+ if (nonNull(parameter)) {
+ this.queryParameters.remove(parameter);
+ }
+ return this;
+ }
+
+ /** @return the string representing the whole fragment part of a token */
+ public String fragment() {
+ return String.join("/", fragments());
+ }
+
+ /**
+ * @return true if all of token (path part, query part, fragments part) are empty,
+ * otherwise return false.
+ */
+ public boolean isEmpty() {
+ return paths.isEmpty() && queryParameters.isEmpty() && fragments.isEmpty();
+ }
+
+ /** @return the full string representation of a {@link ServicePath} */
+ public String value() {
+ String path = path();
+ String separator =
+ (getRootPath().isEmpty()
+ || getRootPath().endsWith("/")
+ || path.startsWith("/")
+ || path.isEmpty())
+ ? ""
+ : "/";
+ return getRootPath() + separator + noRootValue();
+ }
+
+ /** {@inheritDoc} */
+ public String noRootValue() {
+ return path() + appendQuery(query()) + appendFragment();
+ }
+
+ private String appendFragment() {
+ return isEmpty(fragment()) ? "" : "#" + fragment();
+ }
+
+ private String appendQuery(String query) {
+ return isEmpty(query) ? "" : "?" + query;
+ }
+
+ private List asPathsList(String token) {
+ if (isNull(token) || isEmpty(token) || token.startsWith("?") || token.startsWith("#"))
+ return new ArrayList<>();
+ return Arrays.stream(splittedPaths(token))
+ .filter(p -> !p.isEmpty())
+ .collect(Collectors.toCollection(LinkedList::new));
+ }
+
+ private String[] splittedPaths(String pathString) {
+ return parsePathPart(pathString).split("/");
+ }
+
+ private String parsePathPart(String pathString) {
+ return pathString.replace("!", "").split(QUERY_REGEX)[0].split(FRAGMENT_REGEX)[0];
+ }
+
+ private boolean isEmpty(String path) {
+ return isNull(path) || path.isEmpty();
+ }
+
+ private boolean isValidSize(List paths, List targets) {
+ return !targets.isEmpty() && targets.size() <= paths.size();
+ }
+
+ private List asQueryParameters(String token) {
+
+ String queryString = queryPart(token);
+ if (isNull(queryString) || queryString.trim().isEmpty()) {
+ return new LinkedList<>();
+ }
+ return parsedParameters(queryString);
+ }
+
+ private List parsedParameters(String queryString) {
+
+ return Stream.of(queryString.split("&")).map(part -> part.split("="))
+ .collect(
+ Collectors.groupingBy(
+ keyValue -> keyValue[0],
+ LinkedHashMap::new,
+ Collectors.mapping(keyValue -> keyValue[1], Collectors.toList())))
+ .entrySet().stream()
+ .map(entry -> new Parameter(entry.getKey(), entry.getValue()))
+ .collect(Collectors.toCollection(LinkedList::new));
+ }
+
+ private String queryPart(String token) {
+ String query = "";
+ if (token.contains("?") && token.indexOf("?") < token.length() - 1) {
+ String[] parts = token.split(QUERY_REGEX);
+
+ if (parts.length > 1) {
+ if (parts[1].split(FRAGMENT_REGEX).length > 0) {
+ query = parts[1].split(FRAGMENT_REGEX)[0];
+ } else {
+ return query;
+ }
+ } else {
+ query = parts[0].split(FRAGMENT_REGEX)[0];
+ }
+
+ if (!query.isEmpty() && !query.contains("=")) {
+ throw new IllegalArgumentException("Query string [" + query + "] is missing '=' operator.");
+ }
+ }
+ return query;
+ }
+
+ public String getRootPath() {
+ return rootPath;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ServicePath)) return false;
+ ServicePath that = (ServicePath) o;
+
+ return paths.equals(that.paths)
+ && fragments.equals(that.fragments)
+ && queryParameters.size() == that.queryParameters.size()
+ && queryParameters.containsAll(that.queryParameters);
+ }
+
+ public int hashCode() {
+ return Objects.hash(paths, queryParameters, fragments);
+ }
+
+ private static class Parameter {
+ private String key;
+ private List value;
+
+ public Parameter(String key, List value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ private void addValues(List moreValues) {
+ value.addAll(moreValues);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof Parameter)) return false;
+ Parameter parameter = (Parameter) o;
+ return Objects.equals(key, parameter.key)
+ && value.size() == parameter.value.size()
+ && value.containsAll(parameter.value);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(key, value);
+ }
+
+ private String asQueryString() {
+ return value.stream().map(value -> key + "=" + value).collect(Collectors.joining("&"));
+ }
+ }
+}
diff --git a/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/UrlFormatter.java b/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/UrlFormatter.java
index 9850d4b..6180e3d 100644
--- a/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/UrlFormatter.java
+++ b/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/UrlFormatter.java
@@ -19,7 +19,6 @@
import java.util.ArrayList;
import java.util.Map;
-import org.dominokit.domino.history.StateHistoryToken;
import org.dominokit.rest.shared.request.exception.PathParameterMissingException;
/** Formats the url by adding the query parameters and normalizing path parameters */
@@ -45,7 +44,7 @@ protected String formatUrl(String targetUrl) {
String postfix = asTokenString(targetUrl);
String prefix = targetUrl.replace(postfix, "");
- StateHistoryToken tempToken = new StateHistoryToken(postfix);
+ ServicePath tempToken = new ServicePath(postfix);
replaceUrlParamsWithArguments(tempToken);
@@ -56,11 +55,11 @@ private boolean hasExpressions(String url) {
return (url.contains("{") && url.contains("}")) || url.contains(":");
}
- private void replaceUrlParamsWithArguments(StateHistoryToken tempToken) {
+ private void replaceUrlParamsWithArguments(ServicePath tempToken) {
replacePaths(tempToken);
}
- private void replacePaths(StateHistoryToken tempToken) {
+ private void replacePaths(ServicePath tempToken) {
new ArrayList<>(tempToken.paths())
.stream()
.filter(this::isExpressionToken)
diff --git a/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/builder/Consumes.java b/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/builder/Consumes.java
new file mode 100644
index 0000000..34a0634
--- /dev/null
+++ b/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/builder/Consumes.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright © 2019 Dominokit
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.dominokit.rest.shared.request.builder;
+
+public interface Consumes {
+ Produces accepts(String consumes);
+}
diff --git a/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/builder/GenericRequest.java b/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/builder/GenericRequest.java
new file mode 100644
index 0000000..6043de9
--- /dev/null
+++ b/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/builder/GenericRequest.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright © 2019 Dominokit
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.dominokit.rest.shared.request.builder;
+
+import org.dominokit.rest.shared.request.RequestMeta;
+import org.dominokit.rest.shared.request.ServerRequest;
+
+class GenericRequest extends ServerRequest {
+
+ public GenericRequest(RequestMeta requestMeta, R requestBean) {
+ super(requestMeta, requestBean);
+ }
+}
diff --git a/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/builder/HasMethod.java b/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/builder/HasMethod.java
new file mode 100644
index 0000000..e674be7
--- /dev/null
+++ b/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/builder/HasMethod.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright © 2019 Dominokit
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.dominokit.rest.shared.request.builder;
+
+public interface HasMethod {
+
+ HasPath withMethod(String method);
+}
diff --git a/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/builder/HasPath.java b/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/builder/HasPath.java
new file mode 100644
index 0000000..2721c13
--- /dev/null
+++ b/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/builder/HasPath.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright © 2019 Dominokit
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.dominokit.rest.shared.request.builder;
+
+public interface HasPath {
+ Consumes withPath(String consumes);
+}
diff --git a/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/builder/Produces.java b/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/builder/Produces.java
new file mode 100644
index 0000000..7cdbe61
--- /dev/null
+++ b/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/builder/Produces.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright © 2019 Dominokit
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.dominokit.rest.shared.request.builder;
+
+public interface Produces {
+ RestRequestBuilder produces(String produces);
+}
diff --git a/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/builder/RestRequestBuilder.java b/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/builder/RestRequestBuilder.java
new file mode 100644
index 0000000..4c803d5
--- /dev/null
+++ b/domino-rest-shared/src/main/java/org/dominokit/rest/shared/request/builder/RestRequestBuilder.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright © 2019 Dominokit
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.dominokit.rest.shared.request.builder;
+
+import static java.util.Objects.isNull;
+
+import java.util.Optional;
+import org.dominokit.rest.shared.request.RequestMeta;
+import org.dominokit.rest.shared.request.RequestWriter;
+import org.dominokit.rest.shared.request.ResponseReader;
+import org.dominokit.rest.shared.request.ServerRequest;
+
+public class RestRequestBuilder
+ implements HasMethod, HasPath, Consumes, Produces {
+
+ private String key;
+ private Class requestClass;
+ private Class responseClass;
+ private String method;
+ private String consumes;
+ private String produce;
+ private String path;
+ private String serviceRoot = "";
+ private ResponseReader responseReader = response -> null;
+ private RequestWriter requestWriter = request -> null;
+
+ public static HasMethod of(
+ Class requestClass, Class responseClass, String key) {
+ RestRequestBuilder builder = new RestRequestBuilder<>();
+ builder.key = key;
+ builder.requestClass = requestClass;
+ builder.responseClass = responseClass;
+ return builder;
+ }
+
+ @Override
+ public HasPath withMethod(String method) {
+ this.method = method;
+ return this;
+ }
+
+ @Override
+ public Consumes withPath(String path) {
+ this.path = path;
+ return this;
+ }
+
+ @Override
+ public Produces accepts(String consumes) {
+ this.consumes = consumes;
+ return this;
+ }
+
+ @Override
+ public RestRequestBuilder produces(String produces) {
+ this.produce = produces;
+ return this;
+ }
+
+ public RestRequestBuilder withServiceRoot(String serviceRoot) {
+ this.serviceRoot = serviceRoot;
+ return this;
+ }
+
+ public RestRequestBuilder withResponseReader(ResponseReader responseReader) {
+ this.responseReader = responseReader;
+ return this;
+ }
+
+ public RestRequestBuilder withRequestWriter(RequestWriter requestWriter) {
+ this.requestWriter = requestWriter;
+ return this;
+ }
+
+ public ServerRequest build() {
+ return build(null);
+ }
+
+ public ServerRequest build(R requestBean) {
+ ServerRequest request =
+ new GenericRequest<>(
+ new RequestMeta(RestRequestBuilder.class, key, requestClass, responseClass),
+ requestBean);
+ request.setHttpMethod(this.method);
+ request.setAccept(new String[] {this.produce});
+ request.setContentType(new String[] {this.consumes});
+ request.setPath(this.path);
+ request.setServiceRoot(isNull(this.serviceRoot) ? "" : this.serviceRoot);
+ Optional.ofNullable(this.responseReader).ifPresent(request::setResponseReader);
+ Optional.ofNullable(this.requestWriter).ifPresent(request::setRequestWriter);
+
+ return request;
+ }
+}
diff --git a/domino-rest-test/pom.xml b/domino-rest-test/pom.xml
index c08cdf0..63d537e 100644
--- a/domino-rest-test/pom.xml
+++ b/domino-rest-test/pom.xml
@@ -5,7 +5,7 @@
domino-rest
org.dominokit
- 2.0.0-RC1
+ 2.0.0-RC2
4.0.0
diff --git a/domino-rest-test/src/test/java/org/dominokit/rest/model/JakartaResponseService.java b/domino-rest-test/src/test/java/org/dominokit/rest/model/JakartaResponseService.java
new file mode 100644
index 0000000..a6f747c
--- /dev/null
+++ b/domino-rest-test/src/test/java/org/dominokit/rest/model/JakartaResponseService.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2019 Dominokit
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.dominokit.rest.model;
+
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import org.dominokit.rest.shared.request.service.annotations.RequestFactory;
+
+@RequestFactory
+@Path("test")
+public interface JakartaResponseService {
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ Response getResponse();
+}
diff --git a/domino-rest-test/src/test/java/org/dominokit/rest/test/ResponseReturnTypeTest.java b/domino-rest-test/src/test/java/org/dominokit/rest/test/ResponseReturnTypeTest.java
new file mode 100644
index 0000000..209a523
--- /dev/null
+++ b/domino-rest-test/src/test/java/org/dominokit/rest/test/ResponseReturnTypeTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright © 2019 Dominokit
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.dominokit.rest.test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import io.vertx.core.Vertx;
+import io.vertx.junit5.VertxExtension;
+import io.vertx.junit5.VertxTestContext;
+import org.dominokit.rest.model.JakartaResponseServiceFactory;
+import org.dominokit.rest.shared.Response;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@ExtendWith(VertxExtension.class)
+public class ResponseReturnTypeTest extends BaseRestTest {
+
+ @Test
+ @DisplayName("Test using jakarta.ws.rs.core.Response as a return type")
+ void nullQueryParamAsEmpty(Vertx vertx, VertxTestContext testContext) {
+ JakartaResponseServiceFactory.INSTANCE
+ .getResponse()
+ .onSuccess(
+ response -> {
+ assertThat(Response.class.isAssignableFrom(response.getClass()));
+ testContext.completeNow();
+ })
+ .send();
+ }
+}
diff --git a/pom.xml b/pom.xml
index aeb0ec4..1d830c6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.dominokit
domino-rest
- 2.0.0-RC1
+ 2.0.0-RC2
pom
domino-rest
@@ -70,7 +70,7 @@
HEAD-SNAPSHOT
- 2.0.0-RC1
+ 2.0.0-RC2
11
11
UTF-8
@@ -88,14 +88,13 @@
3.0.0-M5
1.1.0
- 2.10.0
+ 2.12.0
1.0.3
- 1.0.4
- 1.0.3
- 1.0.2
+ 1.0.5
+ 1.0.3
3.1.0
2.16.0
- 1.2.1
+ 1.2.3