Spring Javadocs (#323)

* Spring Javadocs

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Rebase fix

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>
This commit is contained in:
Francesco Guardiani 2020-12-10 17:15:07 +01:00 committed by GitHub
parent 24d108fe5d
commit 58570cf4d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 211 additions and 210 deletions

View File

@ -158,6 +158,9 @@
<version>3.2.0</version>
<configuration>
<detectLinks/>
<links>
<link>https://docs.spring.io/spring-framework/docs/current/javadoc-api/</link>
</links>
</configuration>
<executions>
<execution>

View File

@ -15,20 +15,21 @@
*/
package io.cloudevents.spring.http;
import java.util.function.Consumer;
import java.util.function.Supplier;
import io.cloudevents.CloudEvent;
import io.cloudevents.CloudEventContext;
import io.cloudevents.SpecVersion;
import io.cloudevents.core.CloudEventUtils;
import io.cloudevents.core.builder.CloudEventBuilder;
import io.cloudevents.core.message.MessageReader;
import io.cloudevents.http.HttpMessageFactory;
import io.cloudevents.http.impl.HttpMessageWriter;
import io.cloudevents.rw.CloudEventRWException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import java.util.function.Consumer;
import java.util.function.Supplier;
/**
* Miscellaneous utility methods to assist with Cloud Events in the context of Spring Web
* frameworks. Primarily intended for the internal use within Spring-based frameworks or
@ -43,13 +44,14 @@ public class CloudEventHttpUtils {
}
/**
* Create a {@link MessageReader} to assist in conversion of an HTTP request to a
* {@link CloudEvent}.
* Create a {@link MessageReader} to convert an HTTP request to a {@link CloudEvent}.
*
* @param headers the HTTP request headers
* @param body the HTTP request body as a byte array
* @return a {@link MessageReader} representing the {@link CloudEvent}
* @throws CloudEventRWException if something goes wrong while resolving the {@link SpecVersion} or if the message has unknown encoding
*/
public static MessageReader toReader(HttpHeaders headers, Supplier<byte[]> body) {
public static MessageReader toReader(HttpHeaders headers, Supplier<byte[]> body) throws CloudEventRWException {
return HttpMessageFactory.createReaderFromMultimap(headers, body.get());
}
@ -57,6 +59,7 @@ public class CloudEventHttpUtils {
* Create an {@link HttpMessageWriter} that can hand off a {@link CloudEvent} to an
* HTTP response. Mainly useful in a blocking (not async) setting because the response
* body has to be consumed directly.
*
* @param headers the response headers (will be mutated)
* @param sendBody a consumer for the response body that puts the bytes on the wire
*/
@ -66,12 +69,14 @@ public class CloudEventHttpUtils {
/**
* Helper method for extracting {@link HttpHeaders} from a {@link CloudEvent}. Can,
* for instance, be used in a <code>&#64;RequestMapping</code> to return a
* for instance, be used in a {@link org.springframework.web.bind.annotation.RequestMapping} to return a
* {@link ResponseEntity} that has headers copied from a {@link CloudEvent}.
*
* @param event the input {@link CloudEvent}
* @return the response headers represented by the event
* @throws CloudEventRWException if something goes wrong while writing the context to the http headers
*/
public static HttpHeaders toHttp(CloudEventContext event) {
public static HttpHeaders toHttp(CloudEventContext event) throws CloudEventRWException {
HttpHeaders headers = new HttpHeaders();
CloudEventUtils.toReader(CloudEventBuilder.fromContext(event).build()).read(toWriter(headers, bytes -> {
}));
@ -80,14 +85,14 @@ public class CloudEventHttpUtils {
/**
* Helper method for converting {@link HttpHeaders} to a {@link CloudEvent}. The input
* headers must represent a valid event in "binary" form, i.e. it must have headers
* "ce-id", "ce-specversion" etc.
* @param headers the input request headers
* @return a {@link CloudEventBuilder} that can be used to create a new
* {@link CloudEvent}
* headers <b>must</b> represent a valid event in "binary" form, i.e. it must have headers
* {@code ce-id}, {@code ce-specversion} etc.
*
* @param headers the input request headers
* @return a {@link CloudEventBuilder} that can be used to create a new {@link CloudEvent}
* @throws CloudEventRWException if something goes wrong while reading the context from the http headers
*/
public static CloudEventBuilder fromHttp(HttpHeaders headers) {
public static CloudEventBuilder fromHttp(HttpHeaders headers) throws CloudEventRWException {
return CloudEventBuilder
.fromContext(CloudEventUtils.toEvent(CloudEventHttpUtils.toReader(headers, () -> null)));
}

View File

@ -0,0 +1,70 @@
/*
* Copyright 2019-2019 the original author or 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
*
* https://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.spring.messaging;
import io.cloudevents.CloudEvent;
import io.cloudevents.CloudEventContext;
import io.cloudevents.SpecVersion;
import io.cloudevents.core.CloudEventUtils;
import io.cloudevents.rw.CloudEventRWException;
import org.springframework.messaging.MessageHeaders;
import java.util.HashMap;
import java.util.Map;
import static io.cloudevents.spring.messaging.CloudEventsHeaders.CE_PREFIX;
/**
* Utility class for copying message headers to and from {@link CloudEventContext}.
*
* @author Dave Syer
*/
public class CloudEventContextUtils {
/**
* Helper method for converting {@link MessageHeaders} to a {@link CloudEventContext}.
* The input headers <b>must</b> represent a valid event in "binary" form, i.e. it must have headers
* {@code ce-id}, {@code ce-specversion} etc.
*
* @param headers the input message headers
* @return a {@link CloudEventContext} that can be used to create a new {@link CloudEvent}
* @throws CloudEventRWException if something goes wrong while converting the headers to {@link CloudEventContext}
*/
public static CloudEventContext fromMap(Map<String, Object> headers) throws CloudEventRWException {
Object value = headers.get(CloudEventsHeaders.SPEC_VERSION);
SpecVersion version = value == null ? SpecVersion.V1 : SpecVersion.parse(value.toString());
return CloudEventUtils.toEvent(new MessageBinaryMessageReader(version, headers));
}
/**
* Helper method for extracting {@link MessageHeaders} from a {@link CloudEventContext}. The
* result will contain headers canonicalized with a {@code ce-} prefix, analogous to the
* "binary" message format in Cloud Events.
*
* @param context the input {@link CloudEventContext}
* @return the response headers represented by the event
* @throws CloudEventRWException if something goes wrong while converting the {@link CloudEventContext} to headers
*/
public static Map<String, Object> toMap(CloudEventContext context) throws CloudEventRWException {
Map<String, Object> headers = new HashMap<>();
// Probably this should be done in CloudEventContextReaderAdapter
headers.put(CE_PREFIX + "specversion", context.getSpecVersion().toString());
MessageBuilderMessageWriter writer = new MessageBuilderMessageWriter(headers);
CloudEventUtils.toContextReader(context).readContext(writer);
return writer.end().getHeaders();
}
}

View File

@ -1,69 +0,0 @@
/*
* Copyright 2019-2019 the original author or 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
*
* https://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.spring.messaging;
import java.util.HashMap;
import java.util.Map;
import io.cloudevents.CloudEvent;
import io.cloudevents.CloudEventContext;
import io.cloudevents.SpecVersion;
import io.cloudevents.core.CloudEventUtils;
import org.springframework.messaging.MessageHeaders;
import static io.cloudevents.spring.messaging.CloudEventsHeaders.CE_PREFIX;
/**
* Utility class for copying message headers to and from {@link CloudEventContext}.
*
* @author Dave Syer
*
*/
public class CloudEventHeaderUtils {
/**
* Helper method for converting {@link MessageHeaders} to a {@link CloudEventContext}.
* The input headers must represent a valid event in "binary" form, i.e. it must have
* headers "ce-id", "ce-specversion" etc.
* @param headers the input request headers
* @return a {@link CloudEventContext} that can be used to create a new
* {@link CloudEvent}
*
*/
public static CloudEventContext fromMap(Map<String, Object> headers) {
Object value = headers.get(CloudEventsHeaders.SPEC_VERSION);
SpecVersion version = value == null ? SpecVersion.V1 : SpecVersion.parse(value.toString());
return CloudEventUtils.toEvent(new MessageBinaryMessageReader(version, headers));
}
/**
* Helper method for extracting {@link MessageHeaders} from a
* {@link CloudEventContext}. The result will contain headers canonicalized with a
* "ce-" prefix, analogous to the "binary" message format in Cloud Events.
* @param event the input {@link CloudEventContext}
* @return the response headers represented by the event
*/
public static Map<String, Object> toMap(CloudEventContext event) {
Map<String, Object> headers = new HashMap<>();
// Probably this should be done in CloudEventContextReaderAdapter
headers.put(CE_PREFIX + "specversion", event.getSpecVersion().toString());
MessageBuilderMessageWriter writer = new MessageBuilderMessageWriter(headers);
CloudEventUtils.toContextReader(event).readContext(writer);
return writer.end().getHeaders();
}
}

View File

@ -15,8 +15,6 @@
*/
package io.cloudevents.spring.messaging;
import java.nio.charset.Charset;
import io.cloudevents.CloudEvent;
import io.cloudevents.CloudEventContext;
import io.cloudevents.SpecVersion;
@ -25,19 +23,19 @@ import io.cloudevents.core.format.EventFormat;
import io.cloudevents.core.message.MessageReader;
import io.cloudevents.core.message.impl.GenericStructuredMessageReader;
import io.cloudevents.core.message.impl.MessageUtils;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.converter.MessageConverter;
import java.nio.charset.Charset;
/**
* A {@link MessageConverter} that can translate to and from a {@link Message
* Message&lt;byte[]>} or {@link Message Message&lt;String>} and a {@link CloudEvent}. The
* {@link CloudEventContext} is canonicalized, with key names given a "ce-" prefix in the
* {@link CloudEventContext} is canonicalized, with key names given a {@code ce-} prefix in the
* {@link MessageHeaders}.
*
* @author Dave Syer
*
*/
public class CloudEventMessageConverter implements MessageConverter {

View File

@ -15,12 +15,9 @@
*/
package io.cloudevents.spring.mvc;
import java.io.IOException;
import io.cloudevents.CloudEvent;
import io.cloudevents.core.CloudEventUtils;
import io.cloudevents.spring.http.CloudEventHttpUtils;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
@ -30,13 +27,14 @@ import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.util.StreamUtils;
import java.io.IOException;
/**
* An {@link HttpMessageConverter} for {@link CloudEvent CloudEvents}. Supports the use of
* {@link CloudEvent} in a <code>&#64;RequestMapping</code> as either a method parameter
* {@link CloudEvent} in a {@link org.springframework.web.bind.annotation.RequestMapping} as either a method parameter
* or a return value.
*
* @author Dave Syer
*
*/
public class CloudEventHttpMessageConverter extends AbstractHttpMessageConverter<CloudEvent> {

View File

@ -15,16 +15,9 @@
*/
package io.cloudevents.spring.webflux;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import io.cloudevents.CloudEvent;
import io.cloudevents.core.message.MessageReader;
import io.cloudevents.spring.http.CloudEventHttpUtils;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.core.ResolvableType;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpHeaders;
@ -32,14 +25,19 @@ import org.springframework.http.MediaType;
import org.springframework.http.ReactiveHttpInputMessage;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.util.StreamUtils;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* A reactive {@link HttpMessageReader} for {@link CloudEvent CloudEvents}, converting
* from an HTTP request to a cloud event. Supports the use of {@link CloudEvent} as an
* from an HTTP request to a CloudEvent. Supports the use of {@link CloudEvent} as an
* input to a reactive endpoint.
*
* @author Dave Syer
*
*/
public class CloudEventHttpMessageReader implements HttpMessageReader<CloudEvent> {

View File

@ -40,11 +40,10 @@ import java.util.Map;
/**
* A reactive {@link HttpMessageWriter} for {@link CloudEvent CloudEvents}, converting
* from a cloud event to an HTTP response. Supports the use of {@link CloudEvent} as an
* from a CloudEvent to an HTTP response. Supports the use of {@link CloudEvent} as an
* output from a reactive endpoint.
*
* @author Dave Syer
*
*/
public class CloudEventHttpMessageWriter implements HttpMessageWriter<CloudEvent> {

View File

@ -0,0 +1,75 @@
package io.cloudevents.spring.messaging;
import io.cloudevents.CloudEvent;
import io.cloudevents.CloudEventContext;
import io.cloudevents.SpecVersion;
import io.cloudevents.core.builder.CloudEventBuilder;
import io.cloudevents.rw.CloudEventRWException;
import org.junit.jupiter.api.Test;
import org.springframework.messaging.MessageHeaders;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
public class CloudEventContextUtilsTests {
@Test
public void testWithEmpty() {
Map<String, Object> headers = new HashMap<>();
assertThatExceptionOfType(CloudEventRWException.class).isThrownBy(() -> {
CloudEventContext attributes = CloudEventContextUtils.fromMap(new MessageHeaders(headers));
assertThat(attributes.getSpecVersion()).isEqualTo(SpecVersion.V1);
assertThat(attributes.getId()).isNull();
assertThat(attributes.getSource()).isNull();
assertThat(attributes.getType()).isNull();
});
}
@Test
public void testWithPrefix() {
Map<String, Object> headers = new HashMap<>();
headers.put("ce-scpecversion", "1.0");
headers.put("ce-id", "A234-1234-1234");
headers.put("ce-source", "https://spring.io/");
headers.put("ce-type", "org.springframework");
headers.put("ce-datacontenttype", "application/json");
CloudEventContext attributes = CloudEventContextUtils.fromMap(new MessageHeaders(headers));
assertThat(attributes.getSpecVersion()).isEqualTo(SpecVersion.V1);
assertThat(attributes.getId()).isEqualTo("A234-1234-1234");
assertThat(attributes.getSource()).isEqualTo(URI.create("https://spring.io/"));
assertThat(attributes.getType()).isEqualTo("org.springframework");
assertThat(attributes.getDataContentType()).isEqualTo("application/json");
}
@Test
public void testExtensionsWithPrefix() {
Map<String, Object> headers = new HashMap<>();
headers.put("ce-scpecversion", "1.0");
headers.put("ce-id", "A234-1234-1234");
headers.put("ce-source", "https://spring.io/");
headers.put("ce-type", "org.springframework");
headers.put("ce-foo", "bar");
CloudEventContext attributes = CloudEventContextUtils.fromMap(new MessageHeaders(headers));
assertThat(attributes.getSpecVersion()).isEqualTo(SpecVersion.V1);
assertThat(attributes.getId()).isEqualTo("A234-1234-1234");
assertThat(attributes.getSource()).isEqualTo(URI.create("https://spring.io/"));
assertThat(attributes.getType()).isEqualTo("org.springframework");
assertThat(attributes.getExtension("foo")).isEqualTo("bar");
}
@Test
public void testToHeaders() {
CloudEvent attributes = CloudEventBuilder.v1().withId("A234-1234-1234")
.withSource(URI.create("https://spring.io/")).withType("org.springframework").build();
Map<String, ?> headers = CloudEventContextUtils.toMap(attributes);
assertThat(headers.get("ce-id")).isEqualTo("A234-1234-1234");
assertThat(headers.get("ce-specversion")).isEqualTo("1.0");
assertThat(headers.get("ce-source")).isEqualTo("https://spring.io/");
assertThat(headers.get("ce-type")).isEqualTo("org.springframework");
}
}

View File

@ -1,76 +0,0 @@
package io.cloudevents.spring.messaging;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import io.cloudevents.CloudEvent;
import io.cloudevents.CloudEventContext;
import io.cloudevents.SpecVersion;
import io.cloudevents.core.builder.CloudEventBuilder;
import io.cloudevents.rw.CloudEventRWException;
import org.junit.jupiter.api.Test;
import org.springframework.messaging.MessageHeaders;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
public class CloudEventHeaderUtilsTests {
@Test
public void testWithEmpty() {
Map<String, Object> headers = new HashMap<>();
assertThatExceptionOfType(CloudEventRWException.class).isThrownBy(() -> {
CloudEventContext attributes = CloudEventHeaderUtils.fromMap(new MessageHeaders(headers));
assertThat(attributes.getSpecVersion()).isEqualTo(SpecVersion.V1);
assertThat(attributes.getId()).isNull();
assertThat(attributes.getSource()).isNull();
assertThat(attributes.getType()).isNull();
});
}
@Test
public void testWithPrefix() {
Map<String, Object> headers = new HashMap<>();
headers.put("ce-scpecversion", "1.0");
headers.put("ce-id", "A234-1234-1234");
headers.put("ce-source", "https://spring.io/");
headers.put("ce-type", "org.springframework");
headers.put("ce-datacontenttype", "application/json");
CloudEventContext attributes = CloudEventHeaderUtils.fromMap(new MessageHeaders(headers));
assertThat(attributes.getSpecVersion()).isEqualTo(SpecVersion.V1);
assertThat(attributes.getId()).isEqualTo("A234-1234-1234");
assertThat(attributes.getSource()).isEqualTo(URI.create("https://spring.io/"));
assertThat(attributes.getType()).isEqualTo("org.springframework");
assertThat(attributes.getDataContentType()).isEqualTo("application/json");
}
@Test
public void testExtensionsWithPrefix() {
Map<String, Object> headers = new HashMap<>();
headers.put("ce-scpecversion", "1.0");
headers.put("ce-id", "A234-1234-1234");
headers.put("ce-source", "https://spring.io/");
headers.put("ce-type", "org.springframework");
headers.put("ce-foo", "bar");
CloudEventContext attributes = CloudEventHeaderUtils.fromMap(new MessageHeaders(headers));
assertThat(attributes.getSpecVersion()).isEqualTo(SpecVersion.V1);
assertThat(attributes.getId()).isEqualTo("A234-1234-1234");
assertThat(attributes.getSource()).isEqualTo(URI.create("https://spring.io/"));
assertThat(attributes.getType()).isEqualTo("org.springframework");
assertThat(attributes.getExtension("foo")).isEqualTo("bar");
}
@Test
public void testToHeaders() {
CloudEvent attributes = CloudEventBuilder.v1().withId("A234-1234-1234")
.withSource(URI.create("https://spring.io/")).withType("org.springframework").build();
Map<String, ?> headers = CloudEventHeaderUtils.toMap(attributes);
assertThat(headers.get("ce-id")).isEqualTo("A234-1234-1234");
assertThat(headers.get("ce-specversion")).isEqualTo("1.0");
assertThat(headers.get("ce-source")).isEqualTo("https://spring.io/");
assertThat(headers.get("ce-type")).isEqualTo("org.springframework");
}
}