Added checkstyle
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
* Copyright 2017-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.
|
||||
@@ -47,18 +47,19 @@ public class ParsedSchema {
|
||||
}
|
||||
|
||||
public Schema getSchema() {
|
||||
return schema;
|
||||
return this.schema;
|
||||
}
|
||||
|
||||
public String getRepresentation() {
|
||||
return representation;
|
||||
return this.representation;
|
||||
}
|
||||
|
||||
public SchemaRegistrationResponse getRegistration() {
|
||||
return registration;
|
||||
return this.registration;
|
||||
}
|
||||
|
||||
public void setRegistration(SchemaRegistrationResponse registration) {
|
||||
this.registration = registration;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2016-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.
|
||||
@@ -24,4 +24,5 @@ public class SchemaNotFoundException extends RuntimeException {
|
||||
public SchemaNotFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2016-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.
|
||||
@@ -20,6 +20,7 @@ import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* References a schema through its subject and version.
|
||||
*
|
||||
* @author Marius Bogoevici
|
||||
*/
|
||||
public class SchemaReference {
|
||||
@@ -97,10 +98,8 @@ public class SchemaReference {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SchemaReference{" +
|
||||
"subject='" + this.subject + '\'' +
|
||||
", version=" + this.version +
|
||||
", format='" + this.format + '\'' +
|
||||
'}';
|
||||
return "SchemaReference{" + "subject='" + this.subject + '\'' + ", version="
|
||||
+ this.version + ", format='" + this.format + '\'' + '}';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2016-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.
|
||||
@@ -40,4 +40,5 @@ public class SchemaRegistrationResponse {
|
||||
public void setSchemaReference(SchemaReference schemaReference) {
|
||||
this.schemaReference = schemaReference;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ import org.springframework.util.MimeType;
|
||||
/**
|
||||
* Base class for Apache Avro
|
||||
* {@link org.springframework.messaging.converter.MessageConverter} implementations.
|
||||
*
|
||||
* @author Marius Bogoevici
|
||||
* @author Vinicius Carvalho
|
||||
* @author Sercan Karaoglu
|
||||
@@ -73,11 +74,13 @@ public abstract class AbstractAvroMessageConverter extends AbstractMessageConver
|
||||
|
||||
@Override
|
||||
protected boolean canConvertFrom(Message<?> message, Class<?> targetClass) {
|
||||
return super.canConvertFrom(message, targetClass) && (message.getPayload() instanceof byte[]);
|
||||
return super.canConvertFrom(message, targetClass)
|
||||
&& (message.getPayload() instanceof byte[]);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object convertFromInternal(Message<?> message, Class<?> targetClass, Object conversionHint) {
|
||||
protected Object convertFromInternal(Message<?> message, Class<?> targetClass,
|
||||
Object conversionHint) {
|
||||
Object result = null;
|
||||
try {
|
||||
byte[] payload = (byte[]) message.getPayload();
|
||||
@@ -96,7 +99,8 @@ public abstract class AbstractAvroMessageConverter extends AbstractMessageConver
|
||||
Schema readerSchema = resolveReaderSchemaForDeserialization(targetClass);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
DatumReader<Object> reader = getDatumReader((Class<Object>) targetClass, readerSchema, writerSchema);
|
||||
DatumReader<Object> reader = getDatumReader((Class<Object>) targetClass,
|
||||
readerSchema, writerSchema);
|
||||
Decoder decoder = DecoderFactory.get().binaryDecoder(payload, null);
|
||||
result = reader.read(null, decoder);
|
||||
}
|
||||
@@ -132,7 +136,8 @@ public abstract class AbstractAvroMessageConverter extends AbstractMessageConver
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
protected DatumReader<Object> getDatumReader(Class<Object> type, Schema schema, Schema writerSchema) {
|
||||
protected DatumReader<Object> getDatumReader(Class<Object> type, Schema schema,
|
||||
Schema writerSchema) {
|
||||
DatumReader<Object> reader = null;
|
||||
if (SpecificRecord.class.isAssignableFrom(type)) {
|
||||
if (schema != null) {
|
||||
@@ -167,15 +172,15 @@ public abstract class AbstractAvroMessageConverter extends AbstractMessageConver
|
||||
}
|
||||
}
|
||||
if (reader == null) {
|
||||
throw new MessageConversionException(
|
||||
"No schema can be inferred from type " + type
|
||||
.getName() + " and no schema has been explicitly configured.");
|
||||
throw new MessageConversionException("No schema can be inferred from type "
|
||||
+ type.getName() + " and no schema has been explicitly configured.");
|
||||
}
|
||||
return reader;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object convertToInternal(Object payload, MessageHeaders headers, Object conversionHint) {
|
||||
protected Object convertToInternal(Object payload, MessageHeaders headers,
|
||||
Object conversionHint) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try {
|
||||
MimeType hintedContentType = null;
|
||||
@@ -184,7 +189,8 @@ public abstract class AbstractAvroMessageConverter extends AbstractMessageConver
|
||||
}
|
||||
Schema schema = resolveSchemaForWriting(payload, headers, hintedContentType);
|
||||
@SuppressWarnings("unchecked")
|
||||
DatumWriter<Object> writer = getDatumWriter((Class<Object>) payload.getClass(), schema);
|
||||
DatumWriter<Object> writer = getDatumWriter(
|
||||
(Class<Object>) payload.getClass(), schema);
|
||||
Encoder encoder = EncoderFactory.get().binaryEncoder(baos, null);
|
||||
writer.write(payload, encoder);
|
||||
encoder.flush();
|
||||
@@ -195,10 +201,11 @@ public abstract class AbstractAvroMessageConverter extends AbstractMessageConver
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
protected abstract Schema resolveSchemaForWriting(Object payload, MessageHeaders headers,
|
||||
MimeType hintedContentType);
|
||||
protected abstract Schema resolveSchemaForWriting(Object payload,
|
||||
MessageHeaders headers, MimeType hintedContentType);
|
||||
|
||||
protected abstract Schema resolveWriterSchemaForDeserialization(MimeType mimeType);
|
||||
|
||||
protected abstract Schema resolveReaderSchemaForDeserialization(Class<?> targetClass);
|
||||
|
||||
}
|
||||
|
||||
@@ -53,7 +53,8 @@ public class AvroMessageConverterAutoConfiguration {
|
||||
@StreamMessageConverter
|
||||
public AvroSchemaRegistryClientMessageConverter avroSchemaMessageConverter(
|
||||
SchemaRegistryClient schemaRegistryClient) {
|
||||
AvroSchemaRegistryClientMessageConverter avroSchemaRegistryClientMessageConverter = new AvroSchemaRegistryClientMessageConverter(
|
||||
AvroSchemaRegistryClientMessageConverter avroSchemaRegistryClientMessageConverter;
|
||||
avroSchemaRegistryClientMessageConverter = new AvroSchemaRegistryClientMessageConverter(
|
||||
schemaRegistryClient, cacheManager());
|
||||
avroSchemaRegistryClientMessageConverter.setDynamicSchemaGenerationEnabled(
|
||||
this.avroMessageConverterProperties.isDynamicSchemaGenerationEnabled());
|
||||
@@ -61,28 +62,32 @@ public class AvroMessageConverterAutoConfiguration {
|
||||
avroSchemaRegistryClientMessageConverter.setReaderSchema(
|
||||
this.avroMessageConverterProperties.getReaderSchema());
|
||||
}
|
||||
if (!ObjectUtils.isEmpty(this.avroMessageConverterProperties.getSchemaLocations())) {
|
||||
if (!ObjectUtils
|
||||
.isEmpty(this.avroMessageConverterProperties.getSchemaLocations())) {
|
||||
avroSchemaRegistryClientMessageConverter.setSchemaLocations(
|
||||
this.avroMessageConverterProperties.getSchemaLocations());
|
||||
}
|
||||
if (!ObjectUtils.isEmpty(this.avroMessageConverterProperties.getSchemaImports())) {
|
||||
if (!ObjectUtils
|
||||
.isEmpty(this.avroMessageConverterProperties.getSchemaImports())) {
|
||||
avroSchemaRegistryClientMessageConverter.setSchemaImports(
|
||||
this.avroMessageConverterProperties.getSchemaImports());
|
||||
}
|
||||
avroSchemaRegistryClientMessageConverter.setPrefix(this.avroMessageConverterProperties.getPrefix());
|
||||
avroSchemaRegistryClientMessageConverter
|
||||
.setPrefix(this.avroMessageConverterProperties.getPrefix());
|
||||
|
||||
try {
|
||||
Class<?> clazz = this.avroMessageConverterProperties.getSubjectNamingStrategy();
|
||||
Class<?> clazz = this.avroMessageConverterProperties
|
||||
.getSubjectNamingStrategy();
|
||||
Constructor constructor = ReflectionUtils.accessibleConstructor(clazz);
|
||||
|
||||
avroSchemaRegistryClientMessageConverter.setSubjectNamingStrategy(
|
||||
(SubjectNamingStrategy) constructor.newInstance()
|
||||
);
|
||||
} catch (Exception ex) {
|
||||
throw new IllegalStateException("Unable to create SubjectNamingStrategy " +
|
||||
this.avroMessageConverterProperties.getSubjectNamingStrategy().toString(),
|
||||
ex
|
||||
);
|
||||
(SubjectNamingStrategy) constructor.newInstance());
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException("Unable to create SubjectNamingStrategy "
|
||||
+ this.avroMessageConverterProperties.getSubjectNamingStrategy()
|
||||
.toString(),
|
||||
ex);
|
||||
}
|
||||
|
||||
return avroSchemaRegistryClientMessageConverter;
|
||||
@@ -93,4 +98,5 @@ public class AvroMessageConverterAutoConfiguration {
|
||||
public CacheManager cacheManager() {
|
||||
return new ConcurrentMapCacheManager();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,17 +32,17 @@ public class AvroMessageConverterProperties {
|
||||
private Resource readerSchema;
|
||||
|
||||
/**
|
||||
* The source directory of Apache Avro schema. This schema is used by this
|
||||
* converter. If this schema depends on other schemas consider defining those
|
||||
* those dependent ones in the {@link #schemaImports}
|
||||
* The source directory of Apache Avro schema. This schema is used by this converter.
|
||||
* If this schema depends on other schemas consider defining those those dependent
|
||||
* ones in the {@link #schemaImports}
|
||||
* @parameter
|
||||
*/
|
||||
private Resource[] schemaLocations;
|
||||
|
||||
/**
|
||||
* A list of files or directories that should be loaded first thus making
|
||||
* them importable by subsequent schemas. Note that imported files
|
||||
* should not reference each other.
|
||||
* A list of files or directories that should be loaded first thus making them
|
||||
* importable by subsequent schemas. Note that imported files should not reference
|
||||
* each other.
|
||||
* @parameter
|
||||
*/
|
||||
private Resource[] schemaImports;
|
||||
@@ -73,7 +73,8 @@ public class AvroMessageConverterProperties {
|
||||
return this.dynamicSchemaGenerationEnabled;
|
||||
}
|
||||
|
||||
public void setDynamicSchemaGenerationEnabled(boolean dynamicSchemaGenerationEnabled) {
|
||||
public void setDynamicSchemaGenerationEnabled(
|
||||
boolean dynamicSchemaGenerationEnabled) {
|
||||
this.dynamicSchemaGenerationEnabled = dynamicSchemaGenerationEnabled;
|
||||
}
|
||||
|
||||
@@ -86,16 +87,17 @@ public class AvroMessageConverterProperties {
|
||||
}
|
||||
|
||||
public Class<?> getSubjectNamingStrategy() {
|
||||
return subjectNamingStrategy;
|
||||
return this.subjectNamingStrategy;
|
||||
}
|
||||
|
||||
public void setSubjectNamingStrategy(Class<? extends SubjectNamingStrategy> subjectNamingStrategy) {
|
||||
public void setSubjectNamingStrategy(
|
||||
Class<? extends SubjectNamingStrategy> subjectNamingStrategy) {
|
||||
Assert.notNull(subjectNamingStrategy, "cannot be null");
|
||||
this.subjectNamingStrategy = subjectNamingStrategy;
|
||||
}
|
||||
|
||||
public Resource[] getSchemaImports() {
|
||||
return schemaImports;
|
||||
return this.schemaImports;
|
||||
}
|
||||
|
||||
public void setSchemaImports(Resource[] schemaImports) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2016-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.
|
||||
@@ -32,6 +32,7 @@ import org.springframework.util.MimeType;
|
||||
* class for {@link org.apache.avro.specific.SpecificRecord} and regular classes, unless a
|
||||
* specific schema is set, case in which that schema will be used instead. For converting
|
||||
* to {@link org.apache.avro.generic.GenericRecord} targets, a schema must be set.s
|
||||
*
|
||||
* @author Marius Bogoevici
|
||||
*/
|
||||
|
||||
@@ -50,6 +51,8 @@ public class AvroSchemaMessageConverter extends AbstractAvroMessageConverter {
|
||||
/**
|
||||
* Create a {@link AvroSchemaMessageConverter}. The converter will be used for the
|
||||
* provided {@link MimeType}.
|
||||
* @param supportedMimeType mime type to be supported by
|
||||
* {@link AvroSchemaMessageConverter}
|
||||
*/
|
||||
public AvroSchemaMessageConverter(MimeType supportedMimeType) {
|
||||
super(supportedMimeType);
|
||||
@@ -111,4 +114,5 @@ public class AvroSchemaMessageConverter extends AbstractAvroMessageConverter {
|
||||
MimeType hintedContentType) {
|
||||
return this.schema;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.cloud.stream.schema.avro;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
@@ -78,27 +77,51 @@ import org.springframework.util.ObjectUtils;
|
||||
public class AvroSchemaRegistryClientMessageConverter extends AbstractAvroMessageConverter
|
||||
implements InitializingBean {
|
||||
|
||||
/**
|
||||
* Avro format defined in the Mime type.
|
||||
*/
|
||||
public static final String AVRO_FORMAT = "avro";
|
||||
|
||||
/**
|
||||
* Pattern for validating the prefix to be used in the publised subtype.
|
||||
*/
|
||||
public static final Pattern PREFIX_VALIDATION_PATTERN = Pattern
|
||||
.compile("[\\p{Alnum}]");
|
||||
|
||||
/**
|
||||
* Spring Cloud Stream schema property prefix.
|
||||
*/
|
||||
public static final String CACHE_PREFIX = "org.springframework.cloud.stream.schema";
|
||||
|
||||
/**
|
||||
* Property for reflection cache.
|
||||
*/
|
||||
public static final String REFLECTION_CACHE_NAME = CACHE_PREFIX + ".reflectionCache";
|
||||
|
||||
/**
|
||||
* Property for schema cache.
|
||||
*/
|
||||
public static final String SCHEMA_CACHE_NAME = CACHE_PREFIX + ".schemaCache";
|
||||
|
||||
/**
|
||||
* Property for reference cache.
|
||||
*/
|
||||
public static final String REFERENCE_CACHE_NAME = CACHE_PREFIX + ".referenceCache";
|
||||
|
||||
public static final MimeType DEFAULT_AVRO_MIME_TYPE = new MimeType("application", "*+" + AVRO_FORMAT);
|
||||
/**
|
||||
* Default Mime type for Avro.
|
||||
*/
|
||||
public static final MimeType DEFAULT_AVRO_MIME_TYPE = new MimeType("application",
|
||||
"*+" + AVRO_FORMAT);
|
||||
|
||||
private final CacheManager cacheManager;
|
||||
|
||||
protected Resource[] schemaImports = new Resource[] {};
|
||||
|
||||
private Pattern versionedSchema;
|
||||
|
||||
private boolean dynamicSchemaGenerationEnabled;
|
||||
|
||||
private final CacheManager cacheManager;
|
||||
|
||||
private Schema readerSchema;
|
||||
|
||||
private Resource[] schemaLocations;
|
||||
@@ -109,8 +132,6 @@ public class AvroSchemaRegistryClientMessageConverter extends AbstractAvroMessag
|
||||
|
||||
private SubjectNamingStrategy subjectNamingStrategy;
|
||||
|
||||
protected Resource[] schemaImports = new Resource[]{};
|
||||
|
||||
/**
|
||||
* Creates a new instance, configuring it with {@link SchemaRegistryClient} and
|
||||
* {@link CacheManager}.
|
||||
@@ -119,7 +140,8 @@ public class AvroSchemaRegistryClientMessageConverter extends AbstractAvroMessag
|
||||
* @param cacheManager instance of {@link CacheManager} to cache parsed schemas. If
|
||||
* caching is not required use {@link NoOpCacheManager}
|
||||
*/
|
||||
public AvroSchemaRegistryClientMessageConverter(SchemaRegistryClient schemaRegistryClient, CacheManager cacheManager) {
|
||||
public AvroSchemaRegistryClientMessageConverter(
|
||||
SchemaRegistryClient schemaRegistryClient, CacheManager cacheManager) {
|
||||
super(Collections.singletonList(DEFAULT_AVRO_MIME_TYPE));
|
||||
Assert.notNull(schemaRegistryClient, "cannot be null");
|
||||
Assert.notNull(cacheManager, "'cacheManager' cannot be null");
|
||||
@@ -144,8 +166,7 @@ public class AvroSchemaRegistryClientMessageConverter extends AbstractAvroMessag
|
||||
/**
|
||||
* A set of locations where the converter can load schemas from. Schemas provided at
|
||||
* these locations will be registered automatically.
|
||||
*
|
||||
* @param schemaLocations
|
||||
* @param schemaLocations array of locations
|
||||
*/
|
||||
public void setSchemaLocations(Resource[] schemaLocations) {
|
||||
Assert.notEmpty(schemaLocations, "cannot be empty");
|
||||
@@ -155,16 +176,15 @@ public class AvroSchemaRegistryClientMessageConverter extends AbstractAvroMessag
|
||||
/**
|
||||
* A set of schema locations where should be imported first. Schemas provided at these
|
||||
* locations will be reference, thus they should not reference each other.
|
||||
*
|
||||
* @param schemaImports
|
||||
* @param schemaImports array of schema imports
|
||||
*/
|
||||
public void setSchemaImports(Resource[] schemaImports) {
|
||||
this.schemaImports = schemaImports;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the prefix to be used in the publised subtype. Default 'vnd'.
|
||||
* @param prefix
|
||||
* Set the prefix to be used in the published subtype. Default 'vnd'.
|
||||
* @param prefix prefix to be set
|
||||
*/
|
||||
public void setPrefix(String prefix) {
|
||||
Assert.hasText(prefix, "Prefix cannot be empty");
|
||||
@@ -190,38 +210,36 @@ public class AvroSchemaRegistryClientMessageConverter extends AbstractAvroMessag
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
this.versionedSchema = Pattern.compile("application/" + this.prefix
|
||||
+ "\\.([\\p{Alnum}\\$\\.]+)\\.v(\\p{Digit}+)\\+"+AVRO_FORMAT);
|
||||
+ "\\.([\\p{Alnum}\\$\\.]+)\\.v(\\p{Digit}+)\\+" + AVRO_FORMAT);
|
||||
|
||||
Stream.of(this.schemaImports, this.schemaLocations)
|
||||
.filter(arr -> !ObjectUtils.isEmpty(arr))
|
||||
.distinct()
|
||||
.peek(resources -> {
|
||||
.filter(arr -> !ObjectUtils.isEmpty(arr)).distinct().peek(resources -> {
|
||||
this.logger.info("Scanning avro schema resources on classpath");
|
||||
if (this.logger.isInfoEnabled()) {
|
||||
this.logger.info("Parsing" + this.schemaImports.length);
|
||||
}
|
||||
}).flatMap(Arrays::stream).forEach(resource -> {
|
||||
try {
|
||||
Schema schema = parseSchema(resource);
|
||||
if (schema.getType().equals(Schema.Type.UNION)) {
|
||||
schema.getTypes().forEach(
|
||||
innerSchema -> registerSchema(resource, innerSchema));
|
||||
}
|
||||
else {
|
||||
registerSchema(resource, schema);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
if (this.logger.isWarnEnabled()) {
|
||||
this.logger.warn(
|
||||
"Failed to parse schema at " + resource.getFilename(),
|
||||
e);
|
||||
}
|
||||
}
|
||||
});
|
||||
try {
|
||||
Schema schema = parseSchema(resource);
|
||||
if (schema.getType().equals(Schema.Type.UNION)) {
|
||||
schema.getTypes().forEach(
|
||||
innerSchema -> registerSchema(resource, innerSchema));
|
||||
}
|
||||
else {
|
||||
registerSchema(resource, schema);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
if (this.logger.isWarnEnabled()) {
|
||||
this.logger.warn(
|
||||
"Failed to parse schema at " + resource.getFilename(),
|
||||
e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (this.cacheManager instanceof NoOpCacheManager) {
|
||||
logger.warn("Schema caching is effectively disabled "
|
||||
this.logger.warn("Schema caching is effectively disabled "
|
||||
+ "since configured cache manager is a NoOpCacheManager. If this was not "
|
||||
+ "the intention, please provide the appropriate instance of CacheManager "
|
||||
+ "(i.e., ConcurrentMapCacheManager).");
|
||||
@@ -229,7 +247,7 @@ public class AvroSchemaRegistryClientMessageConverter extends AbstractAvroMessag
|
||||
}
|
||||
|
||||
protected String toSubject(Schema schema) {
|
||||
return subjectNamingStrategy.toSubject(schema);
|
||||
return this.subjectNamingStrategy.toSubject(schema);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -274,10 +292,11 @@ public class AvroSchemaRegistryClientMessageConverter extends AbstractAvroMessag
|
||||
|
||||
DirectFieldAccessor dfa = new DirectFieldAccessor(headers);
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> _headers = (Map<String, Object>) dfa.getPropertyValue("headers");
|
||||
Map<String, Object> _headers = (Map<String, Object>) dfa
|
||||
.getPropertyValue("headers");
|
||||
_headers.put(MessageHeaders.CONTENT_TYPE,
|
||||
"application/" + this.prefix + "." + schemaReference.getSubject()
|
||||
+ ".v" + schemaReference.getVersion() + "+" + AVRO_FORMAT);
|
||||
"application/" + this.prefix + "." + schemaReference.getSubject() + ".v"
|
||||
+ schemaReference.getVersion() + "+" + AVRO_FORMAT);
|
||||
|
||||
return schema;
|
||||
}
|
||||
@@ -287,13 +306,17 @@ public class AvroSchemaRegistryClientMessageConverter extends AbstractAvroMessag
|
||||
if (this.readerSchema == null) {
|
||||
SchemaReference schemaReference = extractSchemaReference(mimeType);
|
||||
if (schemaReference != null) {
|
||||
ParsedSchema parsedSchema = cacheManager.getCache(REFERENCE_CACHE_NAME).get(schemaReference, ParsedSchema.class);
|
||||
ParsedSchema parsedSchema = this.cacheManager
|
||||
.getCache(REFERENCE_CACHE_NAME)
|
||||
.get(schemaReference, ParsedSchema.class);
|
||||
if (parsedSchema == null) {
|
||||
String schemaContent = this.schemaRegistryClient.fetch(schemaReference);
|
||||
String schemaContent = this.schemaRegistryClient
|
||||
.fetch(schemaReference);
|
||||
if (schemaContent != null) {
|
||||
Schema schema = new Schema.Parser().parse(schemaContent);
|
||||
parsedSchema = new ParsedSchema(schema);
|
||||
cacheManager.getCache(REFERENCE_CACHE_NAME).putIfAbsent(schemaReference, parsedSchema);
|
||||
this.cacheManager.getCache(REFERENCE_CACHE_NAME)
|
||||
.putIfAbsent(schemaReference, parsedSchema);
|
||||
}
|
||||
}
|
||||
if (parsedSchema != null) {
|
||||
@@ -325,9 +348,10 @@ public class AvroSchemaRegistryClientMessageConverter extends AbstractAvroMessag
|
||||
.get(payload.getClass().getName(), Schema.class);
|
||||
if (schema == null) {
|
||||
if (!isDynamicSchemaGenerationEnabled()) {
|
||||
throw new SchemaNotFoundException(String
|
||||
.format("No schema found in the local cache for %s, and dynamic schema generation "
|
||||
+ "is not enabled", payload.getClass()));
|
||||
throw new SchemaNotFoundException(String.format(
|
||||
"No schema found in the local cache for %s, and dynamic schema generation "
|
||||
+ "is not enabled",
|
||||
payload.getClass()));
|
||||
}
|
||||
else {
|
||||
schema = ReflectData.get().getSchema(payload.getClass());
|
||||
@@ -341,15 +365,15 @@ public class AvroSchemaRegistryClientMessageConverter extends AbstractAvroMessag
|
||||
|
||||
private void registerSchema(Resource schemaLocation, Schema schema) {
|
||||
if (this.logger.isInfoEnabled()) {
|
||||
this.logger.info("Resource " + schemaLocation.getFilename()
|
||||
+ " parsed into schema " + schema.getNamespace() + "."
|
||||
+ schema.getName());
|
||||
this.logger.info(
|
||||
"Resource " + schemaLocation.getFilename() + " parsed into schema "
|
||||
+ schema.getNamespace() + "." + schema.getName());
|
||||
}
|
||||
this.schemaRegistryClient.register(toSubject(schema), AVRO_FORMAT,
|
||||
schema.toString());
|
||||
if (this.logger.isInfoEnabled()) {
|
||||
this.logger.info("Schema " + schema.getName()
|
||||
+ " registered with id " + schema);
|
||||
this.logger
|
||||
.info("Schema " + schema.getName() + " registered with id " + schema);
|
||||
}
|
||||
this.cacheManager.getCache(REFLECTION_CACHE_NAME)
|
||||
.put(schema.getNamespace() + "." + schema.getName(), schema);
|
||||
@@ -365,4 +389,5 @@ public class AvroSchemaRegistryClientMessageConverter extends AbstractAvroMessag
|
||||
}
|
||||
return schemaReference;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,4 +27,5 @@ public class DefaultSubjectNamingStrategy implements SubjectNamingStrategy {
|
||||
public String toSubject(Schema schema) {
|
||||
return schema.getName().toLowerCase();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -46,13 +46,14 @@ class OriginalContentTypeResolver implements ContentTypeResolver {
|
||||
mimeType = (MimeType) contentType;
|
||||
}
|
||||
else if (contentType instanceof String) {
|
||||
mimeType = mimeTypeCache.get(contentType);
|
||||
mimeType = this.mimeTypeCache.get(contentType);
|
||||
if (mimeType == null) {
|
||||
String valueAsString = (String) contentType;
|
||||
mimeType = MimeType.valueOf(valueAsString);
|
||||
mimeTypeCache.put(valueAsString, mimeType);
|
||||
this.mimeTypeCache.put(valueAsString, mimeType);
|
||||
}
|
||||
}
|
||||
return mimeType;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,14 +20,17 @@ import org.apache.avro.Schema;
|
||||
|
||||
/**
|
||||
* Provides function towards naming schema registry subjects for Avro files.
|
||||
*
|
||||
* @author David Kalosi
|
||||
*/
|
||||
public interface SubjectNamingStrategy {
|
||||
|
||||
/**
|
||||
* Takes the Avro schema on input and returns the generated subject under which the schema should be registered.
|
||||
* @param schema
|
||||
* Takes the Avro schema on input and returns the generated subject under which the
|
||||
* schema should be registered.
|
||||
* @param schema schema to register
|
||||
* @return subject name
|
||||
*/
|
||||
String toSubject(Schema schema);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
* Copyright 2017-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.
|
||||
@@ -45,23 +45,25 @@ public class CachingRegistryClient implements SchemaRegistryClient {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SchemaRegistrationResponse register(String subject, String format, String schema) {
|
||||
SchemaRegistrationResponse response = delegate.register(subject, format, schema);
|
||||
cacheManager.getCache(ID_CACHE).put(response.getId(), schema);
|
||||
cacheManager.getCache(REF_CACHE).put(response.getSchemaReference(), schema);
|
||||
public SchemaRegistrationResponse register(String subject, String format,
|
||||
String schema) {
|
||||
SchemaRegistrationResponse response = this.delegate.register(subject, format,
|
||||
schema);
|
||||
this.cacheManager.getCache(ID_CACHE).put(response.getId(), schema);
|
||||
this.cacheManager.getCache(REF_CACHE).put(response.getSchemaReference(), schema);
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Cacheable(cacheNames = REF_CACHE)
|
||||
public String fetch(SchemaReference schemaReference) {
|
||||
return delegate.fetch(schemaReference);
|
||||
return this.delegate.fetch(schemaReference);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Cacheable(cacheNames = ID_CACHE)
|
||||
public String fetch(int id) {
|
||||
return delegate.fetch(id);
|
||||
return this.delegate.fetch(id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -43,7 +43,8 @@ import org.springframework.web.client.RestTemplate;
|
||||
*/
|
||||
public class ConfluentSchemaRegistryClient implements SchemaRegistryClient {
|
||||
|
||||
private static final List<String> ACCEPT_HEADERS = Arrays.asList("application/vnd.schemaregistry.v1+json",
|
||||
private static final List<String> ACCEPT_HEADERS = Arrays.asList(
|
||||
"application/vnd.schemaregistry.v1+json",
|
||||
"application/vnd.schemaregistry+json", "application/json");
|
||||
|
||||
private RestTemplate template;
|
||||
@@ -95,11 +96,9 @@ public class ConfluentSchemaRegistryClient implements SchemaRegistryClient {
|
||||
version = getSubjectVersion(subject, payload);
|
||||
}
|
||||
catch (HttpStatusCodeException httpException) {
|
||||
throw new RuntimeException(
|
||||
String.format(
|
||||
"Failed to register subject %s, server replied with status %d",
|
||||
subject, httpException.getStatusCode().value()),
|
||||
httpException);
|
||||
throw new RuntimeException(String.format(
|
||||
"Failed to register subject %s, server replied with status %d",
|
||||
subject, httpException.getStatusCode().value()), httpException);
|
||||
}
|
||||
SchemaRegistrationResponse schemaRegistrationResponse = new SchemaRegistrationResponse();
|
||||
schemaRegistrationResponse.setId(id);
|
||||
@@ -112,7 +111,8 @@ public class ConfluentSchemaRegistryClient implements SchemaRegistryClient {
|
||||
* Confluent register API returns the id, but we need the version of a given schema
|
||||
* subject. After a successful registration we can inquire the server to get the
|
||||
* version of a schema
|
||||
* @param subject
|
||||
* @param subject the schema subject
|
||||
* @param payload payload to send
|
||||
* @return the version of the returned schema
|
||||
*/
|
||||
private Integer getSubjectVersion(String subject, String payload) {
|
||||
@@ -129,11 +129,9 @@ public class ConfluentSchemaRegistryClient implements SchemaRegistryClient {
|
||||
version = (Integer) response.getBody().get("version");
|
||||
}
|
||||
catch (HttpStatusCodeException httpException) {
|
||||
throw new RuntimeException(
|
||||
String.format(
|
||||
"Failed to register subject %s, server replied with status %d",
|
||||
subject, httpException.getStatusCode().value()),
|
||||
httpException);
|
||||
throw new RuntimeException(String.format(
|
||||
"Failed to register subject %s, server replied with status %d",
|
||||
subject, httpException.getStatusCode().value()), httpException);
|
||||
}
|
||||
return version;
|
||||
}
|
||||
@@ -184,4 +182,5 @@ public class ConfluentSchemaRegistryClient implements SchemaRegistryClient {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ public class DefaultSchemaRegistryClient implements SchemaRegistryClient {
|
||||
}
|
||||
|
||||
public DefaultSchemaRegistryClient(RestTemplate restTemplate) {
|
||||
Assert.notNull(restTemplate,"'restTemplate' must not be null.");
|
||||
Assert.notNull(restTemplate, "'restTemplate' must not be null.");
|
||||
this.restTemplate = restTemplate;
|
||||
}
|
||||
|
||||
@@ -59,34 +59,37 @@ public class DefaultSchemaRegistryClient implements SchemaRegistryClient {
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@Override
|
||||
public SchemaRegistrationResponse register(String subject, String format, String schema) {
|
||||
public SchemaRegistrationResponse register(String subject, String format,
|
||||
String schema) {
|
||||
Map<String, String> requestBody = new HashMap<>();
|
||||
requestBody.put("subject", subject);
|
||||
requestBody.put("format", format);
|
||||
requestBody.put("definition", schema);
|
||||
ResponseEntity<Map> responseEntity = this.restTemplate.postForEntity(this.endpoint, requestBody, Map.class);
|
||||
ResponseEntity<Map> responseEntity = this.restTemplate
|
||||
.postForEntity(this.endpoint, requestBody, Map.class);
|
||||
if (responseEntity.getStatusCode().is2xxSuccessful()) {
|
||||
SchemaRegistrationResponse registrationResponse = new SchemaRegistrationResponse();
|
||||
Map<String, Object> responseBody = (Map<String, Object>) responseEntity.getBody();
|
||||
Map<String, Object> responseBody = (Map<String, Object>) responseEntity
|
||||
.getBody();
|
||||
registrationResponse.setId((Integer) responseBody.get("id"));
|
||||
registrationResponse.setSchemaReference(
|
||||
new SchemaReference(subject, (Integer) responseBody.get("version"),
|
||||
responseBody.get("format").toString()));
|
||||
return registrationResponse;
|
||||
}
|
||||
throw new RuntimeException("Failed to register schema: " + responseEntity.toString());
|
||||
throw new RuntimeException(
|
||||
"Failed to register schema: " + responseEntity.toString());
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public String fetch(SchemaReference schemaReference) {
|
||||
ResponseEntity<Map> responseEntity = this.restTemplate.getForEntity(
|
||||
this.endpoint + "/" + schemaReference.getSubject() + "/" + schemaReference
|
||||
.getFormat() + "/v" + schemaReference
|
||||
.getVersion(),
|
||||
Map.class);
|
||||
ResponseEntity<Map> responseEntity = this.restTemplate.getForEntity(this.endpoint
|
||||
+ "/" + schemaReference.getSubject() + "/" + schemaReference.getFormat()
|
||||
+ "/v" + schemaReference.getVersion(), Map.class);
|
||||
if (!responseEntity.getStatusCode().is2xxSuccessful()) {
|
||||
throw new RuntimeException("Failed to fetch schema: " + responseEntity.toString());
|
||||
throw new RuntimeException(
|
||||
"Failed to fetch schema: " + responseEntity.toString());
|
||||
}
|
||||
return (String) responseEntity.getBody().get("definition");
|
||||
}
|
||||
@@ -94,11 +97,13 @@ public class DefaultSchemaRegistryClient implements SchemaRegistryClient {
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public String fetch(int id) {
|
||||
ResponseEntity<Map> responseEntity = this.restTemplate.getForEntity(
|
||||
this.endpoint + "/schemas/" + id, Map.class);
|
||||
ResponseEntity<Map> responseEntity = this.restTemplate
|
||||
.getForEntity(this.endpoint + "/schemas/" + id, Map.class);
|
||||
if (!responseEntity.getStatusCode().is2xxSuccessful()) {
|
||||
throw new RuntimeException("Failed to fetch schema: " + responseEntity.toString());
|
||||
throw new RuntimeException(
|
||||
"Failed to fetch schema: " + responseEntity.toString());
|
||||
}
|
||||
return (String) responseEntity.getBody().get("definition");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2016-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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2016-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.
|
||||
@@ -29,6 +29,7 @@ public interface SchemaRegistryClient {
|
||||
* Registers a schema with the remote repository returning the unique identifier
|
||||
* associated with this schema.
|
||||
* @param subject the full name of the schema
|
||||
* @param format format of the schema
|
||||
* @param schema string representation of the schema
|
||||
* @return a {@link SchemaRegistrationResponse} representing the result of the
|
||||
* operation
|
||||
|
||||
@@ -43,12 +43,14 @@ public class SchemaRegistryClientConfiguration {
|
||||
public SchemaRegistryClient schemaRegistryClient() {
|
||||
DefaultSchemaRegistryClient defaultSchemaRegistryClient = new DefaultSchemaRegistryClient();
|
||||
|
||||
if (StringUtils.hasText(schemaRegistryClientProperties.getEndpoint())) {
|
||||
defaultSchemaRegistryClient.setEndpoint(schemaRegistryClientProperties.getEndpoint());
|
||||
if (StringUtils.hasText(this.schemaRegistryClientProperties.getEndpoint())) {
|
||||
defaultSchemaRegistryClient
|
||||
.setEndpoint(this.schemaRegistryClientProperties.getEndpoint());
|
||||
}
|
||||
|
||||
SchemaRegistryClient client = (schemaRegistryClientProperties.isCached())
|
||||
? new CachingRegistryClient(defaultSchemaRegistryClient) : defaultSchemaRegistryClient;
|
||||
SchemaRegistryClient client = (this.schemaRegistryClientProperties.isCached())
|
||||
? new CachingRegistryClient(defaultSchemaRegistryClient)
|
||||
: defaultSchemaRegistryClient;
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
@@ -38,10 +38,11 @@ public class SchemaRegistryClientProperties {
|
||||
}
|
||||
|
||||
public boolean isCached() {
|
||||
return cached;
|
||||
return this.cached;
|
||||
}
|
||||
|
||||
public void setCached(boolean cached) {
|
||||
this.cached = cached;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
* Copyright 2017-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.
|
||||
@@ -36,7 +36,6 @@ import org.apache.avro.specific.SpecificDatumWriter;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -57,170 +56,164 @@ import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Vinicius Carvalho
|
||||
* @author Sercan Karaoglu
|
||||
*/
|
||||
public class AvroMessageConverterSerializationTests {
|
||||
|
||||
Pattern versionedSchema = Pattern.compile("application/" + "vnd"
|
||||
+ "\\.([\\p{Alnum}\\$\\.]+)\\.v(\\p{Digit}+)\\+avro");
|
||||
Pattern versionedSchema = Pattern.compile(
|
||||
"application/" + "vnd" + "\\.([\\p{Alnum}\\$\\.]+)\\.v(\\p{Digit}+)\\+avro");
|
||||
|
||||
Log logger = LogFactory.getLog(getClass());
|
||||
Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private ConfigurableApplicationContext schemaRegistryServerContext;
|
||||
private ConfigurableApplicationContext schemaRegistryServerContext;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
schemaRegistryServerContext = SpringApplication
|
||||
.run(SchemaRegistryServerApplication.class,
|
||||
"--spring.main.allow-bean-definition-overriding=true");
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
schemaRegistryServerContext.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSchemaImport() throws Exception {
|
||||
SchemaRegistryClient client = new DefaultSchemaRegistryClient();
|
||||
AvroSchemaRegistryClientMessageConverter converter = new AvroSchemaRegistryClientMessageConverter(
|
||||
client, new NoOpCacheManager());
|
||||
converter.setSubjectNamingStrategy(new DefaultSubjectNamingStrategy());
|
||||
converter.setDynamicSchemaGenerationEnabled(false);
|
||||
converter.setSchemaLocations(schemaRegistryServerContext
|
||||
.getResources("classpath:schemas/Command.avsc"));
|
||||
converter.setSchemaImports(schemaRegistryServerContext
|
||||
.getResources("classpath:schemas/imports/*.avsc"));
|
||||
converter.afterPropertiesSet();
|
||||
Command notification = notification();
|
||||
Message specificMessage = converter.toMessage(notification,
|
||||
new MutableMessageHeaders(
|
||||
Collections.<String, Object> emptyMap()));
|
||||
Object o = converter.fromMessage(specificMessage, Command.class);
|
||||
|
||||
Assert.assertEquals("Serialization issue when use schema-imports", o, notification);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sourceWriteSameVersion() throws Exception {
|
||||
User specificRecord = new User();
|
||||
specificRecord.setName("joe");
|
||||
Schema v1 = new Schema.Parser()
|
||||
.parse(AvroMessageConverterSerializationTests.class
|
||||
.getClassLoader()
|
||||
.getResourceAsStream("schemas/user.avsc"));
|
||||
GenericRecord genericRecord = new GenericData.Record(v1);
|
||||
genericRecord.put("name", "joe");
|
||||
SchemaRegistryClient client = new DefaultSchemaRegistryClient();
|
||||
AvroSchemaRegistryClientMessageConverter converter = new AvroSchemaRegistryClientMessageConverter(
|
||||
client, new NoOpCacheManager());
|
||||
|
||||
converter.setSubjectNamingStrategy(new DefaultSubjectNamingStrategy());
|
||||
converter.setDynamicSchemaGenerationEnabled(false);
|
||||
converter.afterPropertiesSet();
|
||||
|
||||
Message specificMessage = converter.toMessage(specificRecord,
|
||||
new MutableMessageHeaders(
|
||||
Collections.<String, Object> emptyMap()),
|
||||
MimeTypeUtils.parseMimeType("application/*+avro"));
|
||||
SchemaReference specificRef = extractSchemaReference(MimeTypeUtils
|
||||
.parseMimeType(specificMessage.getHeaders().get("contentType")
|
||||
.toString()));
|
||||
|
||||
Message genericMessage = converter.toMessage(genericRecord,
|
||||
new MutableMessageHeaders(
|
||||
Collections.<String, Object> emptyMap()),
|
||||
MimeTypeUtils.parseMimeType("application/*+avro"));
|
||||
SchemaReference genericRef = extractSchemaReference(MimeTypeUtils
|
||||
.parseMimeType(genericMessage.getHeaders().get("contentType")
|
||||
.toString()));
|
||||
|
||||
Assert.assertEquals(genericRef, specificRef);
|
||||
Assert.assertEquals(1, genericRef.getVersion());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOriginalContentTypeHeaderOnly() throws Exception {
|
||||
User specificRecord = new User();
|
||||
specificRecord.setName("joe");
|
||||
Schema v1 = new Schema.Parser()
|
||||
.parse(AvroMessageConverterSerializationTests.class
|
||||
.getClassLoader()
|
||||
.getResourceAsStream("schemas/user.avsc"));
|
||||
GenericRecord genericRecord = new GenericData.Record(v1);
|
||||
genericRecord.put("name", "joe");
|
||||
SchemaRegistryClient client = new DefaultSchemaRegistryClient();
|
||||
client.register("user", "avro", v1.toString());
|
||||
AvroSchemaRegistryClientMessageConverter converter = new AvroSchemaRegistryClientMessageConverter(
|
||||
client, new NoOpCacheManager());
|
||||
converter.setDynamicSchemaGenerationEnabled(false);
|
||||
converter.afterPropertiesSet();
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DatumWriter<User> writer = new SpecificDatumWriter<>(User.class);
|
||||
Encoder encoder = EncoderFactory.get().binaryEncoder(baos, null);
|
||||
writer.write(specificRecord, encoder);
|
||||
encoder.flush();
|
||||
Message source = MessageBuilder.withPayload(baos.toByteArray())
|
||||
.setHeader(MessageHeaders.CONTENT_TYPE,
|
||||
MimeTypeUtils.APPLICATION_OCTET_STREAM)
|
||||
.setHeader(BinderHeaders.BINDER_ORIGINAL_CONTENT_TYPE,
|
||||
"application/vnd.user.v1+avro").build();
|
||||
Object converted = converter.fromMessage(source, User.class);
|
||||
Assert.assertNotNull(converted);
|
||||
Assert.assertEquals(specificRecord.getName().toString(),
|
||||
((User) converted).getName().toString());
|
||||
|
||||
}
|
||||
|
||||
private SchemaReference extractSchemaReference(MimeType mimeType) {
|
||||
SchemaReference schemaReference = null;
|
||||
Matcher schemaMatcher = this.versionedSchema.matcher(mimeType.toString());
|
||||
if (schemaMatcher.find()) {
|
||||
String subject = schemaMatcher.group(1);
|
||||
Integer version = Integer.parseInt(schemaMatcher.group(2));
|
||||
schemaReference = new SchemaReference(subject, version,
|
||||
AvroSchemaRegistryClientMessageConverter.AVRO_FORMAT);
|
||||
}
|
||||
return schemaReference;
|
||||
}
|
||||
|
||||
public static Command notification() {
|
||||
Command messageToSend = getCommandToSend();
|
||||
messageToSend.setType("notification");
|
||||
PushNotification pushNotification = new PushNotification();
|
||||
pushNotification.setArn("google");
|
||||
pushNotification.setText("hello");
|
||||
messageToSend.setPayload(pushNotification);
|
||||
return messageToSend;
|
||||
}
|
||||
|
||||
public static Command sms() {
|
||||
Command messageToSend = getCommandToSend();
|
||||
messageToSend.setType("sms");
|
||||
Sms sms = new Sms();
|
||||
sms.setPhoneNumber("6141231212");
|
||||
sms.setText("hello");
|
||||
messageToSend.setPayload(sms);
|
||||
return messageToSend;
|
||||
}
|
||||
|
||||
public static Command email() {
|
||||
Command messageToSend = getCommandToSend();
|
||||
messageToSend.setType("email");
|
||||
Email email = new Email();
|
||||
email.setAddressTo("sercan");
|
||||
email.setText("hello");
|
||||
email.setTitle("hi");
|
||||
messageToSend.setPayload(email);
|
||||
return messageToSend;
|
||||
}
|
||||
|
||||
public static Command getCommandToSend() {
|
||||
Command messageToSend = new Command();
|
||||
messageToSend.setCorrelationId("abc");
|
||||
return messageToSend;
|
||||
public static Command notification() {
|
||||
Command messageToSend = getCommandToSend();
|
||||
messageToSend.setType("notification");
|
||||
PushNotification pushNotification = new PushNotification();
|
||||
pushNotification.setArn("google");
|
||||
pushNotification.setText("hello");
|
||||
messageToSend.setPayload(pushNotification);
|
||||
return messageToSend;
|
||||
}
|
||||
|
||||
public static Command sms() {
|
||||
Command messageToSend = getCommandToSend();
|
||||
messageToSend.setType("sms");
|
||||
Sms sms = new Sms();
|
||||
sms.setPhoneNumber("6141231212");
|
||||
sms.setText("hello");
|
||||
messageToSend.setPayload(sms);
|
||||
return messageToSend;
|
||||
}
|
||||
|
||||
public static Command email() {
|
||||
Command messageToSend = getCommandToSend();
|
||||
messageToSend.setType("email");
|
||||
Email email = new Email();
|
||||
email.setAddressTo("sercan");
|
||||
email.setText("hello");
|
||||
email.setTitle("hi");
|
||||
messageToSend.setPayload(email);
|
||||
return messageToSend;
|
||||
}
|
||||
|
||||
public static Command getCommandToSend() {
|
||||
Command messageToSend = new Command();
|
||||
messageToSend.setCorrelationId("abc");
|
||||
return messageToSend;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.schemaRegistryServerContext = SpringApplication.run(
|
||||
SchemaRegistryServerApplication.class,
|
||||
"--spring.main.allow-bean-definition-overriding=true");
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
this.schemaRegistryServerContext.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSchemaImport() throws Exception {
|
||||
SchemaRegistryClient client = new DefaultSchemaRegistryClient();
|
||||
AvroSchemaRegistryClientMessageConverter converter = new AvroSchemaRegistryClientMessageConverter(
|
||||
client, new NoOpCacheManager());
|
||||
converter.setSubjectNamingStrategy(new DefaultSubjectNamingStrategy());
|
||||
converter.setDynamicSchemaGenerationEnabled(false);
|
||||
converter.setSchemaLocations(this.schemaRegistryServerContext
|
||||
.getResources("classpath:schemas/Command.avsc"));
|
||||
converter.setSchemaImports(this.schemaRegistryServerContext
|
||||
.getResources("classpath:schemas/imports/*.avsc"));
|
||||
converter.afterPropertiesSet();
|
||||
Command notification = notification();
|
||||
Message specificMessage = converter.toMessage(notification,
|
||||
new MutableMessageHeaders(Collections.<String, Object>emptyMap()));
|
||||
Object o = converter.fromMessage(specificMessage, Command.class);
|
||||
|
||||
assertThat(o).isEqualTo(notification)
|
||||
.as("Serialization issue when use schema-imports");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sourceWriteSameVersion() throws Exception {
|
||||
User specificRecord = new User();
|
||||
specificRecord.setName("joe");
|
||||
Schema v1 = new Schema.Parser().parse(AvroMessageConverterSerializationTests.class
|
||||
.getClassLoader().getResourceAsStream("schemas/user.avsc"));
|
||||
GenericRecord genericRecord = new GenericData.Record(v1);
|
||||
genericRecord.put("name", "joe");
|
||||
SchemaRegistryClient client = new DefaultSchemaRegistryClient();
|
||||
AvroSchemaRegistryClientMessageConverter converter = new AvroSchemaRegistryClientMessageConverter(
|
||||
client, new NoOpCacheManager());
|
||||
|
||||
converter.setSubjectNamingStrategy(new DefaultSubjectNamingStrategy());
|
||||
converter.setDynamicSchemaGenerationEnabled(false);
|
||||
converter.afterPropertiesSet();
|
||||
|
||||
Message specificMessage = converter.toMessage(specificRecord,
|
||||
new MutableMessageHeaders(Collections.<String, Object>emptyMap()),
|
||||
MimeTypeUtils.parseMimeType("application/*+avro"));
|
||||
SchemaReference specificRef = extractSchemaReference(MimeTypeUtils.parseMimeType(
|
||||
specificMessage.getHeaders().get("contentType").toString()));
|
||||
|
||||
Message genericMessage = converter.toMessage(genericRecord,
|
||||
new MutableMessageHeaders(Collections.<String, Object>emptyMap()),
|
||||
MimeTypeUtils.parseMimeType("application/*+avro"));
|
||||
SchemaReference genericRef = extractSchemaReference(MimeTypeUtils.parseMimeType(
|
||||
genericMessage.getHeaders().get("contentType").toString()));
|
||||
|
||||
assertThat(specificRef).isEqualTo(genericRef);
|
||||
assertThat(genericRef.getVersion()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOriginalContentTypeHeaderOnly() throws Exception {
|
||||
User specificRecord = new User();
|
||||
specificRecord.setName("joe");
|
||||
Schema v1 = new Schema.Parser().parse(AvroMessageConverterSerializationTests.class
|
||||
.getClassLoader().getResourceAsStream("schemas/user.avsc"));
|
||||
GenericRecord genericRecord = new GenericData.Record(v1);
|
||||
genericRecord.put("name", "joe");
|
||||
SchemaRegistryClient client = new DefaultSchemaRegistryClient();
|
||||
client.register("user", "avro", v1.toString());
|
||||
AvroSchemaRegistryClientMessageConverter converter = new AvroSchemaRegistryClientMessageConverter(
|
||||
client, new NoOpCacheManager());
|
||||
converter.setDynamicSchemaGenerationEnabled(false);
|
||||
converter.afterPropertiesSet();
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DatumWriter<User> writer = new SpecificDatumWriter<>(User.class);
|
||||
Encoder encoder = EncoderFactory.get().binaryEncoder(baos, null);
|
||||
writer.write(specificRecord, encoder);
|
||||
encoder.flush();
|
||||
Message source = MessageBuilder.withPayload(baos.toByteArray())
|
||||
.setHeader(MessageHeaders.CONTENT_TYPE,
|
||||
MimeTypeUtils.APPLICATION_OCTET_STREAM)
|
||||
.setHeader(BinderHeaders.BINDER_ORIGINAL_CONTENT_TYPE,
|
||||
"application/vnd.user.v1+avro")
|
||||
.build();
|
||||
Object converted = converter.fromMessage(source, User.class);
|
||||
assertThat(converted).isNotNull();
|
||||
assertThat(specificRecord.getName().toString())
|
||||
.isEqualTo(((User) converted).getName().toString());
|
||||
}
|
||||
|
||||
private SchemaReference extractSchemaReference(MimeType mimeType) {
|
||||
SchemaReference schemaReference = null;
|
||||
Matcher schemaMatcher = this.versionedSchema.matcher(mimeType.toString());
|
||||
if (schemaMatcher.find()) {
|
||||
String subject = schemaMatcher.group(1);
|
||||
Integer version = Integer.parseInt(schemaMatcher.group(2));
|
||||
schemaReference = new SchemaReference(subject, version,
|
||||
AvroSchemaRegistryClientMessageConverter.AVRO_FORMAT);
|
||||
}
|
||||
return schemaReference;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2016-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.
|
||||
@@ -54,8 +54,8 @@ public class AvroSchemaMessageConverterTests {
|
||||
|
||||
@Test
|
||||
public void testSendMessageWithLocation() throws Exception {
|
||||
ConfigurableApplicationContext sourceContext = SpringApplication.run(AvroSourceApplication.class,
|
||||
"--server.port=0",
|
||||
ConfigurableApplicationContext sourceContext = SpringApplication.run(
|
||||
AvroSourceApplication.class, "--server.port=0",
|
||||
"--spring.jmx.enabled=false",
|
||||
"--schemaLocation=classpath:schemas/users_v1.schema",
|
||||
"--spring.cloud.stream.schemaRegistryClient.enabled=false",
|
||||
@@ -65,12 +65,13 @@ public class AvroSchemaMessageConverterTests {
|
||||
firstOutboundFoo.setName("foo" + UUID.randomUUID().toString());
|
||||
firstOutboundFoo.setFavoriteColor("foo" + UUID.randomUUID().toString());
|
||||
source.output().send(MessageBuilder.withPayload(firstOutboundFoo).build());
|
||||
MessageCollector sourceMessageCollector = sourceContext.getBean(MessageCollector.class);
|
||||
Message<?> outboundMessage = sourceMessageCollector.forChannel(source.output()).poll(1000,
|
||||
TimeUnit.MILLISECONDS);
|
||||
MessageCollector sourceMessageCollector = sourceContext
|
||||
.getBean(MessageCollector.class);
|
||||
Message<?> outboundMessage = sourceMessageCollector.forChannel(source.output())
|
||||
.poll(1000, TimeUnit.MILLISECONDS);
|
||||
|
||||
ConfigurableApplicationContext barSourceContext = SpringApplication.run(AvroSourceApplication.class,
|
||||
"--server.port=0",
|
||||
ConfigurableApplicationContext barSourceContext = SpringApplication.run(
|
||||
AvroSourceApplication.class, "--server.port=0",
|
||||
"--spring.jmx.enabled=false",
|
||||
"--schemaLocation=classpath:schemas/users_v1.schema",
|
||||
"--spring.cloud.stream.schemaRegistryClient.enabled=false",
|
||||
@@ -81,9 +82,10 @@ public class AvroSchemaMessageConverterTests {
|
||||
firstOutboundUser2.setFavoritePlace("foo" + UUID.randomUUID().toString());
|
||||
firstOutboundUser2.setName("foo" + UUID.randomUUID().toString());
|
||||
barSource.output().send(MessageBuilder.withPayload(firstOutboundUser2).build());
|
||||
MessageCollector barSourceMessageCollector = barSourceContext.getBean(MessageCollector.class);
|
||||
Message<?> barOutboundMessage = barSourceMessageCollector.forChannel(barSource.output()).poll(1000,
|
||||
TimeUnit.MILLISECONDS);
|
||||
MessageCollector barSourceMessageCollector = barSourceContext
|
||||
.getBean(MessageCollector.class);
|
||||
Message<?> barOutboundMessage = barSourceMessageCollector
|
||||
.forChannel(barSource.output()).poll(1000, TimeUnit.MILLISECONDS);
|
||||
|
||||
assertThat(barOutboundMessage).isNotNull();
|
||||
|
||||
@@ -92,11 +94,11 @@ public class AvroSchemaMessageConverterTests {
|
||||
secondUser2OutboundPojo.setFavoritePlace("foo" + UUID.randomUUID().toString());
|
||||
secondUser2OutboundPojo.setName("foo" + UUID.randomUUID().toString());
|
||||
source.output().send(MessageBuilder.withPayload(secondUser2OutboundPojo).build());
|
||||
Message<?> secondBarOutboundMessage = sourceMessageCollector.forChannel(source.output()).poll(1000,
|
||||
TimeUnit.MILLISECONDS);
|
||||
Message<?> secondBarOutboundMessage = sourceMessageCollector
|
||||
.forChannel(source.output()).poll(1000, TimeUnit.MILLISECONDS);
|
||||
|
||||
ConfigurableApplicationContext sinkContext = SpringApplication.run(AvroSinkApplication.class,
|
||||
"--server.port=0",
|
||||
ConfigurableApplicationContext sinkContext = SpringApplication.run(
|
||||
AvroSinkApplication.class, "--server.port=0",
|
||||
"--spring.jmx.enabled=false",
|
||||
"--spring.cloud.stream.schemaRegistryClient.enabled=false",
|
||||
"--schemaLocation=classpath:schemas/users_v1.schema");
|
||||
@@ -104,27 +106,33 @@ public class AvroSchemaMessageConverterTests {
|
||||
sink.input().send(outboundMessage);
|
||||
sink.input().send(barOutboundMessage);
|
||||
sink.input().send(secondBarOutboundMessage);
|
||||
List<User1> receivedUsers = sinkContext.getBean(AvroSinkApplication.class).receivedUsers;
|
||||
List<User1> receivedUsers = sinkContext
|
||||
.getBean(AvroSinkApplication.class).receivedUsers;
|
||||
assertThat(receivedUsers).hasSize(3);
|
||||
assertThat(receivedUsers.get(0)).isNotSameAs(firstOutboundFoo);
|
||||
assertThat(receivedUsers.get(0).getFavoriteColor()).isEqualTo(firstOutboundFoo.getFavoriteColor());
|
||||
assertThat(receivedUsers.get(0).getFavoriteColor())
|
||||
.isEqualTo(firstOutboundFoo.getFavoriteColor());
|
||||
assertThat(receivedUsers.get(0).getName()).isEqualTo(firstOutboundFoo.getName());
|
||||
|
||||
assertThat(receivedUsers.get(1)).isNotSameAs(firstOutboundUser2);
|
||||
assertThat(receivedUsers.get(1).getFavoriteColor()).isEqualTo(firstOutboundUser2.getFavoriteColor());
|
||||
assertThat(receivedUsers.get(1).getName()).isEqualTo(firstOutboundUser2.getName());
|
||||
assertThat(receivedUsers.get(1).getFavoriteColor())
|
||||
.isEqualTo(firstOutboundUser2.getFavoriteColor());
|
||||
assertThat(receivedUsers.get(1).getName())
|
||||
.isEqualTo(firstOutboundUser2.getName());
|
||||
|
||||
assertThat(receivedUsers.get(2)).isNotSameAs(secondUser2OutboundPojo);
|
||||
assertThat(receivedUsers.get(2).getFavoriteColor()).isEqualTo(secondUser2OutboundPojo.getFavoriteColor());
|
||||
assertThat(receivedUsers.get(2).getName()).isEqualTo(secondUser2OutboundPojo.getName());
|
||||
assertThat(receivedUsers.get(2).getFavoriteColor())
|
||||
.isEqualTo(secondUser2OutboundPojo.getFavoriteColor());
|
||||
assertThat(receivedUsers.get(2).getName())
|
||||
.isEqualTo(secondUser2OutboundPojo.getName());
|
||||
|
||||
sourceContext.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendMessageWithoutLocation() throws Exception {
|
||||
ConfigurableApplicationContext sourceContext = SpringApplication.run(AvroSourceApplication.class,
|
||||
"--server.port=0",
|
||||
ConfigurableApplicationContext sourceContext = SpringApplication.run(
|
||||
AvroSourceApplication.class, "--server.port=0",
|
||||
"--spring.jmx.enabled=false",
|
||||
"--spring.cloud.stream.schemaRegistryClient.enabled=false",
|
||||
"--spring.cloud.stream.bindings.output.contentType=avro/bytes");
|
||||
@@ -133,12 +141,13 @@ public class AvroSchemaMessageConverterTests {
|
||||
firstOutboundFoo.setName("foo" + UUID.randomUUID().toString());
|
||||
firstOutboundFoo.setFavoriteColor("foo" + UUID.randomUUID().toString());
|
||||
source.output().send(MessageBuilder.withPayload(firstOutboundFoo).build());
|
||||
MessageCollector sourceMessageCollector = sourceContext.getBean(MessageCollector.class);
|
||||
Message<?> outboundMessage = sourceMessageCollector.forChannel(source.output()).poll(1000,
|
||||
TimeUnit.MILLISECONDS);
|
||||
MessageCollector sourceMessageCollector = sourceContext
|
||||
.getBean(MessageCollector.class);
|
||||
Message<?> outboundMessage = sourceMessageCollector.forChannel(source.output())
|
||||
.poll(1000, TimeUnit.MILLISECONDS);
|
||||
|
||||
ConfigurableApplicationContext barSourceContext = SpringApplication.run(AvroSourceApplication.class,
|
||||
"--server.port=0",
|
||||
ConfigurableApplicationContext barSourceContext = SpringApplication.run(
|
||||
AvroSourceApplication.class, "--server.port=0",
|
||||
"--spring.jmx.enabled=false",
|
||||
"--spring.cloud.stream.schemaRegistryClient.enabled=false",
|
||||
"--spring.cloud.stream.bindings.output.contentType=avro/bytes");
|
||||
@@ -148,9 +157,10 @@ public class AvroSchemaMessageConverterTests {
|
||||
firstOutboundUser2.setFavoritePlace("foo" + UUID.randomUUID().toString());
|
||||
firstOutboundUser2.setName("foo" + UUID.randomUUID().toString());
|
||||
barSource.output().send(MessageBuilder.withPayload(firstOutboundUser2).build());
|
||||
MessageCollector barSourceMessageCollector = barSourceContext.getBean(MessageCollector.class);
|
||||
Message<?> barOutboundMessage = barSourceMessageCollector.forChannel(barSource.output()).poll(1000,
|
||||
TimeUnit.MILLISECONDS);
|
||||
MessageCollector barSourceMessageCollector = barSourceContext
|
||||
.getBean(MessageCollector.class);
|
||||
Message<?> barOutboundMessage = barSourceMessageCollector
|
||||
.forChannel(barSource.output()).poll(1000, TimeUnit.MILLISECONDS);
|
||||
|
||||
assertThat(barOutboundMessage).isNotNull();
|
||||
|
||||
@@ -159,30 +169,36 @@ public class AvroSchemaMessageConverterTests {
|
||||
secondUser2OutboundPojo.setFavoritePlace("foo" + UUID.randomUUID().toString());
|
||||
secondUser2OutboundPojo.setName("foo" + UUID.randomUUID().toString());
|
||||
source.output().send(MessageBuilder.withPayload(secondUser2OutboundPojo).build());
|
||||
Message<?> secondBarOutboundMessage = sourceMessageCollector.forChannel(source.output()).poll(1000,
|
||||
TimeUnit.MILLISECONDS);
|
||||
Message<?> secondBarOutboundMessage = sourceMessageCollector
|
||||
.forChannel(source.output()).poll(1000, TimeUnit.MILLISECONDS);
|
||||
|
||||
ConfigurableApplicationContext sinkContext = SpringApplication.run(AvroSinkApplication.class,
|
||||
"--server.port=0",
|
||||
ConfigurableApplicationContext sinkContext = SpringApplication.run(
|
||||
AvroSinkApplication.class, "--server.port=0",
|
||||
"--spring.jmx.enabled=false",
|
||||
"--spring.cloud.stream.schemaRegistryClient.enabled=false");
|
||||
Sink sink = sinkContext.getBean(Sink.class);
|
||||
sink.input().send(outboundMessage);
|
||||
sink.input().send(barOutboundMessage);
|
||||
sink.input().send(secondBarOutboundMessage);
|
||||
List<User1> receivedUsers = sinkContext.getBean(AvroSinkApplication.class).receivedUsers;
|
||||
List<User1> receivedUsers = sinkContext
|
||||
.getBean(AvroSinkApplication.class).receivedUsers;
|
||||
assertThat(receivedUsers).hasSize(3);
|
||||
assertThat(receivedUsers.get(0)).isNotSameAs(firstOutboundFoo);
|
||||
assertThat(receivedUsers.get(0).getFavoriteColor()).isEqualTo(firstOutboundFoo.getFavoriteColor());
|
||||
assertThat(receivedUsers.get(0).getFavoriteColor())
|
||||
.isEqualTo(firstOutboundFoo.getFavoriteColor());
|
||||
assertThat(receivedUsers.get(0).getName()).isEqualTo(firstOutboundFoo.getName());
|
||||
|
||||
assertThat(receivedUsers.get(1)).isNotSameAs(firstOutboundUser2);
|
||||
assertThat(receivedUsers.get(1).getFavoriteColor()).isEqualTo(firstOutboundUser2.getFavoriteColor());
|
||||
assertThat(receivedUsers.get(1).getName()).isEqualTo(firstOutboundUser2.getName());
|
||||
assertThat(receivedUsers.get(1).getFavoriteColor())
|
||||
.isEqualTo(firstOutboundUser2.getFavoriteColor());
|
||||
assertThat(receivedUsers.get(1).getName())
|
||||
.isEqualTo(firstOutboundUser2.getName());
|
||||
|
||||
assertThat(receivedUsers.get(2)).isNotSameAs(secondUser2OutboundPojo);
|
||||
assertThat(receivedUsers.get(2).getFavoriteColor()).isEqualTo(secondUser2OutboundPojo.getFavoriteColor());
|
||||
assertThat(receivedUsers.get(2).getName()).isEqualTo(secondUser2OutboundPojo.getName());
|
||||
assertThat(receivedUsers.get(2).getFavoriteColor())
|
||||
.isEqualTo(secondUser2OutboundPojo.getFavoriteColor());
|
||||
assertThat(receivedUsers.get(2).getName())
|
||||
.isEqualTo(secondUser2OutboundPojo.getName());
|
||||
|
||||
sourceContext.close();
|
||||
}
|
||||
@@ -208,11 +224,12 @@ public class AvroSchemaMessageConverterTests {
|
||||
public MessageConverter userMessageConverter() throws IOException {
|
||||
AvroSchemaMessageConverter avroSchemaMessageConverter = new AvroSchemaMessageConverter(
|
||||
MimeType.valueOf("avro/bytes"));
|
||||
if (schemaLocation != null) {
|
||||
avroSchemaMessageConverter.setSchemaLocation(schemaLocation);
|
||||
if (this.schemaLocation != null) {
|
||||
avroSchemaMessageConverter.setSchemaLocation(this.schemaLocation);
|
||||
}
|
||||
return avroSchemaMessageConverter;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableBinding(Sink.class)
|
||||
@@ -226,7 +243,7 @@ public class AvroSchemaMessageConverterTests {
|
||||
|
||||
@StreamListener(Sink.INPUT)
|
||||
public void listen(User1 user) {
|
||||
receivedUsers.add(user);
|
||||
this.receivedUsers.add(user);
|
||||
}
|
||||
|
||||
public void setSchemaLocation(Resource schemaLocation) {
|
||||
@@ -238,11 +255,12 @@ public class AvroSchemaMessageConverterTests {
|
||||
public MessageConverter userMessageConverter() throws IOException {
|
||||
AvroSchemaMessageConverter avroSchemaMessageConverter = new AvroSchemaMessageConverter(
|
||||
MimeType.valueOf("avro/bytes"));
|
||||
if (schemaLocation != null) {
|
||||
avroSchemaMessageConverter.setSchemaLocation(schemaLocation);
|
||||
if (this.schemaLocation != null) {
|
||||
avroSchemaMessageConverter.setSchemaLocation(this.schemaLocation);
|
||||
}
|
||||
return avroSchemaMessageConverter;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -59,200 +59,195 @@ import static org.springframework.cloud.schema.avro.AvroMessageConverterSerializ
|
||||
*/
|
||||
public class AvroSchemaRegistryClientMessageConverterTests {
|
||||
|
||||
static SchemaRegistryClient stubSchemaRegistryClient = new StubSchemaRegistryClient();
|
||||
static SchemaRegistryClient stubSchemaRegistryClient = new StubSchemaRegistryClient();
|
||||
|
||||
private ConfigurableApplicationContext schemaRegistryServerContext;
|
||||
private ConfigurableApplicationContext schemaRegistryServerContext;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
schemaRegistryServerContext = SpringApplication
|
||||
.run(SchemaRegistryServerApplication.class,
|
||||
"--spring.main.allow-bean-definition-overriding=true");
|
||||
@Before
|
||||
public void setup() {
|
||||
this.schemaRegistryServerContext = SpringApplication.run(
|
||||
SchemaRegistryServerApplication.class,
|
||||
"--spring.main.allow-bean-definition-overriding=true");
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
this.schemaRegistryServerContext.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendMessage() throws Exception {
|
||||
|
||||
ConfigurableApplicationContext sourceContext = SpringApplication.run(
|
||||
AvroSourceApplication.class, "--server.port=0",
|
||||
"--spring.jmx.enabled=false",
|
||||
"--spring.cloud.stream.bindings.output.contentType=application/*+avro",
|
||||
"--spring.cloud.stream.schema.avro.dynamicSchemaGenerationEnabled=true");
|
||||
Source source = sourceContext.getBean(Source.class);
|
||||
User1 firstOutboundFoo = new User1();
|
||||
firstOutboundFoo.setFavoriteColor("foo" + UUID.randomUUID().toString());
|
||||
firstOutboundFoo.setName("foo" + UUID.randomUUID().toString());
|
||||
source.output().send(MessageBuilder.withPayload(firstOutboundFoo).build());
|
||||
MessageCollector sourceMessageCollector = sourceContext
|
||||
.getBean(MessageCollector.class);
|
||||
Message<?> outboundMessage = sourceMessageCollector.forChannel(source.output())
|
||||
.poll(1000, TimeUnit.MILLISECONDS);
|
||||
|
||||
ConfigurableApplicationContext barSourceContext = SpringApplication.run(
|
||||
AvroSourceApplication.class, "--server.port=0",
|
||||
"--spring.jmx.enabled=false",
|
||||
"--spring.cloud.stream.bindings.output.contentType=application/vnd.user1.v1+avro",
|
||||
"--spring.cloud.stream.schema.avro.dynamicSchemaGenerationEnabled=true");
|
||||
Source barSource = barSourceContext.getBean(Source.class);
|
||||
User2 firstOutboundUser2 = new User2();
|
||||
firstOutboundUser2.setFavoriteColor("foo" + UUID.randomUUID().toString());
|
||||
firstOutboundUser2.setName("foo" + UUID.randomUUID().toString());
|
||||
barSource.output().send(MessageBuilder.withPayload(firstOutboundUser2).build());
|
||||
MessageCollector barSourceMessageCollector = barSourceContext
|
||||
.getBean(MessageCollector.class);
|
||||
Message<?> barOutboundMessage = barSourceMessageCollector
|
||||
.forChannel(barSource.output()).poll(1000, TimeUnit.MILLISECONDS);
|
||||
|
||||
assertThat(barOutboundMessage).isNotNull();
|
||||
|
||||
User2 secondBarOutboundPojo = new User2();
|
||||
secondBarOutboundPojo.setFavoriteColor("foo" + UUID.randomUUID().toString());
|
||||
secondBarOutboundPojo.setName("foo" + UUID.randomUUID().toString());
|
||||
source.output().send(MessageBuilder.withPayload(secondBarOutboundPojo).build());
|
||||
Message<?> secondBarOutboundMessage = sourceMessageCollector
|
||||
.forChannel(source.output()).poll(1000, TimeUnit.MILLISECONDS);
|
||||
|
||||
ConfigurableApplicationContext sinkContext = SpringApplication.run(
|
||||
AvroSinkApplication.class, "--server.port=0",
|
||||
"--spring.jmx.enabled=false");
|
||||
Sink sink = sinkContext.getBean(Sink.class);
|
||||
sink.input().send(outboundMessage);
|
||||
sink.input().send(barOutboundMessage);
|
||||
sink.input().send(secondBarOutboundMessage);
|
||||
List<User2> receivedPojos = sinkContext
|
||||
.getBean(AvroSinkApplication.class).receivedPojos;
|
||||
assertThat(receivedPojos).hasSize(3);
|
||||
assertThat(receivedPojos.get(0)).isNotSameAs(firstOutboundFoo);
|
||||
assertThat(receivedPojos.get(0).getFavoriteColor())
|
||||
.isEqualTo(firstOutboundFoo.getFavoriteColor());
|
||||
assertThat(receivedPojos.get(0).getName()).isEqualTo(firstOutboundFoo.getName());
|
||||
assertThat(receivedPojos.get(0).getFavoritePlace()).isEqualTo("NYC");
|
||||
|
||||
assertThat(receivedPojos.get(1)).isNotSameAs(firstOutboundUser2);
|
||||
assertThat(receivedPojos.get(1).getFavoriteColor())
|
||||
.isEqualTo(firstOutboundUser2.getFavoriteColor());
|
||||
assertThat(receivedPojos.get(1).getName())
|
||||
.isEqualTo(firstOutboundUser2.getName());
|
||||
assertThat(receivedPojos.get(1).getFavoritePlace()).isEqualTo("Boston");
|
||||
|
||||
assertThat(receivedPojos.get(2)).isNotSameAs(secondBarOutboundPojo);
|
||||
assertThat(receivedPojos.get(2).getFavoriteColor())
|
||||
.isEqualTo(secondBarOutboundPojo.getFavoriteColor());
|
||||
assertThat(receivedPojos.get(2).getName())
|
||||
.isEqualTo(secondBarOutboundPojo.getName());
|
||||
assertThat(receivedPojos.get(2).getFavoritePlace())
|
||||
.isEqualTo(secondBarOutboundPojo.getFavoritePlace());
|
||||
|
||||
sinkContext.close();
|
||||
barSourceContext.close();
|
||||
sourceContext.close();
|
||||
this.schemaRegistryServerContext.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSchemaImportConfiguration() throws Exception {
|
||||
final String[] args = { "--server.port=0", "--spring.jmx.enabled=false",
|
||||
"--spring.cloud.stream.schema.avro.dynamicSchemaGenerationEnabled=true",
|
||||
"--spring.cloud.stream.bindings.output.contentType=application/*+avro",
|
||||
"--spring.cloud.stream.bindings.output.destination=test",
|
||||
"--spring.cloud.stream.bindings.schema-registry-client.endpoint=http://localhost:8990",
|
||||
"--spring.cloud.stream.schema.avro.schema-locations=classpath:schemas/Command.avsc",
|
||||
"--spring.cloud.stream.schema.avro.schema-imports=classpath:schemas/imports/Sms.avsc,"
|
||||
+ " classpath:schemas/imports/Email.avsc, classpath:schemas/imports/PushNotification.avsc" };
|
||||
|
||||
final ConfigurableApplicationContext sourceContext = SpringApplication
|
||||
.run(AvroSourceApplication.class, args);
|
||||
final ConfigurableApplicationContext sinkContext = SpringApplication
|
||||
.run(CommandSinkApplication.class, args);
|
||||
final Source barSource = sourceContext.getBean(Source.class);
|
||||
final Command notification = notification();
|
||||
barSource.output().send(MessageBuilder.withPayload(notification).build());
|
||||
final MessageCollector barSourceMessageCollector = sourceContext
|
||||
.getBean(MessageCollector.class);
|
||||
final Message<?> outboundMessage = barSourceMessageCollector
|
||||
.forChannel(barSource.output()).poll(1000, TimeUnit.MILLISECONDS);
|
||||
assertThat(outboundMessage).isNotNull();
|
||||
Sink sink = sinkContext.getBean(Sink.class);
|
||||
sink.input().send(outboundMessage);
|
||||
List<Command> receivedPojos = sinkContext
|
||||
.getBean(CommandSinkApplication.class).receivedPojos;
|
||||
|
||||
assertThat(receivedPojos).hasSize(1);
|
||||
assertThat(receivedPojos.get(0)).isEqualTo(notification);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoCacheConfiguration() {
|
||||
ConfigurableApplicationContext sourceContext = SpringApplication
|
||||
.run(NoCacheConfiguration.class, "--spring.main.web-environment=false");
|
||||
AvroSchemaRegistryClientMessageConverter converter = sourceContext
|
||||
.getBean(AvroSchemaRegistryClientMessageConverter.class);
|
||||
DirectFieldAccessor accessor = new DirectFieldAccessor(converter);
|
||||
assertThat(accessor.getPropertyValue("cacheManager"))
|
||||
.isInstanceOf(NoOpCacheManager.class);
|
||||
}
|
||||
|
||||
@EnableBinding(Source.class)
|
||||
@EnableAutoConfiguration
|
||||
@EnableSchemaRegistryClient
|
||||
public static class AvroSourceApplication {
|
||||
|
||||
}
|
||||
|
||||
@EnableBinding(Sink.class)
|
||||
@EnableAutoConfiguration
|
||||
@EnableSchemaRegistryClient
|
||||
public static class AvroSinkApplication {
|
||||
|
||||
public List<User2> receivedPojos = new ArrayList<>();
|
||||
|
||||
@StreamListener(Sink.INPUT)
|
||||
public void listen(User2 fooPojo) {
|
||||
this.receivedPojos.add(fooPojo);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
schemaRegistryServerContext.close();
|
||||
}
|
||||
|
||||
@EnableBinding(Sink.class)
|
||||
@EnableAutoConfiguration
|
||||
@EnableSchemaRegistryClient
|
||||
public static class CommandSinkApplication {
|
||||
|
||||
public List<Command> receivedPojos = new ArrayList<>();
|
||||
|
||||
@StreamListener(Sink.INPUT)
|
||||
public void listen(Command fooPojo) {
|
||||
this.receivedPojos.add(fooPojo);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendMessage() throws Exception {
|
||||
}
|
||||
|
||||
ConfigurableApplicationContext sourceContext = SpringApplication
|
||||
.run(AvroSourceApplication.class, "--server.port=0",
|
||||
"--spring.jmx.enabled=false",
|
||||
"--spring.cloud.stream.bindings.output.contentType=application/*+avro",
|
||||
"--spring.cloud.stream.schema.avro.dynamicSchemaGenerationEnabled=true");
|
||||
Source source = sourceContext.getBean(Source.class);
|
||||
User1 firstOutboundFoo = new User1();
|
||||
firstOutboundFoo.setFavoriteColor("foo" + UUID.randomUUID().toString());
|
||||
firstOutboundFoo.setName("foo" + UUID.randomUUID().toString());
|
||||
source.output()
|
||||
.send(MessageBuilder.withPayload(firstOutboundFoo).build());
|
||||
MessageCollector sourceMessageCollector = sourceContext
|
||||
.getBean(MessageCollector.class);
|
||||
Message<?> outboundMessage = sourceMessageCollector
|
||||
.forChannel(source.output()).poll(1000, TimeUnit.MILLISECONDS);
|
||||
@Configuration
|
||||
public static class NoCacheConfiguration {
|
||||
|
||||
ConfigurableApplicationContext barSourceContext = SpringApplication
|
||||
.run(AvroSourceApplication.class, "--server.port=0",
|
||||
"--spring.jmx.enabled=false",
|
||||
"--spring.cloud.stream.bindings.output.contentType=application/vnd.user1.v1+avro",
|
||||
"--spring.cloud.stream.schema.avro.dynamicSchemaGenerationEnabled=true");
|
||||
Source barSource = barSourceContext.getBean(Source.class);
|
||||
User2 firstOutboundUser2 = new User2();
|
||||
firstOutboundUser2.setFavoriteColor("foo" + UUID.randomUUID().toString());
|
||||
firstOutboundUser2.setName("foo" + UUID.randomUUID().toString());
|
||||
barSource.output()
|
||||
.send(MessageBuilder.withPayload(firstOutboundUser2).build());
|
||||
MessageCollector barSourceMessageCollector = barSourceContext
|
||||
.getBean(MessageCollector.class);
|
||||
Message<?> barOutboundMessage = barSourceMessageCollector
|
||||
.forChannel(barSource.output()).poll(1000, TimeUnit.MILLISECONDS);
|
||||
|
||||
assertThat(barOutboundMessage).isNotNull();
|
||||
|
||||
User2 secondBarOutboundPojo = new User2();
|
||||
secondBarOutboundPojo
|
||||
.setFavoriteColor("foo" + UUID.randomUUID().toString());
|
||||
secondBarOutboundPojo.setName("foo" + UUID.randomUUID().toString());
|
||||
source.output()
|
||||
.send(MessageBuilder.withPayload(secondBarOutboundPojo).build());
|
||||
Message<?> secondBarOutboundMessage = sourceMessageCollector
|
||||
.forChannel(source.output()).poll(1000, TimeUnit.MILLISECONDS);
|
||||
|
||||
ConfigurableApplicationContext sinkContext = SpringApplication
|
||||
.run(AvroSinkApplication.class, "--server.port=0",
|
||||
"--spring.jmx.enabled=false");
|
||||
Sink sink = sinkContext.getBean(Sink.class);
|
||||
sink.input().send(outboundMessage);
|
||||
sink.input().send(barOutboundMessage);
|
||||
sink.input().send(secondBarOutboundMessage);
|
||||
List<User2> receivedPojos = sinkContext
|
||||
.getBean(AvroSinkApplication.class).receivedPojos;
|
||||
assertThat(receivedPojos).hasSize(3);
|
||||
assertThat(receivedPojos.get(0)).isNotSameAs(firstOutboundFoo);
|
||||
assertThat(receivedPojos.get(0).getFavoriteColor())
|
||||
.isEqualTo(firstOutboundFoo.getFavoriteColor());
|
||||
assertThat(receivedPojos.get(0).getName())
|
||||
.isEqualTo(firstOutboundFoo.getName());
|
||||
assertThat(receivedPojos.get(0).getFavoritePlace()).isEqualTo("NYC");
|
||||
|
||||
assertThat(receivedPojos.get(1)).isNotSameAs(firstOutboundUser2);
|
||||
assertThat(receivedPojos.get(1).getFavoriteColor())
|
||||
.isEqualTo(firstOutboundUser2.getFavoriteColor());
|
||||
assertThat(receivedPojos.get(1).getName())
|
||||
.isEqualTo(firstOutboundUser2.getName());
|
||||
assertThat(receivedPojos.get(1).getFavoritePlace()).isEqualTo("Boston");
|
||||
|
||||
assertThat(receivedPojos.get(2)).isNotSameAs(secondBarOutboundPojo);
|
||||
assertThat(receivedPojos.get(2).getFavoriteColor())
|
||||
.isEqualTo(secondBarOutboundPojo.getFavoriteColor());
|
||||
assertThat(receivedPojos.get(2).getName())
|
||||
.isEqualTo(secondBarOutboundPojo.getName());
|
||||
assertThat(receivedPojos.get(2).getFavoritePlace())
|
||||
.isEqualTo(secondBarOutboundPojo.getFavoritePlace());
|
||||
|
||||
sinkContext.close();
|
||||
barSourceContext.close();
|
||||
sourceContext.close();
|
||||
schemaRegistryServerContext.close();
|
||||
@Bean
|
||||
@StreamMessageConverter
|
||||
AvroSchemaRegistryClientMessageConverter avroSchemaRegistryClientMessageConverter() {
|
||||
return new AvroSchemaRegistryClientMessageConverter(
|
||||
new DefaultSchemaRegistryClient(), new NoOpCacheManager());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSchemaImportConfiguration() throws Exception{
|
||||
final String[] args = { "--server.port=0", "--spring.jmx.enabled=false",
|
||||
"--spring.cloud.stream.schema.avro.dynamicSchemaGenerationEnabled=true",
|
||||
"--spring.cloud.stream.bindings.output.contentType=application/*+avro",
|
||||
"--spring.cloud.stream.bindings.output.destination=test",
|
||||
"--spring.cloud.stream.bindings.schema-registry-client.endpoint=http://localhost:8990",
|
||||
"--spring.cloud.stream.schema.avro.schema-locations=classpath:schemas/Command.avsc",
|
||||
"--spring.cloud.stream.schema.avro.schema-imports=classpath:schemas/imports/Sms.avsc, classpath:schemas/imports/Email.avsc, classpath:schemas/imports/PushNotification.avsc" };
|
||||
|
||||
final ConfigurableApplicationContext sourceContext = SpringApplication
|
||||
.run(AvroSourceApplication.class, args);
|
||||
final ConfigurableApplicationContext sinkContext = SpringApplication
|
||||
.run(CommandSinkApplication.class, args);
|
||||
final Source barSource = sourceContext.getBean(Source.class);
|
||||
final Command notification = notification();
|
||||
barSource.output()
|
||||
.send(MessageBuilder.withPayload(notification).build());
|
||||
final MessageCollector barSourceMessageCollector = sourceContext
|
||||
.getBean(MessageCollector.class);
|
||||
final Message<?> outboundMessage = barSourceMessageCollector
|
||||
.forChannel(barSource.output()).poll(1000, TimeUnit.MILLISECONDS);
|
||||
assertThat(outboundMessage).isNotNull();
|
||||
Sink sink = sinkContext.getBean(Sink.class);
|
||||
sink.input().send(outboundMessage);
|
||||
List<Command> receivedPojos = sinkContext
|
||||
.getBean(CommandSinkApplication.class).receivedPojos;
|
||||
|
||||
assertThat(receivedPojos).hasSize(1);
|
||||
assertThat(receivedPojos.get(0)).isEqualTo(notification);
|
||||
|
||||
@Bean
|
||||
ServletWebServerFactory servletWebServerFactory() {
|
||||
return new TomcatServletWebServerFactory();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoCacheConfiguration() {
|
||||
ConfigurableApplicationContext sourceContext = SpringApplication
|
||||
.run(NoCacheConfiguration.class,
|
||||
"--spring.main.web-environment=false");
|
||||
AvroSchemaRegistryClientMessageConverter converter = sourceContext
|
||||
.getBean(AvroSchemaRegistryClientMessageConverter.class);
|
||||
DirectFieldAccessor accessor = new DirectFieldAccessor(converter);
|
||||
assertThat(accessor.getPropertyValue("cacheManager"))
|
||||
.isInstanceOf(NoOpCacheManager.class);
|
||||
}
|
||||
}
|
||||
|
||||
@EnableBinding(Source.class)
|
||||
@EnableAutoConfiguration
|
||||
@EnableSchemaRegistryClient
|
||||
public static class AvroSourceApplication {
|
||||
|
||||
}
|
||||
|
||||
@EnableBinding(Sink.class)
|
||||
@EnableAutoConfiguration
|
||||
@EnableSchemaRegistryClient
|
||||
public static class AvroSinkApplication {
|
||||
|
||||
public List<User2> receivedPojos = new ArrayList<>();
|
||||
|
||||
@StreamListener(Sink.INPUT)
|
||||
public void listen(User2 fooPojo) {
|
||||
receivedPojos.add(fooPojo);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableBinding(Sink.class)
|
||||
@EnableAutoConfiguration
|
||||
@EnableSchemaRegistryClient
|
||||
public static class CommandSinkApplication {
|
||||
|
||||
public List<Command> receivedPojos = new ArrayList<>();
|
||||
|
||||
@StreamListener(Sink.INPUT)
|
||||
public void listen(Command fooPojo) {
|
||||
receivedPojos.add(fooPojo);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class NoCacheConfiguration {
|
||||
|
||||
@Bean
|
||||
@StreamMessageConverter
|
||||
AvroSchemaRegistryClientMessageConverter avroSchemaRegistryClientMessageConverter() {
|
||||
return new AvroSchemaRegistryClientMessageConverter(
|
||||
new DefaultSchemaRegistryClient(),
|
||||
new NoOpCacheManager());
|
||||
}
|
||||
|
||||
@Bean
|
||||
ServletWebServerFactory servletWebServerFactory() {
|
||||
return new TomcatServletWebServerFactory();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2016-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.
|
||||
@@ -47,9 +47,8 @@ public class AvroStubSchemaRegistryClientMessageConverterTests {
|
||||
|
||||
@Test
|
||||
public void testSendMessage() throws Exception {
|
||||
ConfigurableApplicationContext sourceContext = SpringApplication.run(AvroSourceApplication.class,
|
||||
"--server.port=0",
|
||||
"--debug",
|
||||
ConfigurableApplicationContext sourceContext = SpringApplication.run(
|
||||
AvroSourceApplication.class, "--server.port=0", "--debug",
|
||||
"--spring.jmx.enabled=false",
|
||||
"--spring.cloud.stream.bindings.output.contentType=application/*+avro",
|
||||
"--spring.cloud.stream.schema.avro.dynamicSchemaGenerationEnabled=true");
|
||||
@@ -58,12 +57,13 @@ public class AvroStubSchemaRegistryClientMessageConverterTests {
|
||||
firstOutboundFoo.setFavoriteColor("foo" + UUID.randomUUID().toString());
|
||||
firstOutboundFoo.setName("foo" + UUID.randomUUID().toString());
|
||||
source.output().send(MessageBuilder.withPayload(firstOutboundFoo).build());
|
||||
MessageCollector sourceMessageCollector = sourceContext.getBean(MessageCollector.class);
|
||||
Message<?> outboundMessage = sourceMessageCollector.forChannel(source.output()).poll(1000,
|
||||
TimeUnit.MILLISECONDS);
|
||||
MessageCollector sourceMessageCollector = sourceContext
|
||||
.getBean(MessageCollector.class);
|
||||
Message<?> outboundMessage = sourceMessageCollector.forChannel(source.output())
|
||||
.poll(1000, TimeUnit.MILLISECONDS);
|
||||
|
||||
ConfigurableApplicationContext barSourceContext = SpringApplication.run(AvroSourceApplication.class,
|
||||
"--server.port=0",
|
||||
ConfigurableApplicationContext barSourceContext = SpringApplication.run(
|
||||
AvroSourceApplication.class, "--server.port=0",
|
||||
"--spring.jmx.enabled=false",
|
||||
"--spring.cloud.stream.bindings.output.contentType=application/vnd.user1.v1+avro",
|
||||
"--spring.cloud.stream.schema.avro.dynamicSchemaGenerationEnabled=true");
|
||||
@@ -72,9 +72,10 @@ public class AvroStubSchemaRegistryClientMessageConverterTests {
|
||||
firstOutboundUser2.setFavoriteColor("foo" + UUID.randomUUID().toString());
|
||||
firstOutboundUser2.setName("foo" + UUID.randomUUID().toString());
|
||||
barSource.output().send(MessageBuilder.withPayload(firstOutboundUser2).build());
|
||||
MessageCollector barSourceMessageCollector = barSourceContext.getBean(MessageCollector.class);
|
||||
Message<?> barOutboundMessage = barSourceMessageCollector.forChannel(barSource.output()).poll(1000,
|
||||
TimeUnit.MILLISECONDS);
|
||||
MessageCollector barSourceMessageCollector = barSourceContext
|
||||
.getBean(MessageCollector.class);
|
||||
Message<?> barOutboundMessage = barSourceMessageCollector
|
||||
.forChannel(barSource.output()).poll(1000, TimeUnit.MILLISECONDS);
|
||||
|
||||
assertThat(barOutboundMessage).isNotNull();
|
||||
|
||||
@@ -82,31 +83,39 @@ public class AvroStubSchemaRegistryClientMessageConverterTests {
|
||||
secondBarOutboundPojo.setFavoriteColor("foo" + UUID.randomUUID().toString());
|
||||
secondBarOutboundPojo.setName("foo" + UUID.randomUUID().toString());
|
||||
source.output().send(MessageBuilder.withPayload(secondBarOutboundPojo).build());
|
||||
Message<?> secondBarOutboundMessage = sourceMessageCollector.forChannel(source.output()).poll(1000,
|
||||
TimeUnit.MILLISECONDS);
|
||||
Message<?> secondBarOutboundMessage = sourceMessageCollector
|
||||
.forChannel(source.output()).poll(1000, TimeUnit.MILLISECONDS);
|
||||
|
||||
ConfigurableApplicationContext sinkContext = SpringApplication.run(AvroSinkApplication.class,
|
||||
"--server.port=0", "--spring.jmx.enabled=false");
|
||||
ConfigurableApplicationContext sinkContext = SpringApplication.run(
|
||||
AvroSinkApplication.class, "--server.port=0",
|
||||
"--spring.jmx.enabled=false");
|
||||
Sink sink = sinkContext.getBean(Sink.class);
|
||||
sink.input().send(outboundMessage);
|
||||
sink.input().send(barOutboundMessage);
|
||||
sink.input().send(secondBarOutboundMessage);
|
||||
List<User2> receivedPojos = sinkContext.getBean(AvroSinkApplication.class).receivedPojos;
|
||||
List<User2> receivedPojos = sinkContext
|
||||
.getBean(AvroSinkApplication.class).receivedPojos;
|
||||
assertThat(receivedPojos).hasSize(3);
|
||||
assertThat(receivedPojos.get(0)).isNotSameAs(firstOutboundFoo);
|
||||
assertThat(receivedPojos.get(0).getFavoriteColor()).isEqualTo(firstOutboundFoo.getFavoriteColor());
|
||||
assertThat(receivedPojos.get(0).getFavoriteColor())
|
||||
.isEqualTo(firstOutboundFoo.getFavoriteColor());
|
||||
assertThat(receivedPojos.get(0).getName()).isEqualTo(firstOutboundFoo.getName());
|
||||
assertThat(receivedPojos.get(0).getFavoritePlace()).isEqualTo("NYC");
|
||||
|
||||
assertThat(receivedPojos.get(1)).isNotSameAs(firstOutboundUser2);
|
||||
assertThat(receivedPojos.get(1).getFavoriteColor()).isEqualTo(firstOutboundUser2.getFavoriteColor());
|
||||
assertThat(receivedPojos.get(1).getName()).isEqualTo(firstOutboundUser2.getName());
|
||||
assertThat(receivedPojos.get(1).getFavoriteColor())
|
||||
.isEqualTo(firstOutboundUser2.getFavoriteColor());
|
||||
assertThat(receivedPojos.get(1).getName())
|
||||
.isEqualTo(firstOutboundUser2.getName());
|
||||
assertThat(receivedPojos.get(1).getFavoritePlace()).isEqualTo("Boston");
|
||||
|
||||
assertThat(receivedPojos.get(2)).isNotSameAs(secondBarOutboundPojo);
|
||||
assertThat(receivedPojos.get(2).getFavoriteColor()).isEqualTo(secondBarOutboundPojo.getFavoriteColor());
|
||||
assertThat(receivedPojos.get(2).getName()).isEqualTo(secondBarOutboundPojo.getName());
|
||||
assertThat(receivedPojos.get(2).getFavoritePlace()).isEqualTo(secondBarOutboundPojo.getFavoritePlace());
|
||||
assertThat(receivedPojos.get(2).getFavoriteColor())
|
||||
.isEqualTo(secondBarOutboundPojo.getFavoriteColor());
|
||||
assertThat(receivedPojos.get(2).getName())
|
||||
.isEqualTo(secondBarOutboundPojo.getName());
|
||||
assertThat(receivedPojos.get(2).getFavoritePlace())
|
||||
.isEqualTo(secondBarOutboundPojo.getFavoritePlace());
|
||||
|
||||
sourceContext.close();
|
||||
}
|
||||
@@ -119,6 +128,7 @@ public class AvroStubSchemaRegistryClientMessageConverterTests {
|
||||
public SchemaRegistryClient schemaRegistryClient() {
|
||||
return stubSchemaRegistryClient;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableBinding(Sink.class)
|
||||
@@ -129,7 +139,7 @@ public class AvroStubSchemaRegistryClientMessageConverterTests {
|
||||
|
||||
@StreamListener(Sink.INPUT)
|
||||
public void listen(User2 fooPojo) {
|
||||
receivedPojos.add(fooPojo);
|
||||
this.receivedPojos.add(fooPojo);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -138,4 +148,5 @@ public class AvroStubSchemaRegistryClientMessageConverterTests {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,4 +32,5 @@ class CustomSubjectNamingStrategy implements SubjectNamingStrategy {
|
||||
public String toSubject(Schema schema) {
|
||||
return schema.getFullName();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2016-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.
|
||||
@@ -39,12 +39,14 @@ public class StubSchemaRegistryClient implements SchemaRegistryClient {
|
||||
private final Map<String, Map<Integer, SchemaWithId>> storedSchemas = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public SchemaRegistrationResponse register(String subject, String format, String schema) {
|
||||
public SchemaRegistrationResponse register(String subject, String format,
|
||||
String schema) {
|
||||
if (!this.storedSchemas.containsKey(subject)) {
|
||||
this.storedSchemas.put(subject, new TreeMap<Integer, SchemaWithId>());
|
||||
}
|
||||
Map<Integer, SchemaWithId> schemaVersions = this.storedSchemas.get(subject);
|
||||
for (Map.Entry<Integer, SchemaWithId> integerSchemaEntry : schemaVersions.entrySet()) {
|
||||
for (Map.Entry<Integer, SchemaWithId> integerSchemaEntry : schemaVersions
|
||||
.entrySet()) {
|
||||
|
||||
if (integerSchemaEntry.getValue().getSchema().equals(schema)) {
|
||||
SchemaRegistrationResponse schemaRegistrationResponse = new SchemaRegistrationResponse();
|
||||
@@ -60,24 +62,27 @@ public class StubSchemaRegistryClient implements SchemaRegistryClient {
|
||||
schemaVersions.put(nextVersion, new SchemaWithId(id, schema));
|
||||
SchemaRegistrationResponse schemaRegistrationResponse = new SchemaRegistrationResponse();
|
||||
schemaRegistrationResponse.setId(this.index.getAndIncrement());
|
||||
schemaRegistrationResponse.setSchemaReference(
|
||||
new SchemaReference(subject, nextVersion, AvroSchemaRegistryClientMessageConverter.AVRO_FORMAT));
|
||||
schemaRegistrationResponse.setSchemaReference(new SchemaReference(subject,
|
||||
nextVersion, AvroSchemaRegistryClientMessageConverter.AVRO_FORMAT));
|
||||
this.schemasById.put(id, schema);
|
||||
return schemaRegistrationResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String fetch(SchemaReference schemaReference) {
|
||||
if (!AvroSchemaRegistryClientMessageConverter.AVRO_FORMAT.equals(schemaReference.getFormat())) {
|
||||
if (!AvroSchemaRegistryClientMessageConverter.AVRO_FORMAT
|
||||
.equals(schemaReference.getFormat())) {
|
||||
throw new IllegalArgumentException("Only 'avro' is supported by this client");
|
||||
}
|
||||
if (!this.storedSchemas.containsKey(schemaReference.getSubject())) {
|
||||
throw new SchemaNotFoundException("Not found: " + schemaReference);
|
||||
}
|
||||
if (!this.storedSchemas.get(schemaReference.getSubject()).containsKey(schemaReference.getVersion())) {
|
||||
if (!this.storedSchemas.get(schemaReference.getSubject())
|
||||
.containsKey(schemaReference.getVersion())) {
|
||||
throw new SchemaNotFoundException("Not found: " + schemaReference);
|
||||
}
|
||||
return this.storedSchemas.get(schemaReference.getSubject()).get(schemaReference.getVersion()).getSchema();
|
||||
return this.storedSchemas.get(schemaReference.getSubject())
|
||||
.get(schemaReference.getVersion()).getSchema();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -103,6 +108,7 @@ public class StubSchemaRegistryClient implements SchemaRegistryClient {
|
||||
public String getSchema() {
|
||||
return this.schema;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -44,13 +44,13 @@ public class SubjectNamingStrategyTest {
|
||||
|
||||
@Test
|
||||
public void testCustomNamingStrategy() throws Exception {
|
||||
ConfigurableApplicationContext sourceContext = SpringApplication.run(AvroSourceApplication.class,
|
||||
"--server.port=0",
|
||||
"--debug",
|
||||
"--spring.jmx.enabled=false",
|
||||
"--spring.cloud.stream.bindings.output.contentType=application/*+avro",
|
||||
"--spring.cloud.stream.schema.avro.subjectNamingStrategy=org.springframework.cloud.schema.avro.CustomSubjectNamingStrategy",
|
||||
"--spring.cloud.stream.schema.avro.dynamicSchemaGenerationEnabled=true");
|
||||
ConfigurableApplicationContext sourceContext = SpringApplication.run(
|
||||
AvroSourceApplication.class, "--server.port=0", "--debug",
|
||||
"--spring.jmx.enabled=false",
|
||||
"--spring.cloud.stream.bindings.output.contentType=application/*+avro",
|
||||
"--spring.cloud.stream.schema.avro.subjectNamingStrategy="
|
||||
+ "org.springframework.cloud.schema.avro.CustomSubjectNamingStrategy",
|
||||
"--spring.cloud.stream.schema.avro.dynamicSchemaGenerationEnabled=true");
|
||||
|
||||
Source source = sourceContext.getBean(Source.class);
|
||||
User1 user1 = new User1();
|
||||
@@ -58,11 +58,13 @@ public class SubjectNamingStrategyTest {
|
||||
user1.setName("foo" + UUID.randomUUID().toString());
|
||||
source.output().send(MessageBuilder.withPayload(user1).build());
|
||||
|
||||
MessageCollector barSourceMessageCollector = sourceContext.getBean(MessageCollector.class);
|
||||
Message<?> message = barSourceMessageCollector.forChannel(source.output()).poll(1000, TimeUnit.MILLISECONDS);
|
||||
MessageCollector barSourceMessageCollector = sourceContext
|
||||
.getBean(MessageCollector.class);
|
||||
Message<?> message = barSourceMessageCollector.forChannel(source.output())
|
||||
.poll(1000, TimeUnit.MILLISECONDS);
|
||||
|
||||
assertThat(message.getHeaders().get("contentType"))
|
||||
.isEqualTo(MimeType.valueOf("application/vnd.org.springframework.cloud.schema.avro.User1.v1+avro"));
|
||||
assertThat(message.getHeaders().get("contentType")).isEqualTo(MimeType.valueOf(
|
||||
"application/vnd.org.springframework.cloud.schema.avro.User1.v1+avro"));
|
||||
}
|
||||
|
||||
@EnableBinding(Source.class)
|
||||
@@ -73,5 +75,7 @@ public class SubjectNamingStrategyTest {
|
||||
public SchemaRegistryClient schemaRegistryClient() {
|
||||
return stubSchemaRegistryClient;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2016-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.
|
||||
@@ -54,4 +54,5 @@ public class User1 {
|
||||
public void setFavoriteColor(String favoriteColor) {
|
||||
this.favoriteColor = favoriteColor;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2016-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.
|
||||
@@ -66,4 +66,5 @@ public class User2 {
|
||||
public void setFavoritePlace(String favoritePlace) {
|
||||
this.favoritePlace = favoritePlace;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
* Copyright 2017-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.
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.cloud.schema.avro.client;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -31,6 +30,7 @@ import org.springframework.test.web.client.MockRestServiceServer;
|
||||
import org.springframework.web.client.HttpStatusCodeException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.header;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
|
||||
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
|
||||
@@ -38,122 +38,139 @@ import static org.springframework.test.web.client.response.MockRestResponseCreat
|
||||
import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus;
|
||||
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
|
||||
|
||||
|
||||
/**
|
||||
* @author Vinicius Carvalho
|
||||
*/
|
||||
public class ConfluentSchemaRegistryClientTests {
|
||||
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
private MockRestServiceServer mockRestServiceServer;
|
||||
|
||||
@Before
|
||||
public void setup(){
|
||||
public void setup() {
|
||||
this.restTemplate = new RestTemplate();
|
||||
this.mockRestServiceServer = MockRestServiceServer.createServer(restTemplate);
|
||||
this.mockRestServiceServer = MockRestServiceServer
|
||||
.createServer(this.restTemplate);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerSchema() throws Exception{
|
||||
this.mockRestServiceServer.expect(requestTo("http://localhost:8081/subjects/user/versions"))
|
||||
public void registerSchema() throws Exception {
|
||||
this.mockRestServiceServer
|
||||
.expect(requestTo("http://localhost:8081/subjects/user/versions"))
|
||||
.andExpect(method(HttpMethod.POST))
|
||||
.andExpect(header("Content-Type","application/json"))
|
||||
.andExpect(header("Accept","application/vnd.schemaregistry.v1+json"))
|
||||
.andExpect(header("Content-Type", "application/json"))
|
||||
.andExpect(header("Accept", "application/vnd.schemaregistry.v1+json"))
|
||||
.andRespond(withSuccess("{\"id\":101}", MediaType.APPLICATION_JSON));
|
||||
|
||||
this.mockRestServiceServer.expect(requestTo("http://localhost:8081/subjects/user"))
|
||||
this.mockRestServiceServer
|
||||
.expect(requestTo("http://localhost:8081/subjects/user"))
|
||||
.andExpect(method(HttpMethod.POST))
|
||||
.andExpect(header("Content-Type","application/json"))
|
||||
.andExpect(header("Accept","application/vnd.schemaregistry.v1+json"))
|
||||
.andExpect(header("Content-Type", "application/json"))
|
||||
.andExpect(header("Accept", "application/vnd.schemaregistry.v1+json"))
|
||||
.andRespond(withSuccess("{\"version\":1}", MediaType.APPLICATION_JSON));
|
||||
|
||||
ConfluentSchemaRegistryClient client = new ConfluentSchemaRegistryClient(this.restTemplate);
|
||||
SchemaRegistrationResponse response = client.register("user","avro","{}");
|
||||
Assert.assertEquals(1,response.getSchemaReference().getVersion());
|
||||
Assert.assertEquals(101,response.getId());
|
||||
ConfluentSchemaRegistryClient client = new ConfluentSchemaRegistryClient(
|
||||
this.restTemplate);
|
||||
SchemaRegistrationResponse response = client.register("user", "avro", "{}");
|
||||
assertThat(response.getSchemaReference().getVersion()).isEqualTo(1);
|
||||
assertThat(response.getId()).isEqualTo(101);
|
||||
this.mockRestServiceServer.verify();
|
||||
}
|
||||
|
||||
@Test(expected = RuntimeException.class)
|
||||
public void registerWithInvalidJson() {
|
||||
this.mockRestServiceServer.expect(requestTo("http://localhost:8081/subjects/user/versions"))
|
||||
this.mockRestServiceServer
|
||||
.expect(requestTo("http://localhost:8081/subjects/user/versions"))
|
||||
.andExpect(method(HttpMethod.POST))
|
||||
.andExpect(header("Content-Type","application/json"))
|
||||
.andExpect(header("Accept","application/vnd.schemaregistry.v1+json"))
|
||||
.andExpect(header("Content-Type", "application/json"))
|
||||
.andExpect(header("Accept", "application/vnd.schemaregistry.v1+json"))
|
||||
.andRespond(withBadRequest());
|
||||
ConfluentSchemaRegistryClient client = new ConfluentSchemaRegistryClient(this.restTemplate);
|
||||
SchemaRegistrationResponse response = client.register("user","avro","<>");
|
||||
ConfluentSchemaRegistryClient client = new ConfluentSchemaRegistryClient(
|
||||
this.restTemplate);
|
||||
SchemaRegistrationResponse response = client.register("user", "avro", "<>");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerIncompatibleSchema() {
|
||||
this.mockRestServiceServer.expect(requestTo("http://localhost:8081/subjects/user/versions"))
|
||||
this.mockRestServiceServer
|
||||
.expect(requestTo("http://localhost:8081/subjects/user/versions"))
|
||||
.andExpect(method(HttpMethod.POST))
|
||||
.andExpect(header("Content-Type","application/json"))
|
||||
.andExpect(header("Accept","application/vnd.schemaregistry.v1+json"))
|
||||
.andExpect(header("Content-Type", "application/json"))
|
||||
.andExpect(header("Accept", "application/vnd.schemaregistry.v1+json"))
|
||||
.andRespond(withStatus(HttpStatus.CONFLICT));
|
||||
ConfluentSchemaRegistryClient client = new ConfluentSchemaRegistryClient(this.restTemplate);
|
||||
ConfluentSchemaRegistryClient client = new ConfluentSchemaRegistryClient(
|
||||
this.restTemplate);
|
||||
Exception expected = null;
|
||||
try {
|
||||
SchemaRegistrationResponse response = client.register("user","avro","{}");
|
||||
SchemaRegistrationResponse response = client.register("user", "avro", "{}");
|
||||
}
|
||||
catch (Exception e) {
|
||||
expected = e;
|
||||
}
|
||||
Assert.assertTrue(expected instanceof RuntimeException);
|
||||
Assert.assertTrue(expected.getCause() instanceof HttpStatusCodeException);
|
||||
assertThat(expected instanceof RuntimeException).isTrue();
|
||||
assertThat(expected.getCause() instanceof HttpStatusCodeException).isTrue();
|
||||
this.mockRestServiceServer.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void responseErrorFetch() {
|
||||
this.mockRestServiceServer.expect(requestTo("http://localhost:8081/subjects/user/versions"))
|
||||
this.mockRestServiceServer
|
||||
.expect(requestTo("http://localhost:8081/subjects/user/versions"))
|
||||
.andExpect(method(HttpMethod.POST))
|
||||
.andExpect(header("Content-Type","application/json"))
|
||||
.andExpect(header("Accept","application/vnd.schemaregistry.v1+json"))
|
||||
.andExpect(header("Content-Type", "application/json"))
|
||||
.andExpect(header("Accept", "application/vnd.schemaregistry.v1+json"))
|
||||
.andRespond(withSuccess("{\"id\":101}", MediaType.APPLICATION_JSON));
|
||||
|
||||
this.mockRestServiceServer.expect(requestTo("http://localhost:8081/subjects/user"))
|
||||
this.mockRestServiceServer
|
||||
.expect(requestTo("http://localhost:8081/subjects/user"))
|
||||
.andExpect(method(HttpMethod.POST))
|
||||
.andExpect(header("Content-Type","application/json"))
|
||||
.andExpect(header("Accept","application/vnd.schemaregistry.v1+json"))
|
||||
.andExpect(header("Content-Type", "application/json"))
|
||||
.andExpect(header("Accept", "application/vnd.schemaregistry.v1+json"))
|
||||
.andRespond(withBadRequest());
|
||||
ConfluentSchemaRegistryClient client = new ConfluentSchemaRegistryClient(this.restTemplate);
|
||||
ConfluentSchemaRegistryClient client = new ConfluentSchemaRegistryClient(
|
||||
this.restTemplate);
|
||||
Exception expected = null;
|
||||
try {
|
||||
SchemaRegistrationResponse response = client.register("user","avro","{}");
|
||||
SchemaRegistrationResponse response = client.register("user", "avro", "{}");
|
||||
}
|
||||
catch (Exception e) {
|
||||
expected = e;
|
||||
}
|
||||
Assert.assertTrue(expected instanceof RuntimeException);
|
||||
Assert.assertTrue(expected.getCause() instanceof HttpStatusCodeException);
|
||||
assertThat(expected instanceof RuntimeException).isTrue();
|
||||
assertThat(expected.getCause() instanceof HttpStatusCodeException).isTrue();
|
||||
this.mockRestServiceServer.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByReference(){
|
||||
this.mockRestServiceServer.expect(requestTo("http://localhost:8081/subjects/user/versions/1"))
|
||||
public void findByReference() {
|
||||
this.mockRestServiceServer
|
||||
.expect(requestTo("http://localhost:8081/subjects/user/versions/1"))
|
||||
.andExpect(method(HttpMethod.GET))
|
||||
.andExpect(header("Content-Type","application/vnd.schemaregistry.v1+json"))
|
||||
.andExpect(header("Accept","application/vnd.schemaregistry.v1+json"))
|
||||
.andExpect(
|
||||
header("Content-Type", "application/vnd.schemaregistry.v1+json"))
|
||||
.andExpect(header("Accept", "application/vnd.schemaregistry.v1+json"))
|
||||
.andRespond(withSuccess("{\"schema\":\"\"}", MediaType.APPLICATION_JSON));
|
||||
ConfluentSchemaRegistryClient client = new ConfluentSchemaRegistryClient(this.restTemplate);
|
||||
SchemaReference reference = new SchemaReference("user",1,"avro");
|
||||
ConfluentSchemaRegistryClient client = new ConfluentSchemaRegistryClient(
|
||||
this.restTemplate);
|
||||
SchemaReference reference = new SchemaReference("user", 1, "avro");
|
||||
String schema = client.fetch(reference);
|
||||
Assert.assertEquals("",schema);
|
||||
assertThat(schema).isEqualTo("");
|
||||
this.mockRestServiceServer.verify();
|
||||
}
|
||||
|
||||
@Test(expected = SchemaNotFoundException.class)
|
||||
public void schemaNotFound(){
|
||||
this.mockRestServiceServer.expect(requestTo("http://localhost:8081/subjects/user/versions/1"))
|
||||
public void schemaNotFound() {
|
||||
this.mockRestServiceServer
|
||||
.expect(requestTo("http://localhost:8081/subjects/user/versions/1"))
|
||||
.andExpect(method(HttpMethod.GET))
|
||||
.andExpect(header("Content-Type","application/vnd.schemaregistry.v1+json"))
|
||||
.andExpect(header("Accept","application/vnd.schemaregistry.v1+json"))
|
||||
.andExpect(
|
||||
header("Content-Type", "application/vnd.schemaregistry.v1+json"))
|
||||
.andExpect(header("Accept", "application/vnd.schemaregistry.v1+json"))
|
||||
.andRespond(withStatus(HttpStatus.NOT_FOUND));
|
||||
ConfluentSchemaRegistryClient client = new ConfluentSchemaRegistryClient(this.restTemplate);
|
||||
SchemaReference reference = new SchemaReference("user",1,"avro");
|
||||
ConfluentSchemaRegistryClient client = new ConfluentSchemaRegistryClient(
|
||||
this.restTemplate);
|
||||
SchemaReference reference = new SchemaReference("user", 1, "avro");
|
||||
String schema = client.fetch(reference);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,4 +16,4 @@
|
||||
"type":["Sms", "Email", "PushNotification"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,4 +16,4 @@
|
||||
"type":"string"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,4 +12,4 @@
|
||||
"type":"string"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,4 +11,4 @@
|
||||
"type":"string"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,4 +7,4 @@
|
||||
{"name": "text", "type": "string"},
|
||||
{"name": "timestamp", "type": "long"}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,4 +7,4 @@
|
||||
{"name": "favoriteColor", "type": ["string", "null"]}
|
||||
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,4 +7,4 @@
|
||||
{"name": "favoriteColor", "type": ["string", "null"]},
|
||||
{"name": "favoritePlace", "type": ["string","null"], "default" : "NYC"}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user