Author: davsclaus Date: Fri Jul 9 08:54:31 2010 New Revision: 962451 URL: http://svn.apache.org/viewvc?rev=962451&view=rev Log: CAMEL-2920: beanRef and method call DSL now validate method name is a valid method on startup. Better to fail fast.
Added: camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanRefMethodNotFoundTest.java - copied, changed from r962430, camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanRefNotFoundTest.java camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MethodCallBeanRefMethodNotFoundTest.java - copied, changed from r962430, camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MethodCallBeanRefNotFoundTest.java Removed: camel/trunk/camel-core/src/test/java/org/apache/camel/processor/aggregator/AggregatorBeanThrowExceptionTest.java Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java camel/trunk/camel-core/src/main/java/org/apache/camel/model/BeanDefinition.java camel/trunk/camel-core/src/main/java/org/apache/camel/model/language/MethodCallExpression.java camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanInfoTest.java camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanWithMethodHeaderTest.java camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MethodCallBeanRefNotFoundTest.java camel/trunk/camel-core/src/test/java/org/apache/camel/view/DotViewTest.java Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java?rev=962451&r1=962450&r2=962451&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java Fri Jul 9 08:54:31 2010 @@ -23,6 +23,8 @@ import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -132,7 +134,7 @@ public class BeanInfo { String name = exchange.getIn().getHeader(Exchange.BEAN_METHOD_NAME, String.class); if (name != null) { - if (hasOperations(name)) { + if (hasMethod(name)) { List<MethodInfo> methods = getOperations(name); if (methods != null && methods.size() == 1) { // only one method then choose it @@ -231,7 +233,7 @@ public class BeanInfo { LOG.trace("Adding operation: " + opName + " for method: " + methodInfo); } - if (hasOperations(opName)) { + if (hasMethod(opName)) { // we have an overloaded method so add the method info to the same key List<MethodInfo> existing = getOperations(opName); existing.add(methodInfo); @@ -672,7 +674,7 @@ public class BeanInfo { } /** - * Do we have an operation with the given name. + * Do we have a method with the given name. * <p/> * Shorthand method names for getters is supported, so you can pass in eg 'name' and Camel * will can find the real 'getName' method instead. @@ -680,11 +682,36 @@ public class BeanInfo { * @param methodName the method name * @return <tt>true</tt> if we have such a method. */ - private boolean hasOperations(String methodName) { + public boolean hasMethod(String methodName) { return getOperations(methodName) != null; } /** + * Gets the list of methods sorted by A..Z method name. + * + * @return the methods. + */ + @SuppressWarnings("unchecked") + public List<MethodInfo> getMethods() { + if (operations.isEmpty()) { + return Collections.EMPTY_LIST; + } + + List<MethodInfo> methods = new ArrayList<MethodInfo>(); + for (Collection<MethodInfo> col : operations.values()) { + methods.addAll(col); + } + + // sort the methods by name A..Z + Collections.sort(methods, new Comparator<MethodInfo>() { + public int compare(MethodInfo o1, MethodInfo o2) { + return o1.getMethod().getName().compareTo(o2.getMethod().getName()); + } + }); + return methods; + } + + /** * Get the operation(s) with the given name. We can have multiple when methods is overloaded. * <p/> * Shorthand method names for getters is supported, so you can pass in eg 'name' and Camel Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/model/BeanDefinition.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/model/BeanDefinition.java?rev=962451&r1=962450&r2=962451&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/model/BeanDefinition.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/model/BeanDefinition.java Fri Jul 9 08:54:31 2010 @@ -22,9 +22,10 @@ import javax.xml.bind.annotation.XmlAttr import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlTransient; -import org.apache.camel.NoSuchBeanException; import org.apache.camel.Processor; +import org.apache.camel.component.bean.BeanInfo; import org.apache.camel.component.bean.BeanProcessor; +import org.apache.camel.component.bean.MethodNotFoundException; import org.apache.camel.component.bean.RegistryBean; import org.apache.camel.spi.Required; import org.apache.camel.spi.RouteContext; @@ -149,11 +150,10 @@ public class BeanDefinition extends Outp public Processor createProcessor(RouteContext routeContext) { BeanProcessor answer; if (ObjectHelper.isNotEmpty(ref)) { - // if its a ref then check that the ref exists - if (routeContext.getCamelContext().getRegistry().lookup(ref) == null) { - throw new NoSuchBeanException(ref); - } - answer = new BeanProcessor(new RegistryBean(routeContext.getCamelContext(), ref)); + RegistryBean beanHolder = new RegistryBean(routeContext.getCamelContext(), ref); + // bean holder will check if the bean exists + bean = beanHolder.getBean(); + answer = new BeanProcessor(beanHolder); } else { if (bean == null) { ObjectHelper.notNull(beanType, "bean, ref or beanType", this); @@ -171,6 +171,12 @@ public class BeanDefinition extends Outp } if (method != null) { answer.setMethod(method); + + // check there is a method with the given name, and leverage BeanInfo for that + BeanInfo info = new BeanInfo(routeContext.getCamelContext(), bean.getClass()); + if (!info.hasMethod(method)) { + throw ObjectHelper.wrapRuntimeCamelException(new MethodNotFoundException(null, bean, method)); + } } return answer; } Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/model/language/MethodCallExpression.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/model/language/MethodCallExpression.java?rev=962451&r1=962450&r2=962451&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/model/language/MethodCallExpression.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/model/language/MethodCallExpression.java Fri Jul 9 08:54:31 2010 @@ -24,8 +24,11 @@ import javax.xml.bind.annotation.XmlTran import org.apache.camel.CamelContext; import org.apache.camel.Expression; -import org.apache.camel.NoSuchBeanException; import org.apache.camel.Predicate; +import org.apache.camel.component.bean.BeanHolder; +import org.apache.camel.component.bean.BeanInfo; +import org.apache.camel.component.bean.MethodNotFoundException; +import org.apache.camel.component.bean.RegistryBean; import org.apache.camel.language.bean.BeanExpression; import org.apache.camel.util.ObjectHelper; @@ -98,33 +101,68 @@ public class MethodCallExpression extend @Override public Expression createExpression(CamelContext camelContext) { + Expression answer; + if (beanType != null) { - return new BeanExpression(ObjectHelper.newInstance(beanType), getMethod()); + instance = ObjectHelper.newInstance(beanType); + return new BeanExpression(instance, getMethod()); } else if (instance != null) { return new BeanExpression(instance, getMethod()); } else { String ref = beanName(); // if its a ref then check that the ref exists - if (camelContext.getRegistry().lookup(ref) == null) { - throw new NoSuchBeanException(ref); - } - return new BeanExpression(ref, getMethod()); + BeanHolder holder = new RegistryBean(camelContext, ref); + // get the bean which will check that it exists + instance = holder.getBean(); + answer = new BeanExpression(ref, getMethod()); } + + // validate method + validateHasMethod(camelContext, instance, getMethod()); + + return answer; } @Override public Predicate createPredicate(CamelContext camelContext) { + Predicate answer; + if (beanType != null) { - return new BeanExpression(ObjectHelper.newInstance(beanType), getMethod()); + instance = ObjectHelper.newInstance(beanType); + answer = new BeanExpression(instance, getMethod()); } else if (instance != null) { - return new BeanExpression(instance, getMethod()); + answer = new BeanExpression(instance, getMethod()); } else { String ref = beanName(); // if its a ref then check that the ref exists - if (camelContext.getRegistry().lookup(ref) == null) { - throw new NoSuchBeanException(ref); - } - return new BeanExpression(ref, getMethod()); + BeanHolder holder = new RegistryBean(camelContext, ref); + // get the bean which will check that it exists + instance = holder.getBean(); + answer = new BeanExpression(ref, getMethod()); + } + + // validate method + validateHasMethod(camelContext, instance, getMethod()); + + return answer; + } + + /** + * Validates the given bean has the method + * + * @param context camel context + * @param bean the bean instance + * @param method the method, can be <tt>null</tt> if no method name provided + * @throws org.apache.camel.RuntimeCamelException is thrown if bean does not have the method + */ + protected void validateHasMethod(CamelContext context, Object bean, String method) { + if (method == null) { + return; + } + + BeanInfo info = new BeanInfo(context, bean.getClass()); + if (!info.hasMethod(method)) { + throw ObjectHelper.wrapRuntimeCamelException(new MethodNotFoundException(null, bean, method)); } } Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanInfoTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanInfoTest.java?rev=962451&r1=962450&r2=962451&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanInfoTest.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanInfoTest.java Fri Jul 9 08:54:31 2010 @@ -17,9 +17,9 @@ package org.apache.camel.component.bean; import java.lang.reflect.Method; +import java.util.List; import junit.framework.TestCase; - import org.apache.camel.CamelContext; import org.apache.camel.ExchangePattern; import org.apache.camel.InOnly; @@ -37,6 +37,16 @@ public class BeanInfoTest extends TestCa protected CamelContext camelContext = new DefaultCamelContext(); + public void testGetOperations() throws Exception { + BeanInfo info = createBeanInfo(Foo.class); + + List<MethodInfo> operations = info.getMethods(); + assertEquals(3, operations.size()); + assertEquals("inOnlyMethod", operations.get(0).getMethod().getName()); + assertEquals("inOutMethod", operations.get(1).getMethod().getName()); + assertEquals("robustInOnlyMethod", operations.get(2).getMethod().getName()); + } + public void testMethodPatternUsingMethodAnnotations() throws Exception { BeanInfo info = createBeanInfo(Foo.class); Copied: camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanRefMethodNotFoundTest.java (from r962430, camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanRefNotFoundTest.java) URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanRefMethodNotFoundTest.java?p2=camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanRefMethodNotFoundTest.java&p1=camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanRefNotFoundTest.java&r1=962430&r2=962451&rev=962451&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanRefNotFoundTest.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanRefMethodNotFoundTest.java Fri Jul 9 08:54:31 2010 @@ -18,14 +18,13 @@ package org.apache.camel.component.bean; import org.apache.camel.ContextTestSupport; import org.apache.camel.FailedToCreateRouteException; -import org.apache.camel.NoSuchBeanException; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.impl.JndiRegistry; /** * @version $Revision$ */ -public class BeanRefNotFoundTest extends ContextTestSupport { +public class BeanRefMethodNotFoundTest extends ContextTestSupport { @Override protected JndiRegistry createRegistry() throws Exception { @@ -34,13 +33,13 @@ public class BeanRefNotFoundTest extends return jndi; } - public void testBeanRefNotFound() throws Exception { + public void testBeanRefMethodNotFound() throws Exception { context.addRoutes(new RouteBuilder() { @Override public void configure() throws Exception { - from("direct:a").routeId("a").beanRef("foo").to("mock:a"); + from("direct:a").routeId("a").beanRef("foo", "hello").to("mock:a"); - from("direct:b").routeId("b").beanRef("bar").to("mock:b"); + from("direct:b").routeId("b").beanRef("foo", "bye").to("mock:b"); } }); try { @@ -48,8 +47,8 @@ public class BeanRefNotFoundTest extends fail("Should have thrown exception"); } catch (FailedToCreateRouteException e) { assertEquals("b", e.getRouteId()); - NoSuchBeanException cause = assertIsInstanceOf(NoSuchBeanException.class, e.getCause()); - assertEquals("bar", cause.getName()); + MethodNotFoundException cause = assertIsInstanceOf(MethodNotFoundException.class, e.getCause().getCause()); + assertEquals("bye", cause.getMethodName()); } } @@ -57,4 +56,4 @@ public class BeanRefNotFoundTest extends public boolean isUseRouteBuilder() { return false; } -} +} \ No newline at end of file Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanWithMethodHeaderTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanWithMethodHeaderTest.java?rev=962451&r1=962450&r2=962451&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanWithMethodHeaderTest.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/BeanWithMethodHeaderTest.java Fri Jul 9 08:54:31 2010 @@ -22,6 +22,7 @@ import org.apache.camel.CamelExecutionEx import org.apache.camel.ContextTestSupport; import org.apache.camel.Exchange; import org.apache.camel.ExchangePattern; +import org.apache.camel.FailedToCreateRouteException; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; import org.apache.camel.util.jndi.JndiContext; @@ -86,11 +87,15 @@ public class BeanWithMethodHeaderTest ex public void testMethodNotExists() throws Exception { try { - template.sendBody("direct:typo", "Hello World"); + context.addRoutes(new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:typo").beanRef("myBean", "ups").to("mock:result"); + } + }); fail("Should throw an exception"); - } catch (CamelExecutionException e) { - assertIsInstanceOf(MethodNotFoundException.class, e.getCause()); - MethodNotFoundException mnfe = (MethodNotFoundException) e.getCause(); + } catch (FailedToCreateRouteException e) { + MethodNotFoundException mnfe = assertIsInstanceOf(MethodNotFoundException.class, e.getCause().getCause()); assertEquals("ups", mnfe.getMethodName()); assertSame(bean, mnfe.getBean()); } @@ -115,8 +120,6 @@ public class BeanWithMethodHeaderTest ex from("direct:mixed").beanRef("myBean", "echo").beanRef("myBean", "hi").to("mock:result"); from("direct:fail").beanRef("myBean").to("mock:result"); - - from("direct:typo").beanRef("myBean", "ups").to("mock:result"); } }; } Copied: camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MethodCallBeanRefMethodNotFoundTest.java (from r962430, camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MethodCallBeanRefNotFoundTest.java) URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MethodCallBeanRefMethodNotFoundTest.java?p2=camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MethodCallBeanRefMethodNotFoundTest.java&p1=camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MethodCallBeanRefNotFoundTest.java&r1=962430&r2=962451&rev=962451&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MethodCallBeanRefNotFoundTest.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MethodCallBeanRefMethodNotFoundTest.java Fri Jul 9 08:54:31 2010 @@ -18,14 +18,13 @@ package org.apache.camel.component.bean; import org.apache.camel.ContextTestSupport; import org.apache.camel.FailedToCreateRouteException; -import org.apache.camel.NoSuchBeanException; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.impl.JndiRegistry; /** * @version $Revision$ */ -public class MethodCallBeanRefNotFoundTest extends ContextTestSupport { +public class MethodCallBeanRefMethodNotFoundTest extends ContextTestSupport { @Override protected JndiRegistry createRegistry() throws Exception { @@ -34,13 +33,13 @@ public class MethodCallBeanRefNotFoundTe return jndi; } - public void testMethodCallBeanRefNotFound() throws Exception { + public void testMethodCallBeanRefMethodNotFound() throws Exception { context.addRoutes(new RouteBuilder() { @Override public void configure() throws Exception { - from("direct:b").routeId("b").split().method("foo", "myMethod").to("mock:b"); + from("direct:b").routeId("b").split().method("foo", "hello").to("mock:b"); - from("direct:b").routeId("b").split().method("bar", "myMethod").to("mock:b"); + from("direct:b").routeId("b").split().method("foo", "bye").to("mock:b"); } }); try { @@ -48,8 +47,8 @@ public class MethodCallBeanRefNotFoundTe fail("Should have thrown exception"); } catch (FailedToCreateRouteException e) { assertEquals("b", e.getRouteId()); - NoSuchBeanException cause = assertIsInstanceOf(NoSuchBeanException.class, e.getCause()); - assertEquals("bar", cause.getName()); + MethodNotFoundException cause = assertIsInstanceOf(MethodNotFoundException.class, e.getCause().getCause()); + assertEquals("bye", cause.getMethodName()); } } Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MethodCallBeanRefNotFoundTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MethodCallBeanRefNotFoundTest.java?rev=962451&r1=962450&r2=962451&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MethodCallBeanRefNotFoundTest.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/component/bean/MethodCallBeanRefNotFoundTest.java Fri Jul 9 08:54:31 2010 @@ -38,9 +38,9 @@ public class MethodCallBeanRefNotFoundTe context.addRoutes(new RouteBuilder() { @Override public void configure() throws Exception { - from("direct:b").routeId("b").split().method("foo", "myMethod").to("mock:b"); + from("direct:b").routeId("b").split().method("foo", "hello").to("mock:b"); - from("direct:b").routeId("b").split().method("bar", "myMethod").to("mock:b"); + from("direct:b").routeId("b").split().method("bar", "hello").to("mock:b"); } }); try { Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/view/DotViewTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/view/DotViewTest.java?rev=962451&r1=962450&r2=962451&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/view/DotViewTest.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/view/DotViewTest.java Fri Jul 9 08:54:31 2010 @@ -86,7 +86,7 @@ public class DotViewTest extends Context static class FromToBeanRoute extends RouteBuilder { public void configure() throws Exception { - from("seda:foo").beanRef("myBean", "myMethod"); + from("seda:foo").beanRef("myBean", "hello"); } }