From 722f5205b36316e8bab3b125441b973a8b3723b7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 17 Jun 2021 12:18:55 +0200 Subject: [PATCH 01/16] Bump to 2.3.0-SNAPSHOT (#400) Signed-off-by: GitHub Co-authored-by: slinkydeveloper --- amqp/pom.xml | 2 +- api/pom.xml | 2 +- benchmarks/pom.xml | 2 +- core/pom.xml | 2 +- examples/amqp-proton/pom.xml | 2 +- examples/basic-http/pom.xml | 2 +- examples/kafka/pom.xml | 2 +- examples/pom.xml | 2 +- examples/restful-ws-quarkus/pom.xml | 2 +- examples/restful-ws-spring-boot/pom.xml | 2 +- examples/spring-function/pom.xml | 2 +- examples/spring-reactive/pom.xml | 2 +- examples/spring-rsocket/pom.xml | 2 +- examples/vertx/pom.xml | 2 +- formats/json-jackson/pom.xml | 2 +- formats/protobuf/pom.xml | 2 +- http/basic/pom.xml | 2 +- http/restful-ws-integration-tests/pom.xml | 2 +- http/restful-ws-integration-tests/restful-ws-common/pom.xml | 2 +- http/restful-ws-integration-tests/restful-ws-jersey/pom.xml | 2 +- http/restful-ws-integration-tests/restful-ws-resteasy/pom.xml | 2 +- http/restful-ws-integration-tests/restful-ws-spring/pom.xml | 2 +- http/restful-ws/pom.xml | 2 +- http/vertx/pom.xml | 2 +- kafka/pom.xml | 2 +- pom.xml | 2 +- spring/pom.xml | 2 +- sql/pom.xml | 2 +- 28 files changed, 28 insertions(+), 28 deletions(-) diff --git a/amqp/pom.xml b/amqp/pom.xml index 17155b2e5..a8612a432 100644 --- a/amqp/pom.xml +++ b/amqp/pom.xml @@ -6,7 +6,7 @@ io.cloudevents cloudevents-parent - 2.2.0 + 2.3.0-SNAPSHOT cloudevents-amqp-proton diff --git a/api/pom.xml b/api/pom.xml index b9246ef1b..31e3d23f1 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -24,7 +24,7 @@ io.cloudevents cloudevents-parent - 2.2.0 + 2.3.0-SNAPSHOT cloudevents-api diff --git a/benchmarks/pom.xml b/benchmarks/pom.xml index eb3fd0845..a2d5c34a9 100644 --- a/benchmarks/pom.xml +++ b/benchmarks/pom.xml @@ -21,7 +21,7 @@ io.cloudevents cloudevents-parent - 2.2.0 + 2.3.0-SNAPSHOT cloudevents-benchmarks diff --git a/core/pom.xml b/core/pom.xml index acc496c67..9c85d91d6 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -22,7 +22,7 @@ io.cloudevents cloudevents-parent - 2.2.0 + 2.3.0-SNAPSHOT cloudevents-core diff --git a/examples/amqp-proton/pom.xml b/examples/amqp-proton/pom.xml index b7d7c9dfb..2a28a9fd7 100644 --- a/examples/amqp-proton/pom.xml +++ b/examples/amqp-proton/pom.xml @@ -3,7 +3,7 @@ cloudevents-examples io.cloudevents - 2.2.0 + 2.3.0-SNAPSHOT 4.0.0 diff --git a/examples/basic-http/pom.xml b/examples/basic-http/pom.xml index a7d1e4d68..0c85e40cc 100644 --- a/examples/basic-http/pom.xml +++ b/examples/basic-http/pom.xml @@ -21,7 +21,7 @@ cloudevents-examples io.cloudevents - 2.2.0 + 2.3.0-SNAPSHOT 4.0.0 diff --git a/examples/kafka/pom.xml b/examples/kafka/pom.xml index 7398f0c7e..33a03dc7a 100644 --- a/examples/kafka/pom.xml +++ b/examples/kafka/pom.xml @@ -5,7 +5,7 @@ cloudevents-examples io.cloudevents - 2.2.0 + 2.3.0-SNAPSHOT 4.0.0 diff --git a/examples/pom.xml b/examples/pom.xml index 70bc167c2..7b6299be3 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ cloudevents-parent io.cloudevents - 2.2.0 + 2.3.0-SNAPSHOT 4.0.0 diff --git a/examples/restful-ws-quarkus/pom.xml b/examples/restful-ws-quarkus/pom.xml index 53ee2f7c3..4ca4f834f 100644 --- a/examples/restful-ws-quarkus/pom.xml +++ b/examples/restful-ws-quarkus/pom.xml @@ -5,7 +5,7 @@ cloudevents-examples io.cloudevents - 2.2.0 + 2.3.0-SNAPSHOT 4.0.0 cloudevents-restful-ws-quarkus-example diff --git a/examples/restful-ws-spring-boot/pom.xml b/examples/restful-ws-spring-boot/pom.xml index ea172b94e..d877c2e40 100644 --- a/examples/restful-ws-spring-boot/pom.xml +++ b/examples/restful-ws-spring-boot/pom.xml @@ -5,7 +5,7 @@ cloudevents-examples io.cloudevents - 2.2.0 + 2.3.0-SNAPSHOT 4.0.0 diff --git a/examples/spring-function/pom.xml b/examples/spring-function/pom.xml index 37390c1ff..fdb8a3b21 100644 --- a/examples/spring-function/pom.xml +++ b/examples/spring-function/pom.xml @@ -5,7 +5,7 @@ cloudevents-examples io.cloudevents - 2.2.0 + 2.3.0-SNAPSHOT 4.0.0 diff --git a/examples/spring-reactive/pom.xml b/examples/spring-reactive/pom.xml index 21c6a2eb1..25c2f0039 100644 --- a/examples/spring-reactive/pom.xml +++ b/examples/spring-reactive/pom.xml @@ -5,7 +5,7 @@ cloudevents-examples io.cloudevents - 2.2.0 + 2.3.0-SNAPSHOT 4.0.0 diff --git a/examples/spring-rsocket/pom.xml b/examples/spring-rsocket/pom.xml index f96e36b68..cd29b734f 100644 --- a/examples/spring-rsocket/pom.xml +++ b/examples/spring-rsocket/pom.xml @@ -5,7 +5,7 @@ cloudevents-examples io.cloudevents - 2.2.0 + 2.3.0-SNAPSHOT 4.0.0 diff --git a/examples/vertx/pom.xml b/examples/vertx/pom.xml index 73f9196f2..94b622f11 100644 --- a/examples/vertx/pom.xml +++ b/examples/vertx/pom.xml @@ -5,7 +5,7 @@ cloudevents-examples io.cloudevents - 2.2.0 + 2.3.0-SNAPSHOT 4.0.0 diff --git a/formats/json-jackson/pom.xml b/formats/json-jackson/pom.xml index a3b169468..b769aa11d 100644 --- a/formats/json-jackson/pom.xml +++ b/formats/json-jackson/pom.xml @@ -22,7 +22,7 @@ io.cloudevents cloudevents-parent - 2.2.0 + 2.3.0-SNAPSHOT ../../pom.xml diff --git a/formats/protobuf/pom.xml b/formats/protobuf/pom.xml index 033172404..5a490d61f 100644 --- a/formats/protobuf/pom.xml +++ b/formats/protobuf/pom.xml @@ -23,7 +23,7 @@ io.cloudevents cloudevents-parent - 2.2.0 + 2.3.0-SNAPSHOT ../../pom.xml diff --git a/http/basic/pom.xml b/http/basic/pom.xml index a5ec2b7e3..fd46a9adf 100644 --- a/http/basic/pom.xml +++ b/http/basic/pom.xml @@ -21,7 +21,7 @@ io.cloudevents cloudevents-parent - 2.2.0 + 2.3.0-SNAPSHOT ../../pom.xml diff --git a/http/restful-ws-integration-tests/pom.xml b/http/restful-ws-integration-tests/pom.xml index ce101d5f5..4a81ba815 100644 --- a/http/restful-ws-integration-tests/pom.xml +++ b/http/restful-ws-integration-tests/pom.xml @@ -22,7 +22,7 @@ cloudevents-parent io.cloudevents - 2.2.0 + 2.3.0-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/http/restful-ws-integration-tests/restful-ws-common/pom.xml b/http/restful-ws-integration-tests/restful-ws-common/pom.xml index 16b4e2e2f..7e691a914 100644 --- a/http/restful-ws-integration-tests/restful-ws-common/pom.xml +++ b/http/restful-ws-integration-tests/restful-ws-common/pom.xml @@ -22,7 +22,7 @@ cloudevents-http-restful-ws-integration-tests io.cloudevents - 2.2.0 + 2.3.0-SNAPSHOT ../ 4.0.0 diff --git a/http/restful-ws-integration-tests/restful-ws-jersey/pom.xml b/http/restful-ws-integration-tests/restful-ws-jersey/pom.xml index 9a99ddd95..a22edf54e 100644 --- a/http/restful-ws-integration-tests/restful-ws-jersey/pom.xml +++ b/http/restful-ws-integration-tests/restful-ws-jersey/pom.xml @@ -22,7 +22,7 @@ cloudevents-http-restful-ws-integration-tests io.cloudevents - 2.2.0 + 2.3.0-SNAPSHOT ../ 4.0.0 diff --git a/http/restful-ws-integration-tests/restful-ws-resteasy/pom.xml b/http/restful-ws-integration-tests/restful-ws-resteasy/pom.xml index 07b95fff5..8885d7def 100644 --- a/http/restful-ws-integration-tests/restful-ws-resteasy/pom.xml +++ b/http/restful-ws-integration-tests/restful-ws-resteasy/pom.xml @@ -22,7 +22,7 @@ cloudevents-http-restful-ws-integration-tests io.cloudevents - 2.2.0 + 2.3.0-SNAPSHOT ../ 4.0.0 diff --git a/http/restful-ws-integration-tests/restful-ws-spring/pom.xml b/http/restful-ws-integration-tests/restful-ws-spring/pom.xml index 5dcda8f0d..32ab38b36 100644 --- a/http/restful-ws-integration-tests/restful-ws-spring/pom.xml +++ b/http/restful-ws-integration-tests/restful-ws-spring/pom.xml @@ -22,7 +22,7 @@ cloudevents-http-restful-ws-integration-tests io.cloudevents - 2.2.0 + 2.3.0-SNAPSHOT ../ 4.0.0 diff --git a/http/restful-ws/pom.xml b/http/restful-ws/pom.xml index 52bc030f5..3f8ae0705 100644 --- a/http/restful-ws/pom.xml +++ b/http/restful-ws/pom.xml @@ -21,7 +21,7 @@ io.cloudevents cloudevents-parent - 2.2.0 + 2.3.0-SNAPSHOT ../../pom.xml diff --git a/http/vertx/pom.xml b/http/vertx/pom.xml index a2a9ec108..846ecc077 100644 --- a/http/vertx/pom.xml +++ b/http/vertx/pom.xml @@ -22,7 +22,7 @@ io.cloudevents cloudevents-parent - 2.2.0 + 2.3.0-SNAPSHOT ../../pom.xml diff --git a/kafka/pom.xml b/kafka/pom.xml index a05ddd46a..62997a9ec 100644 --- a/kafka/pom.xml +++ b/kafka/pom.xml @@ -23,7 +23,7 @@ io.cloudevents cloudevents-parent - 2.2.0 + 2.3.0-SNAPSHOT cloudevents-kafka diff --git a/pom.xml b/pom.xml index 2cd942c8a..c0d7f92f0 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ io.cloudevents cloudevents-parent - 2.2.0 + 2.3.0-SNAPSHOT pom CloudEvents diff --git a/spring/pom.xml b/spring/pom.xml index 820c41b27..3e44b0dca 100644 --- a/spring/pom.xml +++ b/spring/pom.xml @@ -23,7 +23,7 @@ io.cloudevents cloudevents-parent - 2.2.0 + 2.3.0-SNAPSHOT cloudevents-spring diff --git a/sql/pom.xml b/sql/pom.xml index 6b62eec1c..10d6eaa04 100644 --- a/sql/pom.xml +++ b/sql/pom.xml @@ -5,7 +5,7 @@ cloudevents-parent io.cloudevents - 2.2.0 + 2.3.0-SNAPSHOT 4.0.0 From 73a3c370d5e4c30c7031c11ccbc698dcaebe14a5 Mon Sep 17 00:00:00 2001 From: Nicolas Vervelle <77850427+nvervelle@users.noreply.github.com> Date: Mon, 28 Jun 2021 09:30:41 +0200 Subject: [PATCH 02/16] build: provide a Bill of Materials artifact for easier integration in projects (#405) Signed-off-by: Nicolas Vervelle --- bom/pom.xml | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++ docs/index.md | 5 +++ pom.xml | 1 + 3 files changed, 97 insertions(+) create mode 100644 bom/pom.xml diff --git a/bom/pom.xml b/bom/pom.xml new file mode 100644 index 000000000..733abc572 --- /dev/null +++ b/bom/pom.xml @@ -0,0 +1,91 @@ + + + + 4.0.0 + + + io.cloudevents + cloudevents-parent + 2.3.0-SNAPSHOT + + + cloudevents-bom + CloudEvents - Bill of Materials + pom + + + + + io.cloudevents + cloudevents-api + ${project.version} + + + io.cloudevents + cloudevents-core + ${project.version} + + + io.cloudevents + cloudevents-json-jackson + ${project.version} + + + io.cloudevents + cloudevents-protobuf + ${project.version} + + + io.cloudevents + cloudevents-amqp-proton + ${project.version} + + + io.cloudevents + cloudevents-http-basic + ${project.version} + + + io.cloudevents + cloudevents-http-vertx + ${project.version} + + + io.cloudevents + cloudevents-http-restful-ws + ${project.version} + + + io.cloudevents + cloudevents-kafka + ${project.version} + + + io.cloudevents + cloudevents-spring + ${project.version} + + + io.cloudevents + io.cloudevents.sql + ${project.version} + + + + diff --git a/docs/index.md b/docs/index.md index 5c222bd0b..ea4552f3a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -88,6 +88,9 @@ a different feature from the different sub specs of [Event Formats](https://github.com/cloudevents/spec/blob/v1.0/spec.md#event-format), `MessageReader` /`MessageWriter` to implement [Protocol bindings](https://github.com/cloudevents/spec/blob/v1.0/spec.md#protocol-binding) +- [`cloudevents-bom`] Module providing a + [bill of materials (BOM)](https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#bill-of-materials-bom-poms) + for easier integration of CloudEvents in other projects - [`cloudevents-json-jackson`] Implementation of [JSON Event format] with [Jackson](https://github.com/FasterXML/jackson) - [`cloudevents-protobuf`] Implementation of [Protobuf Event format] using code generated @@ -113,8 +116,10 @@ You can look at the latest published artifacts on [Kafka Protocol Binding]: https://github.com/cloudevents/spec/blob/v1.0/kafka-protocol-binding.md [AMQP Protocol Binding]: https://github.com/cloudevents/spec/blob/v1.0/amqp-protocol-binding.md [`cloudevents-api`]: https://github.com/cloudevents/sdk-java/tree/master/api +[`cloudevents-bom`]: https://github.com/cloudevents/sdk-java/tree/master/bom [`cloudevents-core`]: https://github.com/cloudevents/sdk-java/tree/master/core [`cloudevents-json-jackson`]: https://github.com/cloudevents/sdk-java/tree/master/formats/json-jackson +[`cloudevents-protobuf`]: https://github.com/cloudevents/sdk-java/tree/master/formats/protobuf [`cloudevents-http-vertx`]: https://github.com/cloudevents/sdk-java/tree/master/http/vertx [`cloudevents-http-basic`]: https://github.com/cloudevents/sdk-java/tree/master/http/basic [`cloudevents-http-restful-ws`]: https://github.com/cloudevents/sdk-java/tree/master/http/restful-ws diff --git a/pom.xml b/pom.xml index c0d7f92f0..a124a66aa 100644 --- a/pom.xml +++ b/pom.xml @@ -77,6 +77,7 @@ kafka spring sql + bom From 06c4ec53853c8c4c962be59e63ed55b0760b63f5 Mon Sep 17 00:00:00 2001 From: Francesco Guardiani Date: Mon, 5 Jul 2021 11:43:46 +0200 Subject: [PATCH 03/16] Moved exception factory methods internally (#402) Signed-off-by: Francesco Guardiani --- .../cloudevents/sql/EvaluationException.java | 61 +--------- .../io/cloudevents/sql/ParseException.java | 43 ++----- .../sql/impl/ExceptionFactory.java | 107 ++++++++++++++++++ .../AccessAttributeExpression.java | 4 +- .../impl/expressions/DivisionExpression.java | 4 +- .../FunctionInvocationExpression.java | 4 +- .../impl/expressions/ModuleExpression.java | 4 +- .../sql/impl/functions/LeftFunction.java | 4 +- .../sql/impl/functions/RightFunction.java | 4 +- .../sql/impl/functions/SubstringFunction.java | 4 +- .../SubstringWithLengthFunction.java | 4 +- .../parser/ExpressionTranslatorVisitor.java | 6 +- .../sql/impl/parser/ParserImpl.java | 5 +- .../sql/impl/runtime/TypeCastingProvider.java | 10 +- 14 files changed, 145 insertions(+), 119 deletions(-) create mode 100644 sql/src/main/java/io/cloudevents/sql/impl/ExceptionFactory.java diff --git a/sql/src/main/java/io/cloudevents/sql/EvaluationException.java b/sql/src/main/java/io/cloudevents/sql/EvaluationException.java index ab97537ab..e5ea1f663 100644 --- a/sql/src/main/java/io/cloudevents/sql/EvaluationException.java +++ b/sql/src/main/java/io/cloudevents/sql/EvaluationException.java @@ -43,7 +43,7 @@ public enum ErrorKind { private final Interval interval; private final String expression; - protected EvaluationException(ErrorKind errorKind, Interval interval, String expression, String message, Throwable cause) { + public EvaluationException(ErrorKind errorKind, Interval interval, String expression, String message, Throwable cause) { super(String.format("%s at %s `%s`: %s", errorKind.name(), interval.toString(), expression, message), cause); this.errorKind = errorKind; this.interval = interval; @@ -62,63 +62,4 @@ public String getExpressionText() { return expression; } - public static EvaluationExceptionFactory invalidCastTarget(Class from, Class to) { - return (interval, expression) -> new EvaluationException( - ErrorKind.INVALID_CAST, - interval, - expression, - "Cannot cast " + from + " to " + to + ": no cast defined.", - null - ); - } - - public static EvaluationExceptionFactory castError(Class from, Class to, Throwable cause) { - return (interval, expression) -> new EvaluationException( - ErrorKind.INVALID_CAST, - interval, - expression, - "Cannot cast " + from + " to " + to + ": " + cause.getMessage(), - cause - ); - } - - public static EvaluationException missingAttribute(Interval interval, String expression, String key) { - return new EvaluationException( - ErrorKind.MISSING_ATTRIBUTE, - interval, - expression, - "Missing attribute " + key + " in the input event. Perhaps you should check with 'EXISTS " + key + "' if the input contains the provided key?", - null - ); - } - - public static EvaluationException cannotDispatchFunction(Interval interval, String expression, String functionName, Throwable cause) { - return new EvaluationException( - ErrorKind.FUNCTION_DISPATCH, - interval, - expression, - "Cannot dispatch function invocation to function " + functionName + ": " + cause.getMessage(), - cause - ); - } - - public static EvaluationExceptionFactory functionExecutionError(String functionName, Throwable cause) { - return (interval, expression) -> new EvaluationException( - ErrorKind.FUNCTION_EXECUTION, - interval, - expression, - "Error while executing " + functionName + ": " + cause.getMessage(), - cause - ); - } - - public static EvaluationException divisionByZero(Interval interval, String expression, Integer dividend) { - return new EvaluationException( - ErrorKind.MATH, - interval, - expression, - "Division by zero: " + dividend + " / 0", - null - ); - } } diff --git a/sql/src/main/java/io/cloudevents/sql/ParseException.java b/sql/src/main/java/io/cloudevents/sql/ParseException.java index 77212a02b..7fd477f53 100644 --- a/sql/src/main/java/io/cloudevents/sql/ParseException.java +++ b/sql/src/main/java/io/cloudevents/sql/ParseException.java @@ -1,8 +1,6 @@ package io.cloudevents.sql; -import org.antlr.v4.runtime.RecognitionException; import org.antlr.v4.runtime.misc.Interval; -import org.antlr.v4.runtime.tree.ParseTree; /** * This exception represents an error occurred during parsing. @@ -10,8 +8,17 @@ public class ParseException extends RuntimeException { public enum ErrorKind { + /** + * Error when parsing the expression string + */ RECOGNITION, + /** + * Error when parsing a literal + */ PARSE_VALUE, + /** + * Error when executing the constant parts of the expression + */ CONSTANT_EXPRESSION_EVALUATION, } @@ -19,7 +26,7 @@ public enum ErrorKind { private final Interval interval; private final String expression; - protected ParseException(ErrorKind errorKind, Interval interval, String expression, String message, Throwable cause) { + public ParseException(ErrorKind errorKind, Interval interval, String expression, String message, Throwable cause) { super(String.format("[%s at %d:%d `%s`] %s", errorKind.name(), interval.a, interval.b, expression, message), cause); this.errorKind = errorKind; this.interval = interval; @@ -38,34 +45,4 @@ public String getExpression() { return expression; } - public static ParseException cannotParseValue(ParseTree node, Type target, Throwable cause) { - return new ParseException( - ErrorKind.PARSE_VALUE, - node.getSourceInterval(), - node.getText(), - "Cannot parse to " + target.name() + ": " + cause.getMessage(), - cause - ); - } - - public static ParseException recognitionError(RecognitionException e, String msg) { - return new ParseException( - ErrorKind.RECOGNITION, - new Interval(e.getOffendingToken().getStartIndex(), e.getOffendingToken().getStopIndex()), - e.getOffendingToken().getText(), - "Cannot parse: " + msg, - e - ); - } - - public static ParseException cannotEvaluateConstantExpression(EvaluationException exception) { - return new ParseException( - ErrorKind.CONSTANT_EXPRESSION_EVALUATION, - exception.getExpressionInterval(), - exception.getExpressionText(), - "Cannot evaluate the constant expression: " + exception.getExpressionText(), - exception - ); - } - } diff --git a/sql/src/main/java/io/cloudevents/sql/impl/ExceptionFactory.java b/sql/src/main/java/io/cloudevents/sql/impl/ExceptionFactory.java new file mode 100644 index 000000000..ec03498e4 --- /dev/null +++ b/sql/src/main/java/io/cloudevents/sql/impl/ExceptionFactory.java @@ -0,0 +1,107 @@ +package io.cloudevents.sql.impl; + +import io.cloudevents.sql.EvaluationException; +import io.cloudevents.sql.ParseException; +import io.cloudevents.sql.Type; +import org.antlr.v4.runtime.RecognitionException; +import org.antlr.v4.runtime.misc.Interval; +import org.antlr.v4.runtime.tree.ParseTree; + +/** + * This class includes a list of static methods to create {@link io.cloudevents.sql.ParseException} and {@link io.cloudevents.sql.EvaluationException}. + */ +public class ExceptionFactory { + + private ExceptionFactory() { + } + + public static EvaluationException.EvaluationExceptionFactory invalidCastTarget(Class from, Class to) { + return (interval, expression) -> new EvaluationException( + EvaluationException.ErrorKind.INVALID_CAST, + interval, + expression, + "Cannot cast " + from + " to " + to + ": no cast defined.", + null + ); + } + + public static EvaluationException.EvaluationExceptionFactory castError(Class from, Class to, Throwable cause) { + return (interval, expression) -> new EvaluationException( + EvaluationException.ErrorKind.INVALID_CAST, + interval, + expression, + "Cannot cast " + from + " to " + to + ": " + cause.getMessage(), + cause + ); + } + + public static EvaluationException missingAttribute(Interval interval, String expression, String key) { + return new EvaluationException( + EvaluationException.ErrorKind.MISSING_ATTRIBUTE, + interval, + expression, + "Missing attribute " + key + " in the input event. Perhaps you should check with 'EXISTS " + key + "' if the input contains the provided key?", + null + ); + } + + public static EvaluationException cannotDispatchFunction(Interval interval, String expression, String functionName, Throwable cause) { + return new EvaluationException( + EvaluationException.ErrorKind.FUNCTION_DISPATCH, + interval, + expression, + "Cannot dispatch function invocation to function " + functionName + ": " + cause.getMessage(), + cause + ); + } + + public static EvaluationException.EvaluationExceptionFactory functionExecutionError(String functionName, Throwable cause) { + return (interval, expression) -> new EvaluationException( + EvaluationException.ErrorKind.FUNCTION_EXECUTION, + interval, + expression, + "Error while executing " + functionName + ": " + cause.getMessage(), + cause + ); + } + + public static EvaluationException divisionByZero(Interval interval, String expression, Integer dividend) { + return new EvaluationException( + EvaluationException.ErrorKind.MATH, + interval, + expression, + "Division by zero: " + dividend + " / 0", + null + ); + } + + public static ParseException cannotParseValue(ParseTree node, Type target, Throwable cause) { + return new ParseException( + ParseException.ErrorKind.PARSE_VALUE, + node.getSourceInterval(), + node.getText(), + "Cannot parse to " + target.name() + ": " + cause.getMessage(), + cause + ); + } + + public static ParseException recognitionError(RecognitionException e, String msg) { + return new ParseException( + ParseException.ErrorKind.RECOGNITION, + new Interval(e.getOffendingToken().getStartIndex(), e.getOffendingToken().getStopIndex()), + e.getOffendingToken().getText(), + "Cannot parse: " + msg, + e + ); + } + + public static ParseException cannotEvaluateConstantExpression(EvaluationException exception) { + return new ParseException( + ParseException.ErrorKind.CONSTANT_EXPRESSION_EVALUATION, + exception.getExpressionInterval(), + exception.getExpressionText(), + "Cannot evaluate the constant expression: " + exception.getExpressionText(), + exception + ); + } +} diff --git a/sql/src/main/java/io/cloudevents/sql/impl/expressions/AccessAttributeExpression.java b/sql/src/main/java/io/cloudevents/sql/impl/expressions/AccessAttributeExpression.java index 1755a8fee..63243a91a 100644 --- a/sql/src/main/java/io/cloudevents/sql/impl/expressions/AccessAttributeExpression.java +++ b/sql/src/main/java/io/cloudevents/sql/impl/expressions/AccessAttributeExpression.java @@ -2,8 +2,8 @@ import io.cloudevents.CloudEvent; import io.cloudevents.SpecVersion; -import io.cloudevents.sql.EvaluationException; import io.cloudevents.sql.EvaluationRuntime; +import io.cloudevents.sql.impl.ExceptionFactory; import io.cloudevents.sql.impl.ExceptionThrower; import io.cloudevents.sql.impl.ExpressionInternalVisitor; import org.antlr.v4.runtime.misc.Interval; @@ -28,7 +28,7 @@ public Object evaluate(EvaluationRuntime runtime, CloudEvent event, ExceptionThr Object value = this.getter.apply(event); if (value == null) { thrower.throwException( - EvaluationException.missingAttribute(this.expressionInterval(), this.expressionText(), key) + ExceptionFactory.missingAttribute(this.expressionInterval(), this.expressionText(), key) ); return ""; } diff --git a/sql/src/main/java/io/cloudevents/sql/impl/expressions/DivisionExpression.java b/sql/src/main/java/io/cloudevents/sql/impl/expressions/DivisionExpression.java index b28bb5803..8e54f0ac9 100644 --- a/sql/src/main/java/io/cloudevents/sql/impl/expressions/DivisionExpression.java +++ b/sql/src/main/java/io/cloudevents/sql/impl/expressions/DivisionExpression.java @@ -1,7 +1,7 @@ package io.cloudevents.sql.impl.expressions; -import io.cloudevents.sql.EvaluationException; import io.cloudevents.sql.EvaluationRuntime; +import io.cloudevents.sql.impl.ExceptionFactory; import io.cloudevents.sql.impl.ExceptionThrower; import io.cloudevents.sql.impl.ExpressionInternal; import org.antlr.v4.runtime.misc.Interval; @@ -16,7 +16,7 @@ public DivisionExpression(Interval expressionInterval, String expressionText, Ex Object evaluate(EvaluationRuntime runtime, int left, int right, ExceptionThrower exceptions) { if (right == 0) { exceptions.throwException( - EvaluationException.divisionByZero(expressionInterval(), expressionText(), left) + ExceptionFactory.divisionByZero(expressionInterval(), expressionText(), left) ); return 0; } diff --git a/sql/src/main/java/io/cloudevents/sql/impl/expressions/FunctionInvocationExpression.java b/sql/src/main/java/io/cloudevents/sql/impl/expressions/FunctionInvocationExpression.java index e36e76678..05183b851 100644 --- a/sql/src/main/java/io/cloudevents/sql/impl/expressions/FunctionInvocationExpression.java +++ b/sql/src/main/java/io/cloudevents/sql/impl/expressions/FunctionInvocationExpression.java @@ -2,9 +2,9 @@ import io.cloudevents.CloudEvent; import io.cloudevents.sql.EvaluationContext; -import io.cloudevents.sql.EvaluationException; import io.cloudevents.sql.EvaluationRuntime; import io.cloudevents.sql.Function; +import io.cloudevents.sql.impl.ExceptionFactory; import io.cloudevents.sql.impl.ExceptionThrower; import io.cloudevents.sql.impl.ExpressionInternal; import io.cloudevents.sql.impl.ExpressionInternalVisitor; @@ -34,7 +34,7 @@ public Object evaluate(EvaluationRuntime runtime, CloudEvent event, ExceptionThr function = runtime.resolveFunction(functionName, arguments.size()); } catch (Exception e) { thrower.throwException( - EvaluationException.cannotDispatchFunction(expressionInterval(), expressionText(), functionName, e) + ExceptionFactory.cannotDispatchFunction(expressionInterval(), expressionText(), functionName, e) ); return ""; } diff --git a/sql/src/main/java/io/cloudevents/sql/impl/expressions/ModuleExpression.java b/sql/src/main/java/io/cloudevents/sql/impl/expressions/ModuleExpression.java index f15abe7ce..aa11a38c3 100644 --- a/sql/src/main/java/io/cloudevents/sql/impl/expressions/ModuleExpression.java +++ b/sql/src/main/java/io/cloudevents/sql/impl/expressions/ModuleExpression.java @@ -1,7 +1,7 @@ package io.cloudevents.sql.impl.expressions; -import io.cloudevents.sql.EvaluationException; import io.cloudevents.sql.EvaluationRuntime; +import io.cloudevents.sql.impl.ExceptionFactory; import io.cloudevents.sql.impl.ExceptionThrower; import io.cloudevents.sql.impl.ExpressionInternal; import org.antlr.v4.runtime.misc.Interval; @@ -16,7 +16,7 @@ public ModuleExpression(Interval expressionInterval, String expressionText, Expr Object evaluate(EvaluationRuntime runtime, int left, int right, ExceptionThrower exceptions) { if (right == 0) { exceptions.throwException( - EvaluationException.divisionByZero(expressionInterval(), expressionText(), left) + ExceptionFactory.divisionByZero(expressionInterval(), expressionText(), left) ); return 0; } diff --git a/sql/src/main/java/io/cloudevents/sql/impl/functions/LeftFunction.java b/sql/src/main/java/io/cloudevents/sql/impl/functions/LeftFunction.java index cc3b7dc4b..563c6124b 100644 --- a/sql/src/main/java/io/cloudevents/sql/impl/functions/LeftFunction.java +++ b/sql/src/main/java/io/cloudevents/sql/impl/functions/LeftFunction.java @@ -2,8 +2,8 @@ import io.cloudevents.CloudEvent; import io.cloudevents.sql.EvaluationContext; -import io.cloudevents.sql.EvaluationException; import io.cloudevents.sql.EvaluationRuntime; +import io.cloudevents.sql.impl.ExceptionFactory; public class LeftFunction extends BaseTwoArgumentFunction { public LeftFunction() { @@ -17,7 +17,7 @@ Object invoke(EvaluationContext ctx, EvaluationRuntime evaluationRuntime, CloudE } if (length < 0) { ctx.appendException( - EvaluationException.functionExecutionError(name(), new IllegalArgumentException("The length of the LEFT substring is lower than 0: " + length)) + ExceptionFactory.functionExecutionError(name(), new IllegalArgumentException("The length of the LEFT substring is lower than 0: " + length)) ); return s; } diff --git a/sql/src/main/java/io/cloudevents/sql/impl/functions/RightFunction.java b/sql/src/main/java/io/cloudevents/sql/impl/functions/RightFunction.java index 3a110e627..b5817901c 100644 --- a/sql/src/main/java/io/cloudevents/sql/impl/functions/RightFunction.java +++ b/sql/src/main/java/io/cloudevents/sql/impl/functions/RightFunction.java @@ -2,8 +2,8 @@ import io.cloudevents.CloudEvent; import io.cloudevents.sql.EvaluationContext; -import io.cloudevents.sql.EvaluationException; import io.cloudevents.sql.EvaluationRuntime; +import io.cloudevents.sql.impl.ExceptionFactory; public class RightFunction extends BaseTwoArgumentFunction { public RightFunction() { @@ -17,7 +17,7 @@ Object invoke(EvaluationContext ctx, EvaluationRuntime evaluationRuntime, CloudE } if (length < 0) { ctx.appendException( - EvaluationException.functionExecutionError(name(), new IllegalArgumentException("The length of the RIGHT substring is lower than 0: " + length)) + ExceptionFactory.functionExecutionError(name(), new IllegalArgumentException("The length of the RIGHT substring is lower than 0: " + length)) ); return s; } diff --git a/sql/src/main/java/io/cloudevents/sql/impl/functions/SubstringFunction.java b/sql/src/main/java/io/cloudevents/sql/impl/functions/SubstringFunction.java index 1738a26d4..7123e1286 100644 --- a/sql/src/main/java/io/cloudevents/sql/impl/functions/SubstringFunction.java +++ b/sql/src/main/java/io/cloudevents/sql/impl/functions/SubstringFunction.java @@ -2,8 +2,8 @@ import io.cloudevents.CloudEvent; import io.cloudevents.sql.EvaluationContext; -import io.cloudevents.sql.EvaluationException; import io.cloudevents.sql.EvaluationRuntime; +import io.cloudevents.sql.impl.ExceptionFactory; public class SubstringFunction extends BaseTwoArgumentFunction { public SubstringFunction() { @@ -15,7 +15,7 @@ Object invoke(EvaluationContext ctx, EvaluationRuntime evaluationRuntime, CloudE try { return SubstringWithLengthFunction.substring(x, pos, null); } catch (Exception e) { - ctx.appendException(EvaluationException.functionExecutionError( + ctx.appendException(ExceptionFactory.functionExecutionError( name(), e )); diff --git a/sql/src/main/java/io/cloudevents/sql/impl/functions/SubstringWithLengthFunction.java b/sql/src/main/java/io/cloudevents/sql/impl/functions/SubstringWithLengthFunction.java index c1edff078..50767507a 100644 --- a/sql/src/main/java/io/cloudevents/sql/impl/functions/SubstringWithLengthFunction.java +++ b/sql/src/main/java/io/cloudevents/sql/impl/functions/SubstringWithLengthFunction.java @@ -2,8 +2,8 @@ import io.cloudevents.CloudEvent; import io.cloudevents.sql.EvaluationContext; -import io.cloudevents.sql.EvaluationException; import io.cloudevents.sql.EvaluationRuntime; +import io.cloudevents.sql.impl.ExceptionFactory; public class SubstringWithLengthFunction extends BaseThreeArgumentFunction { public SubstringWithLengthFunction() { @@ -15,7 +15,7 @@ Object invoke(EvaluationContext ctx, EvaluationRuntime evaluationRuntime, CloudE try { return substring(x, pos, len); } catch (Exception e) { - ctx.appendException(EvaluationException.functionExecutionError( + ctx.appendException(ExceptionFactory.functionExecutionError( name(), e )); diff --git a/sql/src/main/java/io/cloudevents/sql/impl/parser/ExpressionTranslatorVisitor.java b/sql/src/main/java/io/cloudevents/sql/impl/parser/ExpressionTranslatorVisitor.java index fd8d9b948..8ce88259f 100644 --- a/sql/src/main/java/io/cloudevents/sql/impl/parser/ExpressionTranslatorVisitor.java +++ b/sql/src/main/java/io/cloudevents/sql/impl/parser/ExpressionTranslatorVisitor.java @@ -1,9 +1,9 @@ package io.cloudevents.sql.impl.parser; -import io.cloudevents.sql.ParseException; import io.cloudevents.sql.Type; import io.cloudevents.sql.generated.CESQLParserBaseVisitor; import io.cloudevents.sql.generated.CESQLParserParser; +import io.cloudevents.sql.impl.ExceptionFactory; import io.cloudevents.sql.impl.ExpressionInternal; import io.cloudevents.sql.impl.expressions.*; @@ -31,7 +31,7 @@ public ExpressionInternal visitIntegerLiteral(CESQLParserParser.IntegerLiteralCo try { return ValueExpression.fromIntegerLiteral(ctx.INTEGER_LITERAL()); } catch (RuntimeException e) { - throw ParseException.cannotParseValue(ctx, Type.INTEGER, e); + throw ExceptionFactory.cannotParseValue(ctx, Type.INTEGER, e); } } @@ -44,7 +44,7 @@ public ExpressionInternal visitStringLiteral(CESQLParserParser.StringLiteralCont return ValueExpression.fromSQuotedStringLiteral(ctx.SQUOTED_STRING_LITERAL()); } } catch (RuntimeException e) { - throw ParseException.cannotParseValue(ctx, Type.STRING, e); + throw ExceptionFactory.cannotParseValue(ctx, Type.STRING, e); } } diff --git a/sql/src/main/java/io/cloudevents/sql/impl/parser/ParserImpl.java b/sql/src/main/java/io/cloudevents/sql/impl/parser/ParserImpl.java index 30f9437dc..c0f042358 100644 --- a/sql/src/main/java/io/cloudevents/sql/impl/parser/ParserImpl.java +++ b/sql/src/main/java/io/cloudevents/sql/impl/parser/ParserImpl.java @@ -6,6 +6,7 @@ import io.cloudevents.sql.Parser; import io.cloudevents.sql.generated.CESQLParserLexer; import io.cloudevents.sql.generated.CESQLParserParser; +import io.cloudevents.sql.impl.ExceptionFactory; import io.cloudevents.sql.impl.ExpressionInternal; import io.cloudevents.sql.impl.runtime.ExpressionImpl; import org.antlr.v4.runtime.*; @@ -52,7 +53,7 @@ public Expression parse(String inputExpression) { @Override public void syntaxError(Recognizer recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) { parseExceptionList.add( - ParseException.recognitionError(e, msg) + ExceptionFactory.recognitionError(e, msg) ); } @@ -82,7 +83,7 @@ public void reportContextSensitivity(org.antlr.v4.runtime.Parser recognizer, DFA try { internal = internal.visit(new ConstantFoldingExpressionVisitor()); } catch (EvaluationException e) { - throw ParseException.cannotEvaluateConstantExpression(e); + throw ExceptionFactory.cannotEvaluateConstantExpression(e); } } diff --git a/sql/src/main/java/io/cloudevents/sql/impl/runtime/TypeCastingProvider.java b/sql/src/main/java/io/cloudevents/sql/impl/runtime/TypeCastingProvider.java index 51f881bcc..ddfc6c468 100644 --- a/sql/src/main/java/io/cloudevents/sql/impl/runtime/TypeCastingProvider.java +++ b/sql/src/main/java/io/cloudevents/sql/impl/runtime/TypeCastingProvider.java @@ -1,8 +1,8 @@ package io.cloudevents.sql.impl.runtime; import io.cloudevents.sql.EvaluationContext; -import io.cloudevents.sql.EvaluationException; import io.cloudevents.sql.Type; +import io.cloudevents.sql.impl.ExceptionFactory; import java.util.Objects; @@ -53,12 +53,12 @@ Object cast(EvaluationContext ctx, Object value, Type target) { return Integer.parseInt((String) value); } catch (NumberFormatException e) { ctx.appendException( - EvaluationException.castError(String.class, Integer.class, e) + ExceptionFactory.castError(String.class, Integer.class, e) ); } } else { ctx.appendException( - EvaluationException.invalidCastTarget(value.getClass(), target.valueClass()) + ExceptionFactory.invalidCastTarget(value.getClass(), target.valueClass()) ); } return 0; @@ -68,12 +68,12 @@ Object cast(EvaluationContext ctx, Object value, Type target) { return parseBool((String) value); } catch (IllegalArgumentException e) { ctx.appendException( - EvaluationException.castError(String.class, Boolean.class, e) + ExceptionFactory.castError(String.class, Boolean.class, e) ); } } else { ctx.appendException( - EvaluationException.invalidCastTarget(value.getClass(), target.valueClass()) + ExceptionFactory.invalidCastTarget(value.getClass(), target.valueClass()) ); } return false; From 15877088050d7e4fd29e2c5078900f829a89c9e3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Jul 2021 12:22:46 +0200 Subject: [PATCH 04/16] Bump spring-framework-bom (#382) Bumps [spring-framework-bom](https://github.com/spring-projects/spring-framework) from 5.2.8.RELEASE to 5.2.9.RELEASE. - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v5.2.8.RELEASE...v5.2.9.RELEASE) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- http/restful-ws-integration-tests/restful-ws-spring/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/http/restful-ws-integration-tests/restful-ws-spring/pom.xml b/http/restful-ws-integration-tests/restful-ws-spring/pom.xml index 32ab38b36..dfeac7c41 100644 --- a/http/restful-ws-integration-tests/restful-ws-spring/pom.xml +++ b/http/restful-ws-integration-tests/restful-ws-spring/pom.xml @@ -33,7 +33,7 @@ 2.3.2.RELEASE - 5.2.8.RELEASE + 5.2.9.RELEASE From 5a323942d3d8df28cf6a13632937f8f1ac8a9083 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Jul 2021 12:22:52 +0200 Subject: [PATCH 05/16] Bump jetty-server in /examples/basic-http (#403) Bumps [jetty-server](https://github.com/eclipse/jetty.project) from 9.4.38.v20210224 to 9.4.41.v20210516. - [Release notes](https://github.com/eclipse/jetty.project/releases) - [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.38.v20210224...jetty-9.4.41.v20210516) --- updated-dependencies: - dependency-name: org.eclipse.jetty:jetty-server dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/basic-http/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/basic-http/pom.xml b/examples/basic-http/pom.xml index 0c85e40cc..8a3b84c44 100644 --- a/examples/basic-http/pom.xml +++ b/examples/basic-http/pom.xml @@ -41,7 +41,7 @@ org.eclipse.jetty jetty-server - 9.4.38.v20210224 + 9.4.41.v20210516 From 624ac693d83319c7a22f6b65472aa99299546703 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Nov 2021 08:06:43 +0100 Subject: [PATCH 06/16] Bump nokogiri from 1.11.5 to 1.12.5 in /docs (#419) Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.11.5 to 1.12.5. - [Release notes](https://github.com/sparklemotion/nokogiri/releases) - [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md) - [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.11.5...v1.12.5) --- updated-dependencies: - dependency-name: nokogiri dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/Gemfile.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock index addc79aa8..163a0efe8 100644 --- a/docs/Gemfile.lock +++ b/docs/Gemfile.lock @@ -207,15 +207,15 @@ GEM rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) mercenary (0.3.6) - mini_portile2 (2.5.1) + mini_portile2 (2.6.1) minima (2.5.1) jekyll (>= 3.5, < 5.0) jekyll-feed (~> 0.9) jekyll-seo-tag (~> 2.1) minitest (5.14.2) multipart-post (2.1.1) - nokogiri (1.11.5) - mini_portile2 (~> 2.5.0) + nokogiri (1.12.5) + mini_portile2 (~> 2.6.1) racc (~> 1.4) octokit (4.19.0) faraday (>= 0.9) From 202849307c5fbfe8bf63ef33e6f3a22d99df0c87 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Nov 2021 08:07:20 +0100 Subject: [PATCH 07/16] Bump addressable from 2.7.0 to 2.8.0 in /docs (#406) Bumps [addressable](https://github.com/sporkmonger/addressable) from 2.7.0 to 2.8.0. - [Release notes](https://github.com/sporkmonger/addressable/releases) - [Changelog](https://github.com/sporkmonger/addressable/blob/main/CHANGELOG.md) - [Commits](https://github.com/sporkmonger/addressable/compare/addressable-2.7.0...addressable-2.8.0) --- updated-dependencies: - dependency-name: addressable dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock index 163a0efe8..8110e5932 100644 --- a/docs/Gemfile.lock +++ b/docs/Gemfile.lock @@ -7,7 +7,7 @@ GEM minitest (~> 5.1) tzinfo (~> 1.1) zeitwerk (~> 2.2, >= 2.2.2) - addressable (2.7.0) + addressable (2.8.0) public_suffix (>= 2.0.2, < 5.0) coffee-script (2.4.1) coffee-script-source From 0277ee4ae4d8f843055868f8703e004376711fac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Nov 2021 08:26:35 +0100 Subject: [PATCH 08/16] Bump spring-framework-bom in /examples/restful-ws-spring-boot (#423) Bumps [spring-framework-bom](https://github.com/spring-projects/spring-framework) from 5.2.8.RELEASE to 5.2.9.RELEASE. - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v5.2.8.RELEASE...v5.2.9.RELEASE) --- updated-dependencies: - dependency-name: org.springframework:spring-framework-bom dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/restful-ws-spring-boot/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/restful-ws-spring-boot/pom.xml b/examples/restful-ws-spring-boot/pom.xml index d877c2e40..e282d896e 100644 --- a/examples/restful-ws-spring-boot/pom.xml +++ b/examples/restful-ws-spring-boot/pom.xml @@ -13,7 +13,7 @@ 2.3.2.RELEASE - 5.2.8.RELEASE + 5.2.9.RELEASE From 32adfe912334594b3598d09146118cde3ddbfa98 Mon Sep 17 00:00:00 2001 From: Dmitrii Bocharov Date: Wed, 3 Nov 2021 08:28:54 +0100 Subject: [PATCH 09/16] Fix NPE in CloudEventDeserializer when deserializing header with null value (#415) Signed-off-by: Dmitrii Bocharov --- .../BaseGenericBinaryMessageReaderImpl.java | 3 +++ .../kafka/CloudEventDeserializerTest.java | 21 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/core/src/main/java/io/cloudevents/core/message/impl/BaseGenericBinaryMessageReaderImpl.java b/core/src/main/java/io/cloudevents/core/message/impl/BaseGenericBinaryMessageReaderImpl.java index 38b1506fd..cf0b00cc0 100644 --- a/core/src/main/java/io/cloudevents/core/message/impl/BaseGenericBinaryMessageReaderImpl.java +++ b/core/src/main/java/io/cloudevents/core/message/impl/BaseGenericBinaryMessageReaderImpl.java @@ -56,6 +56,9 @@ public , V> V read(CloudEventWriterFactory w // This implementation avoids to use visitAttributes and visitExtensions // in order to complete the visit in one loop this.forEachHeader((key, value) -> { + if (value == null) { + return; + } if (isContentTypeHeader(key)) { visitor.withContextAttribute(CloudEventV1.DATACONTENTTYPE, toCloudEventsValue(value)); } else if (isCloudEventsHeader(key)) { diff --git a/kafka/src/test/java/io/cloudevents/kafka/CloudEventDeserializerTest.java b/kafka/src/test/java/io/cloudevents/kafka/CloudEventDeserializerTest.java index ca92b4258..6ab7606be 100644 --- a/kafka/src/test/java/io/cloudevents/kafka/CloudEventDeserializerTest.java +++ b/kafka/src/test/java/io/cloudevents/kafka/CloudEventDeserializerTest.java @@ -23,6 +23,7 @@ import io.cloudevents.core.test.Data; import io.cloudevents.rw.CloudEventDataMapper; import org.apache.kafka.clients.producer.ProducerRecord; +import org.apache.kafka.common.header.Headers; import org.junit.jupiter.api.Test; import java.util.HashMap; @@ -60,6 +61,26 @@ public void deserializerWithMapper() { ); } + @Test + public void deserializerShouldWorkWithNullableManuallyDefinedHeaders() { + String topic = "test"; + CloudEvent testCloudEvent = Data.V1_MIN; + CloudEventDeserializer cloudEventDeserializer = new CloudEventDeserializer(); + + // Serialize the event first + ProducerRecord inRecord = KafkaMessageFactory + .createWriter(topic) + .writeBinary(testCloudEvent); + + // add optional subject header with null value + Headers headers = inRecord.headers(); + headers.add("ce_subject", null); + CloudEvent outEvent = cloudEventDeserializer.deserialize(topic, headers, inRecord.value()); + + assertThat(outEvent) + .isEqualTo(testCloudEvent); + } + private void testDeserialize(CloudEventDeserializer deserializer, CloudEvent input, CloudEvent expected) { String topic = "test"; From a94bc5c81c83d21b5d6ec367830b66b0d9569a6d Mon Sep 17 00:00:00 2001 From: Joke de Buhr Date: Wed, 3 Nov 2021 09:54:38 +0100 Subject: [PATCH 10/16] Close input stream on CloudEventHttpMessageReader (#421) Signed-off-by: Joke de Buhr --- .../spring/webflux/CloudEventHttpMessageReader.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/spring/src/main/java/io/cloudevents/spring/webflux/CloudEventHttpMessageReader.java b/spring/src/main/java/io/cloudevents/spring/webflux/CloudEventHttpMessageReader.java index fe8a9b37e..92892aa9d 100644 --- a/spring/src/main/java/io/cloudevents/spring/webflux/CloudEventHttpMessageReader.java +++ b/spring/src/main/java/io/cloudevents/spring/webflux/CloudEventHttpMessageReader.java @@ -28,6 +28,7 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import java.io.InputStream; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -62,8 +63,8 @@ public Mono readMono(ResolvableType elementType, ReactiveHttpInputMe Map hints) { HttpHeaders headers = message.getHeaders(); Mono body = DataBufferUtils.join(message.getBody()).map(buffer -> { - try { - return StreamUtils.copyToByteArray(buffer.asInputStream(true)); + try (InputStream inputStream = buffer.asInputStream(true)) { + return StreamUtils.copyToByteArray(inputStream); } catch (Exception e) { throw new IllegalArgumentException(e); From 9231e6d230a54037d0f03c246bb2dae2078e018c Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 17 Nov 2021 15:25:59 +0000 Subject: [PATCH 11/16] Add example of Spring WebClient usage (#418) - Add example of WebClient usage - Add additional test case with WebClient usage Signed-off-by: Dave Syer --- docs/spring.md | 12 + .../examples/spring/DemoApplication.java | 14 +- .../examples/spring/DemoApplicationTests.java | 226 ++++++++++-------- .../examples/spring/WebClientTests.java | 58 +++++ 4 files changed, 207 insertions(+), 103 deletions(-) create mode 100644 examples/spring-reactive/src/test/java/io/cloudevents/examples/spring/WebClientTests.java diff --git a/docs/spring.md b/docs/spring.md index f5bd87dd4..d3f9fdf6e 100644 --- a/docs/spring.md +++ b/docs/spring.md @@ -115,6 +115,18 @@ public Mono event(@RequestBody Mono body) { } ``` +The `CodecCustomizer` also works on the client side, so you can use it anywhere that you use a `WebClient` (including in an MVC application). Here's a simple example of a Cloud Event HTTP client: + +```java +WebClient client = ...; // Either WebClient.create() or @Autowired a WebClient.Builder +CloudEvent event = ...; // Create a CloudEvent +Mono response = client.post() + .uri("http://localhost:8080/events") + .bodyValue(event) + .retrieve() + .bodyToMono(CloudEvent.class); +``` + ### Messaging Spring Messaging is applicable in a wide range of use cases including WebSockets, JMS, Apache Kafka, RabbitMQ and others. It is also a core part of the Spring Cloud Function and Spring Cloud Stream libraries, so those are natural tools to use to build applications that use Cloud Events. The core abstraction in Spring is the `Message` which carries headers and a payload, just like a `CloudEvent`. Since the mapping is quite direct it makes sense to have a set of converters for Spring applications, so you can consume and produce `CloudEvents`, by treating them as `Messages`. This project provides a converter that you can register in a Spring Messaging application: diff --git a/examples/spring-function/src/main/java/io/cloudevents/examples/spring/DemoApplication.java b/examples/spring-function/src/main/java/io/cloudevents/examples/spring/DemoApplication.java index a646d177b..2c999774c 100644 --- a/examples/spring-function/src/main/java/io/cloudevents/examples/spring/DemoApplication.java +++ b/examples/spring-function/src/main/java/io/cloudevents/examples/spring/DemoApplication.java @@ -4,22 +4,20 @@ import java.util.UUID; import java.util.function.Function; -import io.cloudevents.CloudEvent; -import io.cloudevents.core.builder.CloudEventBuilder; -import io.cloudevents.spring.messaging.CloudEventMessageConverter; -import io.cloudevents.spring.webflux.CloudEventHttpMessageReader; -import io.cloudevents.spring.webflux.CloudEventHttpMessageWriter; - import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.codec.CodecCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.codec.CodecConfigurer; -import org.springframework.web.bind.annotation.RestController; + +import io.cloudevents.CloudEvent; +import io.cloudevents.core.builder.CloudEventBuilder; +import io.cloudevents.spring.messaging.CloudEventMessageConverter; +import io.cloudevents.spring.webflux.CloudEventHttpMessageReader; +import io.cloudevents.spring.webflux.CloudEventHttpMessageWriter; @SpringBootApplication -@RestController public class DemoApplication { public static void main(String[] args) throws Exception { diff --git a/examples/spring-reactive/src/test/java/io/cloudevents/examples/spring/DemoApplicationTests.java b/examples/spring-reactive/src/test/java/io/cloudevents/examples/spring/DemoApplicationTests.java index 94c465563..2e691671c 100644 --- a/examples/spring-reactive/src/test/java/io/cloudevents/examples/spring/DemoApplicationTests.java +++ b/examples/spring-reactive/src/test/java/io/cloudevents/examples/spring/DemoApplicationTests.java @@ -3,110 +3,146 @@ import java.net.URI; import org.junit.jupiter.api.Test; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.web.server.LocalServerPort; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; -import org.springframework.http.RequestEntity; -import org.springframework.http.ResponseEntity; +import org.springframework.test.web.reactive.server.WebTestClient; +import io.cloudevents.CloudEvent; +import io.cloudevents.core.builder.CloudEventBuilder; import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) public class DemoApplicationTests { - @Autowired - private TestRestTemplate rest; - - @LocalServerPort - private int port; - - @Test - void echoWithCorrectHeaders() { - - ResponseEntity response = rest - .exchange(RequestEntity.post(URI.create("http://localhost:" + port + "/foos")) // - .header("ce-id", "12345") // - .header("ce-specversion", "1.0") // - .header("ce-type", "io.spring.event") // - .header("ce-source", "https://spring.io/events") // - .contentType(MediaType.APPLICATION_JSON) // - .body("{\"value\":\"Dave\"}"), String.class); - - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(response.getBody()).isEqualTo("{\"value\":\"Dave\"}"); - - HttpHeaders headers = response.getHeaders(); - - assertThat(headers).containsKey("ce-id"); - assertThat(headers).containsKey("ce-source"); - assertThat(headers).containsKey("ce-type"); - - assertThat(headers.getFirst("ce-id")).isNotEqualTo("12345"); - assertThat(headers.getFirst("ce-type")).isEqualTo("io.spring.event.Foo"); - assertThat(headers.getFirst("ce-source")).isEqualTo("https://spring.io/foos"); - - } - - @Test - void structuredRequestResponseEvents() { - - ResponseEntity response = rest - .exchange(RequestEntity.post(URI.create("http://localhost:" + port + "/event")) // - .contentType(new MediaType("application", "cloudevents+json")) // - .body("{" // - + "\"id\":\"12345\"," // - + "\"specversion\":\"1.0\"," // - + "\"type\":\"io.spring.event\"," // - + "\"source\":\"https://spring.io/events\"," // - + "\"data\":{\"value\":\"Dave\"}}"), - String.class); - - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(response.getBody()).isEqualTo("{\"value\":\"Dave\"}"); - - HttpHeaders headers = response.getHeaders(); - - assertThat(headers).containsKey("ce-id"); - assertThat(headers).containsKey("ce-source"); - assertThat(headers).containsKey("ce-type"); - - assertThat(headers.getFirst("ce-id")).isNotEqualTo("12345"); - assertThat(headers.getFirst("ce-type")).isEqualTo("io.spring.event.Foo"); - assertThat(headers.getFirst("ce-source")).isEqualTo("https://spring.io/foos"); - - } - - @Test - void requestResponseEvents() { - - ResponseEntity response = rest - .exchange(RequestEntity.post(URI.create("http://localhost:" + port + "/event")) // - .header("ce-id", "12345") // - .header("ce-specversion", "1.0") // - .header("ce-type", "io.spring.event") // - .header("ce-source", "https://spring.io/events") // - .contentType(MediaType.APPLICATION_JSON) // - .body("{\"value\":\"Dave\"}"), String.class); - - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(response.getBody()).isEqualTo("{\"value\":\"Dave\"}"); - - HttpHeaders headers = response.getHeaders(); - - assertThat(headers).containsKey("ce-id"); - assertThat(headers).containsKey("ce-source"); - assertThat(headers).containsKey("ce-type"); - - assertThat(headers.getFirst("ce-id")).isNotEqualTo("12345"); - assertThat(headers.getFirst("ce-type")).isEqualTo("io.spring.event.Foo"); - assertThat(headers.getFirst("ce-source")).isEqualTo("https://spring.io/foos"); - - } + @Autowired + private WebTestClient rest; + + @Test + void echoWithCorrectHeaders() { + + rest.post().uri("/foos").header("ce-id", "12345") // + .header("ce-specversion", "1.0") // + .header("ce-type", "io.spring.event") // + .header("ce-source", "https://spring.io/events") // + .contentType(MediaType.APPLICATION_JSON) // + .bodyValue("{\"value\":\"Dave\"}") // + .exchange() // + .expectStatus().isOk() // + .expectHeader().exists("ce-id") // + .expectHeader().exists("ce-source") // + .expectHeader().exists("ce-type") // + .expectHeader().value("ce-id", value -> { + if (value.equals("12345")) + throw new IllegalStateException(); + }) // + .expectHeader().valueEquals("ce-type", "io.spring.event.Foo") // + .expectHeader().valueEquals("ce-source", "https://spring.io/foos") // + .expectBody(String.class).isEqualTo("{\"value\":\"Dave\"}"); + + } + + @Test + void structuredRequestResponseEvents() { + + rest.post().uri("/event") // + .contentType(new MediaType("application", "cloudevents+json")) // + .bodyValue("{" // + + "\"id\":\"12345\"," // + + "\"specversion\":\"1.0\"," // + + "\"type\":\"io.spring.event\"," // + + "\"source\":\"https://spring.io/events\"," // + + "\"data\":{\"value\":\"Dave\"}}") // + .exchange() // + .expectStatus().isOk() // + .expectHeader().exists("ce-id") // + .expectHeader().exists("ce-source") // + .expectHeader().exists("ce-type") // + .expectHeader().value("ce-id", value -> { + if (value.equals("12345")) + throw new IllegalStateException(); + }) // + .expectHeader().valueEquals("ce-type", "io.spring.event.Foo") // + .expectHeader().valueEquals("ce-source", "https://spring.io/foos") // + .expectBody(String.class).isEqualTo("{\"value\":\"Dave\"}"); + + } + + @Test + void structuredRequestResponseCloudEventToString() { + + rest.post().uri("/event") // + .bodyValue(CloudEventBuilder.v1() // + .withId("12345") // + .withType("io.spring.event") // + .withSource(URI.create("https://spring.io/events")).withData("{\"value\":\"Dave\"}".getBytes()) // + .build()) // + .exchange() // + .expectStatus().isOk() // + .expectHeader().exists("ce-id") // + .expectHeader().exists("ce-source") // + .expectHeader().exists("ce-type") // + .expectHeader().value("ce-id", value -> { + if (value.equals("12345")) + throw new IllegalStateException(); + }) // + .expectHeader().valueEquals("ce-type", "io.spring.event.Foo") // + .expectHeader().valueEquals("ce-source", "https://spring.io/foos") // + .expectBody(String.class).isEqualTo("{\"value\":\"Dave\"}"); + + } + + @Test + void structuredRequestResponseCloudEventToCloudEvent() { + + rest.post().uri("/event") // + .accept(new MediaType("application", "cloudevents+json")) // + .bodyValue(CloudEventBuilder.v1() // + .withId("12345") // + .withType("io.spring.event") // + .withSource(URI.create("https://spring.io/events")) // + .withData("{\"value\":\"Dave\"}".getBytes()) // + .build()) // + .exchange() // + .expectStatus().isOk() // + .expectHeader().exists("ce-id") // + .expectHeader().exists("ce-source") // + .expectHeader().exists("ce-type") // + .expectHeader().value("ce-id", value -> { + if (value.equals("12345")) + throw new IllegalStateException(); + }) // + .expectHeader().valueEquals("ce-type", "io.spring.event.Foo") // + .expectHeader().valueEquals("ce-source", "https://spring.io/foos") // + .expectBody(CloudEvent.class) // + .value(event -> assertThat(new String(event.getData().toBytes())) // + .isEqualTo("{\"value\":\"Dave\"}")); + + } + + @Test + void requestResponseEvents() { + + rest.post().uri("/event").header("ce-id", "12345") // + .header("ce-specversion", "1.0") // + .header("ce-type", "io.spring.event") // + .header("ce-source", "https://spring.io/events") // + .contentType(MediaType.APPLICATION_JSON) // + .bodyValue("{\"value\":\"Dave\"}") // + .exchange() // + .expectStatus().isOk() // + .expectHeader().exists("ce-id") // + .expectHeader().exists("ce-source") // + .expectHeader().exists("ce-type") // + .expectHeader().value("ce-id", value -> { + if (value.equals("12345")) + throw new IllegalStateException(); + }) // + .expectHeader().valueEquals("ce-type", "io.spring.event.Foo") // + .expectHeader().valueEquals("ce-source", "https://spring.io/foos") // + .expectBody(String.class).isEqualTo("{\"value\":\"Dave\"}"); + + } } diff --git a/examples/spring-reactive/src/test/java/io/cloudevents/examples/spring/WebClientTests.java b/examples/spring-reactive/src/test/java/io/cloudevents/examples/spring/WebClientTests.java new file mode 100644 index 000000000..590a4f975 --- /dev/null +++ b/examples/spring-reactive/src/test/java/io/cloudevents/examples/spring/WebClientTests.java @@ -0,0 +1,58 @@ +package io.cloudevents.examples.spring; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.net.URI; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.web.reactive.function.client.WebClient; + +import io.cloudevents.CloudEvent; +import io.cloudevents.core.builder.CloudEventBuilder; +import reactor.core.publisher.Mono; + +/** + * Test case to show example usage of WebClient and CloudEvent. The actual + * content of the request and response are asserted separately in + * {@link DemoApplicationTests}. + */ +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +public class WebClientTests { + + @Autowired + private WebClient.Builder rest; + + @LocalServerPort + private int port; + + private CloudEvent event; + + @BeforeEach + void setUp() { + event = CloudEventBuilder.v1() // + .withId("12345") // + .withSource(URI.create("https://spring.io/events")) // + .withType("io.spring.event") // + .withData("{\"value\":\"Dave\"}".getBytes()) // + .build(); + } + + @Test + void echoWithCorrectHeaders() { + + Mono result = rest.build() // + .post() // + .uri("http://localhost:" + port + "/event") // + .bodyValue(event) // + .exchangeToMono(response -> response.bodyToMono(CloudEvent.class)); + + assertThat(result.block().getData()).isEqualTo(event.getData()); + + } + +} From d00ad967c097390b46a22d4d032292923522d054 Mon Sep 17 00:00:00 2001 From: Pierangelo Di Pilato Date: Wed, 17 Nov 2021 16:55:27 +0100 Subject: [PATCH 12/16] Fix the Java Doc build (#424) - https://vertx.io/docs/apidocs/ returns 404, so removing it - Fix Java Doc error for missing `@param` Signed-off-by: Pierangelo Di Pilato --- api/src/main/java/io/cloudevents/rw/CloudEventReader.java | 5 +++++ pom.xml | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/api/src/main/java/io/cloudevents/rw/CloudEventReader.java b/api/src/main/java/io/cloudevents/rw/CloudEventReader.java index bcd008b16..d2af16941 100644 --- a/api/src/main/java/io/cloudevents/rw/CloudEventReader.java +++ b/api/src/main/java/io/cloudevents/rw/CloudEventReader.java @@ -32,7 +32,12 @@ public interface CloudEventReader { /** * Like {@link #read(CloudEventWriterFactory, CloudEventDataMapper)}, but with the identity {@link CloudEventDataMapper}. * + * @param The type of the {@link CloudEventWriter} created by writerFactory + * @param The return value of the {@link CloudEventWriter} created by writerFactory + * @param writerFactory a factory that generates a visitor starting from the SpecVersion of the event * @see #read(CloudEventWriterFactory, CloudEventDataMapper) + * @return the value returned by {@link CloudEventWriter#end()} or {@link CloudEventWriter#end(CloudEventData)} + * @throws CloudEventRWException if something went wrong during the read. */ default , R> R read(CloudEventWriterFactory writerFactory) throws CloudEventRWException { return read(writerFactory, CloudEventDataMapper.identity()); diff --git a/pom.xml b/pom.xml index a124a66aa..64be11026 100644 --- a/pom.xml +++ b/pom.xml @@ -163,7 +163,6 @@ https://docs.spring.io/spring-framework/docs/current/javadoc-api/ - https://vertx.io/docs/apidocs/ https://jakarta.ee/specifications/platform/8/apidocs/ https://kafka.apache.org/25/javadoc/ https://qpid.apache.org/releases/qpid-proton-j-0.33.7/api/ From 8d91cdaee6573f71c0863cd8f98e29a5664c2ca6 Mon Sep 17 00:00:00 2001 From: Pierangelo Di Pilato Date: Wed, 1 Dec 2021 09:05:02 +0100 Subject: [PATCH 13/16] Run tests with Java 17 (#426) Signed-off-by: Pierangelo Di Pilato --- .github/workflows/pr.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 9de9e5e04..57780b56f 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -11,14 +11,16 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [ 8, 11 ] + java: [ 8, 11, 17 ] name: Java ${{ matrix.java }} Test steps: - uses: actions/checkout@v2 - name: Setup java - uses: actions/setup-java@v1 + uses: actions/setup-java@v2 with: + cache: 'maven' java-version: ${{ matrix.java }} + distribution: 'temurin' - run: | mvn clean install -DskipTests -B mvn verify -B From ceb06757a3800b54b2bc1ec63d57df5c3fc8a9ed Mon Sep 17 00:00:00 2001 From: Myeonghyeon-Lee Date: Fri, 10 Dec 2021 18:26:47 +0900 Subject: [PATCH 14/16] Ignore invalid extension names in jackson CloudEventDeserializer (#429) Signed-off-by: mhyeon-lee --- .../jackson/CloudEventDeserializer.java | 59 ++++++++++- .../io/cloudevents/jackson/JsonFormat.java | 89 +++++++++++++++-- .../jackson/JsonFormatOptions.java | 99 +++++++++++++++++++ .../cloudevents/jackson/JsonFormatTest.java | 32 +++++- .../v03/json_data_with_ext_invalid.json | 15 +++ .../v03/json_data_with_ext_upper_case.json | 14 +++ .../v1/json_data_with_ext_invalid.json | 15 +++ .../v1/json_data_with_ext_upper_case.json | 14 +++ 8 files changed, 323 insertions(+), 14 deletions(-) create mode 100644 formats/json-jackson/src/main/java/io/cloudevents/jackson/JsonFormatOptions.java create mode 100644 formats/json-jackson/src/test/resources/v03/json_data_with_ext_invalid.json create mode 100644 formats/json-jackson/src/test/resources/v03/json_data_with_ext_upper_case.json create mode 100644 formats/json-jackson/src/test/resources/v1/json_data_with_ext_invalid.json create mode 100644 formats/json-jackson/src/test/resources/v1/json_data_with_ext_upper_case.json diff --git a/formats/json-jackson/src/main/java/io/cloudevents/jackson/CloudEventDeserializer.java b/formats/json-jackson/src/main/java/io/cloudevents/jackson/CloudEventDeserializer.java index 87d9a9196..1383d7cb1 100644 --- a/formats/json-jackson/src/main/java/io/cloudevents/jackson/CloudEventDeserializer.java +++ b/formats/json-jackson/src/main/java/io/cloudevents/jackson/CloudEventDeserializer.java @@ -38,19 +38,39 @@ * Jackson {@link com.fasterxml.jackson.databind.JsonDeserializer} for {@link CloudEvent} */ class CloudEventDeserializer extends StdDeserializer { + private final boolean forceExtensionNameLowerCaseDeserialization; + private final boolean forceIgnoreInvalidExtensionNameDeserialization; protected CloudEventDeserializer() { + this(false, false); + } + + protected CloudEventDeserializer( + boolean forceExtensionNameLowerCaseDeserialization, + boolean forceIgnoreInvalidExtensionNameDeserialization + ) { super(CloudEvent.class); + this.forceExtensionNameLowerCaseDeserialization = forceExtensionNameLowerCaseDeserialization; + this.forceIgnoreInvalidExtensionNameDeserialization = forceIgnoreInvalidExtensionNameDeserialization; } private static class JsonMessage implements CloudEventReader { private final JsonParser p; private final ObjectNode node; + private final boolean forceExtensionNameLowerCaseDeserialization; + private final boolean forceIgnoreInvalidExtensionNameDeserialization; - public JsonMessage(JsonParser p, ObjectNode node) { + public JsonMessage( + JsonParser p, + ObjectNode node, + boolean forceExtensionNameLowerCaseDeserialization, + boolean forceIgnoreInvalidExtensionNameDeserialization + ) { this.p = p; this.node = node; + this.forceExtensionNameLowerCaseDeserialization = forceExtensionNameLowerCaseDeserialization; + this.forceIgnoreInvalidExtensionNameDeserialization = forceIgnoreInvalidExtensionNameDeserialization; } @Override @@ -127,6 +147,14 @@ public , V> V read(CloudEventWriterFactory w // Now let's process the extensions node.fields().forEachRemaining(entry -> { String extensionName = entry.getKey(); + if (this.forceExtensionNameLowerCaseDeserialization) { + extensionName = extensionName.toLowerCase(); + } + + if (this.shouldSkipExtensionName(extensionName)) { + return; + } + JsonNode extensionValue = entry.getValue(); switch (extensionValue.getNodeType()) { @@ -192,6 +220,32 @@ private void assertNodeType(JsonNode node, JsonNodeType type, String attributeNa ); } } + + // ignore not valid extension name + private boolean shouldSkipExtensionName(String extensionName) { + return this.forceIgnoreInvalidExtensionNameDeserialization && !this.isValidExtensionName(extensionName); + } + + /** + * Validates the extension name as defined in CloudEvents spec. + * + * @param name the extension name + * @return true if extension name is valid, false otherwise + * @see attribute-naming-convention + */ + private boolean isValidExtensionName(String name) { + for (int i = 0; i < name.length(); i++) { + if (!isValidChar(name.charAt(i))) { + return false; + } + } + return true; + } + + private boolean isValidChar(char c) { + return (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'); + } + } @Override @@ -201,7 +255,8 @@ public CloudEvent deserialize(JsonParser p, DeserializationContext ctxt) throws ObjectNode node = ctxt.readValue(p, ObjectNode.class); try { - return new JsonMessage(p, node).read(CloudEventBuilder::fromSpecVersion); + return new JsonMessage(p, node, this.forceExtensionNameLowerCaseDeserialization, this.forceIgnoreInvalidExtensionNameDeserialization) + .read(CloudEventBuilder::fromSpecVersion); } catch (RuntimeException e) { // Yeah this is bad but it's needed to support checked exceptions... if (e.getCause() instanceof IOException) { diff --git a/formats/json-jackson/src/main/java/io/cloudevents/jackson/JsonFormat.java b/formats/json-jackson/src/main/java/io/cloudevents/jackson/JsonFormat.java index a374b6c1e..49467980b 100644 --- a/formats/json-jackson/src/main/java/io/cloudevents/jackson/JsonFormat.java +++ b/formats/json-jackson/src/main/java/io/cloudevents/jackson/JsonFormat.java @@ -45,8 +45,7 @@ public final class JsonFormat implements EventFormat { public static final String CONTENT_TYPE = "application/cloudevents+json"; private final ObjectMapper mapper; - private final boolean forceDataBase64Serialization; - private final boolean forceStringSerialization; + private final JsonFormatOptions options; /** * Create a new instance of this class customizing the serialization configuration. @@ -57,31 +56,86 @@ public final class JsonFormat implements EventFormat { * @see #withForceNonJsonDataToString() */ public JsonFormat(boolean forceDataBase64Serialization, boolean forceStringSerialization) { + this( + JsonFormatOptions.builder() + .forceDataBase64Serialization(forceDataBase64Serialization) + .forceStringSerialization(forceStringSerialization) + .build() + ); + } + + /** + * Create a new instance of this class customizing the serialization configuration. + * + * @param options json serialization / deserialization options + */ + public JsonFormat(JsonFormatOptions options) { this.mapper = new ObjectMapper(); - this.mapper.registerModule(getCloudEventJacksonModule(forceDataBase64Serialization, forceStringSerialization)); - this.forceDataBase64Serialization = forceDataBase64Serialization; - this.forceStringSerialization = forceStringSerialization; + this.mapper.registerModule(getCloudEventJacksonModule(options)); + this.options = options; } /** * Create a new instance of this class with default serialization configuration */ public JsonFormat() { - this(false, false); + this(new JsonFormatOptions()); } /** * @return a copy of this JsonFormat that serialize events with json data with Base64 encoding */ public JsonFormat withForceJsonDataToBase64() { - return new JsonFormat(true, this.forceStringSerialization); + return new JsonFormat( + JsonFormatOptions.builder() + .forceDataBase64Serialization(true) + .forceStringSerialization(this.options.isForceStringSerialization()) + .forceExtensionNameLowerCaseDeserialization(this.options.isForceExtensionNameLowerCaseDeserialization()) + .forceIgnoreInvalidExtensionNameDeserialization(this.options.isForceIgnoreInvalidExtensionNameDeserialization()) + .build() + ); } /** * @return a copy of this JsonFormat that serialize events with non-json data as string */ public JsonFormat withForceNonJsonDataToString() { - return new JsonFormat(this.forceDataBase64Serialization, true); + return new JsonFormat( + JsonFormatOptions.builder() + .forceDataBase64Serialization(this.options.isForceDataBase64Serialization()) + .forceStringSerialization(true) + .forceExtensionNameLowerCaseDeserialization(this.options.isForceExtensionNameLowerCaseDeserialization()) + .forceIgnoreInvalidExtensionNameDeserialization(this.options.isForceIgnoreInvalidExtensionNameDeserialization()) + .build() + ); + } + + /** + * @return a copy of this JsonFormat that deserialize events with converting extension name lower case. + */ + public JsonFormat withForceExtensionNameLowerCaseDeserialization() { + return new JsonFormat( + JsonFormatOptions.builder() + .forceDataBase64Serialization(this.options.isForceDataBase64Serialization()) + .forceStringSerialization(this.options.isForceStringSerialization()) + .forceExtensionNameLowerCaseDeserialization(true) + .forceIgnoreInvalidExtensionNameDeserialization(this.options.isForceIgnoreInvalidExtensionNameDeserialization()) + .build() + ); + } + + /** + * @return a copy of this JsonFormat that deserialize events with ignoring invalid extension name + */ + public JsonFormat withForceIgnoreInvalidExtensionNameDeserialization() { + return new JsonFormat( + JsonFormatOptions.builder() + .forceDataBase64Serialization(this.options.isForceDataBase64Serialization()) + .forceStringSerialization(this.options.isForceStringSerialization()) + .forceExtensionNameLowerCaseDeserialization(this.options.isForceExtensionNameLowerCaseDeserialization()) + .forceIgnoreInvalidExtensionNameDeserialization(true) + .build() + ); } @Override @@ -137,9 +191,24 @@ public static SimpleModule getCloudEventJacksonModule() { * @see #withForceNonJsonDataToString() */ public static SimpleModule getCloudEventJacksonModule(boolean forceDataBase64Serialization, boolean forceStringSerialization) { + return getCloudEventJacksonModule( + JsonFormatOptions.builder() + .forceDataBase64Serialization(forceDataBase64Serialization) + .forceStringSerialization(forceStringSerialization) + .build() + ); + } + + /** + * @param options json serialization / deserialization options + * @return a JacksonModule with CloudEvent serializer/deserializer customizing the data serialization. + */ + public static SimpleModule getCloudEventJacksonModule(JsonFormatOptions options) { final SimpleModule ceModule = new SimpleModule("CloudEvent"); - ceModule.addSerializer(CloudEvent.class, new CloudEventSerializer(forceDataBase64Serialization, forceStringSerialization)); - ceModule.addDeserializer(CloudEvent.class, new CloudEventDeserializer()); + ceModule.addSerializer(CloudEvent.class, new CloudEventSerializer( + options.isForceDataBase64Serialization(), options.isForceStringSerialization())); + ceModule.addDeserializer(CloudEvent.class, new CloudEventDeserializer( + options.isForceExtensionNameLowerCaseDeserialization(), options.isForceIgnoreInvalidExtensionNameDeserialization())); return ceModule; } diff --git a/formats/json-jackson/src/main/java/io/cloudevents/jackson/JsonFormatOptions.java b/formats/json-jackson/src/main/java/io/cloudevents/jackson/JsonFormatOptions.java new file mode 100644 index 000000000..bf18ebf31 --- /dev/null +++ b/formats/json-jackson/src/main/java/io/cloudevents/jackson/JsonFormatOptions.java @@ -0,0 +1,99 @@ +/* + * Copyright 2018-Present The CloudEvents Authors + *

+ * 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 io.cloudevents.jackson; + +public final class JsonFormatOptions { + private final boolean forceDataBase64Serialization; + private final boolean forceStringSerialization; + private final boolean forceExtensionNameLowerCaseDeserialization; + private final boolean forceIgnoreInvalidExtensionNameDeserialization; + + /** + * Create a new instance of this class options the serialization / deserialization. + */ + public JsonFormatOptions() { + this(false, false, false, false); + } + + JsonFormatOptions( + boolean forceDataBase64Serialization, + boolean forceStringSerialization, + boolean forceExtensionNameLowerCaseDeserialization, + boolean forceIgnoreInvalidExtensionNameDeserialization + ) { + this.forceDataBase64Serialization = forceDataBase64Serialization; + this.forceStringSerialization = forceStringSerialization; + this.forceExtensionNameLowerCaseDeserialization = forceExtensionNameLowerCaseDeserialization; + this.forceIgnoreInvalidExtensionNameDeserialization = forceIgnoreInvalidExtensionNameDeserialization; + } + + public static JsonFormatOptionsBuilder builder() { + return new JsonFormatOptionsBuilder(); + } + + public boolean isForceDataBase64Serialization() { + return this.forceDataBase64Serialization; + } + + public boolean isForceStringSerialization() { + return this.forceStringSerialization; + } + + public boolean isForceExtensionNameLowerCaseDeserialization() { + return this.forceExtensionNameLowerCaseDeserialization; + } + + public boolean isForceIgnoreInvalidExtensionNameDeserialization() { + return this.forceIgnoreInvalidExtensionNameDeserialization; + } + + public static class JsonFormatOptionsBuilder { + private boolean forceDataBase64Serialization = false; + private boolean forceStringSerialization = false; + private boolean forceExtensionNameLowerCaseDeserialization = false; + private boolean forceIgnoreInvalidExtensionNameDeserialization = false; + + public JsonFormatOptionsBuilder forceDataBase64Serialization(boolean forceDataBase64Serialization) { + this.forceDataBase64Serialization = forceDataBase64Serialization; + return this; + } + + public JsonFormatOptionsBuilder forceStringSerialization(boolean forceStringSerialization) { + this.forceStringSerialization = forceStringSerialization; + return this; + } + + public JsonFormatOptionsBuilder forceExtensionNameLowerCaseDeserialization(boolean forceExtensionNameLowerCaseDeserialization) { + this.forceExtensionNameLowerCaseDeserialization = forceExtensionNameLowerCaseDeserialization; + return this; + } + + public JsonFormatOptionsBuilder forceIgnoreInvalidExtensionNameDeserialization(boolean forceIgnoreInvalidExtensionNameDeserialization) { + this.forceIgnoreInvalidExtensionNameDeserialization = forceIgnoreInvalidExtensionNameDeserialization; + return this; + } + + public JsonFormatOptions build() { + return new JsonFormatOptions( + this.forceDataBase64Serialization, + this.forceStringSerialization, + this.forceExtensionNameLowerCaseDeserialization, + this.forceIgnoreInvalidExtensionNameDeserialization + ); + } + } +} diff --git a/formats/json-jackson/src/test/java/io/cloudevents/jackson/JsonFormatTest.java b/formats/json-jackson/src/test/java/io/cloudevents/jackson/JsonFormatTest.java index de99403de..318cffcc5 100644 --- a/formats/json-jackson/src/test/java/io/cloudevents/jackson/JsonFormatTest.java +++ b/formats/json-jackson/src/test/java/io/cloudevents/jackson/JsonFormatTest.java @@ -27,14 +27,12 @@ import io.cloudevents.core.format.EventDeserializationException; import io.cloudevents.core.provider.EventFormatProvider; import io.cloudevents.rw.CloudEventRWException; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import java.io.IOException; -import java.math.BigInteger; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -90,6 +88,22 @@ void deserialize(String inputFile, CloudEvent output) { .isEqualTo(output); } + @ParameterizedTest + @MethodSource("deserializeTestArgumentsUpperCaseExtensionName") + void deserializeWithUpperCaseExtensionName(String inputFile, CloudEvent output) { + CloudEvent deserialized = getFormat().withForceExtensionNameLowerCaseDeserialization().deserialize(loadFile(inputFile)); + assertThat(deserialized) + .isEqualTo(output); + } + + @ParameterizedTest + @MethodSource("deserializeTestArgumentsInvalidExtensionName") + void deserializeWithInvalidExtensionName(String inputFile, CloudEvent output) { + CloudEvent deserialized = getFormat().withForceIgnoreInvalidExtensionNameDeserialization().deserialize(loadFile(inputFile)); + assertThat(deserialized) + .isEqualTo(output); + } + @ParameterizedTest @MethodSource("roundTripTestArguments") void jsonRoundTrip(String inputFile) throws IOException { @@ -204,6 +218,20 @@ public static Stream deserializeTestArguments() { ); } + public static Stream deserializeTestArgumentsUpperCaseExtensionName() { + return Stream.of( + Arguments.of("v03/json_data_with_ext_upper_case.json", normalizeToJsonValueIfNeeded(V03_WITH_JSON_DATA_WITH_EXT)), + Arguments.of("v1/json_data_with_ext_upper_case.json", normalizeToJsonValueIfNeeded(V1_WITH_JSON_DATA_WITH_EXT)) + ); + } + + public static Stream deserializeTestArgumentsInvalidExtensionName() { + return Stream.of( + Arguments.of("v03/json_data_with_ext_invalid.json", normalizeToJsonValueIfNeeded(V03_WITH_JSON_DATA_WITH_EXT)), + Arguments.of("v1/json_data_with_ext_invalid.json", normalizeToJsonValueIfNeeded(V1_WITH_JSON_DATA_WITH_EXT)) + ); + } + public static Stream roundTripTestArguments() { return Stream.of( "v03/min.json", diff --git a/formats/json-jackson/src/test/resources/v03/json_data_with_ext_invalid.json b/formats/json-jackson/src/test/resources/v03/json_data_with_ext_invalid.json new file mode 100644 index 000000000..a55bfae32 --- /dev/null +++ b/formats/json-jackson/src/test/resources/v03/json_data_with_ext_invalid.json @@ -0,0 +1,15 @@ +{ + "specversion": "0.3", + "id": "1", + "type": "mock.test", + "source": "http://localhost/source", + "schemaurl": "http://localhost/schema", + "datacontenttype": "application/json", + "data": {}, + "subject": "sub", + "time": "2018-04-26T14:48:09+02:00", + "astring": "aaa", + "aboolean": true, + "anumber": 10, + "a_invalid_name": "invalidName" +} diff --git a/formats/json-jackson/src/test/resources/v03/json_data_with_ext_upper_case.json b/formats/json-jackson/src/test/resources/v03/json_data_with_ext_upper_case.json new file mode 100644 index 000000000..1cf194184 --- /dev/null +++ b/formats/json-jackson/src/test/resources/v03/json_data_with_ext_upper_case.json @@ -0,0 +1,14 @@ +{ + "specversion": "0.3", + "id": "1", + "type": "mock.test", + "source": "http://localhost/source", + "schemaurl": "http://localhost/schema", + "datacontenttype": "application/json", + "data": {}, + "subject": "sub", + "time": "2018-04-26T14:48:09+02:00", + "aString": "aaa", + "aBoolean": true, + "aNumber": 10 +} diff --git a/formats/json-jackson/src/test/resources/v1/json_data_with_ext_invalid.json b/formats/json-jackson/src/test/resources/v1/json_data_with_ext_invalid.json new file mode 100644 index 000000000..4eda33f05 --- /dev/null +++ b/formats/json-jackson/src/test/resources/v1/json_data_with_ext_invalid.json @@ -0,0 +1,15 @@ +{ + "specversion": "1.0", + "id": "1", + "type": "mock.test", + "source": "http://localhost/source", + "dataschema": "http://localhost/schema", + "datacontenttype": "application/json", + "data": {}, + "subject": "sub", + "time": "2018-04-26T14:48:09+02:00", + "astring": "aaa", + "aboolean": true, + "anumber": 10, + "a_invalid_name": "invalidName" +} diff --git a/formats/json-jackson/src/test/resources/v1/json_data_with_ext_upper_case.json b/formats/json-jackson/src/test/resources/v1/json_data_with_ext_upper_case.json new file mode 100644 index 000000000..3bcc44817 --- /dev/null +++ b/formats/json-jackson/src/test/resources/v1/json_data_with_ext_upper_case.json @@ -0,0 +1,14 @@ +{ + "specversion": "1.0", + "id": "1", + "type": "mock.test", + "source": "http://localhost/source", + "dataschema": "http://localhost/schema", + "datacontenttype": "application/json", + "data": {}, + "subject": "sub", + "time": "2018-04-26T14:48:09+02:00", + "aString": "aaa", + "aBoolean": true, + "aNumber": 10 +} From cc786251d5a24e22436a17cc2c244baea23dfa78 Mon Sep 17 00:00:00 2001 From: Pierangelo Di Pilato Date: Tue, 21 Dec 2021 11:22:02 +0100 Subject: [PATCH 15/16] Handle NullNode for optional attributes in Jackson CloudEventDeserializer (#432) In `getOptionalStringNode` we should handle `JsonNode`s that are instances of `NullNode`. Signed-off-by: Pierangelo Di Pilato --- .../io/cloudevents/jackson/CloudEventDeserializer.java | 9 +++++---- .../test/java/io/cloudevents/jackson/JsonFormatTest.java | 4 +++- .../src/test/resources/v03/min_subject_null.json | 7 +++++++ .../src/test/resources/v1/min_subject_null.json | 7 +++++++ 4 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 formats/json-jackson/src/test/resources/v03/min_subject_null.json create mode 100644 formats/json-jackson/src/test/resources/v1/min_subject_null.json diff --git a/formats/json-jackson/src/main/java/io/cloudevents/jackson/CloudEventDeserializer.java b/formats/json-jackson/src/main/java/io/cloudevents/jackson/CloudEventDeserializer.java index 1383d7cb1..d301a73bd 100644 --- a/formats/json-jackson/src/main/java/io/cloudevents/jackson/CloudEventDeserializer.java +++ b/formats/json-jackson/src/main/java/io/cloudevents/jackson/CloudEventDeserializer.java @@ -24,6 +24,7 @@ import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.exc.MismatchedInputException; import com.fasterxml.jackson.databind.node.JsonNodeType; +import com.fasterxml.jackson.databind.node.NullNode; import com.fasterxml.jackson.databind.node.ObjectNode; import io.cloudevents.CloudEvent; import io.cloudevents.CloudEventData; @@ -203,12 +204,12 @@ private String getStringNode(ObjectNode objNode, JsonParser p, String attributeN } private String getOptionalStringNode(ObjectNode objNode, JsonParser p, String attributeName) throws JsonProcessingException { - JsonNode unparsedSpecVersion = objNode.remove(attributeName); - if (unparsedSpecVersion == null) { + JsonNode unparsedAttribute = objNode.remove(attributeName); + if (unparsedAttribute == null || unparsedAttribute instanceof NullNode) { return null; } - assertNodeType(unparsedSpecVersion, JsonNodeType.STRING, attributeName, null); - return unparsedSpecVersion.asText(); + assertNodeType(unparsedAttribute, JsonNodeType.STRING, attributeName, null); + return unparsedAttribute.asText(); } private void assertNodeType(JsonNode node, JsonNodeType type, String attributeName, String desc) throws JsonProcessingException { diff --git a/formats/json-jackson/src/test/java/io/cloudevents/jackson/JsonFormatTest.java b/formats/json-jackson/src/test/java/io/cloudevents/jackson/JsonFormatTest.java index 318cffcc5..7e40fe98e 100644 --- a/formats/json-jackson/src/test/java/io/cloudevents/jackson/JsonFormatTest.java +++ b/formats/json-jackson/src/test/java/io/cloudevents/jackson/JsonFormatTest.java @@ -45,7 +45,7 @@ class JsonFormatTest { - private ObjectMapper mapper = new ObjectMapper(); + private final ObjectMapper mapper = new ObjectMapper(); @ParameterizedTest @MethodSource("serializeTestArgumentsDefault") @@ -198,6 +198,7 @@ public static Stream serializeTestArgumentsBase64() { public static Stream deserializeTestArguments() { return Stream.of( Arguments.of("v03/min.json", V03_MIN), + Arguments.of("v03/min_subject_null.json", V03_MIN), Arguments.of("v03/json_data.json", normalizeToJsonValueIfNeeded(V03_WITH_JSON_DATA)), Arguments.of("v03/json_data_with_ext.json", normalizeToJsonValueIfNeeded(V03_WITH_JSON_DATA_WITH_EXT)), Arguments.of("v03/base64_json_data.json", V03_WITH_JSON_DATA), @@ -207,6 +208,7 @@ public static Stream deserializeTestArguments() { Arguments.of("v03/text_data.json", V03_WITH_TEXT_DATA), Arguments.of("v03/base64_text_data.json", V03_WITH_TEXT_DATA), Arguments.of("v1/min.json", V1_MIN), + Arguments.of("v1/min_subject_null.json", V1_MIN), Arguments.of("v1/json_data.json", normalizeToJsonValueIfNeeded(V1_WITH_JSON_DATA)), Arguments.of("v1/json_data_with_ext.json", normalizeToJsonValueIfNeeded(V1_WITH_JSON_DATA_WITH_EXT)), Arguments.of("v1/base64_json_data.json", V1_WITH_JSON_DATA), diff --git a/formats/json-jackson/src/test/resources/v03/min_subject_null.json b/formats/json-jackson/src/test/resources/v03/min_subject_null.json new file mode 100644 index 000000000..ff7a923e0 --- /dev/null +++ b/formats/json-jackson/src/test/resources/v03/min_subject_null.json @@ -0,0 +1,7 @@ +{ + "specversion": "0.3", + "id": "1", + "type": "mock.test", + "source": "http://localhost/source", + "subject": null +} diff --git a/formats/json-jackson/src/test/resources/v1/min_subject_null.json b/formats/json-jackson/src/test/resources/v1/min_subject_null.json new file mode 100644 index 000000000..836aac090 --- /dev/null +++ b/formats/json-jackson/src/test/resources/v1/min_subject_null.json @@ -0,0 +1,7 @@ +{ + "specversion": "1.0", + "id": "1", + "type": "mock.test", + "source": "http://localhost/source", + "subject": null +} From ace6859ae00ed3669efde3088d75bcadc0d61baf Mon Sep 17 00:00:00 2001 From: Pierangelo Di Pilato Date: Tue, 21 Dec 2021 12:06:57 +0100 Subject: [PATCH 16/16] Bump version to 2.3.0 (#437) Signed-off-by: Pierangelo Di Pilato --- amqp/pom.xml | 2 +- api/pom.xml | 2 +- benchmarks/pom.xml | 2 +- bom/pom.xml | 2 +- core/pom.xml | 2 +- docs/amqp-proton.md | 2 +- docs/api.md | 2 +- docs/core.md | 2 +- docs/http-basic.md | 2 +- docs/http-jakarta-restful-ws.md | 2 +- docs/http-vertx.md | 2 +- docs/json-jackson.md | 2 +- docs/kafka.md | 2 +- docs/protobuf.md | 2 +- docs/spring.md | 2 +- examples/amqp-proton/pom.xml | 2 +- examples/basic-http/pom.xml | 2 +- examples/kafka/pom.xml | 2 +- examples/pom.xml | 2 +- examples/restful-ws-quarkus/pom.xml | 2 +- examples/restful-ws-spring-boot/pom.xml | 2 +- examples/spring-function/pom.xml | 2 +- examples/spring-reactive/pom.xml | 2 +- examples/spring-rsocket/pom.xml | 2 +- examples/vertx/pom.xml | 2 +- formats/json-jackson/pom.xml | 2 +- formats/protobuf/pom.xml | 2 +- http/basic/pom.xml | 2 +- http/restful-ws-integration-tests/pom.xml | 2 +- http/restful-ws-integration-tests/restful-ws-common/pom.xml | 2 +- http/restful-ws-integration-tests/restful-ws-jersey/pom.xml | 2 +- http/restful-ws-integration-tests/restful-ws-resteasy/pom.xml | 2 +- http/restful-ws-integration-tests/restful-ws-spring/pom.xml | 2 +- http/restful-ws/pom.xml | 2 +- http/vertx/pom.xml | 2 +- kafka/pom.xml | 2 +- pom.xml | 2 +- spring/pom.xml | 2 +- sql/pom.xml | 2 +- 39 files changed, 39 insertions(+), 39 deletions(-) diff --git a/amqp/pom.xml b/amqp/pom.xml index a8612a432..5c6ec0ea2 100644 --- a/amqp/pom.xml +++ b/amqp/pom.xml @@ -6,7 +6,7 @@ io.cloudevents cloudevents-parent - 2.3.0-SNAPSHOT + 2.3.0 cloudevents-amqp-proton diff --git a/api/pom.xml b/api/pom.xml index 31e3d23f1..39b2ffc4b 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -24,7 +24,7 @@ io.cloudevents cloudevents-parent - 2.3.0-SNAPSHOT + 2.3.0 cloudevents-api diff --git a/benchmarks/pom.xml b/benchmarks/pom.xml index a2d5c34a9..24097aebc 100644 --- a/benchmarks/pom.xml +++ b/benchmarks/pom.xml @@ -21,7 +21,7 @@ io.cloudevents cloudevents-parent - 2.3.0-SNAPSHOT + 2.3.0 cloudevents-benchmarks diff --git a/bom/pom.xml b/bom/pom.xml index 733abc572..f80af9329 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -22,7 +22,7 @@ io.cloudevents cloudevents-parent - 2.3.0-SNAPSHOT + 2.3.0 cloudevents-bom diff --git a/core/pom.xml b/core/pom.xml index 9c85d91d6..b1b4cf934 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -22,7 +22,7 @@ io.cloudevents cloudevents-parent - 2.3.0-SNAPSHOT + 2.3.0 cloudevents-core diff --git a/docs/amqp-proton.md b/docs/amqp-proton.md index 25c083b64..f6a456c04 100644 --- a/docs/amqp-proton.md +++ b/docs/amqp-proton.md @@ -18,7 +18,7 @@ binding for CloudEvents: io.cloudevents cloudevents-amqp-proton - 2.2.0 + 2.3.0 ``` diff --git a/docs/api.md b/docs/api.md index 1bb9f3d05..1de08596f 100644 --- a/docs/api.md +++ b/docs/api.md @@ -17,7 +17,7 @@ For Maven based projects, use the following dependency: io.cloudevents cloudevents-api - 2.2.0 + 2.3.0 ``` diff --git a/docs/core.md b/docs/core.md index cb8d857e9..fcafac13d 100644 --- a/docs/core.md +++ b/docs/core.md @@ -16,7 +16,7 @@ For Maven based projects, use the following dependency: io.cloudevents cloudevents-core - 2.2.0 + 2.3.0 ``` diff --git a/docs/http-basic.md b/docs/http-basic.md index 51ed1e97a..f2cb67aa2 100644 --- a/docs/http-basic.md +++ b/docs/http-basic.md @@ -27,7 +27,7 @@ HTTP Transport: io.cloudevents cloudevents-http-basic - 2.2.0 + 2.3.0 ``` diff --git a/docs/http-jakarta-restful-ws.md b/docs/http-jakarta-restful-ws.md index 59ca74205..a7f08fefb 100644 --- a/docs/http-jakarta-restful-ws.md +++ b/docs/http-jakarta-restful-ws.md @@ -14,7 +14,7 @@ RESTful Web Services Binding: io.cloudevents cloudevents-http-restful-ws - 2.2.0 + 2.3.0 ``` diff --git a/docs/http-vertx.md b/docs/http-vertx.md index da603f030..bdecc9a79 100644 --- a/docs/http-vertx.md +++ b/docs/http-vertx.md @@ -14,7 +14,7 @@ HTTP Transport: io.cloudevents cloudevents-http-vertx - 2.2.0 + 2.3.0 ``` diff --git a/docs/json-jackson.md b/docs/json-jackson.md index 0b62d3199..6bb2a7c6a 100644 --- a/docs/json-jackson.md +++ b/docs/json-jackson.md @@ -17,7 +17,7 @@ For Maven based projects, use the following dependency: io.cloudevents cloudevents-json-jackson - 2.2.0 + 2.3.0 ``` diff --git a/docs/kafka.md b/docs/kafka.md index 449ef0af3..bcdeb80ae 100644 --- a/docs/kafka.md +++ b/docs/kafka.md @@ -17,7 +17,7 @@ For Maven based projects, use the following to configure the io.cloudevents cloudevents-kafka - 2.2.0 + 2.3.0 ``` diff --git a/docs/protobuf.md b/docs/protobuf.md index 731a2d0e3..64d7c4318 100644 --- a/docs/protobuf.md +++ b/docs/protobuf.md @@ -17,7 +17,7 @@ For Maven based projects, use the following dependency: io.cloudevents cloudevents-protobuf - 2.2.0 + 2.3.0 ``` diff --git a/docs/spring.md b/docs/spring.md index d3f9fdf6e..b9dab8ed4 100644 --- a/docs/spring.md +++ b/docs/spring.md @@ -17,7 +17,7 @@ For Maven based projects, use the following dependency: io.cloudevents cloudevents-spring - 2.2.0 + 2.3.0 ``` diff --git a/examples/amqp-proton/pom.xml b/examples/amqp-proton/pom.xml index 2a28a9fd7..ed74fed44 100644 --- a/examples/amqp-proton/pom.xml +++ b/examples/amqp-proton/pom.xml @@ -3,7 +3,7 @@ cloudevents-examples io.cloudevents - 2.3.0-SNAPSHOT + 2.3.0 4.0.0 diff --git a/examples/basic-http/pom.xml b/examples/basic-http/pom.xml index 8a3b84c44..9c1642f61 100644 --- a/examples/basic-http/pom.xml +++ b/examples/basic-http/pom.xml @@ -21,7 +21,7 @@ cloudevents-examples io.cloudevents - 2.3.0-SNAPSHOT + 2.3.0 4.0.0 diff --git a/examples/kafka/pom.xml b/examples/kafka/pom.xml index 33a03dc7a..5a4bc51d4 100644 --- a/examples/kafka/pom.xml +++ b/examples/kafka/pom.xml @@ -5,7 +5,7 @@ cloudevents-examples io.cloudevents - 2.3.0-SNAPSHOT + 2.3.0 4.0.0 diff --git a/examples/pom.xml b/examples/pom.xml index 7b6299be3..c6ad569e7 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ cloudevents-parent io.cloudevents - 2.3.0-SNAPSHOT + 2.3.0 4.0.0 diff --git a/examples/restful-ws-quarkus/pom.xml b/examples/restful-ws-quarkus/pom.xml index 4ca4f834f..e27ea3e69 100644 --- a/examples/restful-ws-quarkus/pom.xml +++ b/examples/restful-ws-quarkus/pom.xml @@ -5,7 +5,7 @@ cloudevents-examples io.cloudevents - 2.3.0-SNAPSHOT + 2.3.0 4.0.0 cloudevents-restful-ws-quarkus-example diff --git a/examples/restful-ws-spring-boot/pom.xml b/examples/restful-ws-spring-boot/pom.xml index e282d896e..3740731bb 100644 --- a/examples/restful-ws-spring-boot/pom.xml +++ b/examples/restful-ws-spring-boot/pom.xml @@ -5,7 +5,7 @@ cloudevents-examples io.cloudevents - 2.3.0-SNAPSHOT + 2.3.0 4.0.0 diff --git a/examples/spring-function/pom.xml b/examples/spring-function/pom.xml index fdb8a3b21..035b53072 100644 --- a/examples/spring-function/pom.xml +++ b/examples/spring-function/pom.xml @@ -5,7 +5,7 @@ cloudevents-examples io.cloudevents - 2.3.0-SNAPSHOT + 2.3.0 4.0.0 diff --git a/examples/spring-reactive/pom.xml b/examples/spring-reactive/pom.xml index 25c2f0039..203e9477e 100644 --- a/examples/spring-reactive/pom.xml +++ b/examples/spring-reactive/pom.xml @@ -5,7 +5,7 @@ cloudevents-examples io.cloudevents - 2.3.0-SNAPSHOT + 2.3.0 4.0.0 diff --git a/examples/spring-rsocket/pom.xml b/examples/spring-rsocket/pom.xml index cd29b734f..00b34086e 100644 --- a/examples/spring-rsocket/pom.xml +++ b/examples/spring-rsocket/pom.xml @@ -5,7 +5,7 @@ cloudevents-examples io.cloudevents - 2.3.0-SNAPSHOT + 2.3.0 4.0.0 diff --git a/examples/vertx/pom.xml b/examples/vertx/pom.xml index 94b622f11..5fcc571e7 100644 --- a/examples/vertx/pom.xml +++ b/examples/vertx/pom.xml @@ -5,7 +5,7 @@ cloudevents-examples io.cloudevents - 2.3.0-SNAPSHOT + 2.3.0 4.0.0 diff --git a/formats/json-jackson/pom.xml b/formats/json-jackson/pom.xml index b769aa11d..44921256c 100644 --- a/formats/json-jackson/pom.xml +++ b/formats/json-jackson/pom.xml @@ -22,7 +22,7 @@ io.cloudevents cloudevents-parent - 2.3.0-SNAPSHOT + 2.3.0 ../../pom.xml diff --git a/formats/protobuf/pom.xml b/formats/protobuf/pom.xml index 5a490d61f..0d0a2160a 100644 --- a/formats/protobuf/pom.xml +++ b/formats/protobuf/pom.xml @@ -23,7 +23,7 @@ io.cloudevents cloudevents-parent - 2.3.0-SNAPSHOT + 2.3.0 ../../pom.xml diff --git a/http/basic/pom.xml b/http/basic/pom.xml index fd46a9adf..8b6042eec 100644 --- a/http/basic/pom.xml +++ b/http/basic/pom.xml @@ -21,7 +21,7 @@ io.cloudevents cloudevents-parent - 2.3.0-SNAPSHOT + 2.3.0 ../../pom.xml diff --git a/http/restful-ws-integration-tests/pom.xml b/http/restful-ws-integration-tests/pom.xml index 4a81ba815..1f4e911d9 100644 --- a/http/restful-ws-integration-tests/pom.xml +++ b/http/restful-ws-integration-tests/pom.xml @@ -22,7 +22,7 @@ cloudevents-parent io.cloudevents - 2.3.0-SNAPSHOT + 2.3.0 ../../pom.xml 4.0.0 diff --git a/http/restful-ws-integration-tests/restful-ws-common/pom.xml b/http/restful-ws-integration-tests/restful-ws-common/pom.xml index 7e691a914..16b3d0cfd 100644 --- a/http/restful-ws-integration-tests/restful-ws-common/pom.xml +++ b/http/restful-ws-integration-tests/restful-ws-common/pom.xml @@ -22,7 +22,7 @@ cloudevents-http-restful-ws-integration-tests io.cloudevents - 2.3.0-SNAPSHOT + 2.3.0 ../ 4.0.0 diff --git a/http/restful-ws-integration-tests/restful-ws-jersey/pom.xml b/http/restful-ws-integration-tests/restful-ws-jersey/pom.xml index a22edf54e..f6499ef52 100644 --- a/http/restful-ws-integration-tests/restful-ws-jersey/pom.xml +++ b/http/restful-ws-integration-tests/restful-ws-jersey/pom.xml @@ -22,7 +22,7 @@ cloudevents-http-restful-ws-integration-tests io.cloudevents - 2.3.0-SNAPSHOT + 2.3.0 ../ 4.0.0 diff --git a/http/restful-ws-integration-tests/restful-ws-resteasy/pom.xml b/http/restful-ws-integration-tests/restful-ws-resteasy/pom.xml index 8885d7def..464004245 100644 --- a/http/restful-ws-integration-tests/restful-ws-resteasy/pom.xml +++ b/http/restful-ws-integration-tests/restful-ws-resteasy/pom.xml @@ -22,7 +22,7 @@ cloudevents-http-restful-ws-integration-tests io.cloudevents - 2.3.0-SNAPSHOT + 2.3.0 ../ 4.0.0 diff --git a/http/restful-ws-integration-tests/restful-ws-spring/pom.xml b/http/restful-ws-integration-tests/restful-ws-spring/pom.xml index dfeac7c41..ea945b284 100644 --- a/http/restful-ws-integration-tests/restful-ws-spring/pom.xml +++ b/http/restful-ws-integration-tests/restful-ws-spring/pom.xml @@ -22,7 +22,7 @@ cloudevents-http-restful-ws-integration-tests io.cloudevents - 2.3.0-SNAPSHOT + 2.3.0 ../ 4.0.0 diff --git a/http/restful-ws/pom.xml b/http/restful-ws/pom.xml index 3f8ae0705..64ee65c64 100644 --- a/http/restful-ws/pom.xml +++ b/http/restful-ws/pom.xml @@ -21,7 +21,7 @@ io.cloudevents cloudevents-parent - 2.3.0-SNAPSHOT + 2.3.0 ../../pom.xml diff --git a/http/vertx/pom.xml b/http/vertx/pom.xml index 846ecc077..50c25052d 100644 --- a/http/vertx/pom.xml +++ b/http/vertx/pom.xml @@ -22,7 +22,7 @@ io.cloudevents cloudevents-parent - 2.3.0-SNAPSHOT + 2.3.0 ../../pom.xml diff --git a/kafka/pom.xml b/kafka/pom.xml index 62997a9ec..db7b55e4c 100644 --- a/kafka/pom.xml +++ b/kafka/pom.xml @@ -23,7 +23,7 @@ io.cloudevents cloudevents-parent - 2.3.0-SNAPSHOT + 2.3.0 cloudevents-kafka diff --git a/pom.xml b/pom.xml index 64be11026..0f72b2433 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ io.cloudevents cloudevents-parent - 2.3.0-SNAPSHOT + 2.3.0 pom CloudEvents diff --git a/spring/pom.xml b/spring/pom.xml index 3e44b0dca..13c5b9faf 100644 --- a/spring/pom.xml +++ b/spring/pom.xml @@ -23,7 +23,7 @@ io.cloudevents cloudevents-parent - 2.3.0-SNAPSHOT + 2.3.0 cloudevents-spring diff --git a/sql/pom.xml b/sql/pom.xml index 10d6eaa04..a51e0be02 100644 --- a/sql/pom.xml +++ b/sql/pom.xml @@ -5,7 +5,7 @@ cloudevents-parent io.cloudevents - 2.3.0-SNAPSHOT + 2.3.0 4.0.0