2010-11-08 11 views
5

Estoy intentando escribir un servicio web usando la biblioteca de servicios web de Spring. Puedo configurar mis puntos finales con éxito y funciona bien, pero estoy enfrentando algunos problemas con las asignaciones de excepciones.Cómo crear un mensaje de falla de jabón personalizado usando el servicio web de primavera

soy capaz de asignar excepciones utilizando @SoapFault y SoapFaultAnnotationExceptionResolver pero la definición WSDL es el siguiente

<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> 

¿Cómo puedo escribir una dirección para este Definición del servicio de excepción?

Gracias

Respuesta

7

Después de algún búsqueda más encontré 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); 

ACTUALIZADO

Esto muestra un completo implementaciones que estoy 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

¿De dónde sacas el 'mMarshaller' de? –

+0

@Mark, he actualizado la respuesta. Por favor, hágamelo saber si tiene alguna sugerencia. –

+0

Tenía la esperanza de que lograra pescarlo fuera del 'MessageEndpoint' en alguna parte, pero en última instancia, la dependencia lo inyecta como lo hace. –

2

he utilizado con éxito de SOAP Primavera-WS para crear un servicio web. Ahora que estaba haciendo la aplicación falla en este servicio SOAP y yo era capaz de hacerlo con una clase que he creado como la siguiente,

public class ServiceSoapFaultMappingExceptionResolver extends SoapFaultMappingExceptionResolver 

y dentro del siguiente función reemplazada,

@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); 

} 

favor this answer para la solución original.

+0

Si bien esto podría responder teóricamente a la pregunta, [sería preferible] (http://meta.stackoverflow.com/q/8259) incluir aquí las partes esenciales de la respuesta y proporcionar el enlace de referencia. – chappjc

+0

ok.i hará lo necesario. –

+1

@Himanshu, por favor, vea que la respuesta actualizada está bien. –

Cuestiones relacionadas