You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by GitBox <gi...@apache.org> on 2018/06/14 12:23:46 UTC

[GitHub] wujimin closed pull request #741: [SCB-625] ProduceProcessor use SPI to support extends

wujimin closed pull request #741: [SCB-625] ProduceProcessor use SPI to support extends
URL: https://github.com/apache/incubator-servicecomb-java-chassis/pull/741
 
 
   

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/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/AbstractProduceProcessor.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/AbstractProduceProcessor.java
deleted file mode 100644
index 7704fa2d6..000000000
--- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/AbstractProduceProcessor.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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.common.rest.codec.produce;
-
-public abstract class AbstractProduceProcessor implements ProduceProcessor {
-  public AbstractProduceProcessor() {
-    ProduceProcessorManager.INSTANCE.register(getName(), this);
-  }
-}
diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceJsonProcessor.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceJsonProcessor.java
index 28e2b2908..73cbf6296 100644
--- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceJsonProcessor.java
+++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceJsonProcessor.java
@@ -26,7 +26,7 @@
 
 import com.fasterxml.jackson.databind.JavaType;
 
-public class ProduceJsonProcessor extends AbstractProduceProcessor {
+public class ProduceJsonProcessor implements ProduceProcessor {
 
   @Override
   public String getName() {
@@ -42,4 +42,9 @@ public void doEncodeResponse(OutputStream output, Object result) throws Exceptio
   public Object doDecodeResponse(InputStream input, JavaType type) throws Exception {
     return RestObjectMapper.INSTANCE.readValue(input, type);
   }
+
+  @Override
+  public int getOrder() {
+    return 0;
+  }
 }
diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceProcessor.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceProcessor.java
index 244c9010a..127250ff7 100644
--- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceProcessor.java
+++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceProcessor.java
@@ -30,6 +30,8 @@
 public interface ProduceProcessor {
   String getName();
 
+  int getOrder();
+
   default void encodeResponse(OutputStream output, Object result) throws Exception {
     if (result == null) {
       return;
diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceProcessorManager.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceProcessorManager.java
index d70eac452..255b35d77 100644
--- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceProcessorManager.java
+++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceProcessorManager.java
@@ -17,24 +17,38 @@
 
 package org.apache.servicecomb.common.rest.codec.produce;
 
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
 import javax.ws.rs.core.MediaType;
 
 import org.apache.servicecomb.foundation.common.RegisterManager;
+import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
 
 public final class ProduceProcessorManager extends RegisterManager<String, ProduceProcessor> {
+  private static final List<ProduceProcessor> produceProcessor =
+      SPIServiceUtils.getSortedService(ProduceProcessor.class);
+
   private static final String NAME = "produce processor mgr";
 
   public static final String DEFAULT_TYPE = MediaType.APPLICATION_JSON;
 
   public static final ProduceProcessorManager INSTANCE = new ProduceProcessorManager();
 
-  public static final ProduceProcessor JSON_PROCESSOR = new ProduceJsonProcessor();
+  public static final ProduceProcessor JSON_PROCESSOR =
+      SPIServiceUtils.getTargetService(ProduceProcessor.class, ProduceJsonProcessor.class);
 
-  public static final ProduceProcessor PLAIN_PROCESSOR = new ProduceTextPlainProcessor();
+  public static final ProduceProcessor PLAIN_PROCESSOR =
+      SPIServiceUtils.getTargetService(ProduceProcessor.class, ProduceTextPlainProcessor.class);
 
   public static final ProduceProcessor DEFAULT_PROCESSOR = JSON_PROCESSOR;
 
   private ProduceProcessorManager() {
     super(NAME);
+    Set<String> set = new HashSet<>();
+    produceProcessor.forEach(processor -> {
+      if (set.add(processor.getName()))
+        register(processor.getName(), processor);
+    });
   }
 }
diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceTextPlainProcessor.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceTextPlainProcessor.java
index 7157adf7a..0311182eb 100644
--- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceTextPlainProcessor.java
+++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceTextPlainProcessor.java
@@ -27,7 +27,7 @@
 
 import com.fasterxml.jackson.databind.JavaType;
 
-public class ProduceTextPlainProcessor extends AbstractProduceProcessor {
+public class ProduceTextPlainProcessor implements ProduceProcessor {
   @Override
   public String getName() {
     return MediaType.TEXT_PLAIN;
@@ -59,4 +59,9 @@ public Object doDecodeResponse(InputStream input, JavaType type) throws Exceptio
     //                    .newInstance((String)result);
     //        }
   }
+
+  @Override
+  public int getOrder() {
+    return 0;
+  }
 }
diff --git a/common/common-rest/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor b/common/common-rest/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor
new file mode 100644
index 000000000..9353b9dce
--- /dev/null
+++ b/common/common-rest/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+org.apache.servicecomb.common.rest.codec.produce.ProduceJsonProcessor
+org.apache.servicecomb.common.rest.codec.produce.ProduceTextPlainProcessor
\ No newline at end of file
diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/CodeFirstJaxrs.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/CodeFirstJaxrs.java
index 35cdd56b8..11987e3f0 100644
--- a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/CodeFirstJaxrs.java
+++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/CodeFirstJaxrs.java
@@ -42,6 +42,7 @@
 import org.apache.servicecomb.demo.compute.Person;
 import org.apache.servicecomb.demo.ignore.InputModelForTestIgnore;
 import org.apache.servicecomb.demo.ignore.OutputModelForTestIgnore;
+import org.apache.servicecomb.demo.jaxbbean.JAXBPerson;
 import org.apache.servicecomb.demo.server.User;
 import org.apache.servicecomb.provider.rest.common.RestSchema;
 import org.apache.servicecomb.swagger.extend.annotations.RawJsonRequestBody;
@@ -93,6 +94,14 @@ public String textPlain(String body) {
     return body;
   }
 
+  @Path("/appXml")
+  @POST
+  @Consumes(MediaType.APPLICATION_JSON)
+  @Produces(MediaType.APPLICATION_XML)
+  public JAXBPerson appXml(JAXBPerson body) {
+    return body;
+  }
+
   @Path("/bytes")
   @POST
   public byte[] bytes(byte[] input) {
diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/CodeFirstRestTemplate.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/CodeFirstRestTemplate.java
index d63767264..d5a12be12 100644
--- a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/CodeFirstRestTemplate.java
+++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/CodeFirstRestTemplate.java
@@ -21,11 +21,14 @@
 import java.util.HashMap;
 import java.util.Map;
 
+import org.apache.servicecomb.common.rest.codec.produce.ProduceProcessorManager;
 import org.apache.servicecomb.core.Const;
 import org.apache.servicecomb.core.CseContext;
 import org.apache.servicecomb.demo.compute.Person;
 import org.apache.servicecomb.demo.ignore.InputModelForTestIgnore;
 import org.apache.servicecomb.demo.ignore.OutputModelForTestIgnore;
+import org.apache.servicecomb.demo.jaxbbean.JAXBJob;
+import org.apache.servicecomb.demo.jaxbbean.JAXBPerson;
 import org.apache.servicecomb.demo.server.User;
 import org.apache.servicecomb.serviceregistry.RegistryUtils;
 import org.apache.servicecomb.swagger.invocation.context.ContextUtils;
@@ -34,6 +37,7 @@
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpMethod;
 import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.client.RestTemplate;
 
@@ -62,6 +66,7 @@ public void testCodeFirst(RestTemplate template, String microserviceName, String
   protected void testAllTransport(String microserviceName, RestTemplate template, String cseUrlPrefix) {
     testCodeFirstUserMap(template, cseUrlPrefix);
     testCodeFirstTextPlain(template, cseUrlPrefix);
+    testCodeFirstAppXml(template, cseUrlPrefix);
     testCodeFirstBytes(template, cseUrlPrefix);
     testCseResponse(microserviceName, template, cseUrlPrefix);
     testCodeFirstAddDate(template, cseUrlPrefix);
@@ -123,6 +128,21 @@ private void testCodeFirstTextPlain(RestTemplate template, String cseUrlPrefix)
     TestMgr.check(body, result);
   }
 
+  private void testCodeFirstAppXml(RestTemplate template, String cseUrlPrefix) {
+    JAXBPerson person = new JAXBPerson("jake", 22, "it", "60kg");
+    person.setJob(new JAXBJob("developer", "coding"));
+    HttpHeaders headers = new HttpHeaders();
+    headers.add("Accept", MediaType.APPLICATION_XML_VALUE);
+    headers.add("Content-Type", MediaType.APPLICATION_JSON_VALUE);
+    HttpEntity<JAXBPerson> requestEntity = new HttpEntity<>(person, headers);
+    ResponseEntity<JAXBPerson> resEntity = template.exchange(cseUrlPrefix + "appXml",
+        HttpMethod.POST,
+        requestEntity,
+        JAXBPerson.class);
+    TestMgr.check(-1, ProduceProcessorManager.INSTANCE.ensureFindValue(MediaType.APPLICATION_XML_VALUE).getOrder());
+    TestMgr.check(person, resEntity.getBody());
+  }
+
   private void testCodeFirstBytes(RestTemplate template, String cseUrlPrefix) {
     byte[] body = new byte[] {0, 1, 2};
     byte[] result = template.postForObject(cseUrlPrefix + "bytes",
@@ -240,7 +260,7 @@ protected void testCodeFirstReduce(RestTemplate template, String cseUrlPrefix) {
   protected void testModelFieldIgnore(RestTemplate template, String cseUrlPrefix) {
     InputModelForTestIgnore input = new InputModelForTestIgnore("input_id_rest", "input_id_content",
         new Person("inputSomeone"), new JsonObject("{\"InputJsonKey\" : \"InputJsonValue\"}"), () -> {
-    });
+        });
     OutputModelForTestIgnore output = template
         .postForObject(cseUrlPrefix + "ignore", input, OutputModelForTestIgnore.class);
 
diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/jaxbbean/JAXBJob.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/jaxbbean/JAXBJob.java
new file mode 100644
index 000000000..b8da947c2
--- /dev/null
+++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/jaxbbean/JAXBJob.java
@@ -0,0 +1,45 @@
+package org.apache.servicecomb.demo.jaxbbean;
+
+import javax.xml.bind.annotation.XmlAccessOrder;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorOrder;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "job")
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL)
+public class JAXBJob {
+  private String name;
+
+  private String content;
+
+  public JAXBJob() {
+  }
+
+  public JAXBJob(String name, String content) {
+    this.name = name;
+    this.content = content;
+  }
+
+  @Override
+  public String toString() {
+    return "Job{" + "name'" + name + '\'' + ", content='" + content + '\'' + '}';
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public String getContent() {
+    return content;
+  }
+
+  public void setContent(String content) {
+    this.content = content;
+  }
+}
diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/jaxbbean/JAXBPerson.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/jaxbbean/JAXBPerson.java
new file mode 100644
index 000000000..e69376d74
--- /dev/null
+++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/jaxbbean/JAXBPerson.java
@@ -0,0 +1,92 @@
+package org.apache.servicecomb.demo.jaxbbean;
+
+import java.io.Serializable;
+
+import javax.xml.bind.annotation.XmlAccessOrder;
+import javax.xml.bind.annotation.XmlAccessorOrder;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlType(propOrder = {"name", "role", "job"})
+@XmlRootElement(name = "person")
+@XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL)
+public class JAXBPerson implements Serializable {
+  private static final long serialVersionUID = -7127275268696924681L;
+
+  private String name;
+
+  private int age;
+
+  private String role;
+
+  private String weight;
+
+  private JAXBJob job;
+
+  public JAXBPerson() {
+  }
+
+  public JAXBPerson(String name, int age, String role, String weight) {
+    this.name = name;
+    this.age = age;
+    this.role = role;
+    this.weight = weight;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  @XmlAttribute
+  public int getAge() {
+    return age;
+  }
+
+  public void setAge(int age) {
+    this.age = age;
+  }
+
+  @XmlElement(nillable = true)
+  public String getRole() {
+    return role;
+  }
+
+  public void setRole(String role) {
+    this.role = role;
+  }
+
+  @XmlTransient
+  public String getWeight() {
+    return weight;
+  }
+
+  public void setWeight(String weight) {
+    this.weight = weight;
+  }
+
+  @XmlElement
+  public JAXBJob getJob() {
+    return job;
+  }
+
+  public void setJob(JAXBJob job) {
+    this.job = job;
+  }
+
+  @Override
+  public String toString() {
+    return "Person{" +
+        "name='" + name + '\'' +
+        ", age=" + age +
+        ", role='" + role + '\'' +
+        ", job=" + job +
+        '}';
+  }
+}
diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/produceprocessor/ProduceAppXmlProcessor.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/produceprocessor/ProduceAppXmlProcessor.java
new file mode 100644
index 000000000..db882975b
--- /dev/null
+++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/produceprocessor/ProduceAppXmlProcessor.java
@@ -0,0 +1,35 @@
+package org.apache.servicecomb.demo.produceprocessor;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.ws.rs.core.MediaType;
+
+import org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor;
+import org.apache.servicecomb.demo.utils.JAXBUtils;
+
+import com.fasterxml.jackson.databind.JavaType;
+
+public class ProduceAppXmlProcessor implements ProduceProcessor {
+
+  @Override
+  public String getName() {
+    return MediaType.APPLICATION_XML;
+  }
+
+  @Override
+  public int getOrder() {
+    return 0;
+  }
+
+  @Override
+  public void doEncodeResponse(OutputStream output, Object result) throws Exception {
+    output.write(JAXBUtils.convertToXml(result).getBytes());
+  }
+
+  @Override
+  public Object doDecodeResponse(InputStream input, JavaType type) throws Exception {
+    return JAXBUtils.convertToJavaBean(input, type);
+  }
+
+}
diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/produceprocessor/override/ProduceAppXmlProcessor.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/produceprocessor/override/ProduceAppXmlProcessor.java
new file mode 100644
index 000000000..fc1a01a62
--- /dev/null
+++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/produceprocessor/override/ProduceAppXmlProcessor.java
@@ -0,0 +1,35 @@
+package org.apache.servicecomb.demo.produceprocessor.override;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.ws.rs.core.MediaType;
+
+import org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor;
+import org.apache.servicecomb.demo.utils.JAXBUtils;
+
+import com.fasterxml.jackson.databind.JavaType;
+
+public class ProduceAppXmlProcessor implements ProduceProcessor {
+
+  @Override
+  public String getName() {
+    return MediaType.APPLICATION_XML;
+  }
+
+  @Override
+  public int getOrder() {
+    return -1;
+  }
+
+  @Override
+  public void doEncodeResponse(OutputStream output, Object result) throws Exception {
+    output.write(JAXBUtils.convertToXml(result).getBytes());
+  }
+
+  @Override
+  public Object doDecodeResponse(InputStream input, JavaType type) throws Exception {
+    return JAXBUtils.convertToJavaBean(input, type);
+  }
+
+}
diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/utils/JAXBUtils.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/utils/JAXBUtils.java
new file mode 100644
index 000000000..511a18ccc
--- /dev/null
+++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/utils/JAXBUtils.java
@@ -0,0 +1,75 @@
+package org.apache.servicecomb.demo.utils;
+
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.nio.charset.StandardCharsets;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.Source;
+import javax.xml.transform.sax.SAXSource;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.InputSource;
+
+import com.fasterxml.jackson.databind.JavaType;
+
+public class JAXBUtils {
+  private static final Logger LOGGER = LoggerFactory.getLogger(JAXBUtils.class);
+
+  public static String convertToXml(Object obj) {
+    return convertToXml(obj, StandardCharsets.UTF_8.toString());
+  }
+
+  public static String convertToXml(Object obj, String encoding) {
+    String result = null;
+    try {
+      JAXBContext context = JAXBContext.newInstance(obj.getClass());
+      Marshaller marshaller = context.createMarshaller();
+      marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+      marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding);
+
+      StringWriter writer = new StringWriter();
+      marshaller.marshal(obj, writer);
+      result = writer.toString();
+    } catch (Exception e) {
+      LOGGER.error("Bean convert to xml failed, error message: {}", e.getMessage());
+    }
+    return result;
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T> T convertToJavaBean(InputStream xml, JavaType type) {
+    return (T) convertToJavaBean(xml, type.getRawClass());
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T> T convertToJavaBean(InputStream xml, Class<T> c) {
+    T t = null;
+    try {
+      JAXBContext context = JAXBContext.newInstance(c);
+      Unmarshaller unmarshaller = context.createUnmarshaller();
+      t = (T) unmarshaller.unmarshal(XXEPrevention(xml));
+    } catch (Exception e) {
+      LOGGER.error("Xml convert to Bean failed, error message: {}", e.getMessage());
+    }
+    return t;
+  }
+
+  private static Source XXEPrevention(InputStream xml) {
+    Source xmlSource = null;
+    SAXParserFactory spf = SAXParserFactory.newInstance();
+    try {
+      spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
+      spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
+      spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+      xmlSource = new SAXSource(spf.newSAXParser().getXMLReader(), new InputSource(xml));
+    } catch (Exception e) {
+      LOGGER.error("Xml External Entity (XXE) Processing report error, error message: {}", e.getMessage());
+    }
+    return xmlSource;
+  }
+}
diff --git a/demo/demo-schema/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor b/demo/demo-schema/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor
new file mode 100644
index 000000000..ff9a6cb9a
--- /dev/null
+++ b/demo/demo-schema/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+org.apache.servicecomb.demo.produceprocessor.ProduceAppXmlProcessor
+org.apache.servicecomb.demo.produceprocessor.override.ProduceAppXmlProcessor
\ No newline at end of file
diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java
index 8cae971f5..1f20dc3dd 100644
--- a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java
+++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java
@@ -37,6 +37,7 @@
 import org.apache.servicecomb.demo.compute.Person;
 import org.apache.servicecomb.demo.ignore.InputModelForTestIgnore;
 import org.apache.servicecomb.demo.ignore.OutputModelForTestIgnore;
+import org.apache.servicecomb.demo.jaxbbean.JAXBPerson;
 import org.apache.servicecomb.demo.server.User;
 import org.apache.servicecomb.provider.rest.common.RestSchema;
 import org.apache.servicecomb.swagger.extend.annotations.RawJsonRequestBody;
@@ -161,6 +162,11 @@ public String textPlain(@RequestBody String body) {
     return body;
   }
 
+  @RequestMapping(path = "/appXml", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_XML_VALUE)
+  public JAXBPerson appXml(@RequestBody JAXBPerson person) {
+    return person;
+  }
+
   @RequestMapping(path = "/bytes", method = RequestMethod.POST)
   public byte[] bytes(@RequestBody byte[] input) {
     input[0] = (byte) (input[0] + 1);


 

----------------------------------------------------------------
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:
users@infra.apache.org


With regards,
Apache Git Services