Repository: camel
Updated Branches:
  refs/heads/camel-2.12.x ac3a3281f -> 2460888dc


CAMEL-7560: Fixed advice with when using transacted in the XML routes.


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/70f15415
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/70f15415
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/70f15415

Branch: refs/heads/camel-2.12.x
Commit: 70f15415c732900f15dd2676e24131b69abf9627
Parents: ac3a328
Author: Claus Ibsen <davscl...@apache.org>
Authored: Mon Jun 30 21:12:56 2014 +0200
Committer: Claus Ibsen <davscl...@apache.org>
Committed: Wed Jul 2 09:35:42 2014 +0200

----------------------------------------------------------------------
 .../apache/camel/builder/AdviceWithTasks.java   | 65 ++++++++++------
 .../camel/model/ProcessorDefinitionHelper.java  | 10 +++
 .../camel/issues/AdviceWithPolicyTest.java      | 78 ++++++++++++++++++++
 .../issues/AdviceWithTransactionIssueTest.java  | 76 +++++++++++++++++++
 .../issues/AdviceWithTransactionIssueTest.xml   | 35 +++++++++
 .../jms/AdviceWithTransactionIssueTest.java     | 76 +++++++++++++++++++
 .../jms/AdviceWithTransactionIssueTest.xml      | 58 +++++++++++++++
 7 files changed, 377 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/70f15415/camel-core/src/main/java/org/apache/camel/builder/AdviceWithTasks.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/builder/AdviceWithTasks.java 
b/camel-core/src/main/java/org/apache/camel/builder/AdviceWithTasks.java
index b827f8f..69f5a0a 100644
--- a/camel-core/src/main/java/org/apache/camel/builder/AdviceWithTasks.java
+++ b/camel-core/src/main/java/org/apache/camel/builder/AdviceWithTasks.java
@@ -143,13 +143,13 @@ public final class AdviceWithTasks {
                 while (it.hasNext()) {
                     ProcessorDefinition<?> output = it.next();
                     if (matchBy.match(output)) {
-                        ProcessorDefinition<?> parent = output.getParent();
-                        if (parent != null) {
-                            int index = parent.getOutputs().indexOf(output);
+                        List<ProcessorDefinition> outputs = 
getParentOutputs(output.getParent());
+                        if (outputs != null) {
+                            int index = outputs.indexOf(output);
                             if (index != -1) {
                                 match = true;
-                                parent.getOutputs().add(index + 1, replace);
-                                Object old = parent.getOutputs().remove(index);
+                                outputs.add(index + 1, replace);
+                                Object old = outputs.remove(index);
                                 LOG.info("AdviceWith (" + matchBy.getId() + ") 
: [" + old + "] --> replace [" + replace + "]");
                             }
                         }
@@ -192,12 +192,12 @@ public final class AdviceWithTasks {
                 while (it.hasNext()) {
                     ProcessorDefinition<?> output = it.next();
                     if (matchBy.match(output)) {
-                        ProcessorDefinition<?> parent = output.getParent();
-                        if (parent != null) {
-                            int index = parent.getOutputs().indexOf(output);
+                        List<ProcessorDefinition> outputs = 
getParentOutputs(output.getParent());
+                        if (outputs != null) {
+                            int index = outputs.indexOf(output);
                             if (index != -1) {
                                 match = true;
-                                Object old = parent.getOutputs().remove(index);
+                                Object old = outputs.remove(index);
                                 LOG.info("AdviceWith (" + matchBy.getId() + ") 
: [" + old + "] --> remove");
                             }
                         }
@@ -240,13 +240,13 @@ public final class AdviceWithTasks {
                 while (it.hasNext()) {
                     ProcessorDefinition<?> output = it.next();
                     if (matchBy.match(output)) {
-                        ProcessorDefinition<?> parent = output.getParent();
-                        if (parent != null) {
-                            int index = parent.getOutputs().indexOf(output);
+                        List<ProcessorDefinition> outputs = 
getParentOutputs(output.getParent());
+                        if (outputs != null) {
+                            int index = outputs.indexOf(output);
                             if (index != -1) {
                                 match = true;
-                                Object existing = 
parent.getOutputs().get(index);
-                                parent.getOutputs().add(index, before);
+                                Object existing = outputs.get(index);
+                                outputs.add(index, before);
                                 LOG.info("AdviceWith (" + matchBy.getId() + ") 
: [" + existing + "] --> before [" + before + "]");
                             }
                         }
@@ -289,14 +289,13 @@ public final class AdviceWithTasks {
                 while (it.hasNext()) {
                     ProcessorDefinition<?> output = it.next();
                     if (matchBy.match(output)) {
-
-                        ProcessorDefinition<?> parent = output.getParent();
-                        if (parent != null) {
-                            int index = parent.getOutputs().indexOf(output);
+                        List<ProcessorDefinition> outputs = 
getParentOutputs(output.getParent());
+                        if (outputs != null) {
+                            int index = outputs.indexOf(output);
                             if (index != -1) {
                                 match = true;
-                                Object existing = 
parent.getOutputs().get(index);
-                                parent.getOutputs().add(index + 1, after);
+                                Object existing = outputs.get(index);
+                                outputs.add(index + 1, after);
                                 LOG.info("AdviceWith (" + matchBy.getId() + ") 
: [" + existing + "] --> after [" + after + "]");
                             }
                         }
@@ -310,6 +309,30 @@ public final class AdviceWithTasks {
         };
     }
 
+    /**
+     * Gets the outputs from the given parent.
+     * <p/>
+     * This implementation deals with that outputs can be abstract and 
retrieves the correct non-nested output.
+     *
+     * @param parent the parent
+     * @return <tt>null</tt> if no parent
+     */
+    @SuppressWarnings("unchecked")
+    private static List<ProcessorDefinition> 
getParentOutputs(ProcessorDefinition parent) {
+        if (parent == null) {
+            return null;
+        }
+        List<ProcessorDefinition> outputs = parent.getOutputs();
+        if (outputs.size() >= 1) {
+            // if the 1st output is abstract, then its 
onException,transacted,intercept etc so we should
+            // get the 'actual' outputs from that
+            if (outputs.get(0).isAbstract()) {
+                outputs = outputs.get(0).getOutputs();
+            }
+        }
+        return outputs;
+    }
+
     public static AdviceWithTask replaceFromWith(final RouteDefinition route, 
final String uri) {
         return new AdviceWithTask() {
             public void task() throws Exception {
@@ -367,7 +390,7 @@ public final class AdviceWithTasks {
     }
 
     private static Iterator<ProcessorDefinition<?>> 
createSelectorIterator(final List<ProcessorDefinition<?>> list, final boolean 
selectFirst,
-                                                                        final 
boolean selectLast, final int selectFrom, final int selectTo) {
+                                                                           
final boolean selectLast, final int selectFrom, final int selectTo) {
         return new Iterator<ProcessorDefinition<?>>() {
             private int current;
             private boolean done;

http://git-wip-us.apache.org/repos/asf/camel/blob/70f15415/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java
 
b/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java
index 6395ec6..5575d36 100644
--- 
a/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java
+++ 
b/camel-core/src/main/java/org/apache/camel/model/ProcessorDefinitionHelper.java
@@ -243,6 +243,16 @@ public final class ProcessorDefinitionHelper {
                 continue;
             }
 
+            // special for some types which has special outputs
+            if (out instanceof OutputDefinition) {
+                OutputDefinition outDef = (OutputDefinition) out;
+                List<ProcessorDefinition<?>> outDefOut = outDef.getOutputs();
+                doFindType(outDefOut, type, found);
+
+                // do not check children as we already did that
+                continue;
+            }
+
             // try children as well
             List<ProcessorDefinition<?>> children = out.getOutputs();
             doFindType(children, type, found);

http://git-wip-us.apache.org/repos/asf/camel/blob/70f15415/camel-core/src/test/java/org/apache/camel/issues/AdviceWithPolicyTest.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/test/java/org/apache/camel/issues/AdviceWithPolicyTest.java 
b/camel-core/src/test/java/org/apache/camel/issues/AdviceWithPolicyTest.java
new file mode 100644
index 0000000..c4a3416
--- /dev/null
+++ b/camel-core/src/test/java/org/apache/camel/issues/AdviceWithPolicyTest.java
@@ -0,0 +1,78 @@
+/**
+ * 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.issues;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.AdviceWithRouteBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.ProcessorDefinition;
+import org.apache.camel.model.RouteDefinition;
+import org.apache.camel.spi.Policy;
+import org.apache.camel.spi.RouteContext;
+
+/**
+ * @version 
+ */
+public class AdviceWithPolicyTest extends ContextTestSupport {
+
+    public void testAdviceWithPolicy() throws Exception {
+        RouteDefinition route = context.getRouteDefinitions().get(0);
+        route.adviceWith(context, new AdviceWithRouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                weaveById("b").after().to("mock:result");
+            }
+        });
+        context.start();
+
+        getMockEndpoint("mock:a").expectedMessageCount(1);
+        getMockEndpoint("mock:b").expectedMessageCount(1);
+        getMockEndpoint("mock:result").expectedMessageCount(1);
+
+        template.sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start")
+                    .policy(new MyPolicy())
+                    .to("mock:a").id("a")
+                    .to("mock:b").id("b");
+            }
+        };
+    }
+
+    private static final class MyPolicy implements Policy {
+
+        @Override
+        public void beforeWrap(RouteContext routeContext, 
ProcessorDefinition<?> definition) {
+            // noop
+        }
+
+        @Override
+        public Processor wrap(RouteContext routeContext, Processor processor) {
+            return processor;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/70f15415/components/camel-spring/src/test/java/org/apache/camel/spring/issues/AdviceWithTransactionIssueTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-spring/src/test/java/org/apache/camel/spring/issues/AdviceWithTransactionIssueTest.java
 
b/components/camel-spring/src/test/java/org/apache/camel/spring/issues/AdviceWithTransactionIssueTest.java
new file mode 100644
index 0000000..89d6067
--- /dev/null
+++ 
b/components/camel-spring/src/test/java/org/apache/camel/spring/issues/AdviceWithTransactionIssueTest.java
@@ -0,0 +1,76 @@
+/**
+ * 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.spring.issues;
+
+import org.apache.camel.builder.AdviceWithRouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.SpringTestSupport;
+import org.junit.Test;
+import org.springframework.context.support.AbstractXmlApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public class AdviceWithTransactionIssueTest extends SpringTestSupport {
+
+    @Override
+    public boolean isUseRouteBuilder() {
+        return false;
+    }
+
+    @Override
+    protected AbstractXmlApplicationContext createApplicationContext() {
+        return new 
ClassPathXmlApplicationContext("org/apache/camel/spring/issues/AdviceWithTransactionIssueTest.xml");
+    }
+
+    @Test
+    public void testAdviceWithWeaveById() throws Exception {
+        context.getRouteDefinitions().get(0).adviceWith(context, new 
AdviceWithRouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                weaveById("mock-b*").after().to("mock:last");
+            }
+        });
+        context.start();
+
+        MockEndpoint mockLast = getMockEndpoint("mock:last");
+        mockLast.expectedBodiesReceived("bar");
+        mockLast.setExpectedMessageCount(1);
+
+        template.sendBody("seda:start", "bar");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void testAdviceWithAddLast() throws Exception {
+        context.getRouteDefinitions().get(0).adviceWith(context, new 
AdviceWithRouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                weaveAddLast().to("mock:last");
+            }
+        });
+        context.start();
+
+        MockEndpoint mockLast = getMockEndpoint("mock:last");
+        mockLast.expectedBodiesReceived("bar");
+        mockLast.setExpectedMessageCount(1);
+
+        template.sendBody("seda:start", "bar");
+
+        assertMockEndpointsSatisfied();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/70f15415/components/camel-spring/src/test/resources/org/apache/camel/spring/issues/AdviceWithTransactionIssueTest.xml
----------------------------------------------------------------------
diff --git 
a/components/camel-spring/src/test/resources/org/apache/camel/spring/issues/AdviceWithTransactionIssueTest.xml
 
b/components/camel-spring/src/test/resources/org/apache/camel/spring/issues/AdviceWithTransactionIssueTest.xml
new file mode 100644
index 0000000..1d4bcb2
--- /dev/null
+++ 
b/components/camel-spring/src/test/resources/org/apache/camel/spring/issues/AdviceWithTransactionIssueTest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans";
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+       xsi:schemaLocation="
+       http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd
+       http://camel.apache.org/schema/spring 
http://camel.apache.org/schema/spring/camel-spring.xsd
+    ">
+
+  <import resource="../interceptor/transactionalClientDataSource.xml"/>
+
+  <camelContext id="myCamelContext" 
xmlns="http://camel.apache.org/schema/spring";>
+    <route id="route1">
+      <from uri="seda:start"/>
+      <transacted/>
+      <to id="mock-a" uri="mock:a"/>
+      <to id="mock-b" uri="mock:b"/>
+    </route>
+  </camelContext>
+</beans>

http://git-wip-us.apache.org/repos/asf/camel/blob/70f15415/tests/camel-itest/src/test/java/org/apache/camel/itest/jms/AdviceWithTransactionIssueTest.java
----------------------------------------------------------------------
diff --git 
a/tests/camel-itest/src/test/java/org/apache/camel/itest/jms/AdviceWithTransactionIssueTest.java
 
b/tests/camel-itest/src/test/java/org/apache/camel/itest/jms/AdviceWithTransactionIssueTest.java
new file mode 100644
index 0000000..73163d9
--- /dev/null
+++ 
b/tests/camel-itest/src/test/java/org/apache/camel/itest/jms/AdviceWithTransactionIssueTest.java
@@ -0,0 +1,76 @@
+/**
+ * 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.itest.jms;
+
+import org.apache.camel.builder.AdviceWithRouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.spring.CamelSpringTestSupport;
+import org.apache.xbean.spring.context.ClassPathXmlApplicationContext;
+import org.junit.Test;
+import org.springframework.context.support.AbstractApplicationContext;
+
+public class AdviceWithTransactionIssueTest extends CamelSpringTestSupport {
+
+    @Override
+    protected AbstractApplicationContext createApplicationContext() {
+        return new 
ClassPathXmlApplicationContext("org/apache/camel/itest/jms/AdviceWithTransactionIssueTest.xml");
+    }
+
+    @Override
+    public boolean isUseAdviceWith() {
+        return true;
+    }
+
+    @Test
+    public void testAdviceWithWeaveById() throws Exception {
+        context.getRouteDefinitions().get(0).adviceWith(context, new 
AdviceWithRouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                weaveById("mock-b*").after().to("mock:last");
+            }
+        });
+        context.start();
+
+        MockEndpoint mockLast = getMockEndpoint("mock:last");
+        mockLast.expectedBodiesReceived("bar");
+        mockLast.setExpectedMessageCount(1);
+
+        template.sendBody("activemq:queue:start", "bar");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void testAdviceWithAddLast() throws Exception {
+        context.getRouteDefinitions().get(0).adviceWith(context, new 
AdviceWithRouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                weaveAddLast().to("mock:last");
+            }
+        });
+        context.start();
+
+        MockEndpoint mockLast = getMockEndpoint("mock:last");
+        mockLast.expectedBodiesReceived("bar");
+        mockLast.setExpectedMessageCount(1);
+
+        template.sendBody("activemq:queue:start", "bar");
+
+        assertMockEndpointsSatisfied();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/70f15415/tests/camel-itest/src/test/resources/org/apache/camel/itest/jms/AdviceWithTransactionIssueTest.xml
----------------------------------------------------------------------
diff --git 
a/tests/camel-itest/src/test/resources/org/apache/camel/itest/jms/AdviceWithTransactionIssueTest.xml
 
b/tests/camel-itest/src/test/resources/org/apache/camel/itest/jms/AdviceWithTransactionIssueTest.xml
new file mode 100644
index 0000000..8f145ff
--- /dev/null
+++ 
b/tests/camel-itest/src/test/resources/org/apache/camel/itest/jms/AdviceWithTransactionIssueTest.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans";
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+       xsi:schemaLocation="
+        http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd
+        http://camel.apache.org/schema/spring 
http://camel.apache.org/schema/spring/camel-spring.xsd";>
+
+  <bean id="poolConnectionFactory" 
class="org.apache.activemq.pool.PooledConnectionFactory">
+    <property name="maxConnections" value="8"/>
+    <property name="connectionFactory" ref="jmsConnectionFactory"/>
+  </bean>
+
+  <bean id="jmsConnectionFactory" 
class="org.apache.activemq.ActiveMQConnectionFactory">
+    <property name="brokerURL" 
value="vm://localhost?broker.persistent=false&amp;broker.useJmx=false"/>
+  </bean>
+
+  <bean id="jmsTransactionManager" 
class="org.springframework.jms.connection.JmsTransactionManager">
+    <property name="connectionFactory" ref="poolConnectionFactory"/>
+  </bean>
+
+  <bean id="activemq" 
class="org.apache.activemq.camel.component.ActiveMQComponent">
+    <property name="connectionFactory" ref="poolConnectionFactory"/>
+    <property name="transacted" value="true"/>
+    <property name="transactionManager" ref="jmsTransactionManager"/>
+    <!-- we do not want any exceptions to be logged -->
+    <property name="errorHandlerLoggingLevel" value="OFF"/>
+    <property name="errorHandlerLogStackTrace" value="false"/>
+  </bean>
+
+  <camelContext xmlns="http://camel.apache.org/schema/spring";>
+
+      <route id="route1">
+        <from uri="activemq:queue:start"/>
+        <transacted/>
+        <to id="mock-a" uri="mock:a"/>
+        <to id="mock-b" uri="mock:b"/>
+      </route>
+
+  </camelContext>
+
+
+</beans>

Reply via email to