[ https://issues.apache.org/jira/browse/SCB-926?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16629669#comment-16629669 ]
ASF GitHub Bot commented on SCB-926: ------------------------------------ yhs0092 closed pull request #926: [SCB-926] 3rd party invoke URL: https://github.com/apache/incubator-servicecomb-java-chassis/pull/926 This is a PR merged from a forked repository. As GitHub hides the original diff on merge, it is displayed below for the sake of provenance: As this is a foreign pull request (from a fork), the diff is supplied below (as it won't show otherwise due to GitHub magic): diff --git a/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java b/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java index 70c66f89b..5ed1759c1 100644 --- a/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java +++ b/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java @@ -19,6 +19,7 @@ import org.apache.servicecomb.core.definition.MicroserviceMeta; import org.apache.servicecomb.core.definition.loader.SchemaListenerManager; +import org.apache.servicecomb.core.definition.schema.StaticSchemaFactory; import org.apache.servicecomb.core.provider.consumer.ConsumerProviderManager; import org.apache.servicecomb.core.provider.producer.ProducerProviderManager; import org.apache.servicecomb.core.transport.TransportManager; @@ -74,6 +75,7 @@ public void onApplicationEvent(ApplicationEvent event) { SCBEngine.getInstance().setTransportManager(applicationContext.getBean(TransportManager.class)); SCBEngine.getInstance().setSchemaListenerManager(applicationContext.getBean(SchemaListenerManager.class)); SCBEngine.getInstance().setBootListenerList(applicationContext.getBeansOfType(BootListener.class).values()); + SCBEngine.getInstance().setStaticSchemaFactory(applicationContext.getBean(StaticSchemaFactory.class)); } SCBEngine.getInstance().init(); diff --git a/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java b/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java index 4be7e7c7b..f364d1c6f 100644 --- a/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java +++ b/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java @@ -31,6 +31,7 @@ import org.apache.servicecomb.core.BootListener.EventType; import org.apache.servicecomb.core.definition.MicroserviceMeta; import org.apache.servicecomb.core.definition.loader.SchemaListenerManager; +import org.apache.servicecomb.core.definition.schema.StaticSchemaFactory; import org.apache.servicecomb.core.endpoint.AbstractEndpointsCache; import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.InvocationStartEvent; @@ -82,6 +83,8 @@ private EventBus eventBus = EventManager.getEventBus(); + private StaticSchemaFactory staticSchemaFactory; + private static final SCBEngine INSTANCE = new SCBEngine(); public void setStatus(SCBStatus status) { @@ -374,4 +377,12 @@ public void waitStatusUp(long msWait) throws InterruptedException, TimeoutExcept } } } + + public StaticSchemaFactory getStaticSchemaFactory() { + return staticSchemaFactory; + } + + public void setStaticSchemaFactory(StaticSchemaFactory staticSchemaFactory) { + this.staticSchemaFactory = staticSchemaFactory; + } } diff --git a/core/src/main/java/org/apache/servicecomb/core/definition/MicroserviceVersionMeta.java b/core/src/main/java/org/apache/servicecomb/core/definition/MicroserviceVersionMeta.java index a5eff5853..e4e27632b 100644 --- a/core/src/main/java/org/apache/servicecomb/core/definition/MicroserviceVersionMeta.java +++ b/core/src/main/java/org/apache/servicecomb/core/definition/MicroserviceVersionMeta.java @@ -20,10 +20,15 @@ import org.apache.servicecomb.core.CseContext; import org.apache.servicecomb.core.definition.classloader.MicroserviceClassLoaderFactory; import org.apache.servicecomb.serviceregistry.api.Const; +import org.apache.servicecomb.serviceregistry.api.registry.Microservice; import org.apache.servicecomb.serviceregistry.consumer.MicroserviceVersion; public class MicroserviceVersionMeta extends MicroserviceVersion { - private MicroserviceMeta microserviceMeta; + MicroserviceMeta microserviceMeta; + + MicroserviceVersionMeta(Microservice microservice) { + super(microservice); + } public MicroserviceVersionMeta(String microserviceName, String microserviceId, MicroserviceClassLoaderFactory classLoaderFactory) { diff --git a/core/src/main/java/org/apache/servicecomb/core/definition/StaticMicroserviceVersionMeta.java b/core/src/main/java/org/apache/servicecomb/core/definition/StaticMicroserviceVersionMeta.java new file mode 100644 index 000000000..0fd866bc0 --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/definition/StaticMicroserviceVersionMeta.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.core.definition; + +import org.apache.servicecomb.core.CseContext; +import org.apache.servicecomb.core.SCBEngine; +import org.apache.servicecomb.core.definition.classloader.MicroserviceClassLoaderFactory; +import org.apache.servicecomb.serviceregistry.api.Const; +import org.apache.servicecomb.serviceregistry.api.registry.StaticMicroservice; + +public class StaticMicroserviceVersionMeta extends MicroserviceVersionMeta { + + public StaticMicroserviceVersionMeta(StaticMicroservice microservice, + MicroserviceClassLoaderFactory classLoaderFactory) { + super(microservice); + + this.microserviceMeta = new MicroserviceMeta(microservice.getServiceName()); + this.microserviceMeta.setClassLoader( + classLoaderFactory.create(microservice.getAppId(), microservice.getServiceName(), microservice.getVersion())); + if (Const.REGISTRY_APP_ID.equals(microservice.getAppId()) + && Const.REGISTRY_SERVICE_NAME.equals(microservice.getServiceName())) { + // do not load service center schemas + return; + } + + SCBEngine.getInstance().getStaticSchemaFactory().loadSchema(microserviceMeta, microservice); + CseContext.getInstance().getSchemaListenerManager().notifySchemaListener(microserviceMeta); + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/definition/StaticMicroserviceVersionMetaFactory.java b/core/src/main/java/org/apache/servicecomb/core/definition/StaticMicroserviceVersionMetaFactory.java new file mode 100644 index 000000000..e10dc9b2e --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/definition/StaticMicroserviceVersionMetaFactory.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.core.definition; + +import org.apache.servicecomb.core.definition.classloader.MicroserviceClassLoaderFactory; +import org.apache.servicecomb.core.definition.classloader.PrivateMicroserviceClassLoaderFactory; +import org.apache.servicecomb.serviceregistry.api.registry.StaticMicroservice; +import org.apache.servicecomb.serviceregistry.consumer.MicroserviceVersion; +import org.apache.servicecomb.serviceregistry.consumer.StaticMicroserviceVersionFactory; + +public class StaticMicroserviceVersionMetaFactory implements StaticMicroserviceVersionFactory { + private final MicroserviceClassLoaderFactory classLoaderFactory = PrivateMicroserviceClassLoaderFactory.INSTANCE; + + @Override + public MicroserviceVersion create(StaticMicroservice microservice) { + return new StaticMicroserviceVersionMeta(microservice, classLoaderFactory); + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/definition/schema/ProducerSchemaFactory.java b/core/src/main/java/org/apache/servicecomb/core/definition/schema/ProducerSchemaFactory.java index 5b1d0c885..59888d4c6 100644 --- a/core/src/main/java/org/apache/servicecomb/core/definition/schema/ProducerSchemaFactory.java +++ b/core/src/main/java/org/apache/servicecomb/core/definition/schema/ProducerSchemaFactory.java @@ -36,6 +36,7 @@ import org.apache.servicecomb.core.executor.ExecutorManager; import org.apache.servicecomb.foundation.common.utils.BeanUtils; import org.apache.servicecomb.serviceregistry.RegistryUtils; +import org.apache.servicecomb.swagger.SwaggerUtils; import org.apache.servicecomb.swagger.engine.SwaggerEnvironment; import org.apache.servicecomb.swagger.engine.SwaggerProducer; import org.apache.servicecomb.swagger.engine.SwaggerProducerOperation; @@ -45,13 +46,10 @@ import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectWriter; import com.netflix.config.DynamicPropertyFactory; import io.swagger.models.Operation; import io.swagger.models.Swagger; -import io.swagger.util.Yaml; @Component public class ProducerSchemaFactory extends AbstractSchemaFactory<ProducerSchemaContext> { @@ -60,22 +58,12 @@ @Inject private SwaggerEnvironment swaggerEnv; - private ObjectWriter writer = Yaml.pretty(); - - private String getSwaggerContent(Swagger swagger) { - try { - return writer.writeValueAsString(swagger); - } catch (JsonProcessingException e) { - throw new Error(e); - } - } - public void setSwaggerEnv(SwaggerEnvironment swaggerEnv) { this.swaggerEnv = swaggerEnv; } // 只会在启动流程中调用 - public SchemaMeta getOrCreateProducerSchema( String schemaId, + public SchemaMeta getOrCreateProducerSchema(String schemaId, Class<?> producerClass, Object producerInstance) { MicroserviceMeta microserviceMeta = SCBEngine.getInstance().getProducerMicroserviceMeta(); @@ -126,7 +114,7 @@ protected SchemaMeta createSchema(ProducerSchemaContext context) { if (swagger == null) { SwaggerGenerator generator = generateSwagger(context); swagger = generator.getSwagger(); - String swaggerContent = getSwaggerContent(swagger); + String swaggerContent = SwaggerUtils.swaggerToString(swagger); LOGGER.info("generate swagger for {}/{}/{}, swagger: {}", context.getMicroserviceMeta().getAppId(), context.getMicroserviceName(), diff --git a/core/src/main/java/org/apache/servicecomb/core/definition/schema/StaticSchemaFactory.java b/core/src/main/java/org/apache/servicecomb/core/definition/schema/StaticSchemaFactory.java new file mode 100644 index 000000000..0606e46d8 --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/definition/schema/StaticSchemaFactory.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.core.definition.schema; + +import org.apache.servicecomb.core.definition.MicroserviceMeta; +import org.apache.servicecomb.core.definition.SchemaMeta; +import org.apache.servicecomb.serviceregistry.api.registry.StaticMicroservice; +import org.apache.servicecomb.swagger.SwaggerUtils; +import org.apache.servicecomb.swagger.generator.core.SwaggerGenerator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import io.swagger.models.Swagger; + +@Component +public class StaticSchemaFactory extends AbstractSchemaFactory<SchemaContext> { + + private static final Logger LOGGER = LoggerFactory.getLogger(StaticSchemaFactory.class); + + public void loadSchema(MicroserviceMeta microserviceMeta, StaticMicroservice microservice) { + SchemaContext context = new SchemaContext(); + context.setMicroserviceMeta(microserviceMeta); + // use microservice name as schemaId, since currently we only allow one schema per 3rd party microservice + context.setSchemaId(microserviceMeta.getShortName()); + context.setProviderClass(microservice.getSchemaIntfCls()); + + getOrCreateSchema(context); + } + + @Override + protected SchemaMeta createSchema(SchemaContext context) { + // generate schema according to producer interface + Swagger swagger; + SwaggerGenerator generator = generateSwagger(context); + swagger = generator.getSwagger(); + String swaggerContent = SwaggerUtils.swaggerToString(swagger); + LOGGER.info("generate swagger for {}/{}/{}, swagger: {}", + context.getMicroserviceMeta().getAppId(), + context.getMicroserviceName(), + context.getSchemaId(), + swaggerContent); + + // register swagger schema + return schemaLoader.registerSchema(context.getMicroserviceMeta(), context.getSchemaId(), swagger); + } +} diff --git a/core/src/test/java/org/apache/servicecomb/core/definition/StaticMicroserviceVersionMetaTest.java b/core/src/test/java/org/apache/servicecomb/core/definition/StaticMicroserviceVersionMetaTest.java new file mode 100644 index 000000000..a06f08701 --- /dev/null +++ b/core/src/test/java/org/apache/servicecomb/core/definition/StaticMicroserviceVersionMetaTest.java @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.core.definition; + +import javax.xml.ws.Holder; + +import org.apache.servicecomb.core.CseContext; +import org.apache.servicecomb.core.SCBEngine; +import org.apache.servicecomb.core.definition.classloader.MicroserviceClassLoaderFactory; +import org.apache.servicecomb.core.definition.loader.SchemaListenerManager; +import org.apache.servicecomb.core.definition.schema.StaticSchemaFactory; +import org.apache.servicecomb.serviceregistry.RegistryUtils; +import org.apache.servicecomb.serviceregistry.api.registry.StaticMicroservice; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.Mockito; + +import mockit.Mock; +import mockit.MockUp; + +public class StaticMicroserviceVersionMetaTest { + + private static final String APP_ID_FROM_REGISTRY_UTIL = "appIdFromRegistryUtil"; + + @BeforeClass + public static void beforeClass() { + new MockUp<RegistryUtils>() { + @Mock + String getAppId() { + return APP_ID_FROM_REGISTRY_UTIL; + } + }; + } + + @Test + public void testConstruct() { + StaticMicroservice staticMicroservice = new StaticMicroservice(); + String appId = "testAppId"; + String serviceName = "testServiceName"; + String version = "1.2.1"; + staticMicroservice.setAppId(appId); + staticMicroservice.setServiceName(serviceName); + staticMicroservice.setVersion(version); + + MicroserviceClassLoaderFactory classLoaderFactory = Mockito.mock(MicroserviceClassLoaderFactory.class); + ClassLoader classLoader = Mockito.mock(ClassLoader.class); + Mockito.when(classLoaderFactory.create(appId, serviceName, version)).thenReturn(classLoader); + + Holder<Boolean> schemaLoaded = new Holder<>(false); + SCBEngine.getInstance().setStaticSchemaFactory(new MockUp<StaticSchemaFactory>() { + @Mock + void loadSchema(MicroserviceMeta microserviceMeta, StaticMicroservice microservice) { + Assert.assertSame(classLoader, microserviceMeta.getClassLoader()); + Assert.assertSame(APP_ID_FROM_REGISTRY_UTIL, microserviceMeta.getAppId()); + Assert.assertSame(serviceName, microserviceMeta.getName()); + Assert.assertSame(serviceName, microserviceMeta.getShortName()); + Assert.assertSame(staticMicroservice, microservice); + schemaLoaded.value = true; + } + }.getMockInstance()); + Holder<Boolean> listenerNotified = new Holder<>(false); + CseContext.getInstance().setSchemaListenerManager(new MockUp<SchemaListenerManager>() { + @Mock + void notifySchemaListener(MicroserviceMeta... microserviceMetas) { + Assert.assertEquals(1, microserviceMetas.length); + MicroserviceMeta microserviceMeta = microserviceMetas[0]; + Assert.assertEquals(serviceName, microserviceMeta.getShortName()); + listenerNotified.value = true; + } + }.getMockInstance()); + + StaticMicroserviceVersionMeta staticMicroserviceVersionMeta = new StaticMicroserviceVersionMeta(staticMicroservice, + classLoaderFactory); + + Assert.assertTrue(schemaLoaded.value); + Assert.assertTrue(listenerNotified.value); + Assert.assertSame(staticMicroservice, staticMicroserviceVersionMeta.getMicroservice()); + Assert.assertEquals(serviceName, staticMicroserviceVersionMeta.getMicroserviceMeta().getName()); + } +} \ No newline at end of file diff --git a/core/src/test/java/org/apache/servicecomb/core/definition/schema/StaticSchemaFactoryTest.java b/core/src/test/java/org/apache/servicecomb/core/definition/schema/StaticSchemaFactoryTest.java new file mode 100644 index 000000000..2f254ae7c --- /dev/null +++ b/core/src/test/java/org/apache/servicecomb/core/definition/schema/StaticSchemaFactoryTest.java @@ -0,0 +1,168 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.core.definition.schema; + +import java.lang.reflect.Method; +import java.util.concurrent.CompletableFuture; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.QueryParam; + +import org.apache.servicecomb.core.definition.MicroserviceMeta; +import org.apache.servicecomb.core.definition.OperationMeta; +import org.apache.servicecomb.core.definition.SchemaMeta; +import org.apache.servicecomb.core.definition.loader.SchemaLoader; +import org.apache.servicecomb.core.unittest.UnitTestMeta; +import org.apache.servicecomb.foundation.common.utils.ReflectUtils; +import org.apache.servicecomb.serviceregistry.api.registry.StaticMicroservice; +import org.apache.servicecomb.swagger.SwaggerUtils; +import org.apache.servicecomb.swagger.generator.core.CompositeSwaggerGeneratorContext; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +public class StaticSchemaFactoryTest { + + private static final StaticSchemaFactory staticSchemaFactory = new StaticSchemaFactory(); + + private static final String APPLICATION_ID_KEY = "APPLICATION_ID"; + + private static final String APP_ID_VALUE = "appIdTest"; + + @BeforeClass + public static void beforeClass() { + System.setProperty(APPLICATION_ID_KEY, APP_ID_VALUE); + new UnitTestMeta(); + + CompositeSwaggerGeneratorContext compositeSwaggerGeneratorContext = new CompositeSwaggerGeneratorContext(); + ReflectUtils.setField(staticSchemaFactory, "compositeSwaggerGeneratorContext", compositeSwaggerGeneratorContext); + + SchemaLoader schemaLoader = new SchemaLoader(); + ReflectUtils.setField(staticSchemaFactory, "schemaLoader", schemaLoader); + } + + @AfterClass + public static void afterClass() { + TestProducerSchemaFactory.teardown(); + System.clearProperty(APPLICATION_ID_KEY); + } + + @Test + public void testLoadSchema() { + String serviceAndSchemaName = "3rdPartyService"; + StaticMicroservice staticMicroservice = new StaticMicroservice(); + staticMicroservice.setSchemaIntfCls(Test3rdPartyServiceIntf.class); + MicroserviceMeta microserviceMeta = new MicroserviceMeta(serviceAndSchemaName); + staticSchemaFactory.loadSchema(microserviceMeta, staticMicroservice); + + SchemaMeta schemaMeta = microserviceMeta.findSchemaMeta(serviceAndSchemaName); + Assert.assertEquals(EXPECTED_SCHEMA_CONTENT, + SwaggerUtils.swaggerToString(schemaMeta.getSwagger())); + + Assert.assertEquals(2, schemaMeta.getOperations().size()); + OperationMeta operationMeta = schemaMeta.ensureFindOperation("add"); + Assert.assertEquals("add", operationMeta.getOperationId()); + Method swaggerProducerMethod = operationMeta.getMethod(); + Class<?>[] parameterTypes = swaggerProducerMethod.getParameterTypes(); + Assert.assertEquals(2, parameterTypes.length); + Assert.assertEquals(Integer.class, parameterTypes[0]); + Assert.assertEquals(Integer.class, parameterTypes[1]); + Assert.assertEquals(Integer.class, swaggerProducerMethod.getGenericReturnType()); + + operationMeta = schemaMeta.ensureFindOperation("addAsync"); + Assert.assertEquals("addAsync", operationMeta.getOperationId()); + swaggerProducerMethod = operationMeta.getMethod(); + parameterTypes = swaggerProducerMethod.getParameterTypes(); + Assert.assertEquals(2, parameterTypes.length); + Assert.assertEquals(Integer.class, parameterTypes[0]); + Assert.assertEquals(Integer.class, parameterTypes[1]); + // ensure reactive operation's return type is set correctly, not CompletableFuture<T> + Assert.assertEquals(Integer.class, swaggerProducerMethod.getGenericReturnType()); + } + + @Path("/3rdParty") + interface Test3rdPartyServiceIntf { + + @Path("/add") + @GET + int add(@QueryParam("x") int x, @QueryParam("y") int y); + + @Path("/addAsync") + @GET + CompletableFuture<Integer> addAsync(@QueryParam("x") int x, @QueryParam("y") int y); + } + + private static final String EXPECTED_SCHEMA_CONTENT = "---\n" + + "swagger: \"2.0\"\n" + + "info:\n" + + " version: \"1.0.0\"\n" + + " title: \"swagger definition for org.apache.servicecomb.core.definition.schema.StaticSchemaFactoryTest$Test3rdPartyServiceIntf\"\n" + + " x-java-interface: \"cse.gen.appIdTest._3rdPartyService._3rdPartyService.Test3rdPartyServiceIntfIntf\"\n" + + "basePath: \"/3rdParty\"\n" + + "consumes:\n" + + "- \"application/json\"\n" + + "produces:\n" + + "- \"application/json\"\n" + + "paths:\n" + + " /add:\n" + + " get:\n" + + " operationId: \"add\"\n" + + " parameters:\n" + + " - name: \"x\"\n" + + " in: \"query\"\n" + + " required: false\n" + + " type: \"integer\"\n" + + " default: 0\n" + + " format: \"int32\"\n" + + " - name: \"y\"\n" + + " in: \"query\"\n" + + " required: false\n" + + " type: \"integer\"\n" + + " default: 0\n" + + " format: \"int32\"\n" + + " responses:\n" + + " 200:\n" + + " description: \"response of 200\"\n" + + " schema:\n" + + " type: \"integer\"\n" + + " format: \"int32\"\n" + + " /addAsync:\n" + + " get:\n" + + " operationId: \"addAsync\"\n" + + " parameters:\n" + + " - name: \"x\"\n" + + " in: \"query\"\n" + + " required: false\n" + + " type: \"integer\"\n" + + " default: 0\n" + + " format: \"int32\"\n" + + " - name: \"y\"\n" + + " in: \"query\"\n" + + " required: false\n" + + " type: \"integer\"\n" + + " default: 0\n" + + " format: \"int32\"\n" + + " responses:\n" + + " 200:\n" + + " description: \"response of 200\"\n" + + " schema:\n" + + " type: \"integer\"\n" + + " format: \"int32\"\n"; +} \ No newline at end of file diff --git a/demo/demo-schema/src/main/resources/config/log4j.properties b/demo/demo-schema/src/main/resources/config/log4j.properties index cad696acc..940109425 100644 --- a/demo/demo-schema/src/main/resources/config/log4j.properties +++ b/demo/demo-schema/src/main/resources/config/log4j.properties @@ -19,3 +19,5 @@ paas.logs.dir=../target/logs/ paas.logs.file=cse.log log4j.rootLogger=INFO,paas,stdout +log4j.logger.org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory=OFF +log4j.logger.org.apache.servicecomb.core.definition.schema.StaticSchemaFactory=OFF diff --git a/demo/demo-spring-boot-discovery/demo-spring-boot-discovery-client/src/test/resources/logback-test.xml b/demo/demo-spring-boot-discovery/demo-spring-boot-discovery-client/src/test/resources/logback-test.xml index 3f394068d..52d292541 100644 --- a/demo/demo-spring-boot-discovery/demo-spring-boot-discovery-client/src/test/resources/logback-test.xml +++ b/demo/demo-spring-boot-discovery/demo-spring-boot-discovery-client/src/test/resources/logback-test.xml @@ -18,4 +18,6 @@ <configuration> <include resource="org/springframework/boot/logging/logback/base.xml"/> <logger name="org.springframework" level="ERROR"/> + <logger name="org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory" level="OFF"/> + <logger name="org.apache.servicecomb.core.definition.schema.StaticSchemaFactory" level="OFF"/> </configuration> \ No newline at end of file diff --git a/demo/demo-spring-boot-discovery/demo-spring-boot-discovery-server/src/main/resources/logback-test.xml b/demo/demo-spring-boot-discovery/demo-spring-boot-discovery-server/src/main/resources/logback-test.xml index 3f394068d..52d292541 100644 --- a/demo/demo-spring-boot-discovery/demo-spring-boot-discovery-server/src/main/resources/logback-test.xml +++ b/demo/demo-spring-boot-discovery/demo-spring-boot-discovery-server/src/main/resources/logback-test.xml @@ -18,4 +18,6 @@ <configuration> <include resource="org/springframework/boot/logging/logback/base.xml"/> <logger name="org.springframework" level="ERROR"/> + <logger name="org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory" level="OFF"/> + <logger name="org.apache.servicecomb.core.definition.schema.StaticSchemaFactory" level="OFF"/> </configuration> \ No newline at end of file diff --git a/demo/demo-spring-boot-discovery/demo-spring-boot-zuul-proxy/src/test/resources/logback-test.xml b/demo/demo-spring-boot-discovery/demo-spring-boot-zuul-proxy/src/test/resources/logback-test.xml index 3f394068d..52d292541 100644 --- a/demo/demo-spring-boot-discovery/demo-spring-boot-zuul-proxy/src/test/resources/logback-test.xml +++ b/demo/demo-spring-boot-discovery/demo-spring-boot-zuul-proxy/src/test/resources/logback-test.xml @@ -18,4 +18,6 @@ <configuration> <include resource="org/springframework/boot/logging/logback/base.xml"/> <logger name="org.springframework" level="ERROR"/> + <logger name="org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory" level="OFF"/> + <logger name="org.apache.servicecomb.core.definition.schema.StaticSchemaFactory" level="OFF"/> </configuration> \ No newline at end of file diff --git a/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-client/src/main/resources/config/log4j.properties b/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-client/src/main/resources/config/log4j.properties new file mode 100644 index 000000000..ff989feda --- /dev/null +++ b/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-client/src/main/resources/config/log4j.properties @@ -0,0 +1,18 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +log4j.logger.org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory=OFF +log4j.logger.org.apache.servicecomb.core.definition.schema.StaticSchemaFactory=OFF diff --git a/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-server/src/main/resources/config/log4j.properties b/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-server/src/main/resources/config/log4j.properties new file mode 100644 index 000000000..ff989feda --- /dev/null +++ b/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-server/src/main/resources/config/log4j.properties @@ -0,0 +1,18 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +log4j.logger.org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory=OFF +log4j.logger.org.apache.servicecomb.core.definition.schema.StaticSchemaFactory=OFF diff --git a/demo/demo-spring-boot-provider/demo-spring-boot-springmvc-client/src/main/resources/config/log4j.properties b/demo/demo-spring-boot-provider/demo-spring-boot-springmvc-client/src/main/resources/config/log4j.properties new file mode 100644 index 000000000..ff989feda --- /dev/null +++ b/demo/demo-spring-boot-provider/demo-spring-boot-springmvc-client/src/main/resources/config/log4j.properties @@ -0,0 +1,18 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +log4j.logger.org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory=OFF +log4j.logger.org.apache.servicecomb.core.definition.schema.StaticSchemaFactory=OFF diff --git a/demo/demo-spring-boot-provider/demo-spring-boot-springmvc-server/src/main/resources/config/log4j.properties b/demo/demo-spring-boot-provider/demo-spring-boot-springmvc-server/src/main/resources/config/log4j.properties new file mode 100644 index 000000000..ff989feda --- /dev/null +++ b/demo/demo-spring-boot-provider/demo-spring-boot-springmvc-server/src/main/resources/config/log4j.properties @@ -0,0 +1,18 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +log4j.logger.org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory=OFF +log4j.logger.org.apache.servicecomb.core.definition.schema.StaticSchemaFactory=OFF diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/resources/config/log4j.properties b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/resources/config/log4j.properties new file mode 100644 index 000000000..ff989feda --- /dev/null +++ b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/resources/config/log4j.properties @@ -0,0 +1,18 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +log4j.logger.org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory=OFF +log4j.logger.org.apache.servicecomb.core.definition.schema.StaticSchemaFactory=OFF diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/resources/config/log4j.properties b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/resources/config/log4j.properties new file mode 100644 index 000000000..ff989feda --- /dev/null +++ b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/resources/config/log4j.properties @@ -0,0 +1,18 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +log4j.logger.org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory=OFF +log4j.logger.org.apache.servicecomb.core.definition.schema.StaticSchemaFactory=OFF diff --git a/demo/demo-springmvc/springmvc-client/src/main/resources/config/log4j.properties b/demo/demo-springmvc/springmvc-client/src/main/resources/config/log4j.properties new file mode 100644 index 000000000..ff989feda --- /dev/null +++ b/demo/demo-springmvc/springmvc-client/src/main/resources/config/log4j.properties @@ -0,0 +1,18 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +log4j.logger.org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory=OFF +log4j.logger.org.apache.servicecomb.core.definition.schema.StaticSchemaFactory=OFF diff --git a/demo/demo-springmvc/springmvc-server/src/main/resources/config/log4j.properties b/demo/demo-springmvc/springmvc-server/src/main/resources/config/log4j.properties new file mode 100644 index 000000000..ff989feda --- /dev/null +++ b/demo/demo-springmvc/springmvc-server/src/main/resources/config/log4j.properties @@ -0,0 +1,18 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +log4j.logger.org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory=OFF +log4j.logger.org.apache.servicecomb.core.definition.schema.StaticSchemaFactory=OFF diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java index 12a59f061..32dc0c698 100644 --- a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java +++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java @@ -34,6 +34,7 @@ import org.apache.servicecomb.it.testcase.TestRestServerConfigEdge; import org.apache.servicecomb.it.testcase.TestTrace; import org.apache.servicecomb.it.testcase.TestTraceEdge; +import org.apache.servicecomb.it.testcase.thirdparty.Test3rdPartyInvocation; public class ConsumerMain { private static ResultPrinter resultPrinter = new ResultPrinter(); @@ -132,6 +133,7 @@ private static void testStandalone() throws Throwable { ITJUnitUtils.run(TestRestServerConfigEdge.class); ITJUnitUtils.run(TestRequestBodySpringMvcSchema.class); + ITJUnitUtils.run(Test3rdPartyInvocation.class); ITJUnitUtils.getParents().pop(); deploys.getBaseProducer().stop(); diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/schema/ApiParamSpringmvcSchema.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/schema/ApiParamSpringmvcSchema.java index b291692bf..8cd6e5463 100644 --- a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/schema/ApiParamSpringmvcSchema.java +++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/schema/ApiParamSpringmvcSchema.java @@ -47,7 +47,7 @@ public void query(@ApiParam(value = "desc of query param", readOnly = true, allowEmptyValue = true, name = "inputEx", - example = "example", + example = "10", collectionFormat = "fmt") int input) { } diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/TestApiParam.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/TestApiParam.java index 317874246..f3e120cd6 100644 --- a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/TestApiParam.java +++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/TestApiParam.java @@ -97,7 +97,7 @@ public void springmvcQuery() { Assert.assertTrue(parameter.isReadOnly()); Assert.assertTrue(parameter.getAllowEmptyValue()); Assert.assertEquals("inputEx", parameter.getName()); - Assert.assertEquals("example", ((QueryParameter) parameter).getExample()); + Assert.assertEquals(10L, ((QueryParameter) parameter).getExample()); Assert.assertEquals("fmt", ((QueryParameter) parameter).getCollectionFormat()); } diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/thirdparty/Test3rdPartyInvocation.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/thirdparty/Test3rdPartyInvocation.java new file mode 100644 index 000000000..370910621 --- /dev/null +++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/thirdparty/Test3rdPartyInvocation.java @@ -0,0 +1,246 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.it.testcase.thirdparty; + +import java.util.Collections; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +import javax.ws.rs.CookieParam; +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.QueryParam; +import javax.xml.ws.Holder; + +import org.apache.servicecomb.it.extend.engine.GateRestTemplate; +import org.apache.servicecomb.provider.pojo.Invoker; +import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; +import org.apache.servicecomb.provider.springmvc.reference.async.CseAsyncRestTemplate; +import org.apache.servicecomb.serviceregistry.RegistryUtils; +import org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.util.concurrent.ListenableFuture; +import org.springframework.web.client.RestTemplate; + +public class Test3rdPartyInvocation { + + private static final String THIRD_PARTY_MICROSERVICE_NAME = "3rdPartyDataTypeJaxrs"; + + private static final String ASYNC_THIRD_PARTY_MICROSERVICE_NAME = THIRD_PARTY_MICROSERVICE_NAME + "Async"; + + // to get endpoint from urlPrefix + static GateRestTemplate rt = new GateRestTemplate("it-edge", "it-producer", "dataTypeJaxrs"); + + private static DataTypeJaxrsSchemaIntf dataTypeJaxrsSchema; + + private static DataTypeJaxrsSchemaAsyncIntf dataTypeJaxrsSchemaAsync; + + @BeforeClass + public static void beforeClass() { + String urlPrefix = rt.getUrlPrefix(); + int beginIndex = urlPrefix.indexOf("//"); + int endIndex = urlPrefix.indexOf("/", beginIndex + 3); + String endpoint = "rest:" + urlPrefix.substring(beginIndex, endIndex); + RegistryUtils.getServiceRegistry() + .registerMicroserviceMappingByEndpoints( + THIRD_PARTY_MICROSERVICE_NAME, "1.2.1", + Collections.singletonList(endpoint), + DataTypeJaxrsSchemaIntf.class); + + MicroserviceInstance instance = new MicroserviceInstance(); + instance.setEndpoints(Collections.singletonList(endpoint)); + RegistryUtils.getServiceRegistry() + .registerMicroserviceMapping( + ASYNC_THIRD_PARTY_MICROSERVICE_NAME, "1.1.1", + Collections.singletonList(instance), + DataTypeJaxrsSchemaAsyncIntf.class + ); + + dataTypeJaxrsSchema = Invoker.createProxy( + THIRD_PARTY_MICROSERVICE_NAME, THIRD_PARTY_MICROSERVICE_NAME, DataTypeJaxrsSchemaIntf.class); + dataTypeJaxrsSchemaAsync = Invoker.createProxy( + ASYNC_THIRD_PARTY_MICROSERVICE_NAME, ASYNC_THIRD_PARTY_MICROSERVICE_NAME, DataTypeJaxrsSchemaAsyncIntf.class); + } + + @Test + public void testSyncInvoke_RPC() { + Assert.assertEquals(1, dataTypeJaxrsSchema.intPath(1)); + Assert.assertEquals(2, dataTypeJaxrsSchema.intQuery(2)); + Assert.assertEquals(3, dataTypeJaxrsSchema.intHeader(3)); + Assert.assertEquals(4, dataTypeJaxrsSchema.intCookie(4)); + Assert.assertEquals(5, dataTypeJaxrsSchema.intForm(5)); + Assert.assertEquals(6, dataTypeJaxrsSchema.intBody(6)); + Assert.assertEquals(7, dataTypeJaxrsSchema.add(3, 4)); + Assert.assertEquals("abc", dataTypeJaxrsSchema.stringPath("abc")); + Assert.assertEquals("def", dataTypeJaxrsSchema.stringQuery("def")); + Assert.assertEquals("ghi", dataTypeJaxrsSchema.stringHeader("ghi")); + Assert.assertEquals("jkl", dataTypeJaxrsSchema.stringCookie("jkl")); + Assert.assertEquals("mn", dataTypeJaxrsSchema.stringForm("mn")); + Assert.assertEquals("opq", dataTypeJaxrsSchema.stringBody("opq")); + Assert.assertEquals("uvwxyz", dataTypeJaxrsSchema.stringConcat("uvw", "xyz")); + } + + @Test + public void testAsyncInvoke_RPC() throws ExecutionException, InterruptedException { + Holder<Boolean> addChecked = new Holder<>(false); + dataTypeJaxrsSchemaAsync.add(5, 6).whenComplete((result, t) -> { + Assert.assertEquals(11, result.intValue()); + Assert.assertNull(t); + addChecked.value = true; + }).get(); + Assert.assertTrue(addChecked.value); + + Holder<Boolean> postStringChecked = new Holder<>(false); + dataTypeJaxrsSchemaAsync.stringBody("abc").whenComplete((result, t) -> { + Assert.assertEquals("abc", result); + Assert.assertNull(t); + postStringChecked.value = true; + }).get(); + Assert.assertTrue(postStringChecked.value); + + Holder<Boolean> concatChecked = new Holder<>(false); + dataTypeJaxrsSchemaAsync.stringConcat("uvw", "xyz").whenComplete((result, t) -> { + Assert.assertEquals("uvwxyz", result); + Assert.assertNull(t); + concatChecked.value = true; + }).get(); + Assert.assertTrue(concatChecked.value); + } + + @Test + public void testSyncInvoke_RestTemplate() { + RestTemplate restTemplate = RestTemplateBuilder.create(); + ResponseEntity<Integer> responseEntity = restTemplate + .getForEntity( + "cse://" + THIRD_PARTY_MICROSERVICE_NAME + "/rest/it-producer/v1/dataTypeJaxrs/add?num1=11&num2=22", + int.class); + Assert.assertEquals(200, responseEntity.getStatusCodeValue()); + Assert.assertEquals(33, responseEntity.getBody().intValue()); + + ResponseEntity<String> stringBodyResponse = restTemplate + .exchange("cse://" + THIRD_PARTY_MICROSERVICE_NAME + "/rest/it-producer/v1/dataTypeJaxrs/stringBody", + HttpMethod.POST, + new HttpEntity<>("abc"), String.class); + Assert.assertEquals(200, stringBodyResponse.getStatusCodeValue()); + Assert.assertEquals("abc", stringBodyResponse.getBody()); + } + + @Test + public void testAsyncInvoke_RestTemplate() throws ExecutionException, InterruptedException { + CseAsyncRestTemplate cseAsyncRestTemplate = new CseAsyncRestTemplate(); + ListenableFuture<ResponseEntity<Integer>> responseFuture = cseAsyncRestTemplate + .getForEntity( + "cse://" + ASYNC_THIRD_PARTY_MICROSERVICE_NAME + "/rest/it-producer/v1/dataTypeJaxrs/add?num1=11&num2=22", + Integer.class); + ResponseEntity<Integer> responseEntity = responseFuture.get(); + Assert.assertEquals(200, responseEntity.getStatusCodeValue()); + Assert.assertEquals(33, responseEntity.getBody().intValue()); + + ListenableFuture<ResponseEntity<String>> stringBodyFuture = cseAsyncRestTemplate + .exchange("cse://" + ASYNC_THIRD_PARTY_MICROSERVICE_NAME + "/rest/it-producer/v1/dataTypeJaxrs/stringBody", + HttpMethod.POST, + new HttpEntity<>("abc"), String.class); + ResponseEntity<String> stringBodyResponse = stringBodyFuture.get(); + Assert.assertEquals(200, stringBodyResponse.getStatusCodeValue()); + Assert.assertEquals("abc", stringBodyResponse.getBody()); + } + + @Path("/rest/it-producer/v1/dataTypeJaxrs") + interface DataTypeJaxrsSchemaIntf { + @Path("intPath/{input}") + @GET + int intPath(@PathParam("input") int input); + + @Path("intQuery") + @GET + int intQuery(@QueryParam("input") int input); + + @Path("intHeader") + @GET + int intHeader(@HeaderParam("input") int input); + + @Path("intCookie") + @GET + int intCookie(@CookieParam("input") int input); + + @Path("intForm") + @POST + int intForm(@FormParam("input") int input); + + @Path("intBody") + @POST + int intBody(int input); + + @Path("add") + @GET + int add(@QueryParam("num1") int num1, @QueryParam("num2") int num2); + + //strinnum1 + @Path("stringPath/{input}") + @GET + String stringPath(@PathParam("input") String input); + + @Path("stringQuery") + @GET + String stringQuery(@QueryParam("input") String input); + + @Path("stringHeader") + @GET + String stringHeader(@HeaderParam("input") String input); + + @Path("stringCookie") + @GET + String stringCookie(@CookieParam("input") String input); + + @Path("stringForm") + @POST + String stringForm(@FormParam("input") String input); + + @Path("stringBody") + @POST + String stringBody(String input); + + @Path("stringConcat") + @GET + String stringConcat(@QueryParam("str1") String str1, @QueryParam("str2") String str2); + } + + @Path("/rest/it-producer/v1/dataTypeJaxrs") + interface DataTypeJaxrsSchemaAsyncIntf { + @Path("add") + @GET + CompletableFuture<Integer> add(@QueryParam("num1") int num1, @QueryParam("num2") int num2); + + @Path("stringBody") + @POST + CompletableFuture<String> stringBody(String input); + + @Path("stringConcat") + @GET + CompletableFuture<String> stringConcat(@QueryParam("str1") String str1, @QueryParam("str2") String str2); + } +} diff --git a/integration-tests/spring-zuul-tracing-tests/src/test/resources/log4j.properties b/integration-tests/spring-zuul-tracing-tests/src/test/resources/log4j.properties index e5addd943..a25e46fe6 100644 --- a/integration-tests/spring-zuul-tracing-tests/src/test/resources/log4j.properties +++ b/integration-tests/spring-zuul-tracing-tests/src/test/resources/log4j.properties @@ -21,3 +21,5 @@ log4j.rootLogger=WARN, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n +log4j.logger.org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory=OFF +log4j.logger.org.apache.servicecomb.core.definition.schema.StaticSchemaFactory=OFF diff --git a/integration-tests/tracing-tests/src/test/resources/log4j.properties b/integration-tests/tracing-tests/src/test/resources/log4j.properties new file mode 100644 index 000000000..ff989feda --- /dev/null +++ b/integration-tests/tracing-tests/src/test/resources/log4j.properties @@ -0,0 +1,18 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +log4j.logger.org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory=OFF +log4j.logger.org.apache.servicecomb.core.definition.schema.StaticSchemaFactory=OFF diff --git a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/ServiceRegistry.java b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/ServiceRegistry.java index a8cf7854b..ead2ccc31 100644 --- a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/ServiceRegistry.java +++ b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/ServiceRegistry.java @@ -59,4 +59,38 @@ MicroserviceInstances findServiceInstances(String appId, String microserviceName Microservice getRemoteMicroservice(String microserviceId); Features getFeatures(); + + /** + * <p> + * Register a third party service if not registered before, and set it's instances into + * {@linkplain org.apache.servicecomb.serviceregistry.consumer.StaticMicroserviceVersions StaticMicroserviceVersions}. + * </p> + * <p> + * The registered third party service has the same {@code appId} and {@code environment} as this microservice instance has, + * and there is only one schema represented by {@code schemaIntfCls}, whose name is the same as {@code microserviceName}. + * </p> + * <em> + * This method is for initializing 3rd party service endpoint config. + * i.e. If this service has not been registered before, this service will be registered and the instances will be set; + * otherwise, NOTHING will happen. + * </em> + * + * @param microserviceName name of the 3rd party service, and this param also specifies the schemaId + * @param version version of this 3rd party service + * @param instances the instances of this 3rd party service. Users only need to specify the endpoint information, other + * necessary information will be generate and set in the implementation of this method. + * @param schemaIntfCls the producer interface of the service. This interface is used to generate swagger schema and + * can also be used for the proxy interface of RPC style invocation. + */ + void registerMicroserviceMapping(String microserviceName, String version, List<MicroserviceInstance> instances, + Class<?> schemaIntfCls); + + /** + * @see #registerMicroserviceMapping(String, String, List, Class) + * @param endpoints the endpoints of 3rd party service. Each of endpoints will be treated as a separated instance. + * Format of the endpoints is the same as the endpoints that ServiceComb microservices register in service-center, + * like {@code rest://127.0.0.1:8080} + */ + void registerMicroserviceMappingByEndpoints(String microserviceName, String version, + List<String> endpoints, Class<?> schemaIntfCls); } diff --git a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/api/registry/StaticMicroservice.java b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/api/registry/StaticMicroservice.java new file mode 100644 index 000000000..60d5900df --- /dev/null +++ b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/api/registry/StaticMicroservice.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.serviceregistry.api.registry; + +public class StaticMicroservice extends Microservice { + private Class<?> schemaIntfCls; + + public Class<?> getSchemaIntfCls() { + return schemaIntfCls; + } + + public void setSchemaIntfCls(Class<?> schemaIntfCls) { + this.schemaIntfCls = schemaIntfCls; + } +} diff --git a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/config/ServiceRegistryConfig.java b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/config/ServiceRegistryConfig.java index 23824a800..9832735b9 100644 --- a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/config/ServiceRegistryConfig.java +++ b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/config/ServiceRegistryConfig.java @@ -86,16 +86,21 @@ public static final String PROXY_PASSWD = PROXY_PRE_NAME + "passwd"; - private ServiceRegistryConfig() { } - public String getMicroserviceVersionFactory() { return DynamicPropertyFactory.getInstance().getStringProperty(MICROSERVICE_VERSION_FACTORY, null).get(); } + /** + * Currently we don't provide configuration about {@link org.apache.servicecomb.serviceregistry.consumer.StaticMicroserviceVersionFactory} + */ + public String getStaticMicroserviceVersionFactory() { + return "org.apache.servicecomb.core.definition.StaticMicroserviceVersionMetaFactory"; + } + public HttpVersion getHttpVersion() { DynamicStringProperty property = DynamicPropertyFactory.getInstance() diff --git a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/AppManager.java b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/AppManager.java index 7cc45e221..4eef10f6d 100644 --- a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/AppManager.java +++ b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/AppManager.java @@ -20,10 +20,16 @@ import java.util.Map; import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; +import org.apache.servicecomb.serviceregistry.config.ServiceRegistryConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.common.eventbus.EventBus; public class AppManager { + + private static final Logger LOGGER = LoggerFactory.getLogger(AppManager.class); + private EventBus eventBus; private MicroserviceVersionFactory microserviceVersionFactory = new DefaultMicroserviceVersionFactory(); @@ -31,6 +37,8 @@ // key: appId private Map<String, MicroserviceManager> apps = new ConcurrentHashMapEx<>(); + private volatile StaticMicroserviceVersionFactory staticMicroserviceVersionFactory; + public AppManager(EventBus eventBus) { this.eventBus = eventBus; } @@ -67,4 +75,33 @@ public MicroserviceVersions getOrCreateMicroserviceVersions(String appId, String MicroserviceManager microserviceManager = getOrCreateMicroserviceManager(appId); return microserviceManager.getOrCreateMicroserviceVersions(microserviceName); } + + public StaticMicroserviceVersionFactory getStaticMicroserviceVersionFactory() { + if (null == staticMicroserviceVersionFactory) { + synchronized (this) { + if (null == staticMicroserviceVersionFactory) { + loadStaticMicroserviceVersionFactory(); + } + } + } + return staticMicroserviceVersionFactory; + } + + public void setStaticMicroserviceVersionFactory(StaticMicroserviceVersionFactory staticMicroserviceVersionFactory) { + this.staticMicroserviceVersionFactory = staticMicroserviceVersionFactory; + } + + private void loadStaticMicroserviceVersionFactory() { + String staticMicroserviceVersionFactoryClass = ServiceRegistryConfig.INSTANCE + .getStaticMicroserviceVersionFactory(); + try { + staticMicroserviceVersionFactory = (StaticMicroserviceVersionFactory) Class + .forName(staticMicroserviceVersionFactoryClass).newInstance(); + } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { + LOGGER.info("unable to load StaticMicroserviceVersionFactory", e); + // interrupt this loading process because this error cannot be covered by us. + throw new IllegalStateException("unable to load StaticMicroserviceVersionFactory", e); + } + LOGGER.info("staticMicroserviceVersionFactory is {}.", staticMicroserviceVersionFactoryClass); + } } diff --git a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceVersion.java b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceVersion.java index 68ce8c8eb..b956a664e 100644 --- a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceVersion.java +++ b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceVersion.java @@ -35,6 +35,11 @@ public MicroserviceVersion(String microserviceId) { this.version = new Version(microservice.getVersion()); } + public MicroserviceVersion(Microservice microservice) { + this.microservice = microservice; + this.version = new Version(microservice.getVersion()); + } + public Microservice getMicroservice() { return microservice; } diff --git a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceVersions.java b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceVersions.java index ab4f479d0..e85c51311 100644 --- a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceVersions.java +++ b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/MicroserviceVersions.java @@ -43,7 +43,7 @@ public class MicroserviceVersions { private static final Logger LOGGER = LoggerFactory.getLogger(MicroserviceVersions.class); - private AppManager appManager; + AppManager appManager; private String appId; @@ -58,13 +58,13 @@ // in the future: // pulledInstances means all instance // instances means available instance - private List<MicroserviceInstance> instances; + List<MicroserviceInstance> instances; // key is service id - private Map<String, MicroserviceVersion> versions = new ConcurrentHashMapEx<>(); + Map<String, MicroserviceVersion> versions = new ConcurrentHashMapEx<>(); // key is version rule - private Map<String, MicroserviceVersionRule> versionRules = new ConcurrentHashMapEx<>(); + Map<String, MicroserviceVersionRule> versionRules = new ConcurrentHashMapEx<>(); // process pulled instances and create versionRule must be protected by lock // otherwise maybe lost instance or version in versionRule @@ -74,7 +74,7 @@ // only pendingPullCount is 0, then do a real pull private AtomicInteger pendingPullCount = new AtomicInteger(); - private boolean validated = false; + boolean validated = false; public MicroserviceVersions(AppManager appManager, String appId, String microserviceName) { this.appManager = appManager; diff --git a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/StaticMicroserviceVersionFactory.java b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/StaticMicroserviceVersionFactory.java new file mode 100644 index 000000000..d2fb60d69 --- /dev/null +++ b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/StaticMicroserviceVersionFactory.java @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.serviceregistry.consumer; + +import org.apache.servicecomb.serviceregistry.api.registry.StaticMicroservice; + +public interface StaticMicroserviceVersionFactory { + MicroserviceVersion create(StaticMicroservice microservice); +} diff --git a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/StaticMicroserviceVersions.java b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/StaticMicroserviceVersions.java new file mode 100644 index 000000000..286ff95bb --- /dev/null +++ b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/consumer/StaticMicroserviceVersions.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.serviceregistry.consumer; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import org.apache.servicecomb.serviceregistry.RegistryUtils; +import org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance; +import org.apache.servicecomb.serviceregistry.api.registry.StaticMicroservice; +import org.apache.servicecomb.serviceregistry.version.Version; + +public class StaticMicroserviceVersions extends MicroserviceVersions { + + private Class<?> schemaIntfCls; + + private String environment; + + public StaticMicroserviceVersions(AppManager appManager, String appId, String microserviceName, + Class<?> schemaIntfCls) { + super(appManager, appId, microserviceName); + + validated = true; + this.schemaIntfCls = schemaIntfCls; + this.environment = RegistryUtils.getMicroservice().getEnvironment(); + } + + @Override + public void pullInstances() { + // instance information is stored locally, do not pull from sc + } + + public void addInstances(String version, List<MicroserviceInstance> addedInstances) { + Version parsedVersion = new Version(version); + String serviceId = computeServiceId(parsedVersion); + + for (MicroserviceInstance instance : addedInstances) { + instance.setServiceId(serviceId); + instance.setInstanceId(serviceId + "-" + UUID.randomUUID()); + } + + mergeInstances(addedInstances); + + // ensure microserviceVersion exists + versions.computeIfAbsent(serviceId, microserviceId -> { + StaticMicroservice microservice = createMicroservice(parsedVersion, serviceId); + MicroserviceVersion microserviceVersion = appManager.getStaticMicroserviceVersionFactory().create(microservice); + for (MicroserviceVersionRule microserviceVersionRule : versionRules.values()) { + microserviceVersionRule.addMicroserviceVersion(microserviceVersion); + } + return microserviceVersion; + }); + + for (MicroserviceVersionRule microserviceVersionRule : versionRules.values()) { + microserviceVersionRule.setInstances(this.instances); + } + } + + private void mergeInstances(List<MicroserviceInstance> instances) { + if (null == this.instances) { + this.instances = new ArrayList<>(instances.size()); + } + this.instances.addAll(instances); + } + + private StaticMicroservice createMicroservice(Version parsedVersion, String serviceId) { + StaticMicroservice microservice = new StaticMicroservice(); + microservice.setAppId(this.getAppId()); + microservice.setServiceId(serviceId); + microservice.setServiceName(this.getMicroserviceName()); + microservice.setVersion(parsedVersion.getVersion()); + microservice.setEnvironment(RegistryUtils.getMicroservice().getEnvironment()); + microservice.setSchemaIntfCls(this.schemaIntfCls); + return microservice; + } + + private String computeServiceId(Version parsedVersion) { + return this.getAppId() + "-" + + this.environment + "-" + + this.getMicroserviceName() + "-" + + parsedVersion.getVersion(); + } +} diff --git a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/registry/AbstractServiceRegistry.java b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/registry/AbstractServiceRegistry.java index 6e880faa2..d266b71da 100644 --- a/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/registry/AbstractServiceRegistry.java +++ b/service-registry/src/main/java/org/apache/servicecomb/serviceregistry/registry/AbstractServiceRegistry.java @@ -19,12 +19,15 @@ import static org.apache.servicecomb.foundation.common.base.ServiceCombConstants.CONFIG_DEFAULT_REGISTER_BY; import static org.apache.servicecomb.foundation.common.base.ServiceCombConstants.CONFIG_FRAMEWORK_DEFAULT_NAME; +import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.servicecomb.serviceregistry.Features; +import org.apache.servicecomb.serviceregistry.RegistryUtils; import org.apache.servicecomb.serviceregistry.ServiceRegistry; import org.apache.servicecomb.serviceregistry.api.Const; import org.apache.servicecomb.serviceregistry.api.registry.BasePath; @@ -40,7 +43,9 @@ import org.apache.servicecomb.serviceregistry.client.http.MicroserviceInstances; import org.apache.servicecomb.serviceregistry.config.ServiceRegistryConfig; import org.apache.servicecomb.serviceregistry.consumer.AppManager; +import org.apache.servicecomb.serviceregistry.consumer.MicroserviceManager; import org.apache.servicecomb.serviceregistry.consumer.MicroserviceVersionFactory; +import org.apache.servicecomb.serviceregistry.consumer.StaticMicroserviceVersions; import org.apache.servicecomb.serviceregistry.definition.MicroserviceDefinition; import org.apache.servicecomb.serviceregistry.task.MicroserviceServiceCenterTask; import org.apache.servicecomb.serviceregistry.task.ServiceCenterTask; @@ -181,7 +186,6 @@ private void loadFrameworkVersions() { microservice.setRegisterBy(CONFIG_DEFAULT_REGISTER_BY); } - private void loadStaticConfiguration() { // TODO 如果yaml定义了paths规则属性,替换默认值,现需要DynamicPropertyFactory支持数组获取 List<BasePath> paths = microservice.getPaths(); @@ -303,4 +307,32 @@ public void destroy() { eventBus.post(new ShutdownEvent()); unregisterInstance(); } + + @Override + public void registerMicroserviceMapping(String microserviceName, String version, + List<MicroserviceInstance> instances, Class<?> schemaIntfCls) { + String app = RegistryUtils.getAppId(); + MicroserviceManager microserviceManager = appManager.getOrCreateMicroserviceManager(app); + microserviceManager.getVersionsByName() + .computeIfAbsent(microserviceName, + svcName -> { + StaticMicroserviceVersions microserviceVersions = new StaticMicroserviceVersions(this.appManager, + app, microserviceName, schemaIntfCls); + microserviceVersions.addInstances(version, instances); + return microserviceVersions; + }); + } + + @Override + public void registerMicroserviceMappingByEndpoints(String microserviceName, String version, + List<String> endpoints, Class<?> schemaIntfCls) { + ArrayList<MicroserviceInstance> microserviceInstances = new ArrayList<>(); + for (String endpoint : endpoints) { + MicroserviceInstance instance = new MicroserviceInstance(); + instance.setEndpoints(Collections.singletonList(endpoint)); + microserviceInstances.add(instance); + } + + registerMicroserviceMapping(microserviceName, version, microserviceInstances, schemaIntfCls); + } } diff --git a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/StaticMicroserviceVersionsTest.java b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/StaticMicroserviceVersionsTest.java new file mode 100644 index 000000000..ca3c3b3a5 --- /dev/null +++ b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/StaticMicroserviceVersionsTest.java @@ -0,0 +1,155 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.serviceregistry.consumer; + +import java.util.Collections; + +import org.apache.servicecomb.serviceregistry.RegistryUtils; +import org.apache.servicecomb.serviceregistry.api.registry.Microservice; +import org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance; +import org.apache.servicecomb.serviceregistry.api.registry.StaticMicroservice; +import org.apache.servicecomb.serviceregistry.client.ServiceRegistryClient; +import org.apache.servicecomb.serviceregistry.definition.MicroserviceDefinition; +import org.apache.servicecomb.serviceregistry.registry.AbstractServiceRegistry; +import org.apache.servicecomb.serviceregistry.version.Version; +import org.apache.servicecomb.serviceregistry.version.VersionUtils; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.google.common.eventbus.EventBus; + +import mockit.Mock; +import mockit.MockUp; + +public class StaticMicroserviceVersionsTest { + + private static final String APP_ID = "testAppId"; + + private static final String THIS_SERVICE = "thisService"; + + private static final String MICROSERVICE_NAME = "3rdPartyService"; + + private static final String ENVIRONMENT = "production"; + + private static final String SERVICE_ID_PREFIX = APP_ID + "-" + ENVIRONMENT + "-" + MICROSERVICE_NAME + "-"; + + @BeforeClass + public static void beforeClass() { + RegistryUtils.setServiceRegistry(new AbstractServiceRegistry(null, null, + MicroserviceDefinition.create(APP_ID, THIS_SERVICE)) { + @Override + protected ServiceRegistryClient createServiceRegistryClient() { + return null; + } + }); + RegistryUtils.getMicroservice().setEnvironment(ENVIRONMENT); + } + + @Test + public void addInstanceBasic() { + StaticMicroserviceVersions staticMicroserviceVersions = createStaticMicroserviceVersions(); + + MicroserviceInstance instance = new MicroserviceInstance(); + String serviceVersion = "1.2.1"; + staticMicroserviceVersions.addInstances(serviceVersion, Collections.singletonList(instance)); + + MicroserviceVersionRule versionRule = staticMicroserviceVersions.getOrCreateMicroserviceVersionRule(serviceVersion); + MicroserviceVersion latestMicroserviceVersion = versionRule.getLatestMicroserviceVersion(); + Assert.assertEquals(new Version(serviceVersion), latestMicroserviceVersion.getVersion()); + Microservice latestMicroservice = latestMicroserviceVersion.getMicroservice(); + Assert.assertEquals(APP_ID, latestMicroservice.getAppId()); + Assert.assertEquals(SERVICE_ID_PREFIX + serviceVersion, latestMicroservice.getServiceId()); + Assert.assertEquals(MICROSERVICE_NAME, latestMicroservice.getServiceName()); + Assert.assertEquals(serviceVersion, latestMicroservice.getVersion()); + Assert.assertEquals(ENVIRONMENT, latestMicroservice.getEnvironment()); + Assert.assertEquals(TestServiceIntf.class, ((StaticMicroservice) latestMicroservice).getSchemaIntfCls()); + Assert.assertEquals(1, versionRule.getInstances().size()); + Assert.assertSame(instance, versionRule.getInstances().get(instance.getInstanceId())); + Assert.assertEquals(SERVICE_ID_PREFIX + serviceVersion, instance.getServiceId()); + Assert.assertTrue(instance.getInstanceId().startsWith(SERVICE_ID_PREFIX + serviceVersion + "-")); + } + + @Test + public void addInstancesAndGetVersionRuleMultiTimes() { + StaticMicroserviceVersions staticMicroserviceVersions = createStaticMicroserviceVersions(); + + // add instance1 with version 1.1.0 + MicroserviceInstance instance1 = new MicroserviceInstance(); + staticMicroserviceVersions.addInstances("1.1.0", Collections.singletonList(instance1)); + + MicroserviceVersionRule versionRule = staticMicroserviceVersions.getOrCreateMicroserviceVersionRule("0.0.0+"); + MicroserviceVersion latestMicroserviceVersion = versionRule.getLatestMicroserviceVersion(); + Assert.assertEquals(new Version("1.1.0"), latestMicroserviceVersion.getVersion()); + Assert.assertEquals(1, versionRule.getInstances().size()); + Assert.assertSame(instance1, versionRule.getInstances().get(instance1.getInstanceId())); + + // add instance2 with version 1.1.1 + MicroserviceInstance instance2 = new MicroserviceInstance(); + staticMicroserviceVersions.addInstances("1.1.1", Collections.singletonList(instance2)); + + versionRule = staticMicroserviceVersions.getOrCreateMicroserviceVersionRule("0.0.0+"); + latestMicroserviceVersion = versionRule.getLatestMicroserviceVersion(); + Assert.assertEquals(new Version("1.1.1"), latestMicroserviceVersion.getVersion()); + Assert.assertEquals(2, versionRule.getInstances().size()); + Assert.assertSame(instance1, versionRule.getInstances().get(instance1.getInstanceId())); + Assert.assertSame(instance2, versionRule.getInstances().get(instance2.getInstanceId())); + + // add instance3 with version 0.1.0 + MicroserviceInstance instance3 = new MicroserviceInstance(); + staticMicroserviceVersions.addInstances("0.1.0", Collections.singletonList(instance3)); + + versionRule = staticMicroserviceVersions.getOrCreateMicroserviceVersionRule("0.0.0+"); + latestMicroserviceVersion = versionRule.getLatestMicroserviceVersion(); + Assert.assertEquals(new Version("1.1.1"), latestMicroserviceVersion.getVersion()); + Assert.assertEquals(3, versionRule.getInstances().size()); + Assert.assertSame(instance1, versionRule.getInstances().get(instance1.getInstanceId())); + Assert.assertSame(instance2, versionRule.getInstances().get(instance2.getInstanceId())); + Assert.assertSame(instance3, versionRule.getInstances().get(instance3.getInstanceId())); + + // instance3 should be filtered out + versionRule = staticMicroserviceVersions.getOrCreateMicroserviceVersionRule("1.0.0+"); + latestMicroserviceVersion = versionRule.getLatestMicroserviceVersion(); + Assert.assertEquals(new Version("1.1.1"), latestMicroserviceVersion.getVersion()); + Assert.assertEquals(2, versionRule.getInstances().size()); + Assert.assertSame(instance1, versionRule.getInstances().get(instance1.getInstanceId())); + Assert.assertSame(instance2, versionRule.getInstances().get(instance2.getInstanceId())); + Assert.assertNull(versionRule.getInstances().get(instance3.getInstanceId())); + } + + private StaticMicroserviceVersions createStaticMicroserviceVersions() { + EventBus eventBus = new EventBus(); + AppManager appManager = new AppManager(eventBus); + appManager.setStaticMicroserviceVersionFactory(microservice -> new MockUp<MicroserviceVersion>() { + @Mock + public Version getVersion() { + return VersionUtils.getOrCreate(microservice.getVersion()); + } + + @Mock + public Microservice getMicroservice() { + return microservice; + } + }.getMockInstance()); + return new StaticMicroserviceVersions( + appManager, APP_ID, MICROSERVICE_NAME, TestServiceIntf.class); + } + + private interface TestServiceIntf { + } +} \ No newline at end of file diff --git a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestAppManager.java b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestAppManager.java index 33616899e..e76d23bbe 100644 --- a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestAppManager.java +++ b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestAppManager.java @@ -20,8 +20,10 @@ import java.util.Collections; import org.apache.servicecomb.serviceregistry.RegistryUtils; +import org.apache.servicecomb.serviceregistry.api.registry.StaticMicroservice; import org.apache.servicecomb.serviceregistry.api.response.FindInstancesResponse; import org.apache.servicecomb.serviceregistry.client.http.MicroserviceInstances; +import org.apache.servicecomb.serviceregistry.config.ServiceRegistryConfig; import org.apache.servicecomb.serviceregistry.definition.DefinitionConst; import org.junit.After; import org.junit.Assert; @@ -30,7 +32,10 @@ import com.google.common.eventbus.EventBus; +import mockit.Deencapsulation; import mockit.Expectations; +import mockit.Mock; +import mockit.MockUp; import mockit.Mocked; public class TestAppManager { @@ -97,4 +102,26 @@ public void setMicroserviceVersionFactory(@Mocked MicroserviceVersionFactory mic Assert.assertSame(microserviceVersionFactory, appManager.getMicroserviceVersionFactory()); } + + @Test + public void getStaticMicroserviceVersionFactory() { + new MockUp<ServiceRegistryConfig>() { + @Mock + String getStaticMicroserviceVersionFactory() { + return TestStaticMicroserviceVersionFactory.class.getName(); + } + }; + + Assert.assertNull(Deencapsulation.getField(appManager, "staticMicroserviceVersionFactory")); + + Assert.assertEquals(TestStaticMicroserviceVersionFactory.class, + appManager.getStaticMicroserviceVersionFactory().getClass()); + } + + static class TestStaticMicroserviceVersionFactory implements StaticMicroserviceVersionFactory { + @Override + public MicroserviceVersion create(StaticMicroservice microservice) { + return null; + } + } } diff --git a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestMicroserviceVersion.java b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestMicroserviceVersion.java index 5b5f23aca..02b7ff54c 100644 --- a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestMicroserviceVersion.java +++ b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/consumer/TestMicroserviceVersion.java @@ -17,8 +17,9 @@ package org.apache.servicecomb.serviceregistry.consumer; - import org.apache.servicecomb.serviceregistry.RegistryUtils; +import org.apache.servicecomb.serviceregistry.api.registry.Microservice; +import org.apache.servicecomb.serviceregistry.version.Version; import org.hamcrest.Matchers; import org.junit.Assert; import org.junit.Rule; @@ -51,4 +52,15 @@ public void constructNormal() { Assert.assertEquals("1", microserviceVersion.getMicroservice().getServiceId()); Assert.assertEquals("1.0.0", microserviceVersion.getVersion().getVersion()); } + + @Test + public void constructByMicroservice() { + Microservice microservice = new Microservice(); + String version = "1.2.1"; + microservice.setVersion(version); + MicroserviceVersion microserviceVersion = new MicroserviceVersion(microservice); + + Assert.assertSame(microservice, microserviceVersion.getMicroservice()); + Assert.assertEquals(new Version(version), microserviceVersion.getVersion()); + } } diff --git a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/registry/TestAbstractServiceRegistry.java b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/registry/TestAbstractServiceRegistry.java index b223c3d5d..e11a05808 100644 --- a/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/registry/TestAbstractServiceRegistry.java +++ b/service-registry/src/test/java/org/apache/servicecomb/serviceregistry/registry/TestAbstractServiceRegistry.java @@ -17,19 +17,35 @@ package org.apache.servicecomb.serviceregistry.registry; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; + +import org.apache.servicecomb.serviceregistry.RegistryUtils; +import org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance; import org.apache.servicecomb.serviceregistry.client.ServiceRegistryClient; import org.apache.servicecomb.serviceregistry.config.ServiceRegistryConfig; +import org.apache.servicecomb.serviceregistry.consumer.AppManager; import org.apache.servicecomb.serviceregistry.consumer.DefaultMicroserviceVersionFactory; +import org.apache.servicecomb.serviceregistry.consumer.MicroserviceManager; +import org.apache.servicecomb.serviceregistry.consumer.MicroserviceVersion; +import org.apache.servicecomb.serviceregistry.consumer.MicroserviceVersions; +import org.apache.servicecomb.serviceregistry.consumer.StaticMicroserviceVersionFactory; import org.apache.servicecomb.serviceregistry.definition.MicroserviceDefinition; import org.hamcrest.Matchers; +import org.junit.After; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.mockito.Mockito; import com.google.common.eventbus.EventBus; +import mockit.Deencapsulation; import mockit.Expectations; import mockit.Mocked; @@ -70,6 +86,17 @@ protected ServiceRegistryClient createServiceRegistryClient() { public void setup() { registry = new AbstractServiceRegistryForTest(eventBus, serviceRegistryConfig, microserviceDefinition); + RegistryUtils.setServiceRegistry(registry); + } + + @After + public void tearDown() { + registry.appManager = null; + } + + @AfterClass + public static void afterClass() { + RegistryUtils.setServiceRegistry(null); } @Test @@ -96,8 +123,7 @@ public void initAppManagerSpecialMicroserviceVersionFactoryNormal() } @Test - public void initAppManagerSpecialMicroserviceVersionFactoryFailed() - throws InstantiationException, IllegalAccessException, ClassNotFoundException { + public void initAppManagerSpecialMicroserviceVersionFactoryFailed() { new Expectations() { { serviceRegistryConfig.getMicroserviceVersionFactory(); @@ -109,4 +135,70 @@ public void initAppManagerSpecialMicroserviceVersionFactoryFailed() registry.init(); } + + @Test + public void registryMicroserviceMapping() { + String testServiceName = "testService"; + final String testVersion = "1.0.1"; + + HashMap<String, MicroserviceVersions> versionsByName = prepareForMicroserviceMappingRegistry(); + + ArrayList<MicroserviceInstance> instancesParam = new ArrayList<>(); + instancesParam.add(new MicroserviceInstance()); + registry.registerMicroserviceMapping(testServiceName, testVersion, instancesParam, Test3rdPartyServiceIntf.class); + + MicroserviceVersions microserviceVersions = versionsByName.get(testServiceName); + List<MicroserviceInstance> instances = Deencapsulation.getField(microserviceVersions, "instances"); + Assert.assertEquals(1, instances.size()); + Assert.assertSame(instancesParam.get(0), instances.get(0)); + + // nothing will happen if register repeatedly + List<MicroserviceInstance> newInstancesParam = new ArrayList<>(); + newInstancesParam.add(new MicroserviceInstance()); + registry.registerMicroserviceMapping( + testServiceName, testVersion, newInstancesParam, Test3rdPartyServiceIntf.class); + + microserviceVersions = versionsByName.get(testServiceName); + instances = Deencapsulation.getField(microserviceVersions, "instances"); + Assert.assertEquals(1, instances.size()); + Assert.assertSame(instancesParam.get(0), instances.get(0)); + } + + @Test + public void registryMicroserviceMappingByEndpoints() { + String testServiceName = "testService"; + final String testVersion = "1.0.1"; + + HashMap<String, MicroserviceVersions> versionByName = prepareForMicroserviceMappingRegistry(); + + registry.registerMicroserviceMappingByEndpoints(testServiceName, testVersion, + Arrays.asList("cse://127.0.0.1:8080", "cse://127.0.0.1:8081"), Test3rdPartyServiceIntf.class); + + MicroserviceVersions microserviceVersions = versionByName.get(testServiceName); + List<MicroserviceInstance> instances = Deencapsulation.getField(microserviceVersions, "instances"); + Assert.assertEquals(2, instances.size()); + Assert.assertEquals("cse://127.0.0.1:8080", instances.get(0).getEndpoints().get(0)); + Assert.assertEquals("cse://127.0.0.1:8081", instances.get(1).getEndpoints().get(0)); + } + + private HashMap<String, MicroserviceVersions> prepareForMicroserviceMappingRegistry() { + registry.appManager = Mockito.mock(AppManager.class); + MicroserviceManager microserviceManager = Mockito.mock(MicroserviceManager.class); + StaticMicroserviceVersionFactory staticMicroserviceVersionFactory = + Mockito.mock(StaticMicroserviceVersionFactory.class); + HashMap<String, MicroserviceVersions> versionsByName = new HashMap<>(); + + Mockito.when(registry.appManager.getOrCreateMicroserviceManager(this.appId)).thenReturn(microserviceManager); + Mockito.when(registry.appManager.getEventBus()).thenReturn(Mockito.mock(EventBus.class)); + Mockito.when(registry.appManager.getStaticMicroserviceVersionFactory()) + .thenReturn(staticMicroserviceVersionFactory); + Mockito.when(staticMicroserviceVersionFactory.create(Mockito.any())) + .thenReturn(Mockito.mock(MicroserviceVersion.class)); + + Mockito.when(microserviceManager.getVersionsByName()).thenReturn(versionsByName); + return versionsByName; + } + + private interface Test3rdPartyServiceIntf { + } } diff --git a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/SwaggerGenerator.java b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/SwaggerGenerator.java index aa472fd25..8b51b9b34 100644 --- a/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/SwaggerGenerator.java +++ b/swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecomb/swagger/generator/core/SwaggerGenerator.java @@ -27,6 +27,7 @@ import java.util.Locale; import java.util.Map; import java.util.Set; +import java.util.concurrent.CompletableFuture; import javax.ws.rs.core.MediaType; @@ -203,7 +204,7 @@ private void correctInfo() { } protected void setJavaInterface(Info info, Class<?> cls) { - if (cls.isInterface()) { + if (cls.isInterface() && !isInterfaceReactive(cls)) { info.setVendorExtension(SwaggerConst.EXT_JAVA_INTF, cls.getName()); return; } @@ -218,6 +219,26 @@ protected void setJavaInterface(Info info, Class<?> cls) { info.setVendorExtension(SwaggerConst.EXT_JAVA_INTF, intfName); } + /** + * Whether this interface class is reactive. + * This is used for the situation that the {@code interfaceCls} may be used as swagger interface directly + */ + private boolean isInterfaceReactive(Class<?> interfaceCls) { + for (Method method : interfaceCls.getDeclaredMethods()) { + if (isSkipMethod(method)) { + continue; + } + if (CompletableFuture.class.isAssignableFrom(method.getReturnType())) { + return true; + } + } + return false; + } + + /** + * Whether this method should be processed as a swagger operation + * @return true if this isn't a swagger operation; otherwise, false. + */ protected boolean isSkipMethod(Method method) { if (method.getDeclaringClass().getName().equals(Object.class.getName())) { return true; diff --git a/transports/transport-rest/transport-rest-vertx/src/test/java/org/apache/servicecomb/transport/rest/vertx/accesslog/impl/AccessLogHandlerTest.java b/transports/transport-rest/transport-rest-vertx/src/test/java/org/apache/servicecomb/transport/rest/vertx/accesslog/impl/AccessLogHandlerTest.java index efd4ee2b7..0ef62e508 100644 --- a/transports/transport-rest/transport-rest-vertx/src/test/java/org/apache/servicecomb/transport/rest/vertx/accesslog/impl/AccessLogHandlerTest.java +++ b/transports/transport-rest/transport-rest-vertx/src/test/java/org/apache/servicecomb/transport/rest/vertx/accesslog/impl/AccessLogHandlerTest.java @@ -18,6 +18,7 @@ package org.apache.servicecomb.transport.rest.vertx.accesslog.impl; import java.util.HashSet; +import java.util.concurrent.TimeUnit; import javax.xml.ws.Holder; @@ -78,9 +79,13 @@ public int getStatusCode() { Holder<Integer> counter = new Holder<>(); counter.value = 0; + String testThreadName = Thread.currentThread().getName(); new MockUp<System>() { @Mock long currentTimeMillis() { + if (!testThreadName.equals(Thread.currentThread().getName())) { + return TimeUnit.NANOSECONDS.toMillis(System.nanoTime()); + } if (counter.value < 1) { ++counter.value; return 1L; ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: us...@infra.apache.org > Invoke 3rd party service > ------------------------ > > Key: SCB-926 > URL: https://issues.apache.org/jira/browse/SCB-926 > Project: Apache ServiceComb > Issue Type: New Feature > Affects Versions: java-chassis-1.1.0 > Reporter: YaoHaishi > Assignee: YaoHaishi > Priority: Major > > Provide a interface to let users specify 3rd party services' endpoints and > let users can invoke 3rd party service like invoking the ServiceComb > microservice. -- This message was sent by Atlassian JIRA (v7.6.3#76005)