5 Replies Latest reply on Mar 4, 2013 3:44 PM by dward

    Filtering Context Properties

    dward

      An issue was raised on a user forum thread "Load Balancing Question", which in turn, prompted the creation of this jira: SWITCHYARD-1325.

       

      Boiled down, a Camel object finds it's way into a Context Property, and that Camel object cannot be deserialized since it doesn't have a no-arg constructor.  We have a mechanism for classes we control, where we can annotate the class to define de/serialization strategy.  We also have a mechanism for "special" JDK classes (like InputStreams, DataSources, Collections, etc.) to handle de/serialization as we walk the object graph.

       

      Obviously, we can't add our annotations to Camel classes, and I personally don't want to add a bazillion "else if" blocks to handle every possible specific type of Camel object. That is simply not maintainable long-term.  So, I'm wondering if the following is an option...

       

      What if we were to filter non-serializable classes?  We have a couple different options to do this:

      1. In our SwitchYardRemotingServlet, we already do a context.copy(), which internally will not copy properties that are marked with a "transient" label.  We can add to our CamelContextMapper to automatically add the transient label to any properties it maps that are custom org.apache.camel.* objects.  The properties will still get mapped, but if the runtime execution crosses a process boundry (specifically, goes through our remoting layer), at that point the properites get dropped.
      2. Same as #1, but we only add the label to camel objects that don't have no-arg constructors.  Personally I don't like this option much, as then it will be confusing as hell to people why some Camel objects survived crossing the process boundry, but others didn't.
      3. We can add smarts to our ContextProperty implementation, such that any property that gets created will have it's value introspected, and any value that we know we can't handle during serialization will be automatically marked with a label of "transient".  It's actually pretty straightforward to figure out if a value is de/serializable:
        • It has a no-arg constructor (public/private doesn't matter, as we circumvent that via reflection), or...
        • It is marked with our serialization @Strategy annotation, or...
        • It is one of the (few) "special" types we handle in our serialization NodeBuilder class (InputStreams, DataSources, Collections, etc.), or...
        • It is one of the basic (wrapper) java types (String, Boolean, Number, Date, etc.)

       

      #3 would still have the same problem that I mentioned in #2, but we can do both #1 and #3...

       

      Thoughts? I would like to fix this up ASAP.

        • 1. Re: Filtering Context Properties
          dward

          At face-to-face team discussion today, we have decided to go with #3 for now.

          • 2. Re: Filtering Context Properties
            dward

            I changed direction earlier today, and I have a better (more performant) solution.  The problem with walking the graph and labeling properties as transient, is that we'd be doing it just in case we might serialize.  But in many cases, we won't.  Also, during serialization, we walk the graph a second time anyway.  This is not ideal.  So now, I don't depend upon the transinet label.  And during the actual process of seriazation, when I'm walking the graph already, I pare out the things we know we can't handle at that time.

             

            I have this implemented, and junit test cases that exercise and verify it.  Now I just have to try out the user's app to verify it works there too.

            • 3. Re: Filtering Context Properties
              dward

              FYI, an effect of this solution with regards to Collections, Maps and Arrays...  If element(s) in those structures are not serializable, when then get deserialized, their sizes/lengths will be shorter, as the non-serializable elements will not be present, and they are not replaced with nulls.

              • 4. Re: Filtering Context Properties
                kcbabo

                Chiming in a bit late, but for posterity's sake - I vote for #2.  I kid. 

                 

                The current approach is to guard at serialization time which represents a nice compromise, IMHO.  One thing we discussed at the F2F is whether certain properties should be propagated for in-memory invocations that don't use serialization.  For example, if an application contains two camel routes that both split a message, should the splitter property "leak" between the first route and the second.  The serialization fix will not address this part of the problem, so it will need to be addressed separately.

                • 5. Re: Filtering Context Properties
                  dward

                  Agreed.  For something like that, using the transient label would probably make sense.