12 Replies Latest reply on Feb 2, 2011 7:22 AM by tfennelly

    Get the SOAP + Bean components working smootly together

    tfennelly

      I've been doing some work on SWITCHYARD-59:

       

       

      The point of this task is to get the SOAP and Bean components working more smootly together.  We want to be able to easily invoke a bean component through the SOAPGateway.  To make that work, we obviously need transformations applied as part of the Exchange mechanism in order to transform between the SOAP and Java domains... SOAP -> Java on the IN, Java to SOAP on the way OUT.  So this work required changes in the following areas:

       

      • Transformation related code changes to core in order to support the concept of a TransformSequence (ala pipelines) on an exchange.  Also support fault exception transformation (e.g. transform an Exception into a SOAP fault).
      • Modifications to the SOAP component for attaching IN and OUT TransformSequence info to the Exchange.  The SOAP component uses the wsdl port + the target service operation metadata to work out the data types at each end of the IN and OUT phases of an Exchange.  This data creates the TransformSequences.  Magesh... would be great if you could review these changes too please!!
      • A small mod to the CDI extension that automatically registers all beans that implement the Transformer interface (in the domain TransformerRegistry).  This is experimental, but I do think it's quite neat.  I also think we should (if it's kept) have a way of contolling it e.g. that the Transformer must have something like an @AutoLoad annotation for it to be automatically loaded into the transformation registry.
      • A "Greeting" bean Service test example (in components/tests).  The interface to this service uses semi-complex domain objects (i.e. more than just basic String/Number value types ala a Hello World example).  Intentionally did this so as to exercise the transformation parts of the puzzle.

       

      Still aving an issue with the transformation of Faults.  I have a test there that generates an exception, which gets transformed into a soap fualt that looks OK.  I'm just getting a 500 error from the test http invoker.  Might be an issue with the test, but not sure.

        • 1. Re: Get the SOAP + Bean components working smootly together
          tfennelly

          A high level walk through screencast of the example "GreetingService".  It's rough as hell, but we may as well share it anyway http://www.screencast.com/t/85kxYxF6Cs6e

           

          Some people had issues viewing it on screencast.com... here is is on youtube... http://www.youtube.com/watch#!v=hFDOl_EzI8Y

          • 2. Get the SOAP + Bean components working smootly together
            kcbabo

            There's a lot of ground to cover here, so I'm gonna cover feedback to the core changes in this reply and the component changes in a separate reply.  From what I see so far, this is pretty dang cool.

             

            TransformSequence - I think this is top notch.  Haven't had a chance to really play with it yet, but I definitely like the direction.

             

            PayloadTypeName - I'm not sure I get this one.  A potential use I see is if you have a naming strategy that's different from the (admittedly ugly) class+operation+parameter format used by default.  But that doesn't appear to be the way it's used currently.  Seems more like it's a workaround to address the fact that we don't have a standard type name for HandlerException when it's used as the content of a fault message.  Is that right?  If so, seems reasonable and it looks useful in your test code.  BTW, we should probably move this annotation and the JavaService class to org.switchyard.metadata.java.  We also need to add a getFaultName() method to ServiceOperation, right?

             

            ServiceOperation.Name - this is probably the thing I like the least about the changes.  I realize you did it to standardize on the naming of operation name in the context.  I wonder if we should have a specific ExchangeContext interface with a getOperationName() method?

             

            TransformHandler - I mostly agree that the locateExplicitTransform isn't required now.  I'm fine with dropping it and re-adding it when a specific requirement surfaces.

             

            TransformHandler "static String toMessageType" seems like a weird place to put this method.  I think the public contract for a handler should be what's defined in the ExchangeHandler interface and any utility methods should be move to another class.

             

            ExchangeImpl - hack upon hack.  My fault .  We need to fix this pronto.  And you can save the "I told you so". 

             

            ServiceDomains - lose getRegistry() in this class since it's not necessary.  I'm hopefully going to rip out this entire class in the next week.

             

            Anything else I didn't cover above looks good to me.  Looking at the component changes next ....

            • 3. Get the SOAP + Bean components working smootly together
              kcbabo

              Invocation - I don't quite get why assertOK() exists.  Seems like this tests whether transformation happened vs. just testing to make sure the message type matches the method parameter.  I have a feeling I'm missing a nuance here.

               

              SwitchYardCDIExtension - discovery of Transformer instances seems reasonable to me, although I wonder whether this should be done by the Bean container of if it should be done by the SwitchYardDeployer (i.e. part of our general application deployment framework).

               

              DefaultMessageDecomposer - I would really like to see us avoid coding converter logic into individual components.  The SOAP gateway expects XML and that can come in a bunch of forms : byte[], String, InputStream, Reader, Element, Node, XMLStreamReader, Source, etc, etc.  We should use our own super awesome transformation framework to handle these cases.

               

              HandlerExceptionTransformer - any reason why we're not using a typed Transformer definition here : e.g. Transformer<HandlerException, String> ?

               

              InboundHandler - is it possible for the runtime to assign a TransformSequence based on the message name in the exchange and the service operation's message name?  This would replace associateInTransformSequence and associateOutTransformSequence in InboundHandler.

               

              TransformSequence - the cacheOutput and cacheFault methods seem a bit funky to me.  I realize why they are there, I'm just wondering if there's another way to go about it.  This is probably tied to the whole input/output phase thing you have been talking about.

               

              SOAPGatewayTest - you replaced the system properties, with hard-coded values.  Currently, these are configured in the pom if I'm not mistaken.

               

              JavaReplyToSOAP : you can extend BaseTransformer and use the typed Transformer here, Transformer<String, String>.  Re: your note in the TODO, the reason I included method name in the message name is to address the case where a transform is different depending on the method being invoked.  So if you have two service operations that both transform from String to Date, but you won't different transformers for each method.

               

              Nice test. :-)

              • 4. Re: Get the SOAP + Bean components working smootly together
                tfennelly
                Keith:
                PayloadTypeName - I'm not sure I get this one.  A potential use I see is if you have a naming strategy that's different from the (admittedly ugly)
                class+operation+parameter format used by default.  But that doesn't appear to be the way it's used currently.  Seems more like it's a workaround 
                to address the fact that we don't have a standard type name for HandlerException when it's used as the content of a fault message.  Is that right?  
                If so, seems reasonable and it looks useful in your test code.  BTW, we should probably move this annotation and the JavaService class to 
                org.switchyard.metadata.java.  We also need to add a getFaultName() method to ServiceOperation, right?
                
                

                 

                Right, and I explicitly made that annotation @Inherited.  My immediate use for it was on the HandlerException class and because it's inherited, it means we have a generalized data type for all our exceptions, unless a specific implementation of HandlerException redefine that annotation themselves (if they want a different transform).  So in the case of the soap component, I added that general HandlerExceptionTransform which will transform any HandlerException type (sent as a fault payload) to a SOAP Fault.  So I think it's a useful enough way of supporting the creation of generalized transformers for family of types.

                 

                Keith:
                ServiceOperation.Name - this is probably the thing I like the least about the changes.  I realize you did it to standardize on the naming of
                operation name in the context.  I wonder if we should have a specific ExchangeContext interface with a getOperationName() method?
                
                

                 

                Yeah… that's a bit shit for sure   Yes… I think making the ServiceOperation (from the ServiceInterface) available on the Exchange makes sense (not just the operation name).

                 

                Keith:
                TransformHandler "static String toMessageType" seems like a weird place to put this method.  I think
                the public contract for a handler should be what's defined in the ExchangeHandler interface and any 
                utility methods should be move to another class.
                
                

                Yeah… I was just being a bit lazy tbh.  I wasn't sure at the time where to put it and so just left it there.  I think it's doing stuff similar to what the JavaService class does, so should be rolled in there somewhere.

                 

                Keith:
                Invocation - I don't quite get why assertOK() exists.  Seems like this tests whether transformation
                happened vs. just testing to make sure the message type matches the method parameter.  I have a
                feeling I'm missing a nuance here.
                
                

                 

                It does a bit more than just check if transforms were applied, even just for that, I think it's more appropriate to check if the actual defined transform sequence was applied because what if the resulting java type of the transform was the same as the input type to the transform?  Your java type check would pass, but the content of the instance is probably not what it should be.

                 

                Keith:
                SwitchYardCDIExtension - discovery of Transformer instances seems reasonable to me, although I
                wonder whether this should be done by the Bean container of if it should be done by the
                SwitchYardDeployer (i.e. part of our general application deployment framework).
                
                

                 

                Yeah… I have a feeling this will go.  I like the convenience of it, but I think it's a bit to magical/"funky".

                 

                I do think we could come up with some useful "convention" based mechanisms e.g. users define a transformers.xml file in the META-INF/switchyard folder of their module.  This could be a convention based way of explicitly registering the transformers you want to have registered by the deployer (which just scans the cp for all "META-INF/switchyard/transformers.xml" resources).

                 

                Keith:
                DefaultMessageDecomposer - I would really like to see us avoid coding converter logic into individual
                components.  The SOAP gateway expects XML and that can come in a bunch of forms : byte[], String,
                InputStream, Reader, Element, Node, XMLStreamReader, Source, etc, etc.  We should use our own super
                awesome transformation framework to handle these cases.
                
                

                 

                You saying we should avoid the decomposer mechansim completely and just use the transform mechanism within exchange?  I'd agree with that.

                 

                Keith:
                HandlerExceptionTransformer - any reason why we're not using a typed Transformer definition here
                 e.g. Transformer<HandlerException, String>
                
                

                 

                There is a reason… I'm a lazy ***

                 

                Keith:
                InboundHandler - is it possible for the runtime to assign a TransformSequence based on the message
                name in the exchange and the service operation's message name?  This would replace
                associateInTransformSequence and associateOutTransformSequence in InboundHandler.
                
                

                 

                Yeah… I've been thinking about this too.  I think it would make sense and goes back to the earlier point… making it possible to hook the ServiceOperation (from the ServiceInterface) onto the Exchange instance.  In this case, the SOAP Gateway would perform this task based on the incoming SOAP request.  It would simply lookup the ServiecOperation from the Service and set it onto the Exchange.

                 

                Then, we could have another default handler for processing this on all exchanges (if present), creating and attaching the IN and OUT TransformSequence instances in a generalized way.  I wouldn't do this in the TransformHandler.

                 

                Keith:
                TransformSequence - the cacheOutput and cacheFault methods seem a bit funky to me.  I realize
                why they are there, I'm just wondering if there's another way to go about it.  This is probably
                tied to the whole input/output phase thing you have been talking about.
                
                

                 

                I think the answer to this is tied up with the answer to the previous one.  As well as attaching details about the target ServiceOperation, it also needs to attach the "requirements" it has in terms of the response coming back.

                 

                Perhaps we have something like an InvocationMetaData type that can get set on an Exchange (by e.g. the SOAPGateway) e.g.

                 

                public interface InvocationMetaData {
                    ServiceOperation getServiceOperation();
                    InvokerOperationMetaData getInvokerOperationMetaData();
                }
                
                public inteface InvokerOperationMetaData {
                    Set<String> acceptedResponseTypes;
                    Set<String> acceptedFaultTypes;
                }    
                
                • 5. Re: Get the SOAP + Bean components working smootly together
                  tfennelly

                  Just to say... I'm looking at adding something like the following and making available through Exchange.getContract()

                   

                  /**
                   * Exchange Contract.
                   * <p/>
                   * Two-way Exchange contract, detailing the requirments of both the invoker (in terms of
                   * accepted response/fault types) and target {@link ServiceOperation} being invoked.
                   *
                   * @author <a href="mailto:tom.fennelly@gmail.com">tom.fennelly@gmail.com</a>
                   */
                  public interface ExchangeContract {
                  
                      /**
                       * Get the target service operation being invoked.
                       * @return The target service operation being invoked.
                       */
                      ServiceOperation getServiceOperation();
                  
                      /**
                       * Get the set of valid response types accepted by the exchange invoker.
                       * @return The set of valid response types accepted by the exchange invoker.
                       */
                      Set<String> getAcceptedResponseTypes();
                  
                      /**
                       * Get the set of valid fault types accepted by the exchange invoker.
                       * @return The set of valid fault types accepted by the exchange invoker.
                       */
                      Set<String> getAcceptedFaultTypes();
                  }
                  
                  

                   

                  How about creating an Exchange using an instance of this interface Vs just ExchangePattern (the ServiceOperation has the pattern on it) ?

                  • 6. Get the SOAP + Bean components working smootly together
                    kcbabo

                    Keith:
                    Invocation - I don't quite get why assertOK() exists.  Seems like this tests whether transformation
                    happened vs. just testing to make sure the message type matches the method parameter.  I have a
                    feeling I'm missing a nuance here.
                    
                    

                     

                    It does a bit more than just check if transforms were applied, even just for that, I think it's more appropriate to check if the actual defined transform sequence was applied because what if the resulting java type of the transform was the same as the input type to the transform?  Your java type check would pass, but the content of the instance is probably not what it should be.

                     

                    Why would we do this in the component's code though?  Seems like you would always want to verify that expected handlers have fired and so this could be part of the normal transformation framework.

                     

                    I do think we could come up with some useful "convention" based mechanisms e.g. users define a transformers.xml file in the META-INF/switchyard folder of their module.  This could be a convention based way of explicitly registering the transformers you want to have registered by the deployer (which just scans the cp for all "META-INF/switchyard/transformers.xml" resources).

                    OK, so we agree that the core runtime should register these and we can play around with a couple of possibilities.  Maybe it's a separate transformers file, maybe it's scan for annotated classes in the deployment, or maybe it's something in the application configuration descriptor itself.

                     


                    You saying we should avoid the decomposer mechansim completely and just use the transform mechanism within exchange?  I'd agree with that.

                     

                    When I discussed this with Magesh, I was cool with a SOAP-level composer/decomposer in case users have very specific ways they want to package up or unwrap the SOAP envelope.  In terms of converting between the Message content and the SOAP body, that should be a transformer.

                     

                    Yeah… I've been thinking about this too.  I think it would make sense and goes back to the earlier point… making it possible to hook the ServiceOperation (from the ServiceInterface) onto the Exchange instance.  In this case, the SOAP Gateway would perform this task based on the incoming SOAP request.  It would simply lookup the ServiecOperation from the Service and set it onto the Exchange.

                     

                    Then, we could have another default handler for processing this on all exchanges (if present), creating and attaching the IN and OUT TransformSequence instances in a generalized way.  I wouldn't do this in the TransformHandler.

                    Any reason why this doesn't belong in the TransformHandler?

                    • 7. Re: Get the SOAP + Bean components working smootly together
                      tfennelly

                      Keith Babo wrote:


                      Why would we do this in the component's code though?  Seems like you would always want to verify that expected handlers have fired and so this could be part of the normal transformation framework.

                       

                      Point taken.... doing this in the component code is not the best... I'll go back and revisit this.  But, I don't think it belong in the TransformHandler either because, as I see it, it may be OK for a given instance of the TransformHandler to not apply all the transformations in the TransformSequence for an Exchange phase. 

                       

                      Example... if the Exchange moves through a number of hops (distributed use case) on the IN phase to get to the target service, the first transform (e.g. from invokers format to cannonical form) might get applied on the invoker side of the IN phase.  The second transform (e.g. from cannonical form to target service operation's input type) might get applied on the service side of the IN phase (assumption here .... in a distrubuted model, there'd be multiple handler chains).

                       

                      So I don't think the TransformHandler should bomb if it can't perform one of the transforms in the sequence.  The assumption from the TransformHandler's POV is... the remaining transforms will happen further down the line closer to the service (or visa versa on the OUT phase).

                       

                      But something does need to check just before the final delivery to the service (IN) or the invoker (OUT).  I just happened to do it in this case in the Bean Component's Proxy, but I do agree that we should have a more formalized way of doing it.  We need to figure that out !

                       

                      Keith Babo wrote:


                      When I discussed this with Magesh, I was cool with a SOAP-level composer/decomposer in case users have very specific ways they want to package up or unwrap the SOAP envelope.  In terms of converting between the Message content and the SOAP body, that should be a transformer.

                       

                      Okidoki... I'll revisit this... perhaps I was being a bit lazy

                       

                      Keith Babo wrote:

                       

                      Any reason why this doesn't belong in the TransformHandler?

                       

                      The reason I don't think this should be done in the TransformHandler goes back to my earlier point wrt how all this might behave in a distributed model.

                       

                      So assuming it's the invokers job (e.g. the SOAPGateway) to decorate the Exchange with invocation "contract" type info along the lines of the ExchangeContract I was talking about earlier... I think it should be the job of a dedicated handler (not sure what it could be called) to take this exchange contract (or whatever we call it) info and expand it out into IN and OUT TransformSequences etc (I have a gut feeling there'll be other things too).

                      • 8. Re: Get the SOAP + Bean components working smootly together
                        tfennelly

                        Made some more updates to this work, trying to clean up how we're decorating the Exchange with operation + data type info.

                         

                        See:

                        1. https://github.com/tfennelly/jboss-switchyard-core/tree/SWITCHYARd-v2
                        2. https://github.com/tfennelly/jboss-switchyard-components/tree/SWITCHYARd-v2

                         

                        Yes... I messd up the branch names, but we can sort that out later.

                         

                        Note that I'm proposing to slight change in how we create Exchange instances.  Instead of creating them with just an ExchangePattern, we create with a new ExchangeContract type, which can contain additional info about the data types (input, acceptedOutput, fault) + the target ServiceOperation.

                         

                        This tries to formalize a lot of ugly crap in how I was attaching this info to the exchange in the last version.

                        • 9. Re: Get the SOAP + Bean components working smootly together
                          kcbabo

                          I think I'm gonna have to give feedback in two passes.  Reason being that I like the direction this is headed, but there's something about it that doesn't quite sit right with me.

                           

                          Let's start with what I like.  I think it's a good thing that the consumer of a service can declare the types that they expect to be used in a message exchange.  This allows us to detect message type mismatches and apply transfomations as required.  I think that this information could easily be generated off of the interface the the service consumer is using.  For Bean component, that's the Java interface and we already have a way of creating a ServiceInterface off of that with metadata.java.JavaService.  We should be able to do the same with WSDL interfaces via a similar metadata parser/generator, e.g. metadata.wsdl.WsdlService.

                           

                          Now to what doesn't sit right.  There seems to be overlap between what is represented in ExchangeContract and ServiceOperation.  In fact, if ServiceOperation had a method to query the fault name, they would have exactly the same information.  Now one calls it type and the other calls it name, but they are both talking about the same thing.  Do we really need a contract package if we already have a metadata package?  Is there a way to represent this in a consistent manner?

                           

                          Another thing we need to keep in mind is that while well-defined contracts for services is a best practice and something we will encourage, there is still an important degenerate case where a service consumer or provider accepts a wide range of inputs.  For example, a JMS binding to an ObjectMessage will accept any Java object.  In this case, it may make sense to say that the type system is Java, but it is not appropriate to type the actual message payload.  Perhaps this goes back to how we define the structure of a type name.  So java:org.example.PurchaseOrder would map to a specific java type, while java:* would simply mean any java type, and * would be any type.

                           

                          Bottom line is that I think these changes are an improvement, but I'm thinking some slight mods might be in order.  I will take another pass through the changes to see if I can think of anything.

                          • 10. Re: Get the SOAP + Bean components working smootly together
                            tfennelly

                            Keith Babo wrote:

                             

                            Now to what doesn't sit right.  There seems to be overlap between what is represented in ExchangeContract and ServiceOperation.  In fact, if ServiceOperation had a method to query the fault name, they would have exactly the same information.

                             

                            There seems to be some confusion here.  ServiceOperation provides information about one end of an Exchange only i.e. the Service Operation ala its name.  ExchangeContract provides all (all that we need for now) details relating to both "ends" of an Exchange i.e. Invoker and target Service:

                             

                            1. Invoker Details e.g.:
                              • The exchange input/source data type e.g. for the SOAPGateway... the port input message QName.
                              • The accepted/required output data type at the invoker end e.g. for the SOAPGateway... the port output message QName.
                              • The accepted/required fault type at the invoker end e.g. for the SOAPGateway... the SOAP Fault type QName ala the SOAP spec.
                            2. ServiceOperation:
                              • Service Operation input type e.g. for a Bean component... the type as produced by the JavaService class
                              • Service Operation output type e.g. for a Bean component... the type as produced by the JavaService class

                             

                            To me, the above 2 categories are obviously closely related, but different things.

                             

                            If the ServiceOperation had any fault type info on it, it would be the fault type as of the ServiceOperation, which is not necessarily the same as that required at the invoker end of the exchange e.g. in the case of the SOAPGateway invoking a Bean ServiceOperation... the fault on the ServiceOperation would be based on a Java Exception (JavaService would come into play again I'm sure).  The fault type from the point of view of the SOAPGateway is the SOAP Fault type QName ala the SOAP Spec (i.e. "{http://schemas.xmlsoap.org/soap/envelope/}Fault").

                             

                            Keith Babo wrote:

                             

                            Now one calls it type and the other calls it name, but they are both talking about the same thing.  Do we really need a contract package if we already have a metadata package?  Is there a way to represent this in a consistent manner?

                             

                            Yeah... sorry about that... wasn't thinking there.  Can we call it "type" though?  "type" seems more accurate to me... "name" is kinda meaningless and confusing.  To me, there's a specific meaning when someone says "input type", more so than when someone says "input name".  JAX-WS also calls this stuff "type".

                             

                            Package name "contract"... I was going to put this stuff into metadata and then thought I'd put it somewhere specific first for reviewing purposes... kinda easier to see what I added.  I do think it makes sense to distinguish between service metadata and exchange contract type stuff, but then maybe I'm just thinking about it differently.  I'd be cool with all this stuff being in metadata.

                             

                             

                            Keith Babo wrote:

                            Another thing we need to keep in mind is that while well-defined contracts for services is a best practice and something we will encourage, there is still an important degenerate case where a service consumer or provider accepts a wide range of inputs.  For example, a JMS binding to an ObjectMessage will accept any Java object.  In this case, it may make sense to say that the type system is Java, but it is not appropriate to type the actual message payload.  Perhaps this goes back to how we define the structure of a type name.  So java:org.example.PurchaseOrder would map to a specific java type, while java:* would simply mean any java type, and * would be any type.

                             

                            I don't think that's a problem with what we've done here.  There are static default/opaque contract definitions defined on ExchangeContract for this purpose and they behave in much the same way as the default InOutOperation/InOnlyOperation defined in the metadata package (in fact, they use these).

                             

                            As for the invoker type info on the ExchangeContract.... these can be undefined (and are in the default definitions).  It's up to the components involved in the exchange to then decide whether or not they need this info or not.  If a JMS Binding doesn't need it, then that's fine... it doesn't need to be defined.

                            • 11. Re: Get the SOAP + Bean components working smootly together
                              kcbabo

                              There seems to be some confusion here.  ServiceOperation provides information about one end of an Exchange only i.e. the Service Operation ala its name.  ExchangeContract provides all (all that we need for now) details relating to both "ends" of an Exchange i.e. Invoker and target Service:

                               

                              1. Invoker Details e.g.:
                                • The exchange input/source data type e.g. for the SOAPGateway... the port input message QName.
                                • The accepted/required output data type at the invoker end e.g. for the SOAPGateway... the port output message QName.
                                • The accepted/required fault type at the invoker end e.g. for the SOAPGateway... the SOAP Fault type QName ala the SOAP spec.
                              2. ServiceOperation:
                                • Service Operation input type e.g. for a Bean component... the type as produced by the JavaService class
                                • Service Operation output type e.g. for a Bean component... the type as produced by the JavaService class

                               

                              To me, the above 2 categories are obviously closely related, but different things.

                               

                              I definitely missed that ExchangeContract represents the complete interface view - consumer and provider.  That's interesting.  The point I was trying to make though is that ExchangeContract has a separate set of methods for returning the in/out/fault types.  As an example, could Exchange just have a setOperation(ServiceOperation operation) method which accepted operation metadata?  This could be the same as the Service operation metadata (in the case where consumer and provider us the same interface) or different.  In the mediation layer, we can compare exchange.getServiceOperation() and service.getInterface().getOperation(operationName) and get the same information that ExchangeContract offers.


                              Yeah... sorry about that... wasn't thinking there.  Can we call it "type" though?  "type" seems more accurate to me... "name" is kinda meaningless and confusing.  To me, there's a specific meaning when someone says "input type", more so than when someone says "input name".  JAX-WS also calls this stuff "type".

                              I agree that "name" is dumb and "type" is better.  Let's go with that.

                              Package name "contract"... I was going to put this stuff into metadata and then thought I'd put it somewhere specific first for reviewing purposes... kinda easier to see what I added.  I do think it makes sense to distinguish between service metadata and exchange contract type stuff, but then maybe I'm just thinking about it differently.  I'd be cool with all this stuff being in metadata.

                              I think metadata makes sense, particularly if you agree with my comment above w/r/t ServiceOperation.

                              I don't think that's a problem with what we've done here.  There are static default/opaque contract definitions defined on ExchangeContract for this purpose and they behave in much the same way as the default InOutOperation/InOnlyOperation defined in the metadata package (in fact, they use these).

                               

                              As for the invoker type info on the ExchangeContract.... these can be undefined (and are in the default definitions).  It's up to the components involved in the exchange to then decide whether or not they need this info or not.  If a JMS Binding doesn't need it, then that's fine... it doesn't need to be defined.

                              Cool.  I just want to maintain graceful degradation when it comes to the contract stuff.  We should encourage developers to be contract-based as much as possible, but we still have to allow for the case where a "loose" service contract is appropriate.

                              • 12. Re: Get the SOAP + Bean components working smootly together
                                tfennelly

                                Keith Babo wrote:


                                I definitely missed that ExchangeContract represents the complete interface view - consumer and provider.  That's interesting.  The point I was trying to make though is that ExchangeContract has a separate set of methods for returning the in/out/fault types.  As an example, could Exchange just have a setOperation(ServiceOperation operation) method which accepted operation metadata?  This could be the same as the Service operation metadata (in the case where consumer and provider us the same interface) or different.  In the mediation layer, we can compare exchange.getServiceOperation() and service.getInterface().getOperation(operationName) and get the same information that ExchangeContract offers.

                                 

                                You mean... use a ServiceOperation instance on the Exchange to carry those additional consumer details... inputType, faultType etc.?  That would work for sure, but I think it kinda overloads (for me anyway) the concept of ServiceOperation. 

                                 

                                Maybe we could create a more generalized concept for invocation type info ... say... InvocationMetaData (i.e.more general / less specific than "ServiceOperation") and use this for both?  Or perhaps ServiceOperation just extends this, adding a name for the operation.

                                 

                                I still like the idea of ExchangeContract though e.g. using "InvocationMetaData" (or whatever we call it if we create something more generalized):

                                 

                                public interface ExchangeContract {
                                    InvocationMetaData getInvokerInvocationMetaData();
                                    ServiceOperation getServiceOperation();
                                }
                                

                                 

                                I think this is cleaner than attaching the serive operation name to the exchange (somehow) and then components having to root out the ServiceOperation every time by first getting the name and then calling through the Service interface.  If we're going to be attaching service operation info to the exchange anyway (operationName or ServiceOperation instance), why not just do it once (get the ServiceOperation) and attach that to the exchange and make it available instead of just the name?