This is an automated email from the ASF dual-hosted git repository.
littlecui pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git
The following commit(s) were added to refs/heads/master by this push:
new 7e661e38a add feature , request can be handle by self-defined class
(#3377)
7e661e38a is described below
commit 7e661e38ac5244b3391b28bf5acebfaaf43929e3
Author: gudelian941 <[email protected]>
AuthorDate: Fri Oct 14 17:35:46 2022 +0800
add feature , request can be handle by self-defined class (#3377)
* add feature , request can be handle by self-defined class
* refactor for advice
* refactor for advice
* refactor for advice
* refactor for advice
* add apache license information for file header
* fix issue
* rename function
* modify for suggestion
* modify for suggession
* modify for suggestion
* resolv checkstyle issue
* fix issue
---
.../governance/marker/CustomMatcher.java | 41 +++++++++
.../governance/marker/GovernanceRequest.java | 17 ++++
.../servicecomb/governance/marker/Matcher.java | 10 +++
.../governance/marker/RequestProcessor.java | 85 +++++++++++++++++-
.../servicecomb/governance/utils/CustomMatch.java | 24 +++++
.../servicecomb/governance/CustomMatchTest.java | 100 +++++++++++++++++++++
.../governance/mockclasses/ClassNotImplments.java | 28 ++++++
.../mockclasses/ClassWithAnnotation.java | 39 ++++++++
.../governance/mockclasses/CustomMatchDemo.java | 33 +++++++
.../service/MockConfigurationForCustomMatcher.java | 26 ++++++
.../service/MockProfileClassUserService.java | 27 ++++++
11 files changed, 428 insertions(+), 2 deletions(-)
diff --git
a/governance/src/main/java/org/apache/servicecomb/governance/marker/CustomMatcher.java
b/governance/src/main/java/org/apache/servicecomb/governance/marker/CustomMatcher.java
new file mode 100644
index 000000000..c6ec53637
--- /dev/null
+++
b/governance/src/main/java/org/apache/servicecomb/governance/marker/CustomMatcher.java
@@ -0,0 +1,41 @@
+/*
+ * 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.governance.marker;
+
+public class CustomMatcher {
+
+ private String customMatcherHandler;
+
+ private String customMatcherParameters;
+
+ public String getCustomMatcherHandler() {
+ return customMatcherHandler;
+ }
+
+ public void setCustomMatcherHandler(String customMatcherHandler) {
+ this.customMatcherHandler = customMatcherHandler;
+ }
+
+ public String getCustomMatcherParameters() {
+ return customMatcherParameters;
+ }
+
+ public void setCustomMatcherParameters(String customMatcherParameters) {
+ this.customMatcherParameters = customMatcherParameters;
+ }
+}
diff --git
a/governance/src/main/java/org/apache/servicecomb/governance/marker/GovernanceRequest.java
b/governance/src/main/java/org/apache/servicecomb/governance/marker/GovernanceRequest.java
index 8036e8ab8..e4888dda0 100644
---
a/governance/src/main/java/org/apache/servicecomb/governance/marker/GovernanceRequest.java
+++
b/governance/src/main/java/org/apache/servicecomb/governance/marker/GovernanceRequest.java
@@ -56,6 +56,15 @@ public class GovernanceRequest {
*/
private String serviceName;
+ /**
+ sourceRequest the source request for creating this governanceRequest
+ For provider: uri indicates the request to me.
+ For consumer: uri indicates the request to the target.
+ the type of sourceRequest could be ClientRequest, ServerWebExchange,
HttpRequest, HttpServletRequest and so on,
+ it is desided by user. user will use this request to extract the
information he need
+ */
+ private Object sourceRequest;
+
public String getHeader(String key) {
return headers.get(key);
}
@@ -102,4 +111,12 @@ public class GovernanceRequest {
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
+
+ public Object getSourceRequest() {
+ return sourceRequest;
+ }
+
+ public void setSourceRequest(Object sourceRequest) {
+ this.sourceRequest = sourceRequest;
+ }
}
diff --git
a/governance/src/main/java/org/apache/servicecomb/governance/marker/Matcher.java
b/governance/src/main/java/org/apache/servicecomb/governance/marker/Matcher.java
index f0a70cd66..1cff86523 100644
---
a/governance/src/main/java/org/apache/servicecomb/governance/marker/Matcher.java
+++
b/governance/src/main/java/org/apache/servicecomb/governance/marker/Matcher.java
@@ -32,6 +32,8 @@ public class Matcher {
private String serviceName;
+ private CustomMatcher customMatcher;
+
public String getName() {
return name;
}
@@ -72,4 +74,12 @@ public class Matcher {
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
+
+ public CustomMatcher getCustomMatcher() {
+ return customMatcher;
+ }
+
+ public void setCustomMatcher(CustomMatcher customMatcher) {
+ this.customMatcher = customMatcher;
+ }
}
diff --git
a/governance/src/main/java/org/apache/servicecomb/governance/marker/RequestProcessor.java
b/governance/src/main/java/org/apache/servicecomb/governance/marker/RequestProcessor.java
index d90e73a82..762361f0b 100644
---
a/governance/src/main/java/org/apache/servicecomb/governance/marker/RequestProcessor.java
+++
b/governance/src/main/java/org/apache/servicecomb/governance/marker/RequestProcessor.java
@@ -19,22 +19,35 @@ package org.apache.servicecomb.governance.marker;
import java.util.Map;
import java.util.Map.Entry;
+import org.apache.commons.lang3.StringUtils;
import org.apache.servicecomb.governance.marker.operator.MatchOperator;
import org.apache.servicecomb.governance.marker.operator.RawOperator;
+import org.apache.servicecomb.governance.utils.CustomMatch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
/**
* Request Processor checks if a request matches a configuration.
*/
-public class RequestProcessor {
+public class RequestProcessor implements ApplicationContextAware{
private static final Logger LOGGER =
LoggerFactory.getLogger(RequestProcessor.class);
+ public static final String errorMessageForNotImplements = " didn't implement
interface org.apache.servicecomb.governance.utils.CustomMatch";
+ public static final String errorMessageForAbstractClass = " should be a
instantiable class rather than abstract class or other else";
+ public static final String infoMessageForCreatingClass = "is not in spring
container, create one and register it to spring container";
+
private static final String OPERATOR_SUFFIX = "Operator";
private final Map<String, MatchOperator> operatorMap;
+ private ApplicationContext applicationContext;
+
public RequestProcessor(Map<String, MatchOperator> operatorMap) {
this.operatorMap = operatorMap;
}
@@ -49,7 +62,10 @@ public class RequestProcessor {
if (!headersMatch(request, matcher)) {
return false;
}
- return serviceNameMatch(request, matcher);
+ if (!serviceNameMatch(request, matcher)) {
+ return false;
+ }
+ return customMatch(request, matcher);
}
private boolean serviceNameMatch(GovernanceRequest request, Matcher matcher)
{
@@ -103,4 +119,69 @@ public class RequestProcessor {
}
return true;
}
+
+ private boolean customMatch(GovernanceRequest request, Matcher matcher) {
+ if (matcher.getCustomMatcher() == null) {
+ return true;
+ }
+ String customMatcherHandlerName =
matcher.getCustomMatcher().getCustomMatcherHandler();
+ String customMatcherParameters =
matcher.getCustomMatcher().getCustomMatcherParameters();
+
+ if (StringUtils.isEmpty(customMatcherHandlerName) ||
StringUtils.isEmpty(customMatcherParameters)) {
+ return true;
+ }
+
+ CustomMatch customMatcherHandler =
generateHandler(customMatcherHandlerName);
+ return customMatcherHandler.matchRequest(request, customMatcherParameters);
+ }
+
+ private CustomMatch getBeanByHandlerName(String customMatcherHandler) {
+ Object extractObject = null;
+ if (applicationContext.containsBean(customMatcherHandler)) {
+ extractObject = applicationContext.getBean(customMatcherHandler);
+ if (!(extractObject instanceof CustomMatch)) {
+ LOGGER.error("{} {}", customMatcherHandler,
errorMessageForNotImplements);
+ throw new RuntimeException(customMatcherHandler +
errorMessageForNotImplements);
+ }
+ return (CustomMatch) extractObject;
+ }
+ return null;
+ }
+
+
+ public CustomMatch generateHandler(String customMatcherHandler) {
+ CustomMatch extractObject = getBeanByHandlerName(customMatcherHandler);
+ if (extractObject != null) {
+ return extractObject;
+ }
+
+ LOGGER.info("{} {}", customMatcherHandler, infoMessageForCreatingClass);
+ Class<?> extractionHandlerClass = null;
+ try {
+ extractionHandlerClass = Class.forName(customMatcherHandler);
+ } catch (ClassNotFoundException e) {
+ LOGGER.error(e.getMessage(), e);
+ throw new RuntimeException(e);
+ }
+
+ if (!CustomMatch.class.isAssignableFrom(extractionHandlerClass)) {
+ LOGGER.error("{} {}", customMatcherHandler,
errorMessageForNotImplements);
+ throw new RuntimeException(customMatcherHandler +
errorMessageForNotImplements);
+ }
+ BeanDefinitionBuilder builder =
BeanDefinitionBuilder.genericBeanDefinition(extractionHandlerClass);
+ BeanDefinitionRegistry registry = (BeanDefinitionRegistry)
applicationContext;
+ registry.registerBeanDefinition(customMatcherHandler,
builder.getBeanDefinition());
+ try {
+ extractObject = (CustomMatch)
applicationContext.getBean(customMatcherHandler);
+ return extractObject;
+ } catch (BeansException e) {
+ LOGGER.error(e.getMessage(), e);
+ throw new RuntimeException(customMatcherHandler +
errorMessageForAbstractClass, e);
+ }
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
+ this.applicationContext = applicationContext;
+ }
}
diff --git
a/governance/src/main/java/org/apache/servicecomb/governance/utils/CustomMatch.java
b/governance/src/main/java/org/apache/servicecomb/governance/utils/CustomMatch.java
new file mode 100644
index 000000000..faf9461d3
--- /dev/null
+++
b/governance/src/main/java/org/apache/servicecomb/governance/utils/CustomMatch.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.governance.utils;
+
+import org.apache.servicecomb.governance.marker.GovernanceRequest;
+
+public interface CustomMatch {
+ boolean matchRequest(GovernanceRequest request, String parameters);
+}
diff --git
a/governance/src/test/java/org/apache/servicecomb/governance/CustomMatchTest.java
b/governance/src/test/java/org/apache/servicecomb/governance/CustomMatchTest.java
new file mode 100644
index 000000000..126db5766
--- /dev/null
+++
b/governance/src/test/java/org/apache/servicecomb/governance/CustomMatchTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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.governance;
+
+import org.apache.servicecomb.governance.marker.CustomMatcher;
+import org.apache.servicecomb.governance.marker.GovernanceRequest;
+import org.apache.servicecomb.governance.marker.Matcher;
+import org.apache.servicecomb.governance.marker.RequestProcessor;
+import
org.apache.servicecomb.governance.mockclasses.service.MockConfigurationForCustomMatcher;
+import org.junit.Assert;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ContextConfiguration;
+import org.junit.jupiter.api.Assertions;
+
+@SpringBootTest
+@ContextConfiguration(classes = {GovernanceConfiguration.class,
MockConfiguration.class, MockConfigurationForCustomMatcher.class})
+public class CustomMatchTest {
+
+ private RequestProcessor requestProcessor;
+
+ @Autowired
+ public void setRequestProcessor(RequestProcessor requestProcessor) {
+ this.requestProcessor = requestProcessor;
+ }
+
+ private Matcher generateMatcher(String customMatcherHandler, String
customMatcherParameters) {
+ CustomMatcher customMatcher = new CustomMatcher();
+ customMatcher.setCustomMatcherHandler(customMatcherHandler);
+ customMatcher.setCustomMatcherParameters(customMatcherParameters);
+ Matcher matcher = new Matcher();
+ matcher.setCustomMatcher(customMatcher);
+ return matcher;
+ }
+
+ @Test
+ public void test_should_pass_when_value_class_empty() {
+ GovernanceRequest request = new GovernanceRequest();
+ Matcher mockMatcher = generateMatcher("", "");
+ Assert.assertTrue(this.requestProcessor.match(request, mockMatcher));
+ mockMatcher = generateMatcher("", "bill");
+ Assert.assertTrue(this.requestProcessor.match(request, mockMatcher));
+ mockMatcher = generateMatcher("classWithAnnotation", "");
+ Assert.assertTrue(this.requestProcessor.match(request, mockMatcher));
+ }
+
+ @Test
+ public void test_should_pass_when_value_class_match() {
+ GovernanceRequest request = new GovernanceRequest();
+ Matcher mockMatcher = generateMatcher("classWithAnnotation", "bill");
+ Assert.assertTrue(this.requestProcessor.match(request, mockMatcher));
+ }
+
+ @Test
+ public void test_should_throw_exception_when_class_not_found() {
+ GovernanceRequest request = new GovernanceRequest();
+ try {
+ Matcher mockMatcher =
generateMatcher("classWithAnnotationNotFound", "bill");
+ this.requestProcessor.match(request, mockMatcher);
+ Assertions.fail("an exception is expected!");
+ } catch (Exception e) {
+ Assert.assertTrue(e.getCause() instanceof ClassNotFoundException);
+ }
+ }
+
+ @Test
+ public void test_should_pass_when_multiple_value() {
+ GovernanceRequest request = new GovernanceRequest();
+ Matcher mockMatcher = generateMatcher("classWithAnnotation",
"bill,bill2");
+ Assert.assertTrue(this.requestProcessor.match(request, mockMatcher));
+ }
+
+ @Test
+ public void test_should_throw_exception_when_not_implements_interface() {
+ GovernanceRequest request = new GovernanceRequest();
+ try {
+ Matcher mockMatcher = generateMatcher("classNotImplments",
"bill,bill2");
+ this.requestProcessor.match(request, mockMatcher);
+ Assertions.fail("an exception is expected!");
+ } catch (Exception e) {
+
Assert.assertTrue(e.getMessage().contains(RequestProcessor.errorMessageForNotImplements));
+ }
+ }
+}
diff --git
a/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/ClassNotImplments.java
b/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/ClassNotImplments.java
new file mode 100644
index 000000000..85d14fe08
--- /dev/null
+++
b/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/ClassNotImplments.java
@@ -0,0 +1,28 @@
+/*
+ * 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.governance.mockclasses;
+
+import org.springframework.stereotype.Component;
+import org.apache.servicecomb.governance.marker.GovernanceRequest;
+
+@Component
+public class ClassNotImplments {
+ public boolean matchRequest(GovernanceRequest request, String parameters) {
+ return true;
+ }
+}
diff --git
a/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/ClassWithAnnotation.java
b/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/ClassWithAnnotation.java
new file mode 100644
index 000000000..a9d1f7ccd
--- /dev/null
+++
b/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/ClassWithAnnotation.java
@@ -0,0 +1,39 @@
+/*
+ * 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.governance.mockclasses;
+
+import
org.apache.servicecomb.governance.mockclasses.service.MockProfileClassUserService;
+import org.apache.servicecomb.governance.marker.GovernanceRequest;
+import org.apache.servicecomb.governance.utils.CustomMatch;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+@Component
+public class ClassWithAnnotation implements CustomMatch {
+ @Autowired
+ MockProfileClassUserService service;
+
+ @Override
+ public boolean matchRequest(GovernanceRequest request, String parameters) {
+ String profileValue = service.getUser();
+ return
Stream.of(parameters.split(",")).collect(Collectors.toSet()).contains(profileValue);
+ }
+}
diff --git
a/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/CustomMatchDemo.java
b/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/CustomMatchDemo.java
new file mode 100644
index 000000000..67181c43b
--- /dev/null
+++
b/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/CustomMatchDemo.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.governance.mockclasses;
+
+import org.apache.servicecomb.governance.utils.CustomMatch;
+import org.apache.servicecomb.governance.marker.GovernanceRequest;
+
+public class CustomMatchDemo implements CustomMatch {
+
+ private CustomMatchDemo() {
+
+ }
+
+ @Override
+ public boolean matchRequest(GovernanceRequest request, String parameters) {
+ return true;
+ }
+}
diff --git
a/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/service/MockConfigurationForCustomMatcher.java
b/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/service/MockConfigurationForCustomMatcher.java
new file mode 100644
index 000000000..7668ddc8e
--- /dev/null
+++
b/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/service/MockConfigurationForCustomMatcher.java
@@ -0,0 +1,26 @@
+/*
+ * 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.governance.mockclasses.service;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ComponentScan("org.apache.servicecomb.governance.mockclasses")
+public class MockConfigurationForCustomMatcher {
+}
diff --git
a/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/service/MockProfileClassUserService.java
b/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/service/MockProfileClassUserService.java
new file mode 100644
index 000000000..31aa5479c
--- /dev/null
+++
b/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/service/MockProfileClassUserService.java
@@ -0,0 +1,27 @@
+/*
+ * 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.governance.mockclasses.service;
+
+import org.springframework.stereotype.Service;
+
+@Service
+public class MockProfileClassUserService {
+ public String getUser() {
+ return "bill";
+ }
+}