Author: davsclaus
Date: Thu Oct 22 13:10:46 2009
New Revision: 828677

URL: http://svn.apache.org/viewvc?rev=828677&view=rev
Log:
CAMEL-2101: Camel proxy now converters answer to the expected type of the 
method signature. This avoids class cast exceptions.

Added:
    
camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanProxyTest.java
   (with props)
    
camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/OrderService.java
   (with props)
Modified:
    
camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java
    
camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanConverter.java
    
camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/CamelInvocationHandler.java
    
camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/ToStringTypeConverter.java

Modified: 
camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java?rev=828677&r1=828676&r2=828677&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java
 (original)
+++ 
camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java
 Thu Oct 22 13:10:46 2009
@@ -35,6 +35,7 @@
 import javax.xml.xpath.XPathFunctionException;
 import javax.xml.xpath.XPathFunctionResolver;
 
+import org.apache.camel.component.bean.BeanInvocation;
 import org.w3c.dom.Document;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
@@ -594,6 +595,13 @@
             // special for files so we can work with them out of the box
             InputStream is = 
exchange.getContext().getTypeConverter().convertTo(InputStream.class, answer);
             answer = new InputSource(is);
+        } else if (answer instanceof BeanInvocation) {
+            // if its a null bean invocation then handle that
+            BeanInvocation bi = 
exchange.getContext().getTypeConverter().convertTo(BeanInvocation.class, 
answer);
+            if (bi.getArgs() != null && bi.getArgs().length == 1 && 
bi.getArgs()[0] == null) {
+                // its a null argument from the bean invocation so use null as 
answer
+                answer = null;
+            }
         } else if (answer instanceof String) {
             answer = new InputSource(new StringReader(answer.toString()));
         }

Modified: 
camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanConverter.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanConverter.java?rev=828677&r1=828676&r2=828677&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanConverter.java
 (original)
+++ 
camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanConverter.java
 Thu Oct 22 13:10:46 2009
@@ -35,7 +35,7 @@
     @FallbackConverter
     @SuppressWarnings("unchecked")
     public static Object convertTo(Class<?> type, Exchange exchange, Object 
value, TypeConverterRegistry registry) {
-        // use a fallback type converter so we can convert the embedded body 
if the value is GenericFile
+        // use a fallback type converter so we can convert the embedded body 
if the value is BeanInvocation
         if (BeanInvocation.class.isAssignableFrom(value.getClass())) {
 
             BeanInvocation bi = (BeanInvocation) value;

Modified: 
camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/CamelInvocationHandler.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/CamelInvocationHandler.java?rev=828677&r1=828676&r2=828677&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/CamelInvocationHandler.java
 (original)
+++ 
camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/CamelInvocationHandler.java
 Thu Oct 22 13:10:46 2009
@@ -26,6 +26,8 @@
 import org.apache.camel.Producer;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.impl.DefaultExchange;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 
 /**
  * An {...@link java.lang.reflect.InvocationHandler} which invokes a
@@ -34,6 +36,8 @@
  * @version $Revision$
  */
 public class CamelInvocationHandler implements InvocationHandler {
+    private static final transient Log LOG = 
LogFactory.getLog(CamelInvocationHandler.class);
+
     private final Endpoint endpoint;
     private final Producer producer;
     private final MethodInfoCache methodInfoCache;
@@ -54,7 +58,13 @@
         Exchange exchange = new DefaultExchange(endpoint, pattern);
         exchange.getIn().setBody(invocation);
 
+        // process the exchange
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("Proxied method call " + method.getName() + " invoking 
producer: " + producer);
+        }
         producer.process(exchange);
+
+        // check if we had an exception
         Throwable fault = exchange.getException();
         if (fault != null) {
             if (fault instanceof RuntimeCamelException) {
@@ -67,12 +77,19 @@
             throw new InvocationTargetException(fault);
         }
 
-        // TODO: type convert to method signature
-        if (pattern.isOutCapable()) {
-            return exchange.getOut().getBody();
-        } else {
+        // do not return a reply if the method is VOID or the MEP is not OUT 
capable
+        Class<?> to = method.getReturnType();
+        if (to == Void.TYPE || !pattern.isOutCapable()) {
             return null;
         }
+
+        // use type converter so we can convert output in the desired type 
defined by the method
+        // and let it be mandatory so we know wont return null if we cant 
convert it to the defined type
+        Object answer = exchange.getOut().getMandatoryBody(to);
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("Proxied method call " + method.getName() + " returning: 
" + answer);
+        }
+        return answer;
     }
 }
 

Modified: 
camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/ToStringTypeConverter.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/ToStringTypeConverter.java?rev=828677&r1=828676&r2=828677&view=diff
==============================================================================
--- 
camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/ToStringTypeConverter.java
 (original)
+++ 
camel/trunk/camel-core/src/main/java/org/apache/camel/impl/converter/ToStringTypeConverter.java
 Thu Oct 22 13:10:46 2009
@@ -46,7 +46,7 @@
                 return (T) Void.TYPE;
             }
 
-            // should not try to bean invocations
+            // should not try to convert bean invocations
             if (BeanInvocation.class.isAssignableFrom(value.getClass())) {
                 return (T) Void.TYPE;
             }

Added: 
camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanProxyTest.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanProxyTest.java?rev=828677&view=auto
==============================================================================
--- 
camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanProxyTest.java
 (added)
+++ 
camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanProxyTest.java
 Thu Oct 22 13:10:46 2009
@@ -0,0 +1,138 @@
+/**
+ * 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.component.bean;
+
+import org.apache.camel.InvalidPayloadException;
+import org.w3c.dom.Document;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Endpoint;
+import org.apache.camel.builder.RouteBuilder;
+import static org.apache.camel.builder.xml.XPathBuilder.xpath;
+
+/**
+ * @version $Revision$
+ */
+public class BeanProxyTest extends ContextTestSupport {
+
+    public void testBeanProxyStringReturnString() throws Exception {
+        Endpoint endpoint = context.getEndpoint("direct:start");
+        OrderService service = ProxyHelper.createProxy(endpoint, 
OrderService.class);
+
+        String reply = service.submitOrderStringReturnString("<order 
type=\"book\">Camel in action</order>");
+        assertEquals("<order id=\"123\">OK</order>", reply);
+    }
+
+    public void testBeanProxyStringReturnDocument() throws Exception {
+        Endpoint endpoint = context.getEndpoint("direct:start");
+        OrderService service = ProxyHelper.createProxy(endpoint, 
OrderService.class);
+
+        Document reply = service.submitOrderStringReturnDocument("<order 
type=\"book\">Camel in action</order>");
+        assertNotNull(reply);
+        String s = context.getTypeConverter().convertTo(String.class, reply);
+        assertEquals("<order id=\"123\">OK</order>", s);
+    }
+
+    public void testBeanProxyDocumentReturnString() throws Exception {
+        Endpoint endpoint = context.getEndpoint("direct:start");
+        OrderService service = ProxyHelper.createProxy(endpoint, 
OrderService.class);
+
+        Document doc = context.getTypeConverter().convertTo(Document.class, 
"<order type=\"book\">Camel in action</order>");
+
+        String reply = service.submitOrderDocumentReturnString(doc);
+        assertEquals("<order id=\"123\">OK</order>", reply);
+    }
+
+    public void testBeanProxyDocumentReturnDocument() throws Exception {
+        Endpoint endpoint = context.getEndpoint("direct:start");
+        OrderService service = ProxyHelper.createProxy(endpoint, 
OrderService.class);
+
+        Document doc = context.getTypeConverter().convertTo(Document.class, 
"<order type=\"book\">Camel in action</order>");
+
+        Document reply = service.submitOrderDocumentReturnDocument(doc);
+        assertNotNull(reply);
+        String s = context.getTypeConverter().convertTo(String.class, reply);
+        assertEquals("<order id=\"123\">OK</order>", s);
+    }
+
+    public void testBeanProxyFailure() throws Exception {
+        Endpoint endpoint = context.getEndpoint("direct:start");
+        OrderService service = ProxyHelper.createProxy(endpoint, 
OrderService.class);
+
+        String reply = service.submitOrderStringReturnString("<order 
type=\"beer\">Carlsberg</order>");
+        assertEquals("<order>FAIL</order>", reply);
+    }
+
+    public void testBeanProxyFailureNullBody() throws Exception {
+        Endpoint endpoint = context.getEndpoint("direct:start");
+        OrderService service = ProxyHelper.createProxy(endpoint, 
OrderService.class);
+
+        String reply = service.submitOrderStringReturnString(null);
+        assertEquals("<order>FAIL</order>", reply);
+    }
+
+    public void testBeanProxyFailureNotXMLBody() throws Exception {
+        Endpoint endpoint = context.getEndpoint("direct:start");
+        OrderService service = ProxyHelper.createProxy(endpoint, 
OrderService.class);
+
+        try {
+            service.submitOrderStringReturnString("Hello World");
+            fail("Should have thrown exception");
+        } catch (Exception e) {
+            // expected
+        }
+    }
+
+    public void testBeanProxyVoidReturnType() throws Exception {
+        Endpoint endpoint = context.getEndpoint("direct:start");
+        OrderService service = ProxyHelper.createProxy(endpoint, 
OrderService.class);
+
+        service.doNothing("<order>ping</order>");
+    }
+
+    public void testBeanProxyFailureInvalidReturnType() throws Exception {
+        Endpoint endpoint = context.getEndpoint("direct:start");
+        OrderService service = ProxyHelper.createProxy(endpoint, 
OrderService.class);
+
+        try {
+            service.invalidReturnType("<order 
type=\"beer\">Carlsberg</order>");
+            fail("Should have thrown exception");
+        } catch (Exception e) {
+            // expected
+            InvalidPayloadException cause = 
assertIsInstanceOf(InvalidPayloadException.class, e.getCause());
+            assertEquals(Integer.class, cause.getType());
+        }
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start")
+                    .choice()
+                        .when(xpath("/order/@type = 'book'")).to("direct:book")
+                        .otherwise().to("direct:other")
+                    .end();
+
+                from("direct:book").transform(constant("<order 
id=\"123\">OK</order>"));
+
+                
from("direct:other").transform(constant("<order>FAIL</order>"));
+            }
+        };
+    }
+}

Propchange: 
camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanProxyTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanProxyTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: 
camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/OrderService.java
URL: 
http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/OrderService.java?rev=828677&view=auto
==============================================================================
--- 
camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/OrderService.java
 (added)
+++ 
camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/OrderService.java
 Thu Oct 22 13:10:46 2009
@@ -0,0 +1,38 @@
+/**
+ * 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.component.bean;
+
+import org.w3c.dom.Document;
+
+/**
+ * @version $Revision$
+ */
+public interface OrderService {
+
+    String submitOrderStringReturnString(String order);
+
+    Document submitOrderStringReturnDocument(String order);
+
+    String submitOrderDocumentReturnString(Document order);
+
+    Document submitOrderDocumentReturnDocument(Document order);
+
+    void doNothing(String s);
+
+    Integer invalidReturnType(String s);
+
+}

Propchange: 
camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/OrderService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/OrderService.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date


Reply via email to