2010-11-08 15 views
5

Sto provando a scrivere un servizio Web utilizzando la libreria del servizio Web Spring. Sono in grado di configurare i miei endpoint correttamente e sta funzionando bene, ma sto affrontando alcuni problemi con i mapping delle eccezioni.Come creare un messaggio di errore del sapone personalizzato utilizzando il servizio Web Spring

sono in grado di mappare le eccezioni utilizzando @SoapFault e SoapFaultAnnotationExceptionResolver ma la definizione WSDL è la seguente

<xsd:schema elementFormDefault="qualified" targetNamespace="http://abc.com/soap/"> 
    <xsd:complexType name="ServiceException"> 
     <xsd:sequence> 
      <xsd:element name="message" nillable="true" type="xsd:string"/> 
     </xsd:sequence> 
    </xsd:complexType> 

    <xsd:complexType name="ValidationException"> 
     <xsd:complexContent> 
      <xsd:extension base="tns:ServiceException"> 
       <xsd:sequence/> 
      </xsd:extension> 
     </xsd:complexContent> 
    </xsd:complexType> 

    <xsd:complexType name="InternalException"> 
     <xsd:complexContent> 
      <xsd:extension base="tns:ServiceException"> 
       <xsd:sequence/> 
      </xsd:extension> 
     </xsd:complexContent> 
    </xsd:complexType> 

    <xsd:complexType name="AuthenticationException"> 
     <xsd:complexContent> 
      <xsd:extension base="tns:ServiceException"> 
       <xsd:sequence/> 
      </xsd:extension> 
     </xsd:complexContent> 
    </xsd:complexType> 

    <xsd:complexType name="LoginInput"> 
     <xsd:sequence> 
      <xsd:element minOccurs="1" maxOccurs="1" name="UserName" nillable="false" type="xsd:string"/> 
      <xsd:element minOccurs="1" maxOccurs="1" name="PassWord" nillable="false" type="xsd:string"/> 
     </xsd:sequence> 
    </xsd:complexType> 

    <xsd:complexType name="LoginOutput"> 
     <xsd:sequence> 
      <xsd:element minOccurs="1" maxOccurs="1" name="ValidTo" nillable="false" type="xsd:dateTime"/> 
     </xsd:sequence> 
    </xsd:complexType> 

    <xsd:element name="login" type="tns:LoginInput"/> 
    <xsd:element name="loginResponse" type="tns:LoginOutput"/> 

    <xsd:element name="ValidationException" type="tns:ValidationException"/> 
    <xsd:element name="InternalException" type="tns:InternalException"/> 
    <xsd:element name="AuthenticationException" type="tns:AuthenticationException"/> 
</xsd:schema> 

<message name="LoginRequest"> 
    <part name="login" element="tns:login"/> 
</message> 

<message name="LoginResponse"> 
    <part name="loginResponse" element="tns:loginResponse"/> 
</message> 

<message name="ValidationException"> 
    <part name="ValidationException" element="tns:ValidationException"/> 
</message> 

<message name="InternalException"> 
    <part name="InternalException" element="tns:InternalException"/> 
</message> 

<message name="AuthenticationException"> 
    <part name="AuthenticationException" element="tns:AuthenticationException"/> 
</message> 

<portType name="ServicePortType"> 
    <operation name="Login"> 
     <input message="tns:LoginRequest"/> 
     <output message="tns:LoginResponse"/> 
     <fault name="ValidationException" message="tns:ValidationException"/> 
     <fault name="InternalException" message="tns:InternalException"/> 
     <fault name="AuthenticationException" message="tns:AuthenticationException"/> 
    </operation> 
</portType> 

<binding name="ServiceBinding" type="tns:ServicePortType"> 
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> 
    <operation name="Login"> 
     <soap:operation soapAction="urn://Service#Login"/> 
     <input> 
      <soap:body use="literal"/> 
     </input> 
     <output> 
      <soap:body use="literal"/> 
     </output> 
     <fault name="ValidationException"> 
      <soap:fault name="ValidationException" use="literal"/> 
     </fault> 
     <fault name="InternalException"> 
      <soap:fault name="InternalException" use="literal"/> 
     </fault> 
     <fault name="AuthenticationException"> 
      <soap:fault name="AuthenticationException" use="literal"/> 
     </fault> 
    </operation> 
</binding> 

Come posso scrivere un trattamento per questa definizione di servizio eccezione?

Grazie

risposta

7

Dopo un po 'più di ricerca ho trovato this from spring source forum.

SoapMessage response = (SoapMessage) messageContext.getResponse(); 
SoapBody soapBody = response.getSoapBody(); 

SoapFault soapFault = 
soapBody.addClientOrSenderFault(ex.getMessage(), Locale.ENGLISH); 

SoapFaultDetail faultDetail = soapFault.addFaultDetail(); 
Result result = faultDetail.getResult(); 

// My detail XML object 
InvalidArgumentFault fault = new InvalidArgumentFault(); 
fault.setErrorCode("Custom Error Code"); 
fault.setOpsMessage("This is the ops message"); 
fault.setSystemMessage("This is the system message"); 

// Marshal the detail. We have to use the ObjectFactory which isn't 
// marshaller agnostic because the detail element doesn't have an 
// XmlRootElement tag as required by JAXB. 
ObjectFactory of = new ObjectFactory(); 
mMarshaller.marshal(of.createInvalidArgumentFault(fault), result); 

AGGIORNATO

Questo un completo implementazioni di esempio che sto usando,

import java.lang.reflect.Method; 
import java.util.Collection; 
import java.util.HashMap; 
import java.util.Locale; 
import java.util.Map; 

import javax.xml.transform.Result; 

import org.apache.commons.logging.Log; 
import org.apache.commons.logging.LogFactory; 
import org.springframework.beans.BeansException; 
import org.springframework.context.ApplicationContext; 
import org.springframework.context.ApplicationContextAware; 
import org.springframework.oxm.Marshaller; 
import org.springframework.ws.context.MessageContext; 
import org.springframework.ws.server.endpoint.AbstractEndpointExceptionResolver; 
import org.springframework.ws.soap.SoapBody; 
import org.springframework.ws.soap.SoapFault; 
import org.springframework.ws.soap.SoapFaultDetail; 
import org.springframework.ws.soap.SoapMessage; 

import org.apache.commons.lang.StringUtils; 

public class CustomSoapFaultDetailAnnotationExceptionResolver extends 
     AbstractEndpointExceptionResolver implements ApplicationContextAware { 
    private static Log log = LogFactory 
      .getLog(CustomSoapFaultDetailAnnotationExceptionResolver.class); 

    private Collection<Marshaller> marshallers; 

    private Map<Class<? extends Object>, Marshaller> marshallerMap = new HashMap<Class<? extends Object>, Marshaller>(); 

    public CustomSoapFaultDetailAnnotationExceptionResolver() { 
     setWarnLogCategory(getClass().getCanonicalName()); 
    } 

    @Override 
    protected boolean resolveExceptionInternal(MessageContext messageContext, 
      Object endpoint, Exception ex) { 
     boolean resolved = false; 

     try { 
      CustomSoapFaultDetails annotation = ex.getClass().getAnnotation(
        CustomSoapFaultDetails.class); 
      if (annotation != null) { 

       Method m = ex.getClass().getMethod("getFaultInfo", 
         new Class[] {}); 
       Object fault = m.invoke(ex, new Object[] {}); 

       SoapMessage response = (SoapMessage) messageContext 
         .getResponse(); 
       SoapBody soapBody = response.getSoapBody(); 

       SoapFault soapFault = soapBody 
         .addClientOrSenderFault(
           StringUtils.isBlank(ex.getMessage()) ? "server exception" 
             : ex.getMessage(), Locale.ENGLISH); 

       SoapFaultDetail faultDetail = soapFault.addFaultDetail(); 
       Result result = faultDetail.getResult(); 

       if (marshallerMap.containsKey(fault.getClass())) { 
        marshallerMap.get(fault.getClass()).marshal(fault, result); 
        resolved = true; 
       } else { 
        for (Marshaller marshaller : marshallers) { 
         try { 
          marshaller.marshal(fault, result); 
          marshallerMap.put(fault.getClass(), marshaller); 
          resolved = true; 
          break; 
         } catch (Exception e) { 
          // Ignore error 
         } 
        } 
       } 
      } 
     } catch (Exception e) { 
      log.error(e.toString(), e); 
     } 
     return resolved; 
    } 

    @Override 
    public void setApplicationContext(ApplicationContext applicationContext) 
      throws BeansException { 
     this.marshallers = applicationContext.getBeansOfType(Marshaller.class) 
       .values(); 
    } 
} 
+0

Da dove stai tirando 'mMarshaller'? –

+0

@ Mark, ho aggiornato la risposta. Per favore fatemi sapere se avete qualche suggerimento. –

+0

Speravo che tu fossi riuscito a pescare fuori dal 'MessageEndpoint' da qualche parte, ma alla fine io lo inietto come te. –

2

Ho usato con successo SOAP Primavera-WS per creare un servizio web. Ora stavo facendo l'attuazione colpa in questo servizio SOAP e sono stato in grado di farlo con una classe che ho creato come il seguente,

public class ServiceSoapFaultMappingExceptionResolver extends SoapFaultMappingExceptionResolver 

e dentro la seguente funzione override,

@Override 


protected void customizeFault(Object endpoint, Exception ex, SoapFault fault) { 

//code for adding fault details 

    SoapFaultDefinition soapFaultDefinition = new SoapFaultDefinition(); 
    String ENVELOPE_NAMESPACE_URI = "http://schemas.xmlsoap.org/soap/envelope/"; 

    //  soapFaultDefinition.setFaultStringOrReason("--" + ex); 

    //  soapFaultDefinition.setLocale(Locale.ENGLISH); 

    QName CLIENT_FAULT_NAME = new QName(ENVELOPE_NAMESPACE_URI,"5003", "e"); 
    soapFaultDefinition.setFaultCode(CLIENT_FAULT_NAME); 
    setDefaultFault(soapFaultDefinition); 
    Result result = fault.addFaultDetail().getResult(); 

     // marshal 
     try { 
      JAXBContext.newInstance(ExceptionListType.class).createMarshaller().marshal(exceptionList, result); 

} 

prega this answer per la soluzione originale.

+0

Sebbene ciò possa teoricamente rispondere alla domanda, [sarebbe preferibile] (http://meta.stackoverflow.com/q/8259) includere qui le parti essenziali della risposta e fornire il link per riferimento. – chappjc

+0

ok.i farà il necessario. –

+1

@Himanshu si prega di vedere la risposta aggiornata è ok. –

Problemi correlati