3 Replies Latest reply on Jan 19, 2009 2:49 PM by janstey

    Unexpected data when using Camel-xstream and Camel-velocity in dependencies

    jklemm

       

      Hi,

       

      When I put camel-xstream and camel-velocity components in dependencies POM, the code below return XML data with strange elements.

       

      Code:

       

      from("direct:SQL_EXEC")

      .process(

      new Processor() {

      public void process(Exchange exchange) throws Exception {

      List<String> params = new ArrayList<String>();

      params.add("ABCDEFG");

      exchange.getOut().setBody(params, List.class);

      }

      }

      )

      .to("sql: SELECT * FROM TABLE WHERE COLUMN = #)

      .marshal().xstream()

       

      Result with ONLY camel-xstream in dependencies POM:

       

      INFO: Exchange[BodyType:byte[], Body:<?xml version="1.0" ?><list><linked-hash-map><entry><string>CODCLI</string><string>ABCDEFG</string></entry><entry><string>UNDNEG</string><string>ABC</string></entry><entry><string>SALDOCR</string><big-decimal>12345678.00</big-decimal></entry><entry><string>IND01</string><string>A</string></entry></linked-hash-map></list>]

       

      Simple and clean....

       

      Now, the Result with camel-xstream and camel-velocity in dependencies POM..

       

      INFO: Exchange[BodyType:byte[], Body:<?xml version="1.0" ?><list><org.apache.commons.collections.map.ListOrderedMap serialization="custom"><unserializable-parents></unserializable-parents><org.apache.commons.collections.map.ListOrderedMap><default><insertOrder><string>CODCLI</string><string>UNDNEG</string><string>SALDOCR</string><string>IND01</string></insertOrder></default><org.apache.commons.collections.map.CaseInsensitiveMap serialization="custom"><unserializable-parents></unserializable-parents><org.apache.commons.collections.map.CaseInsensitiveMap><default></default><float>0.75</float><int>8</int><int>4</int><string>ind01</string><string>A</string><string>undneg</string><string>ABC</string><string>codcli</string><string>ABCDEFG</string><string>saldocr</string><big-decimal>12345678.00</big-decimal></org.apache.commons.collections.map.CaseInsensitiveMap></org.apache.commons.collections.map.CaseInsensitiveMap></org.apache.commons.collections.map.ListOrderedMap></org.apache.commons.collections.map.ListOrderedMap></list>]

       

      Looks too strange and complex to Map...

       

      So, Is this a bug ?

       

      Thanks,

       

       

        • 1. Re: Unexpected data when using Camel-xstream and Camel-velocity in dependencies
          janstey

          Tracked this down to a method in org.springframework.core.CollectionFactory

           

          public static Map createLinkedCaseInsensitiveMapIfPossible(int initialCapacity) {
              if (commonsCollections3Available) {
                  logger.trace("Creating [org.apache.commons.collections.map.ListOrderedMap/CaseInsensitiveMap]");
                  return CommonsCollectionFactory.createListOrderedCaseInsensitiveMap(initialCapacity);
              }
              else {
                  logger.debug("Falling back to [java.util.LinkedHashMap] for linked case-insensitive map");
                  return new LinkedHashMap(initialCapacity);
              }
          }
          

           

          So, it uses Apache commons-collections if it is available on the classpath. This is a feature of the Spring Framework. Velocity uses commons-collections so it introduces the behavior we are seeing. There are two options I can think of here to get back the nice XML format you had before...

           

          (1) See if Velocity works without commons-collections on the classpath... this is a long shot

           

          (2) Add in a custom processor to your route that will take the ListOrderedMap from commons-collections and instantiate a new LinkedHashMap from the Java runtime. Something like

          from("direct:SQL_EXEC")
          ...
          .to("sql: SELECT * FROM TABLE WHERE COLUMN = #")
          .process(new Processor() {
              public void process(Exchange exchange) throws Exception {
                  // create your new map here
              }
          }).marshal().xstream()
          ...
          

           

          Cheers,

          Jon

          • 2. Re: Unexpected data when using Camel-xstream and Camel-velocity in dependencies
            jklemm

            So,

             

            The option 2

             

            (2) Add in a custom processor to your route that will take the ListOrderedMap from commons-collections and instantiate a new LinkedHashMap from the Java runtime.

             

            I don't understand how to convert the sql result with a Custom Processor...

             

            I try

             

            .convertBodyTo(LinkedHashMap.class)

            .marshal().xstream()

             

            but it fails.

             

            Can you help me ?

             

            Thanks,

            • 3. Re: Unexpected data when using Camel-xstream and Camel-velocity in dependencies
              janstey

              The DSL method convertBodyTo(LinkedHashMap.class) doesn't work because this is not a common conversion supported by Camel (or anything else probably ). You can do this with a custom processor like so

               

              from("direct:SQL_EXEC")
              ...
              .to("sql: SELECT * FROM TABLE WHERE COLUMN = #")
              .process(new Processor() {
                  public void process(Exchange exchange) throws Exception {
                      Object body = exchange.getIn().getBody();                        
                      if (body instanceof ListOrderedMap) {
                          ListOrderedMap oldMap = (ListOrderedMap) body;                     
                          LinkedHashMap newMap = ... // create newMap from oldMap                          
                          exchange.getIn().setBody(newMap);
                      }                        
                  }}).marshal().xstream()
              ...
              

               

              Of course, you'll need to fill in the blanks where I say "create newMap from oldMap".

               

              Cheers,

              Jon