3

Jax2bを使用してリクエストをアンマーシャリングできるspring-wsプロジェクトを実行していますが、整数/ブール値のアンマーシャリングが失敗すると、詳細がほとんどなく、多くの場合、無効な要素の名前がないエラーメッセージが表示されます。例えば:

org.springframework.oxm.UnmarshallingFailureException: JAXB unmarshalling exception; nested     exception is javax.xml.bind.UnmarshalException
 - with linked exception:
[org.xml.sax.SAXParseException; cvc-datatype-valid.1.2.1: '' is not a valid value for 'integer'.]

これは、私のWebサービスからのSOAPFault応答のコンテンツにもなります。

メッセージを変更して要素名を含めようとしています。ValidationEventHandlerを使用して、イベントハンドラーからRuntimeExceptionをスローすることでメッセージを変更していますが、これは一部の場合にのみ機能します。

ValidationEventHandler:

@Component
public class ValidationEventHandlerImpl implements ValidationEventHandler {

    @Override
    public boolean handleEvent(ValidationEvent event) {

        String message = event.getMessage();
        String linkedMessage = "";
        if(event.getLinkedException() != null)
            linkedMessage = event.getLinkedException().toString();

        boolean ignoreValidationEvent = true;            
        if(message.contains("NumberFormatException") || 
                message.contains("is not a valid value") || 
                linkedMessage.contains("NumberFormatException") || 
                linkedMessage.contains("is not a valid value")){
            ignoreValidationEvent = false;
        }

        if(ignoreValidationEvent){
            return true;
        }else{
            String nodeName = "";
            if(event.getLocator() != null && event.getLocator().getNode() != null)
                nodeName = event.getLocator().getNode().getNodeName();

            //This is the important line
            throw new RuntimeException("Error parsing '" + nodeName + "': " + event.getMessage());

        }
    }

}

正常に変更されます。

JAXB unmarshalling exception; nested exception is javax.xml.bind.UnmarshalException: Not a number: 32g321
 - with linked exception:
[java.lang.NumberFormatException: Not a number: 32g321]

to: RuntimeExceptionメッセージ: " java.lang.RuntimeException:'MyNodeName'の解析中にエラーが発生しました:数値ではありません:32g321 "

(イベントの重大度:エラー)

しかし、変更したい場合は機能しません。

JAXB unmarshalling exception; nested exception is javax.xml.bind.UnmarshalException
 - with linked exception:
[org.xml.sax.SAXParseException; cvc-datatype-valid.1.2.1: '' is not a valid value for 'integer'.]

to: RuntimeExceptionメッセージ: " java.lang.RuntimeException:'MyNodeName'の解析中にエラーが発生しました:''は'integer' "の有効な値ではありません。

RuntimeExceptionは無視され、代わりにSAXParseExceptionがスローされ、SOAPFault応答に追加されます。

(イベントの重大度:FATAL_ERROR)

Jaxb2MarshallingのSpring構成:

<bean id="jaxb2MarshallerContact" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
    <property name="classesToBeBound">
        <list>
            <value>com.model.oxm.ContactRequest</value>
            <value>com.model.oxm.ContactResponse</value>
        </list>
    </property>
    <property name="marshallerProperties">
        <map>
            <entry>
                <key>
                    <util:constant static-field="javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT" />
                </key>
                <value type="boolean">true</value>
            </entry>
            <entry>
                <key>
                    <util:constant static-field="javax.xml.bind.Marshaller.JAXB_FRAGMENT" />
                </key>
                <value type="boolean">true</value>
            </entry>
        </map>
    </property>
    <property name="schema" ref="ContactServiceSchema" />
    <property name="validationEventHandler" ref="validationEventHandlerImpl" />
</bean>

<bean id="ContactServiceSchema" class="org.springframework.core.io.ClassPathResource">
    <constructor-arg value="WEB-INF/schemas/ContactService.xsd" />
</bean> 

終点:

@Endpoint
public class ContactEndpoint {

    private Logger logger = Logger.getLogger(ContactEndpoint.class);

    @Autowired
    private ContactService contactService;

    private static final String NAMESPACE_URI = "http://mydomain/schemas";

    @PayloadRoot(namespace = NAMESPACE_URI, localPart = "ContactRequest")     
    @ResponsePayload
    public ContactResponse handleContactRequest(@RequestPayload ContactRequest contactRequest) throws Exception {
    ...
  • SAXParseExceptionメッセージの代わりにカスタムメッセージを返すにはどうすればよいですか?

  • これを実装するためのより良い方法はありますか?たとえば、ValidationErrorHandlerを使用しますか?

ありがとう!

4

2 に答える 2

2

私はついにこの問題を回避する方法を見つけました。ValidationEventHandlerから新しいRuntimeExceptionをスローする代わりに、イベントにリンクされた例外の抑制された例外として追加しました。

event.getLinkedException().addSuppressed(new RuntimeException(errorMessage));

エンドポイントで、代わりにRequestPayloadのsoapenvelopeを変更しました。marshallingServiceはjax2bmarshallerをラップします。

@PayloadRoot(namespace = NAMESPACE_URI, localPart = "ContactRequest")     
@ResponsePayload
public ContactResponse handleContactRequest(@RequestPayload  SoapEnvelope soapEnvelope) throws Exception {
    ContactRequest contactRequest = marshallingService.unmarshalContact(soapEnvelope.getBody().getPayloadSource());

marshallingServiceは例外をキャッチし、抑制された例外メッセージを抽出して、代わりにそれをスローします。

((UnmarshalException) xmlMappingException.getCause()).getLinkedException().getSuppressed()[0].getLocalizedMessage();

これは洗練されたソリューションではありませんが、エンドポイントは以前よりもはるかに優れたエラーメッセージを生成します。

于 2013-03-14T13:00:35.197 に答える
1

を使ってみましたPayloadValidatingInterceptorか? 私の知る限り、デマーシャリングする前にメッセージを検証します。おそらく、何がうまくいかないのかについての洞察が得られるでしょう。

アプリケーション構成で簡単に設定できます。

private ClassPathResource yourXsdFile = new ClassPathResource("xsd.xsd");

@Bean
public PayloadValidatingInterceptor validatingInterceptor() {
    PayloadValidatingInterceptor interceptor = new PayloadValidatingInterceptor();
    interceptor.setSchema(yourXsdFile);
    interceptor.setAddValidationErrorDetail(true);

    return interceptor;
}

@Bean
public PayloadRootAnnotationMethodEndpointMapping endpointMapping() {
    PayloadRootAnnotationMethodEndpointMapping mapping = new PayloadRootAnnotationMethodEndpointMapping();
    mapping.setInterceptors(new EndpointInterceptor[]{
        validatingInterceptor()
    });

    return mapping;
}

詳細については、 API ドキュメントをご覧ください。

于 2013-02-04T08:48:54.273 に答える