Compare commits

...

78 Commits
2.4.2 ... main

Author SHA1 Message Date
Pierangelo Di Pilato 0d96691f6d
Migrate from OSSRH to Central Portal (#698)
Ref: https://central.sonatype.org/publish/publish-portal-maven/

Signed-off-by: Pierangelo Di Pilato <pierdipi@redhat.com>
2025-06-26 09:44:36 +02:00
Sleiman Jneidi c8a22b5175
build: upgrage to protobuf sdk 4.31.1 (#695)
Signed-off-by: Sleiman <sleiman.jneidi@apple.com>
Co-authored-by: Pierangelo Di Pilato <pierdipi@redhat.com>
2025-06-20 14:56:34 +02:00
Sleiman Jneidi 57f9867a5c
build: remove maven cache (#696)
Signed-off-by: Sleiman <sleiman.jneidi@apple.com>
2025-06-20 09:43:41 +02:00
dependabot[bot] 43f0d5b138
Bump nokogiri from 1.16.5 to 1.18.3 in /docs (#685)
Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.16.5 to 1.18.3.
- [Release notes](https://github.com/sparklemotion/nokogiri/releases)
- [Changelog](https://github.com/sparklemotion/nokogiri/blob/v1.18.3/CHANGELOG.md)
- [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.16.5...v1.18.3)

---
updated-dependencies:
- dependency-name: nokogiri
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-12 08:18:56 +01:00
dependabot[bot] efe7e01b75
Bump org.apache.maven.plugins:maven-antrun-plugin from 3.0.0 to 3.1.0 (#682)
Bumps [org.apache.maven.plugins:maven-antrun-plugin](https://github.com/apache/maven-antrun-plugin) from 3.0.0 to 3.1.0.
- [Commits](https://github.com/apache/maven-antrun-plugin/compare/maven-antrun-plugin-3.0.0...maven-antrun-plugin-3.1.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-antrun-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-27 10:03:16 +01:00
dependabot[bot] 188c3c7085
Bump org.apache.qpid:proton-j from 0.33.7 to 0.34.1 (#678)
Bumps org.apache.qpid:proton-j from 0.33.7 to 0.34.1.

---
updated-dependencies:
- dependency-name: org.apache.qpid:proton-j
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-20 13:13:12 +01:00
dependabot[bot] 659bb8cc01
Bump org.apache.kafka:kafka-clients from 3.0.0 to 3.7.1 in /kafka (#681)
Bumps org.apache.kafka:kafka-clients from 3.0.0 to 3.7.1.

---
updated-dependencies:
- dependency-name: org.apache.kafka:kafka-clients
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-20 13:12:46 +01:00
Kristiyan Marinov 9981635e7d
fix: disallow empty 'subject' context attribute (#679)
Specification clearly states that 'subject' is optional but if present, MUST be non-empty
(spec at https://github.com/cloudevents/spec/blob/v1.0/spec.md#subject)

Signed-off-by: Kristiyan Marinov <kristiyanm@gmail.com>
2024-11-04 09:53:36 +01:00
dependabot[bot] b54df5ca0c
Bump io.projectreactor:reactor-core from 3.5.1 to 3.6.11 (#677)
Bumps [io.projectreactor:reactor-core](https://github.com/reactor/reactor-core) from 3.5.1 to 3.6.11.
- [Release notes](https://github.com/reactor/reactor-core/releases)
- [Commits](https://github.com/reactor/reactor-core/compare/v3.5.1...v3.6.11)

---
updated-dependencies:
- dependency-name: io.projectreactor:reactor-core
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-30 06:47:37 +01:00
dependabot[bot] a3decf768c
Bump org.slf4j:slf4j-simple from 1.7.36 to 2.0.16 (#674)
Bumps org.slf4j:slf4j-simple from 1.7.36 to 2.0.16.

---
updated-dependencies:
- dependency-name: org.slf4j:slf4j-simple
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-29 08:01:59 +01:00
dependabot[bot] 215e67f2c3
Bump rexml from 3.3.6 to 3.3.9 in /docs (#675)
Bumps [rexml](https://github.com/ruby/rexml) from 3.3.6 to 3.3.9.
- [Release notes](https://github.com/ruby/rexml/releases)
- [Changelog](https://github.com/ruby/rexml/blob/master/NEWS.md)
- [Commits](https://github.com/ruby/rexml/compare/v3.3.6...v3.3.9)

---
updated-dependencies:
- dependency-name: rexml
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-29 08:01:19 +01:00
dependabot[bot] 514e00d75b
Bump rexml from 3.2.8 to 3.3.6 in /docs (#665)
Bumps [rexml](https://github.com/ruby/rexml) from 3.2.8 to 3.3.6.
- [Release notes](https://github.com/ruby/rexml/releases)
- [Changelog](https://github.com/ruby/rexml/blob/master/NEWS.md)
- [Commits](https://github.com/ruby/rexml/compare/v3.2.8...v3.3.6)

---
updated-dependencies:
- dependency-name: rexml
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-22 14:24:28 +02:00
dependabot[bot] f7ac215bf1
Bump org.eclipse.jetty:jetty-server in /examples/basic-http (#672)
Bumps org.eclipse.jetty:jetty-server from 9.4.51.v20230217 to 9.4.55.v20240627.

---
updated-dependencies:
- dependency-name: org.eclipse.jetty:jetty-server
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-22 14:23:36 +02:00
dependabot[bot] 5f4abd144a
Bump org.apache.avro:avro from 1.11.3 to 1.11.4 in /formats/avro-compact (#671)
Bumps org.apache.avro:avro from 1.11.3 to 1.11.4.

---
updated-dependencies:
- dependency-name: org.apache.avro:avro
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-08 17:25:38 +02:00
github-actions[bot] 8d59d29bb1
Bump to 4.0.1 (#656)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: pierDipi <pierDipi@users.noreply.github.com>
2024-10-02 19:49:23 +02:00
Rohan Mallya 6ab42de007
docs: correcting import to EventFormatProvider (#658)
Signed-off-by: Rohan R Mallya <bangalorerohan@gmail.com>
2024-10-02 19:48:40 +02:00
dependabot[bot] 2e87988d0c
Bump org.apache.maven.plugins:maven-install-plugin from 2.5.1 to 3.1.3 (#664)
Bumps [org.apache.maven.plugins:maven-install-plugin](https://github.com/apache/maven-install-plugin) from 2.5.1 to 3.1.3.
- [Release notes](https://github.com/apache/maven-install-plugin/releases)
- [Commits](https://github.com/apache/maven-install-plugin/compare/maven-install-plugin-2.5.1...maven-install-plugin-3.1.3)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-install-plugin
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-02 19:48:09 +02:00
David Simansky 6d958b69d4
Fix cloudevents-sql artifactId in bom (#669)
Signed-off-by: David Simansky <dsimansk@redhat.com>
2024-10-02 19:47:43 +02:00
dependabot[bot] 1de03ad38a
Bump org.apache.rocketmq:rocketmq-client-java from 5.0.4 to 5.0.7 (#653)
Bumps [org.apache.rocketmq:rocketmq-client-java](https://github.com/apache/rocketmq-clients) from 5.0.4 to 5.0.7.
- [Release notes](https://github.com/apache/rocketmq-clients/releases)
- [Commits](https://github.com/apache/rocketmq-clients/compare/java-5.0.4...java-5.0.7)

---
updated-dependencies:
- dependency-name: org.apache.rocketmq:rocketmq-client-java
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-03 14:48:32 +02:00
Pierangelo Di Pilato 4c5d0efb89
Make CloudEventValidatorProvider thread safe (#650)
Signed-off-by: Pierangelo Di Pilato <pierdipi@redhat.com>
2024-07-02 17:39:05 +02:00
github-actions[bot] 01a9111d8b
Bump to 4.0.0 in docs (#649)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: pierDipi <pierDipi@users.noreply.github.com>
2024-07-01 20:29:40 +02:00
Pierangelo Di Pilato e056d1b2d8
Allow bumping versions in `/docs` only (#648)
This will allow changing the version in the documentation website
when a new release is published.

Signed-off-by: Pierangelo Di Pilato <pierdipi@redhat.com>
2024-07-01 17:24:48 +02:00
github-actions[bot] efdf0ba866
Bump to 4.1.0-SNAPSHOT (#645)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: pierDipi <pierDipi@users.noreply.github.com>
2024-07-01 12:10:47 +02:00
github-actions[bot] bd90d903ce
Bump to 4.0.0-SNAPSHOT (#644)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: pierDipi <pierDipi@users.noreply.github.com>
2024-07-01 11:41:33 +02:00
dependabot[bot] 52a98d778c
Bump rexml from 3.2.5 to 3.2.8 in /docs (#635)
Bumps [rexml](https://github.com/ruby/rexml) from 3.2.5 to 3.2.8.
- [Release notes](https://github.com/ruby/rexml/releases)
- [Changelog](https://github.com/ruby/rexml/blob/master/NEWS.md)
- [Commits](https://github.com/ruby/rexml/compare/v3.2.5...v3.2.8)

---
updated-dependencies:
- dependency-name: rexml
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-01 10:59:57 +02:00
Calum Murray 010627e784
CE SQL v1 (#641)
- add exception factory for cesql exceptions
- extend EvaluationResult to be usable internally
- expressions use results instead of a thrower interface
- functions use results instead of a thrower interface
- parser handles not equals correctly, does not eagerly evaluate when there may be an error
- parser handles integer literals properly
- updated test files to test v1 spec

Signed-off-by: Calum Murray <cmurray@redhat.com>
Co-authored-by: Pierangelo Di Pilato <pierangelodipilato@gmail.com>
2024-06-21 17:28:26 +02:00
Juan Martinez a7904823c3
fix: invalid automatic module name (#639)
Inspired by [Automatic-Module-Name: Calling All Java Library Maintainers](https://dzone.com/articles/automatic-module-name-calling-all-java-library-maintainers), I added the module names for the non-specified modules on their respective `pom.xml` file

Signed-off-by: Juan MARTINEZ <Jummartinezro@users.noreply.github.com>
2024-06-21 09:24:33 +02:00
Mickaël Schoentgen e5a35ac472
doc: update & uniformize package version (#640)
Signed-off-by: Mickaël Schoentgen <Mickael.Schoentgen@hyland.com>
2024-06-20 12:08:07 +02:00
dependabot[bot] 4d204cef89
Bump org.xmlunit:xmlunit-core from 2.9.0 to 2.10.0 in /formats/xml (#631)
Bumps [org.xmlunit:xmlunit-core](https://github.com/xmlunit/xmlunit) from 2.9.0 to 2.10.0.
- [Release notes](https://github.com/xmlunit/xmlunit/releases)
- [Changelog](https://github.com/xmlunit/xmlunit/blob/main/RELEASE_NOTES.md)
- [Commits](https://github.com/xmlunit/xmlunit/compare/v2.9.0...v2.10.0)

---
updated-dependencies:
- dependency-name: org.xmlunit:xmlunit-core
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-14 11:04:06 +02:00
dependabot[bot] 43afb6ceaa
Bump nokogiri from 1.16.3 to 1.16.5 in /docs (#632)
Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.16.3 to 1.16.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.16.3...v1.16.5)

---
updated-dependencies:
- dependency-name: nokogiri
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-14 11:03:01 +02:00
dependabot[bot] 9c6e7fd11e
Bump io.vertx:vertx-core from 4.3.7 to 4.5.3 in /http/vertx (#622)
Bumps [io.vertx:vertx-core](https://github.com/eclipse/vert.x) from 4.3.7 to 4.5.3.
- [Commits](https://github.com/eclipse/vert.x/compare/4.3.7...4.5.3)

---
updated-dependencies:
- dependency-name: io.vertx:vertx-core
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-09 10:13:49 +02:00
github-actions[bot] 98deac1599
Bump to 3.1.0-SNAPSHOT (#613)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: pierDipi <pierDipi@users.noreply.github.com>
2024-03-26 09:59:22 +01:00
Pierangelo Di Pilato 05baf9be8a
Run workflows on any major version branch (#615)
Signed-off-by: Pierangelo Di Pilato <pierdipi@redhat.com>
2024-03-26 08:42:45 +01:00
Pierangelo Di Pilato 3add823e00
Run workflows on any major version branch (#614)
Signed-off-by: Pierangelo Di Pilato <pierdipi@redhat.com>
2024-03-26 08:39:35 +01:00
dependabot[bot] 5a03173dde
Bump org.apache.maven.plugins:maven-source-plugin from 2.2.1 to 3.3.0 (#608)
Bumps [org.apache.maven.plugins:maven-source-plugin](https://github.com/apache/maven-source-plugin) from 2.2.1 to 3.3.0.
- [Commits](https://github.com/apache/maven-source-plugin/compare/maven-source-plugin-2.2.1...maven-source-plugin-3.3.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-source-plugin
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-26 08:12:40 +01:00
dependabot[bot] 9ee16fb48c
Bump nokogiri from 1.13.10 to 1.16.3 in /docs (#609)
Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.13.10 to 1.16.3.
- [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.13.10...v1.16.3)

---
updated-dependencies:
- dependency-name: nokogiri
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-26 08:11:52 +01:00
dependabot[bot] 0db4446163
Bump com.github.hanleyt:jersey-junit from 2.1.0 to 2.2.0 (#584)
Bumps [com.github.hanleyt:jersey-junit](https://github.com/hanleyt/jersey-junit) from 2.1.0 to 2.2.0.
- [Release notes](https://github.com/hanleyt/jersey-junit/releases)
- [Commits](https://github.com/hanleyt/jersey-junit/compare/2.1.0...2.2.0)

---
updated-dependencies:
- dependency-name: com.github.hanleyt:jersey-junit
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Pierangelo Di Pilato <pierdipi@redhat.com>
2024-03-11 15:57:25 +01:00
touchkey 111fb55cfd
feat: Customizing Cloudevents validation (#594)
Add SPI for custom CloudEvent validation.

Signed-off-by: vbhat6 <vinayas_bhat@intuit.com>
2024-02-15 07:48:55 +01:00
Matej Vasek 55fddb35fc
feat: JSON format to assume JSON content-type where possible (#604)
Signed-off-by: Matej Vašek <mvasek@redhat.com>
2024-02-08 09:49:19 +01:00
Calum Murray 7b9d020acc
Update cesql TCK tests (#603)
Signed-off-by: Calum Murray <cmurray@redhat.com>
2024-01-31 11:51:03 +01:00
Doug Davis fb11b94f2b
Add link to CloudEvent security mailing list (#599)
Signed-off-by: Doug Davis <dug@microsoft.com>
2023-10-16 15:26:53 +02:00
Boris Stumm eaef3becdd
#588 Update jackson to 2.15.2 (#589)
Signed-off-by: Boris Stumm <bs@boris-stumm.de>
2023-10-02 10:08:48 +02:00
dependabot[bot] b30324e916
Bump org.apache.avro:avro from 1.11.2 to 1.11.3 in /formats/avro-compact (#593)
Bumps org.apache.avro:avro from 1.11.2 to 1.11.3.

---
updated-dependencies:
- dependency-name: org.apache.avro:avro
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-02 10:08:22 +02:00
Doug Davis 1f9fa13231
Align SDK governance docs (#590)
Related to https://github.com/cloudevents/spec/pull/1226

Signed-off-by: Doug Davis <dug@microsoft.com>
2023-09-28 09:29:59 +02:00
dependabot[bot] a135755ec6
Bump jackson-dataformat-yaml from 2.11.2 to 2.15.2 (#577)
Bumps [jackson-dataformat-yaml](https://github.com/FasterXML/jackson-dataformats-text) from 2.11.2 to 2.15.2.
- [Commits](https://github.com/FasterXML/jackson-dataformats-text/compare/jackson-dataformats-text-2.11.2...jackson-dataformats-text-2.15.2)

---
updated-dependencies:
- dependency-name: com.fasterxml.jackson.dataformat:jackson-dataformat-yaml
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-21 09:19:35 +02:00
dependabot[bot] 677a2c2628
Bump jetty-server in /examples/basic-http (#579)
Bumps [jetty-server](https://github.com/eclipse/jetty.project) from 9.4.41.v20210516 to 9.4.51.v20230217.
- [Release notes](https://github.com/eclipse/jetty.project/releases)
- [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.41.v20210516...jetty-9.4.51.v20230217)

---
updated-dependencies:
- dependency-name: org.eclipse.jetty:jetty-server
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-21 09:19:06 +02:00
dependabot[bot] 826e099fc0
Bump io.openliberty.arquillian:arquillian-liberty-managed-jakarta-junit (#582)
Bumps [io.openliberty.arquillian:arquillian-liberty-managed-jakarta-junit](https://github.com/OpenLiberty/arquillian-liberty-dependencies) from 2.1.0 to 2.1.4.
- [Release notes](https://github.com/OpenLiberty/arquillian-liberty-dependencies/releases)
- [Commits](https://github.com/OpenLiberty/arquillian-liberty-dependencies/compare/arquillian-liberty-jakarta-dependencies-2.1.0...arquillian-liberty-jakarta-dependencies-2.1.4)

---
updated-dependencies:
- dependency-name: io.openliberty.arquillian:arquillian-liberty-managed-jakarta-junit
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-21 09:18:34 +02:00
dependabot[bot] 76366338fc
Bump truth-proto-extension from 1.1 to 1.1.5 (#580)
Bumps truth-proto-extension from 1.1 to 1.1.5.

---
updated-dependencies:
- dependency-name: com.google.truth.extensions:truth-proto-extension
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-20 18:03:41 +02:00
Alex Collins 4ef304115a
[working-draft] Support Avro Compact Format (#578)
Add support for working-draft spec Avro compact format: 777d0c0398

Signed-off-by: Alex Collins <alex_collins@intuit.com>
2023-07-20 18:02:59 +02:00
dependabot[bot] 582feed520
Bump maven-gpg-plugin from 1.6 to 3.1.0 (#564)
Bumps [maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 1.6 to 3.1.0.
- [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-1.6...maven-gpg-plugin-3.1.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-gpg-plugin
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-23 12:08:54 +02:00
github-actions[bot] 5ef1088a19
Bump to 3.0.0-SNAPSHOT (#571)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: pierDipi <pierDipi@users.noreply.github.com>
2023-05-23 10:55:49 +02:00
Aaron Ai 698cdf7ad4
feat: add rocketmq binding (#554)
Spec details: a6978cf562/rocketmq-cloudevents-binding/rocketmq-transport-binding.md

Signed-off-by: Aaron Ai <yangkun.ayk@alibaba-inc.com>
2023-05-23 10:49:08 +02:00
skepticoitusInteruptus 4ebeab0e0f
Refactor to Facilitate Decoupling from Concrete Implementations of EventFormat (#539)
- Introduce ContentType enum
- Resolve formats by using the ContentType enum

Signed-off-by: Randi Sheaffer-Klass <97033958+skepticoitusInteruptus@users.noreply.github.com>
2023-04-21 10:41:10 +02:00
Jem Day 4c81f3eacc
Make ProtoCloudEventData consistent (#535)
Modified ProtoCloudEventData to always return a 
Protobuf Any object - this ensures it is coherent with
the Protobuf CloudEvent format specification.

It remains possible to wrap any Protobuf 'Message'
object directly (which includes an 'Any') as a
convienience to reduce application code.

Signed-off-by: Jem Day <Jem.Day@cliffhanger.com>
2023-03-10 09:35:24 +01:00
Pierangelo Di Pilato 569e025cf0
Fix javadoc build (#529) (#534)
Signed-off-by: Pierangelo Di Pilato <pierdipi@redhat.com>
2023-03-06 18:25:53 +01:00
Jem Day 3614a4f5f4
Fixed Protobuf data corruption for CloudEvent serialized/deserialized several times (#524)
Fixed issue where mutiple serialize/de-serialize operations
would result in corrupted data if the data was a protobuf
message object.

- Introduced equality checks for ProtoDataWrapper.
- Refactored and cleaned up data-wrappers.

Fixes https://github.com/cloudevents/sdk-java/issues/523

Signed-off-by: Jem Day <Jem.Day@cliffhanger.com>
2023-02-27 11:48:07 +01:00
mxsm d64aff7327
[#521] Remove unused imports (#522)
Signed-off-by: mxsm <ljbmxsm@gmail.com>
2023-02-20 18:06:28 +01:00
dependabot[bot] d1cff75230
Bump activesupport from 6.0.6 to 6.0.6.1 in /docs (#517)
Bumps [activesupport](https://github.com/rails/rails) from 6.0.6 to 6.0.6.1.
- [Release notes](https://github.com/rails/rails/releases)
- [Changelog](https://github.com/rails/rails/blob/v7.0.4.2/activesupport/CHANGELOG.md)
- [Commits](https://github.com/rails/rails/compare/v6.0.6...v6.0.6.1)

---
updated-dependencies:
- dependency-name: activesupport
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-20 08:42:50 +01:00
Ruben Romero Montes 1591cb337a
[#465] Upgrade Quarkus examples with binary and structured events (#515)
Signed-off-by: ruromero <rromerom@redhat.com>
2023-01-24 16:54:22 +01:00
Pierangelo Di Pilato f71303b7b7
Switch default branch to main (#506)
Signed-off-by: Pierangelo Di Pilato <pierdipi@redhat.com>
2023-01-12 19:03:51 +01:00
Pierangelo Di Pilato d59b33307a
Run tests before deploy on Java 17 (#504)
Signed-off-by: Pierangelo Di Pilato <pierdipi@redhat.com>
2023-01-10 16:49:47 +01:00
dependabot[bot] e0d1961f35
Bump nokogiri from 1.13.9 to 1.13.10 in /docs (#496)
Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.13.9 to 1.13.10.
- [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.13.9...v1.13.10)

---
updated-dependencies:
- dependency-name: nokogiri
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-10 16:41:29 +01:00
dependabot[bot] 7c6b52ab30
Bump reactor-core from 3.4.21 to 3.5.1 (#499)
Bumps [reactor-core](https://github.com/reactor/reactor-core) from 3.4.21 to 3.5.1.
- [Release notes](https://github.com/reactor/reactor-core/releases)
- [Commits](https://github.com/reactor/reactor-core/compare/v3.4.21...v3.5.1)

---
updated-dependencies:
- dependency-name: io.projectreactor:reactor-core
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-10 16:10:42 +01:00
Jem Day 433ec5b274
Initial Implementation of XML Format (#448)
Signed-off-by: Day, Jeremy(jday) <jday@paypal.com>
Signed-off-by: Jem Day <Jem.Day@cliffhanger.com>
2023-01-10 09:48:36 +01:00
Doug Davis 40fe91a5e0
Use UTF-8 when using getBytes (#491)
Closes #488

Signed-off-by: Doug Davis <dug@microsoft.com>
2023-01-05 18:01:14 +01:00
Pierangelo Di Pilato a43f90f4e2
Create dependabot.yml 2023-01-02 15:19:06 +01:00
dependabot[bot] e488269510
Bump nokogiri from 1.13.6 to 1.13.9 in /docs (#486)
Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.13.6 to 1.13.9.
- [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.13.6...v1.13.9)

---
updated-dependencies:
- dependency-name: nokogiri
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-02 15:11:24 +01:00
Fabio José 7d50c7fc7a
Bump Vertx to 4.3.7 (#495)
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JAVA-IONETTY-3167773

Co-authored-by: snyk-bot <snyk-bot@snyk.io>
2023-01-02 15:10:38 +01:00
Averi Kitsch f1a86af656
Fix curl command for Spring example (#478)
Signed-off-by: Averi Kitsch <akitsch@google.com>
2023-01-02 13:36:30 +01:00
Doug Davis 354f7a16ef
Upgrade kafka, protobuf, and vert.x versions (#492)
Closes #489

Signed-off-by: Doug Davis <dug@microsoft.com>
2022-12-09 12:35:19 +01:00
Pierangelo Di Pilato 9132a13d81
Remove deprecated constructor usage for JsonCloudEventData (#483)
Fixes #482

Signed-off-by: Pierangelo Di Pilato <pierdipi@redhat.com>
2022-10-12 08:58:41 +02:00
dependabot[bot] a491c85eb2
Bump tzinfo from 1.2.8 to 1.2.10 in /docs (#467)
Bumps [tzinfo](https://github.com/tzinfo/tzinfo) from 1.2.8 to 1.2.10.
- [Release notes](https://github.com/tzinfo/tzinfo/releases)
- [Changelog](https://github.com/tzinfo/tzinfo/blob/master/CHANGES.md)
- [Commits](https://github.com/tzinfo/tzinfo/compare/v1.2.8...v1.2.10)

---
updated-dependencies:
- dependency-name: tzinfo
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-12 08:56:14 +02:00
Frédéric Déléchamp 6362bfbcd6
Strip parameters from data content types to assess if it's JSON format (#484)
Signed-off-by: Frederic Delechamp <fdelechamp@guidewire.com>
2022-10-06 10:42:37 +02:00
Alex Butcher f08a099ed9
Restful-ws jakarta ee9 namespace support (#469)
* Replace javax restful-ws namespace usage with jakarata in own module
* Add microprofile with openliberty example using new jar
* Update gitignore to cover all copied directories
* Update Jersey Version to support jakarta.* namespace packages
* Port jersey integration tests from javax.* to jakarta.*
* Undo changes to existing integration test package names
* Add Integration test for Microprofile/Liberty for Jee9 package
* Add documentation for new Jakarta package

Signed-off-by: alex-butcher <21243172+abutch3r@users.noreply.github.com>
2022-09-27 09:16:03 +02:00
Vikram Vuppla 4139fb7e57
Fix typo in word Covert (#480)
Signed-off-by: Vikram Vuppla <naga.vicky@gmail.com>
2022-09-19 17:31:31 +02:00
Gerard Klijs adde53c817
Correct URL to naming-conventions (#477)
Signed-off-by: Gerard Klijs <gerard.klijs@axoniq.io>
2022-09-14 15:46:09 +02:00
Jorge Oliva 0dc10251ff
Fix example in "Materialize an Extension" (#475)
Was using `ExtensionParser` instead `ExtensionProvider`

Signed-off-by: Jorge Oliva <Jorge.OlivaFernandez@santander.co.uk>
2022-09-14 11:39:25 +02:00
github-actions[bot] b9eaa2fcaa
Bump to 2.5.0-SNAPSHOT (#474)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: pierDipi <pierdipi@redhat.com>
2022-09-06 15:52:34 +02:00
271 changed files with 7334 additions and 1076 deletions

11
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,11 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "maven"
directory: "/" # Location of package manifests
schedule:
interval: "daily"

View File

@ -4,7 +4,8 @@ on:
push:
branches:
- master
- 2.[0-9]+
- main
- '[0-9]+.[0-9]+'
jobs:
test:
@ -12,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
java: [ 8, 11 ]
java: [ 8, 11, 17 ]
steps:
- uses: actions/checkout@v2
- name: Setup java
@ -20,8 +21,9 @@ jobs:
with:
java-version: ${{ matrix.java }}
- run: |
mvn clean install -DskipTests -B
mvn verify -B
./mvnw clean install -DskipTests -B
./mvnw verify -B
deploy:
runs-on: ubuntu-latest
name: Deploy
@ -32,13 +34,13 @@ jobs:
uses: actions/setup-java@v1
with:
java-version: 8
server-id: ossrh # Value of the distributionManagement/repository/id field of the pom.xml
server-id: central # Value of the distributionManagement/repository/id field of the pom.xml
server-username: MAVEN_USERNAME # env variable for username in deploy
server-password: MAVEN_CENTRAL_TOKEN # env variable for token in deploy
gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} # Value of the GPG private key to import
gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase
- name: Publish to Apache Maven Central
run: mvn clean deploy -Drelease -DskipTests -B
run: ./mvnw clean deploy -Drelease -DskipTests -B
env:
MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
MAVEN_CENTRAL_TOKEN: ${{ secrets.MAVEN_CENTRAL_TOKEN }}

View File

@ -5,6 +5,14 @@ on:
version:
description: 'Version to bump (without prepending "v")'
required: true
maven-modules:
description: "Whether to bump versions in pom.xml files"
type: choice
required: true
default: 'true'
options:
- 'true'
- 'false'
jobs:
bump:
@ -19,7 +27,8 @@ jobs:
with:
java-version: 8
- name: Bump version using Maven
run: 'mvn versions:set -DnewVersion=$NEW_VERSION -DgenerateBackupPoms=false -B'
if: ${{ inputs.maven-modules == 'true' }}
run: './mvnw versions:set -DnewVersion=$NEW_VERSION -DgenerateBackupPoms=false -B'
- name: Bump version in docs
if: ${{ !endsWith(github.event.inputs.version, 'SNAPSHOT') }}
run: 'find . -type f -name "*.md" -exec sed -i -e "s+<version>[a-zA-Z0-9.-]*<\/version>+<version>$NEW_VERSION</version>+g" {} +'

View File

@ -4,7 +4,8 @@ on:
pull_request:
branches:
- master
- 2.[0-9]+
- main
- '[0-9]+.[0-9]+'
jobs:
test:
@ -18,9 +19,9 @@ jobs:
- name: Setup java
uses: actions/setup-java@v2
with:
cache: 'maven'
java-version: ${{ matrix.java }}
distribution: 'temurin'
- run: |
mvn clean install -DskipTests -B
mvn verify -B
./mvnw clean install -DskipTests -B
./mvnw verify -B
./mvnw javadoc:javadoc

2
.gitignore vendored
View File

@ -45,3 +45,5 @@ _site/
# MacOS
*.DS_Store
/http/restful-ws-jakarta/src/main/*

View File

@ -23,7 +23,7 @@ your code. Thanks for getting involved! :rocket:
* [Getting Started](#getting-started)
* [Branches](#branches)
* [Commit Messages](#commit-messages)
* [Staying current with master](#staying-current-with-master)
* [Staying current with main](#staying-current-with-main)
* [Submitting and Updating a Pull Request](#submitting-and-updating-a-pull-request)
* [Congratulations!](#congratulations)
@ -47,7 +47,7 @@ organized.
```console
git fetch upstream
git reset --hard upstream/master
git reset --hard upstream/main
git checkout FETCH_HEAD
git checkout -b 48-fix-http-agent-error
```
@ -102,19 +102,19 @@ Date: Thu Feb 2 11:41:15 2018 -0800
Notice the `Author` and `Signed-off-by` lines match. If they don't your PR will
be rejected by the automated DCO check.
## Staying Current with `master`
## Staying Current with `main`
As you are working on your branch, changes may happen on `master`. Before
As you are working on your branch, changes may happen on `main`. Before
submitting your pull request, be sure that your branch has been updated
with the latest commits.
```console
git fetch upstream
git rebase upstream/master
git rebase upstream/main
```
This may cause conflicts if the files you are changing on your branch are
also changed on master. Error messages from `git` will indicate if conflicts
also changed on main. Error messages from `git` will indicate if conflicts
exist and what files need attention. Resolve the conflicts in each file, then
continue with the rebase with `git rebase --continue`.
@ -131,15 +131,15 @@ git push -f origin 48-fix-http-agent-error
Before submitting a pull request, you should make sure that all of the tests
successfully pass.
Once you have sent your pull request, `master` may continue to evolve
before your pull request has landed. If there are any commits on `master`
Once you have sent your pull request, `main` may continue to evolve
before your pull request has landed. If there are any commits on `main`
that conflict with your changes, you may need to update your branch with
these changes before the pull request can land. Resolve conflicts the same
way as before.
```console
git fetch upstream
git rebase upstream/master
git rebase upstream/main
# fix any potential conflicts
git push -f origin 48-fix-http-agent-error
```
@ -156,7 +156,7 @@ for details.
```console
git commit -m "fixup: fix typo"
git rebase -i upstream/master # follow git instructions
git rebase -i upstream/main # follow git instructions
```
Once you have rebased your commits, you can force push to your fork as before.

View File

@ -1,57 +1,5 @@
# Maintainers
Currently, active maintainers who may be found in the CNCF Slack.
Current active maintainers of this SDK:
- [Pierangelo Di Pilato](https://github.com/pierDipi)
# Maintainer's Guide
## Release Process
The release process is automated with Github actions. In order to perform a release:
1. Check if master CI pass.
1. Open the Github repository main page and go in the tab "Actions". Trigger the workflow "Bump version" and insert the new version to release. This will create a new release PR.
1. Check the release PR, merge it and cleanup the created branch.
1. Wait for the CI to complete the deploy of the modules to OSSRH.
1. Using the Github UI, create a new release, specifying the release notes and the tag to use.
1. Trigger again the workflow "Bump version" to bump versions back to a snapshot version.
1. Check the snapshot release PR, merge it and cleanup the created branch.
## Tips
Here are a few tips for repository maintainers.
* Stay on top of your pull requests. PRs that languish for too long can become difficult to merge.
* Work from your own fork. As you are making contributions to the project, you should be working from your own fork just as outside contributors do. This keeps the branches in github to a minimum and reduces unnecessary CI runs.
* Try to proactively label issues and pull requests with labels
* Actively review pull requests as they are submitted
* Triage issues once in a while in order to keep the repository alive.
* If some issues are stale for too long because they are no longer valid/relevant or because the discussion reached no significant action items to perform, close them and invite the users to reopen if they need it.
* If some PRs are no longer valid due to conflicts, but the PR is still needed, ask the contributor to rebase their PR.
* If some issues and PRs are still relevant, use labels to help organize tasks.
* If you find an issue that you want to create a pull request for, be sure to assign it to yourself so that other maintainers don't start working on it at the same time.
## Landing Pull Requests
When landing pull requests, be sure to check the first line uses an appropriate commit message prefix (e.g. docs, feat, lib, etc). If there is more than one commit, try to squash into a single commit. Usually this can just be done with the GitHub UI when merging the PR. Use "Squash and merge". To help ensure that everyone in the community has an opportunity to review and comment on pull requests, it's often good to have some time after a pull request has been submitted, and before it has landed. Some guidelines here about approvals and timing.
* No pull request may land without passing all automated checks
* All pull requests require at least one approval from a maintainer before landing
* A pull request author may approve their own PR, but will need an additional approval to land it
* If a maintainer has submitted a pull request and it has not received approval from at least one other maintainer, it can be landed after 72 hours
* If a pull request has both approvals and requested changes, it can't be landed until those requested changes are resolved
## Branch Management
The `master` branch is the bleeding edge. New major versions of the module
are cut from this branch and tagged. If you intend to submit a pull request
you should use `master HEAD` as your starting point.
Each major release will result in a new branch and tag. For example, the
release of version 1.0.0 of the module will result in a `v1.0.0` tag on the
release commit, and a new branch `v1.x.y` for subsequent minor and patch
level releases of that major version. However, development will continue
apace on `master` for the next major version - e.g. 2.0.0. Version branches
are only created for each major version. Minor and patch level releases
are simply tagged.

39
MAINTAINERS_GUIDE.md Normal file
View File

@ -0,0 +1,39 @@
# Maintainer's Guide
## Tips
Here are a few tips for repository maintainers.
* Stay on top of your pull requests. PRs that languish for too long can become difficult to merge.
* Work from your own fork. As you are making contributions to the project, you should be working from your own fork just as outside contributors do. This keeps the branches in github to a minimum and reduces unnecessary CI runs.
* Try to proactively label issues and pull requests with labels
* Actively review pull requests as they are submitted
* Triage issues once in a while in order to keep the repository alive.
* If some issues are stale for too long because they are no longer valid/relevant or because the discussion reached no significant action items to perform, close them and invite the users to reopen if they need it.
* If some PRs are no longer valid due to conflicts, but the PR is still needed, ask the contributor to rebase their PR.
* If some issues and PRs are still relevant, use labels to help organize tasks.
* If you find an issue that you want to create a pull request for, be sure to assign it to yourself so that other maintainers don't start working on it at the same time.
## Landing Pull Requests
When landing pull requests, be sure to check the first line uses an appropriate commit message prefix (e.g. docs, feat, lib, etc). If there is more than one commit, try to squash into a single commit. Usually this can just be done with the GitHub UI when merging the PR. Use "Squash and merge". To help ensure that everyone in the community has an opportunity to review and comment on pull requests, it's often good to have some time after a pull request has been submitted, and before it has landed. Some guidelines here about approvals and timing.
* No pull request may land without passing all automated checks
* All pull requests require at least one approval from a maintainer before landing
* A pull request author may approve their own PR, but will need an additional approval to land it
* If a maintainer has submitted a pull request and it has not received approval from at least one other maintainer, it can be landed after 72 hours
* If a pull request has both approvals and requested changes, it can't be landed until those requested changes are resolved
## Branch Management
The `main` branch is the bleeding edge. New major versions of the module
are cut from this branch and tagged. If you intend to submit a pull request
you should use `main HEAD` as your starting point.
Each major release will result in a new branch and tag. For example, the
release of version 1.0.0 of the module will result in a `v1.0.0` tag on the
release commit, and a new branch `v1.x.y` for subsequent minor and patch
level releases of that major version. However, development will continue
apace on `main` for the next major version - e.g. 2.0.0. Version branches
are only created for each major version. Minor and patch level releases
are simply tagged.

View File

@ -63,8 +63,10 @@ Javadocs are available on [javadoc.io](https://www.javadoc.io):
- [cloudevents-api](https://www.javadoc.io/doc/io.cloudevents/cloudevents-api)
- [cloudevents-core](https://www.javadoc.io/doc/io.cloudevents/cloudevents-core)
- [cloudevents-avro-compact](https://www.javadoc.io/doc/io.cloudevents/cloudevents-avro-compact)
- [cloudevents-json-jackson](https://www.javadoc.io/doc/io.cloudevents/cloudevents-json-jackson)
- [cloudevents-protobuf](https://www.javadoc.io/doc/io.cloudevents/cloudevents-protobuf)
- [cloudevents-xml](https://www.javadoc.io/doc/io.cloudevents/cloudevents-xml)
- [cloudevents-http-basic](https://www.javadoc.io/doc/io.cloudevents/cloudevents-http-basic)
- [cloudevents-http-restful-ws](https://www.javadoc.io/doc/io.cloudevents/cloudevents-http-restful-ws)
- [cloudevents-http-vertx](https://www.javadoc.io/doc/io.cloudevents/cloudevents-http-vertx)
@ -97,13 +99,25 @@ You can check out the examples in the [examples](examples) directory.
Each SDK may have its own unique processes, tooling and guidelines, common
governance related material can be found in the
[CloudEvents `community`](https://github.com/cloudevents/spec/tree/master/community)
[CloudEvents `community`](https://github.com/cloudevents/spec/tree/main/docs)
directory. In particular, in there you will find information concerning how SDK
projects are
[managed](https://github.com/cloudevents/spec/blob/master/community/SDK-GOVERNANCE.md),
[guidelines](https://github.com/cloudevents/spec/blob/master/community/SDK-maintainer-guidelines.md)
[managed](https://github.com/cloudevents/spec/blob/main/docs/SDK-GOVERNANCE.md),
[guidelines](https://github.com/cloudevents/spec/blob/main/docs/SDK-maintainer-guidelines.md)
for how PR reviews and approval, and our
[Code of Conduct](https://github.com/cloudevents/spec/blob/master/community/GOVERNANCE.md#additional-information)
[Code of Conduct](https://github.com/cloudevents/spec/blob/main/docs/GOVERNANCE.md#additional-information)
information.
If there is a security concern with one of the CloudEvents specifications, or
with one of the project's SDKs, please send an email to
[cncf-cloudevents-security@lists.cncf.io](mailto:cncf-cloudevents-security@lists.cncf.io).
## Additional SDK Resources
- [List of current active maintainers](MAINTAINERS.md)
- [How to contribute to the project](CONTRIBUTING.md)
- [SDK's License](LICENSE)
- [SDK's Release process](RELEASING.md)
- [SDK Maintainer's guide](MAINTAINERS_GUIDE.md)
[http4k]: https://www.http4k.org/guide/reference/cloud_events/

12
RELEASING.md Normal file
View File

@ -0,0 +1,12 @@
# Release Process
The release process is automated with Github actions. In order to perform a release:
1. Check if main CI pass.
1. Open the Github repository main page and go in the tab "Actions". Trigger the workflow "Bump version" and insert the new version to release. This will create a new release PR.
1. Check the release PR, merge it and cleanup the created branch.
1. Wait for the CI to complete the deploy of the modules to OSSRH.
1. Using the Github UI, create a new release, specifying the release notes and the tag to use.
1. Trigger again the workflow "Bump version" to bump versions back to a snapshot version.
1. Check the snapshot release PR, merge it and cleanup the created branch.

View File

@ -6,7 +6,7 @@
<parent>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-parent</artifactId>
<version>2.4.0-SNAPSHOT</version>
<version>4.1.0-SNAPSHOT</version>
</parent>
<artifactId>cloudevents-amqp-proton</artifactId>
@ -14,7 +14,7 @@
<packaging>jar</packaging>
<properties>
<protonj.version>0.33.7</protonj.version>
<protonj.version>0.34.1</protonj.version>
<jsr305.version>3.0.2</jsr305.version>
<module-name>io.cloudevents.amqp.proton</module-name>
</properties>

View File

@ -24,7 +24,7 @@
<parent>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-parent</artifactId>
<version>2.4.0-SNAPSHOT</version>
<version>4.1.0-SNAPSHOT</version>
</parent>
<artifactId>cloudevents-api</artifactId>

View File

@ -216,4 +216,15 @@ public class CloudEventRWException extends RuntimeException {
cause
);
}
/**
* An exception for use where none of the other variants are
* appropriate.
*
* @param msg A description error message.
* @return a new {@link CloudEventRWException}
*/
public static CloudEventRWException newOther(String msg){
return new CloudEventRWException(CloudEventRWExceptionKind.OTHER, msg);
}
}

View File

@ -21,7 +21,7 @@
<parent>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-parent</artifactId>
<version>2.4.0-SNAPSHOT</version>
<version>4.1.0-SNAPSHOT</version>
</parent>
<artifactId>cloudevents-benchmarks</artifactId>
@ -141,7 +141,7 @@
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.1</version>
<version>3.1.3</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
@ -161,7 +161,7 @@
</plugin>
<plugin>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<version>3.3.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>

View File

@ -22,7 +22,7 @@
<parent>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-parent</artifactId>
<version>2.4.0-SNAPSHOT</version>
<version>4.1.0-SNAPSHOT</version>
</parent>
<artifactId>cloudevents-bom</artifactId>
@ -83,7 +83,7 @@
</dependency>
<dependency>
<groupId>io.cloudevents</groupId>
<artifactId>io.cloudevents.sql</artifactId>
<artifactId>cloudevents-sql</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>

View File

@ -22,7 +22,7 @@
<parent>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-parent</artifactId>
<version>2.4.0-SNAPSHOT</version>
<version>4.1.0-SNAPSHOT</version>
</parent>
<artifactId>cloudevents-core</artifactId>

View File

@ -26,7 +26,7 @@ import java.util.*;
/**
* This extension embeds context from Distributed Tracing so that distributed systems can include traces that span an event-driven system.
*
* @see <a href="https://github.com/cloudevents/spec/blob/master/extensions/distributed-tracing.md">https://github.com/cloudevents/spec/blob/master/extensions/distributed-tracing.md</a>
* @see <a href="https://github.com/cloudevents/spec/blob/main/extensions/distributed-tracing.md">https://github.com/cloudevents/spec/blob/main/extensions/distributed-tracing.md</a>
*/
public final class DistributedTracingExtension implements CloudEventExtension {

View File

@ -0,0 +1,72 @@
/*
* Copyright 2018-Present The CloudEvents Authors
* <p>
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.core.format;
import io.cloudevents.CloudEvent;
import io.cloudevents.CloudEventData;
import io.cloudevents.rw.CloudEventDataMapper;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.Collections;
import java.util.Set;
/**
* <p>A construct that aggregates a two-part identifier of file formats and format contents transmitted on the Internet.
*
* <p>The two parts of a {@code ContentType} are its <em>type</em> and a <em>subtype</em>; separated by a forward slash ({@code /}).
*
* <p>The constants enumerated by {@code ContentType} correspond <em>only</em> to the specialized formats supported by the Java SDK for CloudEvents.
*
* @see io.cloudevents.core.format.EventFormat
*/
@ParametersAreNonnullByDefault
public enum ContentType {
/**
* Content type associated with the JSON event format
*/
JSON("application/cloudevents+json"),
/**
* The content type for transports sending cloudevents in the protocol buffer format.
*/
PROTO("application/cloudevents+protobuf"),
/**
* The content type for transports sending cloudevents in the compact Avro format.
*/
AVRO_COMPACT("application/cloudevents+avrocompact"),
/**
* The content type for transports sending cloudevents in XML format.
*/
XML("application/cloudevents+xml");
private String value;
private ContentType(String value) { this.value = value; }
/**
* Return a string consisting of the slash-delimited ({@code /}) two-part identifier for this {@code enum} constant.
*/
public String value() { return value; }
/**
* Return a string consisting of the slash-delimited ({@code /}) two-part identifier for this {@code enum} constant.
*/
@Override
public String toString() { return value(); }
}

View File

@ -124,6 +124,9 @@ public abstract class BaseCloudEventBuilder<SELF extends BaseCloudEventBuilder<S
return self;
}
// @TODO - I think this method should be removed/deprecated
// **Number** Is NOT a valid CE Context atrribute type.
public SELF withExtension(@Nonnull String key, @Nonnull Number value) {
if (!isValidExtensionName(key)) {
throw CloudEventRWException.newInvalidExtensionName(key);
@ -132,6 +135,14 @@ public abstract class BaseCloudEventBuilder<SELF extends BaseCloudEventBuilder<S
return self;
}
public SELF withExtension(@Nonnull String key, @Nonnull Integer value) {
if (!isValidExtensionName(key)) {
throw CloudEventRWException.newInvalidExtensionName(key);
}
this.extensions.put(key, value);
return self;
}
public SELF withExtension(@Nonnull String key, @Nonnull Boolean value) {
if (!isValidExtensionName(key)) {
throw CloudEventRWException.newInvalidExtensionName(key);
@ -208,12 +219,16 @@ public abstract class BaseCloudEventBuilder<SELF extends BaseCloudEventBuilder<S
return new IllegalStateException("Attribute '" + attributeName + "' cannot be null");
}
protected static IllegalStateException createEmptyAttributeException(String attributeName) {
return new IllegalStateException("Attribute '" + attributeName + "' cannot be empty");
}
/**
* Validates the extension name as defined in CloudEvents spec.
*
* @param name the extension name
* @return true if extension name is valid, false otherwise
* @see <a href="https://github.com/cloudevents/spec/blob/master/spec.md#attribute-naming-convention">attribute-naming-convention</a>
* @see <a href="https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#naming-conventions">attribute-naming-conventions</a>
*/
private static boolean isValidExtensionName(String name) {
for (int i = 0; i < name.length(); i++) {

View File

@ -0,0 +1,57 @@
/*
* Copyright 2018-Present The CloudEvents Authors
* <p>
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.core.provider;
import io.cloudevents.CloudEvent;
import io.cloudevents.core.validator.CloudEventValidator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.ServiceLoader;
/**
* CloudEventValidatorProvider is a singleton class which loads and access CE Validator service providers on behalf of service clients.
*/
public class CloudEventValidatorProvider {
private static final CloudEventValidatorProvider cloudEventValidatorProvider = new CloudEventValidatorProvider();
private final Collection<CloudEventValidator> validators;
private CloudEventValidatorProvider() {
final ServiceLoader<CloudEventValidator> loader = ServiceLoader.load(CloudEventValidator.class);
this.validators = new ArrayList<>(2);
for (CloudEventValidator cloudEventValidator : loader) {
validators.add(cloudEventValidator);
}
}
public static CloudEventValidatorProvider getInstance() {
return cloudEventValidatorProvider;
}
/**
* iterates through available Cloudevent validators.
*
* @param cloudEvent event to validate.
*/
public void validate(CloudEvent cloudEvent) {
for (final CloudEventValidator validator : validators) {
validator.validate(cloudEvent);
}
}
}

View File

@ -25,6 +25,7 @@ import java.util.stream.StreamSupport;
import javax.annotation.ParametersAreNonnullByDefault;
import io.cloudevents.core.format.ContentType;
import io.cloudevents.core.format.EventFormat;
import io.cloudevents.lang.Nullable;
@ -98,4 +99,14 @@ public final class EventFormatProvider {
return this.formats.get(contentType);
}
/**
* Resolve an event format starting from the content type.
*
* @param contentType the content type to resolve the event format
* @return null if no format was found for the provided content type
*/
@Nullable
public EventFormat resolveFormat(ContentType contentType) {
return this.formats.get(contentType.value());
}
}

View File

@ -16,9 +16,12 @@
*/
package io.cloudevents.core.v03;
import io.cloudevents.CloudEvent;
import io.cloudevents.SpecVersion;
import io.cloudevents.core.CloudEventUtils;
import io.cloudevents.core.impl.BaseCloudEventBuilder;
import io.cloudevents.core.provider.CloudEventValidatorProvider;
import io.cloudevents.core.v1.CloudEventV1;
import io.cloudevents.rw.CloudEventContextReader;
import io.cloudevents.rw.CloudEventContextWriter;
import io.cloudevents.rw.CloudEventRWException;
@ -121,8 +124,15 @@ public final class CloudEventBuilder extends BaseCloudEventBuilder<CloudEventBui
if (type == null) {
throw createMissingAttributeException("type");
}
if (subject != null && subject.isEmpty()) {
throw createEmptyAttributeException(("subject"));
}
return new CloudEventV03(id, source, type, time, schemaurl, datacontenttype, subject, this.data, this.extensions);
CloudEventV03 cloudEvent = new CloudEventV03(id, source, type, time, schemaurl, datacontenttype, subject, this.data, this.extensions);
final CloudEventValidatorProvider validator = CloudEventValidatorProvider.getInstance();
validator.validate(cloudEvent);
return cloudEvent;
}
@Override

View File

@ -21,6 +21,8 @@ import io.cloudevents.CloudEvent;
import io.cloudevents.SpecVersion;
import io.cloudevents.core.CloudEventUtils;
import io.cloudevents.core.impl.BaseCloudEventBuilder;
import io.cloudevents.core.provider.CloudEventValidatorProvider;
import io.cloudevents.core.validator.CloudEventValidator;
import io.cloudevents.rw.CloudEventContextReader;
import io.cloudevents.rw.CloudEventContextWriter;
import io.cloudevents.rw.CloudEventRWException;
@ -118,8 +120,16 @@ public final class CloudEventBuilder extends BaseCloudEventBuilder<CloudEventBui
if (type == null) {
throw createMissingAttributeException(TYPE);
}
if (subject != null && subject.isEmpty()) {
throw createEmptyAttributeException(("subject"));
}
return new CloudEventV1(id, source, type, datacontenttype, dataschema, subject, time, this.data, this.extensions);
CloudEvent cloudEvent = new CloudEventV1(id, source, type, datacontenttype, dataschema, subject, time, this.data, this.extensions);
final CloudEventValidatorProvider validator = CloudEventValidatorProvider.getInstance();
validator.validate(cloudEvent);
return cloudEvent;
}
@Override

View File

@ -0,0 +1,33 @@
/*
* Copyright 2018-Present The CloudEvents Authors
* <p>
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.core.validator;
import io.cloudevents.CloudEvent;
/**
* @author Vinay Bhat
* Interface which defines validation for CloudEvents attributes and extensions.
*/
public interface CloudEventValidator {
/**
* Validate the attributes of a CloudEvent.
*
* @param cloudEvent the CloudEvent to validate
*/
void validate(CloudEvent cloudEvent);
}

View File

@ -1,5 +1,7 @@
package io.cloudevents.core.data;
import java.nio.charset.StandardCharsets;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
@ -8,7 +10,7 @@ class PojoCloudEventDataTest {
@Test
void testWrapAndMemoization() {
PojoCloudEventData<Integer> data = PojoCloudEventData.wrap(10, i -> i.toString().getBytes());
PojoCloudEventData<Integer> data = PojoCloudEventData.wrap(10, i -> i.toString().getBytes(StandardCharsets.UTF_8));
assertThat(data.getValue())
.isEqualTo(10);
@ -16,7 +18,7 @@ class PojoCloudEventDataTest {
byte[] firstConversion = data.toBytes();
assertThat(firstConversion)
.isEqualTo("10".getBytes());
.isEqualTo("10".getBytes(StandardCharsets.UTF_8));
assertThat(data.toBytes())
.isSameAs(firstConversion);
@ -24,7 +26,7 @@ class PojoCloudEventDataTest {
@Test
void testAlreadySerializedValue() {
byte[] serialized = "10".getBytes();
byte[] serialized = "10".getBytes(StandardCharsets.UTF_8);
PojoCloudEventData<Integer> data = PojoCloudEventData.wrap(10, v -> serialized);
assertThat(data.getValue())

View File

@ -55,7 +55,7 @@ public class CSVFormat implements EventFormat {
event.getData() != null
? new String(Base64.getEncoder().encode(event.getData().toBytes()), StandardCharsets.UTF_8)
: "null"
).getBytes();
).getBytes(StandardCharsets.UTF_8);
}
@Override
@ -70,7 +70,7 @@ public class CSVFormat implements EventFormat {
URI dataschema = splitted[5].equals("null") ? null : URI.create(splitted[5]);
String subject = splitted[6].equals("null") ? null : splitted[6];
OffsetDateTime time = splitted[7].equals("null") ? null : Time.parseTime(splitted[7]);
byte[] data = splitted[8].equals("null") ? null : Base64.getDecoder().decode(splitted[8].getBytes());
byte[] data = splitted[8].equals("null") ? null : Base64.getDecoder().decode(splitted[8].getBytes(StandardCharsets.UTF_8));
CloudEventBuilder builder = CloudEventBuilder.fromSpecVersion(sv)
.withId(id)

View File

@ -1,7 +1,7 @@
package io.cloudevents.core.mock;
import io.cloudevents.CloudEventData;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
public class MyCloudEventData implements CloudEventData {
@ -14,7 +14,7 @@ public class MyCloudEventData implements CloudEventData {
@Override
public byte[] toBytes() {
return Integer.toString(value).getBytes();
return Integer.toString(value).getBytes(StandardCharsets.UTF_8);
}
public int getValue() {

View File

@ -0,0 +1,17 @@
package io.cloudevents.core.test;
import io.cloudevents.CloudEvent;
import io.cloudevents.core.validator.CloudEventValidator;
public class CloudEventCustomValidator implements CloudEventValidator {
@Override
public void validate(CloudEvent cloudEvent) {
String namespace = null;
if ((namespace = (String) cloudEvent.getExtension("namespace")) != null &&
!namespace.equals("sales")){
throw new IllegalStateException("Expecting sales in namespace extension");
}
}
}

View File

@ -23,6 +23,7 @@ import io.cloudevents.types.Time;
import java.math.BigDecimal;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.time.OffsetDateTime;
import java.util.Objects;
import java.util.stream.Stream;
@ -39,9 +40,9 @@ public class Data {
public static final String SUBJECT = "sub";
public static final OffsetDateTime TIME = Time.parseTime("2018-04-26T14:48:09+02:00");
public static byte[] DATA_JSON_SERIALIZED = "{}".getBytes();
public static byte[] DATA_XML_SERIALIZED = "<stuff></stuff>".getBytes();
public static byte[] DATA_TEXT_SERIALIZED = "Hello World Lorena!".getBytes();
public static byte[] DATA_JSON_SERIALIZED = "{}".getBytes(StandardCharsets.UTF_8);
public static byte[] DATA_XML_SERIALIZED = "<stuff></stuff>".getBytes(StandardCharsets.UTF_8);
public static byte[] DATA_TEXT_SERIALIZED = "Hello World Lorena!".getBytes(StandardCharsets.UTF_8);
public static byte[] BINARY_VALUE = { (byte) 0xE0, (byte) 0xFF, (byte) 0x00, (byte) 0x44, (byte) 0xAA }; // Base64: 4P8ARKo=
public static final CloudEvent V1_MIN = CloudEventBuilder.v1()

View File

@ -158,4 +158,27 @@ public class CloudEventBuilderTest {
).hasMessageContaining("Attribute 'type' cannot be null");
}
@Test
void testMissingSubject() {
CloudEvent actual = CloudEventBuilder
.v03()
.withId("000")
.withSource(URI.create("http://localhost"))
.withType(TYPE)
.build();
assertThat(actual).isNotNull();
}
@Test
void testEmptySubject() {
assertThatCode(() -> CloudEventBuilder
.v03()
.withId("000")
.withSource(URI.create("http://localhost"))
.withType(TYPE)
.withSubject("")
.build()
).hasMessageContaining("Attribute 'subject' cannot be empty");
}
}

View File

@ -142,4 +142,39 @@ public class CloudEventBuilderTest {
).hasMessageContaining("Attribute 'type' cannot be null");
}
@Test
void testValidatorProvider(){
assertThatCode(() -> CloudEventBuilder
.v1()
.withId("000")
.withSource(URI.create("http://localhost"))
.withType(TYPE)
.withExtension("namespace", "order")
.build()
).hasMessageContaining("Expecting sales in namespace extension");
}
@Test
void testMissingSubject() {
CloudEvent actual = CloudEventBuilder
.v1()
.withId("000")
.withSource(URI.create("http://localhost"))
.withType(TYPE)
.build();
assertThat(actual).isNotNull();
}
@Test
void testEmptySubject() {
assertThatCode(() -> CloudEventBuilder
.v1()
.withId("000")
.withSource(URI.create("http://localhost"))
.withType(TYPE)
.withSubject("")
.build()
).hasMessageContaining("Attribute 'subject' cannot be empty");
}
}

View File

@ -0,0 +1 @@
io.cloudevents.core.test.CloudEventCustomValidator

View File

@ -1,14 +1,14 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (6.0.3.4)
activesupport (6.0.6.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
zeitwerk (~> 2.2, >= 2.2.2)
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
addressable (2.8.1)
public_suffix (>= 2.0.2, < 6.0)
coffee-script (2.4.1)
coffee-script-source
execjs
@ -16,7 +16,7 @@ GEM
colorator (1.1.0)
commonmarker (0.17.13)
ruby-enum (~> 0.5)
concurrent-ruby (1.1.7)
concurrent-ruby (1.2.0)
dnsruby (1.61.5)
simpleidn (~> 0.1)
em-websocket (0.5.2)
@ -82,7 +82,7 @@ GEM
octokit (~> 4.0)
public_suffix (~> 3.0)
typhoeus (~> 1.3)
html-pipeline (2.14.0)
html-pipeline (2.14.3)
activesupport (>= 2)
nokogiri (>= 1.4)
http_parser.rb (0.6.0)
@ -203,19 +203,19 @@ GEM
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
liquid (4.0.3)
listen (3.3.0)
listen (3.7.1)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
mercenary (0.3.6)
mini_portile2 (2.8.0)
mini_portile2 (2.8.8)
minima (2.5.1)
jekyll (>= 3.5, < 5.0)
jekyll-feed (~> 0.9)
jekyll-seo-tag (~> 2.1)
minitest (5.14.2)
minitest (5.17.0)
multipart-post (2.1.1)
nokogiri (1.13.6)
mini_portile2 (~> 2.8.0)
nokogiri (1.18.3)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
octokit (4.19.0)
faraday (>= 0.9)
@ -223,12 +223,12 @@ GEM
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (3.1.1)
racc (1.6.0)
racc (1.8.1)
rake (13.0.1)
rb-fsevent (0.10.4)
rb-inotify (0.10.1)
ffi (~> 1.0)
rexml (3.2.5)
rexml (3.3.9)
rouge (3.23.0)
ruby-enum (0.8.0)
i18n
@ -250,13 +250,13 @@ GEM
thread_safe (0.3.6)
typhoeus (1.4.0)
ethon (>= 0.9.0)
tzinfo (1.2.8)
tzinfo (1.2.11)
thread_safe (~> 0.1)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.7)
unicode-display_width (1.7.0)
zeitwerk (2.4.1)
zeitwerk (2.6.6)
PLATFORMS
ruby

View File

@ -11,7 +11,7 @@ search_enabled: true
gh_edit_link: true
gh_edit_link_text: "Edit this page on GitHub."
gh_edit_repository: "https://github.com/cloudevents/sdk-java"
gh_edit_branch: "master"
gh_edit_branch: "main"
gh_edit_source: docs
gh_edit_view_mode: "tree"

View File

@ -18,7 +18,7 @@ binding for CloudEvents:
<dependency>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-amqp-proton</artifactId>
<version>2.3.0</version>
<version>4.0.1</version>
</dependency>
```
@ -43,5 +43,5 @@ public class ProtonAmqpMessageFactory {
The example uses the `vertx-proton` integration to send/receive CloudEvent
messages over AMQP:
- [Vertx AmqpServer](https://github.com/cloudevents/sdk-java/tree/master/examples/amqp-proton/src/main/java/io/cloudevents/examples/amqp/vertx/AmqpServer.java)
- [Vertx AmqpClient](https://github.com/cloudevents/sdk-java/tree/master/examples/amqp-proton/src/main/java/io/cloudevents/examples/amqp/vertx/AmqpClient.java)
- [Vertx AmqpServer](https://github.com/cloudevents/sdk-java/tree/main/examples/amqp-proton/src/main/java/io/cloudevents/examples/amqp/vertx/AmqpServer.java)
- [Vertx AmqpClient](https://github.com/cloudevents/sdk-java/tree/main/examples/amqp-proton/src/main/java/io/cloudevents/examples/amqp/vertx/AmqpClient.java)

View File

@ -17,7 +17,7 @@ For Maven based projects, use the following dependency:
<dependency>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-api</artifactId>
<version>2.3.0</version>
<version>4.0.1</version>
</dependency>
```

49
docs/avro.md Normal file
View File

@ -0,0 +1,49 @@
---
title: CloudEvents Avro Compact
nav_order: 4
---
# CloudEvents Avro Compact
[![Javadocs](http://www.javadoc.io/badge/io.cloudevents/cloudevents-avro-compact.svg?color=green)](http://www.javadoc.io/doc/io.cloudevents/cloudevents-avro-compact)
This module provides the Avro Compact `EventFormat` implementation.
# Setup
For Maven based projects, use the following dependency:
```xml
<dependency>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-avro-compact</artifactId>
<version>4.0.1</version>
</dependency>
```
No further configuration is required is use the module.
## Using the Avro Compact Event Format
### Event serialization
```java
import io.cloudevents.CloudEvent;
import io.cloudevents.core.provider.EventFormatProvider;
import io.cloudevents.core.builder.CloudEventBuilder;
import io.cloudevents.avro.avro.compact.AvroCompactFormat;
CloudEvent event = CloudEventBuilder.v1()
.withId("hello")
.withType("example.vertx")
.withSource(URI.create("http://localhost"))
.build();
byte[] serialized = EventFormatProvider
.getInstance()
.resolveFormat(AvroCompactFormat.CONTENT_TYPE)
.serialize(event);
```
The `EventFormatProvider` will automatically resolve the format using the
`ServiceLoader` APIs.

View File

@ -16,7 +16,7 @@ For Maven based projects, use the following dependency:
<dependency>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-core</artifactId>
<version>2.3.0</version>
<version>4.0.1</version>
</dependency>
```
@ -34,7 +34,7 @@ final CloudEvent event = CloudEventBuilder.v1()
.withId("000")
.withType("example.demo")
.withSource(URI.create("http://example.com"))
.withData("text/plain","Hello world!".getBytes())
.withData("text/plain","Hello world!".getBytes("UTF-8"))
.build();
```
@ -87,7 +87,7 @@ with Jackson, add `cloudevents-json-jackson` as a dependency and then using the
`EventFormatProvider`:
```java
import io.cloudevents.core.format.EventFormatProvider;
import io.cloudevents.core.provider.EventFormatProvider;
import io.cloudevents.jackson.JsonFormat;
EventFormat format = EventFormatProvider
@ -110,6 +110,6 @@ CloudEvent extensions can be materialized in their respective POJOs using the
import io.cloudevents.core.extensions.DistributedTracingExtension;
import io.cloudevents.core.provider.ExtensionProvider;
DistributedTracingExtension dte = ExtensionsParser.getInstance()
DistributedTracingExtension dte = ExtensionProvider.getInstance()
.parseExtension(DistributedTracingExtension.class, event);
```

View File

@ -27,7 +27,7 @@ HTTP Transport:
<dependency>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-http-basic</artifactId>
<version>2.3.0</version>
<version>4.0.1</version>
</dependency>
```
@ -48,6 +48,6 @@ public class HttpMessageFactory {
## Examples
- [Standard Java HttpServer](https://github.com/cloudevents/sdk-java/tree/master/examples/basic-http/src/main/java/io/cloudevents/examples/http/basic/BasicHttpServer.java)
- [Http Client with HttpURLConnection](https://github.com/cloudevents/sdk-java/tree/master/examples/basic-http/src/main/java/io/cloudevents/examples/http/basic/HttpURLConnectionClient.java)
- [Http Servlet with Jetty](https://github.com/cloudevents/sdk-java/tree/master/examples/basic-http/src/main/java/io/cloudevents/examples/http/basic/JettyServer.java)
- [Standard Java HttpServer](https://github.com/cloudevents/sdk-java/tree/main/examples/basic-http/src/main/java/io/cloudevents/examples/http/basic/BasicHttpServer.java)
- [Http Client with HttpURLConnection](https://github.com/cloudevents/sdk-java/tree/main/examples/basic-http/src/main/java/io/cloudevents/examples/http/basic/HttpURLConnectionClient.java)
- [Http Servlet with Jetty](https://github.com/cloudevents/sdk-java/tree/main/examples/basic-http/src/main/java/io/cloudevents/examples/http/basic/JettyServer.java)

View File

@ -0,0 +1,137 @@
---
title: CloudEvents HTTP Jakarta EE 9+ - Jakarta RESTful Web Services
nav_order: 5
---
# HTTP Protocol Binding for Jakarta EE 9+ - Jakarta RESTful Web Services
[![Javadocs](https://www.javadoc.io/badge/io.cloudevents/cloudevents-http-restful-ws.svg?color=green)](https://www.javadoc.io/doc/io.cloudevents/cloudevents-http-restful-ws)
For Maven based projects, use the following to configure the CloudEvents Jakarta
RESTful Web Services Binding for Jakarta EE 9+:
```xml
<dependency>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-http-restful-ws-jakarta</artifactId>
<version>4.0.1</version>
</dependency>
```
This integration is tested with Jersey (Requires JDK11 or higher), RestEasy & Microprofile Liberty.
#### * Before using this package ensure your web framework does support the `jakarta.*` namespace.
## Receiving CloudEvents
You need to configure the `CloudEventsProvider` to enable
marshalling/unmarshalling of CloudEvents.
Below is a sample on how to read and write CloudEvents:
```java
import io.cloudevents.CloudEvent;
import io.cloudevents.core.builder.CloudEventBuilder;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.Response;
@Path("/")
public class EventReceiverResource {
@GET
@Path("getMinEvent")
public CloudEvent getMinEvent() {
return CloudEventBuilder.v1()
.withId("hello")
.withType("example.vertx")
.withSource(URI.create("http://localhost"))
.build();
}
// Return the CloudEvent using the HTTP binding structured encoding
@GET
@Path("getStructuredEvent")
@StructuredEncoding("application/cloudevents+csv")
public CloudEvent getStructuredEvent() {
return CloudEventBuilder.v1()
.withId("hello")
.withType("example.vertx")
.withSource(URI.create("http://localhost"))
.build();
}
@POST
@Path("postEventWithoutBody")
public Response postEvent(CloudEvent inputEvent) {
// Handle the event
return Response.ok().build();
}
}
```
## Sending CloudEvents
You need to configure the `CloudEventsProvider` to enable
marshalling/unmarshalling of CloudEvents.
Below is a sample on how to use the client to send a CloudEvent:
```java
import io.cloudevents.CloudEvent;
import io.cloudevents.http.restful.ws.CloudEventsProvider;
import jakarta.ws.rs.client.Entity;
import jakarta.ws.rs.client.WebTarget;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.Response;
public class CloudEventSender {
public Response sendEvent(WebTarget target, CloudEvent event) {
return target
.path("postEvent")
.request()
.buildPost(Entity.entity(event, CloudEventsProvider.CLOUDEVENT_TYPE))
.invoke();
}
public Response sendEventAsStructured(WebTarget target, CloudEvent event) {
return target
.path("postEvent")
.request()
.buildPost(Entity.entity(event, "application/cloudevents+json"))
.invoke();
}
public CloudEvent getEvent(WebTarget target) {
Response response = target
.path("getEvent")
.request()
.buildGet()
.invoke();
return response.readEntity(CloudEvent.class);
}
}
```
## Migrating EE 8 applications to EE 9+
The main change between Jakarta EE 8 and Jakarta EE 9 and future versions is the changing of the `javax.` to `jakarta.` namespaces used by key packages such as `jakarta.ws.rs-api` which provides the restful-ws API.
This change largely impacts only `import` statements it does filter down to dependencies such as this.
### Application migration
For application migration we would recommend reviewing materials available from https://jakarta.ee/resources/#documentation as a starting point.
### CloudEvents Dependency
To migrate to use EE 9+ supported package - replace `cloudevents-http-restful-ws` with `cloudevents-http-restful-ws-jakarta` and ensure the version is a minimum of `2.5.0-SNAPSHOT`
## Examples
- [Microprofile and Liberty](https://github.com/cloudevents/sdk-java/tree/main/examples/restful-ws-micropofile-liberty)

View File

@ -3,18 +3,18 @@ title: CloudEvents HTTP Jakarta RESTful Web Services
nav_order: 5
---
# HTTP Protocol Binding for Jakarta RESTful Web Services
# HTTP Protocol Binding for Jakarta EE8 - RESTful Web Services
[![Javadocs](http://www.javadoc.io/badge/io.cloudevents/cloudevents-http-restful-ws.svg?color=green)](http://www.javadoc.io/doc/io.cloudevents/cloudevents-http-restful-ws)
For Maven based projects, use the following to configure the CloudEvents Jakarta
RESTful Web Services Binding:
RESTful Web Services Binding for Jakarta EE 8:
```xml
<dependency>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-http-restful-ws</artifactId>
<version>2.3.0</version>
<version>4.0.1</version>
</dependency>
```
@ -118,5 +118,5 @@ public class CloudEventSender {
## Examples
- [Quarkus and Resteasy](https://github.com/cloudevents/sdk-java/tree/master/examples/restful-ws-quarkus)
- [Jersey and Spring Boot](https://github.com/cloudevents/sdk-java/tree/master/examples/restful-ws-spring-boot)
- [Quarkus and Resteasy](https://github.com/cloudevents/sdk-java/tree/main/examples/restful-ws-quarkus)
- [Jersey and Spring Boot](https://github.com/cloudevents/sdk-java/tree/main/examples/restful-ws-spring-boot)

View File

@ -14,7 +14,7 @@ HTTP Transport:
<dependency>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-http-vertx</artifactId>
<version>2.3.0</version>
<version>4.0.1</version>
</dependency>
```
@ -95,4 +95,4 @@ public class CloudEventClientVerticle extends AbstractVerticle {
## Examples:
- [Vert.x Client and Server](https://github.com/cloudevents/sdk-java/tree/master/examples/vertx)
- [Vert.x Client and Server](https://github.com/cloudevents/sdk-java/tree/main/examples/vertx)

View File

@ -42,6 +42,8 @@ Using the Java SDK you can:
| - [Jackson](json-jackson.md) | :heavy_check_mark: | :heavy_check_mark: |
| Protobuf Event Format | :heavy_check_mark: | :heavy_check_mark: |
| - [Proto](protobuf.md) | :heavy_check_mark: | :heavy_check_mark: |
| XML Event Format | :heavy_check_mark: | :heavy_check_mark: |
| - [XML](xml.md) | :heavy_check_mark: | :heavy_check_mark: |
| [Kafka Protocol Binding](kafka.md) | :heavy_check_mark: | :heavy_check_mark: |
| MQTT Protocol Binding | :x: | :x: |
| NATS Protocol Binding | :x: | :x: |
@ -62,7 +64,8 @@ receive CloudEvents, check out the dedicated pages:
- [AMQP using Proton](amqp-proton.md)
- [HTTP using Vert.x](http-vertx.md)
- [HTTP using Jakarta Restful WS](http-jakarta-restful-ws.md)
- [HTTP using Jakarta EE 8 - Jakarta Restful WS](http-jakarta-restful-ws.md)
- [HTTP using Jakarta EE 9+ - Jakarta Restful WS](http-jakarta-restful-ws-jakarta.md)
- [HTTP using Spring](spring.md)
- [HTTP using Jackson](json-jackson.md)
- [Kafka](kafka.md)
@ -72,7 +75,7 @@ and related interfaces, in order to interoperate with the other components of
the SDK, check out the [API module documentation](api.md).
You can also check out the
[**Examples**](https://github.com/cloudevents/sdk-java/tree/master/examples).
[**Examples**](https://github.com/cloudevents/sdk-java/tree/main/examples).
## Modules
@ -95,10 +98,13 @@ a different feature from the different sub specs of
[Jackson](https://github.com/FasterXML/jackson)
- [`cloudevents-protobuf`] Implementation of [Protobuf Event format] using code generated
from the standard [protoc](https://github.com/protocolbuffers/protobuf) compiler.
- [`cloudevents-xml`] Implementation of the XML Event Format.
- [`cloudevents-http-vertx`] Implementation of [HTTP Protocol Binding] with
[Vert.x Core](https://vertx.io/)
- [`cloudevents-http-restful-ws`] Implementation of [HTTP Protocol Binding]
for [Jakarta Restful WS](https://jakarta.ee/specifications/restful-ws/)
for [Jakarta EE 8 Restful WS](https://jakarta.ee/specifications/restful-ws/2.1/)
- [`cloudevents-http-restful-ws-jakarta`] Implementation of [HTTP Protocol Binding]
for [Jakarta EE 9+ Restful WS](https://jakarta.ee/specifications/restful-ws/)
- [`cloudevents-http-basic`] Generic implementation of [HTTP Protocol
Binding], primarily intended for integrators
- [`cloudevents-kafka`] Implementation of [Kafka Protocol Binding]
@ -115,15 +121,17 @@ You can look at the latest published artifacts on
[HTTP Protocol Binding]: https://github.com/cloudevents/spec/blob/v1.0/http-protocol-binding.md
[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
[`cloudevents-kafka`]: https://github.com/cloudevents/sdk-java/tree/master/kafka
[`cloudevents-amqp-proton`]: https://github.com/cloudevents/sdk-java/tree/master/amqp
[`cloudevents-spring`]: https://github.com/cloudevents/sdk-java/tree/master/spring
[`cloudevents-api`]: https://github.com/cloudevents/sdk-java/tree/main/api
[`cloudevents-bom`]: https://github.com/cloudevents/sdk-java/tree/main/bom
[`cloudevents-core`]: https://github.com/cloudevents/sdk-java/tree/main/core
[`cloudevents-json-jackson`]: https://github.com/cloudevents/sdk-java/tree/main/formats/json-jackson
[`cloudevents-protobuf`]: https://github.com/cloudevents/sdk-java/tree/main/formats/protobuf
[`cloudevents-xml`]: https://github.com/cloudevents/sdk-java/tree/main/formats/xml
[`cloudevents-http-vertx`]: https://github.com/cloudevents/sdk-java/tree/main/http/vertx
[`cloudevents-http-basic`]: https://github.com/cloudevents/sdk-java/tree/main/http/basic
[`cloudevents-http-restful-ws`]: https://github.com/cloudevents/sdk-java/tree/main/http/restful-ws
[`cloudevents-http-restful-ws-jakarta`]: https://github.com/cloudevents/sdk-java/tree/main/http/restful-ws-jakarta
[`cloudevents-kafka`]: https://github.com/cloudevents/sdk-java/tree/main/kafka
[`cloudevents-amqp-proton`]: https://github.com/cloudevents/sdk-java/tree/main/amqp
[`cloudevents-spring`]: https://github.com/cloudevents/sdk-java/tree/main/spring
[http4k]: https://www.http4k.org/guide/modules/cloud_events/

View File

@ -17,7 +17,7 @@ For Maven based projects, use the following dependency:
<dependency>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-json-jackson</artifactId>
<version>2.3.0</version>
<version>4.0.1</version>
</dependency>
```
@ -28,9 +28,9 @@ adding the dependency to your project:
```java
import io.cloudevents.CloudEvent;
import io.cloudevents.core.format.EventFormatProvider;
import io.cloudevents.core.format.ContentType;
import io.cloudevents.core.provider.EventFormatProvider;
import io.cloudevents.core.builder.CloudEventBuilder;
import io.cloudevents.jackson.JsonFormat;
CloudEvent event = CloudEventBuilder.v1()
.withId("hello")
@ -40,7 +40,7 @@ CloudEvent event = CloudEventBuilder.v1()
byte[]serialized = EventFormatProvider
.getInstance()
.resolveFormat(JsonFormat.CONTENT_TYPE)
.resolveFormat(ContentType.JSON)
.serialize(event);
```

View File

@ -10,14 +10,14 @@ nav_order: 5
Implementation of Kafka Protocol Binding to send and receive CloudEvents.
For Maven based projects, use the following to configure the
[Kafka Protocol Binding](https://github.com/cloudevents/spec/blob/master/kafka-protocol-binding.md):
[Kafka Protocol Binding](https://github.com/cloudevents/spec/blob/main/kafka-protocol-binding.md):
```xml
<dependency>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-kafka</artifactId>
<version>2.3.0</version>
<version>4.0.1</version>
</dependency>
```
@ -64,7 +64,7 @@ public class CloudEventProducer {
You can configure the Encoding and EventFormat to use to emit the event.
Check out the
[`CloudEventSerializer`](https://github.com/cloudevents/sdk-java/tree/master/kafka/src/main/java/io/cloudevents/kafka/CloudEventSerializer.java)
[`CloudEventSerializer`](https://github.com/cloudevents/sdk-java/tree/main/kafka/src/main/java/io/cloudevents/kafka/CloudEventSerializer.java)
javadoc for more info.
### Partition key extension
@ -81,7 +81,7 @@ producerProps.put(
When using in your producer, this interceptor will pick the `partitionkey`
extension from the event and will set it as record key, regardless of the input record key.
Check out the [`PartitionKeyExtensionInterceptor`](https://github.com/cloudevents/sdk-java/tree/master/kafka/src/main/java/io/cloudevents/kafka/PartitionKeyExtensionInterceptor.java)
Check out the [`PartitionKeyExtensionInterceptor`](https://github.com/cloudevents/sdk-java/tree/main/kafka/src/main/java/io/cloudevents/kafka/PartitionKeyExtensionInterceptor.java)
javadoc for more info.
## Consuming CloudEvents

View File

@ -11,26 +11,28 @@ This module provides the Protocol Buffer (protobuf) `EventFormat` implementation
Protobuf runtime and classes generated from the CloudEvents
[proto spec](https://github.com/cloudevents/spec/blob/v1.0.1/spec.proto).
# Setup
For Maven based projects, use the following dependency:
```xml
<dependency>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-protobuf</artifactId>
<version>2.3.0</version>
<version>4.0.1</version>
</dependency>
```
No further configuration is required is use the module.
## Using the Protobuf Event Format
You don't need to perform any operation to configure the module, more than
adding the dependency to your project:
### Event serialization
```java
import io.cloudevents.CloudEvent;
import io.cloudevents.core.format.EventFormatProvider;
import io.cloudevents.core.format.ContentType;
import io.cloudevents.core.provider.EventFormatProvider;
import io.cloudevents.core.builder.CloudEventBuilder;
import io.cloudevents.protobuf.ProtobufFormat;
CloudEvent event = CloudEventBuilder.v1()
.withId("hello")
@ -40,9 +42,55 @@ CloudEvent event = CloudEventBuilder.v1()
byte[]serialized = EventFormatProvider
.getInstance()
.resolveFormat(ProtobufFormat.CONTENT_TYPE)
.resolveFormat(ContentType.PROTO)
.serialize(event);
```
The `EventFormatProvider` will resolve automatically the `ProtobufFormat` using the
The `EventFormatProvider` will automatically resolve the `ProtobufFormat` using the
`ServiceLoader` APIs.
## Passing Protobuf messages as CloudEvent data.
The `ProtoCloudEventData` capability provides a convenience mechanism to handle Protobuf message object data.
### Building
```java
// Build my business event message.
com.google.protobuf.Message myMessage = ..... ;
// Wrap the protobuf message as CloudEventData.
CloudEventData ceData = ProtoCloudEventData.wrap(myMessage);
// Build the CloudEvent
CloudEvent event = CloudEventBuilder.v1()
.withId("hello")
.withType("example.protodata")
.withSource(URI.create("http://localhost"))
.withData(ceData)
.build();
```
### Reading
If the `ProtobufFormat` is used to deserialize a CloudEvent that contains a protobuf message object as data you can use
the `ProtoCloudEventData` to access it as an 'Any' directly.
```java
// Deserialize the event.
CloudEvent myEvent = eventFormat.deserialize(raw);
// Get the Data
CloudEventData eventData = myEvent.getData();
if (ceData instanceOf ProtoCloudEventData) {
// Obtain the protobuf 'any'
Any anAny = ((ProtoCloudEventData) eventData).getAny();
...
}
```

View File

@ -17,7 +17,7 @@ For Maven based projects, use the following dependency:
<dependency>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-spring</artifactId>
<version>2.3.0</version>
<version>4.0.1</version>
</dependency>
```
@ -194,12 +194,12 @@ public Mono<CloudEvent> event(@RequestBody Mono<CloudEvent> body) {
Check out the integration tests and samples:
- [spring-reactive](https://github.com/cloudevents/sdk-java/tree/master/examples/spring-reactive)
- [spring-reactive](https://github.com/cloudevents/sdk-java/tree/main/examples/spring-reactive)
shows how to receive and send CloudEvents through HTTP using Spring Boot and
Webflux.
- [spring-rsocket](https://github.com/cloudevents/sdk-java/tree/master/examples/spring-rsocket)
- [spring-rsocket](https://github.com/cloudevents/sdk-java/tree/main/examples/spring-rsocket)
shows how to receive and send CloudEvents through RSocket using Spring Boot.
- [spring-cloud-function](https://github.com/cloudevents/sdk-java/tree/master/examples/spring-function)
- [spring-cloud-function](https://github.com/cloudevents/sdk-java/tree/main/examples/spring-function)
shows how to consume and process CloudEvents via Spring Cloud Function.

77
docs/xml.md Normal file
View File

@ -0,0 +1,77 @@
---
title: CloudEvents XML Format
nav_order: 4
---
# CloudEvents XML Format
[![Javadocs](http://www.javadoc.io/badge/io.cloudevents/cloudevents-xml.svg?color=green)](http://www.javadoc.io/doc/io.cloudevents/cloudevents-xml)
This module provides and `EventFormat` implementation that adheres
to the CloudEvent XML Format specification.
This format also supports specialized handling for XML CloudEvent `data`.
For Maven based projects, use the following dependency:
```xml
<dependency>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-xml</artifactId>
<version>4.0.1</version>
</dependency>
```
## Using the XML Event Format
You don't need to perform any operation to configure the module, more than
adding the dependency to your project:
```java
import io.cloudevents.CloudEvent;
import io.cloudevents.core.format.ContentType;
import io.cloudevents.core.provider.EventFormatProvider;
import io.cloudevents.core.builder.CloudEventBuilder;
CloudEvent event = CloudEventBuilder.v1()
.withId("hello")
.withType("example.xml")
.withSource(URI.create("http://localhost"))
.build();
byte[] serialized = EventFormatProvider
.getInstance()
.resolveFormat(ContentType.XML)
.serialize(event);
```
The `EventFormatProvider` will resolve automatically the `XMLFormat` using the
`ServiceLoader` APIs.
XML Document data handling is supported via the `XMLCloudEventData`
facility. This convenience wrapper can be used with `any` other supported
format.
```java
import org.w3c.dom.Document;
import io.cloudevents.CloudEvent;
import io.cloudevents.core.builder.CloudEventBuilder;
import io.cloudevents.xml.XMLCloudEventData;
// Create the business event data.
Document xmlDoc = .... ;
// Wrap it into CloudEventData
CloudEventData myData = XMLCloudEventData.wrap(xmlDoc);
// Construct the event
CloudEvent event = CloudEventBuilder.v1()
.withId("hello")
.withType("example.xml")
.withSource(URI.create("http://localhost"))
.withData(myData)
.build();
```

View File

@ -3,14 +3,15 @@
<parent>
<artifactId>cloudevents-examples</artifactId>
<groupId>io.cloudevents</groupId>
<version>2.4.0-SNAPSHOT</version>
<version>4.1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloudevents-amqp-proton-example</artifactId>
<properties>
<vertx.version>4.0.0.Beta1</vertx.version>
<module-name>cloudevents.example.amqp.proton</module-name>
<vertx.version>4.0.0.Beta1</vertx.version>
</properties>
<dependencies>
<dependency>

View File

@ -15,6 +15,7 @@ import org.apache.qpid.proton.message.Message;
import java.io.PrintWriter;
import java.net.URI;
import java.nio.charset.StandardCharsets;
/**
* A example vertx-based AMQP client that interacts with a remote AMQP server to send and receive CloudEvent messages.
@ -71,7 +72,7 @@ public class AmqpClient {
.withSource(URI.create("http://127.0.0.1/amqp-client"))
.withType("com.example.sampletype1")
.withTime(Time.parseTime("2020-11-06T21:47:12.037467+00:00"))
.withData(payload.toString().getBytes())
.withData(payload.toString().getBytes(StandardCharsets.UTF_8))
.build();
final Message message = ProtonAmqpMessageFactory.createWriter().writeBinary(event);

View File

@ -2,6 +2,7 @@ package io.cloudevents.examples.amqp.vertx;
import java.io.PrintWriter;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.Arrays;
@ -81,7 +82,7 @@ public class AmqpServer {
.withType("com.example.sampletype1")
.withSource(URI.create("http://127.0.0.1/amqp-server"))
.withTime(OffsetDateTime.now())
.withData("{\"temp\": 5}".getBytes())
.withData("{\"temp\": 5}".getBytes(StandardCharsets.UTF_8))
.build();
final Message message = writer.writeBinary(event);

View File

@ -21,11 +21,14 @@
<parent>
<artifactId>cloudevents-examples</artifactId>
<groupId>io.cloudevents</groupId>
<version>2.4.0-SNAPSHOT</version>
<version>4.1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloudevents-basic-http-example</artifactId>
<properties>
<module-name>cloudevents.example.basic.http</module-name>
</properties>
<dependencies>
<dependency>
@ -41,7 +44,7 @@
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.4.41.v20210516</version>
<version>9.4.55.v20240627</version>
</dependency>
</dependencies>
</project>

View File

@ -5,11 +5,14 @@
<parent>
<artifactId>cloudevents-examples</artifactId>
<groupId>io.cloudevents</groupId>
<version>2.4.0-SNAPSHOT</version>
<version>4.1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloudevents-kafka-example</artifactId>
<properties>
<module-name>cloudevents.example.kafka</module-name>
</properties>
<dependencies>
<dependency>

View File

@ -12,6 +12,7 @@ import org.apache.kafka.clients.producer.RecordMetadata;
import org.apache.kafka.common.serialization.StringSerializer;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Properties;
import java.util.UUID;
@ -42,7 +43,7 @@ public class SampleProducer {
// Create an event template to set basic CloudEvent attributes
CloudEventBuilder eventTemplate = CloudEventBuilder.v1()
.withSource(URI.create("https://github.com/cloudevents/sdk-java/tree/master/examples/kafka"))
.withSource(URI.create("https://github.com/cloudevents/sdk-java/tree/main/examples/kafka"))
.withType("producer.example");
for (int i = 0; i < MESSAGE_COUNT; i++) {
@ -53,7 +54,7 @@ public class SampleProducer {
// Create the event starting from the template
CloudEvent event = eventTemplate.newBuilder()
.withId(id)
.withData("text/plain", data.getBytes())
.withData("text/plain", data.getBytes(StandardCharsets.UTF_8))
.build();
// Send the record

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>cloudevents-parent</artifactId>
<groupId>io.cloudevents</groupId>
<version>2.4.0-SNAPSHOT</version>
<version>4.1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -21,6 +21,7 @@
<modules>
<module>kafka</module>
<module>restful-ws-quarkus</module>
<module>restful-ws-microprofile-liberty</module>
<module>vertx</module>
<module>basic-http</module>
<module>restful-ws-spring-boot</module>
@ -28,6 +29,7 @@
<module>spring-reactive</module>
<module>spring-rsocket</module>
<module>spring-function</module>
<module>rocketmq</module>
</modules>
</project>

View File

@ -0,0 +1,140 @@
# Cloudevents Restful WS Microprofile Example
This project uses Microprofile 5.0 with OpenLiberty
If you would like to know more about Microprofile go to https://microprofile.io
This Example uses Jakarta EE9 features as such the top level namespace of the `ws-api` packages has changed from `javax` to `jakarta` and uses the `cloudevents-http-restful-ws-jakarta` artifact.
## Build and Execution
### Running the application in dev mode
You can run your application in dev mode that enables live coding using:
```
mvn liberty:dev
```
### Packaging and running the application
To Package and run as a minimum jar without a full OpenLiberty server
```
mvn liberty:package -Drunnable=mvn liberty:package -Dinclude=runnable
```
### Making requests against the server
This sample application has a `/events` RESTful endpoint on the application `cloudevents-restful-ws-microprofile-example
the base application is available at `http://localhost:9080/cloudevents-restful-ws-microprofile-example/`
There are three operations that can be performed:
#### GET /events
Returns a Cloud event with a payload containing a message
```shell
curl -v http://localhost:9080/cloudevents-restful-ws-microprofile-example/events
* Trying 127.0.0.1:9080...
* Connected to localhost (127.0.0.1) port 9080 (#0)
> GET /cloudevents-restful-ws-microprofile-example/events HTTP/1.1
> Host: localhost:9080
> User-Agent: curl/7.83.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 201 no-content
< Ce-Id: hello
< Ce-Source: http://localhost
< Ce-Specversion: 1.0
< Ce-Type: example.http
< Content-Type: application/json
< Content-Language: en-GB
< Content-Length: 64
< Date: Wed, 17 Aug 2022 14:01:50 GMT
<
{"message":"Welcome to this Cloudevents + Microprofile example"}
```
#### POST /events
POST a Cloudevent with a payload that is printed out in the server logs
```shell
curl -v http://localhost:9080/cloudevents-restful-ws-microprofile-example/events \
-H "Ce-Specversion: 1.0" \
-H "Ce-Type: User" \
-H "Ce-Source: io.cloudevents.examples/user" \
-H "Ce-Id: 536808d3-88be-4077-9d7a-a3f162705f78" \
-H "Content-Type: application/json" \
-H "Ce-Subject: SUBJ-0001" \
-d "hello"
* Trying 127.0.0.1:9080...
* Connected to localhost (127.0.0.1) port 9080 (#0)
> POST /cloudevents-restful-ws-microprofile-example/events HTTP/1.1
> Host: localhost:9080
> User-Agent: curl/7.83.1
> Accept: */*
> Ce-Specversion: 1.0
> Ce-Type: User
> Ce-Source: io.cloudevents.examples/user
> Ce-Id: 536808d3-88be-4077-9d7a-a3f162705f78
> Content-Type: application/json
> Ce-Subject: SUBJ-0001
> Content-Length: 5
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 204 No Content
< Content-Language: en-GB
< Content-Length: 0
< Date: Thu, 18 Aug 2022 13:33:03 GMT
<
* Connection #0 to host localhost left intact
```
Server log statement
```
[INFO] Received request providing a event with body hello
[INFO] CloudEvent{id='536808d3-88be-4077-9d7a-a3f162705f78', source=io.cloudevents.examples/user, type='User', datacontenttype='application/json', subject='SUBJ-0001', data=BytesCloudEventData{value=[104, 101, 108, 108, 111]}, extensions={}}
```
#### POST /events/echo
POST a Cloudevent with a payload and have it echoed back as a Cloudevent
```shell
curl -v http://localhost:9080/cloudevents-restful-ws-microprofile-example/events/echo \
-H "Ce-Specversion: 1.0" \
-H "Ce-Type: User" \
-H "Ce-Source: io.cloudevents.examples/user" \
-H "Ce-Id: 536808d3-88be-4077-9d7a-a3f162705f78" \
-H "Content-Type: application/json" \
-H "Ce-Subject: SUBJ-0001" \
-d "hello"
* Trying 127.0.0.1:9080...
* Connected to localhost (127.0.0.1) port 9080 (#0)
> POST /cloudevents-restful-ws-microprofile-example/rest/events/echo HTTP/1.1
> Host: localhost:9080
> User-Agent: curl/7.83.1
> Accept: */*
> Ce-Specversion: 1.0
> Ce-Type: User
> Ce-Source: io.cloudevents.examples/user
> Ce-Id: 536808d3-88be-4077-9d7a-a3f162705f78
> Content-Type: application/json
> Ce-Subject: SUBJ-0001
> Content-Length: 5
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Ce-Id: echo
< Ce-Source: http://localhost
< Ce-Specversion: 1.0
< Ce-Type: echo.http
< Content-Type: application/json
< Content-Language: en-GB
< Content-Length: 17
< Date: Wed, 17 Aug 2022 12:57:59 GMT
<
{"echo": "hello"}* Connection #0 to host localhost left intact
```

View File

@ -0,0 +1,185 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>cloudevents-examples</artifactId>
<groupId>io.cloudevents</groupId>
<version>4.1.0-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloudevents-restful-ws-microprofile-liberty-example</artifactId>
<packaging>war</packaging>
<properties>
<openliberty.maven.version>3.5.1</openliberty.maven.version>
<app.name>cloudevents-microprofile</app.name>
<module-name>cloudevents.example.restful.ws.microprofile.liberty</module-name>
<!-- Liberty server properties -->
<final.name>cloudeventsServer</final.name>
<testServerHttpPort>9080</testServerHttpPort>
<testServerHttpsPort>9443</testServerHttpsPort>
<!--This is set in the ibm-web-ext.xml file -->
<warContext>cloudeventsexperiments</warContext>
<package.file>${project.build.directory}/${app.name}.zip</package.file>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<profiles>
<profile>
<id>runnable</id>
<properties>
<package.file>${project.build.directory}/${app.name}.jar</package.file>
<packaging.type>runnable</packaging.type>
</properties>
</profile>
</profiles>
<dependencies>
<dependency>
<groupId>org.eclipse.microprofile</groupId>
<artifactId>microprofile</artifactId>
<version>5.0</version>
<type>pom</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-http-restful-ws-jakarta</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<version>3.6.11</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.2</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<packagingExcludes>pom.xml</packagingExcludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.10</version>
<executions>
<execution>
<id>copy-server-files</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeArtifactIds>server-snippet</includeArtifactIds>
<prependGroupId>true</prependGroupId>
<outputDirectory>
${project.build.directory}/wlp/usr/servers/${wlpServerName}/configDropins/defaults
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<executions>
<execution>
<id>copy-app</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/wlp/usr/servers/${wlpServerName}/dropins
</outputDirectory>
<resources>
<resource>
<directory>${project.build.directory}</directory>
<includes>
<include>${project.artifactId}-${project.version}.war</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<!-- Enable liberty-maven plugin -->
<plugin>
<groupId>io.openliberty.tools</groupId>
<artifactId>liberty-maven-plugin</artifactId>
<version>${openliberty.maven.version}</version>
<executions>
<execution>
<id>package-server</id>
<phase>package</phase>
<goals>
<goal>create</goal>
<goal>install-feature</goal>
<goal>deploy</goal>
<goal>package</goal>
</goals>
<configuration>
<outputDirectory>target/wlp-package</outputDirectory>
</configuration>
</execution>
</executions>
<configuration>
<include>runnable</include>
<serverName>${final.name}</serverName>
<bootstrapProperties>
<project.name>${final.name}</project.name>
<jwt.issuer>https://server.example.com</jwt.issuer>
<app.context.root>/</app.context.root>
</bootstrapProperties>
</configuration>
</plugin>
<!-- Plugin to run functional tests -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.18.1</version>
<executions>
<execution>
<phase>integration-test</phase>
<id>integration-test</id>
<goals>
<goal>integration-test</goal>
</goals>
<configuration>
<includes>
<include>**/it/**</include>
</includes>
<systemPropertyVariables>
<liberty.test.port>${testServerHttpPort}</liberty.test.port>
<war.name>${warContext}</war.name>
<running.bluemix>${running.bluemix}</running.bluemix>
<cf.context.root>${cf.context.root}</cf.context.root>
</systemPropertyVariables>
</configuration>
</execution>
<execution>
<id>verify-results</id>
<goals>
<goal>verify</goal>
</goals>
</execution>
</executions>
<configuration>
<summaryFile>${project.build.directory}/test-reports/it/failsafe-summary.xml</summaryFile>
<reportsDirectory>${project.build.directory}/test-reports/it</reportsDirectory>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,9 @@
package io.cloudevents.examples.microprofile;
import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.core.Application;
@ApplicationPath("/")
public class CloudEventsApplication extends Application {
}

View File

@ -0,0 +1,56 @@
package io.cloudevents.examples.microprofile;
import io.cloudevents.CloudEvent;
import io.cloudevents.core.builder.CloudEventBuilder;
import jakarta.enterprise.context.RequestScoped;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.net.URI;
import java.nio.charset.StandardCharsets;
@RequestScoped
@Path("events")
public class CloudEventsJaxrsService {
@GET
@Produces(MediaType.APPLICATION_JSON)
public CloudEvent retrieveEvent(){
System.out.println("Received request for an event");
return CloudEventBuilder.v1()
.withData("{\"message\":\"Welcome to this Cloudevents + Microprofile example\"}".getBytes(StandardCharsets.UTF_8))
.withDataContentType("application/json")
.withId("hello")
.withType("example.http")
.withSource(URI.create("http://localhost"))
.build();
}
//Example Curl - curl -v http://localhost:9080/cloudevents-restful-ws-microprofile-example/events -H "Ce-Specversion: 1.0" -H "Ce-Type: User" -H "Ce-Source: io.cloudevents.examples/user" -H "Ce-Id: 536808d3-88be-4077-9d7a-a3f162705f78" -H "Content-Type: application/json" -H "Ce-Subject: SUBJ-0001" -d "hello"
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response postEvent(CloudEvent event){
System.out.println("Received request providing a event with body "+ new String(event.getData().toBytes(), StandardCharsets.UTF_8));
System.out.println(event);
return Response.noContent().build();
}
//Example Curl - curl -v http://localhost:9080/cloudevents-restful-ws-microprofile-example/events/echo -H "Ce-Specversion: 1.0" -H "Ce-Type: User" -H "Ce-Source: io.cloudevents.examples/user" -H "Ce-Id: 536808d3-88be-4077-9d7a-a3f162705f78" -H "Content-Type: application/json" -H "Ce-Subject: SUBJ-0001" -d "hello"
@POST
@Path("/echo")
@Consumes(MediaType.APPLICATION_JSON)
public CloudEvent echo(CloudEvent event){
return CloudEventBuilder.v1()
.withData("application/json", ("{\"echo\": \"" + new String(event.getData().toBytes(),StandardCharsets.UTF_8) + "\"}").getBytes(StandardCharsets.UTF_8))
.withId("echo")
.withType("echo.http")
.withSource(URI.create("http://localhost"))
.build();
}
}

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<server description="${project.name}">
<featureManager>
<feature>microProfile-5.0</feature>
</featureManager>
<httpEndpoint id="defaultHttpEndpoint"
httpPort="9080"
httpsPort="9443"/>
<webApplication location="${project.name}.war">
<classloader apiTypeVisibility="+third-party" />
</webApplication>
<mpMetrics authentication="false"/>
<!-- This is the keystore that will be used by SSL and by JWT. -->
<keyStore id="defaultKeyStore" location="public.jks" type="JKS" password="atbash" />
<!-- The MP JWT configuration that injects the caller's JWT into a ResourceScoped bean for inspection. -->
<mpJwt id="jwtUserConsumer" keyName="theKeyId" audiences="targetService" issuer="${jwt.issuer}"/>
</server>

View File

@ -1,7 +1,11 @@
# Cloudevents Restful WS Quarkus example
This sample application has a `/users` REST endpoint in which you can manage the different users.
The way to create users is through CloudEvents. Here is an example POST:
The way to create users is through CloudEvents.
## Example requests
### [Binary Content mode](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/http-protocol-binding.md#31-binary-content-mode)
```shell script
curl -v http://localhost:8080/users \
@ -30,6 +34,29 @@ curl -v http://localhost:8080/users \
< Location: http://localhost:8080/users
```
### [Structured Content mode](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/http-protocol-binding.md#32-structured-content-mode)
```shell script
curl -v http://localhost:8080/users \
-H "Content-Type: application/cloudevents+json" \
-d @examples/user_structured.json
> POST /users HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.82.0
> Accept: */*
> Content-Type: application/cloudevents+json
> Content-Length: 290
>
< HTTP/1.1 201 Created
< Location: http://localhost:8081/users
< content-length: 0
<
```
### Generated events
In order to also show how to create and send CloudEvents, generated events will be periodically sent
each 2 seconds through HTTP to the same endpoint using a REST client.

View File

@ -0,0 +1,13 @@
{
"specversion" : "1.0",
"type" : "User",
"source": "io.cloudevents.examples/user",
"id": "536808d3-88be-4077-9d7a-a3f162705f78",
"subject": "SUBJ-0001",
"data" : {
"username": "jsmith",
"firstName": "John",
"lastName": "Smith",
"age": 37
}
}

View File

@ -5,11 +5,12 @@
<parent>
<artifactId>cloudevents-examples</artifactId>
<groupId>io.cloudevents</groupId>
<version>2.4.0-SNAPSHOT</version>
<version>4.1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloudevents-restful-ws-quarkus-example</artifactId>
<properties>
<module-name>cloudevents.example.restful.ws.quarkus</module-name>
<quarkus-plugin.version>1.10.3.Final</quarkus-plugin.version>
<quarkus.platform.artifact-id>quarkus-universe-bom</quarkus.platform.artifact-id>
<quarkus.platform.group-id>io.quarkus</quarkus.platform.group-id>

View File

@ -1,11 +1,12 @@
package io.cloudevents.examples.quarkus.client;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import io.cloudevents.CloudEvent;
import io.cloudevents.jackson.JsonFormat;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
@Path("/users")
@ -13,8 +14,11 @@ import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
public interface UserClient {
// This will emit binary encoded events.
// To use structured JSON encoding use @Produces(JsonFormat.CONTENT_TYPE).
// To use structured JSON encoding use @Consumes(JsonFormat.CONTENT_TYPE).
@POST
@Produces(MediaType.APPLICATION_JSON)
void emit(CloudEvent event);
void emitBinary(CloudEvent event);
@POST
@Consumes(JsonFormat.CONTENT_TYPE)
void emitStructured(CloudEvent event);
}

View File

@ -19,7 +19,6 @@ import io.cloudevents.core.builder.CloudEventBuilder;
import io.cloudevents.core.data.PojoCloudEventData;
import io.cloudevents.examples.quarkus.model.User;
import io.quarkus.scheduler.Scheduled;
import io.smallrye.mutiny.Uni;
@ApplicationScoped
public class UserEventsGenerator {
@ -38,8 +37,13 @@ public class UserEventsGenerator {
@Scheduled(every="2s")
public void init() {
CloudEvent event = createEvent(userCount++);
LOGGER.info("try to emit user: {}", event.getId());
userClient.emit(event);
if(userCount % 2 == 0) {
LOGGER.info("try to emit binary event for user: {}", event.getId());
userClient.emitBinary(event);
} else {
LOGGER.info("try to emit structured event for user: {}", event.getId());
userClient.emitStructured(event);
}
}
private CloudEvent createEvent(long id) {

View File

@ -19,7 +19,7 @@ import java.util.Map;
@Path("/users")
@Consumes({MediaType.APPLICATION_JSON, JsonFormat.CONTENT_TYPE})
@Produces({MediaType.APPLICATION_JSON})
@Produces(MediaType.APPLICATION_JSON)
public class UserResource {
private static final Logger LOGGER = LoggerFactory.getLogger(UserResource.class);

View File

@ -4,7 +4,6 @@ import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.is;
@QuarkusTest
public class UserResourceTest {

View File

@ -11,11 +11,11 @@ mvn spring-boot:run
You can try sending a request using `curl`:
```shell
curl -X POST -v -d '{"username": "slinkydeveloper", "firstName": "Francesco", "lastName": "Guardiani", "age": 23}' \ ~
-H'Content-type: application/json' \
-H'Ce-id: 1' \
-H'Ce-source: cloud-event-example' \
-H'Ce-type: happybirthday.myapplication' \
-H'Ce-specversion: 1.0' \
curl -X POST -v -d '{"username": "slinkydeveloper", "firstName": "Francesco", "lastName": "Guardiani", "age": 23}' \
-H 'Content-type: application/json' \
-H 'Ce-id: 1' \
-H 'Ce-source: cloud-event-example' \
-H 'Ce-type: happybirthday.myapplication' \
-H 'Ce-specversion: 1.0' \
http://localhost:8080/happy_birthday
```

View File

@ -5,13 +5,14 @@
<parent>
<artifactId>cloudevents-examples</artifactId>
<groupId>io.cloudevents</groupId>
<version>2.4.0-SNAPSHOT</version>
<version>4.1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloudevents-spring-boot-example</artifactId>
<properties>
<module-name>cloudevents.example.spring.boot</module-name>
<spring-boot.version>2.3.2.RELEASE</spring-boot.version>
<spring.version>5.2.9.RELEASE</spring.version>
</properties>

View File

@ -0,0 +1,27 @@
# RocketMQ + CloudEvents Sample
This example demonstrates the integration of [RocketMQ 5.x client library](https://github.com/apache/rocketmq-clients)
with CloudEvents to create a RocketMQ binding.
## Building the Project
```shell
mvn package
```
## Setting Up a RocketMQ Instance
Follow the [quickstart guide](https://rocketmq.apache.org/docs/quick-start/01quickstart) on the official RocketMQ
website to set up the necessary components, including nameserver, proxy, and broker.
## Event Production
```shell
mvn exec:java -Dexec.mainClass="io.cloudevents.examples.rocketmq.RocketmqProducer" -Dexec.args="foobar:8081 sample-topic"
```
## Event Consumption
```shell
mvn exec:java -Dexec.mainClass="io.cloudevents.examples.rocketmq.RocketmqConsumer" -Dexec.args="foobar:8081 sample-topic sample-consumer-group"
```

24
examples/rocketmq/pom.xml Normal file
View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloudevents-examples</artifactId>
<groupId>io.cloudevents</groupId>
<version>4.1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloudevents-rocketmq-example</artifactId>
<properties>
<module-name>cloudevents.example.rocketmq</module-name>
</properties>
<dependencies>
<dependency>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-rocketmq</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,50 @@
package io.cloudevents.examples.rocketmq;
import io.cloudevents.CloudEvent;
import io.cloudevents.core.message.MessageReader;
import io.cloudevents.rocketmq.RocketMqMessageFactory;
import java.io.IOException;
import java.util.Collections;
import org.apache.rocketmq.client.apis.ClientConfiguration;
import org.apache.rocketmq.client.apis.ClientException;
import org.apache.rocketmq.client.apis.ClientServiceProvider;
import org.apache.rocketmq.client.apis.consumer.ConsumeResult;
import org.apache.rocketmq.client.apis.consumer.FilterExpression;
import org.apache.rocketmq.client.apis.consumer.PushConsumer;
public class RocketmqConsumer {
private RocketmqConsumer() {
}
public static void main(String[] args) throws InterruptedException, ClientException, IOException {
if (args.length < 3) {
System.out.println("Usage: rocketmq_consumer <endpoints> <topic> <consumer_group>");
return;
}
final ClientServiceProvider provider = ClientServiceProvider.loadService();
String endpoints = args[0];
ClientConfiguration clientConfiguration = ClientConfiguration.newBuilder()
.setEndpoints(endpoints)
.build();
FilterExpression filterExpression = new FilterExpression();
String topic = args[1];
String consumerGroup = args[2];
// Create the RocketMQ Consumer.
PushConsumer pushConsumer = provider.newPushConsumerBuilder()
.setClientConfiguration(clientConfiguration)
.setConsumerGroup(consumerGroup)
.setSubscriptionExpressions(Collections.singletonMap(topic, filterExpression))
.setMessageListener(messageView -> {
final MessageReader reader = RocketMqMessageFactory.createReader(messageView);
final CloudEvent event = reader.toEvent();
System.out.println("Received event=" + event + ", messageId=" + messageView.getMessageId());
return ConsumeResult.SUCCESS;
})
.build();
// Block the main thread, no need for production environment.
Thread.sleep(Long.MAX_VALUE);
// Close the push consumer when you don't need it anymore.
pushConsumer.close();
}
}

View File

@ -0,0 +1,64 @@
package io.cloudevents.examples.rocketmq;
import io.cloudevents.CloudEvent;
import io.cloudevents.core.v1.CloudEventBuilder;
import io.cloudevents.rocketmq.RocketMqMessageFactory;
import io.cloudevents.types.Time;
import java.io.IOException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import org.apache.rocketmq.client.apis.ClientConfiguration;
import org.apache.rocketmq.client.apis.ClientException;
import org.apache.rocketmq.client.apis.ClientServiceProvider;
import org.apache.rocketmq.client.apis.message.Message;
import org.apache.rocketmq.client.apis.producer.Producer;
import org.apache.rocketmq.client.apis.producer.SendReceipt;
import org.apache.rocketmq.shaded.com.google.gson.Gson;
public class RocketmqProducer {
private RocketmqProducer() {
}
public static void main(String[] args) throws ClientException, IOException {
if (args.length < 2) {
System.out.println("Usage: rocketmq_producer <endpoints> <topic>");
return;
}
final ClientServiceProvider provider = ClientServiceProvider.loadService();
String endpoints = args[0];
ClientConfiguration clientConfiguration = ClientConfiguration.newBuilder()
.setEndpoints(endpoints)
.build();
String topic = args[1];
// Create the RocketMQ Producer.
final Producer producer = provider.newProducerBuilder()
.setClientConfiguration(clientConfiguration)
.setTopics(topic)
.build();
final Gson gson = new Gson();
Map<String, String> payload = new HashMap<>();
payload.put("foo", "bar");
final CloudEvent event = new CloudEventBuilder()
.withId("client-id")
.withSource(URI.create("http://127.0.0.1/rocketmq-client"))
.withType("com.foobar")
.withTime(Time.parseTime("2022-11-09T21:47:12.032198+00:00"))
.withData(gson.toJson(payload).getBytes(StandardCharsets.UTF_8))
.build();
// Transform event into message.
final Message message = RocketMqMessageFactory.createWriter(topic).writeBinary(event);
try {
// Send the message.
final SendReceipt sendReceipt = producer.send(message);
System.out.println("Send message successfully, messageId=" + sendReceipt.getMessageId());
} catch (Exception e) {
System.out.println("Failed to send message");
e.printStackTrace();
}
// Close the producer when you don't need it anymore.
producer.close();
}
}

View File

@ -5,13 +5,14 @@
<parent>
<artifactId>cloudevents-examples</artifactId>
<groupId>io.cloudevents</groupId>
<version>2.4.0-SNAPSHOT</version>
<version>4.1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloudevents-spring-function-example</artifactId>
<properties>
<module-name>cloudevents.example.spring.function</module-name>
<spring-boot.version>2.4.3</spring-boot.version>
</properties>

View File

@ -5,13 +5,14 @@
<parent>
<artifactId>cloudevents-examples</artifactId>
<groupId>io.cloudevents</groupId>
<version>2.4.0-SNAPSHOT</version>
<version>4.1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloudevents-spring-reactive-example</artifactId>
<properties>
<module-name>cloudevents.example.spring.reactive</module-name>
<spring-boot.version>2.4.3</spring-boot.version>
</properties>

View File

@ -1,6 +1,7 @@
package io.cloudevents.examples.spring;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
@ -76,7 +77,7 @@ public class DemoApplicationTests {
.bodyValue(CloudEventBuilder.v1() //
.withId("12345") //
.withType("io.spring.event") //
.withSource(URI.create("https://spring.io/events")).withData("{\"value\":\"Dave\"}".getBytes()) //
.withSource(URI.create("https://spring.io/events")).withData("{\"value\":\"Dave\"}".getBytes(StandardCharsets.UTF_8)) //
.build()) //
.exchange() //
.expectStatus().isOk() //
@ -102,7 +103,7 @@ public class DemoApplicationTests {
.withId("12345") //
.withType("io.spring.event") //
.withSource(URI.create("https://spring.io/events")) //
.withData("{\"value\":\"Dave\"}".getBytes()) //
.withData("{\"value\":\"Dave\"}".getBytes(StandardCharsets.UTF_8)) //
.build()) //
.exchange() //
.expectStatus().isOk() //

View File

@ -3,6 +3,7 @@ package io.cloudevents.examples.spring;
import static org.assertj.core.api.Assertions.assertThat;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@ -38,7 +39,7 @@ public class WebClientTests {
.withId("12345") //
.withSource(URI.create("https://spring.io/events")) //
.withType("io.spring.event") //
.withData("{\"value\":\"Dave\"}".getBytes()) //
.withData("{\"value\":\"Dave\"}".getBytes(StandardCharsets.UTF_8)) //
.build();
}

View File

@ -5,13 +5,14 @@
<parent>
<artifactId>cloudevents-examples</artifactId>
<groupId>io.cloudevents</groupId>
<version>2.4.0-SNAPSHOT</version>
<version>4.1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloudevents-spring-rsocket-example</artifactId>
<properties>
<module-name>cloudevents.example.spring.rsocket</module-name>
<spring-boot.version>2.4.3</spring-boot.version>
</properties>

View File

@ -5,11 +5,14 @@
<parent>
<artifactId>cloudevents-examples</artifactId>
<groupId>io.cloudevents</groupId>
<version>2.4.0-SNAPSHOT</version>
<version>4.1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloudevents-vertx-example</artifactId>
<properties>
<module-name>cloudevents.example.vertx</module-name>
</properties>
<dependencies>
<dependency>

View File

@ -12,6 +12,7 @@ import io.vertx.ext.web.client.HttpResponse;
import io.vertx.ext.web.client.WebClient;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
public class SampleHTTPClient {
@ -31,7 +32,7 @@ public class SampleHTTPClient {
// Create an event template to set basic CloudEvent attributes.
CloudEventBuilder eventTemplate = CloudEventBuilder.v1()
.withSource(URI.create("https://github.com/cloudevents/sdk-java/tree/master/examples/vertx"))
.withSource(URI.create("https://github.com/cloudevents/sdk-java/tree/main/examples/vertx"))
.withType("vertx.example");
// Send NUM_EVENTS events.
@ -41,7 +42,7 @@ public class SampleHTTPClient {
// Create the event starting from the template
final CloudEvent event = eventTemplate.newBuilder()
.withId(UUID.randomUUID().toString())
.withData("text/plain", data.getBytes())
.withData("text/plain", data.getBytes(StandardCharsets.UTF_8))
.build();
Future<HttpResponse<Buffer>> responseFuture;

View File

@ -23,7 +23,7 @@ public class SampleHTTPServer {
// We need to read the event from the HTTP request we get, so create a MessageReader.
VertxMessageFactory.createReader(request)
// Covert the MessageReader to a CloudEvent.
// Convert the MessageReader to a CloudEvent.
.map(MessageReader::toEvent)
.onSuccess(event -> {
// Print out the event.

View File

@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2021-Present The CloudEvents Authors
~ <p>
~ 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
~ <p>
~ http://www.apache.org/licenses/LICENSE-2.0
~ <p>
~ 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.
~
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-parent</artifactId>
<version>4.1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>cloudevents-avro-compact</artifactId>
<name>CloudEvents - Avro Compact</name>
<properties>
<module-name>io.cloudevents.formats.avro.compact</module-name>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.avro</groupId>
<artifactId>avro-maven-plugin</artifactId>
<version>1.11.2</version>
<configuration>
<stringType>String</stringType>
</configuration>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>schema</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.avro</groupId>
<artifactId>avro</artifactId>
<version>1.11.4</version>
</dependency>
<!-- Test deps -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.16</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit-jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${assertj-core.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-core</artifactId>
<classifier>tests</classifier>
<type>test-jar</type>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,81 @@
{
"namespace": "io.cloudevents.v1.avro.compact",
"type": "record",
"name": "CloudEvent",
"version": "1.0",
"doc": "Avro Compact Event Format for CloudEvents",
"fields": [
{
"name": "id",
"type": "string"
},
{
"name": "source",
"type": "string"
},
{
"name": "type",
"type": "string"
},
{
"name": "datacontenttype",
"type": [
"null",
"string"
],
"default": null
},
{
"name": "dataschema",
"type": [
"null",
"string"
],
"default": null
},
{
"name": "subject",
"type": [
"null",
"string"
],
"default": null
},
{
"name": "time",
"type": [
"null",
{
"type": "long",
"logicalType": "timestamp-micros"
}
],
"default": null
},
{
"name": "extensions",
"type": {
"type": "map",
"values": [
"boolean",
"int",
{
"type": "long",
"logicalType" : "timestamp-micros"
},
"string",
"bytes"
]
},
"default": {}
},
{
"name": "data",
"type": [
"bytes",
"null"
],
"default": "null"
}
]
}

View File

@ -0,0 +1,134 @@
/*
* Copyright 2018-Present The CloudEvents Authors
* <p>
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.avro.compact;
import io.cloudevents.CloudEvent;
import io.cloudevents.CloudEventData;
import io.cloudevents.core.builder.CloudEventBuilder;
import io.cloudevents.core.data.BytesCloudEventData;
import io.cloudevents.core.format.EventDeserializationException;
import io.cloudevents.core.format.EventFormat;
import io.cloudevents.core.format.EventSerializationException;
import io.cloudevents.rw.CloudEventDataMapper;
import io.cloudevents.v1.avro.compact.CloudEvent.Builder;
import java.net.URI;
import java.nio.ByteBuffer;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.HashMap;
import java.util.Map;
/**
* An implementation of {@link EventFormat} for the Avro Compact format.
* This format is resolvable with {@link io.cloudevents.core.provider.EventFormatProvider} using the content type {@link #AVRO_COMPACT_CONTENT_TYPE}.
*/
public class AvroCompactFormat implements EventFormat {
public static final String AVRO_COMPACT_CONTENT_TYPE = "application/cloudevents+avrocompact";
@Override
public byte[] serialize(CloudEvent from) throws EventSerializationException {
try {
Builder to = io.cloudevents.v1.avro.compact.CloudEvent.newBuilder();
// extensions
Map<String, Object> extensions = new HashMap<>();
for (String name : from.getExtensionNames()) {
Object value = from.getExtension(name);
if (value instanceof byte[])
value = ByteBuffer.wrap((byte[]) value);
else if (value instanceof OffsetDateTime)
value = ((OffsetDateTime) value).toInstant();
extensions.put(name, value);
}
to.setSource(from.getSource().toString())
.setType(from.getType())
.setId(from.getId())
.setSubject(from.getSubject())
.setDatacontenttype(from.getDataContentType())
.setExtensions(extensions);
if (from.getTime() != null)
to.setTime(from.getTime().toInstant());
if (from.getDataSchema() != null)
to.setDataschema(from.getDataSchema().toString());
CloudEventData data = from.getData();
if (data != null)
to.setData(ByteBuffer.wrap(data.toBytes()));
return to.build().toByteBuffer().array();
} catch (Exception e) {
throw new EventSerializationException(e);
}
}
@Override
public CloudEvent deserialize(byte[] bytes, CloudEventDataMapper<? extends CloudEventData> mapper) throws EventDeserializationException {
try {
io.cloudevents.v1.avro.compact.CloudEvent from = io.cloudevents.v1.avro.compact.CloudEvent.fromByteBuffer(ByteBuffer.wrap(bytes));
CloudEventBuilder to = CloudEventBuilder.v1()
.withSource(URI.create(from.getSource()))
.withType(from.getType())
.withId(from.getType())
.withSubject(from.getSubject())
.withDataContentType(from.getDatacontenttype());
if (from.getTime() != null)
to.withTime(from.getTime().atOffset(ZoneOffset.UTC));
if (from.getDataschema() != null)
to.withDataSchema(URI.create(from.getDataschema()));
// extensions
for (Map.Entry<String, Object> entry : from.getExtensions().entrySet()) {
String name = entry.getKey();
Object value = entry.getValue();
// Avro supports boolean, int, string, bytes
if (value instanceof Boolean)
to.withExtension(name, (boolean) value);
else if (value instanceof Integer)
to.withExtension(name, (int) value);
else if (value instanceof Instant)
to.withExtension(name, ((Instant) value).atOffset(ZoneOffset.UTC));
else if (value instanceof String)
to.withExtension(name, (String) value);
else if (value instanceof ByteBuffer)
to.withExtension(name, ((ByteBuffer) value).array());
else
// this cannot happen, if ever seen, must be bug in this library
throw new AssertionError(String.format("invalid extension %s unsupported type %s", name, value.getClass()));
}
if (from.getData() == null)
return to.end();
else {
CloudEventData data = BytesCloudEventData.wrap(from.getData().array());
return to.end(mapper.map(data));
}
} catch (Exception e) {
throw new EventDeserializationException(e);
}
}
@Override
public String serializedContentType() {
return AVRO_COMPACT_CONTENT_TYPE;
}
}

View File

@ -0,0 +1 @@
io.cloudevents.avro.compact.AvroCompactFormat

View File

@ -0,0 +1,75 @@
/*
* Copyright 2018-Present The CloudEvents Authors
* <p>
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.avro.compact;
import io.cloudevents.CloudEvent;
import io.cloudevents.core.builder.CloudEventBuilder;
import io.cloudevents.core.data.BytesCloudEventData;
import io.cloudevents.core.format.EventFormat;
import io.cloudevents.core.provider.EventFormatProvider;
import org.junit.jupiter.api.Test;
import java.net.URI;
import java.time.Instant;
import java.time.ZoneOffset;
import java.util.Collections;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
class AvroCompactFormatTest {
private final EventFormat format = EventFormatProvider.getInstance().resolveFormat(AvroCompactFormat.AVRO_COMPACT_CONTENT_TYPE);
@Test
void format() {
assertNotNull(format);
assertEquals(Collections.singleton("application/cloudevents+avrocompact"), format.deserializableContentTypes());
CloudEvent event = CloudEventBuilder.v1()
// mandatory
.withId("")
.withSource(URI.create(""))
.withType("")
// optional
.withTime(Instant.EPOCH.atOffset(ZoneOffset.UTC))
.withSubject("subject")
.withDataSchema(URI.create(""))
// extension
// support boolean, int, long, string, bytes
.withExtension("boolean", false)
.withExtension("int", 0)
.withExtension("time", Instant.EPOCH.atOffset(ZoneOffset.UTC))
.withExtension("string", "")
// omitting bytes, because it is not supported by CloudEvent.equals
.withData("", BytesCloudEventData.wrap(new byte[0]))
.build();
byte[] serialized = format.serialize(event);
assertNotNull(serialized);
CloudEvent deserialized = format.deserialize(serialized);
assertEquals(event, deserialized);
byte[] reserialized = format.serialize(deserialized);
assertArrayEquals(serialized, reserialized);
}
}

View File

@ -22,7 +22,7 @@
<parent>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-parent</artifactId>
<version>2.4.0-SNAPSHOT</version>
<version>4.1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
@ -31,7 +31,7 @@
<packaging>jar</packaging>
<properties>
<jackson.version>2.13.3</jackson.version>
<jackson.version>2.15.2</jackson.version>
<module-name>io.cloudevents.formats.jackson</module-name>
</properties>

View File

@ -33,6 +33,7 @@ import io.cloudevents.core.builder.CloudEventBuilder;
import io.cloudevents.core.data.BytesCloudEventData;
import io.cloudevents.rw.*;
import java.nio.charset.StandardCharsets;
import java.io.IOException;
/**
@ -41,18 +42,21 @@ import java.io.IOException;
class CloudEventDeserializer extends StdDeserializer<CloudEvent> {
private final boolean forceExtensionNameLowerCaseDeserialization;
private final boolean forceIgnoreInvalidExtensionNameDeserialization;
private final boolean disableDataContentTypeDefaulting;
protected CloudEventDeserializer() {
this(false, false);
this(false, false, false);
}
protected CloudEventDeserializer(
boolean forceExtensionNameLowerCaseDeserialization,
boolean forceIgnoreInvalidExtensionNameDeserialization
boolean forceIgnoreInvalidExtensionNameDeserialization,
boolean disableDataContentTypeDefaulting
) {
super(CloudEvent.class);
this.forceExtensionNameLowerCaseDeserialization = forceExtensionNameLowerCaseDeserialization;
this.forceIgnoreInvalidExtensionNameDeserialization = forceIgnoreInvalidExtensionNameDeserialization;
this.disableDataContentTypeDefaulting = disableDataContentTypeDefaulting;
}
private static class JsonMessage implements CloudEventReader {
@ -61,17 +65,20 @@ class CloudEventDeserializer extends StdDeserializer<CloudEvent> {
private final ObjectNode node;
private final boolean forceExtensionNameLowerCaseDeserialization;
private final boolean forceIgnoreInvalidExtensionNameDeserialization;
private final boolean disableDataContentTypeDefaulting;
public JsonMessage(
JsonParser p,
ObjectNode node,
boolean forceExtensionNameLowerCaseDeserialization,
boolean forceIgnoreInvalidExtensionNameDeserialization
boolean forceIgnoreInvalidExtensionNameDeserialization,
boolean disableDataContentTypeDefaulting
) {
this.p = p;
this.node = node;
this.forceExtensionNameLowerCaseDeserialization = forceExtensionNameLowerCaseDeserialization;
this.forceIgnoreInvalidExtensionNameDeserialization = forceIgnoreInvalidExtensionNameDeserialization;
this.disableDataContentTypeDefaulting = disableDataContentTypeDefaulting;
}
@Override
@ -91,6 +98,9 @@ class CloudEventDeserializer extends StdDeserializer<CloudEvent> {
// Parse datacontenttype if any
String contentType = getOptionalStringNode(this.node, this.p, "datacontenttype");
if (!this.disableDataContentTypeDefaulting && contentType == null && this.node.has("data")) {
contentType = "application/json";
}
if (contentType != null) {
writer.withContextAttribute("datacontenttype", contentType);
}
@ -118,11 +128,11 @@ class CloudEventDeserializer extends StdDeserializer<CloudEvent> {
if (JsonFormat.dataIsJsonContentType(contentType)) {
// This solution is quite bad, but i see no alternatives now.
// Hopefully in future we can improve it
data = new JsonCloudEventData(node.remove("data"));
data = JsonCloudEventData.wrap(node.remove("data"));
} else {
JsonNode dataNode = node.remove("data");
assertNodeType(dataNode, JsonNodeType.STRING, "data", "Because content type is not a json, only a string is accepted as data");
data = BytesCloudEventData.wrap(dataNode.asText().getBytes());
data = BytesCloudEventData.wrap(dataNode.asText().getBytes(StandardCharsets.UTF_8));
}
}
}
@ -136,11 +146,11 @@ class CloudEventDeserializer extends StdDeserializer<CloudEvent> {
if (JsonFormat.dataIsJsonContentType(contentType)) {
// This solution is quite bad, but i see no alternatives now.
// Hopefully in future we can improve it
data = new JsonCloudEventData(node.remove("data"));
data = JsonCloudEventData.wrap(node.remove("data"));
} else {
JsonNode dataNode = node.remove("data");
assertNodeType(dataNode, JsonNodeType.STRING, "data", "Because content type is not a json, only a string is accepted as data");
data = BytesCloudEventData.wrap(dataNode.asText().getBytes());
data = BytesCloudEventData.wrap(dataNode.asText().getBytes(StandardCharsets.UTF_8));
}
}
}
@ -232,7 +242,7 @@ class CloudEventDeserializer extends StdDeserializer<CloudEvent> {
*
* @param name the extension name
* @return true if extension name is valid, false otherwise
* @see <a href="https://github.com/cloudevents/spec/blob/master/spec.md#attribute-naming-convention">attribute-naming-convention</a>
* @see <a href="https://github.com/cloudevents/spec/blob/main/spec.md#attribute-naming-convention">attribute-naming-convention</a>
*/
private boolean isValidExtensionName(String name) {
for (int i = 0; i < name.length(); i++) {
@ -256,7 +266,7 @@ class CloudEventDeserializer extends StdDeserializer<CloudEvent> {
ObjectNode node = ctxt.readValue(p, ObjectNode.class);
try {
return new JsonMessage(p, node, this.forceExtensionNameLowerCaseDeserialization, this.forceIgnoreInvalidExtensionNameDeserialization)
return new JsonMessage(p, node, this.forceExtensionNameLowerCaseDeserialization, this.forceIgnoreInvalidExtensionNameDeserialization, this.disableDataContentTypeDefaulting)
.read(CloudEventBuilder::fromSpecVersion);
} catch (RuntimeException e) {
// Yeah this is bad but it's needed to support checked exceptions...

View File

@ -20,6 +20,7 @@ package io.cloudevents.jackson;
import com.fasterxml.jackson.databind.JsonNode;
import io.cloudevents.CloudEventData;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
/**
@ -40,7 +41,7 @@ public class JsonCloudEventData implements CloudEventData {
@Override
public byte[] toBytes() {
return node.toString().getBytes();
return node.toString().getBytes(StandardCharsets.UTF_8);
}
/**

View File

@ -22,6 +22,7 @@ import com.fasterxml.jackson.databind.module.SimpleModule;
import io.cloudevents.CloudEvent;
import io.cloudevents.CloudEventData;
import io.cloudevents.core.builder.CloudEventBuilder;
import io.cloudevents.core.format.ContentType;
import io.cloudevents.core.format.EventDeserializationException;
import io.cloudevents.core.format.EventFormat;
import io.cloudevents.core.format.EventSerializationException;
@ -47,7 +48,7 @@ public final class JsonFormat implements EventFormat {
/**
* JSON Data Content Type Discriminator
*/
private static final Pattern JSON_CONTENT_TYPE_PATTERN = Pattern.compile("^(application|text)\\/([a-zA-Z]+\\+)?json$");
private static final Pattern JSON_CONTENT_TYPE_PATTERN = Pattern.compile("^(application|text)\\/([a-zA-Z]+\\+)?json(;.*)*$");
private final ObjectMapper mapper;
private final JsonFormatOptions options;
@ -212,7 +213,7 @@ public final class JsonFormat implements EventFormat {
ceModule.addSerializer(CloudEvent.class, new CloudEventSerializer(
options.isForceDataBase64Serialization(), options.isForceStringSerialization()));
ceModule.addDeserializer(CloudEvent.class, new CloudEventDeserializer(
options.isForceExtensionNameLowerCaseDeserialization(), options.isForceIgnoreInvalidExtensionNameDeserialization()));
options.isForceExtensionNameLowerCaseDeserialization(), options.isForceIgnoreInvalidExtensionNameDeserialization(), options.isDataContentTypeDefaultingDisabled()));
return ceModule;
}

View File

@ -21,24 +21,27 @@ public final class JsonFormatOptions {
private final boolean forceStringSerialization;
private final boolean forceExtensionNameLowerCaseDeserialization;
private final boolean forceIgnoreInvalidExtensionNameDeserialization;
private final boolean disableDataContentTypeDefaulting;
/**
* Create a new instance of this class options the serialization / deserialization.
*/
public JsonFormatOptions() {
this(false, false, false, false);
this(false, false, false, false, false);
}
JsonFormatOptions(
boolean forceDataBase64Serialization,
boolean forceStringSerialization,
boolean forceExtensionNameLowerCaseDeserialization,
boolean forceIgnoreInvalidExtensionNameDeserialization
boolean forceIgnoreInvalidExtensionNameDeserialization,
boolean disableDataContentTypeDefaulting
) {
this.forceDataBase64Serialization = forceDataBase64Serialization;
this.forceStringSerialization = forceStringSerialization;
this.forceExtensionNameLowerCaseDeserialization = forceExtensionNameLowerCaseDeserialization;
this.forceIgnoreInvalidExtensionNameDeserialization = forceIgnoreInvalidExtensionNameDeserialization;
this.disableDataContentTypeDefaulting = disableDataContentTypeDefaulting;
}
public static JsonFormatOptionsBuilder builder() {
@ -61,11 +64,14 @@ public final class JsonFormatOptions {
return this.forceIgnoreInvalidExtensionNameDeserialization;
}
public boolean isDataContentTypeDefaultingDisabled() { return this.disableDataContentTypeDefaulting; }
public static class JsonFormatOptionsBuilder {
private boolean forceDataBase64Serialization = false;
private boolean forceStringSerialization = false;
private boolean forceExtensionNameLowerCaseDeserialization = false;
private boolean forceIgnoreInvalidExtensionNameDeserialization = false;
private boolean disableDataContentTypeDefaulting = false;
public JsonFormatOptionsBuilder forceDataBase64Serialization(boolean forceDataBase64Serialization) {
this.forceDataBase64Serialization = forceDataBase64Serialization;
@ -87,12 +93,18 @@ public final class JsonFormatOptions {
return this;
}
public JsonFormatOptionsBuilder disableDataContentTypeDefaulting(boolean disableDataContentTypeDefaulting) {
this.disableDataContentTypeDefaulting = disableDataContentTypeDefaulting;
return this;
}
public JsonFormatOptions build() {
return new JsonFormatOptions(
this.forceDataBase64Serialization,
this.forceStringSerialization,
this.forceExtensionNameLowerCaseDeserialization,
this.forceIgnoreInvalidExtensionNameDeserialization
this.forceIgnoreInvalidExtensionNameDeserialization,
this.disableDataContentTypeDefaulting
);
}
}

View File

@ -0,0 +1,69 @@
package io.cloudevents.jackson;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import io.cloudevents.CloudEvent;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.io.StringReader;
import static io.cloudevents.jackson.JsonFormat.getCloudEventJacksonModule;
import static org.assertj.core.api.Assertions.assertThat;
public class CloudEventDeserializerTest {
private static final String nonBinaryPayload = "{\n" +
" \"specversion\" : \"1.0\",\n" +
" \"type\" : \"com.example.someevent\",\n" +
" \"source\" : \"/mycontext\",\n" +
" \"subject\": null,\n" +
" \"id\" : \"D234-1234-1234\",\n" +
" \"time\" : \"2018-04-05T17:31:00Z\",\n" +
" \"comexampleextension1\" : \"value\",\n" +
" \"comexampleothervalue\" : 5,\n" +
" \"data\" : \"I'm just a string\"\n" +
"}";
private static final String binaryPayload = "{\n" +
" \"specversion\" : \"1.0\",\n" +
" \"type\" : \"com.example.someevent\",\n" +
" \"source\" : \"/mycontext\",\n" +
" \"id\" : \"D234-1234-1234\",\n" +
" \"data_base64\" : \"eyAieHl6IjogMTIzIH0=\"\n" +
"}";
@Test
void impliedDataContentTypeNonBinaryData() throws IOException {
ObjectMapper mapper = getObjectMapper(false);
StringReader reader = new StringReader(nonBinaryPayload);
CloudEvent ce = mapper.readValue(reader, CloudEvent.class);
assertThat(ce.getDataContentType()).isEqualTo("application/json");
mapper = getObjectMapper(true);
reader = new StringReader(nonBinaryPayload);
ce = mapper.readValue(reader, CloudEvent.class);
assertThat(ce.getDataContentType()).isNull();
}
@Test
void impliedDataContentTypeBinaryData() throws IOException {
final ObjectMapper mapper = getObjectMapper(false);
StringReader reader = new StringReader(binaryPayload);
CloudEvent ce = mapper.readValue(reader, CloudEvent.class);
assertThat(ce.getDataContentType()).isNull();
}
private static ObjectMapper getObjectMapper(boolean disableDataContentTypeDefaulting) {
final ObjectMapper mapper = new ObjectMapper();
final SimpleModule module = getCloudEventJacksonModule(
JsonFormatOptions
.builder()
.disableDataContentTypeDefaulting(disableDataContentTypeDefaulting)
.build()
);
mapper.registerModule(module);
return mapper;
}
}

View File

@ -37,7 +37,7 @@ public class JsonCloudEventDataTest {
@MethodSource("textContentArguments")
public void testMapper(String contentType) {
CloudEvent event = CloudEventBuilder.v1(Data.V1_MIN)
.withData(contentType, new JsonCloudEventData(JsonNodeFactory.instance.numberNode(10)))
.withData(contentType, JsonCloudEventData.wrap(JsonNodeFactory.instance.numberNode(10)))
.build();
byte[] serialized = EventFormatProvider.getInstance().resolveFormat(JsonFormat.CONTENT_TYPE)

View File

@ -24,6 +24,7 @@ import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import io.cloudevents.CloudEvent;
import io.cloudevents.SpecVersion;
import io.cloudevents.core.builder.CloudEventBuilder;
import io.cloudevents.core.format.ContentType;
import io.cloudevents.core.format.EventDeserializationException;
import io.cloudevents.core.provider.EventFormatProvider;
import io.cloudevents.rw.CloudEventRWException;
@ -40,6 +41,7 @@ import java.nio.file.Paths;
import java.util.Objects;
import java.util.stream.Stream;
import static io.cloudevents.core.format.ContentType.*;
import static io.cloudevents.core.test.Data.*;
import static org.assertj.core.api.Assertions.*;
@ -47,6 +49,22 @@ class JsonFormatTest {
private final ObjectMapper mapper = new ObjectMapper();
@ParameterizedTest
@MethodSource("jsonContentTypes")
void isJsonContentType(String contentType) {
boolean json = JsonFormat.dataIsJsonContentType(contentType);
assertThat(json).isTrue();
}
@ParameterizedTest
@MethodSource("wrongJsonContentTypes")
void isNotJsonContentType(String contentType) {
boolean json = JsonFormat.dataIsJsonContentType(contentType);
assertThat(json).isFalse();
}
@ParameterizedTest
@MethodSource("serializeTestArgumentsDefault")
void serialize(CloudEvent input, String outputFile) throws IOException {
@ -151,6 +169,42 @@ class JsonFormatTest {
}
static Stream<Arguments> jsonContentTypes() {
return Stream.of(
Arguments.of("application/json"),
Arguments.of("application/json;charset=utf-8"),
Arguments.of("application/json;\tcharset = \"utf-8\""),
Arguments.of("application/cloudevents+json;charset=UTF-8"),
Arguments.of("text/json"),
Arguments.of("text/json;charset=utf-8"),
Arguments.of("text/cloudevents+json;charset=UTF-8"),
Arguments.of("text/json;\twhatever"),
Arguments.of("text/json; boundary=something"),
Arguments.of("text/json;foo=\"bar\""),
Arguments.of("text/json; charset = \"us-ascii\""),
Arguments.of("text/json; \t"),
Arguments.of("text/json;"),
//https://www.rfc-editor.org/rfc/rfc2045#section-5.1
// any us-ascii char can be part of parameters (except CTRLs and tspecials)
Arguments.of("text/json; char-set = $!#$%&'*+.^_`|"),
Arguments.of((Object) null),
Arguments.of(JSON + ""),
Arguments.of(JSON.value()),
Arguments.of(JSON.toString())
);
}
static Stream<Arguments> wrongJsonContentTypes() {
return Stream.of(
Arguments.of("applications/json"),
Arguments.of("application/jsom"),
Arguments.of("application/jsonwrong"),
Arguments.of("text/json "),
Arguments.of("text/json ;"),
Arguments.of("test/json")
);
}
public static Stream<Arguments> serializeTestArgumentsDefault() {
return Stream.of(
Arguments.of(V03_MIN, "v03/min.json"),
@ -258,7 +312,7 @@ class JsonFormatTest {
}
private JsonFormat getFormat() {
return (JsonFormat) EventFormatProvider.getInstance().resolveFormat(JsonFormat.CONTENT_TYPE);
return (JsonFormat) EventFormatProvider.getInstance().resolveFormat(JSON);
}
private static byte[] loadFile(String input) {
@ -266,7 +320,7 @@ class JsonFormatTest {
return String.join(
"",
Files.readAllLines(Paths.get(Objects.requireNonNull(Thread.currentThread().getContextClassLoader().getResource(input)).toURI()), StandardCharsets.UTF_8)
).getBytes();
).getBytes(StandardCharsets.UTF_8);
} catch (IOException | URISyntaxException e) {
throw new RuntimeException(e);
}
@ -281,7 +335,7 @@ class JsonFormatTest {
builder = CloudEventBuilder.v03(event);
}
return builder
.withData(new JsonCloudEventData(JsonNodeFactory.instance.objectNode()))
.withData(JsonCloudEventData.wrap(JsonNodeFactory.instance.objectNode()))
.build();
} else {
return event;

View File

@ -13,6 +13,7 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import java.nio.charset.StandardCharsets;
import java.util.stream.Stream;
import static org.assertj.core.api.Assertions.assertThat;
@ -28,7 +29,7 @@ public class PojoCloudEventDataMapperTest {
public void testWithBytes(PojoCloudEventDataMapper<MyPojo> mapper) {
CloudEvent event = CloudEventBuilder.v1(Data.V1_MIN)
.withData("application/json", myPojoSerialized.getBytes())
.withData("application/json", myPojoSerialized.getBytes(StandardCharsets.UTF_8))
.build();
PojoCloudEventData<MyPojo> mappedData = CloudEventUtils.mapData(
@ -46,7 +47,7 @@ public class PojoCloudEventDataMapperTest {
public void testWithJson(PojoCloudEventDataMapper<MyPojo> mapper) {
CloudEvent event = CloudEventBuilder.v1(Data.V1_MIN)
.withData("application/json", new JsonCloudEventData(myPojoJson))
.withData("application/json", JsonCloudEventData.wrap(myPojoJson))
.build();
PojoCloudEventData<MyPojo> mappedData = CloudEventUtils.mapData(

View File

@ -23,7 +23,7 @@
<parent>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-parent</artifactId>
<version>2.4.0-SNAPSHOT</version>
<version>4.1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
@ -32,7 +32,7 @@
<packaging>jar</packaging>
<properties>
<protobuf.version>3.15.0</protobuf.version>
<protobuf.version>4.31.1</protobuf.version>
<module-name>io.cloudevents.formats.protobuf</module-name>
</properties>
@ -112,7 +112,7 @@
<dependency>
<groupId>com.google.truth.extensions</groupId>
<artifactId>truth-proto-extension</artifactId>
<version>1.1</version>
<version>1.4.4</version>
<scope>test</scope>
</dependency>

View File

@ -16,6 +16,7 @@
*/
package io.cloudevents.protobuf;
import com.google.protobuf.Any;
import com.google.protobuf.Message;
import io.cloudevents.CloudEventData;
@ -26,13 +27,7 @@ import io.cloudevents.CloudEventData;
public interface ProtoCloudEventData extends CloudEventData {
/**
* Gets the protobuf {@link Message} representation of this data.
* @return The data as a {@link Message}
*/
Message getMessage();
/**
* Convenience helper to wrap a Protobuf Message as
* Convenience helper to wrap a Protobuf {@link Message} as
* CloudEventData.
*
* @param protoMessage The message to wrap
@ -41,4 +36,11 @@ public interface ProtoCloudEventData extends CloudEventData {
static CloudEventData wrap(Message protoMessage) {
return new ProtoDataWrapper(protoMessage);
}
/**
* Gets the protobuf {@link Any} representation of this data.
*
* @return The data as an {@link Any}
*/
Any getAny();
}

View File

@ -16,23 +16,74 @@
*/
package io.cloudevents.protobuf;
import com.google.protobuf.Any;
import com.google.protobuf.Message;
import java.util.Objects;
class ProtoDataWrapper implements ProtoCloudEventData {
private final Message protoMessage;
private final Any protoAny;
ProtoDataWrapper(Message protoMessage) {
this.protoMessage = protoMessage;
Objects.requireNonNull(protoMessage);
if (protoMessage instanceof Any) {
protoAny = (Any) protoMessage;
} else {
protoAny = Any.pack(protoMessage);
}
}
@Override
public Message getMessage() {
return protoMessage;
public Any getAny() {
return protoAny;
}
@Override
public byte[] toBytes() {
return protoMessage.toByteArray();
return protoAny.toByteArray();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return (true);
}
if (!(obj instanceof ProtoDataWrapper)) {
return (false);
}
// Now compare the actual data
ProtoDataWrapper rhs = (ProtoDataWrapper) obj;
final Any lhsAny = getAny();
final Any rhsAny = rhs.getAny();
// This is split out for readability.
// 1. Sanity compare the 'Any' references.
// 2. Compare the content in terms onf an 'Any'.
// - Verify the types match
// - Verify the values match.
// NULL checks not required as object cannot be built
// with a null.
if (lhsAny == rhsAny) {
return true;
}
final boolean typesMatch = (ProtoSupport.extractMessageType(lhsAny).equals(ProtoSupport.extractMessageType(rhsAny)));
if (typesMatch) {
return lhsAny.getValue().equals(rhsAny.getValue());
} else {
return false;
}
}
}

View File

@ -16,18 +16,14 @@
*/
package io.cloudevents.protobuf;
import com.google.protobuf.Message;
import io.cloudevents.CloudEventData;
import io.cloudevents.SpecVersion;
import io.cloudevents.core.data.BytesCloudEventData;
import io.cloudevents.core.v1.CloudEventV1;
import io.cloudevents.rw.CloudEventDataMapper;
import io.cloudevents.rw.CloudEventRWException;
import io.cloudevents.rw.CloudEventReader;
import io.cloudevents.rw.CloudEventWriter;
import io.cloudevents.rw.CloudEventWriterFactory;
import io.cloudevents.rw.*;
import io.cloudevents.v1.proto.CloudEvent;
import io.cloudevents.v1.proto.CloudEvent.CloudEventAttributeValue;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
@ -105,7 +101,7 @@ class ProtoDeserializer implements CloudEventReader {
data = BytesCloudEventData.wrap(raw);
break;
case PROTO_DATA:
data = new ProtoAccessor(this.protoCe);
data = new ProtoDataWrapper(this.protoCe.getProtoData());
break;
case DATA_NOT_SET:
break;
@ -130,22 +126,4 @@ class ProtoDeserializer implements CloudEventReader {
return instant.atOffset(ZoneOffset.UTC);
}
private static class ProtoAccessor implements ProtoCloudEventData {
private final Message message;
ProtoAccessor(CloudEvent proto){
this.message = proto.getProtoData();
}
@Override
public Message getMessage() {
return message;
}
@Override
public byte[] toBytes() {
return message.toByteArray();
}
}
}

View File

@ -30,7 +30,6 @@ import io.cloudevents.rw.CloudEventContextWriter;
import io.cloudevents.rw.CloudEventRWException;
import io.cloudevents.rw.CloudEventWriter;
import io.cloudevents.v1.proto.CloudEvent;
import io.cloudevents.v1.proto.CloudEvent.*;
import java.net.URI;
import java.time.Instant;
@ -247,10 +246,20 @@ class ProtoSerializer {
// If it's a proto message we can handle that directly.
if (data instanceof ProtoCloudEventData) {
final ProtoCloudEventData protoData = (ProtoCloudEventData) data;
if (protoData.getMessage() != null) {
protoBuilder.setProtoData(Any.pack(protoData.getMessage()));
final Any anAny = protoData.getAny();
// Even though our local implementation cannot be instantiated
// with NULL data nothing stops somebody from having their own
// variant that isn't as 'safe'.
if (anAny != null) {
protoBuilder.setProtoData(anAny);
} else {
throw CloudEventRWException.newOther("ProtoCloudEventData: getAny() was NULL");
}
} else {
if (Objects.equals(dataContentType, PROTO_DATA_CONTENT_TYPE)) {
// This will throw if the data provided is not an Any. The protobuf CloudEvent spec requires proto data to be stored as

Some files were not shown because too many files have changed in this diff Show More