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