【问题标题】:validate parts of the incoming web service request lazily in JAX-WS RI在 JAX-WS RI 中延迟验证部分传入的 Web 服务请求
【发布时间】:2016-05-27 16:51:23
【问题描述】:

我必须在 Java 8 Web 服务 (JAX-WS RI) 中处理大请求。一个请求包含一个“标头”和许多这样的“记录”(不是第 2、3、4、5 个学生记录根据架构无效):

<helloStudentsServiceRequest>
    <workshop>
        <name>wsname</name>
        <tutor>tutorname</tutor>
    </workshop>
    <studentList>
        <!--1 or more repetitions: -->
        <student>
            <Name>st1</Name>
            <Birth>1999-11-11</Birth>
        </student>
        <student>
            <Name>st2</Name>
        </student>
        <student>
            <Name>st2</Name>
            <Birth>199O-11-11</Birth>
        </student>
        <student>
            <Name>st3</Name>
            <Birth>stoneage</Birth>
        </student>
        <student>
            <Birth>stoneage</Birth>
        </student>
        <student>
            <Name>st6</Name>
            <Birth>2001-11-12</Birth>
        </student>
    </studentList>
</helloStudentsServiceRequest>

我使用模式 (XSD) 来描述我的界面。例如:

<xsd:complexType name="HelloStudentsServiceRequestType">
    <xsd:sequence>
        <xsd:element name="workshop" type="WorkshopType" />
        <xsd:element name="studentList">
            <xsd:complexType>
                <xsd:sequence>
                    <xsd:element name="student" type="StudentType" maxOccurs="unbounded"/>
                </xsd:sequence>
            </xsd:complexType>
        </xsd:element>
    </xsd:sequence>
</xsd:complexType>
<xsd:complexType name="WorkshopType">
    <xsd:sequence>
        <xsd:element name="name" type="xsd:string" />
        <xsd:element name="tutor" type="xsd:string" />
    </xsd:sequence>
</xsd:complexType>
<xsd:complexType name="StudentType">
</xsd:annotation>
    <xsd:sequence>
        <xsd:element name="Name" type="xsd:string" />
        <xsd:element name="Birth" type="xsd:date" />
    </xsd:sequence>
</xsd:complexType>

我想使用此架构来验证请求。

但是,如果其中的一些“记录”根据架构无效,我不允许拒绝请求。在这种情况下,我必须处理有效记录并返回一些关于无效记录的有意义的信息(最好是 SAX 错误)。

我想让请求的架构不包含完成此“延迟验证”所需的技术细节。例如我不想使用“大字符串”来保存“记录”,然后根据架构验证该字符串。这会破坏界面并且难以与客户沟通。所以这对我来说是不行

...
<xsd:element name="studentList">
    <xsd:complexType>
        <xsd:sequence>
            <xsd:element name="student" type="xsd:string" maxOccurs="unbounded"/>
        </xsd:sequence>
    </xsd:complexType>
</xsd:element>
...

您知道在 JAX-WS RI (JAXB2) 中解决此问题的优雅方法吗?

【问题讨论】:

    标签: java web-services validation xsd lazy-evaluation


    【解决方案1】:

    可以自定义 JAXB 绑定以将部分 XML 映射到 DOM。详情:

    https://jaxb.java.net/guide/Avoid_strong_databinding.html#Mapping_to_DOM

    所以我将“WorkshopType”和“StudentType”映射到 DOM。现在可以单独验证这些 DOM 并拒绝或部分处理传入的消息。如果 DOM 验证不成功,也可以捕获 SAX 异常并将其发回给客户端。

    working example zipped

    我使用了这个绑定自定义:

    <jxb:bindings version="1.0" 
    xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <jxb:bindings
        schemaLocation="WorkshopType.xsd"
        node="//xsd:complexType[@name='WorkshopType']">
        <jxb:dom />
    </jxb:bindings> 
    <jxb:bindings
        schemaLocation="StudentType.xsd"
        node="//xsd:complexType[@name='StudentType']">
        <jxb:dom />
    </jxb:bindings> 
    

    这些是架构:

    对于请求:

    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    elementFormDefault="qualified" xmlns="helloStudentsNS"
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0"
    targetNamespace="helloStudentsNS">
    
    <xsd:include schemaLocation="StudentType.xsd" />
    <xsd:include schemaLocation="WorkshopType.xsd" />
    
    <xsd:element name="helloStudentsServiceRequest" type="HelloStudentsServiceRequestType" />
    <xsd:element name="helloStudentsServiceResponse" type="HelloStudentsServiceResponseType" />
    
    <xsd:complexType name="HelloStudentsServiceRequestType">
        <xsd:sequence>
            <xsd:element name="workshop" type="WorkshopType" />
            <xsd:element name="studentList">
                <xsd:complexType>
                    <xsd:sequence>
                        <xsd:element name="student" type="StudentType" maxOccurs="unbounded"/>
                    </xsd:sequence>
                </xsd:complexType>
            </xsd:element>
        </xsd:sequence>
    </xsd:complexType>
    
    <xsd:complexType name="HelloStudentsServiceResponseType">
        <xsd:sequence>
            <xsd:element name="GreetingHeader" type="xsd:string" />
            <xsd:element name="StudentGreeting" type="xsd:string" maxOccurs="unbounded"/>
        </xsd:sequence>
    </xsd:complexType>
    

    对于研讨会和学生类型:

    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    elementFormDefault="qualified" 
    xmlns="helloStudentsNS"
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" 
    jaxb:version="2.0"
    targetNamespace="helloStudentsNS">
    
    <xsd:element name="workshop" type="WorkshopType"/>
    
    <xsd:complexType name="WorkshopType">
        <!-- <xsd:annotation><xsd:appinfo><jaxb:dom/></xsd:appinfo></xsd:annotation> -->
        <xsd:sequence>
            <xsd:element name="name" type="xsd:string" />
            <xsd:element name="tutor" type="xsd:string" />
        </xsd:sequence>
    </xsd:complexType>
    

    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    elementFormDefault="qualified" 
    xmlns="helloStudentsNS" 
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
    jaxb:version="2.0" targetNamespace="helloStudentsNS">
    
    <!-- 
    -->
    <xsd:element name="student" type="StudentType"/> 
    
    <xsd:complexType name="StudentType">
        <!-- <xsd:annotation><xsd:appinfo><jaxb:dom/></xsd:appinfo></xsd:annotation> -->
        <xsd:sequence>
            <xsd:element name="Name" type="xsd:string" />
            <xsd:element name="Birth" type="xsd:date" />
        </xsd:sequence>
    </xsd:complexType>
    

    这是java代码:

    public HelloStudentsServiceResponseType greetStudents(HelloStudentsServiceRequestType req) {
    
        WorkshopType ws;
        // unmarshall workshop data
        Element element = req.getWorkshop(); // workshop is retrieved as DOM 
        try {
            Unmarshaller u = jc.createUnmarshaller(); // jaxb ri unmarshaller not thread safe: https://jaxb.java.net/guide/Performance_and_thread_safety.html
            u.setSchema(workshopSchema); // enable validation by workshopType.xsd
            ws = u.unmarshal(element, WorkshopType.class).getValue(); // unmarshal
        } catch (JAXBException e) {
            // this is fatal
            throw new RuntimeException("fatal: invalid workshop data: ", e);
        }
    
        // unmarshall students
        List<String> studentGreetings = new ArrayList<>();
        for(Element studentElement : req.getStudentList().getStudent()) { // retrieve students as DOMs
            try {
                StudentType st;
                Unmarshaller u = jc.createUnmarshaller(); // jaxb ri unmarshaller not thread safe: https://jaxb.java.net/guide/Performance_and_thread_safety.html
                u.setSchema(studentSchema); // enable validation by studentType.xsd
                st = u.unmarshal(studentElement, StudentType.class).getValue();
                studentGreetings.add("Dear " + st.getName() + ", " + st.getBirth() + ", welcome in the workshop!");
            } catch (JAXBException e) {
                Throwable cause = e.getLinkedException();
                if(cause != null) {
                    studentGreetings.add("Dear student, your data is invalid: " + cause.getMessage());
                }
                else {
                    studentGreetings.add("Dear student, there's an unknown problem with your data");
                }
            }
        }
    
        // construct response
        HelloStudentsServiceResponseType response = new HelloStudentsServiceResponseType();
        response.setGreetingHeader("I'd like to greet everybody in the " + ws.getName() + " workshop. " +
                "Your tutor is " + ws.getTutor());
        response.getStudentGreeting().addAll(studentGreetings);
    
        return response;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-17
      • 2012-01-05
      • 1970-01-01
      • 2011-02-24
      • 2010-12-16
      相关资源
      最近更新 更多