Hi Claus,

I think it's a little bit hard to determine if a collection/map is Serializable. Let's say there's a map1, a valule of this map1 is also a map2, so we should also recursively check if all the values in the map2 is Serializable, also map2 could have collection/map as values, and so on... However this recursive way MIGHT cause problem, like users MAY incorrectly put map2 as value of map1, and again put map1 as value as map2, this circular reference will cause infinite loop if we recursively check the Serializable values.

Regards
Freeman

On 2011-6-1, at 下午4:54, davscl...@apache.org wrote:

Author: davsclaus
Date: Wed Jun  1 08:54:41 2011
New Revision: 1130060

URL: http://svn.apache.org/viewvc?rev=1130060&view=rev
Log:
CAMEL-4035: DefaultExchangeHolder should check map/collection for serializable objects. Also adjusted logging to not WARN log Camel keys.

Added:
camel/trunk/components/camel-jms/src/test/java/org/apache/camel/ component/jms/JmsTransferExchangeFromSplitterTest.java - copied, changed from r1130001, camel/trunk/components/camel- jms/src/test/java/org/apache/camel/component/jms/ JmsTransferExchangeTest.java
Modified:
camel/trunk/camel-core/src/main/java/org/apache/camel/impl/ DefaultExchangeHolder.java camel/trunk/camel-core/src/test/java/org/apache/camel/impl/ DefaultExchangeHolderTest.java

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/impl/ DefaultExchangeHolder.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/DefaultExchangeHolder.java?rev=1130060&r1=1130059&r2=1130060&view=diff
= = = = = = = = ====================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/impl/ DefaultExchangeHolder.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/impl/ DefaultExchangeHolder.java Wed Jun 1 08:54:41 2011
@@ -17,10 +17,12 @@
package org.apache.camel.impl;

import java.io.Serializable;
+import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.camel.Exchange;
+import org.apache.camel.util.ObjectHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@@ -61,7 +63,6 @@ public class DefaultExchangeHolder imple

    /**
* Creates a payload object with the information from the given exchange.
-     * Only marshal the Serializable object
     *
     * @param exchange the exchange
* @return the holder object with information copied form the exchange
@@ -72,7 +73,6 @@ public class DefaultExchangeHolder imple

    /**
* Creates a payload object with the information from the given exchange.
-     * Only marshal the Serializable object
     *
     * @param exchange the exchange
* @param includeProperties whether or not to include exchange properties
@@ -82,10 +82,10 @@ public class DefaultExchangeHolder imple
        DefaultExchangeHolder payload = new DefaultExchangeHolder();

        payload.exchangeId = exchange.getExchangeId();
- payload.inBody = checkSerializableObject("in body", exchange, exchange.getIn().getBody()); + payload.inBody = checkSerializableBody("in body", exchange, exchange.getIn().getBody());
        payload.safeSetInHeaders(exchange);
        if (exchange.hasOut()) {
- payload.outBody = checkSerializableObject("out body", exchange, exchange.getOut().getBody()); + payload.outBody = checkSerializableBody("out body", exchange, exchange.getOut().getBody());
            payload.outFaultFlag = exchange.getOut().isFault();
            payload.safeSetOutHeaders(exchange);
        }
@@ -182,7 +182,7 @@ public class DefaultExchangeHolder imple
        return null;
    }

- private static Object checkSerializableObject(String type, Exchange exchange, Object object) { + private static Object checkSerializableBody(String type, Exchange exchange, Object object) {
        if (object == null) {
            return null;
        }
@@ -191,7 +191,7 @@ public class DefaultExchangeHolder imple
        if (converted != null) {
            return converted;
        } else {
- LOG.warn(type + " containing object: " + object + " of type: " + object.getClass().getCanonicalName() + " cannot be serialized, it will be excluded by the holder."); + LOG.warn("Exchange " + type + " containing object: " + object + " of type: " + object.getClass().getCanonicalName() + " cannot be serialized, it will be excluded by the holder.");
            return null;
        }
    }
@@ -203,18 +203,71 @@ public class DefaultExchangeHolder imple

Map<String, Object> result = new LinkedHashMap<String, Object>();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
+
            // silently skip any values which is null
            if (entry.getValue() != null) {
Serializable converted = exchange .getContext().getTypeConverter().convertTo(Serializable.class, exchange, entry.getValue());
+
+ // if the converter is a map/collection we need to check its content as well
+                if (converted instanceof Collection) {
+                    Collection valueCol = (Collection) converted;
+ if (! collectionContainsAllSerializableObjects(valueCol, exchange)) { + logCannotSerializeObject(type, entry.getKey(), entry.getValue());
+                        continue;
+                    }
+                } else if (converted instanceof Map) {
+                    Map valueMap = (Map) converted;
+ if (! mapContainsAllSerializableObjects(valueMap, exchange)) { + logCannotSerializeObject(type, entry.getKey(), entry.getValue());
+                        continue;
+                    }
+                }
+
                if (converted != null) {
                    result.put(entry.getKey(), converted);
                } else {
- LOG.warn(type + " containing object: " + entry.getValue() + " with key: " + entry.getKey() - + " cannot be serialized, it will be excluded by the holder."); + logCannotSerializeObject(type, entry.getKey(), entry.getValue());
                }
            }
        }

        return result;
    }
+
+ private static void logCannotSerializeObject(String type, String key, Object value) {
+        if (key.startsWith("Camel")) {
+            // log Camel at DEBUG level
+            if (LOG.isDebugEnabled()) {
+ LOG.debug("Exchange {} containing key: {} with object: {} of type: {} cannot be serialized, it will be excluded by the holder.", new Object[]{type, key, value, ObjectHelper.classCanonicalName(value)});
+            }
+        } else {
+            // log regular at WARN level
+ LOG.warn("Exchange {} containing key: {} with object: {} of type: {} cannot be serialized, it will be excluded by the holder.", new Object[]{type, key, value, ObjectHelper.classCanonicalName(value)});
+        }
+    }
+
+ private static boolean collectionContainsAllSerializableObjects(Collection col, Exchange exchange) {
+        for (Object value : col) {
+            if (value != null) {
+ Serializable converted = exchange .getContext().getTypeConverter().convertTo(Serializable.class, exchange, value);
+                if (converted == null) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+ private static boolean mapContainsAllSerializableObjects(Map map, Exchange exchange) {
+        for (Object value : map.values()) {
+            if (value != null) {
+ Serializable converted = exchange .getContext().getTypeConverter().convertTo(Serializable.class, exchange, value);
+                if (converted == null) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
}

Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/impl/ DefaultExchangeHolderTest.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/impl/DefaultExchangeHolderTest.java?rev=1130060&r1=1130059&r2=1130060&view=diff
= = = = = = = = ====================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/impl/ DefaultExchangeHolderTest.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/impl/ DefaultExchangeHolderTest.java Wed Jun 1 08:54:41 2011
@@ -16,6 +16,11 @@
 */
package org.apache.camel.impl;

+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
import org.apache.camel.ContextTestSupport;
import org.apache.camel.Exchange;

@@ -27,31 +32,124 @@ public class DefaultExchangeHolderTest e
    private String id;

    public void testMarshal() throws Exception {
-        DefaultExchangeHolder holder = createHolder();
+        DefaultExchangeHolder holder = createHolder(true);
        assertNotNull(holder);
        assertNotNull(holder.toString());
    }

+    public void testNoProperties() throws Exception {
+        DefaultExchangeHolder holder = createHolder(false);
+        assertNotNull(holder);
+
+        Exchange exchange = new DefaultExchange(context);
+        DefaultExchangeHolder.unmarshal(exchange, holder);
+
+        assertEquals("Hello World", exchange.getIn().getBody());
+        assertEquals("Bye World", exchange.getOut().getBody());
+        assertEquals(123, exchange.getIn().getHeader("foo"));
+        assertNull(exchange.getProperty("bar"));
+    }
+
    public void testUnmarshal() throws Exception {
        id = null;
        Exchange exchange = new DefaultExchange(context);

-        DefaultExchangeHolder.unmarshal(exchange, createHolder());
+ DefaultExchangeHolder.unmarshal(exchange, createHolder(true));
        assertEquals("Hello World", exchange.getIn().getBody());
        assertEquals("Bye World", exchange.getOut().getBody());
        assertEquals(123, exchange.getIn().getHeader("foo"));
+ assertEquals("Hi Camel", exchange.getIn().getHeader("CamelFoo"));
        assertEquals(444, exchange.getProperty("bar"));
+        assertEquals(555, exchange.getProperty("CamelBar"));
        assertEquals(id, exchange.getExchangeId());
    }

-    private DefaultExchangeHolder createHolder() {
+    public void testSkipNonSerializableData() throws Exception {
+        Exchange exchange = new DefaultExchange(context);
+        exchange.getIn().setBody("Hello World");
+        exchange.getIn().setHeader("Foo", new MyFoo("Tiger"));
+        exchange.getIn().setHeader("Bar", 123);
+
+ DefaultExchangeHolder holder = DefaultExchangeHolder.marshal(exchange);
+
+        exchange = new DefaultExchange(context);
+        DefaultExchangeHolder.unmarshal(exchange, holder);
+
+        // the non serializable header should be skipped
+        assertEquals("Hello World", exchange.getIn().getBody());
+        assertEquals(123, exchange.getIn().getHeader("Bar"));
+        assertNull(exchange.getIn().getHeader("Foo"));
+    }
+
+    @SuppressWarnings("unchecked")
+ public void testSkipNonSerializableDataFromList() throws Exception { + // use a mixed list, the MyFoo is not serializable so the entire list should be skipped
+        List list = new ArrayList();
+        list.add("I am okay");
+        list.add(new MyFoo("Tiger"));
+
+        Exchange exchange = new DefaultExchange(context);
+        exchange.getIn().setBody("Hello World");
+        exchange.getIn().setHeader("Foo", list);
+        exchange.getIn().setHeader("Bar", 123);
+
+ DefaultExchangeHolder holder = DefaultExchangeHolder.marshal(exchange);
+
+        exchange = new DefaultExchange(context);
+        DefaultExchangeHolder.unmarshal(exchange, holder);
+
+        // the non serializable header should be skipped
+        assertEquals("Hello World", exchange.getIn().getBody());
+        assertEquals(123, exchange.getIn().getHeader("Bar"));
+        assertNull(exchange.getIn().getHeader("Foo"));
+    }
+
+    @SuppressWarnings("unchecked")
+ public void testSkipNonSerializableDataFromMap() throws Exception { + // use a mixed Map, the MyFoo is not serializable so the entire map should be skipped
+        Map map = new HashMap();
+        map.put("A", "I am okay");
+        map.put("B", new MyFoo("Tiger"));
+
+        Exchange exchange = new DefaultExchange(context);
+        exchange.getIn().setBody("Hello World");
+        exchange.getIn().setHeader("Foo", map);
+        exchange.getIn().setHeader("Bar", 123);
+
+ DefaultExchangeHolder holder = DefaultExchangeHolder.marshal(exchange);
+
+        exchange = new DefaultExchange(context);
+        DefaultExchangeHolder.unmarshal(exchange, holder);
+
+        // the non serializable header should be skipped
+        assertEquals("Hello World", exchange.getIn().getBody());
+        assertEquals(123, exchange.getIn().getHeader("Bar"));
+        assertNull(exchange.getIn().getHeader("Foo"));
+    }
+
+ private DefaultExchangeHolder createHolder(boolean includeProperties) {
        Exchange exchange = new DefaultExchange(context);
        id = exchange.getExchangeId();
        exchange.getIn().setBody("Hello World");
        exchange.getIn().setHeader("foo", 123);
+        exchange.getIn().setHeader("CamelFoo", "Hi Camel");
        exchange.setProperty("bar", 444);
+        exchange.setProperty("CamelBar", 555);
        exchange.getOut().setBody("Bye World");
-        return DefaultExchangeHolder.marshal(exchange);
+ return DefaultExchangeHolder.marshal(exchange, includeProperties);
+    }
+
+    private class MyFoo {
+        private String foo;
+
+        private MyFoo(String foo) {
+            this.foo = foo;
+        }
+
+        public String getFoo() {
+            return foo;
+        }
+
    }

}

Copied: camel/trunk/components/camel-jms/src/test/java/org/apache/ camel/component/jms/JmsTransferExchangeFromSplitterTest.java (from r1130001, camel/trunk/components/camel-jms/src/test/java/org/apache/ camel/component/jms/JmsTransferExchangeTest.java)
URL: 
http://svn.apache.org/viewvc/camel/trunk/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsTransferExchangeFromSplitterTest.java?p2=camel/trunk/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsTransferExchangeFromSplitterTest.java&p1=camel/trunk/components/camel-jms/src/test/java/org/apache/camel/component/jms/JmsTransferExchangeTest.java&r1=1130001&r2=1130060&rev=1130060&view=diff
= = = = = = = = ====================================================================== --- camel/trunk/components/camel-jms/src/test/java/org/apache/camel/ component/jms/JmsTransferExchangeTest.java (original) +++ camel/trunk/components/camel-jms/src/test/java/org/apache/camel/ component/jms/JmsTransferExchangeFromSplitterTest.java Wed Jun 1 08:54:41 2011
@@ -18,7 +18,6 @@ package org.apache.camel.component.jms;

import javax.jms.ConnectionFactory;

-import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.camel.CamelContext;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
@@ -26,48 +25,28 @@ import org.apache.camel.builder.RouteBui
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.test.junit4.CamelTestSupport;
import org.junit.Test;
+
import static org .apache.camel.component.jms.JmsComponent.jmsComponentAutoAcknowledge;

/**
 * @version
 */
-public class JmsTransferExchangeTest extends CamelTestSupport {
+public class JmsTransferExchangeFromSplitterTest extends CamelTestSupport {

    protected String getUri() {
        return "activemq:queue:foo?transferExchange=true";
    }

    @Test
-    public void testBodyOnly() throws Exception {
-        MockEndpoint mock = getMockEndpoint("mock:result");
-        mock.expectedBodiesReceived("Hello World");
-
-        template.sendBody("direct:start", "Hello World");
-
-        assertMockEndpointsSatisfied();
-    }
-
-    @Test
-    public void testBodyAndHeaderOnly() throws Exception {
+    public void testSplit() throws Exception {
        MockEndpoint mock = getMockEndpoint("mock:result");
-        mock.expectedBodiesReceived("Hello World");
-        mock.expectedHeaderReceived("foo", "cheese");
-
- template.sendBodyAndHeader("direct:start", "Hello World", "foo", "cheese");
-
-        assertMockEndpointsSatisfied();
-    }
-
-    @Test
-    public void testSendExchange() throws Exception {
-        MockEndpoint mock = getMockEndpoint("mock:result");
-        mock.expectedBodiesReceived("Hello World");
-        mock.expectedHeaderReceived("foo", "cheese");
-        mock.expectedPropertyReceived("bar", 123);
+        mock.expectedBodiesReceived("A", "B", "C");
+        mock.allMessages().header("foo").isEqualTo("cheese");
+        mock.allMessages().property("bar").isEqualTo(123);

        template.send("direct:start", new Processor() {
            public void process(Exchange exchange) throws Exception {
-                exchange.getIn().setBody("Hello World");
+                exchange.getIn().setBody("A,B,C");
                exchange.getIn().setHeader("foo", "cheese");
                exchange.setProperty("bar", 123);
            }
@@ -90,7 +69,10 @@ public class JmsTransferExchangeTest ext
        return new RouteBuilder() {
            @Override
            public void configure() throws Exception {
-                from("direct:start").to(getUri());
+                from("direct:start")
+                    .split(body().tokenize(","))
+                        .to(getUri());
+
                from(getUri()).to("mock:result");
            }
        };



---------------------------------------------
Freeman Fang

FuseSource
Email:ff...@fusesource.com
Web: fusesource.com
Twitter: freemanfang
Blog: http://freemanfang.blogspot.com
Connect at CamelOne May 24-26
The Open Source Integration Conference








Reply via email to