diff --git a/http/restful-ws-jakarta-integration-tests/restful-ws-resteasy/pom.xml b/http/restful-ws-jakarta-integration-tests/restful-ws-resteasy/pom.xml
index 1702d47c7..06e12e1f5 100644
--- a/http/restful-ws-jakarta-integration-tests/restful-ws-resteasy/pom.xml
+++ b/http/restful-ws-jakarta-integration-tests/restful-ws-resteasy/pom.xml
@@ -9,7 +9,7 @@
4.0.0
cloudevents-http-restful-ws-jakarta-integration-tests-resteasy
- CloudEvents - JAX-RS Jakarta EE9+ Integration Tests - RESTEasy
+ CloudEvents - JAX-RS Jakarta EE 9+ Integration Tests - RESTEasy
jar
diff --git a/http/restful-ws-jakarta/README.md b/http/restful-ws-jakarta/README.md
index 87e63476e..a517723cf 100644
--- a/http/restful-ws-jakarta/README.md
+++ b/http/restful-ws-jakarta/README.md
@@ -1,7 +1,7 @@
-# HTTP Protocol Binding for Jakarta EE9+ - Jakarta RESTful Web Services
+# HTTP Protocol Binding for Jakarta EE 9+ - Jakarta RESTful Web Services
-Javadocs: [](http://www.javadoc.io/doc/io.cloudevents/cloudevents-http-restful-ws)
+Javadocs: [](http://www.javadoc.io/doc/io.cloudevents/cloudevents-http-restful-ws-jakarta)
-Documentation: https://cloudevents.github.io/sdk-java/http-jakarta-restful-ws
+Documentation: https://cloudevents.github.io/sdk-java/http-jakarta-restful-ws-jakarta
The code for this package lies within the [restful-ws](https://github.com/cloudevents/sdk-java/tree/main/http/restful-ws) directory and is copied within here and has `javax.` replaced with `jakarta.`
diff --git a/http/restful-ws-jakarta/pom.xml b/http/restful-ws-jakarta/pom.xml
index 3ef8d87a9..640b1a593 100644
--- a/http/restful-ws-jakarta/pom.xml
+++ b/http/restful-ws-jakarta/pom.xml
@@ -61,37 +61,4 @@
-
-
-
- maven-antrun-plugin
- 3.1.0
-
-
- generate-sources
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- run
-
-
-
-
-
-
-
diff --git a/http/restful-ws-jakarta/src/main/java/io/cloudevents/http/restful/ws/BinaryEncoding.java b/http/restful-ws-jakarta/src/main/java/io/cloudevents/http/restful/ws/BinaryEncoding.java
new file mode 100644
index 000000000..08627f330
--- /dev/null
+++ b/http/restful-ws-jakarta/src/main/java/io/cloudevents/http/restful/ws/BinaryEncoding.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2018-Present The CloudEvents Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package io.cloudevents.http.restful.ws;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotate a method with this annotation to specify that you want to write the returned event
+ * in binary mode.
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface BinaryEncoding {
+}
diff --git a/http/restful-ws-jakarta/src/main/java/io/cloudevents/http/restful/ws/CloudEventsProvider.java b/http/restful-ws-jakarta/src/main/java/io/cloudevents/http/restful/ws/CloudEventsProvider.java
new file mode 100644
index 000000000..837004688
--- /dev/null
+++ b/http/restful-ws-jakarta/src/main/java/io/cloudevents/http/restful/ws/CloudEventsProvider.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2018-Present The CloudEvents Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package io.cloudevents.http.restful.ws;
+
+import io.cloudevents.CloudEvent;
+import io.cloudevents.core.format.EventFormat;
+import io.cloudevents.core.message.MessageWriter;
+import io.cloudevents.core.provider.EventFormatProvider;
+import io.cloudevents.http.restful.ws.impl.RestfulWSClientMessageWriter;
+import io.cloudevents.http.restful.ws.impl.RestfulWSMessageFactory;
+import io.cloudevents.http.restful.ws.impl.RestfulWSMessageWriter;
+import io.cloudevents.rw.CloudEventWriter;
+
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.ext.MessageBodyReader;
+import jakarta.ws.rs.ext.MessageBodyWriter;
+import jakarta.ws.rs.ext.Provider;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.Optional;
+
+/**
+ * This provider implements {@link CloudEvent} encoding and decoding for Jax-Rs Resources and with {@link jakarta.ws.rs.client.Client}.
+ */
+@Provider
+@Consumes(MediaType.WILDCARD)
+@Produces(MediaType.WILDCARD)
+public class CloudEventsProvider implements MessageBodyReader, MessageBodyWriter, ClientRequestFilter {
+
+ /**
+ * The content type to use when sending {@link CloudEvent} with {@link jakarta.ws.rs.client.Client}
+ */
+ public static MediaType CLOUDEVENT_TYPE = MediaType.valueOf("application/cloudevents");
+
+ @Override
+ public boolean isReadable(Class> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return CloudEvent.class.isAssignableFrom(type);
+ }
+
+ @Override
+ public CloudEvent readFrom(Class type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, InputStream entityStream) throws IOException, WebApplicationException {
+ return RestfulWSMessageFactory.create(mediaType, httpHeaders, bufferBodyInput(entityStream)).toEvent();
+ }
+
+ private byte[] bufferBodyInput(InputStream inputStream) throws IOException {
+ if (inputStream == null) {
+ return null;
+ }
+
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+
+ int nRead;
+ byte[] data = new byte[1024];
+ while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
+ buffer.write(data, 0, nRead);
+ }
+
+ buffer.flush();
+ return buffer.toByteArray();
+ }
+
+ @Override
+ public boolean isWriteable(Class> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return CloudEvent.class.isAssignableFrom(type);
+ }
+
+ @Override
+ public void writeTo(CloudEvent event, Class> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {
+ Optional structuredEncodingFormat = Arrays
+ .stream(annotations)
+ .filter(a -> a.annotationType().equals(StructuredEncoding.class))
+ .map(a -> ((StructuredEncoding) a).value())
+ .findFirst();
+
+ if (structuredEncodingFormat.isPresent()) {
+ writeStructured(
+ event,
+ structuredEncodingFormat.get(),
+ new RestfulWSMessageWriter(httpHeaders, entityStream)
+ );
+ } else {
+ writeBinary(
+ event,
+ new RestfulWSMessageWriter(httpHeaders, entityStream)
+ );
+ }
+ }
+
+ private & CloudEventWriter> void writeBinary(CloudEvent input, V visitor) {
+ visitor.writeBinary(input);
+ }
+
+ private & CloudEventWriter> void writeStructured(CloudEvent input, EventFormat format, V visitor) {
+ visitor.writeStructured(input, format);
+ }
+
+ private & CloudEventWriter> void writeStructured(CloudEvent input, String formatString, V visitor) {
+ EventFormat format = EventFormatProvider.getInstance().resolveFormat(formatString);
+
+ if (format == null) {
+ throw new IllegalArgumentException("Cannot resolve format " + formatString);
+ }
+
+ writeStructured(input, format, visitor);
+ }
+
+ @Override
+ public void filter(ClientRequestContext requestContext) throws IOException {
+ if (isCloudEventEntity(requestContext.getEntity())) {
+ EventFormat format = EventFormatProvider.getInstance().resolveFormat(requestContext.getMediaType().toString());
+
+ if (format != null) {
+ writeStructured(
+ (CloudEvent) requestContext.getEntity(),
+ format,
+ new RestfulWSClientMessageWriter(requestContext)
+ );
+ } else {
+ writeBinary(
+ (CloudEvent) requestContext.getEntity(),
+ new RestfulWSClientMessageWriter(requestContext)
+ );
+ }
+ }
+ }
+
+ private static boolean isCloudEventEntity(Object obj) {
+ return obj != null && CloudEvent.class.isAssignableFrom(obj.getClass());
+ }
+
+}
diff --git a/http/restful-ws-jakarta/src/main/java/io/cloudevents/http/restful/ws/StructuredEncoding.java b/http/restful-ws-jakarta/src/main/java/io/cloudevents/http/restful/ws/StructuredEncoding.java
new file mode 100644
index 000000000..0e98a8fe8
--- /dev/null
+++ b/http/restful-ws-jakarta/src/main/java/io/cloudevents/http/restful/ws/StructuredEncoding.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2018-Present The CloudEvents Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package io.cloudevents.http.restful.ws;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotate a method with this annotation to specify that you want to write the returned event
+ * in structured mode.
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface StructuredEncoding {
+ /**
+ * Specify the content type of the structured mode.
+ * This values will be used to resolve the {@link io.cloudevents.core.format.EventFormat} through
+ * the {@link io.cloudevents.core.provider.EventFormatProvider}.
+ */
+ String value();
+}
diff --git a/http/restful-ws-jakarta/src/main/java/io/cloudevents/http/restful/ws/impl/BinaryRestfulWSMessageReaderImpl.java b/http/restful-ws-jakarta/src/main/java/io/cloudevents/http/restful/ws/impl/BinaryRestfulWSMessageReaderImpl.java
new file mode 100644
index 000000000..bce8497b2
--- /dev/null
+++ b/http/restful-ws-jakarta/src/main/java/io/cloudevents/http/restful/ws/impl/BinaryRestfulWSMessageReaderImpl.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2018-Present The CloudEvents Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package io.cloudevents.http.restful.ws.impl;
+
+import io.cloudevents.SpecVersion;
+import io.cloudevents.core.data.BytesCloudEventData;
+import io.cloudevents.core.impl.StringUtils;
+import io.cloudevents.core.message.impl.BaseGenericBinaryMessageReaderImpl;
+
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.MultivaluedMap;
+import java.util.Objects;
+import java.util.function.BiConsumer;
+
+import static io.cloudevents.http.restful.ws.impl.CloudEventsHeaders.CE_PREFIX;
+
+public final class BinaryRestfulWSMessageReaderImpl extends BaseGenericBinaryMessageReaderImpl {
+
+ private final MultivaluedMap headers;
+
+ public BinaryRestfulWSMessageReaderImpl(SpecVersion version, MultivaluedMap headers, byte[] body) {
+ super(version, body != null && body.length > 0 ? BytesCloudEventData.wrap(body) : null);
+
+ Objects.requireNonNull(headers);
+ this.headers = headers;
+ }
+
+ @Override
+ protected boolean isContentTypeHeader(String key) {
+ return key.equalsIgnoreCase(HttpHeaders.CONTENT_TYPE);
+ }
+
+ @Override
+ protected boolean isCloudEventsHeader(String key) {
+ return key.length() > CE_PREFIX.length() && StringUtils.startsWithIgnoreCase(key, CE_PREFIX);
+ }
+
+ @Override
+ protected String toCloudEventsKey(String key) {
+ return key.substring(CE_PREFIX.length()).toLowerCase();
+ }
+
+ @Override
+ protected void forEachHeader(BiConsumer fn) {
+ this.headers.forEach((k, v) -> fn.accept(k, v.get(0)));
+ }
+
+ @Override
+ protected String toCloudEventsValue(String value) {
+ return value;
+ }
+}
diff --git a/http/restful-ws-jakarta/src/main/java/io/cloudevents/http/restful/ws/impl/CloudEventsHeaders.java b/http/restful-ws-jakarta/src/main/java/io/cloudevents/http/restful/ws/impl/CloudEventsHeaders.java
new file mode 100644
index 000000000..0bf1bfa6e
--- /dev/null
+++ b/http/restful-ws-jakarta/src/main/java/io/cloudevents/http/restful/ws/impl/CloudEventsHeaders.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2018-Present The CloudEvents Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package io.cloudevents.http.restful.ws.impl;
+
+import io.cloudevents.core.message.impl.MessageUtils;
+
+import jakarta.ws.rs.core.HttpHeaders;
+import java.util.Map;
+
+class CloudEventsHeaders {
+
+ static final String CE_PREFIX = "ce-";
+
+ static final Map ATTRIBUTES_TO_HEADERS = MessageUtils.generateAttributesToHeadersMapping(v -> {
+ if (v.equals("datacontenttype")) {
+ return HttpHeaders.CONTENT_TYPE;
+ }
+ return CE_PREFIX + v;
+ });
+
+ static final String SPEC_VERSION = ATTRIBUTES_TO_HEADERS.get("specversion");
+
+}
diff --git a/http/restful-ws-jakarta/src/main/java/io/cloudevents/http/restful/ws/impl/RestfulWSClientMessageWriter.java b/http/restful-ws-jakarta/src/main/java/io/cloudevents/http/restful/ws/impl/RestfulWSClientMessageWriter.java
new file mode 100644
index 000000000..1b69024cc
--- /dev/null
+++ b/http/restful-ws-jakarta/src/main/java/io/cloudevents/http/restful/ws/impl/RestfulWSClientMessageWriter.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2018-Present The CloudEvents Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package io.cloudevents.http.restful.ws.impl;
+
+import io.cloudevents.CloudEventData;
+import io.cloudevents.SpecVersion;
+import io.cloudevents.core.format.EventFormat;
+import io.cloudevents.core.message.MessageWriter;
+import io.cloudevents.rw.CloudEventRWException;
+import io.cloudevents.rw.CloudEventWriter;
+
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.MediaType;
+
+public final class RestfulWSClientMessageWriter implements CloudEventWriter, MessageWriter {
+
+ private final ClientRequestContext context;
+
+ public RestfulWSClientMessageWriter(ClientRequestContext context) {
+ this.context = context;
+
+ // http headers could contain a content type, so let's remove it
+ this.context.getHeaders().remove(HttpHeaders.CONTENT_TYPE);
+ this.context.setEntity(null);
+ }
+
+ @Override
+ public RestfulWSClientMessageWriter create(SpecVersion version) {
+ this.context.getHeaders().add(CloudEventsHeaders.SPEC_VERSION, version.toString());
+ return this;
+ }
+
+ @Override
+ public RestfulWSClientMessageWriter withContextAttribute(String name, String value) throws CloudEventRWException {
+ String headerName = CloudEventsHeaders.ATTRIBUTES_TO_HEADERS.get(name);
+ if (headerName == null) {
+ headerName = CloudEventsHeaders.CE_PREFIX + name;
+ }
+ this.context.getHeaders().add(headerName, value);
+ return this;
+ }
+
+ @Override
+ public Void end(CloudEventData value) throws CloudEventRWException {
+ this.context.setEntity(value.toBytes());
+ return null;
+ }
+
+ @Override
+ public Void end() {
+ return null;
+ }
+
+ @Override
+ public Void setEvent(EventFormat format, byte[] value) throws CloudEventRWException {
+ this.context.setEntity(value, null, MediaType.valueOf(format.serializedContentType()));
+ return null;
+ }
+}
diff --git a/http/restful-ws-jakarta/src/main/java/io/cloudevents/http/restful/ws/impl/RestfulWSMessageFactory.java b/http/restful-ws-jakarta/src/main/java/io/cloudevents/http/restful/ws/impl/RestfulWSMessageFactory.java
new file mode 100644
index 000000000..1de114f75
--- /dev/null
+++ b/http/restful-ws-jakarta/src/main/java/io/cloudevents/http/restful/ws/impl/RestfulWSMessageFactory.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2018-Present The CloudEvents Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package io.cloudevents.http.restful.ws.impl;
+
+import io.cloudevents.core.message.MessageReader;
+import io.cloudevents.core.message.impl.GenericStructuredMessageReader;
+import io.cloudevents.core.message.impl.MessageUtils;
+
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
+
+public final class RestfulWSMessageFactory {
+
+ private RestfulWSMessageFactory() {
+ }
+
+ public static MessageReader create(MediaType mediaType, MultivaluedMap headers, byte[] payload) throws IllegalArgumentException {
+ return MessageUtils.parseStructuredOrBinaryMessage(
+ () -> headers.getFirst(HttpHeaders.CONTENT_TYPE),
+ format -> new GenericStructuredMessageReader(format, payload),
+ () -> headers.getFirst(CloudEventsHeaders.SPEC_VERSION),
+ sv -> new BinaryRestfulWSMessageReaderImpl(sv, headers, payload)
+ );
+ }
+
+}
diff --git a/http/restful-ws-jakarta/src/main/java/io/cloudevents/http/restful/ws/impl/RestfulWSMessageWriter.java b/http/restful-ws-jakarta/src/main/java/io/cloudevents/http/restful/ws/impl/RestfulWSMessageWriter.java
new file mode 100644
index 000000000..bdc58c5d1
--- /dev/null
+++ b/http/restful-ws-jakarta/src/main/java/io/cloudevents/http/restful/ws/impl/RestfulWSMessageWriter.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2018-Present The CloudEvents Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package io.cloudevents.http.restful.ws.impl;
+
+import io.cloudevents.CloudEventData;
+import io.cloudevents.SpecVersion;
+import io.cloudevents.core.format.EventFormat;
+import io.cloudevents.core.message.MessageWriter;
+import io.cloudevents.rw.CloudEventRWException;
+import io.cloudevents.rw.CloudEventWriter;
+
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.MultivaluedMap;
+import java.io.IOException;
+import java.io.OutputStream;
+
+public final class RestfulWSMessageWriter implements CloudEventWriter, MessageWriter {
+
+ private final MultivaluedMap httpHeaders;
+ private final OutputStream entityStream;
+
+ public RestfulWSMessageWriter(MultivaluedMap httpHeaders, OutputStream entityStream) {
+ this.httpHeaders = httpHeaders;
+ this.entityStream = entityStream;
+
+ // http headers could contain a content type, so let's remove it
+ this.httpHeaders.remove(HttpHeaders.CONTENT_TYPE);
+ }
+
+ @Override
+ public RestfulWSMessageWriter create(SpecVersion version) {
+ this.httpHeaders.add(CloudEventsHeaders.SPEC_VERSION, version.toString());
+ return this;
+ }
+
+ @Override
+ public RestfulWSMessageWriter withContextAttribute(String name, String value) throws CloudEventRWException {
+ String headerName = CloudEventsHeaders.ATTRIBUTES_TO_HEADERS.get(name);
+ if (headerName == null) {
+ headerName = CloudEventsHeaders.CE_PREFIX + name;
+ }
+ this.httpHeaders.add(headerName, value);
+ return this;
+ }
+
+ @Override
+ public Void end(CloudEventData value) throws CloudEventRWException {
+ try {
+ this.entityStream.write(value.toBytes());
+ } catch (IOException e) {
+ throw CloudEventRWException.newOther(e);
+ }
+ return this.end();
+ }
+
+ @Override
+ public Void end() {
+ try {
+ this.entityStream.flush();
+ } catch (IOException e) {
+ throw CloudEventRWException.newOther(e);
+ }
+ return null;
+ }
+
+ @Override
+ public Void setEvent(EventFormat format, byte[] value) throws CloudEventRWException {
+ this.httpHeaders.add(HttpHeaders.CONTENT_TYPE, format.serializedContentType());
+ try {
+ this.entityStream.write(value);
+ } catch (IOException e) {
+ throw CloudEventRWException.newOther(e);
+ }
+ return this.end();
+ }
+}
diff --git a/http/restful-ws-jakarta/src/main/resources/META-INF/services/jakarta.ws.rs.client.ClientRequestFilter b/http/restful-ws-jakarta/src/main/resources/META-INF/services/jakarta.ws.rs.client.ClientRequestFilter
new file mode 100644
index 000000000..d70b7236c
--- /dev/null
+++ b/http/restful-ws-jakarta/src/main/resources/META-INF/services/jakarta.ws.rs.client.ClientRequestFilter
@@ -0,0 +1,17 @@
+#
+# Copyright 2018-Present The CloudEvents Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+io.cloudevents.http.restful.ws.CloudEventsProvider
diff --git a/http/restful-ws-jakarta/src/main/resources/META-INF/services/jakarta.ws.rs.ext.MessageBodyReader b/http/restful-ws-jakarta/src/main/resources/META-INF/services/jakarta.ws.rs.ext.MessageBodyReader
new file mode 100644
index 000000000..d70b7236c
--- /dev/null
+++ b/http/restful-ws-jakarta/src/main/resources/META-INF/services/jakarta.ws.rs.ext.MessageBodyReader
@@ -0,0 +1,17 @@
+#
+# Copyright 2018-Present The CloudEvents Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+io.cloudevents.http.restful.ws.CloudEventsProvider
diff --git a/http/restful-ws-jakarta/src/main/resources/META-INF/services/jakarta.ws.rs.ext.MessageBodyWriter b/http/restful-ws-jakarta/src/main/resources/META-INF/services/jakarta.ws.rs.ext.MessageBodyWriter
new file mode 100644
index 000000000..d70b7236c
--- /dev/null
+++ b/http/restful-ws-jakarta/src/main/resources/META-INF/services/jakarta.ws.rs.ext.MessageBodyWriter
@@ -0,0 +1,17 @@
+#
+# Copyright 2018-Present The CloudEvents Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+io.cloudevents.http.restful.ws.CloudEventsProvider
diff --git a/http/restful-ws-jakarta/src/main/resources/META-INF/services/jakarta.ws.rs.ext.Providers b/http/restful-ws-jakarta/src/main/resources/META-INF/services/jakarta.ws.rs.ext.Providers
new file mode 100644
index 000000000..2a284a1eb
--- /dev/null
+++ b/http/restful-ws-jakarta/src/main/resources/META-INF/services/jakarta.ws.rs.ext.Providers
@@ -0,0 +1 @@
+io.cloudevents.http.restful.ws.CloudEventsProvider
diff --git a/http/restful-ws/README.md b/http/restful-ws/README.md
index 1e6dca297..34ccf9ed3 100644
--- a/http/restful-ws/README.md
+++ b/http/restful-ws/README.md
@@ -1,5 +1,8 @@
# HTTP Protocol Binding for Jakarta RESTful Web Services
+This module is deprecated and will be removed in version 5.0.
+Please migrate to Jakarta EE 9+ and use the `cloudevents-http-restful-ws-jakarta` module instead.
+
Javadocs: [](http://www.javadoc.io/doc/io.cloudevents/cloudevents-http-restful-ws)
Documentation: https://cloudevents.github.io/sdk-java/http-jakarta-restful-ws
diff --git a/http/restful-ws/src/main/java/io/cloudevents/http/restful/ws/BinaryEncoding.java b/http/restful-ws/src/main/java/io/cloudevents/http/restful/ws/BinaryEncoding.java
index 08627f330..265316372 100644
--- a/http/restful-ws/src/main/java/io/cloudevents/http/restful/ws/BinaryEncoding.java
+++ b/http/restful-ws/src/main/java/io/cloudevents/http/restful/ws/BinaryEncoding.java
@@ -28,5 +28,6 @@
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
+@Deprecated // to be removed in version 5.0, use cloudevents-http-restful-ws-jakarta module instead
public @interface BinaryEncoding {
}
diff --git a/http/restful-ws/src/main/java/io/cloudevents/http/restful/ws/CloudEventsProvider.java b/http/restful-ws/src/main/java/io/cloudevents/http/restful/ws/CloudEventsProvider.java
index 04a60cac2..39e9d1760 100644
--- a/http/restful-ws/src/main/java/io/cloudevents/http/restful/ws/CloudEventsProvider.java
+++ b/http/restful-ws/src/main/java/io/cloudevents/http/restful/ws/CloudEventsProvider.java
@@ -51,6 +51,7 @@
@Provider
@Consumes(MediaType.WILDCARD)
@Produces(MediaType.WILDCARD)
+@Deprecated // to be removed in version 5.0, use cloudevents-http-restful-ws-jakarta module instead
public class CloudEventsProvider implements MessageBodyReader, MessageBodyWriter, ClientRequestFilter {
/**
diff --git a/http/restful-ws/src/main/java/io/cloudevents/http/restful/ws/StructuredEncoding.java b/http/restful-ws/src/main/java/io/cloudevents/http/restful/ws/StructuredEncoding.java
index 0e98a8fe8..4fd9d52a8 100644
--- a/http/restful-ws/src/main/java/io/cloudevents/http/restful/ws/StructuredEncoding.java
+++ b/http/restful-ws/src/main/java/io/cloudevents/http/restful/ws/StructuredEncoding.java
@@ -28,6 +28,7 @@
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
+@Deprecated // to be removed in version 5.0, use cloudevents-http-restful-ws-jakarta module instead
public @interface StructuredEncoding {
/**
* Specify the content type of the structured mode.
diff --git a/http/restful-ws/src/main/java/io/cloudevents/http/restful/ws/impl/BinaryRestfulWSMessageReaderImpl.java b/http/restful-ws/src/main/java/io/cloudevents/http/restful/ws/impl/BinaryRestfulWSMessageReaderImpl.java
index 15453e495..4ebb7c13b 100644
--- a/http/restful-ws/src/main/java/io/cloudevents/http/restful/ws/impl/BinaryRestfulWSMessageReaderImpl.java
+++ b/http/restful-ws/src/main/java/io/cloudevents/http/restful/ws/impl/BinaryRestfulWSMessageReaderImpl.java
@@ -29,6 +29,7 @@
import static io.cloudevents.http.restful.ws.impl.CloudEventsHeaders.CE_PREFIX;
+@Deprecated // to be removed in version 5.0, use cloudevents-http-restful-ws-jakarta module instead
public final class BinaryRestfulWSMessageReaderImpl extends BaseGenericBinaryMessageReaderImpl {
private final MultivaluedMap headers;
diff --git a/http/restful-ws/src/main/java/io/cloudevents/http/restful/ws/impl/RestfulWSClientMessageWriter.java b/http/restful-ws/src/main/java/io/cloudevents/http/restful/ws/impl/RestfulWSClientMessageWriter.java
index cfd45ef28..125a8e187 100644
--- a/http/restful-ws/src/main/java/io/cloudevents/http/restful/ws/impl/RestfulWSClientMessageWriter.java
+++ b/http/restful-ws/src/main/java/io/cloudevents/http/restful/ws/impl/RestfulWSClientMessageWriter.java
@@ -28,6 +28,7 @@
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
+@Deprecated // to be removed in version 5.0, use cloudevents-http-restful-ws-jakarta module instead
public final class RestfulWSClientMessageWriter implements CloudEventWriter, MessageWriter {
private final ClientRequestContext context;
diff --git a/http/restful-ws/src/main/java/io/cloudevents/http/restful/ws/impl/RestfulWSMessageFactory.java b/http/restful-ws/src/main/java/io/cloudevents/http/restful/ws/impl/RestfulWSMessageFactory.java
index 73a95904f..9f5c9f74d 100644
--- a/http/restful-ws/src/main/java/io/cloudevents/http/restful/ws/impl/RestfulWSMessageFactory.java
+++ b/http/restful-ws/src/main/java/io/cloudevents/http/restful/ws/impl/RestfulWSMessageFactory.java
@@ -25,6 +25,7 @@
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
+@Deprecated // to be removed in version 5.0, use cloudevents-http-restful-ws-jakarta module instead
public final class RestfulWSMessageFactory {
private RestfulWSMessageFactory() {
diff --git a/http/restful-ws/src/main/java/io/cloudevents/http/restful/ws/impl/RestfulWSMessageWriter.java b/http/restful-ws/src/main/java/io/cloudevents/http/restful/ws/impl/RestfulWSMessageWriter.java
index 1bf21df60..91abdb797 100644
--- a/http/restful-ws/src/main/java/io/cloudevents/http/restful/ws/impl/RestfulWSMessageWriter.java
+++ b/http/restful-ws/src/main/java/io/cloudevents/http/restful/ws/impl/RestfulWSMessageWriter.java
@@ -29,6 +29,7 @@
import java.io.IOException;
import java.io.OutputStream;
+@Deprecated // to be removed in version 5.0, use cloudevents-http-restful-ws-jakarta module instead
public final class RestfulWSMessageWriter implements CloudEventWriter, MessageWriter {
private final MultivaluedMap httpHeaders;