You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by bv...@apache.org on 2012/03/04 13:39:03 UTC

svn commit: r1296787 - in /camel/trunk/camel-core/src: main/java/org/apache/camel/processor/UnmarshalProcessor.java main/java/org/apache/camel/spi/DataFormat.java test/java/org/apache/camel/processor/UnmarshalProcessorTest.java

Author: bvahdat
Date: Sun Mar  4 12:39:03 2012
New Revision: 1296787

URL: http://svn.apache.org/viewvc?rev=1296787&view=rev
Log:
CAMEL-4797: DataFormat.unmarshal() should allow to return Message or Exchange to make it more flexible.

Added:
    camel/trunk/camel-core/src/test/java/org/apache/camel/processor/UnmarshalProcessorTest.java   (with props)
Modified:
    camel/trunk/camel-core/src/main/java/org/apache/camel/processor/UnmarshalProcessor.java
    camel/trunk/camel-core/src/main/java/org/apache/camel/spi/DataFormat.java

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/processor/UnmarshalProcessor.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/UnmarshalProcessor.java?rev=1296787&r1=1296786&r2=1296787&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/processor/UnmarshalProcessor.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/processor/UnmarshalProcessor.java Sun Mar  4 12:39:03 2012
@@ -23,6 +23,7 @@ import org.apache.camel.CamelContextAwar
 import org.apache.camel.Exchange;
 import org.apache.camel.Message;
 import org.apache.camel.Processor;
+import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.Traceable;
 import org.apache.camel.spi.DataFormat;
 import org.apache.camel.support.ServiceSupport;
@@ -50,13 +51,28 @@ public class UnmarshalProcessor extends 
 
         InputStream stream = ExchangeHelper.getMandatoryInBody(exchange, InputStream.class);
         try {
-            // lets setup the out message before we invoke the dataFormat
-            // so that it can mutate it if necessary
+            // lets setup the out message before we invoke the dataFormat so that it can mutate it if necessary
             Message out = exchange.getOut();
             out.copyFrom(exchange.getIn());
 
             Object result = dataFormat.unmarshal(exchange, stream);
-            out.setBody(result);
+            if (result instanceof Exchange) {
+                if (result != exchange) {
+                    // it's not allowed to return another exchange other than the one provided to dataFormat
+                    throw new RuntimeCamelException("The returned exchange " + result + " is not the same as " + exchange + " provided to the DataFormat");
+                }
+            } else if (result instanceof Message) {
+                Message message = (Message) result;
+
+                // message body should be already set properly by the dataFormat
+                ObjectHelper.notNull(message.getBody(), "body", message);
+
+                // the dataformat has probably set headers, attachments, etc. so let's use it as the outbound payload
+                exchange.setOut((Message) result);
+            } else {
+                ObjectHelper.notNull(result, "result");
+                out.setBody(result);
+            }
         } catch (Exception e) {
             // remove OUT message, as an exception occurred
             exchange.setOut(null);

Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/spi/DataFormat.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/spi/DataFormat.java?rev=1296787&r1=1296786&r2=1296787&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/spi/DataFormat.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/spi/DataFormat.java Sun Mar  4 12:39:03 2012
@@ -20,6 +20,7 @@ import java.io.InputStream;
 import java.io.OutputStream;
 
 import org.apache.camel.Exchange;
+import org.apache.camel.Message;
 
 /**
  * Represents a
@@ -48,11 +49,14 @@ public interface DataFormat {
      * <b>Notice:</b> The result is set as body on the exchange OUT message.
      * It is possible to mutate the OUT message provided in the given exchange parameter.
      * For instance adding headers to the OUT message will be preserved.
+     * <p/>
+     * It's also legal to return the <b>same</b> passed <tt>exchange</tt> as is but also a
+     * {@link Message} object as well which will be used as the OUT message of <tt>exchange</tt>.
      *
      * @param exchange    the current exchange
      * @param stream      the input stream with the object to be unmarshalled
      * @return            the unmarshalled object
-     * @throws Exception can be thrown
+     * @throws Exception can be thrown, for example when the body of the OUT message becomes <tt>null</tt>
      */
     Object unmarshal(Exchange exchange, InputStream stream) throws Exception;
 }

Added: camel/trunk/camel-core/src/test/java/org/apache/camel/processor/UnmarshalProcessorTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/UnmarshalProcessorTest.java?rev=1296787&view=auto
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/processor/UnmarshalProcessorTest.java (added)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/processor/UnmarshalProcessorTest.java Sun Mar  4 12:39:03 2012
@@ -0,0 +1,101 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.processor;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.TestSupport;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.impl.DefaultMessage;
+import org.apache.camel.spi.DataFormat;
+
+public class UnmarshalProcessorTest extends TestSupport {
+
+    public void testDataFormatReturnsSameExchange() throws Exception {
+        Exchange exchange = createExchangeWithBody(new DefaultCamelContext(), "body");
+        UnmarshalProcessor processor = new UnmarshalProcessor(new MyDataFormat(exchange));
+
+        processor.process(exchange);
+
+        // as the process method call above acts as noop there's nothing to assert on
+    }
+
+    public void testDataFormatReturnsAnotherExchange() throws Exception {
+        CamelContext context = new DefaultCamelContext();
+        Exchange exchange = createExchangeWithBody(context, "body");
+        Exchange exchange2 = createExchangeWithBody(context, "body2");
+        UnmarshalProcessor processor = new UnmarshalProcessor(new MyDataFormat(exchange2));
+
+        try {
+            processor.process(exchange);
+            fail("Should have thrown exception");
+        } catch (RuntimeCamelException e) {
+            assertEquals("The returned exchange " + exchange2 + " is not the same as " + exchange + " provided to the DataFormat", e.getMessage());
+        }
+    }
+
+    public void testDataFormatReturnsMessage() throws Exception {
+        Exchange exchange = createExchangeWithBody(new DefaultCamelContext(), "body");
+        Message out = new DefaultMessage();
+        out.setBody(new Object());
+        UnmarshalProcessor processor = new UnmarshalProcessor(new MyDataFormat(out));
+
+        processor.process(exchange);
+        assertEquals(out, exchange.getOut());
+    }
+
+    public void testDataFormatReturnsBody() throws Exception {
+        Exchange exchange = createExchangeWithBody(new DefaultCamelContext(), "body");
+        Object unmarshalled = new Object();
+        UnmarshalProcessor processor = new UnmarshalProcessor(new MyDataFormat(unmarshalled));
+
+        processor.process(exchange);
+        assertEquals(unmarshalled, exchange.getOut().getBody());
+    }
+
+    private static class MyDataFormat implements DataFormat {
+
+        private final Object object;
+
+        MyDataFormat(Exchange exchange) {
+            object = exchange;
+        }
+
+        MyDataFormat(Message message) {
+            object = message;
+        }
+
+        MyDataFormat(Object unmarshalled) {
+            object = unmarshalled;
+        }
+
+        @Override
+        public void marshal(Exchange exchange, Object graph, OutputStream stream) throws Exception {
+            throw new IllegalAccessException("This method is not expected to be used by UnmarshalProcessor");
+        }
+
+        @Override
+        public Object unmarshal(Exchange exchange, InputStream stream) throws Exception {
+            return object;
+        }
+    }
+}

Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/processor/UnmarshalProcessorTest.java
------------------------------------------------------------------------------
    svn:eol-style = native



Re: svn commit: r1296787 - in /camel/trunk/camel-core/src: main/java/org/apache/camel/processor/UnmarshalProcessor.java main/java/org/apache/camel/spi/DataFormat.java test/java/org/apache/camel/processor/UnmarshalProcessorTest.java

Posted by Johan Edstrom <je...@savoirtech.com>.
Thank you Babak!

On Mar 5, 2012, at 1:15 AM, Babak Vahdat wrote:

> Hi Claus
> 
> I did relax that notNull restriction now.
> 
> Babak
> 
> --
> View this message in context: http://camel.465427.n5.nabble.com/Re-svn-commit-r1296787-in-camel-trunk-camel-core-src-main-java-org-apache-camel-processor-UnmarshalPa-tp5536800p5536844.html
> Sent from the Camel Development mailing list archive at Nabble.com.


Re: svn commit: r1296787 - in /camel/trunk/camel-core/src: main/java/org/apache/camel/processor/UnmarshalProcessor.java main/java/org/apache/camel/spi/DataFormat.java test/java/org/apache/camel/processor/UnmarshalProcessorTest.java

Posted by Babak Vahdat <ba...@swissonline.ch>.
Hi Claus

I did relax that notNull restriction now.

Babak

--
View this message in context: http://camel.465427.n5.nabble.com/Re-svn-commit-r1296787-in-camel-trunk-camel-core-src-main-java-org-apache-camel-processor-UnmarshalPa-tp5536800p5536844.html
Sent from the Camel Development mailing list archive at Nabble.com.

Re: svn commit: r1296787 - in /camel/trunk/camel-core/src: main/java/org/apache/camel/processor/UnmarshalProcessor.java main/java/org/apache/camel/spi/DataFormat.java test/java/org/apache/camel/processor/UnmarshalProcessorTest.java

Posted by Johan Edstrom <je...@savoirtech.com>.
Eeee….

We can't just change API :)


On Mar 5, 2012, at 12:51 AM, Claus Ibsen wrote:

> Hi Babak
> 
> It should be okay for the unmarshal processor to return null, which
> means the body should be set to null as a result.
> You have introduced a not null check, which now will cause problems.
> 
> Also this check will always pass as getBody will lazy create an empty
> body as its stated in its javadoc.
> You should use hasBody() to check for that instead
> 
>>  ObjectHelper.notNull(message.getBody(), "body", message);
> 
> 
> Some tests that fails due this are
> https://builds.apache.org/job/Camel.trunk.fulltest/728/
> 
> 
> On Sun, Mar 4, 2012 at 1:39 PM,  <bv...@apache.org> wrote:
>> Author: bvahdat
>> Date: Sun Mar  4 12:39:03 2012
>> New Revision: 1296787
>> 
>> URL: http://svn.apache.org/viewvc?rev=1296787&view=rev
>> Log:
>> CAMEL-4797: DataFormat.unmarshal() should allow to return Message or Exchange to make it more flexible.
>> 
>> Added:
>>    camel/trunk/camel-core/src/test/java/org/apache/camel/processor/UnmarshalProcessorTest.java   (with props)
>> Modified:
>>    camel/trunk/camel-core/src/main/java/org/apache/camel/processor/UnmarshalProcessor.java
>>    camel/trunk/camel-core/src/main/java/org/apache/camel/spi/DataFormat.java
>> 
>> Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/processor/UnmarshalProcessor.java
>> URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/UnmarshalProcessor.java?rev=1296787&r1=1296786&r2=1296787&view=diff
>> ==============================================================================
>> --- camel/trunk/camel-core/src/main/java/org/apache/camel/processor/UnmarshalProcessor.java (original)
>> +++ camel/trunk/camel-core/src/main/java/org/apache/camel/processor/UnmarshalProcessor.java Sun Mar  4 12:39:03 2012
>> @@ -23,6 +23,7 @@ import org.apache.camel.CamelContextAwar
>>  import org.apache.camel.Exchange;
>>  import org.apache.camel.Message;
>>  import org.apache.camel.Processor;
>> +import org.apache.camel.RuntimeCamelException;
>>  import org.apache.camel.Traceable;
>>  import org.apache.camel.spi.DataFormat;
>>  import org.apache.camel.support.ServiceSupport;
>> @@ -50,13 +51,28 @@ public class UnmarshalProcessor extends
>> 
>>         InputStream stream = ExchangeHelper.getMandatoryInBody(exchange, InputStream.class);
>>         try {
>> -            // lets setup the out message before we invoke the dataFormat
>> -            // so that it can mutate it if necessary
>> +            // lets setup the out message before we invoke the dataFormat so that it can mutate it if necessary
>>             Message out = exchange.getOut();
>>             out.copyFrom(exchange.getIn());
>> 
>>             Object result = dataFormat.unmarshal(exchange, stream);
>> -            out.setBody(result);
>> +            if (result instanceof Exchange) {
>> +                if (result != exchange) {
>> +                    // it's not allowed to return another exchange other than the one provided to dataFormat
>> +                    throw new RuntimeCamelException("The returned exchange " + result + " is not the same as " + exchange + " provided to the DataFormat");
>> +                }
>> +            } else if (result instanceof Message) {
>> +                Message message = (Message) result;
>> +
>> +                // message body should be already set properly by the dataFormat
>> +                ObjectHelper.notNull(message.getBody(), "body", message);
>> +
>> +                // the dataformat has probably set headers, attachments, etc. so let's use it as the outbound payload
>> +                exchange.setOut((Message) result);
>> +            } else {
>> +                ObjectHelper.notNull(result, "result");
>> +                out.setBody(result);
>> +            }
>>         } catch (Exception e) {
>>             // remove OUT message, as an exception occurred
>>             exchange.setOut(null);
>> 
>> Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/spi/DataFormat.java
>> URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/spi/DataFormat.java?rev=1296787&r1=1296786&r2=1296787&view=diff
>> ==============================================================================
>> --- camel/trunk/camel-core/src/main/java/org/apache/camel/spi/DataFormat.java (original)
>> +++ camel/trunk/camel-core/src/main/java/org/apache/camel/spi/DataFormat.java Sun Mar  4 12:39:03 2012
>> @@ -20,6 +20,7 @@ import java.io.InputStream;
>>  import java.io.OutputStream;
>> 
>>  import org.apache.camel.Exchange;
>> +import org.apache.camel.Message;
>> 
>>  /**
>>  * Represents a
>> @@ -48,11 +49,14 @@ public interface DataFormat {
>>      * <b>Notice:</b> The result is set as body on the exchange OUT message.
>>      * It is possible to mutate the OUT message provided in the given exchange parameter.
>>      * For instance adding headers to the OUT message will be preserved.
>> +     * <p/>
>> +     * It's also legal to return the <b>same</b> passed <tt>exchange</tt> as is but also a
>> +     * {@link Message} object as well which will be used as the OUT message of <tt>exchange</tt>.
>>      *
>>      * @param exchange    the current exchange
>>      * @param stream      the input stream with the object to be unmarshalled
>>      * @return            the unmarshalled object
>> -     * @throws Exception can be thrown
>> +     * @throws Exception can be thrown, for example when the body of the OUT message becomes <tt>null</tt>
>>      */
>>     Object unmarshal(Exchange exchange, InputStream stream) throws Exception;
>>  }
>> 
>> Added: camel/trunk/camel-core/src/test/java/org/apache/camel/processor/UnmarshalProcessorTest.java
>> URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/UnmarshalProcessorTest.java?rev=1296787&view=auto
>> ==============================================================================
>> --- camel/trunk/camel-core/src/test/java/org/apache/camel/processor/UnmarshalProcessorTest.java (added)
>> +++ camel/trunk/camel-core/src/test/java/org/apache/camel/processor/UnmarshalProcessorTest.java Sun Mar  4 12:39:03 2012
>> @@ -0,0 +1,101 @@
>> +/**
>> + * Licensed to the Apache Software Foundation (ASF) under one or more
>> + * contributor license agreements.  See the NOTICE file distributed with
>> + * this work for additional information regarding copyright ownership.
>> + * The ASF licenses this file to You under the Apache License, Version 2.0
>> + * (the "License"); you may not use this file except in compliance with
>> + * the License.  You may obtain a copy of the License at
>> + *
>> + *      http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + * Unless required by applicable law or agreed to in writing, software
>> + * distributed under the License is distributed on an "AS IS" BASIS,
>> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
>> + * See the License for the specific language governing permissions and
>> + * limitations under the License.
>> + */
>> +package org.apache.camel.processor;
>> +
>> +import java.io.InputStream;
>> +import java.io.OutputStream;
>> +
>> +import org.apache.camel.CamelContext;
>> +import org.apache.camel.Exchange;
>> +import org.apache.camel.Message;
>> +import org.apache.camel.RuntimeCamelException;
>> +import org.apache.camel.TestSupport;
>> +import org.apache.camel.impl.DefaultCamelContext;
>> +import org.apache.camel.impl.DefaultMessage;
>> +import org.apache.camel.spi.DataFormat;
>> +
>> +public class UnmarshalProcessorTest extends TestSupport {
>> +
>> +    public void testDataFormatReturnsSameExchange() throws Exception {
>> +        Exchange exchange = createExchangeWithBody(new DefaultCamelContext(), "body");
>> +        UnmarshalProcessor processor = new UnmarshalProcessor(new MyDataFormat(exchange));
>> +
>> +        processor.process(exchange);
>> +
>> +        // as the process method call above acts as noop there's nothing to assert on
>> +    }
>> +
>> +    public void testDataFormatReturnsAnotherExchange() throws Exception {
>> +        CamelContext context = new DefaultCamelContext();
>> +        Exchange exchange = createExchangeWithBody(context, "body");
>> +        Exchange exchange2 = createExchangeWithBody(context, "body2");
>> +        UnmarshalProcessor processor = new UnmarshalProcessor(new MyDataFormat(exchange2));
>> +
>> +        try {
>> +            processor.process(exchange);
>> +            fail("Should have thrown exception");
>> +        } catch (RuntimeCamelException e) {
>> +            assertEquals("The returned exchange " + exchange2 + " is not the same as " + exchange + " provided to the DataFormat", e.getMessage());
>> +        }
>> +    }
>> +
>> +    public void testDataFormatReturnsMessage() throws Exception {
>> +        Exchange exchange = createExchangeWithBody(new DefaultCamelContext(), "body");
>> +        Message out = new DefaultMessage();
>> +        out.setBody(new Object());
>> +        UnmarshalProcessor processor = new UnmarshalProcessor(new MyDataFormat(out));
>> +
>> +        processor.process(exchange);
>> +        assertEquals(out, exchange.getOut());
>> +    }
>> +
>> +    public void testDataFormatReturnsBody() throws Exception {
>> +        Exchange exchange = createExchangeWithBody(new DefaultCamelContext(), "body");
>> +        Object unmarshalled = new Object();
>> +        UnmarshalProcessor processor = new UnmarshalProcessor(new MyDataFormat(unmarshalled));
>> +
>> +        processor.process(exchange);
>> +        assertEquals(unmarshalled, exchange.getOut().getBody());
>> +    }
>> +
>> +    private static class MyDataFormat implements DataFormat {
>> +
>> +        private final Object object;
>> +
>> +        MyDataFormat(Exchange exchange) {
>> +            object = exchange;
>> +        }
>> +
>> +        MyDataFormat(Message message) {
>> +            object = message;
>> +        }
>> +
>> +        MyDataFormat(Object unmarshalled) {
>> +            object = unmarshalled;
>> +        }
>> +
>> +        @Override
>> +        public void marshal(Exchange exchange, Object graph, OutputStream stream) throws Exception {
>> +            throw new IllegalAccessException("This method is not expected to be used by UnmarshalProcessor");
>> +        }
>> +
>> +        @Override
>> +        public Object unmarshal(Exchange exchange, InputStream stream) throws Exception {
>> +            return object;
>> +        }
>> +    }
>> +}
>> 
>> Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/processor/UnmarshalProcessorTest.java
>> ------------------------------------------------------------------------------
>>    svn:eol-style = native
>> 
>> 
> 
> 
> 
> -- 
> Claus Ibsen
> -----------------
> FuseSource
> Email: cibsen@fusesource.com
> Web: http://fusesource.com
> Twitter: davsclaus, fusenews
> Blog: http://davsclaus.blogspot.com/
> Author of Camel in Action: http://www.manning.com/ibsen/


Re: svn commit: r1296787 - in /camel/trunk/camel-core/src: main/java/org/apache/camel/processor/UnmarshalProcessor.java main/java/org/apache/camel/spi/DataFormat.java test/java/org/apache/camel/processor/UnmarshalProcessorTest.java

Posted by Claus Ibsen <cl...@gmail.com>.
Hi Babak

It should be okay for the unmarshal processor to return null, which
means the body should be set to null as a result.
You have introduced a not null check, which now will cause problems.

Also this check will always pass as getBody will lazy create an empty
body as its stated in its javadoc.
You should use hasBody() to check for that instead

>  ObjectHelper.notNull(message.getBody(), "body", message);


Some tests that fails due this are
https://builds.apache.org/job/Camel.trunk.fulltest/728/


On Sun, Mar 4, 2012 at 1:39 PM,  <bv...@apache.org> wrote:
> Author: bvahdat
> Date: Sun Mar  4 12:39:03 2012
> New Revision: 1296787
>
> URL: http://svn.apache.org/viewvc?rev=1296787&view=rev
> Log:
> CAMEL-4797: DataFormat.unmarshal() should allow to return Message or Exchange to make it more flexible.
>
> Added:
>    camel/trunk/camel-core/src/test/java/org/apache/camel/processor/UnmarshalProcessorTest.java   (with props)
> Modified:
>    camel/trunk/camel-core/src/main/java/org/apache/camel/processor/UnmarshalProcessor.java
>    camel/trunk/camel-core/src/main/java/org/apache/camel/spi/DataFormat.java
>
> Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/processor/UnmarshalProcessor.java
> URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/processor/UnmarshalProcessor.java?rev=1296787&r1=1296786&r2=1296787&view=diff
> ==============================================================================
> --- camel/trunk/camel-core/src/main/java/org/apache/camel/processor/UnmarshalProcessor.java (original)
> +++ camel/trunk/camel-core/src/main/java/org/apache/camel/processor/UnmarshalProcessor.java Sun Mar  4 12:39:03 2012
> @@ -23,6 +23,7 @@ import org.apache.camel.CamelContextAwar
>  import org.apache.camel.Exchange;
>  import org.apache.camel.Message;
>  import org.apache.camel.Processor;
> +import org.apache.camel.RuntimeCamelException;
>  import org.apache.camel.Traceable;
>  import org.apache.camel.spi.DataFormat;
>  import org.apache.camel.support.ServiceSupport;
> @@ -50,13 +51,28 @@ public class UnmarshalProcessor extends
>
>         InputStream stream = ExchangeHelper.getMandatoryInBody(exchange, InputStream.class);
>         try {
> -            // lets setup the out message before we invoke the dataFormat
> -            // so that it can mutate it if necessary
> +            // lets setup the out message before we invoke the dataFormat so that it can mutate it if necessary
>             Message out = exchange.getOut();
>             out.copyFrom(exchange.getIn());
>
>             Object result = dataFormat.unmarshal(exchange, stream);
> -            out.setBody(result);
> +            if (result instanceof Exchange) {
> +                if (result != exchange) {
> +                    // it's not allowed to return another exchange other than the one provided to dataFormat
> +                    throw new RuntimeCamelException("The returned exchange " + result + " is not the same as " + exchange + " provided to the DataFormat");
> +                }
> +            } else if (result instanceof Message) {
> +                Message message = (Message) result;
> +
> +                // message body should be already set properly by the dataFormat
> +                ObjectHelper.notNull(message.getBody(), "body", message);
> +
> +                // the dataformat has probably set headers, attachments, etc. so let's use it as the outbound payload
> +                exchange.setOut((Message) result);
> +            } else {
> +                ObjectHelper.notNull(result, "result");
> +                out.setBody(result);
> +            }
>         } catch (Exception e) {
>             // remove OUT message, as an exception occurred
>             exchange.setOut(null);
>
> Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/spi/DataFormat.java
> URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/spi/DataFormat.java?rev=1296787&r1=1296786&r2=1296787&view=diff
> ==============================================================================
> --- camel/trunk/camel-core/src/main/java/org/apache/camel/spi/DataFormat.java (original)
> +++ camel/trunk/camel-core/src/main/java/org/apache/camel/spi/DataFormat.java Sun Mar  4 12:39:03 2012
> @@ -20,6 +20,7 @@ import java.io.InputStream;
>  import java.io.OutputStream;
>
>  import org.apache.camel.Exchange;
> +import org.apache.camel.Message;
>
>  /**
>  * Represents a
> @@ -48,11 +49,14 @@ public interface DataFormat {
>      * <b>Notice:</b> The result is set as body on the exchange OUT message.
>      * It is possible to mutate the OUT message provided in the given exchange parameter.
>      * For instance adding headers to the OUT message will be preserved.
> +     * <p/>
> +     * It's also legal to return the <b>same</b> passed <tt>exchange</tt> as is but also a
> +     * {@link Message} object as well which will be used as the OUT message of <tt>exchange</tt>.
>      *
>      * @param exchange    the current exchange
>      * @param stream      the input stream with the object to be unmarshalled
>      * @return            the unmarshalled object
> -     * @throws Exception can be thrown
> +     * @throws Exception can be thrown, for example when the body of the OUT message becomes <tt>null</tt>
>      */
>     Object unmarshal(Exchange exchange, InputStream stream) throws Exception;
>  }
>
> Added: camel/trunk/camel-core/src/test/java/org/apache/camel/processor/UnmarshalProcessorTest.java
> URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/UnmarshalProcessorTest.java?rev=1296787&view=auto
> ==============================================================================
> --- camel/trunk/camel-core/src/test/java/org/apache/camel/processor/UnmarshalProcessorTest.java (added)
> +++ camel/trunk/camel-core/src/test/java/org/apache/camel/processor/UnmarshalProcessorTest.java Sun Mar  4 12:39:03 2012
> @@ -0,0 +1,101 @@
> +/**
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements.  See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to You under the Apache License, Version 2.0
> + * (the "License"); you may not use this file except in compliance with
> + * the License.  You may obtain a copy of the License at
> + *
> + *      http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +package org.apache.camel.processor;
> +
> +import java.io.InputStream;
> +import java.io.OutputStream;
> +
> +import org.apache.camel.CamelContext;
> +import org.apache.camel.Exchange;
> +import org.apache.camel.Message;
> +import org.apache.camel.RuntimeCamelException;
> +import org.apache.camel.TestSupport;
> +import org.apache.camel.impl.DefaultCamelContext;
> +import org.apache.camel.impl.DefaultMessage;
> +import org.apache.camel.spi.DataFormat;
> +
> +public class UnmarshalProcessorTest extends TestSupport {
> +
> +    public void testDataFormatReturnsSameExchange() throws Exception {
> +        Exchange exchange = createExchangeWithBody(new DefaultCamelContext(), "body");
> +        UnmarshalProcessor processor = new UnmarshalProcessor(new MyDataFormat(exchange));
> +
> +        processor.process(exchange);
> +
> +        // as the process method call above acts as noop there's nothing to assert on
> +    }
> +
> +    public void testDataFormatReturnsAnotherExchange() throws Exception {
> +        CamelContext context = new DefaultCamelContext();
> +        Exchange exchange = createExchangeWithBody(context, "body");
> +        Exchange exchange2 = createExchangeWithBody(context, "body2");
> +        UnmarshalProcessor processor = new UnmarshalProcessor(new MyDataFormat(exchange2));
> +
> +        try {
> +            processor.process(exchange);
> +            fail("Should have thrown exception");
> +        } catch (RuntimeCamelException e) {
> +            assertEquals("The returned exchange " + exchange2 + " is not the same as " + exchange + " provided to the DataFormat", e.getMessage());
> +        }
> +    }
> +
> +    public void testDataFormatReturnsMessage() throws Exception {
> +        Exchange exchange = createExchangeWithBody(new DefaultCamelContext(), "body");
> +        Message out = new DefaultMessage();
> +        out.setBody(new Object());
> +        UnmarshalProcessor processor = new UnmarshalProcessor(new MyDataFormat(out));
> +
> +        processor.process(exchange);
> +        assertEquals(out, exchange.getOut());
> +    }
> +
> +    public void testDataFormatReturnsBody() throws Exception {
> +        Exchange exchange = createExchangeWithBody(new DefaultCamelContext(), "body");
> +        Object unmarshalled = new Object();
> +        UnmarshalProcessor processor = new UnmarshalProcessor(new MyDataFormat(unmarshalled));
> +
> +        processor.process(exchange);
> +        assertEquals(unmarshalled, exchange.getOut().getBody());
> +    }
> +
> +    private static class MyDataFormat implements DataFormat {
> +
> +        private final Object object;
> +
> +        MyDataFormat(Exchange exchange) {
> +            object = exchange;
> +        }
> +
> +        MyDataFormat(Message message) {
> +            object = message;
> +        }
> +
> +        MyDataFormat(Object unmarshalled) {
> +            object = unmarshalled;
> +        }
> +
> +        @Override
> +        public void marshal(Exchange exchange, Object graph, OutputStream stream) throws Exception {
> +            throw new IllegalAccessException("This method is not expected to be used by UnmarshalProcessor");
> +        }
> +
> +        @Override
> +        public Object unmarshal(Exchange exchange, InputStream stream) throws Exception {
> +            return object;
> +        }
> +    }
> +}
>
> Propchange: camel/trunk/camel-core/src/test/java/org/apache/camel/processor/UnmarshalProcessorTest.java
> ------------------------------------------------------------------------------
>    svn:eol-style = native
>
>



-- 
Claus Ibsen
-----------------
FuseSource
Email: cibsen@fusesource.com
Web: http://fusesource.com
Twitter: davsclaus, fusenews
Blog: http://davsclaus.blogspot.com/
Author of Camel in Action: http://www.manning.com/ibsen/