From e870c6505a9b5edd5140950ee0083bbcee3be8d0 Mon Sep 17 00:00:00 2001 From: Soby Chacko Date: Mon, 19 Aug 2019 19:16:36 -0400 Subject: [PATCH] Move Schema Registry out of Spring Cloud Stream Migrated to https://github.com/spring-cloud/spring-cloud-schema-registry Resolves #1786 --- pom.xml | 8 - spring-cloud-stream-schema-server/.jdk8 | 0 spring-cloud-stream-schema-server/pom.xml | 59 -- .../server/EnableSchemaRegistryServer.java | 39 -- .../SchemaRegistryServerApplication.java | 35 -- .../config/SchemaServerConfiguration.java | 72 --- .../server/config/SchemaServerProperties.java | 56 -- .../server/controllers/ServerController.java | 263 -------- .../schema/server/model/Compatibility.java | 44 -- .../stream/schema/server/model/Schema.java | 93 --- .../server/repository/SchemaRepository.java | 37 -- .../server/support/AvroSchemaValidator.java | 69 -- .../support/InvalidSchemaException.java | 28 - .../SchemaDeletionNotAllowedException.java | 32 - .../support/SchemaNotFoundException.java | 28 - .../server/support/SchemaValidator.java | 58 -- .../support/UnsupportedFormatException.java | 28 - .../main/resources/META-INF/spring.factories | 1 - .../src/main/resources/application.yml | 6 - .../SchemaRegistryServerAvroTests.java | 594 ------------------ .../entityScanning/EntityScanningTests.java | 45 -- .../EntityScanningTestsWithEntityScan.java | 47 -- .../entityScanning/domain/TestEntity.java | 51 -- spring-cloud-stream-schema/.jdk8 | 0 spring-cloud-stream-schema/pom.xml | 103 --- .../cloud/stream/schema/ParsedSchema.java | 65 -- .../schema/SchemaNotFoundException.java | 28 - .../cloud/stream/schema/SchemaReference.java | 105 ---- .../schema/SchemaRegistrationResponse.java | 44 -- .../avro/AbstractAvroMessageConverter.java | 146 ----- ...AvroMessageConverterAutoConfiguration.java | 107 ---- .../avro/AvroMessageConverterProperties.java | 107 ---- .../avro/AvroSchemaMessageConverter.java | 152 ----- ...oSchemaRegistryClientMessageConverter.java | 424 ------------- .../schema/avro/AvroSchemaServiceManager.java | 75 --- .../avro/AvroSchemaServiceManagerImpl.java | 174 ----- .../avro/DefaultSubjectNamingStrategy.java | 31 - .../avro/OriginalContentTypeResolver.java | 59 -- .../avro/QualifiedSubjectNamingStrategy.java | 32 - .../schema/avro/SubjectNamingStrategy.java | 36 -- .../schema/client/CachingRegistryClient.java | 69 -- .../client/ConfluentSchemaRegistryClient.java | 160 ----- .../client/DefaultSchemaRegistryClient.java | 109 ---- .../client/EnableSchemaRegistryClient.java | 41 -- .../schema/client/SchemaRegistryClient.java | 54 -- .../SchemaRegistryClientConfiguration.java | 58 -- .../SchemaRegistryClientProperties.java | 48 -- .../main/resources/META-INF/spring.factories | 2 - ...vroMessageConverterSerializationTests.java | 224 ------- .../avro/AvroSchemaMessageConverterTests.java | 270 -------- ...maRegistryClientMessageConverterTests.java | 274 -------- .../avro/AvroSchemaServiceManagerTests.java | 179 ------ ...maRegistryClientMessageConverterTests.java | 152 ----- .../schema/avro/StubSchemaRegistryClient.java | 114 ---- .../avro/SubjectNamingStrategyTest.java | 82 --- .../cloud/schema/avro/User1.java | 58 -- .../cloud/schema/avro/User2.java | 70 --- .../ConfluentSchemaRegistryClientTests.java | 164 ----- .../cloud/schema/avro/domain/FoodOrder.java | 44 -- .../src/test/resources/schemas/Command.avsc | 19 - .../test/resources/schemas/imports/Email.avsc | 19 - .../schemas/imports/PushNotification.avsc | 15 - .../test/resources/schemas/imports/Sms.avsc | 14 - .../src/test/resources/schemas/status.avsc | 10 - .../src/test/resources/schemas/user.avsc | 10 - .../test/resources/schemas/users_v1.schema | 10 - .../test/resources/schemas/users_v2.schema | 10 - 67 files changed, 5660 deletions(-) delete mode 100644 spring-cloud-stream-schema-server/.jdk8 delete mode 100644 spring-cloud-stream-schema-server/pom.xml delete mode 100644 spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/EnableSchemaRegistryServer.java delete mode 100644 spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/SchemaRegistryServerApplication.java delete mode 100644 spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/config/SchemaServerConfiguration.java delete mode 100644 spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/config/SchemaServerProperties.java delete mode 100644 spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/controllers/ServerController.java delete mode 100644 spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/model/Compatibility.java delete mode 100644 spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/model/Schema.java delete mode 100644 spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/repository/SchemaRepository.java delete mode 100644 spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/support/AvroSchemaValidator.java delete mode 100644 spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/support/InvalidSchemaException.java delete mode 100644 spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/support/SchemaDeletionNotAllowedException.java delete mode 100644 spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/support/SchemaNotFoundException.java delete mode 100644 spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/support/SchemaValidator.java delete mode 100644 spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/support/UnsupportedFormatException.java delete mode 100644 spring-cloud-stream-schema-server/src/main/resources/META-INF/spring.factories delete mode 100644 spring-cloud-stream-schema-server/src/main/resources/application.yml delete mode 100644 spring-cloud-stream-schema-server/src/test/java/org/springframework/cloud/stream/schema/server/controllers/SchemaRegistryServerAvroTests.java delete mode 100644 spring-cloud-stream-schema-server/src/test/java/org/springframework/cloud/stream/schema/server/entityScanning/EntityScanningTests.java delete mode 100644 spring-cloud-stream-schema-server/src/test/java/org/springframework/cloud/stream/schema/server/entityScanning/EntityScanningTestsWithEntityScan.java delete mode 100644 spring-cloud-stream-schema-server/src/test/java/org/springframework/cloud/stream/schema/server/entityScanning/domain/TestEntity.java delete mode 100644 spring-cloud-stream-schema/.jdk8 delete mode 100644 spring-cloud-stream-schema/pom.xml delete mode 100644 spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/ParsedSchema.java delete mode 100644 spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/SchemaNotFoundException.java delete mode 100644 spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/SchemaReference.java delete mode 100644 spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/SchemaRegistrationResponse.java delete mode 100644 spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/AbstractAvroMessageConverter.java delete mode 100644 spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/AvroMessageConverterAutoConfiguration.java delete mode 100644 spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/AvroMessageConverterProperties.java delete mode 100644 spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/AvroSchemaMessageConverter.java delete mode 100644 spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/AvroSchemaRegistryClientMessageConverter.java delete mode 100644 spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/AvroSchemaServiceManager.java delete mode 100644 spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/AvroSchemaServiceManagerImpl.java delete mode 100644 spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/DefaultSubjectNamingStrategy.java delete mode 100644 spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/OriginalContentTypeResolver.java delete mode 100644 spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/QualifiedSubjectNamingStrategy.java delete mode 100644 spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/SubjectNamingStrategy.java delete mode 100644 spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/client/CachingRegistryClient.java delete mode 100644 spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/client/ConfluentSchemaRegistryClient.java delete mode 100644 spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/client/DefaultSchemaRegistryClient.java delete mode 100644 spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/client/EnableSchemaRegistryClient.java delete mode 100644 spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/client/SchemaRegistryClient.java delete mode 100644 spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/client/config/SchemaRegistryClientConfiguration.java delete mode 100644 spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/client/config/SchemaRegistryClientProperties.java delete mode 100644 spring-cloud-stream-schema/src/main/resources/META-INF/spring.factories delete mode 100644 spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/AvroMessageConverterSerializationTests.java delete mode 100644 spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/AvroSchemaMessageConverterTests.java delete mode 100644 spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/AvroSchemaRegistryClientMessageConverterTests.java delete mode 100644 spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/AvroSchemaServiceManagerTests.java delete mode 100644 spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/AvroStubSchemaRegistryClientMessageConverterTests.java delete mode 100644 spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/StubSchemaRegistryClient.java delete mode 100644 spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/SubjectNamingStrategyTest.java delete mode 100644 spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/User1.java delete mode 100644 spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/User2.java delete mode 100644 spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/client/ConfluentSchemaRegistryClientTests.java delete mode 100644 spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/domain/FoodOrder.java delete mode 100644 spring-cloud-stream-schema/src/test/resources/schemas/Command.avsc delete mode 100644 spring-cloud-stream-schema/src/test/resources/schemas/imports/Email.avsc delete mode 100644 spring-cloud-stream-schema/src/test/resources/schemas/imports/PushNotification.avsc delete mode 100644 spring-cloud-stream-schema/src/test/resources/schemas/imports/Sms.avsc delete mode 100644 spring-cloud-stream-schema/src/test/resources/schemas/status.avsc delete mode 100644 spring-cloud-stream-schema/src/test/resources/schemas/user.avsc delete mode 100644 spring-cloud-stream-schema/src/test/resources/schemas/users_v1.schema delete mode 100644 spring-cloud-stream-schema/src/test/resources/schemas/users_v2.schema diff --git a/pom.xml b/pom.xml index 540da4311..c3642ea6b 100644 --- a/pom.xml +++ b/pom.xml @@ -48,11 +48,6 @@ spring-cloud-stream-tools ${project.version} - - org.springframework.cloud - spring-cloud-stream-schema-server - ${project.version} - org.springframework.cloud spring-cloud-stream-binder-test @@ -109,9 +104,6 @@ - spring-cloud-stream-schema - spring-cloud-stream-schema-server - docs diff --git a/spring-cloud-stream-schema-server/.jdk8 b/spring-cloud-stream-schema-server/.jdk8 deleted file mode 100644 index e69de29bb..000000000 diff --git a/spring-cloud-stream-schema-server/pom.xml b/spring-cloud-stream-schema-server/pom.xml deleted file mode 100644 index c876d6a5f..000000000 --- a/spring-cloud-stream-schema-server/pom.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - 4.0.0 - spring-cloud-stream-schema-server - - - spring-cloud-stream-parent - org.springframework.cloud - 3.0.0.BUILD-SNAPSHOT - - - - - org.springframework.cloud - spring-cloud-stream - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-test - test - - - org.springframework.boot - spring-boot-starter-data-jpa - - - com.h2database - h2 - 1.4.192 - - - org.apache.avro - avro - 1.8.1 - - - org.springframework.boot - spring-boot-configuration-processor - true - - - org.springframework.cloud - spring-cloud-stream-test-support - test - - - org.springframework.cloud - spring-cloud-stream-test-support-internal - test - - - - diff --git a/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/EnableSchemaRegistryServer.java b/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/EnableSchemaRegistryServer.java deleted file mode 100644 index c8ac3a0c3..000000000 --- a/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/EnableSchemaRegistryServer.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.server; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.springframework.cloud.stream.schema.server.config.SchemaServerConfiguration; -import org.springframework.context.annotation.Import; - -/** - * Enables the schema registry server enpoints. - * - * @author Vinicius Carvalho - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@Import(SchemaServerConfiguration.class) -public @interface EnableSchemaRegistryServer { - -} diff --git a/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/SchemaRegistryServerApplication.java b/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/SchemaRegistryServerApplication.java deleted file mode 100644 index 743af9959..000000000 --- a/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/SchemaRegistryServerApplication.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.server; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * @author Vinicius Carvalho - */ -// @checkstyle:off -@SpringBootApplication -@EnableSchemaRegistryServer -public class SchemaRegistryServerApplication { - - public static void main(String[] args) { - SpringApplication.run(SchemaRegistryServerApplication.class, args); - } - -} -// @checkstyle:on diff --git a/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/config/SchemaServerConfiguration.java b/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/config/SchemaServerConfiguration.java deleted file mode 100644 index 0666c7de4..000000000 --- a/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/config/SchemaServerConfiguration.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.server.config; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.config.BeanFactoryPostProcessor; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.boot.autoconfigure.domain.EntityScanPackages; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.stream.schema.server.controllers.ServerController; -import org.springframework.cloud.stream.schema.server.model.Schema; -import org.springframework.cloud.stream.schema.server.repository.SchemaRepository; -import org.springframework.cloud.stream.schema.server.support.AvroSchemaValidator; -import org.springframework.cloud.stream.schema.server.support.SchemaValidator; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.data.jpa.repository.config.EnableJpaRepositories; - -/** - * @author Vinicius Carvalho - * @author Soby Chacko - */ -@Configuration -@EnableJpaRepositories(basePackageClasses = SchemaRepository.class) -@EnableConfigurationProperties(SchemaServerProperties.class) -@Import(ServerController.class) -public class SchemaServerConfiguration { - - @Bean - public static BeanFactoryPostProcessor entityScanPackagesPostProcessor() { - return new BeanFactoryPostProcessor() { - - @Override - public void postProcessBeanFactory( - ConfigurableListableBeanFactory beanFactory) throws BeansException { - if (beanFactory instanceof BeanDefinitionRegistry) { - EntityScanPackages.register((BeanDefinitionRegistry) beanFactory, - Collections - .singletonList(Schema.class.getPackage().getName())); - } - } - }; - } - - @Bean - public Map schemaValidators() { - Map validatorMap = new HashMap<>(); - validatorMap.put("avro", new AvroSchemaValidator()); - return validatorMap; - } - -} diff --git a/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/config/SchemaServerProperties.java b/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/config/SchemaServerProperties.java deleted file mode 100644 index 93ffc346f..000000000 --- a/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/config/SchemaServerProperties.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.server.config; - -import org.springframework.boot.context.properties.ConfigurationProperties; - -/** - * @author Vinicius Carvalho - * @author Ilayaperumal Gopinathan - */ -@ConfigurationProperties("spring.cloud.stream.schema.server") -public class SchemaServerProperties { - - /** - * Prefix for configuration resource paths (default is empty). Useful when embedding - * in another application when you don't want to change the context path or servlet - * path. - */ - private String path; - - /** - * Boolean flag to enable/disable schema deletion. - */ - private boolean allowSchemaDeletion; - - public String getPath() { - return this.path; - } - - public void setPath(String path) { - this.path = path; - } - - public boolean isAllowSchemaDeletion() { - return this.allowSchemaDeletion; - } - - public void setAllowSchemaDeletion(boolean allowSchemaDeletion) { - this.allowSchemaDeletion = allowSchemaDeletion; - } - -} diff --git a/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/controllers/ServerController.java b/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/controllers/ServerController.java deleted file mode 100644 index f9c80ee38..000000000 --- a/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/controllers/ServerController.java +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright 2016-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.server.controllers; - -import java.util.List; -import java.util.Map; -import java.util.Optional; - -import org.springframework.cloud.stream.schema.server.config.SchemaServerProperties; -import org.springframework.cloud.stream.schema.server.model.Schema; -import org.springframework.cloud.stream.schema.server.repository.SchemaRepository; -import org.springframework.cloud.stream.schema.server.support.InvalidSchemaException; -import org.springframework.cloud.stream.schema.server.support.SchemaDeletionNotAllowedException; -import org.springframework.cloud.stream.schema.server.support.SchemaNotFoundException; -import org.springframework.cloud.stream.schema.server.support.SchemaValidator; -import org.springframework.cloud.stream.schema.server.support.UnsupportedFormatException; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.lang.NonNull; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.util.UriComponentsBuilder; - -import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; - -/** - * @author Vinicius Carvalho - * @author Ilayaperumal Gopinathan - */ -@RestController -@RequestMapping(path = "${spring.cloud.stream.schema.server.path:}") -public class ServerController { - - private final SchemaRepository repository; - - private final Map validators; - - private final SchemaServerProperties schemaServerProperties; - - public ServerController(SchemaRepository repository, - Map validators, - SchemaServerProperties schemaServerProperties) { - Assert.notNull(repository, "cannot be null"); - Assert.notEmpty(validators, "cannot be empty"); - this.repository = repository; - this.validators = validators; - this.schemaServerProperties = schemaServerProperties; - } - - @RequestMapping(method = RequestMethod.POST, path = "/", consumes = "application/json", produces = "application/json") - public synchronized ResponseEntity register(@RequestBody Schema schema, - UriComponentsBuilder builder) { - SchemaValidator validator = this.validators.get(schema.getFormat()); - - if (validator == null) { - throw new UnsupportedFormatException( - String.format("Invalid format, supported types are: %s", StringUtils - .collectionToCommaDelimitedString(this.validators.keySet()))); - } - - if (!validator.isValid(schema.getDefinition())) { - throw new InvalidSchemaException("Invalid schema"); - } - - Schema result; - List registeredEntities = this.repository - .findBySubjectAndFormatOrderByVersion(schema.getSubject(), - schema.getFormat()); - if (registeredEntities.isEmpty()) { - schema.setVersion(1); - result = this.repository.save(schema); - } - else { - result = validator.match(registeredEntities, schema.getDefinition()); - if (result == null) { - schema.setVersion( - registeredEntities.get(registeredEntities.size() - 1).getVersion() - + 1); - result = this.repository.save(schema); - } - - } - - HttpHeaders headers = new HttpHeaders(); - headers.add(HttpHeaders.LOCATION, - builder.path("/{subject}/{format}/v{version}") - .buildAndExpand(result.getSubject(), result.getFormat(), - result.getVersion()) - .toString()); - ResponseEntity response = new ResponseEntity<>(result, headers, - HttpStatus.CREATED); - - return response; - - } - - @RequestMapping(method = RequestMethod.GET, produces = "application/json", path = "/{subject}/{format}/v{version}") - public ResponseEntity findOne(@PathVariable("subject") String subject, - @PathVariable("format") String format, - @PathVariable("version") Integer version) { - Schema schema = this.repository.findOneBySubjectAndFormatAndVersion(subject, - format, version); - if (schema == null) { - throw new SchemaNotFoundException("Could not find Schema"); - } - return new ResponseEntity<>(schema, HttpStatus.OK); - } - - @RequestMapping(method = RequestMethod.GET, produces = "application/json", path = "/schemas/{id}") - public ResponseEntity findOne(@PathVariable("id") Integer id) { - Optional schema = this.repository.findById(id); - if (!schema.isPresent()) { - throw new SchemaNotFoundException("Could not find Schema"); - } - return new ResponseEntity<>(schema.get(), HttpStatus.OK); - } - - /** - *

- * Find by {@link Schema#getSubject() subject} and {@link Schema#getFormat() format}. - * - * @param subject the {@link Schema#getSubject() subject}, must not be - * {@literal null}. - * @param format the {@link Schema#getFormat() format}, must not be {@literal null}. - * @return An {@link HttpStatus#OK} response populated with the list of {@link Schema - * Schemas}, in ascending order by {@link Schema#getVersion() version}, that matched - * the supplied {@link Schema#getSubject() subject} and {@link Schema#getFormat() - * format}. - * @deprecated use {@link #findBySubjectAndFormat(String, String)} - * @see GH-1760 - */ - @Deprecated - public ResponseEntity> findBySubjectAndVersion(@PathVariable("subject") String subject, - @PathVariable("format") String format) { - return findBySubjectAndFormatOrderByVersionAsc(subject, format); - } - - /** - * Find by {@link Schema#getSubject() subject} and {@link Schema#getFormat() format}. - * - * @param subject the {@link Schema#getSubject() subject}, must not be - * {@literal null}. - * @param format the {@link Schema#getFormat() format}, must not be {@literal null}. - * @return An {@link HttpStatus#OK} response populated with the list of {@link Schema - * Schemas}, in ascending order by {@link Schema#getVersion() version}, that matched - * the supplied {@link Schema#getSubject() subject} and {@link Schema#getFormat() - * format}. - * - * @since 3.0.0 - */ - @GetMapping(produces = APPLICATION_JSON_VALUE, path = "/{subject}/{format}") - @NonNull - public ResponseEntity> findBySubjectAndFormat(@NonNull @PathVariable("subject") final String subject, - @NonNull @PathVariable("format") final String format) { - return findBySubjectAndFormatOrderByVersionAsc(subject, format); - } - - @RequestMapping(value = "/{subject}/{format}/v{version}", method = RequestMethod.DELETE) - public void delete(@PathVariable("subject") String subject, - @PathVariable("format") String format, - @PathVariable("version") Integer version) { - if (this.schemaServerProperties.isAllowSchemaDeletion()) { - Schema schema = this.repository.findOneBySubjectAndFormatAndVersion(subject, - format, version); - deleteSchema(schema); - } - else { - throw new SchemaDeletionNotAllowedException(); - } - } - - @RequestMapping(value = "/schemas/{id}", method = RequestMethod.DELETE) - public void delete(@PathVariable("id") Integer id) { - if (this.schemaServerProperties.isAllowSchemaDeletion()) { - Optional schema = this.repository.findById(id); - if (!schema.isPresent()) { - throw new SchemaNotFoundException("Could not find Schema"); - } - deleteSchema(schema.get()); - } - else { - throw new SchemaDeletionNotAllowedException(); - } - } - - @RequestMapping(value = "/{subject}", method = RequestMethod.DELETE) - public void delete(@PathVariable("subject") String subject) { - if (this.schemaServerProperties.isAllowSchemaDeletion()) { - for (Schema schema : this.repository.findAll()) { - if (schema.getSubject().equals(subject)) { - deleteSchema(schema); - } - } - } - else { - throw new SchemaDeletionNotAllowedException(); - } - - } - - @NonNull - final ResponseEntity> findBySubjectAndFormatOrderByVersionAsc(@NonNull final String subject, - @NonNull final String format) { - List schemas = this.repository.findBySubjectAndFormatOrderByVersion(subject, format); - if (schemas.isEmpty()) { - throw new SchemaNotFoundException( - String.format("No schemas found for subject %s and format %s", subject, format)); - } - return new ResponseEntity<>(schemas, HttpStatus.OK); - } - - private void deleteSchema(Schema schema) { - if (schema == null) { - throw new SchemaNotFoundException("Could not find Schema"); - } - this.repository.delete(schema); - } - - @ExceptionHandler(UnsupportedFormatException.class) - @ResponseStatus(value = HttpStatus.BAD_REQUEST, reason = "Format not supported") - public void unsupportedFormat(UnsupportedFormatException ex) { - } - - @ExceptionHandler(InvalidSchemaException.class) - @ResponseStatus(value = HttpStatus.BAD_REQUEST, reason = "Invalid schema") - public void invalidSchema(InvalidSchemaException ex) { - } - - @ExceptionHandler(SchemaNotFoundException.class) - @ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "Schema not found") - public void schemaNotFound(SchemaNotFoundException ex) { - } - - @ExceptionHandler(SchemaDeletionNotAllowedException.class) - @ResponseStatus(value = HttpStatus.METHOD_NOT_ALLOWED, reason = "Schema deletion is not permitted") - public void schemaDeletionNotPermitted(SchemaDeletionNotAllowedException ex) { - } - -} diff --git a/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/model/Compatibility.java b/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/model/Compatibility.java deleted file mode 100644 index 46c13a7a1..000000000 --- a/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/model/Compatibility.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.server.model; - -/** - * @author Vinicius Carvalho - */ -public enum Compatibility { - - /** - * Backward compatibiltity. - */ - BACKWARD, - - /** - * Forward compatibility. - */ - FORWARD, - - /** - * Full compatibility. - */ - FULL, - - /** - * Lack of compatibility. - */ - INCOMPATIBLE; - -} diff --git a/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/model/Schema.java b/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/model/Schema.java deleted file mode 100644 index 250896c8d..000000000 --- a/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/model/Schema.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.server.model; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.Lob; -import javax.persistence.Table; - -/** - * @author Vinicius Carvalho - * - * Represents a persisted schema entity. - */ -@Entity -@Table(name = "SCHEMA_REPOSITORY") -public class Schema { - - @Id - @GeneratedValue - @Column(name = "ID") - private Integer id; - - @Column(name = "VERSION", nullable = false) - private Integer version; - - @Column(name = "SUBJECT", nullable = false) - private String subject; - - @Column(name = "FORMAT", nullable = false) - private String format; - - @Lob - @Column(name = "DEFINITION", nullable = false, length = 8192) - private String definition; - - public Integer getId() { - return this.id; - } - - public void setId(Integer id) { - this.id = id; - } - - public Integer getVersion() { - return this.version; - } - - public void setVersion(Integer version) { - this.version = version; - } - - public String getSubject() { - return this.subject; - } - - public void setSubject(String subject) { - this.subject = subject; - } - - public String getFormat() { - return this.format; - } - - public void setFormat(String format) { - this.format = format; - } - - public String getDefinition() { - return this.definition; - } - - public void setDefinition(String definition) { - this.definition = definition; - } - -} diff --git a/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/repository/SchemaRepository.java b/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/repository/SchemaRepository.java deleted file mode 100644 index 9fb8ad4ae..000000000 --- a/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/repository/SchemaRepository.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.server.repository; - -import java.util.List; - -import org.springframework.cloud.stream.schema.server.model.Schema; -import org.springframework.data.repository.PagingAndSortingRepository; -import org.springframework.transaction.annotation.Transactional; - -/** - * @author Vinicius Carvalho - */ -public interface SchemaRepository extends PagingAndSortingRepository { - - @Transactional - List findBySubjectAndFormatOrderByVersion(String subject, String format); - - @Transactional - Schema findOneBySubjectAndFormatAndVersion(String subject, String format, - Integer version); - -} diff --git a/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/support/AvroSchemaValidator.java b/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/support/AvroSchemaValidator.java deleted file mode 100644 index 0af3f5a64..000000000 --- a/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/support/AvroSchemaValidator.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.server.support; - -import java.util.List; - -import org.apache.avro.SchemaParseException; - -import org.springframework.cloud.stream.schema.server.model.Compatibility; -import org.springframework.cloud.stream.schema.server.model.Schema; - -/** - * @author Vinicius Carvalho - */ -public class AvroSchemaValidator implements SchemaValidator { - - @Override - public boolean isValid(String definition) { - boolean result = true; - try { - new org.apache.avro.Schema.Parser().parse(definition); - } - catch (SchemaParseException ex) { - result = false; - } - return result; - } - - @Override - public Compatibility compatibilityCheck(String source, String other) { - return null; - } - - @Override - public Schema match(List schemas, String definition) { - Schema result = null; - org.apache.avro.Schema source = new org.apache.avro.Schema.Parser() - .parse(definition); - for (Schema s : schemas) { - org.apache.avro.Schema target = new org.apache.avro.Schema.Parser() - .parse(s.getDefinition()); - if (target.equals(source)) { - result = s; - break; - } - } - return result; - } - - @Override - public String getFormat() { - return "avro"; - } - -} diff --git a/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/support/InvalidSchemaException.java b/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/support/InvalidSchemaException.java deleted file mode 100644 index c53a523db..000000000 --- a/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/support/InvalidSchemaException.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.server.support; - -/** - * @author Vinicius Carvalho - */ -public class InvalidSchemaException extends RuntimeException { - - public InvalidSchemaException(String message) { - super(message); - } - -} diff --git a/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/support/SchemaDeletionNotAllowedException.java b/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/support/SchemaDeletionNotAllowedException.java deleted file mode 100644 index 61709632d..000000000 --- a/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/support/SchemaDeletionNotAllowedException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.server.support; - -/** - * @author Ilayaperumal Gopinathan - */ -public class SchemaDeletionNotAllowedException extends RuntimeException { - - public SchemaDeletionNotAllowedException(String message) { - super(message); - } - - public SchemaDeletionNotAllowedException() { - super("Schema Deletion Not Allowed"); - } - -} diff --git a/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/support/SchemaNotFoundException.java b/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/support/SchemaNotFoundException.java deleted file mode 100644 index b8f1d4784..000000000 --- a/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/support/SchemaNotFoundException.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.server.support; - -/** - * @author Vinicius Carvalho - */ -public class SchemaNotFoundException extends RuntimeException { - - public SchemaNotFoundException(String message) { - super(message); - } - -} diff --git a/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/support/SchemaValidator.java b/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/support/SchemaValidator.java deleted file mode 100644 index 81067a82a..000000000 --- a/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/support/SchemaValidator.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.server.support; - -import java.util.List; - -import org.springframework.cloud.stream.schema.server.model.Compatibility; -import org.springframework.cloud.stream.schema.server.model.Schema; - -/** - * @author Vinicius Carvalho - * - * Provides utility methods to validate, check compatibility and match schemas of - * different implementations - */ -public interface SchemaValidator { - - /** - * Verifies if a definition is a valid schema. - * @param definition - The textual representation of the schema file - * @return true if valid, false otherwise - */ - boolean isValid(String definition); - - /** - * Checks for compatibility between two schemas @see Compatibility class for types - * This method may not be supported for certain formats. - * @param source - The textual representation of the schema to tested - * @param other - The textual representation of the other schema to tested - * @return {@link Compatibility} - */ - Compatibility compatibilityCheck(String source, String other); - - /** - * Return the Schema that is represented by the definition. - * @param schemas List of schemas to be tested - * @param definition Textual representation of the schema - * @return A full Schema object with identifier and subject properties - */ - Schema match(List schemas, String definition); - - String getFormat(); - -} diff --git a/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/support/UnsupportedFormatException.java b/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/support/UnsupportedFormatException.java deleted file mode 100644 index 2c2bf85e7..000000000 --- a/spring-cloud-stream-schema-server/src/main/java/org/springframework/cloud/stream/schema/server/support/UnsupportedFormatException.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.server.support; - -/** - * @author Vinicius Carvalho - */ -public class UnsupportedFormatException extends RuntimeException { - - public UnsupportedFormatException(String message) { - super(message); - } - -} diff --git a/spring-cloud-stream-schema-server/src/main/resources/META-INF/spring.factories b/spring-cloud-stream-schema-server/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 8b1378917..000000000 --- a/spring-cloud-stream-schema-server/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1 +0,0 @@ - diff --git a/spring-cloud-stream-schema-server/src/main/resources/application.yml b/spring-cloud-stream-schema-server/src/main/resources/application.yml deleted file mode 100644 index a5aad28b1..000000000 --- a/spring-cloud-stream-schema-server/src/main/resources/application.yml +++ /dev/null @@ -1,6 +0,0 @@ -spring: - application: - name: SchemaRegistryServer -server: - port: 8990 - diff --git a/spring-cloud-stream-schema-server/src/test/java/org/springframework/cloud/stream/schema/server/controllers/SchemaRegistryServerAvroTests.java b/spring-cloud-stream-schema-server/src/test/java/org/springframework/cloud/stream/schema/server/controllers/SchemaRegistryServerAvroTests.java deleted file mode 100644 index d63b5d77b..000000000 --- a/spring-cloud-stream-schema-server/src/test/java/org/springframework/cloud/stream/schema/server/controllers/SchemaRegistryServerAvroTests.java +++ /dev/null @@ -1,594 +0,0 @@ -/* - * Copyright 2016-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.server.controllers; - -import java.net.URI; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Optional; -import java.util.stream.Stream; - -import org.apache.avro.Schema.Parser; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.web.ServerProperties; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.web.server.Ssl; -import org.springframework.cloud.stream.schema.server.config.SchemaServerProperties; -import org.springframework.cloud.stream.schema.server.model.Schema; -import org.springframework.cloud.stream.schema.server.support.SchemaNotFoundException; -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.RequestEntity; -import org.springframework.http.ResponseEntity; -import org.springframework.lang.NonNull; -import org.springframework.lang.Nullable; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.web.util.UriComponentsBuilder; - -import static java.util.stream.Collectors.toList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.springframework.test.annotation.DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD; - -/** - * @author Vinicius Carvalho - * @author Ilayaperumal Gopinathan - */ -@RunWith(SpringRunner.class) -// @checkstyle:off -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT, properties = "spring.main.allow-bean-definition-overriding=true") -// @checkstyle:on -@DirtiesContext(classMode = AFTER_EACH_TEST_METHOD) -public class SchemaRegistryServerAvroTests { - - private static final String AVRO_FORMAT_NAME = "avro"; - - private static final String AVRO_USER_DEFINITION_SCHEMA_V1 = "{\"namespace\": \"example.avro\",\n" - + " \"type\": \"record\",\n" + " \"name\": \"User\",\n" + " \"fields\": [\n" - + " {\"name\": \"name\", \"type\": \"string\"},\n" - + " {\"name\": \"favorite_number\", \"type\": [\"int\", \"null\"]}\n" - + " ]\n" + "}"; - - private static final String AVRO_USER_DEFINTITION_SCHEMA_V2 = "{\"namespace\": \"example.avro\",\n" - + " \"type\": \"record\",\n" + " \"name\": \"User\",\n" + " \"fields\": [\n" - + " {\"name\": \"name\", \"type\": \"string\"},\n" - + " {\"name\": \"favorite_number\", \"type\": [\"int\", \"null\"]},\n" - + " {\"name\": \"favorite_color\", \"type\": [\"string\", \"null\"]}\n" - + " ]\n" + "}"; - - private static final org.apache.avro.Schema AVRO_USER_AVRO_SCHEMA_V1 = new Parser() - .parse(AVRO_USER_DEFINITION_SCHEMA_V1); - - private static final org.apache.avro.Schema AVRO_USER_AVRO_SCHEMA_V2 = new Parser() - .parse(AVRO_USER_DEFINTITION_SCHEMA_V2); - - private static final String AVRO_USER_SCHEMA_DEFAULT_NAME_STRATEGY_SUBJECT = AVRO_USER_AVRO_SCHEMA_V1.getName() - .toLowerCase(); - - - private static final String AVRO_USER_SCHEMA_QUALIFED_NAME_STRATEGY_SUBJECT = AVRO_USER_AVRO_SCHEMA_V1 - .getFullName() - .toLowerCase(); - - private static final Schema AVRO_USER_REGISTRY_SCHEMA_V1 = toSchema( - AVRO_USER_SCHEMA_DEFAULT_NAME_STRATEGY_SUBJECT, - AVRO_FORMAT_NAME, AVRO_USER_AVRO_SCHEMA_V1.toString()); - - private static final Schema AVRO_USER_REGISTRY_SCHEMA_V2 = toSchema( - AVRO_USER_SCHEMA_DEFAULT_NAME_STRATEGY_SUBJECT, - AVRO_FORMAT_NAME, AVRO_USER_AVRO_SCHEMA_V2.toString()); - - private static final Schema AAVRO_USER_REGISTRY_SCHEMA_V1_WITH_QUAL_SUBJECT = toSchema( - AVRO_USER_SCHEMA_QUALIFED_NAME_STRATEGY_SUBJECT, - AVRO_FORMAT_NAME, AVRO_USER_AVRO_SCHEMA_V1.toString()); - @Autowired - private TestRestTemplate client; - - @Autowired - private SchemaServerProperties schemaServerProperties; - - @Autowired - private ServerController serverController; - - @Autowired - private ServerProperties serverProperties; - - private URI serverControllerUri; - - @Before - public void setUp() { - - String scheme = Optional.ofNullable(this.serverProperties.getSsl()) - .filter(Ssl::isEnabled) - .map(ssl -> "https").orElse("http"); - - Integer port = this.serverProperties.getPort(); - String contextPath = this.serverProperties.getServlet().getContextPath(); - - this.serverControllerUri = UriComponentsBuilder.newInstance().scheme(scheme) - .host("localhost") - .port(port) - .path(contextPath).build().toUri(); - - } - - @NonNull - static Schema toSchema(String subject, String format, String definition) { - Schema schema = new Schema(); - schema.setSubject(subject); - schema.setFormat(format); - schema.setDefinition(definition); - return schema; - } - - @Test - public void testUnsupportedFormat() throws Exception { - Schema schema = new Schema(); - schema.setFormat("spring"); - schema.setSubject("boot"); - ResponseEntity response = this.client - .postForEntity(this.serverControllerUri, schema, Schema.class); - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); - } - - @Test - public void testInvalidSchema() throws Exception { - Schema schema = new Schema(); - schema.setFormat(AVRO_FORMAT_NAME); - schema.setSubject("boot"); - schema.setDefinition("{}"); - ResponseEntity response = this.client - .postForEntity(this.serverControllerUri, schema, Schema.class); - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); - } - - @Test - public void testRegister1AvroSchema() { - - Schema schema = new Schema(); - schema.setFormat(AVRO_FORMAT_NAME); - schema.setSubject("org.springframework.cloud.stream.schema.User"); - schema.setDefinition(SchemaRegistryServerAvroTests.AVRO_USER_DEFINITION_SCHEMA_V1); - - registerSchemaAndAssertSuccess(schema, 1, 1); - - } - - @Test - public void testFindByIdFound() { - - ResponseEntity registerSchemaReponse = registerSchemaAndAssertSuccess( - AVRO_USER_REGISTRY_SCHEMA_V1, 1, 1); - - Schema registeredSchema = registerSchemaReponse.getBody(); - - URI findByIdUriId1 = this.serverControllerUri.resolve("/schemas/" + registeredSchema.getId()); - - ResponseEntity findByIdResponse = this.client - .getForEntity(findByIdUriId1, Schema.class); - - assertThat(findByIdResponse.getStatusCode().is2xxSuccessful()).isTrue(); - - Schema actual = findByIdResponse.getBody(); - assertSchema(registeredSchema, actual); - } - - @Test - public void testFindByIdNotFound() { - - registerSchemaAndAssertSuccess(AVRO_USER_REGISTRY_SCHEMA_V1, 1, 1); - - URI findByIdUriId1 = this.serverControllerUri.resolve("/schemas/" + 2); - - ResponseEntity response = this.client - .getForEntity(findByIdUriId1, Schema.class); - - final HttpStatus statusCode = response.getStatusCode(); - - assertThat(statusCode).isEqualTo(HttpStatus.NOT_FOUND); - - } - @Test - public void testUserSchemaV2() { - - registerSchemasAndAssertSuccess( - AVRO_USER_REGISTRY_SCHEMA_V1, - AVRO_USER_REGISTRY_SCHEMA_V2); - } - - @Test - public void testIdempotentRegistration() { - - registerSchemaAndAssertSuccess( - AVRO_USER_REGISTRY_SCHEMA_V1, 1, 1); - - - registerSchemaAndAssertSuccess( - AVRO_USER_REGISTRY_SCHEMA_V1, 1, 1); - - } - - @Test - public void testSchemaNotfound() throws Exception { - ResponseEntity response = this.client - .getForEntity("http://localhost:8990/foo/avro/v42", Schema.class); - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); - } - - @Test - public void testSchemaDeletionBySubjectFormatVersion() throws Exception { - - ResponseEntity registerSchemaAndAssertSuccess = registerSchemaAndAssertSuccess( - AVRO_USER_REGISTRY_SCHEMA_V1, 1, 1); - - this.schemaServerProperties.setAllowSchemaDeletion(true); - - URI subjectFormatVersionUri = this.serverControllerUri - .resolve(registerSchemaAndAssertSuccess.getHeaders().getLocation()); - - - ResponseEntity deleteResponse = this.client.exchange( - new RequestEntity<>(HttpMethod.DELETE, subjectFormatVersionUri), - Void.class); - - assertThat(deleteResponse.getStatusCode()).isEqualTo(HttpStatus.OK); - - ResponseEntity findBySubjectFormatVersionUriResponse = this.client - .getForEntity(subjectFormatVersionUri, Schema.class); - - assertThat(findBySubjectFormatVersionUriResponse.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); - } - - @Test - public void testSchemaDeletionBySubjectFormatVersionNotFound() throws Exception { - - ResponseEntity registerSchemaAndAssertSuccess = registerSchemaAndAssertSuccess( - AVRO_USER_REGISTRY_SCHEMA_V1, 1, 1); - - this.schemaServerProperties.setAllowSchemaDeletion(true); - - URI subjectFormatVersionUri = this.serverControllerUri - .resolve(registerSchemaAndAssertSuccess.getHeaders().getLocation().toString().replace("v1", "v100")); - - ResponseEntity deleteResponse = this.client.exchange( - new RequestEntity<>(HttpMethod.DELETE, subjectFormatVersionUri), - Void.class); - - assertThat(deleteResponse.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); - - } - - @Test - public void testSchemaDeletionBySubjectFormatVersionNotAllowed() throws Exception { - - ResponseEntity registerSchemaAndAssertSuccess = registerSchemaAndAssertSuccess( - AVRO_USER_REGISTRY_SCHEMA_V1, 1, 1); - - URI versionUri = this.serverControllerUri - .resolve(registerSchemaAndAssertSuccess.getHeaders().getLocation()); - - ResponseEntity deleteResponse = this.client.exchange(new RequestEntity<>(HttpMethod.DELETE, versionUri), - Void.class); - - assertThat(deleteResponse.getStatusCode()).isEqualTo(HttpStatus.METHOD_NOT_ALLOWED); - - } - - @Test - public void testSchemaDeletionById() throws Exception { - - - ResponseEntity registerSchemaAndAssertSuccess = registerSchemaAndAssertSuccess( - AVRO_USER_REGISTRY_SCHEMA_V1, 1, 1); - - this.schemaServerProperties.setAllowSchemaDeletion(true); - this.client.delete(this.serverControllerUri - .resolve("/schemas/" + registerSchemaAndAssertSuccess.getBody().getVersion())); - - ResponseEntity response3 = this.client - .getForEntity(registerSchemaAndAssertSuccess.getHeaders().getLocation(), Schema.class); - assertThat(response3.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); - - } - - @Test - public void testSchemaDeletionByIdNotFound() throws Exception { - - registerSchemaAndAssertSuccess( - AVRO_USER_REGISTRY_SCHEMA_V1, 1, 1); - - this.schemaServerProperties.setAllowSchemaDeletion(true); - - ResponseEntity deleteByIdResponse = this.client.exchange( - new RequestEntity<>(HttpMethod.DELETE, this.serverControllerUri - .resolve("/schemas/" + 2)), - Void.class); - - assertThat(deleteByIdResponse.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); - } - - @Test - public void testSchemaDeletionByIdNotAllowed() throws Exception { - - ResponseEntity registerSchemaAndAssertSuccess = registerSchemaAndAssertSuccess( - AVRO_USER_REGISTRY_SCHEMA_V1, 1, 1); - - URI schemaIdUri = this.serverControllerUri - .resolve(this.serverControllerUri - .resolve("/schemas/" + registerSchemaAndAssertSuccess.getBody().getVersion())); - - ResponseEntity exchange = this.client.exchange(new RequestEntity<>(HttpMethod.DELETE, schemaIdUri), - Void.class); - - assertThat(exchange.getStatusCode()).isEqualTo(HttpStatus.METHOD_NOT_ALLOWED); - } - - @Test - public void testSchemaDeletionBySubject() { - Map>>> registerSchemaResponsesByFormatBySubject = registerSchemasAndAssertSuccess( - AVRO_USER_REGISTRY_SCHEMA_V1, - AVRO_USER_REGISTRY_SCHEMA_V2, AAVRO_USER_REGISTRY_SCHEMA_V1_WITH_QUAL_SUBJECT); - - this.schemaServerProperties.setAllowSchemaDeletion(true); - - registerSchemaResponsesByFormatBySubject.forEach((subject, registerSchemaResponsesByFormat) -> { - - assertThat(registerSchemaResponsesByFormat).isNotEmpty(); - ResponseEntity deleteBySubject = this.client.exchange( - new RequestEntity<>(HttpMethod.DELETE, this.serverControllerUri - .resolve("/" + subject)), - Void.class); - - assertThat(deleteBySubject.getStatusCode()).isEqualTo(HttpStatus.OK); - - registerSchemaResponsesByFormat.forEach((format, registerSchemaResponses) -> { - - assertThat(registerSchemaResponses).isNotEmpty(); - - registerSchemaResponses.forEach(registerSchemaResponse -> { - - ResponseEntity shouldBe404Response = this.client.getForEntity( - registerSchemaResponse.getHeaders().getLocation(), - Schema.class); - - assertThat(shouldBe404Response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); - - }); - }); - }); - - } - - @Test - public void testSchemaDeletionBySubjectNotFound() throws Exception { - - registerSchemaAndAssertSuccess( - AVRO_USER_REGISTRY_SCHEMA_V1, 1, 1); - - this.schemaServerProperties.setAllowSchemaDeletion(true); - - ResponseEntity deleteBySubject = this.client.exchange( - new RequestEntity<>(HttpMethod.DELETE, this.serverControllerUri - .resolve("/foo")), - Void.class); - - assertThat(deleteBySubject.getStatusCode()) - .isEqualTo(HttpStatus.OK); - - - } - - @Test - public void testSchemaDeletionBySubjectNotAllowed() throws Exception { - - ResponseEntity registerSchemaAndAssertSuccess = registerSchemaAndAssertSuccess( - AVRO_USER_REGISTRY_SCHEMA_V1, 1, 1); - - Schema schema = registerSchemaAndAssertSuccess.getBody(); - - ResponseEntity deleteBySubject = this.client.exchange( - new RequestEntity<>(HttpMethod.DELETE, this.serverControllerUri - .resolve("/" + schema.getSubject())), - Void.class); - - assertThat(deleteBySubject.getStatusCode()) - .isEqualTo(HttpStatus.METHOD_NOT_ALLOWED); - - } - - @Test - public void testFindSchemasBySubjectAndVersion() { - - Map>>> registerSchemaResponsesByFormatBySubject = registerSchemasAndAssertSuccess( - AVRO_USER_REGISTRY_SCHEMA_V1, - AVRO_USER_REGISTRY_SCHEMA_V2); - - registerSchemaResponsesByFormatBySubject.forEach((subject, schemasByFormat) -> { - - assertThat(schemasByFormat).hasSize(1); - - schemasByFormat.forEach((format, schemas) -> { - assertThat(schemas).hasSize(2); - - @SuppressWarnings("deprecation") - final ResponseEntity> findBySubjectAndVersionResponseEntity = this.serverController - .findBySubjectAndVersion(subject, format); - - assertThat(findBySubjectAndVersionResponseEntity.getStatusCode().is2xxSuccessful()).isTrue(); - - final List schemaResponseBody = findBySubjectAndVersionResponseEntity.getBody(); - - assertThat(schemaResponseBody) - .zipSatisfy(schemas.stream().map(ResponseEntity::getBody) - .collect(toList()), this::assertSchema); - - }); - }); - - } - - @Test - public void testFindBySubjectAndFormatOrderByVersionAscNoMatch() { - String subject = "test"; - - String format = AVRO_FORMAT_NAME; - - assertThatExceptionOfType(SchemaNotFoundException.class).isThrownBy(() -> this.serverController - .findBySubjectAndFormatOrderByVersionAsc(subject, format)) - .withMessage("No schemas found for subject %s and format %s", subject, format) - .withNoCause(); - - - } - - @Test - public void testFindSchemasBySubjectAndFormat() { - - Map>>> registerSchemaResponsesByFormatBySubject = registerSchemasAndAssertSuccess( - AVRO_USER_REGISTRY_SCHEMA_V1, - AVRO_USER_REGISTRY_SCHEMA_V2); - - registerSchemaResponsesByFormatBySubject.forEach((subject, schemasByFormat) -> { - - assertThat(schemasByFormat).hasSize(1); - - schemasByFormat.forEach((format, schemas) -> { - assertThat(schemas).hasSize(2); - - ResponseEntity> findBySubjectFormatResponse = this.client.exchange( - this.serverControllerUri.resolve("/" + subject + "/" + format), HttpMethod.GET, null, - new ParameterizedTypeReference>() { - }); - - assertThat(findBySubjectFormatResponse.getStatusCode().is2xxSuccessful()).isTrue(); - - final List schemaResponseBody = findBySubjectFormatResponse.getBody(); - - assertThat(schemaResponseBody) - .zipSatisfy(schemas.stream().map(ResponseEntity::getBody) - .collect(toList()), this::assertSchema); - - }); - }); - - } - - private Map>>> registerSchemasAndAssertSuccess( - @NonNull Schema... schemas) { - Map> versionsByFormatAndSubject = new HashMap<>(); - Map>>> result = new HashMap<>(); - int numOfSchemas = schemas.length; - int id = 0; - for (int i = 0; i < numOfSchemas; i++) { - Schema schema = schemas[i]; - id++; - String format = schema.getFormat(); - String subject = schema.getSubject(); - Integer version = versionsByFormatAndSubject - .compute(subject, - (_subject, currentValue) -> currentValue == null ? new HashMap<>() : currentValue) - .merge(format, 1, Integer::sum); - ResponseEntity registerSchemaResponse = registerSchemaAndAssertSuccess(schema, version, id); - result.compute(subject, - (_subject, currentValue) -> currentValue == null ? new HashMap<>() : currentValue) - - .compute(format, (_format, currentValue) -> { - List> value = currentValue == null ? new ArrayList<>() : currentValue; - value.add(registerSchemaResponse); - return value; - }); - } - Stream> asStream = result.entrySet().stream() - .map(Entry::getValue) - .map(Map::entrySet) - .flatMap(Collection::stream) - .map(Entry::getValue) - .flatMap(Collection::stream); - assertThat(asStream).hasSize(numOfSchemas); - return result; - - } - - @NonNull - private ResponseEntity registerSchemaAndAssertSuccess(@NonNull Schema schema, - @Nullable Integer expectedVersion, - @Nullable Integer expectedId) { - - ResponseEntity registerReponse = this.client - .postForEntity(this.serverControllerUri, schema, Schema.class); - - HttpStatus statusCode = registerReponse.getStatusCode(); - assertThat(statusCode.is2xxSuccessful()).isTrue(); - - Schema registeredSchema = registerReponse.getBody(); - assertSchema(schema, expectedVersion, expectedId, registeredSchema); - - HttpHeaders headers = registerReponse.getHeaders(); - assertLocation(headers, registeredSchema); - - return registerReponse; - } - - private void assertLocation(HttpHeaders headers, Schema registeredSchema) { - URI location = headers.getLocation(); - - assertThat(location).isNotNull(); - assertPersisted(location, registeredSchema); - } - - private void assertPersisted(URI location, Schema registeredSchema) { - - ResponseEntity findOneResponse = this.client.getForEntity(location, - Schema.class); - - HttpStatus statusCode = findOneResponse.getStatusCode(); - assertThat(statusCode.is2xxSuccessful()).isTrue(); - - Schema actual = findOneResponse.getBody(); - assertSchema(registeredSchema, registeredSchema.getVersion(), registeredSchema.getId(), actual); - - } - - private void assertSchema(@NonNull Schema expected, @NonNull Schema actual) { - - assertSchema(expected, expected.getVersion(), expected.getId(), actual); - } - - private void assertSchema(@NonNull Schema expected, Integer expectedVersion, Integer expectedId, - @NonNull Schema actual) { - - assertThat(actual).isEqualToIgnoringGivenFields(expected, "version", "id"); - if (expectedVersion != null) { - assertThat(actual.getVersion()).isEqualTo(expectedVersion); - } - if (expectedId != null) { - assertThat(actual.getId()).isEqualTo(expectedId); - } - } -} diff --git a/spring-cloud-stream-schema-server/src/test/java/org/springframework/cloud/stream/schema/server/entityScanning/EntityScanningTests.java b/spring-cloud-stream-schema-server/src/test/java/org/springframework/cloud/stream/schema/server/entityScanning/EntityScanningTests.java deleted file mode 100644 index 3dad37920..000000000 --- a/spring-cloud-stream-schema-server/src/test/java/org/springframework/cloud/stream/schema/server/entityScanning/EntityScanningTests.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.server.entityScanning; - -import org.junit.Test; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.cloud.stream.schema.server.EnableSchemaRegistryServer; -import org.springframework.context.ConfigurableApplicationContext; - -/** - * @author Marius Bogoevici - */ -public class EntityScanningTests { - - @Test - public void testApplicationWithEmbeddedSchemaRegistryServerOutsideOfRootPackage() - throws Exception { - final ConfigurableApplicationContext context = SpringApplication - .run(CustomApplicationEmbeddingSchemaServer.class, "--server.port=0"); - context.close(); - } - - @EnableAutoConfiguration - @EnableSchemaRegistryServer - public static class CustomApplicationEmbeddingSchemaServer { - - } - -} diff --git a/spring-cloud-stream-schema-server/src/test/java/org/springframework/cloud/stream/schema/server/entityScanning/EntityScanningTestsWithEntityScan.java b/spring-cloud-stream-schema-server/src/test/java/org/springframework/cloud/stream/schema/server/entityScanning/EntityScanningTestsWithEntityScan.java deleted file mode 100644 index 7742f05d0..000000000 --- a/spring-cloud-stream-schema-server/src/test/java/org/springframework/cloud/stream/schema/server/entityScanning/EntityScanningTestsWithEntityScan.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.server.entityScanning; - -import org.junit.Test; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.domain.EntityScan; -import org.springframework.cloud.stream.schema.server.EnableSchemaRegistryServer; -import org.springframework.context.ConfigurableApplicationContext; - -/** - * @author Marius Bogoevici - */ -public class EntityScanningTestsWithEntityScan { - - @Test - public void testApplicationWithEmbeddedSchemaRegistryServerOutsideOfRootPackage() - throws Exception { - final ConfigurableApplicationContext context = SpringApplication - .run(CustomApplicationEmbeddingSchemaServer.class, "--server.port=0"); - context.close(); - } - - @EnableAutoConfiguration - @EnableSchemaRegistryServer - @EntityScan(basePackages = "org.springframework.cloud.stream.schema.server.entityScanning.domain") - public static class CustomApplicationEmbeddingSchemaServer { - - } - -} diff --git a/spring-cloud-stream-schema-server/src/test/java/org/springframework/cloud/stream/schema/server/entityScanning/domain/TestEntity.java b/spring-cloud-stream-schema-server/src/test/java/org/springframework/cloud/stream/schema/server/entityScanning/domain/TestEntity.java deleted file mode 100644 index 2c65ba6af..000000000 --- a/spring-cloud-stream-schema-server/src/test/java/org/springframework/cloud/stream/schema/server/entityScanning/domain/TestEntity.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.server.entityScanning.domain; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; - -/** - * @author Marius Bogoevici - */ -@Entity -public class TestEntity { - - @Id - private long id; - - @Column(name = "name") - private String name; - - public long getId() { - return this.id; - } - - public void setId(long id) { - this.id = id; - } - - public String getName() { - return this.name; - } - - public void setName(String name) { - this.name = name; - } - -} diff --git a/spring-cloud-stream-schema/.jdk8 b/spring-cloud-stream-schema/.jdk8 deleted file mode 100644 index e69de29bb..000000000 diff --git a/spring-cloud-stream-schema/pom.xml b/spring-cloud-stream-schema/pom.xml deleted file mode 100644 index 307f2c5a0..000000000 --- a/spring-cloud-stream-schema/pom.xml +++ /dev/null @@ -1,103 +0,0 @@ - - - - spring-cloud-stream-parent - org.springframework.cloud - 3.0.0.BUILD-SNAPSHOT - - 4.0.0 - - spring-cloud-stream-schema - - 1.8.1 - - - - - org.springframework.cloud - spring-cloud-stream - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-configuration-processor - true - - - org.springframework.boot - spring-boot-starter-test - test - - - org.apache.avro - avro - ${avro.version} - true - - - org.springframework.cloud - spring-cloud-stream-test-support - test - - - org.springframework.cloud - spring-cloud-stream-test-support-internal - test - - - org.springframework.cloud - spring-cloud-stream-schema-server - test - - - com.fasterxml.jackson.dataformat - jackson-dataformat-avro - test - - - - - - org.apache.avro - avro-maven-plugin - ${avro.version} - - - generate-test-sources - - schema - - - - - ${project.basedir}/target/generated-test-sources - - - ${project.basedir}/target/generated-test-sources - - ${project.basedir}/src/test/resources/schemas - - - **/*.avsc - - - - ${project.basedir}/src/test/resources/schemas/imports/Email.avsc - - - ${project.basedir}/src/test/resources/schemas/imports/Sms.avsc - - - ${project.basedir}/src/test/resources/schemas/imports/PushNotification.avsc - - - - - - - diff --git a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/ParsedSchema.java b/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/ParsedSchema.java deleted file mode 100644 index 1daada556..000000000 --- a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/ParsedSchema.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema; - -import org.apache.avro.Schema; - -/** - * Stores a {@link Schema} together with its String representation. - * - * Helps to avoid unnecessary parsing of schema textual representation, as well as calls - * to {@link org.apache.avro.Schema} toString method which is very expensive due the - * utilization of {@link com.fasterxml.jackson.databind.ObjectMapper} to output a JSON - * representation of the schema. - * - * Once a schema is found for any Class, be it a POJO or a - * {@link org.apache.avro.generic.GenericContainer}, both textual representation as well - * as the {@link org.apache.avro.Schema} will be stored within this class. - * - * @author Vinicius Carvalho - * - */ -public class ParsedSchema { - - private final Schema schema; - - private final String representation; - - private SchemaRegistrationResponse registration; - - public ParsedSchema(Schema schema) { - this.schema = schema; - this.representation = schema.toString(); - } - - public Schema getSchema() { - return this.schema; - } - - public String getRepresentation() { - return this.representation; - } - - public SchemaRegistrationResponse getRegistration() { - return this.registration; - } - - public void setRegistration(SchemaRegistrationResponse registration) { - this.registration = registration; - } - -} diff --git a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/SchemaNotFoundException.java b/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/SchemaNotFoundException.java deleted file mode 100644 index 4c9707e23..000000000 --- a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/SchemaNotFoundException.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema; - -/** - * @author Vinicius Carvalho - */ -public class SchemaNotFoundException extends RuntimeException { - - public SchemaNotFoundException(String message) { - super(message); - } - -} diff --git a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/SchemaReference.java b/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/SchemaReference.java deleted file mode 100644 index 4a1b8c9e7..000000000 --- a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/SchemaReference.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema; - -import org.springframework.util.Assert; - -/** - * References a schema through its subject and version. - * - * @author Marius Bogoevici - */ -public class SchemaReference { - - private String subject; - - private int version; - - private String format; - - public SchemaReference(String subject, int version, String format) { - Assert.hasText(subject, "cannot be empty"); - Assert.isTrue(version > 0, "must be a positive integer"); - Assert.hasText(format, "cannot be empty"); - this.subject = subject; - this.version = version; - this.format = format; - } - - public String getSubject() { - return this.subject; - } - - public void setSubject(String subject) { - Assert.hasText(subject, "cannot be empty"); - this.subject = subject; - } - - public int getVersion() { - return this.version; - } - - public void setVersion(int version) { - Assert.isTrue(version > 0, "must be a positive integer"); - this.version = version; - } - - public String getFormat() { - return this.format; - } - - public void setFormat(String format) { - Assert.hasText(format, "cannot be empty"); - this.format = format; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - SchemaReference that = (SchemaReference) o; - - if (this.version != that.version) { - return false; - } - if (!this.subject.equals(that.subject)) { - return false; - } - return this.format.equals(that.format); - - } - - @Override - public int hashCode() { - int result = this.subject.hashCode(); - result = 31 * result + this.version; - result = 31 * result + this.format.hashCode(); - return result; - } - - @Override - public String toString() { - return "SchemaReference{" + "subject='" + this.subject + '\'' + ", version=" - + this.version + ", format='" + this.format + '\'' + '}'; - } - -} diff --git a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/SchemaRegistrationResponse.java b/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/SchemaRegistrationResponse.java deleted file mode 100644 index 0a3e24efa..000000000 --- a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/SchemaRegistrationResponse.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema; - -/** - * @author Marius Bogoevici - */ -public class SchemaRegistrationResponse { - - private int id; - - private SchemaReference schemaReference; - - public int getId() { - return this.id; - } - - public void setId(int id) { - this.id = id; - } - - public SchemaReference getSchemaReference() { - return this.schemaReference; - } - - public void setSchemaReference(SchemaReference schemaReference) { - this.schemaReference = schemaReference; - } - -} diff --git a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/AbstractAvroMessageConverter.java b/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/AbstractAvroMessageConverter.java deleted file mode 100644 index 5f1daa425..000000000 --- a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/AbstractAvroMessageConverter.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2016-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.avro; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.Collection; -import java.util.Collections; - -import org.apache.avro.Schema; -import org.apache.avro.io.DatumWriter; -import org.apache.avro.io.Encoder; -import org.apache.avro.io.EncoderFactory; - -import org.springframework.core.io.Resource; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.converter.AbstractMessageConverter; -import org.springframework.messaging.converter.MessageConversionException; -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 - * @author Ish Mahajan - */ -public abstract class AbstractAvroMessageConverter extends AbstractMessageConverter { - - /** - * common parser will let user to import external schemas. - */ - private Schema.Parser schemaParser = new Schema.Parser(); - private AvroSchemaServiceManager avroSchemaServiceManager; - - @Deprecated - protected AbstractAvroMessageConverter(MimeType supportedMimeType) { - this(Collections.singletonList(supportedMimeType), new AvroSchemaServiceManagerImpl()); - } - - protected AbstractAvroMessageConverter(MimeType supportedMimeType, AvroSchemaServiceManager avroSchemaServiceManager) { - this(Collections.singletonList(supportedMimeType), avroSchemaServiceManager); - } - - @Deprecated - protected AbstractAvroMessageConverter(Collection supportedMimeTypes) { - this(supportedMimeTypes, new AvroSchemaServiceManagerImpl()); - setContentTypeResolver(new OriginalContentTypeResolver()); - } - - protected AbstractAvroMessageConverter(Collection supportedMimeTypes, AvroSchemaServiceManager manager) { - super(supportedMimeTypes); - setContentTypeResolver(new OriginalContentTypeResolver()); - this.avroSchemaServiceManager = manager; - } - - protected AvroSchemaServiceManager avroSchemaServiceManager() { - return this.avroSchemaServiceManager; - } - - protected Schema parseSchema(Resource r) throws IOException { - return this.schemaParser.parse(r.getInputStream()); - } - - @Override - protected boolean canConvertFrom(Message message, Class targetClass) { - return super.canConvertFrom(message, targetClass) - && (message.getPayload() instanceof byte[]); - } - - @Override - protected Object convertFromInternal(Message message, Class targetClass, - Object conversionHint) { - Object result; - try { - byte[] payload = (byte[]) message.getPayload(); - - MimeType mimeType = getContentTypeResolver().resolve(message.getHeaders()); - if (mimeType == null) { - if (conversionHint instanceof MimeType) { - mimeType = (MimeType) conversionHint; - } - else { - return null; - } - } - - Schema writerSchema = resolveWriterSchemaForDeserialization(mimeType); - Schema readerSchema = resolveReaderSchemaForDeserialization(targetClass); - - result = avroSchemaServiceManager().readData(targetClass, payload, readerSchema, writerSchema); - } - catch (IOException e) { - throw new MessageConversionException(message, "Failed to read payload", e); - } - return result; - } - - @Override - protected Object convertToInternal(Object payload, MessageHeaders headers, - Object conversionHint) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try { - MimeType hintedContentType = null; - if (conversionHint instanceof MimeType) { - hintedContentType = (MimeType) conversionHint; - } - Schema schema = resolveSchemaForWriting(payload, headers, hintedContentType); - @SuppressWarnings("unchecked") - DatumWriter writer = avroSchemaServiceManager() - .getDatumWriter(payload.getClass(), schema); - Encoder encoder = EncoderFactory.get().binaryEncoder(baos, null); - writer.write(payload, encoder); - encoder.flush(); - } - catch (IOException e) { - throw new MessageConversionException("Failed to write payload", e); - } - return baos.toByteArray(); - } - - protected abstract Schema resolveSchemaForWriting(Object payload, - MessageHeaders headers, MimeType hintedContentType); - - protected abstract Schema resolveWriterSchemaForDeserialization(MimeType mimeType); - - protected abstract Schema resolveReaderSchemaForDeserialization(Class targetClass); - -} diff --git a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/AvroMessageConverterAutoConfiguration.java b/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/AvroMessageConverterAutoConfiguration.java deleted file mode 100644 index dbe8f0326..000000000 --- a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/AvroMessageConverterAutoConfiguration.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2016-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.avro; - -import java.lang.reflect.Constructor; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cache.CacheManager; -import org.springframework.cache.concurrent.ConcurrentMapCacheManager; -import org.springframework.cloud.stream.annotation.StreamMessageConverter; -import org.springframework.cloud.stream.schema.client.SchemaRegistryClient; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.util.ObjectUtils; -import org.springframework.util.ReflectionUtils; - -/** - * @author Marius Bogoevici - * @author Vinicius Carvalho - * @author Sercan Karaoglu - * @author Ish Mahajan - */ -@Configuration -@ConditionalOnClass(name = "org.apache.avro.Schema") -@ConditionalOnProperty(value = "spring.cloud.stream.schemaRegistryClient.enabled", matchIfMissing = true) -@ConditionalOnBean(type = "org.springframework.cloud.stream.schema.client.SchemaRegistryClient") -@EnableConfigurationProperties({ AvroMessageConverterProperties.class }) -@Import(AvroSchemaServiceManagerImpl.class) -public class AvroMessageConverterAutoConfiguration { - - @Autowired - private AvroMessageConverterProperties avroMessageConverterProperties; - @Autowired - private AvroSchemaServiceManager avroSchemaServiceManager; - - @Bean - @ConditionalOnMissingBean(AvroSchemaRegistryClientMessageConverter.class) - @StreamMessageConverter - public AvroSchemaRegistryClientMessageConverter avroSchemaMessageConverter( - SchemaRegistryClient schemaRegistryClient) { - AvroSchemaRegistryClientMessageConverter avroSchemaRegistryClientMessageConverter; - avroSchemaRegistryClientMessageConverter = new AvroSchemaRegistryClientMessageConverter( - schemaRegistryClient, cacheManager(), avroSchemaServiceManager); - avroSchemaRegistryClientMessageConverter.setDynamicSchemaGenerationEnabled( - this.avroMessageConverterProperties.isDynamicSchemaGenerationEnabled()); - if (this.avroMessageConverterProperties.getReaderSchema() != null) { - avroSchemaRegistryClientMessageConverter.setReaderSchema( - this.avroMessageConverterProperties.getReaderSchema()); - } - if (!ObjectUtils - .isEmpty(this.avroMessageConverterProperties.getSchemaLocations())) { - avroSchemaRegistryClientMessageConverter.setSchemaLocations( - this.avroMessageConverterProperties.getSchemaLocations()); - } - if (!ObjectUtils - .isEmpty(this.avroMessageConverterProperties.getSchemaImports())) { - avroSchemaRegistryClientMessageConverter.setSchemaImports( - this.avroMessageConverterProperties.getSchemaImports()); - } - avroSchemaRegistryClientMessageConverter - .setPrefix(this.avroMessageConverterProperties.getPrefix()); - - try { - 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); - } - - return avroSchemaRegistryClientMessageConverter; - } - - @Bean - @ConditionalOnMissingBean - public CacheManager cacheManager() { - return new ConcurrentMapCacheManager(); - } - -} diff --git a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/AvroMessageConverterProperties.java b/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/AvroMessageConverterProperties.java deleted file mode 100644 index a6082772a..000000000 --- a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/AvroMessageConverterProperties.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2016-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.avro; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.core.io.Resource; -import org.springframework.util.Assert; - -/** - * @author Vinicius Carvalho - * @author Sercan Karaoglu - */ -@ConfigurationProperties(prefix = "spring.cloud.stream.schema.avro") -public class AvroMessageConverterProperties { - - private boolean dynamicSchemaGenerationEnabled; - - 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} - * @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. - * @parameter - */ - private Resource[] schemaImports; - - private String prefix = "vnd"; - - private Class subjectNamingStrategy = DefaultSubjectNamingStrategy.class; - - public Resource getReaderSchema() { - return this.readerSchema; - } - - public void setReaderSchema(Resource readerSchema) { - Assert.notNull(readerSchema, "cannot be null"); - this.readerSchema = readerSchema; - } - - public Resource[] getSchemaLocations() { - return this.schemaLocations; - } - - public void setSchemaLocations(Resource[] schemaLocations) { - Assert.notEmpty(schemaLocations, "cannot be null"); - this.schemaLocations = schemaLocations; - } - - public boolean isDynamicSchemaGenerationEnabled() { - return this.dynamicSchemaGenerationEnabled; - } - - public void setDynamicSchemaGenerationEnabled( - boolean dynamicSchemaGenerationEnabled) { - this.dynamicSchemaGenerationEnabled = dynamicSchemaGenerationEnabled; - } - - public String getPrefix() { - return this.prefix; - } - - public void setPrefix(String prefix) { - this.prefix = prefix; - } - - public Class getSubjectNamingStrategy() { - return this.subjectNamingStrategy; - } - - public void setSubjectNamingStrategy( - Class subjectNamingStrategy) { - Assert.notNull(subjectNamingStrategy, "cannot be null"); - this.subjectNamingStrategy = subjectNamingStrategy; - } - - public Resource[] getSchemaImports() { - return this.schemaImports; - } - - public void setSchemaImports(Resource[] schemaImports) { - this.schemaImports = schemaImports; - } - -} diff --git a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/AvroSchemaMessageConverter.java b/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/AvroSchemaMessageConverter.java deleted file mode 100644 index 3435cc4b7..000000000 --- a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/AvroSchemaMessageConverter.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.avro; - -import java.io.IOException; -import java.util.Collection; - -import org.apache.avro.Schema; - -import org.springframework.core.io.Resource; -import org.springframework.messaging.MessageHeaders; -import org.springframework.util.Assert; -import org.springframework.util.MimeType; - -/** - * A {@link org.springframework.messaging.converter.MessageConverter} using Apache Avro. - * The schema for serializing and deserializing will be automatically inferred from the - * 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 - * @author Ish Mahajan - */ - -public class AvroSchemaMessageConverter extends AbstractAvroMessageConverter { - - private Schema schema; - - /** - * Create a {@link AvroSchemaMessageConverter}. Uses the default {@link MimeType} of - * {@code "application/avro"}. - */ - @Deprecated - public AvroSchemaMessageConverter() { - super(new MimeType("application", "avro")); - } - - /** - * Create a {@link AvroSchemaMessageConverter}. Uses the default {@link MimeType} of - * {@code "application/avro"}. - * @param manager for schema management - */ - public AvroSchemaMessageConverter(AvroSchemaServiceManager manager) { - super(new MimeType("application", "avro"), manager); - } - - /** - * Create a {@link AvroSchemaMessageConverter}. The converter will be used for the - * provided {@link MimeType}. - * @param supportedMimeType mime type to be supported by - * {@link AvroSchemaMessageConverter} - */ - @Deprecated - public AvroSchemaMessageConverter(MimeType supportedMimeType) { - super(supportedMimeType); - } - - /** - * Create a {@link AvroSchemaMessageConverter}. The converter will be used for the - * provided {@link MimeType}. - * @param supportedMimeType mime type to be supported by - * {@link AvroSchemaMessageConverter} - * @param manager for schema management - */ - public AvroSchemaMessageConverter(MimeType supportedMimeType, AvroSchemaServiceManager manager) { - super(supportedMimeType, manager); - } - - /** - * Create a {@link AvroSchemaMessageConverter}. The converter will be used for the - * provided {@link MimeType}s. - * @param supportedMimeTypes the mime types supported by this converter - */ - @Deprecated - public AvroSchemaMessageConverter(Collection supportedMimeTypes) { - super(supportedMimeTypes); - } - - /** - * Create a {@link AvroSchemaMessageConverter}. The converter will be used for the - * provided {@link MimeType}s. - * @param supportedMimeTypes the mime types supported by this converter - * @param manager for schema management - */ - public AvroSchemaMessageConverter(Collection supportedMimeTypes, AvroSchemaServiceManager manager) { - super(supportedMimeTypes, manager); - } - - public Schema getSchema() { - return this.schema; - } - - /** - * Sets the Apache Avro schema to be used by this converter. - * @param schema schema to be used by this converter - */ - public void setSchema(Schema schema) { - Assert.notNull(schema, "schema cannot be null"); - this.schema = schema; - } - - /** - * The location of the Apache Avro schema to be used by this converter. - * @param schemaLocation the location of the schema used by this converter. - */ - public void setSchemaLocation(Resource schemaLocation) { - Assert.notNull(schemaLocation, "schema cannot be null"); - try { - this.schema = parseSchema(schemaLocation); - } - catch (IOException e) { - throw new IllegalStateException("Schema cannot be parsed:", e); - } - } - - @Override - protected boolean supports(Class clazz) { - return true; - } - - @Override - protected Schema resolveWriterSchemaForDeserialization(MimeType mimeType) { - return this.schema; - } - - @Override - protected Schema resolveReaderSchemaForDeserialization(Class targetClass) { - return this.schema; - } - - @Override - protected Schema resolveSchemaForWriting(Object payload, MessageHeaders headers, - MimeType hintedContentType) { - return this.schema; - } - -} diff --git a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/AvroSchemaRegistryClientMessageConverter.java b/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/AvroSchemaRegistryClientMessageConverter.java deleted file mode 100644 index 795cc6ce6..000000000 --- a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/AvroSchemaRegistryClientMessageConverter.java +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Copyright 2016-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.avro; - -import java.io.IOException; -import java.util.Arrays; -import java.util.Collections; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Stream; - -import org.apache.avro.Schema; -import org.apache.avro.generic.GenericContainer; - -import org.springframework.beans.DirectFieldAccessor; -import org.springframework.beans.factory.BeanInitializationException; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.cache.Cache; -import org.springframework.cache.CacheManager; -import org.springframework.cache.support.NoOpCacheManager; -import org.springframework.cloud.stream.schema.ParsedSchema; -import org.springframework.cloud.stream.schema.SchemaNotFoundException; -import org.springframework.cloud.stream.schema.SchemaReference; -import org.springframework.cloud.stream.schema.SchemaRegistrationResponse; -import org.springframework.cloud.stream.schema.client.SchemaRegistryClient; -import org.springframework.core.io.Resource; -import org.springframework.messaging.MessageHeaders; -import org.springframework.util.Assert; -import org.springframework.util.MimeType; -import org.springframework.util.ObjectUtils; - -/** - * A {@link org.springframework.messaging.converter.MessageConverter} for Apache Avro, - * with the ability to publish and retrieve schemas stored in a schema server, allowing - * for schema evolution in applications. The supported content types are in the form - * `application/*+avro`. - * - * During the conversion to a message, the converter will set the 'contentType' header to - * 'application/[prefix].[subject].v[version]+avro', where: - * - *
  • - *
      - * prefix is a configurable prefix (default 'vnd'); - *
    - *
      - * subject is a subject derived from the type of the outgoing object - typically - * the class name; - *
    - *
      - * version is the schema version for the given subject; - *
    - *
  • - * - * When converting from a message, the converter will parse the content-type and use it to - * fetch and cache the writer schema using the provided {@link SchemaRegistryClient}. - * - * @author Marius Bogoevici - * @author Vinicius Carvalho - * @author Oleg Zhurakousky - * @author Sercan Karaoglu - * @author Ish Mahajan - */ -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"; - - /** - * Default Mime type for Avro. - */ - public static final MimeType DEFAULT_AVRO_MIME_TYPE = new MimeType("application", - "*+" + AVRO_FORMAT); - - private static final AvroSchemaServiceManager defaultAvroSchemaServiceManager = - new AvroSchemaServiceManagerImpl(); - - private final CacheManager cacheManager; - - protected Resource[] schemaImports = new Resource[] {}; - - private Pattern versionedSchema; - - private boolean dynamicSchemaGenerationEnabled; - - private Schema readerSchema; - - private Resource[] schemaLocations; - - private SchemaRegistryClient schemaRegistryClient; - - private String prefix = "vnd"; - - private SubjectNamingStrategy subjectNamingStrategy; - - /** - * Creates a new instance, configuring it with {@link SchemaRegistryClient} and - * {@link CacheManager}. - * @param schemaRegistryClient the {@link SchemaRegistryClient} used to interact with - * the schema registry server. - * @param cacheManager instance of {@link CacheManager} to cache parsed schemas. If - * caching is not required use {@link NoOpCacheManager} - */ - @Deprecated - public AvroSchemaRegistryClientMessageConverter( - SchemaRegistryClient schemaRegistryClient, CacheManager cacheManager) { - super(Collections.singletonList(DEFAULT_AVRO_MIME_TYPE), defaultAvroSchemaServiceManager); - Assert.notNull(schemaRegistryClient, "cannot be null"); - Assert.notNull(cacheManager, "'cacheManager' cannot be null"); - this.schemaRegistryClient = schemaRegistryClient; - this.cacheManager = cacheManager; - } - - /** - * Creates a new instance, configuring it with {@link SchemaRegistryClient} and - * {@link CacheManager}. - * @param schemaRegistryClient the {@link SchemaRegistryClient} used to interact with - * the schema registry server. - * @param cacheManager instance of {@link CacheManager} to cache parsed schemas. If - * caching is not required use {@link NoOpCacheManager} - * @param manager instance of {@link AvroSchemaServiceManager} to manage schemas. - */ - public AvroSchemaRegistryClientMessageConverter( - SchemaRegistryClient schemaRegistryClient, CacheManager cacheManager, AvroSchemaServiceManager manager) { - super(Collections.singletonList(DEFAULT_AVRO_MIME_TYPE), manager); - Assert.notNull(schemaRegistryClient, "cannot be null"); - Assert.notNull(cacheManager, "'cacheManager' cannot be null"); - Assert.notNull(manager, "'avroSchemaServiceManager' cannot be null"); - this.schemaRegistryClient = schemaRegistryClient; - this.cacheManager = cacheManager; - } - - public boolean isDynamicSchemaGenerationEnabled() { - return this.dynamicSchemaGenerationEnabled; - } - - /** - * Allows the converter to generate and register schemas automatically. If set to - * false, it only allows the converter to use pre-registered schemas. Default 'true'. - * @param dynamicSchemaGenerationEnabled true if dynamic schema generation is enabled - */ - public void setDynamicSchemaGenerationEnabled( - boolean dynamicSchemaGenerationEnabled) { - this.dynamicSchemaGenerationEnabled = dynamicSchemaGenerationEnabled; - } - - /** - * A set of locations where the converter can load schemas from. Schemas provided at - * these locations will be registered automatically. - * @param schemaLocations array of locations - */ - public void setSchemaLocations(Resource[] schemaLocations) { - Assert.notEmpty(schemaLocations, "cannot be empty"); - this.schemaLocations = schemaLocations; - } - - /** - * 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 array of schema imports - */ - public void setSchemaImports(Resource[] schemaImports) { - this.schemaImports = schemaImports; - } - - /** - * 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"); - Assert.isTrue(!PREFIX_VALIDATION_PATTERN.matcher(this.prefix).matches(), - "Invalid prefix:" + this.prefix); - this.prefix = prefix; - } - - public void setReaderSchema(Resource readerSchema) { - Assert.notNull(readerSchema, "cannot be null"); - try { - this.readerSchema = parseSchema(readerSchema); - } - catch (IOException e) { - throw new BeanInitializationException("Cannot initialize reader schema", e); - } - } - - public void setSubjectNamingStrategy(SubjectNamingStrategy subjectNamingStrategy) { - this.subjectNamingStrategy = subjectNamingStrategy; - } - - @Override - public void afterPropertiesSet() throws Exception { - this.versionedSchema = Pattern.compile("application/" + this.prefix - + "\\.([\\p{Alnum}\\$\\.]+)\\.v(\\p{Digit}+)\\+" + AVRO_FORMAT); - - Stream.of(this.schemaImports, this.schemaLocations) - .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); - } - } - }); - - if (this.cacheManager instanceof NoOpCacheManager) { - 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)."); - } - } - - protected String toSubject(Schema schema) { - return this.subjectNamingStrategy.toSubject(schema); - } - - @Override - protected boolean supports(Class clazz) { - // we support all types - return true; - } - - @Override - protected boolean supportsMimeType(MessageHeaders headers) { - if (super.supportsMimeType(headers)) { - return true; - } - MimeType mimeType = getContentTypeResolver().resolve(headers); - return DEFAULT_AVRO_MIME_TYPE.includes(mimeType); - } - - @Override - protected Schema resolveSchemaForWriting(Object payload, MessageHeaders headers, - MimeType hintedContentType) { - - Schema schema; - schema = extractSchemaForWriting(payload); - ParsedSchema parsedSchema = this.getCache(REFERENCE_CACHE_NAME) - .get(schema, ParsedSchema.class); - - if (parsedSchema == null) { - parsedSchema = new ParsedSchema(schema); - this.getCache(REFERENCE_CACHE_NAME).putIfAbsent(schema, - parsedSchema); - } - - if (parsedSchema.getRegistration() == null) { - SchemaRegistrationResponse response = this.schemaRegistryClient.register( - toSubject(schema), AVRO_FORMAT, parsedSchema.getRepresentation()); - parsedSchema.setRegistration(response); - - } - - SchemaReference schemaReference = parsedSchema.getRegistration() - .getSchemaReference(); - - DirectFieldAccessor dfa = new DirectFieldAccessor(headers); - @SuppressWarnings("unchecked") - Map _headers = (Map) dfa - .getPropertyValue("headers"); - _headers.put(MessageHeaders.CONTENT_TYPE, - "application/" + this.prefix + "." + schemaReference.getSubject() + ".v" - + schemaReference.getVersion() + "+" + AVRO_FORMAT); - - return schema; - } - - @Override - protected Schema resolveWriterSchemaForDeserialization(MimeType mimeType) { - if (this.readerSchema == null) { - SchemaReference schemaReference = extractSchemaReference(mimeType); - if (schemaReference != null) { - ParsedSchema parsedSchema = this.getCache(REFERENCE_CACHE_NAME) - .get(schemaReference, ParsedSchema.class); - if (parsedSchema == null) { - String schemaContent = this.schemaRegistryClient - .fetch(schemaReference); - if (schemaContent != null) { - Schema schema = new Schema.Parser().parse(schemaContent); - parsedSchema = new ParsedSchema(schema); - this.getCache(REFERENCE_CACHE_NAME) - .putIfAbsent(schemaReference, parsedSchema); - } - } - if (parsedSchema != null) { - return parsedSchema.getSchema(); - } - } - } - return this.readerSchema; - } - - @Override - protected Schema resolveReaderSchemaForDeserialization(Class targetClass) { - return this.readerSchema; - } - - private Schema extractSchemaForWriting(Object payload) { - Schema schema = null; - if (this.logger.isDebugEnabled()) { - this.logger.debug("Obtaining schema for class " + payload.getClass()); - } - if (GenericContainer.class.isAssignableFrom(payload.getClass())) { - schema = ((GenericContainer) payload).getSchema(); - if (this.logger.isDebugEnabled()) { - this.logger.debug("Avro type detected, using schema from object"); - } - } - else { - schema = this.getCache(REFLECTION_CACHE_NAME) - .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())); - } - else { - schema = super.avroSchemaServiceManager().getSchema(payload.getClass()); - } - this.getCache(REFLECTION_CACHE_NAME) - .put(payload.getClass().getName(), schema); - } - } - return schema; - } - - 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.schemaRegistryClient.register(toSubject(schema), AVRO_FORMAT, - schema.toString()); - if (this.logger.isInfoEnabled()) { - this.logger - .info("Schema " + schema.getName() + " registered with id " + schema); - } - this.getCache(REFLECTION_CACHE_NAME) - .put(schema.getNamespace() + "." + schema.getName(), schema); - } - - 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, AVRO_FORMAT); - } - return schemaReference; - } - - private Cache getCache(String name) { - Cache cache = this.cacheManager.getCache(name); - Assert.notNull(cache, "Cache by the name '" + name + "' is not present in this CacheManager - '" - + this.cacheManager + "'. Typically caches are auto-created by the CacheManagers. " - + "Consider reporting it as an issue to the developer of this CacheManager."); - return cache; - } - -} diff --git a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/AvroSchemaServiceManager.java b/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/AvroSchemaServiceManager.java deleted file mode 100644 index 087db862d..000000000 --- a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/AvroSchemaServiceManager.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.avro; - -import java.io.IOException; - -import org.apache.avro.Schema; -import org.apache.avro.io.DatumReader; -import org.apache.avro.io.DatumWriter; - -/** - * Manage a {@link Schema} together with its String representation. - * - * Helps to substitute the default implementation of {@link org.apache.avro.Schema} - * Generation using Custom Avro schema generator - * - * Provide a custom bean definition of {@link AvroSchemaServiceManager} and mark - * it as @Primary to override the default implementation - * - * @author Ish Mahajan - * - */ -public interface AvroSchemaServiceManager { - - /** - * get {@link Schema}. - * @param clazz {@link Class} for which schema generation is required - * @return returns avro schema for given class - */ - Schema getSchema(Class clazz); - - /** - * get {@link DatumWriter}. - * @param type {@link Class} of java object which needs to be serialized - * @param schema {@link Schema} of object which needs to be serialized - * @return datum writer which can be used to write Avro payload - */ - DatumWriter getDatumWriter(Class type, Schema schema); - - /** - * get {@link DatumReader}. - * @param type {@link Class} of java object which needs to be serialized - * @param schema {@link Schema} default schema of object which needs to be de-serialized - * @param writerSchema {@link Schema} writerSchema provided at run time - * @return datum reader which can be used to read Avro payload - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - DatumReader getDatumReader(Class type, Schema schema, Schema writerSchema); - - /** - * read data from avro type payload {@link DatumReader}. - * @param targetClass {@link Class} of java object which needs to be serialized - * @param payload {@link byte} serialized payload of object which needs to be de-serialized - * @param readerSchema {@link Schema} readerSchema of object which needs to be de-serialized - * @param writerSchema {@link Schema} writerSchema used to while serializing payload - * @return java object after reading Avro Payload - * @throws IOException in case of error - */ - Object readData(Class targetClass, byte[] payload, Schema readerSchema, Schema writerSchema) - throws IOException; -} diff --git a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/AvroSchemaServiceManagerImpl.java b/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/AvroSchemaServiceManagerImpl.java deleted file mode 100644 index 79b073226..000000000 --- a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/AvroSchemaServiceManagerImpl.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.avro; - -import java.io.IOException; - -import org.apache.avro.Schema; -import org.apache.avro.generic.GenericDatumReader; -import org.apache.avro.generic.GenericDatumWriter; -import org.apache.avro.generic.GenericRecord; -import org.apache.avro.io.DatumReader; -import org.apache.avro.io.DatumWriter; -import org.apache.avro.io.Decoder; -import org.apache.avro.io.DecoderFactory; -import org.apache.avro.reflect.ReflectData; -import org.apache.avro.reflect.ReflectDatumReader; -import org.apache.avro.reflect.ReflectDatumWriter; -import org.apache.avro.specific.SpecificDatumReader; -import org.apache.avro.specific.SpecificDatumWriter; -import org.apache.avro.specific.SpecificRecord; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.messaging.converter.MessageConversionException; -import org.springframework.stereotype.Component; - -/** - * Default Concrete implementation of {@link AvroSchemaServiceManager}. - * - * Helps to substitute the default implementation of {@link org.apache.avro.Schema} - * Generation using Custom Avro schema generator - * - * Provide a custom bean definition of {@link AvroSchemaServiceManager} and mark - * it as @Primary to override this default implementation - * - * @author Ish Mahajan - * - */ - -@Component -public class AvroSchemaServiceManagerImpl implements AvroSchemaServiceManager { - - protected final Log logger = LogFactory.getLog(this.getClass()); - - /** - * get {@link Schema}. - * @param clazz {@link Class} for which schema generation - * is required - * @return returns avro schema for given class - */ - @Override - public Schema getSchema(Class clazz) { - return ReflectData.get().getSchema(clazz); - } - - /** - * get {@link DatumWriter}. - * @param type {@link Class} of java object which needs to be serialized - * @param schema {@link Schema} of object which needs to be serialized - * @return datum writer which can be used to write Avro payload - */ - @Override - public DatumWriter getDatumWriter(Class type, Schema schema) { - DatumWriter writer; - this.logger.debug("Finding correct DatumWriter for type " + type.getName()); - if (SpecificRecord.class.isAssignableFrom(type)) { - if (schema != null) { - writer = new SpecificDatumWriter<>(schema); - } - else { - writer = new SpecificDatumWriter(type); - } - } - else if (GenericRecord.class.isAssignableFrom(type)) { - writer = new GenericDatumWriter<>(schema); - } - else { - if (schema != null) { - writer = new ReflectDatumWriter<>(schema); - } - else { - writer = new ReflectDatumWriter(type); - } - } - return writer; - } - - /** - * get {@link DatumReader}. - * @param type {@link Class} of java object which needs to be serialized - * @param schema {@link Schema} default schema of object which needs to be de-serialized - * @param writerSchema {@link Schema} writerSchema provided at run time - * @return datum reader which can be used to read Avro payload - */ - @SuppressWarnings({"unchecked", "rawtypes"}) - @Override - public DatumReader getDatumReader(Class type, Schema schema, Schema writerSchema) { - DatumReader reader = null; - if (SpecificRecord.class.isAssignableFrom(type)) { - if (schema != null) { - if (writerSchema != null) { - reader = new SpecificDatumReader<>(writerSchema, schema); - } - else { - reader = new SpecificDatumReader<>(schema); - } - } - else { - reader = new SpecificDatumReader(type); - if (writerSchema != null) { - reader.setSchema(writerSchema); - } - } - } - else if (GenericRecord.class.isAssignableFrom(type)) { - if (schema != null) { - if (writerSchema != null) { - reader = new GenericDatumReader<>(writerSchema, schema); - } - else { - reader = new GenericDatumReader<>(schema); - } - } - else { - if (writerSchema != null) { - reader = new GenericDatumReader(writerSchema); - } - } - } - else { - reader = new ReflectDatumReader(type); - if (writerSchema != null) { - reader.setSchema(writerSchema); - } - } - if (reader == null) { - throw new MessageConversionException("No schema can be inferred from type " - + type.getName() + " and no schema has been explicitly configured."); - } - return reader; - } - - /** - * read data from avro type payload {@link DatumReader}. - * @param clazz {@link Class} of java object which needs to be serialized - * @param payload {@link byte} serialized payload of object which needs to be de-serialized - * @param readerSchema {@link Schema} readerSchema of object which needs to be de-serialized - * @param writerSchema {@link Schema} writerSchema used to while serializing payload - * @return java object after reading Avro Payload - * @throws IOException is thrown in case of error - */ - @Override - public Object readData(Class clazz, byte[] payload, Schema readerSchema, - Schema writerSchema) throws IOException { - DatumReader reader = this.getDatumReader(clazz, - readerSchema, writerSchema); - Decoder decoder = DecoderFactory.get().binaryDecoder(payload, null); - return reader.read(null, decoder); - } -} diff --git a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/DefaultSubjectNamingStrategy.java b/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/DefaultSubjectNamingStrategy.java deleted file mode 100644 index 90cd3598a..000000000 --- a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/DefaultSubjectNamingStrategy.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2016-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.avro; - -import org.apache.avro.Schema; - -/** - * @author David Kalosi - */ -public class DefaultSubjectNamingStrategy implements SubjectNamingStrategy { - - @Override - public String toSubject(Schema schema) { - return schema.getName().toLowerCase(); - } - -} diff --git a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/OriginalContentTypeResolver.java b/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/OriginalContentTypeResolver.java deleted file mode 100644 index 76b51d267..000000000 --- a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/OriginalContentTypeResolver.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2017-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.avro; - -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import org.springframework.cloud.stream.binder.BinderHeaders; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.converter.ContentTypeResolver; -import org.springframework.util.MimeType; - -/** - * @author Vinicius Carvalho - * - * Resolves contentType looking for a originalContentType header first. If not found - * returns the contentType - * - */ -class OriginalContentTypeResolver implements ContentTypeResolver { - - private ConcurrentMap mimeTypeCache = new ConcurrentHashMap<>(); - - @Override - public MimeType resolve(MessageHeaders headers) { - Object contentType = headers - .get(BinderHeaders.BINDER_ORIGINAL_CONTENT_TYPE) != null - ? headers.get(BinderHeaders.BINDER_ORIGINAL_CONTENT_TYPE) - : headers.get(MessageHeaders.CONTENT_TYPE); - MimeType mimeType = null; - if (contentType instanceof MimeType) { - mimeType = (MimeType) contentType; - } - else if (contentType instanceof String) { - mimeType = this.mimeTypeCache.get(contentType); - if (mimeType == null) { - String valueAsString = (String) contentType; - mimeType = MimeType.valueOf(valueAsString); - this.mimeTypeCache.put(valueAsString, mimeType); - } - } - return mimeType; - } - -} diff --git a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/QualifiedSubjectNamingStrategy.java b/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/QualifiedSubjectNamingStrategy.java deleted file mode 100644 index d068eb6c3..000000000 --- a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/QualifiedSubjectNamingStrategy.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.avro; - -import org.apache.avro.Schema; - -/** - * @author José A. Íñigo - * @since 2.2.0 - */ -public class QualifiedSubjectNamingStrategy implements SubjectNamingStrategy { - - @Override - public String toSubject(Schema schema) { - return schema.getFullName().toLowerCase(); - } - -} diff --git a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/SubjectNamingStrategy.java b/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/SubjectNamingStrategy.java deleted file mode 100644 index 923e7da97..000000000 --- a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/avro/SubjectNamingStrategy.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2016-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.avro; - -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 schema to register - * @return subject name - */ - String toSubject(Schema schema); - -} diff --git a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/client/CachingRegistryClient.java b/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/client/CachingRegistryClient.java deleted file mode 100644 index dadfacd98..000000000 --- a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/client/CachingRegistryClient.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.client; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cache.CacheManager; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.cloud.stream.schema.SchemaReference; -import org.springframework.cloud.stream.schema.SchemaRegistrationResponse; -import org.springframework.util.Assert; - -/** - * @author Vinicius Carvalho - */ -public class CachingRegistryClient implements SchemaRegistryClient { - - private static final String CACHE_PREFIX = "org.springframework.cloud.stream.schema.client"; - - private static final String ID_CACHE = CACHE_PREFIX + ".schemaByIdCache"; - - private static final String REF_CACHE = CACHE_PREFIX + ".schemaByReferenceCache"; - - private SchemaRegistryClient delegate; - - @Autowired - private CacheManager cacheManager; - - public CachingRegistryClient(SchemaRegistryClient delegate) { - Assert.notNull(delegate, "The delegate cannot be null"); - this.delegate = delegate; - } - - @Override - 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 this.delegate.fetch(schemaReference); - } - - @Override - @Cacheable(cacheNames = ID_CACHE) - public String fetch(int id) { - return this.delegate.fetch(id); - } - -} diff --git a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/client/ConfluentSchemaRegistryClient.java b/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/client/ConfluentSchemaRegistryClient.java deleted file mode 100644 index eca44f3b5..000000000 --- a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/client/ConfluentSchemaRegistryClient.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright 2016-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.client; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; - -import org.springframework.cloud.stream.schema.SchemaNotFoundException; -import org.springframework.cloud.stream.schema.SchemaReference; -import org.springframework.cloud.stream.schema.SchemaRegistrationResponse; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.util.Assert; -import org.springframework.web.client.HttpStatusCodeException; -import org.springframework.web.client.RestTemplate; - -/** - * @author Vinicius Carvalho - * @author Marius Bogoevici - * @author Jon Archer - * @author Tengzhou Dong - */ -public class ConfluentSchemaRegistryClient implements SchemaRegistryClient { - - private static final List ACCEPT_HEADERS = Arrays.asList( - "application/vnd.schemaregistry.v1+json", - "application/vnd.schemaregistry+json", "application/json"); - - private RestTemplate template; - - private String endpoint = "http://localhost:8081"; - - private ObjectMapper mapper; - - public ConfluentSchemaRegistryClient() { - this(new RestTemplate()); - } - - public ConfluentSchemaRegistryClient(RestTemplate template) { - this(template, new ObjectMapper()); - } - - public ConfluentSchemaRegistryClient(RestTemplate template, ObjectMapper mapper) { - this.template = template; - this.mapper = mapper; - } - - public void setEndpoint(String endpoint) { - this.endpoint = endpoint; - } - - @Override - public SchemaRegistrationResponse register(String subject, String format, - String schema) { - Assert.isTrue("avro".equals(format), "Only Avro is supported"); - HttpHeaders headers = new HttpHeaders(); - headers.put("Accept", ACCEPT_HEADERS); - headers.add("Content-Type", "application/json"); - Integer version = null; - Integer id = null; - String payload = null; - Map maps = new HashMap<>(); - maps.put("subject", subject); - maps.put("format", format); - maps.put("definition", schema); - try { - payload = this.mapper.writeValueAsString(maps); - } - catch (JsonProcessingException e) { - throw new RuntimeException("Could not parse schema, invalid JSON format", e); - } - try { - HttpEntity request = new HttpEntity<>(payload, headers); - ResponseEntity response = this.template.exchange(this.endpoint, - HttpMethod.POST, request, Map.class); - id = (Integer) response.getBody().get("id"); - version = (Integer) ((Map) 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); - } - SchemaRegistrationResponse schemaRegistrationResponse = new SchemaRegistrationResponse(); - schemaRegistrationResponse.setId(id); - schemaRegistrationResponse - .setSchemaReference(new SchemaReference(subject, version, "avro")); - return schemaRegistrationResponse; - } - - @Override - public String fetch(SchemaReference schemaReference) { - String path = String.format("/%s/%s/v%d", - schemaReference.getSubject(), schemaReference.getFormat(), schemaReference.getVersion()); - HttpHeaders headers = new HttpHeaders(); - headers.put("Accept", ACCEPT_HEADERS); - headers.add("Content-Type", "application/vnd.schemaregistry.v1+json"); - HttpEntity request = new HttpEntity<>("", headers); - try { - ResponseEntity response = this.template.exchange(this.endpoint + path, - HttpMethod.GET, request, Map.class); - return (String) response.getBody().get("schema"); - } - catch (HttpStatusCodeException e) { - if (e.getStatusCode() == HttpStatus.NOT_FOUND) { - throw new SchemaNotFoundException(String.format( - "Could not find schema for reference: %s", schemaReference)); - } - else { - throw e; - } - } - } - - @Override - public String fetch(int id) { - String path = String.format("/schemas/%d", id); - HttpHeaders headers = new HttpHeaders(); - headers.put("Accept", ACCEPT_HEADERS); - headers.add("Content-Type", "application/vnd.schemaregistry.v1+json"); - HttpEntity request = new HttpEntity<>("", headers); - try { - ResponseEntity response = this.template.exchange(this.endpoint + path, - HttpMethod.GET, request, Map.class); - return (String) response.getBody().get("schema"); - } - catch (HttpStatusCodeException e) { - if (e.getStatusCode() == HttpStatus.NOT_FOUND) { - throw new SchemaNotFoundException( - String.format("Could not find schema with id: %s", id)); - } - else { - throw e; - } - } - } - -} diff --git a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/client/DefaultSchemaRegistryClient.java b/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/client/DefaultSchemaRegistryClient.java deleted file mode 100644 index c2fc9abc8..000000000 --- a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/client/DefaultSchemaRegistryClient.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2016-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.client; - -import java.util.HashMap; -import java.util.Map; - -import org.springframework.cloud.stream.schema.SchemaReference; -import org.springframework.cloud.stream.schema.SchemaRegistrationResponse; -import org.springframework.http.ResponseEntity; -import org.springframework.util.Assert; -import org.springframework.web.client.RestTemplate; - -/** - * @author Marius Bogoevici - * @author Vinicius Carvalho - */ -public class DefaultSchemaRegistryClient implements SchemaRegistryClient { - - private RestTemplate restTemplate; - - private String endpoint = "http://localhost:8990"; - - public DefaultSchemaRegistryClient() { - this(new RestTemplate()); - } - - public DefaultSchemaRegistryClient(RestTemplate restTemplate) { - Assert.notNull(restTemplate, "'restTemplate' must not be null."); - this.restTemplate = restTemplate; - } - - protected String getEndpoint() { - return this.endpoint; - } - - public void setEndpoint(String endpoint) { - Assert.hasText(endpoint, "cannot be empty"); - this.endpoint = endpoint; - } - - protected RestTemplate getRestTemplate() { - return this.restTemplate; - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Override - public SchemaRegistrationResponse register(String subject, String format, - String schema) { - Map requestBody = new HashMap<>(); - requestBody.put("subject", subject); - requestBody.put("format", format); - requestBody.put("definition", schema); - ResponseEntity responseEntity = this.restTemplate - .postForEntity(this.endpoint, requestBody, Map.class); - if (responseEntity.getStatusCode().is2xxSuccessful()) { - SchemaRegistrationResponse registrationResponse = new SchemaRegistrationResponse(); - Map responseBody = (Map) 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()); - } - - @SuppressWarnings("rawtypes") - @Override - public String fetch(SchemaReference schemaReference) { - ResponseEntity 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()); - } - return (String) responseEntity.getBody().get("definition"); - } - - @SuppressWarnings("rawtypes") - @Override - public String fetch(int id) { - ResponseEntity responseEntity = this.restTemplate - .getForEntity(this.endpoint + "/schemas/" + id, Map.class); - if (!responseEntity.getStatusCode().is2xxSuccessful()) { - throw new RuntimeException( - "Failed to fetch schema: " + responseEntity.toString()); - } - return (String) responseEntity.getBody().get("definition"); - } - -} diff --git a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/client/EnableSchemaRegistryClient.java b/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/client/EnableSchemaRegistryClient.java deleted file mode 100644 index 087c94688..000000000 --- a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/client/EnableSchemaRegistryClient.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.client; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.springframework.cloud.stream.schema.client.config.SchemaRegistryClientConfiguration; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; - -/** - * @author Marius Bogoevici - */ -@Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE }) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@Inherited -@Configuration -@Import(SchemaRegistryClientConfiguration.class) -public @interface EnableSchemaRegistryClient { - -} diff --git a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/client/SchemaRegistryClient.java b/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/client/SchemaRegistryClient.java deleted file mode 100644 index e7b0172c1..000000000 --- a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/client/SchemaRegistryClient.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.client; - -import org.springframework.cloud.stream.schema.SchemaReference; -import org.springframework.cloud.stream.schema.SchemaRegistrationResponse; - -/** - * @author Vinicius Carvalho - * @author Marius Bogoevici - */ -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 - */ - SchemaRegistrationResponse register(String subject, String format, String schema); - - /** - * Retrieves a schema by its reference (subject and version). - * @param schemaReference a {@link SchemaReference} used to identify the target - * schema. - * @return schema - */ - String fetch(SchemaReference schemaReference); - - /** - * Retrieves a schema by its identifier. - * @param id the id of the target schema. - * @return schema - */ - String fetch(int id); - -} diff --git a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/client/config/SchemaRegistryClientConfiguration.java b/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/client/config/SchemaRegistryClientConfiguration.java deleted file mode 100644 index 097b3a14c..000000000 --- a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/client/config/SchemaRegistryClientConfiguration.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2016-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.client.config; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.stream.schema.client.CachingRegistryClient; -import org.springframework.cloud.stream.schema.client.DefaultSchemaRegistryClient; -import org.springframework.cloud.stream.schema.client.SchemaRegistryClient; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.util.StringUtils; - -/** - * @author Marius Bogoevici - * @author Vinicius Carvalho - * @author Soby Chacko - */ -@Configuration -@EnableConfigurationProperties(SchemaRegistryClientProperties.class) -public class SchemaRegistryClientConfiguration { - - @Autowired - private SchemaRegistryClientProperties schemaRegistryClientProperties; - - @Bean - @ConditionalOnMissingBean - public SchemaRegistryClient schemaRegistryClient() { - DefaultSchemaRegistryClient defaultSchemaRegistryClient = new DefaultSchemaRegistryClient(); - - if (StringUtils.hasText(this.schemaRegistryClientProperties.getEndpoint())) { - defaultSchemaRegistryClient - .setEndpoint(this.schemaRegistryClientProperties.getEndpoint()); - } - - SchemaRegistryClient client = (this.schemaRegistryClientProperties.isCached()) - ? new CachingRegistryClient(defaultSchemaRegistryClient) - : defaultSchemaRegistryClient; - - return client; - } - -} diff --git a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/client/config/SchemaRegistryClientProperties.java b/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/client/config/SchemaRegistryClientProperties.java deleted file mode 100644 index 4d3f5e255..000000000 --- a/spring-cloud-stream-schema/src/main/java/org/springframework/cloud/stream/schema/client/config/SchemaRegistryClientProperties.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2016-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.stream.schema.client.config; - -import org.springframework.boot.context.properties.ConfigurationProperties; - -/** - * @author Marius Bogoevici - * @author Vinicius Carvalho - */ -@ConfigurationProperties(prefix = "spring.cloud.stream.schema-registry-client") -public class SchemaRegistryClientProperties { - - private String endpoint; - - private boolean cached = false; - - public String getEndpoint() { - return this.endpoint; - } - - public void setEndpoint(String endpoint) { - this.endpoint = endpoint; - } - - public boolean isCached() { - return this.cached; - } - - public void setCached(boolean cached) { - this.cached = cached; - } - -} diff --git a/spring-cloud-stream-schema/src/main/resources/META-INF/spring.factories b/spring-cloud-stream-schema/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 0530b64e9..000000000 --- a/spring-cloud-stream-schema/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,2 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -org.springframework.cloud.stream.schema.avro.AvroMessageConverterAutoConfiguration diff --git a/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/AvroMessageConverterSerializationTests.java b/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/AvroMessageConverterSerializationTests.java deleted file mode 100644 index 8dbdb271e..000000000 --- a/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/AvroMessageConverterSerializationTests.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.schema.avro; - -import java.io.ByteArrayOutputStream; -import java.util.Collections; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import example.avro.Command; -import example.avro.Email; -import example.avro.PushNotification; -import example.avro.Sms; -import example.avro.User; -import org.apache.avro.Schema; -import org.apache.avro.generic.GenericData; -import org.apache.avro.generic.GenericRecord; -import org.apache.avro.io.DatumWriter; -import org.apache.avro.io.Encoder; -import org.apache.avro.io.EncoderFactory; -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.Before; -import org.junit.Test; - -import org.springframework.boot.SpringApplication; -import org.springframework.cache.support.NoOpCacheManager; -import org.springframework.cloud.stream.binder.BinderHeaders; -import org.springframework.cloud.stream.schema.SchemaReference; -import org.springframework.cloud.stream.schema.avro.AvroSchemaRegistryClientMessageConverter; -import org.springframework.cloud.stream.schema.avro.AvroSchemaServiceManager; -import org.springframework.cloud.stream.schema.avro.AvroSchemaServiceManagerImpl; -import org.springframework.cloud.stream.schema.avro.DefaultSubjectNamingStrategy; -import org.springframework.cloud.stream.schema.client.DefaultSchemaRegistryClient; -import org.springframework.cloud.stream.schema.client.SchemaRegistryClient; -import org.springframework.cloud.stream.schema.server.SchemaRegistryServerApplication; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.integration.support.MessageBuilder; -import org.springframework.integration.support.MutableMessageHeaders; -import org.springframework.messaging.Message; -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"); - - Log logger = LogFactory.getLog(getClass()); - - private ConfigurableApplicationContext schemaRegistryServerContext; - - 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(); - AvroSchemaServiceManager manager = new AvroSchemaServiceManagerImpl(); - AvroSchemaRegistryClientMessageConverter converter = new AvroSchemaRegistryClientMessageConverter( - client, new NoOpCacheManager(), manager); - 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.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(); - AvroSchemaServiceManager manager = new AvroSchemaServiceManagerImpl(); - AvroSchemaRegistryClientMessageConverter converter = new AvroSchemaRegistryClientMessageConverter( - client, new NoOpCacheManager(), manager); - - converter.setSubjectNamingStrategy(new DefaultSubjectNamingStrategy()); - converter.setDynamicSchemaGenerationEnabled(false); - converter.afterPropertiesSet(); - - Message specificMessage = converter.toMessage(specificRecord, - new MutableMessageHeaders(Collections.emptyMap()), - MimeTypeUtils.parseMimeType("application/*+avro")); - SchemaReference specificRef = extractSchemaReference(MimeTypeUtils.parseMimeType( - specificMessage.getHeaders().get("contentType").toString())); - - Message genericMessage = converter.toMessage(genericRecord, - new MutableMessageHeaders(Collections.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()); - AvroSchemaServiceManager manager = new AvroSchemaServiceManagerImpl(); - AvroSchemaRegistryClientMessageConverter converter = new AvroSchemaRegistryClientMessageConverter( - client, new NoOpCacheManager(), manager); - converter.setDynamicSchemaGenerationEnabled(false); - converter.afterPropertiesSet(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - DatumWriter 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; - } - -} diff --git a/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/AvroSchemaMessageConverterTests.java b/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/AvroSchemaMessageConverterTests.java deleted file mode 100644 index c63d629a6..000000000 --- a/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/AvroSchemaMessageConverterTests.java +++ /dev/null @@ -1,270 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.schema.avro; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.TimeUnit; - -import org.junit.Test; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.cloud.stream.annotation.StreamMessageConverter; -import org.springframework.cloud.stream.messaging.Sink; -import org.springframework.cloud.stream.messaging.Source; -import org.springframework.cloud.stream.schema.avro.AvroSchemaMessageConverter; -import org.springframework.cloud.stream.schema.avro.AvroSchemaServiceManager; -import org.springframework.cloud.stream.schema.avro.AvroSchemaServiceManagerImpl; -import org.springframework.cloud.stream.schema.client.SchemaRegistryClient; -import org.springframework.cloud.stream.test.binder.MessageCollector; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.core.io.Resource; -import org.springframework.messaging.Message; -import org.springframework.messaging.converter.MessageConverter; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.util.MimeType; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Marius Bogoevici - */ -public class AvroSchemaMessageConverterTests { - - static StubSchemaRegistryClient stubSchemaRegistryClient = new StubSchemaRegistryClient(); - - @Test - public void testSendMessageWithLocation() throws Exception { - 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", - "--spring.cloud.stream.bindings.output.contentType=avro/bytes"); - Source source = sourceContext.getBean(Source.class); - User1 firstOutboundFoo = new User1(); - 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); - - 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", - "--spring.cloud.stream.bindings.output.contentType=avro/bytes"); - Source barSource = barSourceContext.getBean(Source.class); - User2 firstOutboundUser2 = new User2(); - firstOutboundUser2.setFavoriteColor("foo" + UUID.randomUUID().toString()); - 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); - - assertThat(barOutboundMessage).isNotNull(); - - User2 secondUser2OutboundPojo = new User2(); - secondUser2OutboundPojo.setFavoriteColor("foo" + UUID.randomUUID().toString()); - 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); - - 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"); - Sink sink = sinkContext.getBean(Sink.class); - sink.input().send(outboundMessage); - sink.input().send(barOutboundMessage); - sink.input().send(secondBarOutboundMessage); - List 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).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(2)).isNotSameAs(secondUser2OutboundPojo); - 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", - "--spring.jmx.enabled=false", - "--spring.cloud.stream.schemaRegistryClient.enabled=false", - "--spring.cloud.stream.bindings.output.contentType=avro/bytes"); - Source source = sourceContext.getBean(Source.class); - User1 firstOutboundFoo = new User1(); - 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); - - 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"); - Source barSource = barSourceContext.getBean(Source.class); - User2 firstOutboundUser2 = new User2(); - firstOutboundUser2.setFavoriteColor("foo" + UUID.randomUUID().toString()); - 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); - - assertThat(barOutboundMessage).isNotNull(); - - User2 secondUser2OutboundPojo = new User2(); - secondUser2OutboundPojo.setFavoriteColor("foo" + UUID.randomUUID().toString()); - 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); - - 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 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).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(2)).isNotSameAs(secondUser2OutboundPojo); - assertThat(receivedUsers.get(2).getFavoriteColor()) - .isEqualTo(secondUser2OutboundPojo.getFavoriteColor()); - assertThat(receivedUsers.get(2).getName()) - .isEqualTo(secondUser2OutboundPojo.getName()); - - sourceContext.close(); - } - - @EnableBinding(Source.class) - @EnableAutoConfiguration - @ConfigurationProperties - public static class AvroSourceApplication { - - private Resource schemaLocation; - - @Bean - public SchemaRegistryClient schemaRegistryClient() { - return stubSchemaRegistryClient; - } - - public void setSchemaLocation(Resource schemaLocation) { - this.schemaLocation = schemaLocation; - } - - @Bean - @StreamMessageConverter - public MessageConverter userMessageConverter() throws IOException { - AvroSchemaServiceManager manager = new AvroSchemaServiceManagerImpl(); - AvroSchemaMessageConverter avroSchemaMessageConverter = new AvroSchemaMessageConverter( - MimeType.valueOf("avro/bytes"), manager); - if (this.schemaLocation != null) { - avroSchemaMessageConverter.setSchemaLocation(this.schemaLocation); - } - return avroSchemaMessageConverter; - } - - } - - @EnableBinding(Sink.class) - @EnableAutoConfiguration - @ConfigurationProperties - public static class AvroSinkApplication { - - public List receivedUsers = new ArrayList<>(); - - private Resource schemaLocation; - - @StreamListener(Sink.INPUT) - public void listen(User1 user) { - this.receivedUsers.add(user); - } - - public void setSchemaLocation(Resource schemaLocation) { - this.schemaLocation = schemaLocation; - } - - @Bean - @StreamMessageConverter - public MessageConverter userMessageConverter() throws IOException { - AvroSchemaServiceManager manager = new AvroSchemaServiceManagerImpl(); - AvroSchemaMessageConverter avroSchemaMessageConverter = new AvroSchemaMessageConverter( - MimeType.valueOf("avro/bytes"), manager); - if (this.schemaLocation != null) { - avroSchemaMessageConverter.setSchemaLocation(this.schemaLocation); - } - return avroSchemaMessageConverter; - } - - } - -} diff --git a/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/AvroSchemaRegistryClientMessageConverterTests.java b/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/AvroSchemaRegistryClientMessageConverterTests.java deleted file mode 100644 index a0c4b8833..000000000 --- a/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/AvroSchemaRegistryClientMessageConverterTests.java +++ /dev/null @@ -1,274 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.schema.avro; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.TimeUnit; - -import example.avro.Command; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import org.springframework.beans.DirectFieldAccessor; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; -import org.springframework.boot.web.servlet.server.ServletWebServerFactory; -import org.springframework.cache.CacheManager; -import org.springframework.cache.support.NoOpCache; -import org.springframework.cache.support.NoOpCacheManager; -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.cloud.stream.annotation.StreamMessageConverter; -import org.springframework.cloud.stream.messaging.Sink; -import org.springframework.cloud.stream.messaging.Source; -import org.springframework.cloud.stream.schema.avro.AvroSchemaRegistryClientMessageConverter; -import org.springframework.cloud.stream.schema.avro.AvroSchemaServiceManager; -import org.springframework.cloud.stream.schema.avro.AvroSchemaServiceManagerImpl; -import org.springframework.cloud.stream.schema.client.DefaultSchemaRegistryClient; -import org.springframework.cloud.stream.schema.client.EnableSchemaRegistryClient; -import org.springframework.cloud.stream.schema.client.SchemaRegistryClient; -import org.springframework.cloud.stream.schema.server.SchemaRegistryServerApplication; -import org.springframework.cloud.stream.test.binder.MessageCollector; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.test.util.ReflectionTestUtils; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.springframework.cloud.schema.avro.AvroMessageConverterSerializationTests.notification; - -/** - * @author Marius Bogoevici - * @author Oleg Zhurakousky - * @author Sercan Karaoglu - * @author James Gee - */ -public class AvroSchemaRegistryClientMessageConverterTests { - - static SchemaRegistryClient stubSchemaRegistryClient = new StubSchemaRegistryClient(); - - private ConfigurableApplicationContext schemaRegistryServerContext; - - @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 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 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); - } - - @Test - public void testNamedCacheIsRequested() { - CacheManager mockCache = Mockito.mock(CacheManager.class); - when(mockCache.getCache(any())).thenReturn(new NoOpCache("")); - AvroSchemaServiceManager manager = new AvroSchemaServiceManagerImpl(); - AvroSchemaRegistryClientMessageConverter converter = new AvroSchemaRegistryClientMessageConverter(new DefaultSchemaRegistryClient(), mockCache, manager); - ReflectionTestUtils.invokeMethod(converter, "getCache", "TEST_CACHE"); - verify(mockCache).getCache("TEST_CACHE"); - } - - @EnableBinding(Source.class) - @EnableAutoConfiguration - @EnableSchemaRegistryClient - public static class AvroSourceApplication { - - } - - @EnableBinding(Sink.class) - @EnableAutoConfiguration - @EnableSchemaRegistryClient - public static class AvroSinkApplication { - - public List receivedPojos = new ArrayList<>(); - - @StreamListener(Sink.INPUT) - public void listen(User2 fooPojo) { - this.receivedPojos.add(fooPojo); - } - - } - - @EnableBinding(Sink.class) - @EnableAutoConfiguration - @EnableSchemaRegistryClient - public static class CommandSinkApplication { - - public List receivedPojos = new ArrayList<>(); - - @StreamListener(Sink.INPUT) - public void listen(Command fooPojo) { - this.receivedPojos.add(fooPojo); - } - - } - - @Configuration - public static class NoCacheConfiguration { - - @Bean - @StreamMessageConverter - AvroSchemaRegistryClientMessageConverter avroSchemaRegistryClientMessageConverter() { - AvroSchemaServiceManager manager = new AvroSchemaServiceManagerImpl(); - return new AvroSchemaRegistryClientMessageConverter( - new DefaultSchemaRegistryClient(), new NoOpCacheManager(), manager); - } - - @Bean - ServletWebServerFactory servletWebServerFactory() { - return new TomcatServletWebServerFactory(); - } - - } - -} diff --git a/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/AvroSchemaServiceManagerTests.java b/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/AvroSchemaServiceManagerTests.java deleted file mode 100644 index d35c30305..000000000 --- a/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/AvroSchemaServiceManagerTests.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.schema.avro; - - -import java.io.File; -import java.io.IOException; - -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.dataformat.avro.AvroFactory; -import com.fasterxml.jackson.dataformat.avro.AvroMapper; -import com.fasterxml.jackson.dataformat.avro.AvroSchema; -import com.fasterxml.jackson.dataformat.avro.schema.AvroSchemaGenerator; -import org.apache.avro.Schema; -import org.apache.avro.SchemaParseException; -import org.apache.avro.file.DataFileReader; -import org.apache.avro.file.DataFileWriter; -import org.apache.avro.io.DatumReader; -import org.apache.avro.io.DatumWriter; -import org.assertj.core.util.Lists; -import org.junit.Test; - -import org.springframework.cloud.schema.avro.domain.FoodOrder; -import org.springframework.cloud.stream.schema.avro.AvroSchemaMessageConverter; -import org.springframework.cloud.stream.schema.avro.AvroSchemaServiceManager; -import org.springframework.cloud.stream.schema.avro.AvroSchemaServiceManagerImpl; -import org.springframework.core.io.ByteArrayResource; -import org.springframework.util.MimeType; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.fail; -/** - * @author Ish Mahajan - */ -public class AvroSchemaServiceManagerTests { - - @SuppressWarnings({ "rawtypes", "unchecked", "resource" }) - @Test(expected = DataFileWriter.AppendWriteException.class) - public void testWithDefaultImplementation() throws IOException { - AvroSchemaServiceManager defaultServiceManager = new AvroSchemaServiceManagerImpl(); - Schema schema = defaultServiceManager.getSchema(FoodOrder.class); - FoodOrder foodOrder = new FoodOrder(); - foodOrder.setRestaurant("Spring Kitchen"); - foodOrder.setOrderDescription("avro makhani"); - foodOrder.setCustomerAddress("world wide web"); - File file = new File("foodorder.avro"); - - DatumWriter datumWriter = defaultServiceManager.getDatumWriter(foodOrder.getClass(), schema); - DataFileWriter dataFileWriter = new DataFileWriter(datumWriter); - dataFileWriter.create(schema, file); - dataFileWriter.append(foodOrder); - - FoodOrder foodOrder2 = new FoodOrder(); - dataFileWriter.append(foodOrder2); - dataFileWriter.close(); - - DatumReader userDatumReader = defaultServiceManager.getDatumReader(foodOrder.getClass(), schema, schema); - DataFileReader dataFileReader = new DataFileReader(file, userDatumReader); - FoodOrder foodOrderDeserialized = null; - while (dataFileReader.hasNext()) { - // Reuse user object by passing it to next(). This saves us from - // allocating and garbage collecting many objects for files with - // many items. - foodOrderDeserialized = dataFileReader.next(foodOrderDeserialized); - System.out.println("De-serialised Successfully : " + foodOrderDeserialized); - } - } - - @Test - public void testWithCustomImplementation() throws IOException { - AvroSchemaServiceManager manager = new AvroSchemaServiceManager() { - @Override - public Schema getSchema(Class clazz) { - ObjectMapper mapper = new ObjectMapper(new AvroFactory()); - AvroSchemaGenerator gen = new AvroSchemaGenerator(); - try { - mapper.acceptJsonFormatVisitor(FoodOrder.class, gen); - } - catch (JsonMappingException e) { - fail("Error while setting acceptJsonFormatVisitor {}", e); - } - AvroSchema schemaWrapper = gen.getGeneratedSchema(); - return schemaWrapper.getAvroSchema(); - } - - @Override - public DatumWriter getDatumWriter(Class type, Schema schema) { - return new AvroSchemaServiceManagerImpl().getDatumWriter(type, schema); - } - - @Override - public DatumReader getDatumReader(Class type, Schema schema, Schema writerSchema) { - return new AvroSchemaServiceManagerImpl().getDatumReader(type, schema, schema); - } - - @Override - public Object readData(Class targetClass, byte[] payload, Schema readerSchema, - Schema writerSchema) throws IOException { - ObjectMapper mapper = new ObjectMapper(new AvroFactory()); - AvroSchemaGenerator gen = new AvroSchemaGenerator(); - try { - mapper.acceptJsonFormatVisitor(targetClass, gen); - } - catch (JsonMappingException e) { - fail("Error while setting acceptJsonFormatVisitor {}", e); - } - return mapper.readerFor(targetClass) - .with(new AvroSchema(readerSchema)) - .readValue(payload); - } - }; - - FoodOrder foodOrder1 = new FoodOrder(); - foodOrder1.setRestaurant("Spring Kitchen"); - foodOrder1.setOrderDescription("avro makhani"); - foodOrder1.setCustomerAddress("world wide web"); - FoodOrder foodOrder2 = new FoodOrder(); - foodOrder2.setRestaurant("Spring Kitchen"); - - Schema schema = manager.getSchema(FoodOrder.class); - AvroMapper mapper = new AvroMapper(); - byte[] payload1 = mapper.writer(new AvroSchema(schema)).writeValueAsBytes(foodOrder1); - byte[] payload2 = mapper.writer(new AvroSchema(schema)).writeValueAsBytes(foodOrder2); - foodOrder1 = (FoodOrder) manager.readData(foodOrder1.getClass(), payload1, schema, schema); - foodOrder2 = (FoodOrder) manager.readData(foodOrder1.getClass(), payload2, schema, schema); - assertThat(foodOrder2.getOrderDescription()).isNull(); - assertThat(foodOrder2.getCustomerAddress()).isNull(); - } - - @Test - public void testAvroSchemaMessageConverter() { - AvroSchemaMessageConverter converter = new AvroSchemaMessageConverter(); - MimeType mimeType = new MimeType("application", "avro"); - assertThat(mimeType).isEqualTo(converter.getSupportedMimeTypes().get(0)); - - AvroSchemaMessageConverter converter2 = new AvroSchemaMessageConverter(mimeType); - assertThat(mimeType).isEqualTo(converter2.getSupportedMimeTypes().get(0)); - - AvroSchemaMessageConverter converter3 = - new AvroSchemaMessageConverter(Lists.newArrayList(mimeType)); - assertThat(mimeType).isEqualTo(converter3.getSupportedMimeTypes().get(0)); - - AvroSchemaServiceManager manager = new AvroSchemaServiceManagerImpl(); - AvroSchemaMessageConverter converter4 = new AvroSchemaMessageConverter(manager); - assertThat(mimeType).isEqualTo(converter4.getSupportedMimeTypes().get(0)); - - AvroSchemaMessageConverter converter5 = - new AvroSchemaMessageConverter(Lists.newArrayList(mimeType), manager); - Schema schema = manager.getSchema(FoodOrder.class); - converter5.setSchema(schema); - assertThat(mimeType).isEqualTo(converter5.getSupportedMimeTypes().get(0)); - assertThat(schema).isEqualTo(converter5.getSchema()); - } - - @Test(expected = SchemaParseException.class) - public void testAvroSchemaMessageConverterException() { - MimeType mimeType = new MimeType("application", "avro"); - AvroSchemaServiceManager manager = new AvroSchemaServiceManagerImpl(); - AvroSchemaMessageConverter converter = - new AvroSchemaMessageConverter(Lists.newArrayList(mimeType), manager); - converter.setSchemaLocation(new ByteArrayResource(new byte[2]) { - }); - } -} diff --git a/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/AvroStubSchemaRegistryClientMessageConverterTests.java b/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/AvroStubSchemaRegistryClientMessageConverterTests.java deleted file mode 100644 index d260a0450..000000000 --- a/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/AvroStubSchemaRegistryClientMessageConverterTests.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.schema.avro; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.TimeUnit; - -import org.junit.Test; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.cloud.stream.messaging.Sink; -import org.springframework.cloud.stream.messaging.Source; -import org.springframework.cloud.stream.schema.client.SchemaRegistryClient; -import org.springframework.cloud.stream.test.binder.MessageCollector; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Marius Bogoevici - */ -public class AvroStubSchemaRegistryClientMessageConverterTests { - - static SchemaRegistryClient stubSchemaRegistryClient = new StubSchemaRegistryClient(); - - @Test - public void testSendMessage() 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.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 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()); - - sourceContext.close(); - } - - @EnableBinding(Source.class) - @EnableAutoConfiguration - public static class AvroSourceApplication { - - @Bean - public SchemaRegistryClient schemaRegistryClient() { - return stubSchemaRegistryClient; - } - - } - - @EnableBinding(Sink.class) - @EnableAutoConfiguration - public static class AvroSinkApplication { - - public List receivedPojos = new ArrayList<>(); - - @StreamListener(Sink.INPUT) - public void listen(User2 fooPojo) { - this.receivedPojos.add(fooPojo); - } - - @Bean - public SchemaRegistryClient schemaRegistryClient() { - return stubSchemaRegistryClient; - } - - } - -} diff --git a/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/StubSchemaRegistryClient.java b/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/StubSchemaRegistryClient.java deleted file mode 100644 index 486444f78..000000000 --- a/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/StubSchemaRegistryClient.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.schema.avro; - -import java.util.HashMap; -import java.util.Map; -import java.util.TreeMap; -import java.util.concurrent.atomic.AtomicInteger; - -import org.springframework.cloud.stream.schema.SchemaNotFoundException; -import org.springframework.cloud.stream.schema.SchemaReference; -import org.springframework.cloud.stream.schema.SchemaRegistrationResponse; -import org.springframework.cloud.stream.schema.avro.AvroSchemaRegistryClientMessageConverter; -import org.springframework.cloud.stream.schema.client.SchemaRegistryClient; - -/** - * @author Marius Bogoevici - */ -public class StubSchemaRegistryClient implements SchemaRegistryClient { - - private final AtomicInteger index = new AtomicInteger(0); - - private final Map schemasById = new HashMap<>(); - - private final Map> storedSchemas = new HashMap<>(); - - @Override - public SchemaRegistrationResponse register(String subject, String format, - String schema) { - if (!this.storedSchemas.containsKey(subject)) { - this.storedSchemas.put(subject, new TreeMap()); - } - Map schemaVersions = this.storedSchemas.get(subject); - for (Map.Entry integerSchemaEntry : schemaVersions - .entrySet()) { - - if (integerSchemaEntry.getValue().getSchema().equals(schema)) { - SchemaRegistrationResponse schemaRegistrationResponse = new SchemaRegistrationResponse(); - schemaRegistrationResponse.setId(integerSchemaEntry.getValue().getId()); - schemaRegistrationResponse.setSchemaReference( - new SchemaReference(subject, integerSchemaEntry.getKey(), - AvroSchemaRegistryClientMessageConverter.AVRO_FORMAT)); - return schemaRegistrationResponse; - } - } - int nextVersion = schemaVersions.size() + 1; - int id = this.index.incrementAndGet(); - 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)); - this.schemasById.put(id, schema); - return schemaRegistrationResponse; - } - - @Override - public String fetch(SchemaReference schemaReference) { - 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())) { - throw new SchemaNotFoundException("Not found: " + schemaReference); - } - return this.storedSchemas.get(schemaReference.getSubject()) - .get(schemaReference.getVersion()).getSchema(); - } - - @Override - public String fetch(int id) { - return this.schemasById.get(id); - } - - static class SchemaWithId { - - int id; - - String schema; - - SchemaWithId(int id, String schema) { - this.id = id; - this.schema = schema; - } - - public int getId() { - return this.id; - } - - public String getSchema() { - return this.schema; - } - - } - -} diff --git a/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/SubjectNamingStrategyTest.java b/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/SubjectNamingStrategyTest.java deleted file mode 100644 index 2b6fb3410..000000000 --- a/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/SubjectNamingStrategyTest.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.schema.avro; - -import java.util.UUID; -import java.util.concurrent.TimeUnit; - -import org.junit.Test; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.messaging.Source; -import org.springframework.cloud.stream.schema.client.SchemaRegistryClient; -import org.springframework.cloud.stream.test.binder.MessageCollector; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.util.MimeType; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author David Kalosi - * @author José A. Íñigo - */ -public class SubjectNamingStrategyTest { - - private static StubSchemaRegistryClient stubSchemaRegistryClient = new StubSchemaRegistryClient(); - - @Test - public void testQualifiedSubjectNamingStrategy() 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.stream.schema.avro.QualifiedSubjectNamingStrategy", - "--spring.cloud.stream.schema.avro.dynamicSchemaGenerationEnabled=true"); - - Source source = sourceContext.getBean(Source.class); - User1 user1 = new User1(); - user1.setFavoriteColor("foo" + UUID.randomUUID().toString()); - 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); - - assertThat(message.getHeaders().get("contentType")).isEqualTo(MimeType.valueOf( - "application/vnd.org.springframework.cloud.schema.avro.User1.v1+avro")); - } - - @EnableBinding(Source.class) - @EnableAutoConfiguration - public static class AvroSourceApplication { - - @Bean - public SchemaRegistryClient schemaRegistryClient() { - return stubSchemaRegistryClient; - } - - } - -} diff --git a/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/User1.java b/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/User1.java deleted file mode 100644 index aa11902b0..000000000 --- a/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/User1.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.schema.avro; - -import org.apache.avro.reflect.Nullable; - -/** - * @author Marius Bogoevici - */ -public class User1 { - - @Nullable - private String name; - - private int favoriteNumber; - - @Nullable - private String favoriteColor; - - public String getName() { - return this.name; - } - - public void setName(String name) { - this.name = name; - } - - public int getFavoriteNumber() { - return this.favoriteNumber; - } - - public void setFavoriteNumber(int favoriteNumber) { - this.favoriteNumber = favoriteNumber; - } - - public String getFavoriteColor() { - return this.favoriteColor; - } - - public void setFavoriteColor(String favoriteColor) { - this.favoriteColor = favoriteColor; - } - -} diff --git a/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/User2.java b/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/User2.java deleted file mode 100644 index a3cb94c1a..000000000 --- a/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/User2.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.schema.avro; - -import org.apache.avro.reflect.AvroDefault; -import org.apache.avro.reflect.Nullable; - -/** - * @author Marius Bogoevici - */ -public class User2 { - - @Nullable - private String name; - - private int favoriteNumber; - - @Nullable - private String favoriteColor; - - @AvroDefault("\"NYC\"") - private String favoritePlace = "Boston"; - - public String getName() { - return this.name; - } - - public void setName(String name) { - this.name = name; - } - - public int getFavoriteNumber() { - return this.favoriteNumber; - } - - public void setFavoriteNumber(int favoriteNumber) { - this.favoriteNumber = favoriteNumber; - } - - public String getFavoriteColor() { - return this.favoriteColor; - } - - public void setFavoriteColor(String favoriteColor) { - this.favoriteColor = favoriteColor; - } - - public String getFavoritePlace() { - return this.favoritePlace; - } - - public void setFavoritePlace(String favoritePlace) { - this.favoritePlace = favoritePlace; - } - -} diff --git a/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/client/ConfluentSchemaRegistryClientTests.java b/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/client/ConfluentSchemaRegistryClientTests.java deleted file mode 100644 index 23d8cacc9..000000000 --- a/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/client/ConfluentSchemaRegistryClientTests.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.schema.avro.client; - -import org.junit.Before; -import org.junit.Test; - -import org.springframework.cloud.stream.schema.SchemaNotFoundException; -import org.springframework.cloud.stream.schema.SchemaReference; -import org.springframework.cloud.stream.schema.SchemaRegistrationResponse; -import org.springframework.cloud.stream.schema.client.ConfluentSchemaRegistryClient; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -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; -import static org.springframework.test.web.client.response.MockRestResponseCreators.withBadRequest; -import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus; -import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; - -/** - * @author Vinicius Carvalho - * @author TengZhou Dong - */ -public class ConfluentSchemaRegistryClientTests { - - private RestTemplate restTemplate; - - private MockRestServiceServer mockRestServiceServer; - - @Before - public void setup() { - this.restTemplate = new RestTemplate(); - this.mockRestServiceServer = MockRestServiceServer - .createServer(this.restTemplate); - } - - @Test - public void registerSchema() throws Exception { - this.mockRestServiceServer - .expect(requestTo("http://localhost:8081")) - .andExpect(method(HttpMethod.POST)) - .andExpect(header("Content-Type", "application/json")) - .andExpect(header("Accept", "application/vnd.schemaregistry.v1+json")) - .andRespond(withSuccess("{\"id\":101,\"version\":1}", MediaType.APPLICATION_JSON)); - - 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")) - .andExpect(method(HttpMethod.POST)) - .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", "<>"); - } - - @Test - public void registerIncompatibleSchema() { - this.mockRestServiceServer - .expect(requestTo("http://localhost:8081")) - .andExpect(method(HttpMethod.POST)) - .andExpect(header("Content-Type", "application/json")) - .andExpect(header("Accept", "application/vnd.schemaregistry.v1+json")) - .andRespond(withStatus(HttpStatus.CONFLICT)); - ConfluentSchemaRegistryClient client = new ConfluentSchemaRegistryClient( - this.restTemplate); - Exception expected = null; - try { - SchemaRegistrationResponse response = client.register("user", "avro", "{}"); - } - catch (Exception e) { - expected = e; - } - 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/user/avro/v1")) - .andExpect(method(HttpMethod.GET)) - .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"); - String schema = client.fetch(reference); - assertThat(schema).isEqualTo(""); - this.mockRestServiceServer.verify(); - } - - @Test(expected = SchemaNotFoundException.class) - public void schemaNotFound() { - this.mockRestServiceServer - .expect(requestTo("http://localhost:8081/user/avro/v1")) - .andExpect(method(HttpMethod.GET)) - .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"); - String schema = client.fetch(reference); - } - - @Test - public void responseErrorFetch() { - this.mockRestServiceServer - .expect(requestTo("http://localhost:8081")) - .andExpect(method(HttpMethod.POST)) - .andExpect(header("Content-Type", "application/json")) - .andExpect(header("Accept", "application/vnd.schemaregistry.v1+json")) - .andRespond(withBadRequest()); - - ConfluentSchemaRegistryClient client = new ConfluentSchemaRegistryClient( - this.restTemplate); - Exception expected = null; - try { - SchemaRegistrationResponse response = client.register("user", "avro", "{}"); - } - catch (Exception e) { - expected = e; - } - assertThat(expected != null).isTrue(); - assertThat(expected.getCause() instanceof HttpStatusCodeException).isTrue(); - this.mockRestServiceServer.verify(); - } -} diff --git a/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/domain/FoodOrder.java b/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/domain/FoodOrder.java deleted file mode 100644 index be4eb94b7..000000000 --- a/spring-cloud-stream-schema/src/test/java/org/springframework/cloud/schema/avro/domain/FoodOrder.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.schema.avro.domain; - -/** - * @author Ish Mahajan - */ -public class FoodOrder { - private String restaurant; - private String customerAddress; - private String orderDescription; - public String getRestaurant() { - return restaurant; - } - public void setRestaurant(String restaurant) { - this.restaurant = restaurant; - } - public String getCustomerAddress() { - return customerAddress; - } - public void setCustomerAddress(String customerAddress) { - this.customerAddress = customerAddress; - } - public String getOrderDescription() { - return orderDescription; - } - public void setOrderDescription(String orderDescription) { - this.orderDescription = orderDescription; - } -} diff --git a/spring-cloud-stream-schema/src/test/resources/schemas/Command.avsc b/spring-cloud-stream-schema/src/test/resources/schemas/Command.avsc deleted file mode 100644 index 3cfc1d9ce..000000000 --- a/spring-cloud-stream-schema/src/test/resources/schemas/Command.avsc +++ /dev/null @@ -1,19 +0,0 @@ -{ - "namespace":"example.avro", - "name":"Command", - "type":"record", - "fields":[ - { - "name":"type", - "type":"string" - }, - { - "name":"correlationId", - "type":"string" - }, - { - "name":"payload", - "type":["Sms", "Email", "PushNotification"] - } - ] -} diff --git a/spring-cloud-stream-schema/src/test/resources/schemas/imports/Email.avsc b/spring-cloud-stream-schema/src/test/resources/schemas/imports/Email.avsc deleted file mode 100644 index 2b24fc236..000000000 --- a/spring-cloud-stream-schema/src/test/resources/schemas/imports/Email.avsc +++ /dev/null @@ -1,19 +0,0 @@ -{ - "namespace":"example.avro", - "name": "Email", - "type": "record", - "fields":[ - { - "name":"addressTo", - "type":"string" - }, - { - "name":"title", - "type":"string" - }, - { - "name":"text", - "type":"string" - } - ] -} diff --git a/spring-cloud-stream-schema/src/test/resources/schemas/imports/PushNotification.avsc b/spring-cloud-stream-schema/src/test/resources/schemas/imports/PushNotification.avsc deleted file mode 100644 index afded1f20..000000000 --- a/spring-cloud-stream-schema/src/test/resources/schemas/imports/PushNotification.avsc +++ /dev/null @@ -1,15 +0,0 @@ -{ - "namespace":"example.avro", - "name": "PushNotification", - "type": "record", - "fields":[ - { - "name":"arn", - "type":"string" - }, - { - "name":"text", - "type":"string" - } - ] -} diff --git a/spring-cloud-stream-schema/src/test/resources/schemas/imports/Sms.avsc b/spring-cloud-stream-schema/src/test/resources/schemas/imports/Sms.avsc deleted file mode 100644 index 90b7ced8c..000000000 --- a/spring-cloud-stream-schema/src/test/resources/schemas/imports/Sms.avsc +++ /dev/null @@ -1,14 +0,0 @@ -{ - "namespace":"example.avro", - "name": "Sms", - "type": "record", - "fields":[ - { - "name":"phoneNumber", - "type":"string" - },{ - "name":"text", - "type":"string" - } - ] -} diff --git a/spring-cloud-stream-schema/src/test/resources/schemas/status.avsc b/spring-cloud-stream-schema/src/test/resources/schemas/status.avsc deleted file mode 100644 index 972a80c08..000000000 --- a/spring-cloud-stream-schema/src/test/resources/schemas/status.avsc +++ /dev/null @@ -1,10 +0,0 @@ -{ - "namespace":"org.springframework.cloud.stream.samples", - "name": "Status", - "type" : "record", - "fields": [ - {"name": "id", "type": "string"}, - {"name": "text", "type": "string"}, - {"name": "timestamp", "type": "long"} - ] -} diff --git a/spring-cloud-stream-schema/src/test/resources/schemas/user.avsc b/spring-cloud-stream-schema/src/test/resources/schemas/user.avsc deleted file mode 100644 index 662029a22..000000000 --- a/spring-cloud-stream-schema/src/test/resources/schemas/user.avsc +++ /dev/null @@ -1,10 +0,0 @@ -{"namespace": "example.avro", - "type": "record", - "name": "User", - "fields": [ - {"name": "name", "type": "string"}, - {"name": "favoriteNumber", "type": ["int", "null"]}, - {"name": "favoriteColor", "type": ["string", "null"]} - - ] -} diff --git a/spring-cloud-stream-schema/src/test/resources/schemas/users_v1.schema b/spring-cloud-stream-schema/src/test/resources/schemas/users_v1.schema deleted file mode 100644 index 662029a22..000000000 --- a/spring-cloud-stream-schema/src/test/resources/schemas/users_v1.schema +++ /dev/null @@ -1,10 +0,0 @@ -{"namespace": "example.avro", - "type": "record", - "name": "User", - "fields": [ - {"name": "name", "type": "string"}, - {"name": "favoriteNumber", "type": ["int", "null"]}, - {"name": "favoriteColor", "type": ["string", "null"]} - - ] -} diff --git a/spring-cloud-stream-schema/src/test/resources/schemas/users_v2.schema b/spring-cloud-stream-schema/src/test/resources/schemas/users_v2.schema deleted file mode 100644 index 1cb8c4130..000000000 --- a/spring-cloud-stream-schema/src/test/resources/schemas/users_v2.schema +++ /dev/null @@ -1,10 +0,0 @@ -{"namespace": "example.avro", - "type": "record", - "name": "User", - "fields": [ - {"name": "name", "type": "string"}, - {"name": "favoriteNumber", "type": ["int", "null"]}, - {"name": "favoriteColor", "type": ["string", "null"]}, - {"name": "favoritePlace", "type": ["string","null"], "default" : "NYC"} - ] -}