Page 2 of 3 FirstFirst 123 LastLast
Results 11 to 20 of 21

Thread: Wanting to return the message from a custom Exception as a SOAP Fault string

  1. #11
    Join Date
    Mar 2006
    Location
    Germany, Karlsruhe
    Posts
    157

    Default

    Hi,

    thank you very much for your code!
    I think it really helps me a lot. But it's sad, that we have to add a QName, because this drives us to ugly code.
    Maybe Arjen will add another method, if he reads this thread again.

    I'll try the same like you did with JDOM, but with the standard marshaller object which is also used for MarshallingPayloadEndpoints.
    I hope i get it work.

    Thank you very much again,

    Ingo

  2. #12
    Join Date
    Jul 2005
    Location
    Rotterdam, the Netherlands
    Posts
    1,562

    Default

    You're right, the code you will need to write is quite verbose. I will think about adding a new way to be able to use a marshaller to populate the detail entry.
    Arjen Poutsma

    Spring Web Services Dev Lead
    Please read the FAQ

  3. #13
    Join Date
    Mar 2006
    Location
    Germany, Karlsruhe
    Posts
    157

    Default

    I have a first version which is working, but not heavily tested.
    "eimFault" is my application fault bean, which will be written to the <details> tag.

    Code:
    DOMResult domResult = new DOMResult();
    try {
      marshaller.marshal(eimFault, domResult);
    } catch (XmlMappingException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
    
    Node node = domResult.getNode();
    Node faultNameNode = node.getFirstChild();
    QName faultNameAsQName = new QName(faultNameNode.getNamespaceURI(), faultNameNode.getLocalName(), faultNameNode.getPrefix());
    
    NodeList faultNameChilds = faultNameNode.getChildNodes();
    
    // add qname which is the first element of the details element        
    SoapFaultDetailElement faultDetailElement = faultDetail.addFaultDetailElement(faultNameAsQName);
            
    try {
      Transformer transformer = TransformerFactory.newInstance().newTransformer();
    
      // write all children to the details element
      for(int i=0; i<faultNameChilds.getLength(); i++) {
        Node child = faultNameChilds.item(i);
        DOMSource childAsDOMSource = new DOMSource(child);
    	        	
        transformer.transform(childAsDOMSource, faultDetailElement.getResult());
      }
    } catch(TransformerConfigurationException confException) {
      confException.printStackTrace();
    } catch (TransformerException transformerException) {
      transformerException.printStackTrace();
    }
    What do you think?
    Any bad mistakes?

    Cheers,

    Ingo

  4. #14
    Join Date
    Jul 2005
    Location
    Rotterdam, the Netherlands
    Posts
    1,562

    Default

    I've added a getResult() to SoapFaultDetail, so that you can use a marshaller to directly marshal into the detail. The usage of addFaultDetailElement is no longer required.
    Arjen Poutsma

    Spring Web Services Dev Lead
    Please read the FAQ

  5. #15
    Join Date
    Sep 2007
    Posts
    8

    Default step from tutorial

    Hi,
    Let say I'm a beginner and I want to use SoapFaultDetail...
    I just did the tutorial and I'm using the AbstractJDomPayloadEndpoint.
    For me everything start with protected Element invokeInternal(Element) how can I generate a fault from there... I'm new to spring and I find it difficult to identify bean required to manage my exception. OK let say I install an exception resolver and that give me access to a WebServiceMessage or SoapFaultDefinition how does that link to a SoapFault?

    Thanks
    mapospring

  6. #16
    Join Date
    Sep 2007
    Posts
    8

    Default

    I finally build my own resolver and got access to customizeFault(...).
    So Arjen suggested:
    Well, it's not a good idea to cast the Result to a StaxResult directly. It's better to create a Source (DOMSource or StreamSource), and to transform that source to the result, like so: code ...
    I try the call
    Code:
    transformer.transform(elSource, el.getResult());
    but only the first part was in the fault message missing the errorCode? Like this:

    Code:
              
      <detail>
        <e:myfaultdetails xmlns:e="Some-URI">
          <message>
            My application didn't work
          </message>
        </e:myfaultdetails>
      </detail>
    What could be the problem?

    thanks

  7. #17
    Join Date
    Jul 2005
    Location
    Rotterdam, the Netherlands
    Posts
    1,562

    Default

    Could you perhaps list the entire piece of code that's in the exception resolver?
    Arjen Poutsma

    Spring Web Services Dev Lead
    Please read the FAQ

  8. #18
    Join Date
    Sep 2007
    Posts
    8

    Default

    Hi,
    It looks like the transformer does not like the format of the xml message if they are not within a element. If I add a dummy test element it's working:
    Code:
      
    <detail>
        <e:myfaultdetails xmlns:e="Some-URI">
          <test>
            <message>
              My application didn't work
            </message>
            <text>
               More information...
            </text>
          </test>
        </e:myfaultdetails>
      </detail>
    Here is the code:

    Code:
       
    private static final QName SERVICE_EXCEPTION_QNAME = new QName("http://www.mycompagny.com/services/project/wsdl/holiday", "ServiceExceptionDetail", "holi");
    
       @Override
       protected void customizeFault(Object endpoint, Exception serviceException, SoapFault soapFault)
       {
          try
          {
             assert serviceException instanceof ProjectWebServiceException:"exception should be instanceof ProjectWebServiceException";
             ProjectWebServiceException pwsException = (ProjectWebServiceException) serviceException;
             SoapFaultDetail soapFaultDetail = soapFault.addFaultDetail();
             ServiceExceptionDetail sed = pwsException.getDetails();
             SoapFaultDetailElement el = soapFaultDetail.addFaultDetailElement(SERVICE_EXCEPTION_QNAME);
             Source elSource = new StringSource(createXmlServiceExceptionDetails(sed));
             
             Transformer transformer;
             transformer = TransformerFactory.newInstance().newTransformer();
             transformer.transform(elSource, el.getResult());
          }
          catch(TransformerConfigurationException e)
          {
             e.printStackTrace();
          }
          catch(TransformerFactoryConfigurationError e)
          {
             e.printStackTrace();
          }
          catch(TransformerException e)
          {
             e.printStackTrace();
          }
       }
    
       private static String createXmlServiceExceptionDetails(ServiceExceptionDetail exDetail)
       {
          StringBuilder sb = new StringBuilder();
          //sb.append("<test>"); //Its working if I use that dummy element level.
          sb.append("<messageId>\n\t").append(exDetail.getMessageId()).append("\n</messageId>");
          sb.append("<text>\n\t").append(exDetail.getText()).append("\n</text>");
          //sb.append("</test>");
          return sb.toString();
       }
    I try to modify the xml message by using "\n\t" or spaces or nothing between element but its always the same result.

    mapospring

  9. #19
    Join Date
    Sep 2007
    Posts
    8

    Default

    I guess a good night of sleep solve most of my problems!

    To be able to create the details with multiple elements I had to call the transformer more then once with one element for each call:

    Code:
             
    transformer.transform(new StringSource("<funny> part </funny>"), el.getResult());         
    transformer.transform(new StringSource("<strange> test </strange>"), el.getResult());
    The code is a bit ugly but now its working!

  10. #20

    Default

    instead of calling transformer multiple times to add into the details, that makes the code look ugly. another way could be to use StreamSouce in the transformer


    StreamSource sc = new StreamSource(new ByteArrayInputStream(sb.toString().getBytes("UTF-8")));

    populate all your soapfault detail XML in sb = StringBuffer()

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •