diff --git a/demo/demo-pojo/pojo-client/src/main/resources/META-INF/spring/pojo.client.bean.xml b/demo/demo-pojo/pojo-client/src/main/resources/META-INF/spring/pojo.client.bean.xml index 3ba39d33f4d..5a7faa49fd6 100644 --- a/demo/demo-pojo/pojo-client/src/main/resources/META-INF/spring/pojo.client.bean.xml +++ b/demo/demo-pojo/pojo-client/src/main/resources/META-INF/spring/pojo.client.bean.xml @@ -27,10 +27,6 @@ - - - diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/resources/META-INF/spring/pojo.client.bean.xml b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/resources/META-INF/spring/pojo.client.bean.xml index 8e715fc0b9f..98a273b5137 100644 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/resources/META-INF/spring/pojo.client.bean.xml +++ b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/resources/META-INF/spring/pojo.client.bean.xml @@ -24,9 +24,6 @@ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.huawei.com/schema/paas/cse/rpc classpath:META-INF/spring/spring-paas-cse-rpc.xsd"> - - diff --git a/providers/provider-pojo/src/main/java/io/servicecomb/provider/pojo/Invoker.java b/providers/provider-pojo/src/main/java/io/servicecomb/provider/pojo/Invoker.java index 28413193744..00d7e7951b3 100644 --- a/providers/provider-pojo/src/main/java/io/servicecomb/provider/pojo/Invoker.java +++ b/providers/provider-pojo/src/main/java/io/servicecomb/provider/pojo/Invoker.java @@ -16,7 +16,14 @@ package io.servicecomb.provider.pojo; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; + +import org.springframework.util.StringUtils; + +import io.servicecomb.core.CseContext; import io.servicecomb.core.Invocation; +import io.servicecomb.core.definition.MicroserviceMeta; import io.servicecomb.core.definition.SchemaMeta; import io.servicecomb.core.invocation.InvocationFactory; import io.servicecomb.core.provider.consumer.InvokerUtils; @@ -25,27 +32,64 @@ import io.servicecomb.swagger.engine.SwaggerConsumerOperation; import io.servicecomb.swagger.invocation.Response; import io.servicecomb.swagger.invocation.exception.ExceptionFactory; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; public class Invoker implements InvocationHandler { + // 原始数据 + private String microserviceName; + + private String schemaId; + + private Class consumerIntf; + + // 生成的数据 private SchemaMeta schemaMeta; - private ReferenceConfig config; + private ReferenceConfig referenceConfig; private SwaggerConsumer swaggerConsumer; - public void init(ReferenceConfig config, SchemaMeta schemaMeta, - SwaggerConsumer swaggerConsumer) { - this.config = config; - this.schemaMeta = schemaMeta; - this.swaggerConsumer = swaggerConsumer; + public Invoker(String microserviceName, String schemaId, Class consumerIntf) { + this.microserviceName = microserviceName; + this.schemaId = schemaId; + this.consumerIntf = consumerIntf; + } + + public Class getConsumerIntf() { + return consumerIntf; + } + + public void prepare() { + referenceConfig = CseContext.getInstance().getConsumerProviderManager().getReferenceConfig(microserviceName); + MicroserviceMeta microserviceMeta = referenceConfig.getMicroserviceMeta(); + + if (StringUtils.isEmpty(schemaId)) { + // 未指定schemaId,看看consumer接口是否等于契约接口 + schemaMeta = microserviceMeta.findSchemaMeta(consumerIntf); + if (schemaMeta == null) { + // 尝试用consumer接口名作为schemaId + schemaId = consumerIntf.getName(); + schemaMeta = microserviceMeta.ensureFindSchemaMeta(schemaId); + } + } else { + schemaMeta = microserviceMeta.ensureFindSchemaMeta(schemaId); + } + + if (consumerIntf == null) { + consumerIntf = schemaMeta.getSwaggerIntf(); + } + + this.swaggerConsumer = CseContext.getInstance().getSwaggerEnvironment().createConsumer(consumerIntf, + schemaMeta.getSwaggerIntf()); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + if (swaggerConsumer == null) { + prepare(); + } + Invocation invocation = - InvocationFactory.forConsumer(config, schemaMeta, method.getName(), null); + InvocationFactory.forConsumer(referenceConfig, schemaMeta, method.getName(), null); SwaggerConsumerOperation consumerOperation = swaggerConsumer.findOperation(method.getName()); consumerOperation.getArgumentsMapper().toInvocation(args, invocation); diff --git a/providers/provider-pojo/src/main/java/io/servicecomb/provider/pojo/reference/PojoReferenceMeta.java b/providers/provider-pojo/src/main/java/io/servicecomb/provider/pojo/reference/PojoReferenceMeta.java index 565e1d300c1..443851bbae4 100644 --- a/providers/provider-pojo/src/main/java/io/servicecomb/provider/pojo/reference/PojoReferenceMeta.java +++ b/providers/provider-pojo/src/main/java/io/servicecomb/provider/pojo/reference/PojoReferenceMeta.java @@ -16,21 +16,22 @@ package io.servicecomb.provider.pojo.reference; -import io.servicecomb.core.CseContext; -import io.servicecomb.core.definition.MicroserviceMeta; -import io.servicecomb.core.definition.SchemaMeta; -import io.servicecomb.core.provider.CseBeanPostProcessor.EmptyBeanPostProcessor; -import io.servicecomb.core.provider.consumer.ReferenceConfig; -import io.servicecomb.foundation.common.exceptions.ServiceCombException; -import io.servicecomb.provider.pojo.Invoker; -import io.servicecomb.swagger.engine.SwaggerConsumer; import java.lang.reflect.Proxy; + import javax.inject.Inject; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; -import org.springframework.util.StringUtils; + +import io.servicecomb.core.provider.CseBeanPostProcessor.EmptyBeanPostProcessor; +import io.servicecomb.foundation.common.exceptions.ServiceCombException; +import io.servicecomb.provider.pojo.Invoker; public class PojoReferenceMeta implements FactoryBean, InitializingBean, EmptyBeanPostProcessor { + private static final Logger LOGGER = LoggerFactory.getLogger(PojoReferenceMeta.class); + // 原始数据 private String microserviceName; @@ -41,60 +42,25 @@ public class PojoReferenceMeta implements FactoryBean, InitializingBean, @Inject private PojoConsumers pojoConsumers; - // 生成的数据 - private ReferenceConfig referenceConfig; - - private SchemaMeta schemaMeta; - - private SwaggerConsumer swaggerConsumer; - // 根据intf创建出来的动态代理 // TODO:未实现本地优先(本地场景下,应该跳过handler机制) private Object proxy; - private final Invoker invoker = new Invoker(); - - private void prepare() { - referenceConfig = CseContext.getInstance().getConsumerProviderManager().getReferenceConfig(microserviceName); - MicroserviceMeta microserviceMeta = referenceConfig.getMicroserviceMeta(); - - if (StringUtils.isEmpty(schemaId)) { - // 未指定schemaId,看看consumer接口是否等于契约接口 - schemaMeta = microserviceMeta.findSchemaMeta(consumerIntf); - if (schemaMeta == null) { - // 尝试用consumer接口名作为schemaId - schemaId = consumerIntf.getName(); - schemaMeta = microserviceMeta.ensureFindSchemaMeta(schemaId); - } - } else { - schemaMeta = microserviceMeta.ensureFindSchemaMeta(schemaId); - } - - if (consumerIntf == null) { - consumerIntf = schemaMeta.getSwaggerIntf(); - } - - this.swaggerConsumer = CseContext.getInstance().getSwaggerEnvironment().createConsumer(consumerIntf, - schemaMeta.getSwaggerIntf()); - } + private Invoker invoker; public void createInvoker() { - prepare(); + // only consumerIntf is null need to do query contract during boot + if (consumerIntf != null) { + return; + } - invoker.init(getReferenceConfig(), - getSchemaMeta(), - swaggerConsumer); + invoker.prepare(); + this.consumerIntf = invoker.getConsumerIntf(); createProxy(); } protected void createProxy() { - if (proxy == null) { - proxy = Proxy.newProxyInstance(consumerIntf.getClassLoader(), new Class[] {consumerIntf}, invoker); - } - } - - public ReferenceConfig getReferenceConfig() { - return referenceConfig; + proxy = Proxy.newProxyInstance(consumerIntf.getClassLoader(), new Class[] {consumerIntf}, invoker); } public Object getProxy() { @@ -105,12 +71,10 @@ public Object getProxy() { public Object getObject() { if (proxy == null) { throw new ServiceCombException( - String.format("Rpc reference %s with service name [%s] and schema [%s] is not populated", - consumerIntf == null? "" : consumerIntf, - microserviceName, - schemaId - ) - ); + String.format("Rpc reference %s with service name [%s] and schema [%s] is not populated", + consumerIntf == null ? "" : consumerIntf, + microserviceName, + schemaId)); } return proxy; } @@ -120,10 +84,6 @@ public Class getObjectType() { return consumerIntf; } - public Class getConsumerIntf() { - return consumerIntf; - } - @Override public boolean isSingleton() { return true; @@ -133,10 +93,6 @@ public void setConsumerIntf(Class intf) { this.consumerIntf = intf; } - public SchemaMeta getSchemaMeta() { - return schemaMeta; - } - public void setMicroserviceName(String microserviceName) { this.microserviceName = microserviceName; } @@ -147,8 +103,13 @@ public void setSchemaId(String schemaId) { @Override public void afterPropertiesSet() { + invoker = new Invoker(microserviceName, schemaId, consumerIntf); if (consumerIntf != null) { createProxy(); + } else { + LOGGER.warn("Deprecated usage. xml definition cse:rpc-reference missed \"interface\" property, " + + "to support this, must query schema ids from service center in blocking mode during boot until got it, " + + "if there is loop dependency between microservices, will cause the microservices can not boot."); } if (pojoConsumers != null) { diff --git a/providers/provider-pojo/src/test/java/io/servicecomb/provider/pojo/TestInvoker.java b/providers/provider-pojo/src/test/java/io/servicecomb/provider/pojo/TestInvoker.java new file mode 100644 index 00000000000..cafcfde0bb9 --- /dev/null +++ b/providers/provider-pojo/src/test/java/io/servicecomb/provider/pojo/TestInvoker.java @@ -0,0 +1,110 @@ +/* + * Copyright 2017 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.servicecomb.provider.pojo; + +import org.junit.Assert; +import org.junit.Test; + +import io.servicecomb.core.CseContext; +import io.servicecomb.core.definition.MicroserviceMeta; +import io.servicecomb.core.definition.schema.ConsumerSchemaFactory; +import io.servicecomb.core.provider.consumer.ConsumerProviderManager; +import io.servicecomb.core.provider.consumer.ReferenceConfig; +import io.servicecomb.swagger.engine.SwaggerConsumer; +import io.servicecomb.swagger.engine.bootstrap.BootstrapNormal; +import mockit.Deencapsulation; +import mockit.Expectations; +import mockit.Injectable; + +public class TestInvoker { + @Test + public void testNormalSchemaId(@Injectable ConsumerProviderManager manager, + @Injectable ReferenceConfig config, + @Injectable MicroserviceMeta microserviceMeta, + @Injectable ConsumerSchemaFactory factory) { + new Expectations() { + { + manager.getReferenceConfig("test"); + result = config; + config.getMicroserviceMeta(); + result = microserviceMeta; + microserviceMeta.ensureFindSchemaMeta("schemaId"); + } + }; + CseContext.getInstance().setConsumerProviderManager(manager); + CseContext.getInstance().setConsumerSchemaFactory(factory); + CseContext.getInstance().setSwaggerEnvironment(new BootstrapNormal().boot()); + + Invoker invoker = new Invoker("test", "schemaId", IPerson.class); + invoker.prepare(); + + SwaggerConsumer swaggerConsumer = Deencapsulation.getField(invoker, "swaggerConsumer"); + Assert.assertEquals(IPerson.class, swaggerConsumer.getConsumerIntf()); + } + + @Test + public void testFindSchemaByConsumerInterface(@Injectable ConsumerProviderManager manager, + @Injectable ReferenceConfig config, + @Injectable MicroserviceMeta microserviceMeta, + @Injectable ConsumerSchemaFactory factory) { + new Expectations() { + { + manager.getReferenceConfig("test"); + result = config; + config.getMicroserviceMeta(); + result = microserviceMeta; + microserviceMeta.findSchemaMeta(IPerson.class); + } + }; + CseContext.getInstance().setConsumerProviderManager(manager); + CseContext.getInstance().setConsumerSchemaFactory(factory); + CseContext.getInstance().setSwaggerEnvironment(new BootstrapNormal().boot()); + + Invoker invoker = new Invoker("test", null, IPerson.class); + invoker.prepare(); + + SwaggerConsumer swaggerConsumer = Deencapsulation.getField(invoker, "swaggerConsumer"); + Assert.assertEquals(IPerson.class, swaggerConsumer.getConsumerIntf()); + } + + @Test + public void testConsumerInterfaceAsSchemaId(@Injectable ConsumerProviderManager manager, + @Injectable ReferenceConfig config, + @Injectable MicroserviceMeta microserviceMeta, + @Injectable ConsumerSchemaFactory factory) { + new Expectations() { + { + manager.getReferenceConfig("test"); + result = config; + config.getMicroserviceMeta(); + result = microserviceMeta; + microserviceMeta.findSchemaMeta(IPerson.class); + result = null; + microserviceMeta.ensureFindSchemaMeta(IPerson.class.getName()); + } + }; + CseContext.getInstance().setConsumerProviderManager(manager); + CseContext.getInstance().setConsumerSchemaFactory(factory); + CseContext.getInstance().setSwaggerEnvironment(new BootstrapNormal().boot()); + + Invoker invoker = new Invoker("test", null, IPerson.class); + invoker.prepare(); + + SwaggerConsumer swaggerConsumer = Deencapsulation.getField(invoker, "swaggerConsumer"); + Assert.assertEquals(IPerson.class, swaggerConsumer.getConsumerIntf()); + } +} diff --git a/providers/provider-pojo/src/test/java/io/servicecomb/provider/pojo/reference/PojoReferenceMetaTest.java b/providers/provider-pojo/src/test/java/io/servicecomb/provider/pojo/reference/PojoReferenceMetaTest.java index 88eb447c99c..640c55cf14d 100644 --- a/providers/provider-pojo/src/test/java/io/servicecomb/provider/pojo/reference/PojoReferenceMetaTest.java +++ b/providers/provider-pojo/src/test/java/io/servicecomb/provider/pojo/reference/PojoReferenceMetaTest.java @@ -19,73 +19,81 @@ import static org.hamcrest.core.IsInstanceOf.instanceOf; import static org.junit.Assert.assertThat; +import org.junit.Assert; +import org.junit.Test; + import io.servicecomb.core.CseContext; import io.servicecomb.core.definition.MicroserviceMeta; +import io.servicecomb.core.definition.SchemaMeta; import io.servicecomb.core.definition.schema.ConsumerSchemaFactory; import io.servicecomb.core.provider.consumer.ConsumerProviderManager; import io.servicecomb.core.provider.consumer.ReferenceConfig; +import io.servicecomb.foundation.common.exceptions.ServiceCombException; import io.servicecomb.provider.pojo.IPerson; import io.servicecomb.swagger.engine.bootstrap.BootstrapNormal; import mockit.Expectations; import mockit.Injectable; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; public class PojoReferenceMetaTest { - - private PojoReferenceMeta pojoReferenceMeta = new PojoReferenceMeta(); - - @Before - public void setUp() throws Exception { + @Test + public void testHasConsumerInterface() { + PojoReferenceMeta pojoReferenceMeta = new PojoReferenceMeta(); pojoReferenceMeta.setMicroserviceName("test"); pojoReferenceMeta.setSchemaId("schemaId"); pojoReferenceMeta.setConsumerIntf(IPerson.class); - } - @Test - public void testGetSchemaMeta() throws Exception { - Assert.assertEquals(null, pojoReferenceMeta.getSchemaMeta()); - } + pojoReferenceMeta.afterPropertiesSet(); - @Test - public void testGetObjectType() throws Exception { Assert.assertEquals(IPerson.class, pojoReferenceMeta.getObjectType()); - } + Object proxy = pojoReferenceMeta.getProxy(); + assertThat(proxy, instanceOf(IPerson.class)); + Assert.assertEquals(true, pojoReferenceMeta.isSingleton()); - @Test - public void testGetProxy() throws Exception { - pojoReferenceMeta.createProxy(); - assertThat(pojoReferenceMeta.getProxy(), instanceOf(IPerson.class)); + // not recreate proxy + pojoReferenceMeta.createInvoker(); + Assert.assertSame(proxy, pojoReferenceMeta.getProxy()); } @Test - public void testIsSingleton() throws Exception { - Assert.assertEquals(true, pojoReferenceMeta.isSingleton()); + public void testNoConsumerInterface() { + PojoReferenceMeta pojoReferenceMeta = new PojoReferenceMeta(); + pojoReferenceMeta.setMicroserviceName("test"); + pojoReferenceMeta.setSchemaId("schemaId"); + + pojoReferenceMeta.afterPropertiesSet(); + + try { + pojoReferenceMeta.getProxy(); + Assert.fail("must throw exception"); + } catch (ServiceCombException e) { + Assert.assertEquals( + "Rpc reference with service name [test] and schema [schemaId] is not populated", + e.getMessage()); + } } @Test - public void test(@Injectable ConsumerProviderManager manager, + public void testNoConsumerInterfaceCreateInvoke(@Injectable ConsumerProviderManager manager, @Injectable ReferenceConfig config, @Injectable MicroserviceMeta microserviceMeta, - @Injectable ConsumerSchemaFactory factory) { + @Injectable ConsumerSchemaFactory factory, + @Injectable SchemaMeta schemaMeta) { new Expectations() { { - manager.getReferenceConfig("test"); - result = config; - config.getMicroserviceMeta(); - result = microserviceMeta; - microserviceMeta.ensureFindSchemaMeta("schemaId"); + schemaMeta.getSwaggerIntf(); + result = IPerson.class; } }; CseContext.getInstance().setConsumerProviderManager(manager); CseContext.getInstance().setConsumerSchemaFactory(factory); CseContext.getInstance().setSwaggerEnvironment(new BootstrapNormal().boot()); - Assert.assertEquals(null, pojoReferenceMeta.getReferenceConfig()); - Assert.assertEquals(IPerson.class, pojoReferenceMeta.getConsumerIntf()); - pojoReferenceMeta.createInvoker(); + PojoReferenceMeta pojoReferenceMeta = new PojoReferenceMeta(); + pojoReferenceMeta.setMicroserviceName("test"); + pojoReferenceMeta.setSchemaId("schemaId"); pojoReferenceMeta.afterPropertiesSet(); - Assert.assertEquals(config, pojoReferenceMeta.getReferenceConfig()); + + pojoReferenceMeta.createInvoker(); + assertThat(pojoReferenceMeta.getProxy(), instanceOf(IPerson.class)); } } diff --git a/providers/provider-rest-common/src/main/java/io/servicecomb/provider/rest/common/RestConsumerProvider.java b/providers/provider-rest-common/src/main/java/io/servicecomb/provider/rest/common/RestConsumerProvider.java index 3a8e30e65fc..fcab1befd47 100644 --- a/providers/provider-rest-common/src/main/java/io/servicecomb/provider/rest/common/RestConsumerProvider.java +++ b/providers/provider-rest-common/src/main/java/io/servicecomb/provider/rest/common/RestConsumerProvider.java @@ -27,8 +27,4 @@ public class RestConsumerProvider extends AbstractConsumerProvider { public String getName() { return RestConst.REST; } - - @Override - public void init() throws Exception { - } } diff --git a/transports/transport-highway/src/main/java/io/servicecomb/transport/highway/HighwayClientConnection.java b/transports/transport-highway/src/main/java/io/servicecomb/transport/highway/HighwayClientConnection.java index 649a09cb80f..f2cd3ced019 100644 --- a/transports/transport-highway/src/main/java/io/servicecomb/transport/highway/HighwayClientConnection.java +++ b/transports/transport-highway/src/main/java/io/servicecomb/transport/highway/HighwayClientConnection.java @@ -18,8 +18,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import io.protostuff.LinkedBuffer; -import io.protostuff.ProtobufOutput; import io.protostuff.runtime.ProtobufFeature; import io.servicecomb.foundation.vertx.client.tcp.AbstractTcpClientPackage; import io.servicecomb.foundation.vertx.client.tcp.TcpClientConfig; @@ -50,17 +48,12 @@ public ProtobufFeature getProtobufFeature() { @Override protected TcpOutputStream createLogin() { try { - LinkedBuffer linkedBuffer = LinkedBuffer.allocate(); - ProtobufOutput output = new ProtobufOutput(linkedBuffer); - RequestHeader header = new RequestHeader(); header.setMsgType(MsgType.LOGIN); - header.writeObject(output); LoginRequest login = new LoginRequest(); login.setProtocol(HighwayTransport.NAME); login.setUseProtobufMapCodec(true); - login.writeObject(output); HighwayOutputStream os = new HighwayOutputStream(AbstractTcpClientPackage.getAndIncRequestId(), null); os.write(header, LoginRequest.getLoginRequestSchema(), login);