7 Replies Latest reply on Mar 13, 2014 2:11 AM by mageshbk

    Always return a SOAPFault as per the contract

    jorgemoralespou_2

      Hi,

      I have been playing with SwitchYard, and I can't get to do this. I have a SOAP binding, that it is supposed to return always one of the defined SOAPFaults. I need to encapsulate any other fault within my faults.

      If I let the route fail, with a tranformation error, I get a Fault, but not one of Faults that are in the WSDL declared, so in the contract. I would like to wrap the internal fault in my SOAPFault.

       

      How could I implement that? Is there a way of using Interceptors for the SOAPBinding? What kind of interceptors should these be? Should them extend anything?

        • 1. Re: Always return a SOAPFault as per the contract
          jorgemoralespou_2

          I've seen that this might be done via an intercepter, either an InInterceptor or an outInterceptor related to the SOAP Binding.

           

          First thing I noticed is that, at least with the tooling" if I set an interceptor, it gets set for all SOAP Bindings in my composite app. I don't know if this should be like this or not, if whenever adding interceptors to the composite for SOAP Bindings they are added in a general manner :-(

           

          Second thing is that is is very difficult to know what interceptor are configured and in what phases they are configured. I have deployed my own interceptor, to play with it, but haven't been able to hook it where it should be.

          I have followed this post http://i-proving.com/2008/11/03/adding-an-interceptor-to-the-cxf-fault-chain/ (rather outdated) but where something similar to what I want to do is done. I am always getting the SwitchYard exception:

          Caused by: org.switchyard.SwitchYardException: SWITCHYARD010813: Cannot convert from 'com.example.switchyard.jorge.jaxb.Download' to 'com.example.switchyard.jorge.jaxb.VideoDetails'.  No registered Transformer available for transforming from 'java:com.example.switchyard.jorge.jaxb.Download' to 'java:com.example.switchyard.jorge.jaxb.VideoDetails'.  A Transformer must be registered.
          


          No matter what I do.


          Any help would be appreciated.


          Maybe it is a better question to JBossWS or CXF. If so, just let me know.


          • 2. Re: Always return a SOAPFault as per the contract
            kcbabo

            I would do this in a custom message composer.

            Message Composition - SwitchYard - Project Documentation Editor

            • 3. Re: Re: Always return a SOAPFault as per the contract
              jorgemoralespou_2

              I've tried to implement my custom MessageComposer to return my SOAP Fault. For this I have extended SOAPMessageComposer, as I do not want to modify anything but the Exception being generated.

              I do want that, if there is an Exception of type:

              • MyCustomSOAPException: the SOAPFault code to be env:Server
              • UserNotLOggedInException: the SOAPFault code to be env:Security

               

              I want to do a custom Exception to SOAPFault mapping, but being unable. And if I use a MessageComposer, there are still some Exceptions that I will not be able to map, due to the fact that they are being generated/handled after the MessageComposer has executed, in the InboundHandler, or so.

               

              There should be a way to map Exceptions/Faults in an Interceptor, or so, so that I can modify these behavior.

               

              Fault codes are extensible, per the specification: http://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383510

              • 4. Re: Re: Re: Always return a SOAPFault as per the contract
                jorgemoralespou_2

                Hi Keith, I've made it work with a MessageComposer. Still I think there are some gotchas:

                • I have subclassed SOAPMessageComposer, but I don't think this class is meant for subclassing.
                • I have created/mapped the custom Fault in a very basic way. I think there should be helper classes for this. If they are, please, tell me.
                • If error happens outside the scope of what MessageComposers handle, there is no custom Fault possible. For this, I think CXF interceptors should be easier, but my knowledge is very limited.

                 

                I have blogged with the solution, so if anybody else needs it, it is there. http://unpoucode.blogspot.com/2014/03/customize-soap-fault-in-switchyard.html

                • 5. Re: Always return a SOAPFault as per the contract
                  kcbabo
                  • I have subclassed SOAPMessageComposer, but I don't think this class is meant for subclassing.

                   

                  When you create a custom message composer, you have a choice to extend the existing composer or create a new one.  In either case, you need to use the appropriate BindingData for the gateway in use.  Subclassing is A-OK and generally the right way to go.

                   

                  • I have created/mapped the custom Fault in a very basic way. I think there should be helper classes for this. If they are, please, tell me.

                   

                  You have access to the SAAJ message from SOAPBindingData to set the fault details.  Can you elaborate on what helper methods/classes might do to make it easier?

                   

                  • If error happens outside the scope of what MessageComposers handle, there is no custom Fault possible. For this, I think CXF interceptors should be easier, but my knowledge is very limited.


                  CXF interceptors are an option, but even in that scenario there is code which executes after the interceptor.  The purpose of message composers is to provide customized control over the formatting of a message into and out of the system.  No user code executes after decompose() on the return path and there's a limited amount of runtime code.

                  • 6. Re: Always return a SOAPFault as per the contract
                    jorgemoralespou_2

                    When you create a custom message composer, you have a choice to extend the existing composer or create a new one.  In either case, you need to use the appropriate BindingData for the gateway in use.  Subclassing is A-OK and generally the right way to go.

                    Ok. When I subclassed SOAPMessageComposer I wasn't sure on what functionality I could use from a call to super, so if I copied the implementation to tweak it, there was calls to protected/private stuff that I couldn't just use :-( Anyway, calling super did the trick.

                    You have access to the SAAJ message from SOAPBindingData to set the fault details.  Can you elaborate on what helper methods/classes might do to make it easier?

                    You're right. Maybe I'm not proficient on SAAJ to know hot to do it right, and prefer to have a tested utility method that does insert the Fault for me, ensuring that the rest of the message is discarded, that headers are correct, and so...

                     

                    CXF interceptors are an option, but even in that scenario there is code which executes after the interceptor.  The purpose of message composers is to provide customized control over the formatting of a message into and out of the system.  No user code executes after decompose() on the return path and there's a limited amount of runtime code.

                    You are again right.

                     

                    Thanks

                    • 7. Re: Re: Always return a SOAPFault as per the contract
                      mageshbk

                      Maybe I'm not proficient on SAAJ to know hot to do it right, and prefer to have a tested utility method that does insert the Fault for me, ensuring that the rest of the message is discarded, that headers are correct, and so...

                      You can use SOAPUtil for generating fault messages if you prefer.