如何将wsdl内部架构设置为Jaxb2Marshaller以验证我所做的每个帖子? [英] How to set wsdl inner schema to Jaxb2Marshaller to validate each post i wold make?

查看:109
本文介绍了如何将wsdl内部架构设置为Jaxb2Marshaller以验证我所做的每个帖子?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用SOAP Web服务,我必须在调用之前验证每个xml帖子。

I'm consuming a SOAP webservice where I have to validate every xml post before call it.

所以我正在使用:


  • 生成POJO树结构的 cxf-codegen-plugin

  • 第三部分wsdl (xxxx-soap-service.wsdl)

  • 实现 WebServiceGatewaySupport 弹簧界面以进行调用的类。

  • Jaxb2Marshaller spring marshaller / unmarshaller转换pojo<···xml

  • The cxf-codegen-plugin to generate the POJO tree structure.
  • A third part wsdl (xxxx-soap-service.wsdl)
  • A class implementing WebServiceGatewaySupport spring interface to make the calls.
  • Jaxb2Marshaller spring marshaller/unmarshaller to convert pojo <··> xml

嗯,代码碎片现在我有:

Well, the code fragments now I have:


  • applicationContext-xxxx-base.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee" xmlns:mybatis="http://mybatis.org/schema/mybatis-spring"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
                        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.3.xsd
                        http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd">

    <mybatis:scan base-package="com.company.integration.xxxx.domain.mybatis.mapper" />

    <context:component-scan base-package="com.company.integration.remo" />

    <bean id="xxxxMarshallerProperties" class="com.company.integration.xxxx.domain.properties.XxxxMarshallerProperties"/>

    <bean id="xxxxMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller" depends-on="xxxxMarshallerProperties">
        <property name="contextPath" value="#{xxxxMarshallerProperties.contextPath}"/>
        <property name="validationEventHandler" value="#{xxxxMarshallerProperties.validationEventHandler}"/>
        <property name="schema" value="#{xxxxMarshallerProperties.schema}"/>
    </bean>

    <bean id="xxxxService" class="com.company.integration.xxxx.domain.client.XxxxServiceImpl">
        <property name="defaultUri" value="#{'${xxxx.baseUrl}' + '${xxxx.url.sufix}'}" />
        <property name="marshaller" ref="xxxxMarshaller" />
        <property name="unmarshaller" ref="xxxxMarshaller" />
    </bean>

    <bean id="xxxxObjectFactory" class="com.company.integration.xxxx.domain.model.ObjectFactory" />


</beans>




  • XxxxMarshallerProperties ,进行配置marshaller / unmarshaller bean:

    • XxxxMarshallerProperties, to configure marshaller/unmarshaller bean:

      //
      @Component
      public class XxxxMarshallerProperties {
      @Autowired
      private ResourceLoader resourceLoader;

      // @Component public class XxxxMarshallerProperties { @Autowired private ResourceLoader resourceLoader;

      public Resource getSchema() throws IOException, SAXException {
          WebServiceClient wscAnnotation = Service.class.getAnnotation(WebServiceClient.class);
          String wsdlLocationPath = wscAnnotation.wsdlLocation();
          Resource wsdlResource = resourceLoader.getResource(wsdlLocationPath);
          final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
          URI wsdlUri = wsdlResource.getURI();
          Source[] streamSources = new Source[] { new StreamSource(wsdlUri.toString()) };
          final Schema wsdlSchema = schemaFactory.newSchema(streamSources);
          return wsdlSchema;
      }
      
      public DefaultValidationEventHandler getValidationEventHandler() {
          return new DefaultValidationEventHandler();
      }
      
      public String getContextPath() {
          return XXXXX.class.getPackage().getName();
      }
      

      }

      用于调用webservice的 xxxxService bean类:

      The xxxxService bean class used to call the webservice:

      public class XxxxServiceImpl扩展WebServiceGatewaySupport实现ServiceSoap {

      public class XxxxServiceImpl extends WebServiceGatewaySupport implements ServiceSoap {

      @Autowired
      XxxxProperties xxxxProperties;
      
      @Autowired
      private ObjectFactory xxxxObjectFactory;
      
      @Autowired
      private ResourceLoader resourceLoader;
      
      private String getActionUrl(String actionName) {
          return xxxxProperties.getActionNamespace() + actionName;
      }
      
      public CXXXX callXXXX(CallXXXX request) {
          Jaxb2Marshaller marshaller = (Jaxb2Marshaller) getMarshaller();
          Result result = new StringResult();
      
          CallXXXXResponse response = (CallXXXXResponse) getWebServiceTemplate().marshalSendAndReceive(request,
              new WebServiceMessageCallback() {
      
                  public void doWithMessage(WebServiceMessage message) {
                      ((SoapMessage) message).setSoapAction(getActionUrl(xxxxProperties.getSoapActionCallXXXX()));
                  }
              });
          return response.getCallXXXXResult();
      }
      

      }

      My意图是将wsdl( xxxx-soap-service.wsdl )附加到编组器( xxxxMarshaller ),以便检查由它生成的xml,对照包含的模式wsdl,在调用make之前。

      My intention is to attach the wsdl (xxxx-soap-service.wsdl) to the marshaller (xxxxMarshaller) in order to check the xml generated by it, against the contained schema in wsdl, before the call is make.

      我遇到的问题是,如果我只是附加wsdl(在bean定义中通过schema属性),Jaxb2Marshaller似乎认为它是一个xsd并给我一个 org.xml.sax.SAXParseException:s4s-elt-schema-ns:'definitions'命名空间必须是......

      I'm facing the problem that if I simply attach the wsdl (in bean definition through schema property), Jaxb2Marshaller seems consider it as an xsd and gives me back an org.xml.sax.SAXParseException: s4s-elt-schema-ns: 'definitions' namespace must be...

      我现在正试图从wsdl中提取内部xsd并将其附加到marshaller,但xsd必须是 org.springframework.core.io.Resource 才能执行那。那是因为我的代码尚未编译。

      I'm now trying to extract the inner xsd from the wsdl and attach it to the marshaller, but the xsd it has to be a org.springframework.core.io.Resource to do that. That's because my code not compile yet.

      我已经看到 JaxbMarshaller (不是Jaxb 2 Marshaller)是可能的。

      I have seen that for JaxbMarshaller (not Jaxb2Marshaller) this is possible.

      你能以这种方式帮助我吗?

      So could you help me in that way?

      我愿意探索其他方法或更好的解决方案。

      I'm open to explore other ways or better solutions.

      推荐答案

      最后我找到了一个适合我的实现。

      finally I found an implementation that works for me.

      这个想法是:


      • 从wsdl中提取嵌入式模式,

      • 配置每个模式名称空间,

      • 添加尚未定义的所有posible名称空间,但是在< wsdl:definition>上定义了这些名称空间。 tag,

      • 配置每个架构导入和位置,

      • 将每个架构存储到spring的Resource接口的实现类中,

      • 将所有这些数据存储到资源数组中

      • 并通过 setSchema [s] 将此数组传递给Jaxb2Marshaller,而不是 setSchema (正如我一直在做的那样)。

      • to extract the embedded schema's from the wsdl,
      • configure each schema namespace,
      • adding all posible namespaces non defined yet in it but that are defined on <wsdl:definition> tag,
      • configure each schema import and locations,
      • store each schema into an implementing class of spring's Resource interface,
      • store all of them into an Resource array
      • and pass this array to the Jaxb2Marshaller through setSchema[s], instead of setSchema (as I have been doing).

      基于这个问题,我不得不修改 XxxxMarshallerProperties class和 applicationContext-xxxx-base.xml 文件。

      Based on the question, I had to modify the XxxxMarshallerProperties class and the applicationContext-xxxx-base.xml files, only.

      XxxxMarshallerProperties

      @Component
      public class XxxxMarshallerProperties {
          @Autowired
          private ResourceLoader resourceLoader;
      
          /**
           * @return A new transformer.
           * @throws TransformerFactoryConfigurationError
           * @throws TransformerConfigurationException
           */
          private Transformer newTransformer()
              throws TransformerFactoryConfigurationError, TransformerConfigurationException {
              TransformerFactory transformerFactory = TransformerFactory.newInstance();
              Transformer transformer = transformerFactory.newTransformer();
              return transformer;
          }
      
          /**
           * Load the wsdl into a dom Document. Used at:<br/>
           * &nbsp;&nbsp;&nbsp;&nbsp;<b>getSchemas</b>
           *
           * @param wsdlUrl
           *            url where the WSDL is located at
           * @param transformer
           *            used to load the document
           * @return The wsdl dom Document
           * @throws ParserConfigurationException
           * @throws IOException
           * @throws TransformerException
           */
          private Document loadWsdlDoc(URL wsdlUrl, Transformer transformer)
              throws ParserConfigurationException, IOException, TransformerException {
              DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
              DocumentBuilder schemaBuilder = docFactory.newDocumentBuilder();
              Document wsdlDoc = schemaBuilder.newDocument();
              BufferedReader wsdlReader = new BufferedReader(new InputStreamReader(wsdlUrl.openStream()));
              Source source = new StreamSource(wsdlReader);
              transformer.transform(source, new DOMResult(wsdlDoc));
              return wsdlDoc;
          }
      
          /**
           * Store into a map all namespaces defined on the wsdl. Used at:<br/>
           * &nbsp;&nbsp;&nbsp;&nbsp;<b>getSchemas</b>
           *
           * @param defNode
           *            &lt;<b><i>wsdl:definitions</i></b>&gt; dom node where to look
           *            up.
           * @return A map of namespace definition attributes. Format: [(nodeName,
           *         node)....]
           */
          private Map<String, Node> getWsdlDefinedNamespaces(Element defNode) {
              Map<String, Node> namespaces = new TreeMap<>();
              NamedNodeMap defNodeAtt = defNode.getAttributes();
              int defNodeAttSz = defNodeAtt.getLength();
              for (int attIndex = 0; attIndex < defNodeAttSz; attIndex++) {
                  String ns = defNodeAtt.item(attIndex).getPrefix();
                  if ("xmlns".equals(ns)) {
                      namespaces.put(//
                          defNodeAtt.item(attIndex).getNodeName(), //
                          defNodeAtt.item(attIndex));
                  }
              }
      
              return namespaces;
          }
      
          /**
           * Store into a map all the atributes present in a xsd schema node. Used at:
           * <br/>
           * &nbsp;&nbsp;&nbsp;&nbsp;<b>addDefinitionNamespaces</b>
           *
           * @param wsdlSchemaNode
           *            &lt;<b><i>s:schema</i></b>&gt; dom node where to look up.
           * @return A map of attributes. Format: [(nodeName, node)....]
           */
          private Map<String, Node> getCurrentSchemaAtt(Node wsdlSchemaNode) {
              Map<String, Node> schemaXmlnss = new HashMap<>();
      
              NamedNodeMap schemaNodeAtt = wsdlSchemaNode.getAttributes();
              int schemaNodeAttSz = schemaNodeAtt.getLength();
              for (int attIndex = 0; attIndex < schemaNodeAttSz; attIndex++) {
                  String nodeAttName = schemaNodeAtt.item(attIndex).getNodeName();
                  Node nodeAtt = ((NamedNodeMap) schemaNodeAtt).item(attIndex);
                  schemaXmlnss.put(nodeAttName, nodeAtt);
              }
              return schemaXmlnss;
          }
      
          /**
           * Adds all non existing namespace definition attributes to a schema node in
           * that schema node. If a namespace definition attribute name is found into
           * schema node, it's not added to the current schema node attributes. Used
           * at: <br/>
           * &nbsp;&nbsp;&nbsp;&nbsp;<b>getSchemas</b>
           *
           * @param schemaNode
           *            &lt;<b><i>s:schema</i></b>&gt; dom node where to add the
           *            namespace definition attributes.
           * @param namespaces
           *            map storing all namespace definition attributes.
           */
          private void addDefinitionNamespaces(Node schemaNode, Map<String, Node> namespaces) {
              Map<String, Node> currSchemaAttMap = getCurrentSchemaAtt(schemaNode);
              for (Node xmlns : namespaces.values()) {
                  String nodeName = xmlns.getNodeName();
                  if (!currSchemaAttMap.containsKey(nodeName)) {
                      String namespaceURI = xmlns.getNamespaceURI();
                      String nodeValue = xmlns.getNodeValue();
                      ((Element) schemaNode).setAttributeNS(namespaceURI, nodeName, nodeValue);
                  }
              }
          }
      
          /**
           * Update schema location by adding path. Used at: <br/>
           * &nbsp;&nbsp;&nbsp;&nbsp;<b>getSchemas</b>
           *
           * @param schemaNode
           *            &lt;<b><i>s:schema</i></b>&gt; dom node to update its
           *            location.
           * @return The updated schema.
           */
          private DOMSource updateSchemaLocationByAddingPath(Node schemaNode) {
              DOMSource schemaDomSource = new DOMSource(schemaNode);
              NodeList noteList = schemaDomSource.getNode().getChildNodes();
              for (int j = 0; j < noteList.getLength(); j++) {
                  if ("xsd:import".equals(noteList.item(j).getNodeName())) {
                      NamedNodeMap nodeMap = noteList.item(j).getAttributes();
                      for (int attIndex = 0; attIndex < nodeMap.getLength(); attIndex++) {
                          if ("schemaLocation".equals(nodeMap.item(attIndex).getNodeName())) {
                              nodeMap.item(attIndex).setNodeValue(nodeMap.item(attIndex).getNodeValue());
                          }
                      }
                  }
              }
              return schemaDomSource;
          }
      
          /**
           * Transform a DOMSource schema into a spring's {@link Resource} to be
           * attached to a {@link Jaxb2Marshaller}.
           *
           * @param schemaDomSource
           *            The schema to be transformed.
           * @param transformer
           *            The transformer used.
           * @return A spring's {@link Resource} interface.
           * @throws TransformerException
           */
          private Resource transformToResource(DOMSource schemaDomSource, Transformer transformer)
              throws TransformerException {
              ByteArrayOutputStream outStream = new ByteArrayOutputStream();
              Result result = new StreamResult(outStream);
              transformer.transform(schemaDomSource, result);
              ByteArrayResource schemaResource = new ByteArrayResource(outStream.toByteArray());
              return schemaResource;
          }
      
          /**
           * Generate and retrieves all schemas contained into a wsdl file stored in
           * the classpath, in an {@link Resource} array, to be attached to a
           * {@link Jaxb2Marshaller} .
           *
           * @return An {@link Resource} array.
           * @throws IOException
           * @throws SAXException
           * @throws ParserConfigurationException
           * @throws TransformerException
           */
          public Resource[] getSchemas()
              throws IOException, SAXException, ParserConfigurationException, TransformerException {
              Resource[] schemaResources = null;
      
              WebServiceClient wscAnnotation = Service.class.getAnnotation(WebServiceClient.class);
              String wsdlLocationPath = wscAnnotation.wsdlLocation();
              Resource wsdlResource = resourceLoader.getResource(wsdlLocationPath);
              URL wsdlUri = wsdlResource.getURL();
      
              Transformer transformer = newTransformer();
              Document wsdlDoc = loadWsdlDoc(wsdlUri, transformer);
              NodeList schemaNodes = wsdlDoc.getElementsByTagNameNS(XMLConstants.W3C_XML_SCHEMA_NS_URI, "schema");
              int nrSchemas = schemaNodes.getLength();
              if (nrSchemas > 0) {
                  Element defNode = wsdlDoc.getDocumentElement();
                  Map<String, Node> namespaces = getWsdlDefinedNamespaces(defNode);
      
                  schemaResources = new Resource[nrSchemas];
      
                  for (int i = 0; i < nrSchemas; i++) {
                      Node schemaNode = schemaNodes.item(i);
                      addDefinitionNamespaces(schemaNode, namespaces);
                      DOMSource schemaDomSource = updateSchemaLocationByAddingPath(schemaNode);
                      schemaResources[i] = transformToResource(schemaDomSource, transformer);
                  }
              }
      
              return schemaResources;
          }
      }
      

      applicationContext-xxxx-base.xml

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
          xmlns:context="http://www.springframework.org/schema/context"
          xmlns:jee="http://www.springframework.org/schema/jee" xmlns:mybatis="http://mybatis.org/schema/mybatis-spring"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
                              http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
                              http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.3.xsd
                              http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd">
      
          <mybatis:scan base-package="com.company.integration.xxxx.domain.mybatis.mapper" />
      
          <context:component-scan base-package="com.company.integration.remo" />
      
          <bean id="xxxxMarshallerProperties" class="com.company.integration.xxxx.domain.properties.XxxxMarshallerProperties"/>
      
          <bean id="xxxxMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller" depends-on="xxxxMarshallerProperties">
              <property name="contextPath" value="#{xxxxMarshallerProperties.contextPath}"/>
              <property name="validationEventHandler" value="#{xxxxMarshallerProperties.validationEventHandler}"/>
              <property name="schemas" value="#{xxxxMarshallerProperties.schemas}"/>
          </bean>
      
          <bean id="xxxxService" class="com.company.integration.xxxx.domain.client.XxxxServiceImpl">
              <property name="defaultUri" value="#{'${xxxx.baseUrl}' + '${xxxx.url.sufix}'}" />
              <property name="marshaller" ref="xxxxMarshaller" />
              <property name="unmarshaller" ref="xxxxMarshaller" />
          </bean>
      
          <bean id="xxxxObjectFactory" class="com.company.integration.xxxx.domain.model.ObjectFactory" />
      
      
      </beans>
      

      请注意,我使用的是Jaxb2Marshaller 架构,属性(setSchemas) ,这允许我设置几个模式,而不是只有一个。

      Note that I'm using the Jaxb2Marshaller schemas, property (setSchemas), that allow me to set several schemas, instead of only one.

      这篇关于如何将wsdl内部架构设置为Jaxb2Marshaller以验证我所做的每个帖子?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆