You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by lb...@apache.org on 2017/11/10 05:51:57 UTC

[camel] branch camel-2.20.x updated: CAMEL-12001: Cannot create a component based on the SqlComponent

This is an automated email from the ASF dual-hosted git repository.

lburgazzoli pushed a commit to branch camel-2.20.x
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/camel-2.20.x by this push:
     new 0a5e891  CAMEL-12001: Cannot create a component based on the SqlComponent
0a5e891 is described below

commit 0a5e8910de2c585ca34a8b8444723da50b5e5ec6
Author: lburgazzoli <lb...@gmail.com>
AuthorDate: Thu Nov 9 19:24:34 2017 +0100

    CAMEL-12001: Cannot create a component based on the SqlComponent
---
 .../org/apache/camel/impl/DefaultCamelContext.java | 35 +++++++++++-----
 .../camel/impl/CamelContextDeadlockText.java       | 48 ++++++++++++++++++++++
 connectors/camel-connector/pom.xml                 | 29 +++++++++++++
 .../connector/DefaultConnectorComponent.java       | 19 ++++-----
 .../src/main/resources/camel-connector.json        |  4 ++
 .../src/main/resources/camel-connector.json        |  4 ++
 .../src/main/resources/camel-connector.json        |  4 ++
 .../src/main/resources/camel-connector.json        |  4 ++
 .../find/springboot/TwitterFindConnectorTest.java  |  2 +-
 .../src/main/resources/camel-connector.json        |  4 ++
 10 files changed, 130 insertions(+), 23 deletions(-)

diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
index b2bf974..7ac8b82 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
@@ -470,10 +470,30 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
         }
 
         try {
+            // Flag used to mark a component of being created.
+            final AtomicBoolean created = new AtomicBoolean(false);
+
             // atomic operation to get/create a component. Avoid global locks.
-            return components.computeIfAbsent(name, comp -> initComponent(name, autoCreateComponents, autoStart));
+            final Component component = components.computeIfAbsent(name, comp -> {
+                created.set(true);
+                return initComponent(name, autoCreateComponents);
+            });
+
+            // Start the component after its creation as if it is a component proxy
+            // that creates/start a delegated component, we may end up in a deadlock
+            if (component != null && created.get() && autoStart && (isStarted() || isStarting())) {
+                // If the component is looked up after the context is started,
+                // lets start it up.
+                if (component instanceof Service) {
+                    startService((Service)component);
+                }
+            }
+
+            return  component;
+        } catch (Exception e) {
+            throw new RuntimeCamelException("Cannot auto create component: " + name, e);
         } finally {
-            // cremove the reference to the component being created
+            // remove the reference to the component being created
             componentsInCreation.get().remove(name);
         }
     }
@@ -481,7 +501,7 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
     /**
      * Function to initialize a component and auto start. Returns null if the autoCreateComponents is disabled
      */
-    private Component initComponent(String name, boolean autoCreateComponents, boolean autoStart) {
+    private Component initComponent(String name, boolean autoCreateComponents) {
         Component component = null;
         if (autoCreateComponents) {
             try {
@@ -524,13 +544,6 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
                 if (component != null) {
                     component.setCamelContext(this);
                     postInitComponent(name, component);
-                    if (autoStart && (isStarted() || isStarting())) {
-                        // If the component is looked up after the context is started,
-                        // lets start it up.
-                        if (component instanceof Service) {
-                            startService((Service)component);
-                        }
-                    }
                 }
             } catch (Exception e) {
                 throw new RuntimeCamelException("Cannot auto create component: " + name, e);
@@ -3391,7 +3404,7 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
         validatorRegistry = new DefaultValidatorRegistry(this, validators);
         addService(validatorRegistry, true, true);
 
-        // optimised to not include runtimeEndpointRegistry unless its enabled or JMX statistics is in extended mode
+        // optimised to not include runtimeEndpointRegistry unlesstartServices its enabled or JMX statistics is in extended mode
         if (runtimeEndpointRegistry == null && getManagementStrategy() != null && getManagementStrategy().getManagementAgent() != null) {
             Boolean isEnabled = getManagementStrategy().getManagementAgent().getEndpointRuntimeStatisticsEnabled();
             boolean isExtended = getManagementStrategy().getManagementAgent().getStatisticsLevel().isExtended();
diff --git a/camel-core/src/test/java/org/apache/camel/impl/CamelContextDeadlockText.java b/camel-core/src/test/java/org/apache/camel/impl/CamelContextDeadlockText.java
new file mode 100644
index 0000000..7642d00
--- /dev/null
+++ b/camel-core/src/test/java/org/apache/camel/impl/CamelContextDeadlockText.java
@@ -0,0 +1,48 @@
+/**
+ * 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.impl;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Component;
+import org.apache.camel.component.direct.DirectComponent;
+import org.junit.Test;
+
+public class CamelContextDeadlockText {
+
+    @Test(timeout = 5000)
+    public void testComponentDeadlock() throws Exception {
+        SimpleRegistry registry = new SimpleRegistry();
+        registry.put("sql-connector", new DirectComponent() {
+                @Override
+                protected void doStart() throws Exception {
+                    Component delegate = new DirectComponent();
+
+                    getCamelContext().removeComponent("sql-connector-component");
+                    getCamelContext().addService(delegate, true, true);
+                    getCamelContext().addComponent("sql-connector-component", delegate);
+
+                    super.doStart();
+                }
+            }
+        );
+
+        CamelContext context = new DefaultCamelContext(registry);
+        context.start();
+        context.getComponent("sql-connector", true, true);
+        context.stop();
+    }
+}
diff --git a/connectors/camel-connector/pom.xml b/connectors/camel-connector/pom.xml
index 5ffca92..ad5003d 100644
--- a/connectors/camel-connector/pom.xml
+++ b/connectors/camel-connector/pom.xml
@@ -59,6 +59,35 @@
       <version>${spring-boot-version}</version>
     </dependency>
 
+    <!-- logging -->
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-api</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-slf4j-impl</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <!-- testing -->
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-test</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-sql</artifactId>
+      <scope>test</scope>
+    </dependency>
+
   </dependencies>
 
 </project>
diff --git a/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/DefaultConnectorComponent.java b/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/DefaultConnectorComponent.java
index 3ba61ab..5c36e92 100644
--- a/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/DefaultConnectorComponent.java
+++ b/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/DefaultConnectorComponent.java
@@ -56,7 +56,6 @@ public abstract class DefaultConnectorComponent extends DefaultComponent impleme
     private final CamelCatalog catalog = new DefaultCamelCatalog(false);
 
     private final String baseScheme;
-    private final String componentAlias;
     private final String componentScheme;
     private final String componentName;
     private final ConnectorModel model;
@@ -82,8 +81,7 @@ public abstract class DefaultConnectorComponent extends DefaultComponent impleme
         this.model = new ConnectorModel(componentName, componentClass);
         this.baseScheme = this.model.getBaseScheme();
         this.componentName = componentName;
-        this.componentScheme = componentScheme != null ? componentScheme : componentName + "-component";
-        this.componentAlias = componentScheme != null ? baseScheme + "-" + componentScheme : componentName + "-component";
+        this.componentScheme = componentScheme != null ? baseScheme + "-" + componentScheme : baseScheme + "-" + componentName + "-component";
         this.options = new HashMap<>();
 
         // add to catalog
@@ -96,8 +94,8 @@ public abstract class DefaultConnectorComponent extends DefaultComponent impleme
 
         // Add an alias for the base component so there's no clash between connectors
         // if they set options targeting the component.
-        if (!catalog.findComponentNames().contains(componentAlias)) {
-            this.catalog.addComponent(componentAlias, this.model.getBaseJavaType(), catalog.componentJSonSchema(baseScheme));
+        if (!catalog.findComponentNames().contains(this.componentScheme)) {
+            this.catalog.addComponent(this.componentScheme, this.model.getBaseJavaType(), catalog.componentJSonSchema(baseScheme));
         }
 
         registerExtension(this::getComponentVerifierExtension);
@@ -135,7 +133,7 @@ public abstract class DefaultConnectorComponent extends DefaultComponent impleme
         Map<String, String> options = buildEndpointOptions(remaining, parameters);
 
         // create the uri of the base component
-        String delegateUri = createEndpointUri(componentAlias, options);
+        String delegateUri = createEndpointUri(componentScheme, options);
         Endpoint delegate = getCamelContext().getEndpoint(delegateUri);
 
         if (log.isInfoEnabled()) {
@@ -288,19 +286,18 @@ public abstract class DefaultConnectorComponent extends DefaultComponent impleme
 
         Component component = createNewBaseComponent();
         if (component != null) {
-            log.info("Register component: {} (type: {}) with scheme: {} and alias: {}",
+            log.info("Register component: {} (type: {}) with scheme: {}",
                 this.componentName,
                 component.getClass().getName(),
-                this.componentScheme,
-                this.componentAlias
+                this.componentScheme
             );
 
             //String delegateComponentScheme =
-            getCamelContext().removeComponent(this.componentAlias);
+            getCamelContext().removeComponent(this.componentScheme);
 
             // ensure component is started and stopped when Camel shutdown
             getCamelContext().addService(component, true, true);
-            getCamelContext().addComponent(this.componentAlias, component);
+            getCamelContext().addComponent(this.componentScheme, component);
         }
 
         log.debug("Starting connector: {}", componentName);
diff --git a/connectors/examples/foo-connector/src/main/resources/camel-connector.json b/connectors/examples/foo-connector/src/main/resources/camel-connector.json
index e1fb402..1c809f5 100644
--- a/connectors/examples/foo-connector/src/main/resources/camel-connector.json
+++ b/connectors/examples/foo-connector/src/main/resources/camel-connector.json
@@ -2,7 +2,11 @@
   "baseScheme" : "timer",
   "baseGroupId" : "org.apache.camel",
   "baseArtifactId" : "camel-core",
+<<<<<<< HEAD
   "baseVersion" : "2.20.1-20171103.154156-30",
+=======
+  "baseVersion" : "2.21.0-SNAPSHOT",
+>>>>>>> 176975e3de... CAMEL-12001: Cannot create a component based on the SqlComponent
   "baseJavaType" : "org.apache.camel.component.timer.TimerComponent",
   "name" : "Foo",
   "scheme" : "foo",
diff --git a/connectors/examples/petstore-connector/src/main/resources/camel-connector.json b/connectors/examples/petstore-connector/src/main/resources/camel-connector.json
index f00aa7b..346f261 100644
--- a/connectors/examples/petstore-connector/src/main/resources/camel-connector.json
+++ b/connectors/examples/petstore-connector/src/main/resources/camel-connector.json
@@ -2,7 +2,11 @@
   "baseScheme" : "rest-swagger",
   "baseGroupId" : "org.apache.camel",
   "baseArtifactId" : "camel-rest-swagger",
+<<<<<<< HEAD
   "baseVersion" : "2.20.1-20171103.161431-29",
+=======
+  "baseVersion" : "2.21.0-20171109.020941-31",
+>>>>>>> 176975e3de... CAMEL-12001: Cannot create a component based on the SqlComponent
   "baseJavaType" : "org.apache.camel.component.rest.swagger.RestSwaggerComponent",
   "name" : "PetStore",
   "scheme" : "petstore",
diff --git a/connectors/examples/salesforce-upsert-contact-connector/src/main/resources/camel-connector.json b/connectors/examples/salesforce-upsert-contact-connector/src/main/resources/camel-connector.json
index 321516a..b4044a5 100644
--- a/connectors/examples/salesforce-upsert-contact-connector/src/main/resources/camel-connector.json
+++ b/connectors/examples/salesforce-upsert-contact-connector/src/main/resources/camel-connector.json
@@ -2,7 +2,11 @@
   "baseScheme" : "salesforce",
   "baseGroupId" : "org.apache.camel",
   "baseArtifactId" : "camel-salesforce",
+<<<<<<< HEAD
   "baseVersion" : "2.20.1-20171103.161619-29",
+=======
+  "baseVersion" : "2.21.0-20171109.021225-31",
+>>>>>>> 176975e3de... CAMEL-12001: Cannot create a component based on the SqlComponent
   "baseJavaType" : "org.apache.camel.component.salesforce.SalesforceComponent",
   "name" : "SalesforceUpsertContact",
   "scheme" : "salesforce-upsert-contact",
diff --git a/connectors/examples/twitter-find-connector/src/main/resources/camel-connector.json b/connectors/examples/twitter-find-connector/src/main/resources/camel-connector.json
index deded1b..e858d44 100644
--- a/connectors/examples/twitter-find-connector/src/main/resources/camel-connector.json
+++ b/connectors/examples/twitter-find-connector/src/main/resources/camel-connector.json
@@ -2,7 +2,11 @@
   "baseScheme" : "twitter-search",
   "baseGroupId" : "org.apache.camel",
   "baseArtifactId" : "camel-twitter",
+<<<<<<< HEAD
   "baseVersion" : "2.20.1-20171103.162737-28",
+=======
+  "baseVersion" : "2.21.0-20171109.022511-29",
+>>>>>>> 176975e3de... CAMEL-12001: Cannot create a component based on the SqlComponent
   "baseJavaType" : "org.apache.camel.component.twitter.search.TwitterSearchComponent",
   "name" : "TwitterFind",
   "scheme" : "twitter-find",
diff --git a/connectors/examples/twitter-find-connector/src/test/java/org/foo/find/springboot/TwitterFindConnectorTest.java b/connectors/examples/twitter-find-connector/src/test/java/org/foo/find/springboot/TwitterFindConnectorTest.java
index a56b010..9106220 100644
--- a/connectors/examples/twitter-find-connector/src/test/java/org/foo/find/springboot/TwitterFindConnectorTest.java
+++ b/connectors/examples/twitter-find-connector/src/test/java/org/foo/find/springboot/TwitterFindConnectorTest.java
@@ -58,7 +58,7 @@ public class TwitterFindConnectorTest {
         Assert.assertFalse(endpoints.isEmpty());
 
         endpoints.forEach(endpoint -> {
-            if (endpoint.getEndpointUri().startsWith("twitter-find-component:")) {
+            if (endpoint.getEndpointUri().startsWith("twitter-search-twitter-find-component:")) {
                 Assert.assertEquals("cameltest", endpoint.getKeywords());
                 Assert.assertTrue(endpoint.isFilterOld());
             } else if (endpoint.getEndpointUri().startsWith("twitter-search-tw-find1:")) {
diff --git a/connectors/examples/twitter-mention-connector/src/main/resources/camel-connector.json b/connectors/examples/twitter-mention-connector/src/main/resources/camel-connector.json
index 918d695..f102ca2 100644
--- a/connectors/examples/twitter-mention-connector/src/main/resources/camel-connector.json
+++ b/connectors/examples/twitter-mention-connector/src/main/resources/camel-connector.json
@@ -2,7 +2,11 @@
   "baseScheme" : "twitter",
   "baseGroupId" : "org.apache.camel",
   "baseArtifactId" : "camel-twitter",
+<<<<<<< HEAD
   "baseVersion" : "2.20.1-20171103.162737-28",
+=======
+  "baseVersion" : "2.21.0-20171109.022511-29",
+>>>>>>> 176975e3de... CAMEL-12001: Cannot create a component based on the SqlComponent
   "baseJavaType" : "org.apache.camel.component.twitter.TwitterComponent",
   "name" : "TwitterMention",
   "scheme" : "twitter-mention",

-- 
To stop receiving notification emails like this one, please contact
['"commits@camel.apache.org" <co...@camel.apache.org>'].