1 2 Previous Next 22 Replies Latest reply on Apr 3, 2013 7:17 AM by kcbabo Go to original post
      • 15. Re: Hiding ExchangeImpl from ServiceReference
        kcbabo

        BTW, one nice side effect of the above change is that we can do away with the reply handler and and the consumer callback handler in our Camel pipeline.

        • 16. Re: Hiding ExchangeImpl from ServiceReference
          splatch

          I really like the idea of Future usage and removal of reply handler. It makes things lots simpler - at least from camel bus implementation point of view.

          • 17. Re: Hiding ExchangeImpl from ServiceReference
            splatch

            I've completed first stage of changes with replacement of IN/OUT scope. Changes may be accessed here:

            https://github.com/splatch/switchyard-core/tree/message-context

            https://github.com/splatch/switchyard-components/tree/message-context

            https://github.com/splatch/switchyard-quickstarts/tree/message-context (only one change is http-quickstart which uses CDI to inject Context instances)

             

            In addition I did a mock for Future<Message> implementations. Everything is in async-exchange branch.

             

            Quick summary of changes

            • Context Mappers now receive exchange context and message context instead of one (scoped context)
              • During refactor I wanted to implement back scoped context with support for Exchange and Message context, then I realized that context mapper may use "deatached" message instance ie. which is not related to any exchange.
            • Exchange Handlers have to copy message instead of resending same instance. The state of message is determined by org.switchyard.messageId property - if it's already set then message can not be re-used.
              • This introduces an question mark do we need "create" flag in Message Composers - since we can not re-use messages any more.
            • Transition from IN/OUT scope was really easy - in all places where IN scope was used I use exchange.getMessage().getContext(), in places where OUT scope was used I use message which going to be send by handler. So far none from tests failed after this change.
            • 18. Re: Hiding ExchangeImpl from ServiceReference
              kcbabo

              Awesome work, Lukasz!  I'm going to post comments in phases here so that we can sort of build up from core.  Looking at the core diffs, I have the following feedback:

               

              - I don't think there should be a setContext() on Message.  A context is created when the message is created and it is modified but not replaced.

              - RemoteMessage should not extend DefaultMessage

              - I couldn't figure out what the _scope field is used for in DefaultContext

              - DefaultMessage copies all context headers and I think we decided it copies no context headers

              - I would prefer it if we had a private instance variable in DefaultMessage which tracked whether it's been sent instead of checking for MESSAGE_ID header.  My reasoning there is that other state can be associated with the context besides MESSAGE_ID, so it's probably best just to keep the check private to our implementation.

              - ExchangeImpl.initContentType(Message) appears to set the contract's input type for IN and OUT now?  I think we need to go back to two methods or have a conditional in this method based off exchange phase.  Also, small nit but the message reference doesn't have to come in as a parameter, I think we could use getMesssage() instead.

              - I made an error in my prior post indicating that there was an Exchange.getContext(Scope scope), when Context itself is scope aware.  Not sure how I messed that up.  I like the idea of context as an abstraction over both scopes, so I'll need to ponder this a bit more. :-)

               

               

              Overall, your changes look great and I think this will make things considerably easier.

              • 19. Re: Hiding ExchangeImpl from ServiceReference
                splatch

                Hey Keith,

                - The setContext method was introduced because RemoteMessage extends DefaultMessage - if it will be removed then there will be no need for that.

                - Scope is used when you setProperty - scope distinguish properties set on Exchange and Message - if you will put all properties in Set they will not override each other.

                - Context copy do not contain properties marked as transient.

                - You are right, I've hit this problem when message was mapped by camel.

                 

                Regarding Exchange.getContext(Scope) - I decided to not continue this, however I do agree it might be very useful, especially for Context Mappers. The problem is that Exchange.getContext(MESSAGE) will always return scope of message attached to Exchange. Our users should be notified to don't make mistakes.

                • 20. Re: Hiding ExchangeImpl from ServiceReference
                  kcbabo

                  I've been thinking about this quite a bit relative to our original goals around Context.  Scope was introduced to represent the lifecycle of state associated with an invocation (stored as context properties).  It was never intended to allow a given property to live simultaenously in multiple scopes.  In other words, Context has one bucket of properties and some properties in that bucket live longer than others.

                   

                  I think there is only one Context.  We should not pass a separate context for message and exchange to context mappers.  You get a single context and for any property in that context there is a scope.  This is just from an API standpoint.  Underneath the covers, Camel exchange properties and message headers can be used to store the actual values.  A call to context.getProperty("foo") would look in message first, then in exchange scope.  A call to context.getProperty("foo", Scope.MESSAGE) would look directly in the message headers.  I would consider it rare and likely borderline buggy if a property existed in both scopes, so I'm just stating this so that we have a precedence rule.  When they do, the most specific setting (i.e. message) should be the one we go with.  Any context property returned has a scope associated with it as well, like we have today.

                   

                  I believe that Message.getContext() should return the properties with Scope.MESSAGE for that specific message instance.  Any properties set on that Context instance are Scope.MESSAGE.  Attempting to set Scope.EXCHANGE properties should result in SwitchYardException to fail fast with a clear error.

                  • 21. Re: Hiding ExchangeImpl from ServiceReference
                    splatch

                    What's about an extension of context:

                     

                    package org.switchyard;
                    
                    public interface ScopedContext extends Context {
                    
                        Property getProperty(String name, Scope scope);
                    
                        void removeProperties(Scope scope);
                    
                        Property setProperty(String name, Object val, Scope scope);
                    
                    }
                    

                     

                    Then in context mappers we could use this instance instead of two Context instances and keep messages context deatached from exchange when necessary.

                    • 22. Re: Hiding ExchangeImpl from ServiceReference
                      kcbabo

                      Do we even need a ScopedContext?  Can the above methods just be on Context and you essentially have a wrapper object under the covers that represents ScopedContext?

                      1 2 Previous Next