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/05/15 15:18:36 UTC
[2/2] camel git commit: CAMEL-11196: Camel connectors - Allow to
configure in one place and let it figure out component vs endpoint level
CAMEL-11196: Camel connectors - Allow to configure in one place and let it figure out component vs endpoint level
Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/3dd29006
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/3dd29006
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/3dd29006
Branch: refs/heads/master
Commit: 3dd29006c3aa1c9612dc25461b64a4845e31138d
Parents: 000e09a
Author: lburgazzoli <lb...@gmail.com>
Authored: Wed May 10 18:20:48 2017 +0200
Committer: lburgazzoli <lb...@gmail.com>
Committed: Mon May 15 17:06:47 2017 +0200
----------------------------------------------------------------------
.../apache/camel/util/IntrospectionSupport.java | 5 +
connectors/camel-connector-maven-plugin/pom.xml | 7 +
.../SpringBootAutoConfigurationMojo.java | 236 ++++++++++++++-----
.../maven/connector/model/ComponentModel.java | 11 +-
.../connector/model/ComponentOptionModel.java | 128 +---------
.../connector/model/EndpointOptionModel.java | 215 +++++++++++++++++
.../maven/connector/model/OptionModel.java | 146 ++++++++++++
.../src/main/docs/connector-component.adoc | 56 ++++-
.../component/connector/ConnectorComponent.java | 39 ++-
.../component/connector/ConnectorModel.java | 76 ++++++
.../connector/DefaultConnectorComponent.java | 199 ++++++++++------
.../PetStoreConnectorAutoConfiguration.java | 41 +++-
.../PetStoreConnectorConfiguration.java | 33 +--
.../PetStoreConnectorConfigurationCommon.java | 61 +++++
connectors/examples/pom.xml | 2 +
...UpsertContactConnectorAutoConfiguration.java | 41 +++-
...orceUpsertContactConnectorConfiguration.java | 73 +-----
...sertContactConnectorConfigurationCommon.java | 113 +++++++++
.../examples/twitter-mention-connector/pom.xml | 2 +
...witterMentionConnectorAutoConfiguration.java | 41 +++-
.../TwitterMentionConnectorConfiguration.java | 62 +----
...tterMentionConnectorConfigurationCommon.java | 78 ++++++
.../examples/twitter-search-connector/pom.xml | 188 +++++++++++++++
.../org/foo/search/TwitterSearchComponent.java | 30 +++
...TwitterSearchConnectorAutoConfiguration.java | 93 ++++++++
.../TwitterSearchConnectorConfiguration.java | 38 +++
...itterSearchConnectorConfigurationCommon.java | 116 +++++++++
.../org/apache/camel/component/twitter-search | 18 ++
.../main/resources/META-INF/spring.factories | 19 ++
.../main/resources/camel-connector-schema.json | 30 +++
.../src/main/resources/camel-connector.json | 25 ++
.../springbot/TwitterSearchConnectorTest.java | 65 +++++
.../src/test/resources/application.properties | 7 +
.../src/test/resources/logback.xml | 36 +++
.../examples/twitter-search-example/README.md | 18 ++
.../examples/twitter-search-example/pom.xml | 112 +++++++++
.../java/org/foo/TwitterSearchApplication.java | 32 +++
.../main/java/org/foo/TwitterSearchRoute.java | 29 +++
.../src/main/resources/META-INF/LICENSE.txt | 203 ++++++++++++++++
.../src/main/resources/META-INF/NOTICE.txt | 11 +
.../src/main/resources/application.properties | 29 +++
41 files changed, 2345 insertions(+), 419 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java b/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java
index 185ef3b..21384cc 100755
--- a/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java
+++ b/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java
@@ -635,6 +635,11 @@ public final class IntrospectionSupport {
return false;
}
+ public static boolean setProperty(CamelContext context, Object target, String name, Object value) throws Exception {
+ // allow build pattern as a setter as well
+ return setProperty(context, context != null ? context.getTypeConverter() : null, target, name, value, null, true);
+ }
+
public static boolean setProperty(CamelContext context, TypeConverter typeConverter, Object target, String name, Object value) throws Exception {
// allow build pattern as a setter as well
return setProperty(context, typeConverter, target, name, value, null, true);
http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/connectors/camel-connector-maven-plugin/pom.xml
----------------------------------------------------------------------
diff --git a/connectors/camel-connector-maven-plugin/pom.xml b/connectors/camel-connector-maven-plugin/pom.xml
index 2e8bb3b..cbb2c84 100644
--- a/connectors/camel-connector-maven-plugin/pom.xml
+++ b/connectors/camel-connector-maven-plugin/pom.xml
@@ -85,6 +85,13 @@
<version>${spring-boot-version}</version>
</dependency>
+ <!-- guava for some word wrap helper -->
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>${google-guava-version}</version>
+ </dependency>
+
<!-- logging -->
<dependency>
<groupId>org.slf4j</groupId>
http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/SpringBootAutoConfigurationMojo.java
----------------------------------------------------------------------
diff --git a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/SpringBootAutoConfigurationMojo.java b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/SpringBootAutoConfigurationMojo.java
index 997878a..c8ca459 100644
--- a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/SpringBootAutoConfigurationMojo.java
+++ b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/SpringBootAutoConfigurationMojo.java
@@ -21,13 +21,18 @@ import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import javax.annotation.Generated;
+import javax.annotation.PostConstruct;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.camel.maven.connector.model.ComponentModel;
import org.apache.camel.maven.connector.model.ComponentOptionModel;
+import org.apache.camel.maven.connector.model.EndpointOptionModel;
+import org.apache.camel.maven.connector.model.OptionModel;
import org.apache.camel.maven.connector.util.JSonSchemaHelper;
import org.apache.commons.io.FileUtils;
import org.apache.maven.plugin.AbstractMojo;
@@ -44,10 +49,13 @@ import org.jboss.forge.roaster.model.source.MethodSource;
import org.jboss.forge.roaster.model.source.PropertySource;
import org.jboss.forge.roaster.model.util.Formatter;
import org.jboss.forge.roaster.model.util.Strings;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.DeprecatedConfigurationProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
@@ -89,7 +97,8 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo {
String javaType = null;
String connectorScheme = null;
- List<String> componentOptions = null;
+ List<String> componentOptions = Collections.emptyList();
+ List<String> endpointOptions = Collections.emptyList();
File file = new File(classesDirectory, "camel-connector.json");
if (file.exists()) {
@@ -99,6 +108,7 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo {
javaType = (String) dto.get("javaType");
connectorScheme = (String) dto.get("scheme");
componentOptions = (List) dto.get("componentOptions");
+ endpointOptions = (List) dto.get("endpointOptions");
}
// find the component dependency and get its .json file
@@ -119,7 +129,7 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo {
if (hasOptions) {
getLog().info("Generating Spring Boot AutoConfiguration for Connector: " + model.getScheme());
- createConnectorConfigurationSource(pkg, model, javaType, connectorScheme, componentOptions);
+ createConnectorConfigurationSource(pkg, model, javaType, connectorScheme, componentOptions, endpointOptions);
createConnectorAutoConfigurationSource(pkg, hasOptions, javaType, connectorScheme);
createConnectorSpringFactorySource(pkg, javaType);
}
@@ -165,23 +175,29 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo {
}
}
+
+
private void createConnectorConfigurationSource(String packageName, ComponentModel model, String javaType,
- String connectorScheme, List<String> componentOptions) throws MojoFailureException {
- final JavaClassSource javaClass = Roaster.create(JavaClassSource.class);
+ String connectorScheme, List<String> componentOptions, List<String> endpointOptions) throws MojoFailureException {
- int pos = javaType.lastIndexOf(".");
- String name = javaType.substring(pos + 1);
- name = name.replace("Component", "ConnectorConfiguration");
- javaClass.setPackage(packageName).setName(name);
+ final int pos = javaType.lastIndexOf(".");
+ final String commonName = javaType.substring(pos + 1).replace("Component", "ConnectorConfigurationCommon");
+ final String configName = javaType.substring(pos + 1).replace("Component", "ConnectorConfiguration");
- String doc = "Generated by camel-connector-maven-plugin - do not edit this file!";
+ // Common base class
+ JavaClassSource commonClass = Roaster.create(JavaClassSource.class);
+ commonClass.setPackage(packageName);
+ commonClass.setName(commonName);
+
+ String doc = "Generated by camel-package-maven-plugin - do not edit this file!";
if (!Strings.isBlank(model.getDescription())) {
doc = model.getDescription() + "\n\n" + doc;
}
// replace Component with Connector
doc = doc.replaceAll("Component", "Connector");
doc = doc.replaceAll("component", "connector");
- javaClass.getJavaDoc().setFullText(doc);
+ commonClass.getJavaDoc().setFullText(doc);
+ commonClass.addAnnotation(Generated.class).setStringValue("value", SpringBootAutoConfigurationMojo.class.getName());
// compute the configuration prefix to use with spring boot configuration
String prefix = "";
@@ -194,53 +210,53 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo {
}
prefix += connectorScheme.toLowerCase(Locale.US);
- javaClass.addAnnotation("org.springframework.boot.context.properties.ConfigurationProperties").setStringValue("prefix", prefix);
-
- for (ComponentOptionModel option : model.getComponentOptions()) {
+ for (OptionModel option : model.getComponentOptions()) {
+ boolean isComponentOption= componentOptions != null && componentOptions.stream().anyMatch(o -> o.equals(option.getName()));
+ boolean isEndpointOption = endpointOptions != null && endpointOptions.stream().anyMatch(o -> o.equals(option.getName()));
- // only include the options that has been explicit configured in the camel-connector.json file
- boolean accepted = false;
- if (componentOptions != null) {
- accepted = componentOptions.stream().anyMatch(o -> o.equals(option.getName()));
+ // only include the options that has been explicit configured in the
+ // componentOptions section of camel-connector.json file and exclude
+ // those configured on endpointOptions in the same file
+ if (isComponentOption && !isEndpointOption) {
+ addProperty(commonClass, model, option);
}
+ }
- if (accepted) {
- String type = option.getJavaType();
- PropertySource<JavaClassSource> prop = javaClass.addProperty(type, option.getName());
-
- if ("true".equals(option.getDeprecated())) {
- prop.getField().addAnnotation(Deprecated.class);
- prop.getAccessor().addAnnotation(Deprecated.class);
- prop.getMutator().addAnnotation(Deprecated.class);
- // DeprecatedConfigurationProperty must be on getter when deprecated
- prop.getAccessor().addAnnotation(DeprecatedConfigurationProperty.class);
- }
- if (!Strings.isBlank(option.getDescription())) {
- prop.getField().getJavaDoc().setFullText(option.getDescription());
- }
- if (!Strings.isBlank(option.getDefaultValue())) {
- if ("java.lang.String".equals(option.getJavaType())) {
- prop.getField().setStringInitializer(option.getDefaultValue());
- } else if ("long".equals(option.getJavaType()) || "java.lang.Long".equals(option.getJavaType())) {
- // the value should be a Long number
- String value = option.getDefaultValue() + "L";
- prop.getField().setLiteralInitializer(value);
- } else if ("integer".equals(option.getType()) || "boolean".equals(option.getType())) {
- prop.getField().setLiteralInitializer(option.getDefaultValue());
- } else if (!Strings.isBlank(option.getEnums())) {
- String enumShortName = type.substring(type.lastIndexOf(".") + 1);
- prop.getField().setLiteralInitializer(enumShortName + "." + option.getDefaultValue());
- javaClass.addImport(model.getJavaType());
- }
- }
+ for (OptionModel option : model.getEndpointOptions()) {
+ if (endpointOptions != null && endpointOptions.stream().anyMatch(o -> o.equals(option.getName()))) {
+ addProperty(commonClass, model, option);
}
}
+ sortImports(commonClass);
+ writeSourceIfChanged(commonClass, packageName.replaceAll("\\.", "\\/") + "/" + commonName + ".java");
- sortImports(javaClass);
+ // Config class
+ JavaClassSource configClass = Roaster.create(JavaClassSource.class);
+ configClass.setPackage(packageName);
+ configClass.setName(configName);
+ configClass.extendSuperType(commonClass);
+ configClass.addAnnotation(Generated.class).setStringValue("value", SpringBootAutoConfigurationMojo.class.getName());
+ configClass.addAnnotation(ConfigurationProperties.class).setStringValue("prefix", prefix);
+ configClass.addImport(Map.class);
+ configClass.addImport(HashMap.class);
+ configClass.removeImport(commonClass);
- String fileName = packageName.replaceAll("\\.", "\\/") + "/" + name + ".java";
- writeSourceIfChanged(javaClass, fileName);
+ configClass.addField("Map<String, " + commonName + "> configurations = new HashMap<>()")
+ .setPrivate()
+ .getJavaDoc().setFullText("Define additional configuration definitions");
+
+ MethodSource<JavaClassSource> method;
+
+ method = configClass.addMethod();
+ method.setName("getConfigurations");
+ method.setReturnType("Map<String, " + commonName + ">");
+ method.setPublic();
+ method.setBody("return configurations;");
+
+
+ sortImports(configClass);
+ writeSourceIfChanged(configClass, packageName.replaceAll("\\.", "\\/") + "/" + configName + ".java");
}
private void createConnectorAutoConfigurationSource(String packageName, boolean hasOptions,
@@ -251,12 +267,15 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo {
int pos = javaType.lastIndexOf(".");
String name = javaType.substring(pos + 1);
name = name.replace("Component", "ConnectorAutoConfiguration");
+ final String configNameCommon = javaType.substring(pos + 1).replace("Component", "ConnectorConfigurationCommon");
+ final String configName = javaType.substring(pos + 1).replace("Component", "ConnectorConfiguration");
javaClass.setPackage(packageName).setName(name);
String doc = "Generated by camel-connector-maven-plugin - do not edit this file!";
javaClass.getJavaDoc().setFullText(doc);
+ javaClass.addAnnotation(Generated.class).setStringValue("value", SpringBootAutoConfigurationMojo.class.getName());
javaClass.addAnnotation(Configuration.class);
javaClass.addAnnotation(ConditionalOnBean.class).setStringValue("type", "org.apache.camel.spring.boot.CamelAutoConfiguration");
javaClass.addAnnotation(AutoConfigureAfter.class).setStringValue("name", "org.apache.camel.spring.boot.CamelAutoConfiguration");
@@ -272,32 +291,44 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo {
}
javaClass.addImport(javaType);
+ javaClass.addImport(BeanCreationException.class);
javaClass.addImport("org.apache.camel.CamelContext");
+ javaClass.addField()
+ .setName("camelContext")
+ .setType("org.apache.camel.CamelContext")
+ .setPrivate()
+ .addAnnotation(Autowired.class);
+ javaClass.addField()
+ .setName("configuration")
+ .setType(configName)
+ .setPrivate()
+ .addAnnotation(Autowired.class);
+
// add method for auto configure
String shortJavaType = getShortJavaType(javaType);
- String body = createComponentBody(shortJavaType, hasOptions);
- String methodName = "configure" + shortJavaType;
+ // must be named -component because camel-spring-boot uses that to lookup components
+ String beanName = connectorScheme + "-component";
- MethodSource<JavaClassSource> method = javaClass.addMethod()
- .setName(methodName)
+ MethodSource<JavaClassSource> configureMethod = javaClass.addMethod()
+ .setName("configure" + shortJavaType)
.setPublic()
- .setBody(body)
+ .setBody(createComponentBody(shortJavaType, hasOptions))
.setReturnType(shortJavaType)
.addThrows(Exception.class);
- method.addParameter("CamelContext", "camelContext");
+ configureMethod.addAnnotation(Lazy.class);
+ configureMethod.addAnnotation(Bean.class).setStringValue("name", beanName);
+ configureMethod.addAnnotation(ConditionalOnClass.class).setLiteralValue("value", "CamelContext.class");
+ configureMethod.addAnnotation(ConditionalOnMissingBean.class).setStringValue("name", beanName);
- if (hasOptions) {
- method.addParameter(configurationName, "configuration");
- }
+ MethodSource<JavaClassSource> postProcessMethod = javaClass.addMethod()
+ .setName("postConstruct" + shortJavaType)
+ .setPublic()
+ .setBody(createPostConstructBody(shortJavaType, configNameCommon));
- // must be named -component because camel-spring-boot uses that to lookup components
- String beanName = connectorScheme + "-component";
- method.addAnnotation(Lazy.class);
- method.addAnnotation(Bean.class).setStringValue("name", beanName);
- method.addAnnotation(ConditionalOnClass.class).setLiteralValue("value", "CamelContext.class");
- method.addAnnotation(ConditionalOnMissingBean.class).setLiteralValue("value", javaType + ".class");
+
+ postProcessMethod.addAnnotation(PostConstruct.class);
sortImports(javaClass);
@@ -353,6 +384,31 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo {
return sb.toString();
}
+ private static String createPostConstructBody(String shortJavaType, String commonConfigurationName) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("if (camelContext != null) {\n");
+ sb.append("Map<String, Object> parameters = new HashMap<>();\n");
+ sb.append("\n");
+ sb.append("for (Map.Entry<String, " + commonConfigurationName + "> entry : configuration.getConfigurations().entrySet()) {\n");
+ sb.append("parameters.clear();\n");
+ sb.append("\n");
+ sb.append(shortJavaType).append(" connector = new ").append(shortJavaType).append("();\n");
+ sb.append("connector.setCamelContext(camelContext);\n");
+ sb.append("\n");
+ sb.append("try {\n");
+ sb.append("IntrospectionSupport.getProperties(entry.getValue(), parameters, null, false);\n");
+ sb.append("IntrospectionSupport.setProperties(camelContext, camelContext.getTypeConverter(), connector, parameters);\n");
+ sb.append("connector.setComponentOptions(parameters);\n");
+ sb.append("\n");
+ sb.append("camelContext.addComponent(entry.getKey(), connector);\n");
+ sb.append("} catch (Exception e) {\n");
+ sb.append("throw new BeanCreationException(entry.getKey(), e.getMessage(), e);\n");
+ sb.append("}\n");
+ sb.append("}\n");
+ sb.append("}\n");
+ return sb.toString();
+ }
+
private static void sortImports(JavaClassSource javaClass) {
// sort imports
List<Import> imports = javaClass.getImports();
@@ -439,7 +495,59 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo {
component.addComponentOption(option);
}
+ rows = JSonSchemaHelper.parseJsonSchema("properties", json, true);
+ for (Map<String, String> row : rows) {
+ EndpointOptionModel option = new EndpointOptionModel();
+ option.setName(getSafeValue("name", row));
+ option.setDisplayName(getSafeValue("displayName", row));
+ option.setKind(getSafeValue("kind", row));
+ option.setGroup(getSafeValue("group", row));
+ option.setRequired(getSafeValue("required", row));
+ option.setType(getSafeValue("type", row));
+ option.setJavaType(getSafeValue("javaType", row));
+ option.setEnums(getSafeValue("enum", row));
+ option.setPrefix(getSafeValue("prefix", row));
+ option.setMultiValue(getSafeValue("multiValue", row));
+ option.setDeprecated(getSafeValue("deprecated", row));
+ option.setDefaultValue(getSafeValue("defaultValue", row));
+ option.setDescription(getSafeValue("description", row));
+ option.setEnumValues(getSafeValue("enum", row));
+ component.addEndpointOption(option);
+ }
+
return component;
}
+
+ private void addProperty(JavaClassSource clazz, ComponentModel model, OptionModel option) {
+ String type = option.getJavaType();
+ PropertySource<JavaClassSource> prop = clazz.addProperty(type, option.getName());
+
+ if ("true".equals(option.getDeprecated())) {
+ prop.getField().addAnnotation(Deprecated.class);
+ prop.getAccessor().addAnnotation(Deprecated.class);
+ prop.getMutator().addAnnotation(Deprecated.class);
+ // DeprecatedConfigurationProperty must be on getter when deprecated
+ prop.getAccessor().addAnnotation(DeprecatedConfigurationProperty.class);
+ }
+ if (!Strings.isBlank(option.getDescription())) {
+ prop.getField().getJavaDoc().setFullText(option.getDescription());
+ }
+ if (!Strings.isBlank(option.getDefaultValue())) {
+ if ("java.lang.String".equals(option.getJavaType())) {
+ prop.getField().setStringInitializer(option.getDefaultValue());
+ } else if ("long".equals(option.getJavaType()) || "java.lang.Long".equals(option.getJavaType())) {
+ // the value should be a Long number
+ String value = option.getDefaultValue() + "L";
+ prop.getField().setLiteralInitializer(value);
+ } else if ("integer".equals(option.getType()) || "boolean".equals(option.getType())) {
+ prop.getField().setLiteralInitializer(option.getDefaultValue());
+ } else if (!Strings.isBlank(option.getEnums())) {
+ String enumShortName = type.substring(type.lastIndexOf(".") + 1);
+ prop.getField().setLiteralInitializer(enumShortName + "." + option.getDefaultValue());
+ clazz.addImport(model.getJavaType());
+ }
+ }
+ }
+
}
http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/ComponentModel.java
----------------------------------------------------------------------
diff --git a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/ComponentModel.java b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/ComponentModel.java
index 2cacb78..0d61b14 100644
--- a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/ComponentModel.java
+++ b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/ComponentModel.java
@@ -37,7 +37,8 @@ public class ComponentModel {
private String groupId;
private String artifactId;
private String version;
- private final List<ComponentOptionModel> componentOptions = new ArrayList<ComponentOptionModel>();
+ private final List<ComponentOptionModel> componentOptions = new ArrayList<>();
+ private final List<EndpointOptionModel> endpointOptions = new ArrayList<>();
public String getKind() {
return kind;
@@ -175,6 +176,14 @@ public class ComponentModel {
componentOptions.add(option);
}
+ public List<EndpointOptionModel> getEndpointOptions() {
+ return endpointOptions;
+ }
+
+ public void addEndpointOption(EndpointOptionModel option) {
+ endpointOptions.add(option);
+ }
+
public String getShortJavaType() {
if (javaType.startsWith("java.util.Map")) {
return "Map";
http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/ComponentOptionModel.java
----------------------------------------------------------------------
diff --git a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/ComponentOptionModel.java b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/ComponentOptionModel.java
index 96b5598..a97cf53 100644
--- a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/ComponentOptionModel.java
+++ b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/ComponentOptionModel.java
@@ -16,131 +16,5 @@
*/
package org.apache.camel.maven.connector.model;
-public class ComponentOptionModel {
-
- private String name;
- private String displayName;
- private String kind;
- private String group;
- private String required;
- private String type;
- private String javaType;
- private String deprecated;
- private String secret;
- private String description;
- private String defaultValue;
- private String enums;
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getDisplayName() {
- return displayName;
- }
-
- public void setDisplayName(String displayName) {
- this.displayName = displayName;
- }
-
- public String getKind() {
- return kind;
- }
-
- public void setKind(String kind) {
- this.kind = kind;
- }
-
- public String getGroup() {
- return group;
- }
-
- public void setGroup(String group) {
- this.group = group;
- }
-
- public String getRequired() {
- return required;
- }
-
- public void setRequired(String required) {
- this.required = required;
- }
-
- public String getType() {
- return type;
- }
-
- public void setType(String type) {
- this.type = type;
- }
-
- public String getJavaType() {
- return javaType;
- }
-
- public void setJavaType(String javaType) {
- this.javaType = javaType;
- }
-
- public String getDeprecated() {
- return deprecated;
- }
-
- public void setDeprecated(String deprecated) {
- this.deprecated = deprecated;
- }
-
- public String getSecret() {
- return secret;
- }
-
- public void setSecret(String secret) {
- this.secret = secret;
- }
-
- public String getDescription() {
- return description;
- }
-
- public void setDescription(String description) {
- this.description = description;
- }
-
- public String getDefaultValue() {
- return defaultValue;
- }
-
- public void setDefaultValue(String defaultValue) {
- this.defaultValue = defaultValue;
- }
-
- public String getEnums() {
- return enums;
- }
-
- public void setEnums(String enums) {
- this.enums = enums;
- }
-
- public String getShortJavaType() {
- if (javaType.startsWith("java.util.Map")) {
- return "Map";
- } else if (javaType.startsWith("java.util.Set")) {
- return "Set";
- } else if (javaType.startsWith("java.util.List")) {
- return "List";
- }
- int pos = javaType.lastIndexOf(".");
- if (pos != -1) {
- return javaType.substring(pos + 1);
- } else {
- return javaType;
- }
- }
-
+public class ComponentOptionModel extends OptionModel {
}
http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/EndpointOptionModel.java
----------------------------------------------------------------------
diff --git a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/EndpointOptionModel.java b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/EndpointOptionModel.java
new file mode 100644
index 0000000..07d536a
--- /dev/null
+++ b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/EndpointOptionModel.java
@@ -0,0 +1,215 @@
+/**
+ * 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.maven.connector.model;
+
+import com.google.common.base.CaseFormat;
+
+public class EndpointOptionModel extends OptionModel {
+ private String prefix;
+ private String multiValue;
+ private String enumValues;
+
+ // special for documentation rendering
+ private boolean newGroup;
+
+
+ public String getPrefix() {
+ return prefix;
+ }
+
+ public void setPrefix(String prefix) {
+ this.prefix = prefix;
+ }
+
+ public String getMultiValue() {
+ return multiValue;
+ }
+
+ public void setMultiValue(String multiValue) {
+ this.multiValue = multiValue;
+ }
+
+ public String getEnumValues() {
+ return enumValues;
+ }
+
+ public void setEnumValues(String enumValues) {
+ this.enumValues = enumValues;
+ }
+
+ public boolean isNewGroup() {
+ return newGroup;
+ }
+
+ public void setNewGroup(boolean newGroup) {
+ this.newGroup = newGroup;
+ }
+
+ @Override
+ public String getShortJavaType() {
+ // TODO: use watermark in the others
+ return getShortJavaType(40);
+ }
+
+ public String getShortJavaType(int watermark) {
+ String group = getGroup();
+ String type = getType();
+ String javaType = getJavaType();
+
+ if (javaType.startsWith("java.util.Map")) {
+ return "Map";
+ } else if (javaType.startsWith("java.util.Set")) {
+ return "Set";
+ } else if (javaType.startsWith("java.util.List")) {
+ return "List";
+ }
+
+ String text = javaType;
+
+ int pos = text.lastIndexOf(".");
+ if (pos != -1) {
+ text = text.substring(pos + 1);
+ }
+
+ // if its some kind of java object then lets wrap it as its long
+ if ("object".equals(type)) {
+ text = wrapCamelCaseWords(text, watermark, " ");
+ }
+ return text;
+ }
+
+ public String getShortGroup() {
+ String group = getGroup();
+
+ if (group.endsWith(" (advanced)")) {
+ return group.substring(0, group.length() - 11);
+ }
+ return group;
+ }
+
+ public String getShortDefaultValue(int watermark) {
+ String defaultValue = getDefaultValue();
+
+ if (defaultValue.isEmpty()) {
+ return "";
+ }
+ String text = defaultValue;
+ if (text.endsWith("<T>")) {
+ text = text.substring(0, text.length() - 3);
+ } else if (text.endsWith("<T>>")) {
+ text = text.substring(0, text.length() - 4);
+ }
+
+ // TODO: dirty hack for AUTO_ACKNOWLEDGE which we should wrap
+ if ("AUTO_ACKNOWLEDGE".equals(text)) {
+ return "AUTO_ ACKNOWLEDGE";
+ }
+
+ return text;
+ }
+
+ public String getShortName(int watermark) {
+ String text = wrapCamelCaseWords(getName(), watermark, " ");
+ // ensure the option name starts with lower-case
+ return Character.toLowerCase(text.charAt(0)) + text.substring(1);
+ }
+
+ /**
+ * To wrap long camel cased texts by words.
+ *
+ * @param option the option which is camel cased.
+ * @param watermark a watermark to denote the size to cut after
+ * @param newLine the new line to use when breaking into a new line
+ */
+ private String wrapCamelCaseWords(String option, int watermark, String newLine) {
+ String text = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, option);
+ text = text.replace('-', ' ');
+ text = wrapWords(text, "\n", watermark, false);
+ text = text.replace(' ', '-');
+ text = CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, text);
+
+ // upper case first char on each line
+ String[] lines = text.split("\n");
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < lines.length; i++) {
+ String line = lines[i];
+ line = Character.toUpperCase(line.charAt(0)) + line.substring(1);
+ sb.append(line);
+ if (i < lines.length - 1) {
+ sb.append(newLine);
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * To wrap a big line by words.
+ *
+ * @param line the big line
+ * @param newLine the new line to use when breaking into a new line
+ * @param watermark a watermark to denote the size to cut after
+ * @param wrapLongWords whether to wrap long words
+ */
+ private String wrapWords(String line, String newLine, int watermark, boolean wrapLongWords) {
+ if (line == null) {
+ return null;
+ } else {
+ if (newLine == null) {
+ newLine = System.lineSeparator();
+ }
+
+ if (watermark < 1) {
+ watermark = 1;
+ }
+
+ int inputLineLength = line.length();
+ int offset = 0;
+ StringBuilder sb = new StringBuilder(inputLineLength + 32);
+
+ while (inputLineLength - offset > watermark) {
+ if (line.charAt(offset) == 32) {
+ ++offset;
+ } else {
+ int spaceToWrapAt = line.lastIndexOf(32, watermark + offset);
+ if (spaceToWrapAt >= offset) {
+ sb.append(line.substring(offset, spaceToWrapAt));
+ sb.append(newLine);
+ offset = spaceToWrapAt + 1;
+ } else if (wrapLongWords) {
+ sb.append(line.substring(offset, watermark + offset));
+ sb.append(newLine);
+ offset += watermark;
+ } else {
+ spaceToWrapAt = line.indexOf(32, watermark + offset);
+ if (spaceToWrapAt >= 0) {
+ sb.append(line.substring(offset, spaceToWrapAt));
+ sb.append(newLine);
+ offset = spaceToWrapAt + 1;
+ } else {
+ sb.append(line.substring(offset));
+ offset = inputLineLength;
+ }
+ }
+ }
+ }
+
+ sb.append(line.substring(offset));
+ return sb.toString();
+ }
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/OptionModel.java
----------------------------------------------------------------------
diff --git a/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/OptionModel.java b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/OptionModel.java
new file mode 100644
index 0000000..64d8002
--- /dev/null
+++ b/connectors/camel-connector-maven-plugin/src/main/java/org/apache/camel/maven/connector/model/OptionModel.java
@@ -0,0 +1,146 @@
+/**
+ * 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.maven.connector.model;
+
+public class OptionModel {
+
+ private String name;
+ private String displayName;
+ private String kind;
+ private String group;
+ private String required;
+ private String type;
+ private String javaType;
+ private String deprecated;
+ private String secret;
+ private String description;
+ private String defaultValue;
+ private String enums;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ public void setDisplayName(String displayName) {
+ this.displayName = displayName;
+ }
+
+ public String getKind() {
+ return kind;
+ }
+
+ public void setKind(String kind) {
+ this.kind = kind;
+ }
+
+ public String getGroup() {
+ return group;
+ }
+
+ public void setGroup(String group) {
+ this.group = group;
+ }
+
+ public String getRequired() {
+ return required;
+ }
+
+ public void setRequired(String required) {
+ this.required = required;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getJavaType() {
+ return javaType;
+ }
+
+ public void setJavaType(String javaType) {
+ this.javaType = javaType;
+ }
+
+ public String getDeprecated() {
+ return deprecated;
+ }
+
+ public void setDeprecated(String deprecated) {
+ this.deprecated = deprecated;
+ }
+
+ public String getSecret() {
+ return secret;
+ }
+
+ public void setSecret(String secret) {
+ this.secret = secret;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getDefaultValue() {
+ return defaultValue;
+ }
+
+ public void setDefaultValue(String defaultValue) {
+ this.defaultValue = defaultValue;
+ }
+
+ public String getEnums() {
+ return enums;
+ }
+
+ public void setEnums(String enums) {
+ this.enums = enums;
+ }
+
+ public String getShortJavaType() {
+ if (javaType.startsWith("java.util.Map")) {
+ return "Map";
+ } else if (javaType.startsWith("java.util.Set")) {
+ return "Set";
+ } else if (javaType.startsWith("java.util.List")) {
+ return "List";
+ }
+ int pos = javaType.lastIndexOf(".");
+ if (pos != -1) {
+ return javaType.substring(pos + 1);
+ } else {
+ return javaType;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/connectors/camel-connector/src/main/docs/connector-component.adoc
----------------------------------------------------------------------
diff --git a/connectors/camel-connector/src/main/docs/connector-component.adoc b/connectors/camel-connector/src/main/docs/connector-component.adoc
index f3f1e67..a5ea535 100644
--- a/connectors/camel-connector/src/main/docs/connector-component.adoc
+++ b/connectors/camel-connector/src/main/docs/connector-component.adoc
@@ -42,6 +42,7 @@ You can also copy the existing examples from the `connectors` directory where th
- `foo-connector` - A connector that is based on the Timer component from `camel-core`.
- `bar-connector` - A connector that is based on the 3rd party `beverage-component`.
- `wine-connector` - Another connector that is based on the 3rd party `beverage-component`.
+- 'twitter-search' - A connector based on twitter to search for keywords.
You can find an example using these connectors in the `foo-bar-wine-example` in the `connectors` directory.
@@ -111,14 +112,18 @@ And these following Maven plugins:
### Spring Boot compliant
-A Camel connector works great with Spring Boot. If a connector has been configured to allow configuration
- on the component level which is done in the `camel-connector.json` file, such as
+A Camel connector works great with Spring Boot. If a connector has been configured to allow configuration on the component and/por endpoint level which is done in the `camel-connector.json` file, such as
- "componentOptions" : [ "loginUrl", "clientId", "clientSecret", "refreshToken" ],
+ "componentOptions" : [ "consumerKey", "consumerSecret", "accessToken", "accessTokenSecret" ],
+ "endpointOptions" : [ "keywords" ],
Then the `camel-connector-maven-plugin` will be able to generate Spring Boot auto configuration for these options.
This allows users to essily configure these options if using Spring Boot with the connector.
+NOTE: There's no disctinction between component/endpoint options on spring-boot auto configuration side so all the options are flattered to a single namespace thus they appear as connector options and then the conenctor figures out where they should be applied.
+
+TIP: The options configured through spring-boot auto configuration classes can be overridden by standard endpoint options.
+
To enable Spring Boot generation you need to enable this in the `camel-connector-maven-plugin` by adding
an `<execution>` with the `prepare-spring-boot-auto-configuration` goal:
@@ -157,6 +162,50 @@ You will also need to add the `spring-boot-configuration-processor` in the Maven
</dependency>
------------
+An example on how to configure a component in spring boot can be taken from the twitter-search connector:
+
+[source]
+------------
+ camel.connector.twitter-search.consumer-key = ...
+ camel.connector.twitter-search.consumer-secret = ...
+ camel.connector.twitter-search.access-token = ...
+ camel.connector.twitter-search.access-token-secret = ...
+ camel.connector.twitter-search.keywords = apache-camel
+------------
+
+You may need to instantiate multiple instance of the connector i.e. to use different logins and this is now possible through the 'configurations' parameters:
+
+[source]
+------------
+ camel.connector.twitter-search.configurations.tw-search1.consumer-key = ...
+ camel.connector.twitter-search.configurations.tw-search1.consumer-secret = ...
+ camel.connector.twitter-search.configurations.tw-search1.access-token = ...
+ camel.connector.twitter-search.configurations.tw-search1.access-token-secret = ...
+ camel.connector.twitter-search.configurations.tw-search1.keywords = apache-camel
+
+ camel.connector.twitter-search.configurations.tw-search2.consumer-key = ...
+ camel.connector.twitter-search.configurations.tw-search2.consumer-secret = ...
+ camel.connector.twitter-search.configurations.tw-search2.access-token = ...
+ camel.connector.twitter-search.configurations.tw-search2.access-token-secret = ...
+ camel.connector.twitter-search.configurations.tw-search2.keywords = apache-karaf
+------------
+
+This would create two instances of the twitter-search connector each one configured with its own list o options.
+You can no use the nre connector as standard components like:
+
+[source,java]
+------------
+ @Component
+ public class MyRouteBuilder implements RouteBuilder{
+ public void configure() throws Exception {
+ from("tw-search1")
+ .log("On account 1 I got: ${body}")
+ from("tw-search2")
+ .log("On account 2 I got: ${body}")
+ }
+ }
+------------
+
### Input and Output Data Type
@@ -192,4 +241,3 @@ The options the connector can provide is a limited set of all the existing optio
its based upon. Each option can then also be pre-configured with a default-value.
To understand this schema file, its easier to study those existing connectors from the `connectors` directory.
-
http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/ConnectorComponent.java
----------------------------------------------------------------------
diff --git a/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/ConnectorComponent.java b/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/ConnectorComponent.java
index 901ed0b..b25ff70 100644
--- a/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/ConnectorComponent.java
+++ b/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/ConnectorComponent.java
@@ -68,20 +68,42 @@ public interface ConnectorComponent extends Component {
String getCamelConnectorJSon();
/**
- * A set of additional component options to use for the base component when creating connector endpoints.
+ * A set of additional component/endpoint options to use for the base component when creating connector endpoints.
+ *
+ * @deprecated use {@link #getOptions()} instead
+ */
+ @Deprecated
+ default Map<String, Object> getComponentOptions() {
+ return getOptions();
+ }
+
+ /**
+ * A set of additional component/endpoint options to use for the base component when creating connector endpoints.
+ */
+ Map<String, Object> getOptions();
+
+ /**
+ * A set of additional component/endpoint options to use for the base component when creating connector endpoints.
+ *
+ * @deprecated use {@link #setOptions(Map)} instead
*/
- Map<String, Object> getComponentOptions();
+ default void setComponentOptions(Map<String, Object> options) {
+ setOptions(options);
+ }
/**
- * A set of additional component options to use for the base component when creating connector endpoints.
+ * A set of additional component/endpoint options to use for the base component when creating connector endpoints.
*/
- void setComponentOptions(Map<String, Object> baseComponentOptions);
+ void setOptions(Map<String, Object> options);
/**
* To perform custom processing before the producer is sending the message.
*/
void setBeforeProducer(Processor processor);
+ /**
+ * Gets the processor used to perform custom processing before the producer is sending the message.
+ */
Processor getBeforeProducer();
/**
@@ -89,6 +111,9 @@ public interface ConnectorComponent extends Component {
*/
void setAfterProducer(Processor processor);
+ /**
+ * Gets the processor used to perform custom processing after the producer has sent the message and received any reply (if InOut).
+ */
Processor getAfterProducer();
/**
@@ -96,6 +121,9 @@ public interface ConnectorComponent extends Component {
*/
void setBeforeConsumer(Processor processor);
+ /**
+ * Gets the processor used to perform custom processing when the consumer has just received a new incoming message.
+ */
Processor getBeforeConsumer();
/**
@@ -103,5 +131,8 @@ public interface ConnectorComponent extends Component {
*/
void setAfterConsumer(Processor processor);
+ /**
+ * Gets the processor used to perform custom processing when the consumer is about to send back a reply message to the caller (if InOut).
+ */
Processor getAfterConsumer();
}
http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/ConnectorModel.java
----------------------------------------------------------------------
diff --git a/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/ConnectorModel.java b/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/ConnectorModel.java
index 2165d41..8d409f7 100644
--- a/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/ConnectorModel.java
+++ b/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/ConnectorModel.java
@@ -61,6 +61,8 @@ final class ConnectorModel {
private DataType outputDataType;
private Map<String, String> defaultComponentOptions;
private Map<String, String> defaultEndpointOptions;
+ private List<String> endpointOptions;
+ private List<String> componentOptions;
ConnectorModel(String componentName, String className) {
this.componentName = componentName;
@@ -132,6 +134,22 @@ final class ConnectorModel {
return defaultEndpointOptions;
}
+ public List<String> getEndpointOptions() {
+ if (endpointOptions == null) {
+ endpointOptions = Collections.unmodifiableList(extractEndpointOptions(lines.get()));
+ }
+
+ return endpointOptions;
+ }
+
+ public List<String> getComponentOptions() {
+ if (endpointOptions == null) {
+ endpointOptions = Collections.unmodifiableList(extractComponentOptions(lines.get()));
+ }
+
+ return endpointOptions;
+ }
+
public DataType getInputDataType() {
if (inputDataType == null) {
String line = extractInputDataType(lines.get());
@@ -334,4 +352,62 @@ final class ConnectorModel {
return answer;
}
+
+ private List<String> extractComponentOptions(List<String> lines) {
+ List<String> answer = new ArrayList<>();
+
+ // extract the default options
+ for (String line : lines) {
+ line = line.trim();
+ if (line.startsWith("\"componentOptions\"")) {
+ int start = line.indexOf('[');
+ if (start == -1) {
+ throw new IllegalStateException("Malformed camel-connector.json");
+ }
+
+ int end = line.indexOf(']', start);
+ if (end == -1) {
+ throw new IllegalStateException("Malformed camel-connector.json");
+ }
+
+ line = line.substring(start + 1, end).trim();
+ for (String option : line.split(",")) {
+ answer.add(StringHelper.removeLeadingAndEndingQuotes(option));
+ }
+
+ break;
+ }
+ }
+
+ return answer;
+ }
+
+ private List<String> extractEndpointOptions(List<String> lines) {
+ List<String> answer = new ArrayList<>();
+
+ // extract the default options
+ for (String line : lines) {
+ line = line.trim();
+ if (line.startsWith("\"endpointOptions\"")) {
+ int start = line.indexOf('[');
+ if (start == -1) {
+ throw new IllegalStateException("Malformed camel-connector.json");
+ }
+
+ int end = line.indexOf(']', start);
+ if (end == -1) {
+ throw new IllegalStateException("Malformed camel-connector.json");
+ }
+
+ line = line.substring(start + 1, end).trim();
+ for (String option : line.split(",")) {
+ answer.add(StringHelper.removeLeadingAndEndingQuotes(option));
+ }
+
+ break;
+ }
+ }
+
+ return answer;
+ }
}
http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/connectors/camel-connector/src/main/java/org/apache/camel/component/connector/DefaultConnectorComponent.java
----------------------------------------------------------------------
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 192ebf1..50d1407 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
@@ -20,13 +20,18 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.net.URI;
import java.net.URISyntaxException;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
+import java.util.List;
import java.util.Map;
+import org.apache.camel.CamelContext;
import org.apache.camel.Component;
import org.apache.camel.ComponentVerifier;
import org.apache.camel.Endpoint;
+import org.apache.camel.NoTypeConversionAvailableException;
import org.apache.camel.Processor;
import org.apache.camel.VerifiableComponent;
import org.apache.camel.catalog.CamelCatalog;
@@ -35,6 +40,7 @@ import org.apache.camel.impl.DefaultComponent;
import org.apache.camel.impl.verifier.ResultBuilder;
import org.apache.camel.impl.verifier.ResultErrorBuilder;
import org.apache.camel.util.IntrospectionSupport;
+import org.apache.camel.util.ObjectHelper;
import org.apache.camel.util.URISupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -48,20 +54,35 @@ public abstract class DefaultConnectorComponent extends DefaultComponent impleme
private final Logger log = LoggerFactory.getLogger(getClass());
private final CamelCatalog catalog = new DefaultCamelCatalog(false);
+ private final String baseScheme;
private final String componentName;
+ private final String componentScheme;
private final ConnectorModel model;
- private Map<String, Object> componentOptions;
+ private Map<String, Object> options;
private Processor beforeProducer;
private Processor afterProducer;
private Processor beforeConsumer;
private Processor afterConsumer;
protected DefaultConnectorComponent(String componentName, String className) {
- this.componentName = componentName;
this.model = new ConnectorModel(componentName, className);
+ this.baseScheme = this.model.getBaseScheme();
+ this.componentName = componentName;
+ this.componentScheme = componentName + "-component";
// add to catalog
this.catalog.addComponent(componentName, className);
+
+ // It may be a custom component so we need to register this in the camel catalog also
+ if (!catalog.findComponentNames().contains(baseScheme)) {
+ catalog.addComponent(baseScheme, model.getBaseJavaType());
+ }
+
+ // 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(componentScheme)) {
+ this.catalog.addComponent(componentScheme, this.model.getBaseJavaType(), catalog.componentJSonSchema(baseScheme));
+ }
}
@Override
@@ -78,16 +99,10 @@ public abstract class DefaultConnectorComponent extends DefaultComponent impleme
// grab the regular query parameters
Map<String, String> options = buildEndpointOptions(remaining, parameters);
- String scheme = model.getBaseScheme();
-
- // now create the endpoint instance which either happens with a new
- // base component which has been pre-configured for this connector
- // or we fallback and use the default component in the camel context
- createNewBaseComponent(scheme);
-
// create the uri of the base component
- String delegateUri = createEndpointUri(scheme, options);
+ String delegateUri = createEndpointUri(componentScheme, options);
Endpoint delegate = getCamelContext().getEndpoint(delegateUri);
+
if (log.isInfoEnabled()) {
// the uris can have sensitive information so sanitize
log.info("Connector resolved: {} -> {}", sanitizeUri(uri), sanitizeUri(delegateUri));
@@ -119,7 +134,10 @@ public abstract class DefaultConnectorComponent extends DefaultComponent impleme
@Override
public void addConnectorOption(Map<String, String> options, String name, String value) {
log.trace("Adding option: {}={}", name, value);
- options.put(name, value);
+ Object val = options.put(name, value);
+ if (val != null) {
+ log.debug("Options {} overridden, old value was {}", name, val);
+ }
}
@Override
@@ -142,48 +160,60 @@ public abstract class DefaultConnectorComponent extends DefaultComponent impleme
return componentName;
}
- public Map<String, Object> getComponentOptions() {
- return componentOptions;
+ @Override
+ public Map<String, Object> getOptions() {
+ return options;
}
- public void setComponentOptions(Map<String, Object> baseComponentOptions) {
- this.componentOptions = baseComponentOptions;
+ @Override
+ public void setOptions(Map<String, Object> baseComponentOptions) {
+ // Copy the map so if the given map is externally modified the connector
+ // is not impacted.
+ this.options = Collections.unmodifiableMap(new HashMap<>(baseComponentOptions));
}
@SuppressWarnings("unchecked")
@Override
public ComponentVerifier getVerifier() {
- final String scheme = model.getBaseScheme();
- // only get or create component but do NOT start it as component
- final Component component = getCamelContext().getComponent(scheme, true, false);
+ try {
+ // Create the component but no need to add it to the camel context
+ // nor to start it.
+ final Component component = createNewBaseComponent();
+
+ if (component instanceof VerifiableComponent) {
+ return (scope, map) -> {
+ Map<String, Object> options;
+
+ try {
+ // A little nasty hack required as verifier uses Map<String, Object>
+ // to be compatible with all the methods in CamelContext whereas
+ // catalog deals with Map<String, String>
+ options = (Map) buildEndpointOptions(null, map);
+ } catch (URISyntaxException | NoTypeConversionAvailableException e) {
+ // If a failure is detected while reading the catalog, wrap it
+ // and stop the validation step.
+ return ResultBuilder.withStatusAndScope(ComponentVerifier.Result.Status.OK, scope)
+ .error(ResultErrorBuilder.withException(e).build())
+ .build();
+ }
- if (component instanceof VerifiableComponent) {
- return (scope, map) -> {
- Map<String, Object> options;
-
- try {
- // A little nasty hack required as verifier uses Map<String, Object>
- // to be compatible with all the methods in CamelContext whereas
- // catalog deals with Map<String, String>
- options = (Map) buildEndpointOptions(null, map);
- } catch (URISyntaxException e) {
- // If a failure is detected while reading the catalog, wrap it
- // and stop the validation step.
- return ResultBuilder.withStatusAndScope(ComponentVerifier.Result.Status.OK, scope)
- .error(ResultErrorBuilder.withException(e).build())
+ return ((VerifiableComponent) component).getVerifier().verify(scope, options);
+ };
+ } else {
+ return (scope, map) -> {
+ return ResultBuilder.withStatusAndScope(ComponentVerifier.Result.Status.UNSUPPORTED, scope)
+ .error(
+ ResultErrorBuilder.withCode(ComponentVerifier.VerificationError.StandardCode.UNSUPPORTED)
+ .detail("camel_connector_name", getConnectorName())
+ .detail("camel_component_name", getComponentName())
+ .build())
.build();
- }
-
- return ((VerifiableComponent)component).getVerifier().verify(scope, options);
- };
- } else {
+ };
+ }
+ } catch (Exception e) {
return (scope, map) -> {
- return ResultBuilder.withStatusAndScope(ComponentVerifier.Result.Status.UNSUPPORTED, scope)
- .error(
- ResultErrorBuilder.withCode(ComponentVerifier.VerificationError.StandardCode.UNSUPPORTED)
- .detail("camel_connector_name", getConnectorName())
- .detail("camel_component_name", getComponentName())
- .build())
+ return ResultBuilder.withStatusAndScope(ComponentVerifier.Result.Status.OK, scope)
+ .error(ResultErrorBuilder.withException(e).build())
.build();
};
}
@@ -194,7 +224,6 @@ public abstract class DefaultConnectorComponent extends DefaultComponent impleme
@Override
protected void doStart() throws Exception {
// lets enforce that every connector must have an input and output data type
-
if (model.getInputDataType() == null) {
throw new IllegalArgumentException("Camel connector must have inputDataType defined in camel-connector.json file");
}
@@ -208,11 +237,13 @@ public abstract class DefaultConnectorComponent extends DefaultComponent impleme
throw new IllegalArgumentException("Camel connector must have baseJavaType defined in camel-connector.json file");
}
- // it may be a custom component so we need to register this in the camel catalog also
- String scheme = model.getBaseScheme();
- if (!catalog.findComponentNames().contains(scheme)) {
- String javaType = model.getBaseJavaType();
- catalog.addComponent(scheme, javaType);
+ Component component = createNewBaseComponent();
+ if (component != null) {
+ getCamelContext().removeComponent(this.componentScheme);
+
+ // ensure component is started and stopped when Camel shutdown
+ getCamelContext().addService(component, true, true);
+ getCamelContext().addComponent(this.componentScheme, component);
}
log.debug("Starting connector: {}", componentName);
@@ -269,8 +300,16 @@ public abstract class DefaultConnectorComponent extends DefaultComponent impleme
// Helpers
// ***************************************
- private Component createNewBaseComponent(String scheme) throws Exception {
- String baseClassName = model.getBaseJavaType();
+ /**
+ * Create the endpoint instance which either happens with a new base component
+ * which has been pre-configured for this connector or we fallback and use
+ * the default component in the camel context
+ */
+ private Component createNewBaseComponent() throws Exception {
+ final String baseClassName = model.getBaseJavaType();
+ final CamelContext context = getCamelContext();
+
+ Component base = null;
if (baseClassName != null) {
// create a new instance of this base component
@@ -278,45 +317,46 @@ public abstract class DefaultConnectorComponent extends DefaultComponent impleme
Constructor ctr = getPublicDefaultConstructor(type);
if (ctr != null) {
// call default no-arg constructor
- Object base = ctr.newInstance();
+ base = (Component)ctr.newInstance();
+ base.setCamelContext(context);
// the connector may have default values for the component level also
- // and if so we need to prepare these values and set on this component before we can start
+ // and if so we need to prepare these values and set on this component
+ // before we can start
Map<String, String> defaultOptions = model.getDefaultComponentOptions();
if (!defaultOptions.isEmpty()) {
- Map<String, Object> copy = new LinkedHashMap<>();
for (Map.Entry<String, String> entry : defaultOptions.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
if (value != null) {
// also support {{ }} placeholders so resolve those first
value = getCamelContext().resolvePropertyPlaceholders(value);
+
log.debug("Using component option: {}={}", key, value);
- copy.put(key, value);
+ IntrospectionSupport.setProperty(context, base, key, value);
}
}
- IntrospectionSupport.setProperties(getCamelContext(), getCamelContext().getTypeConverter(), base, copy);
}
// configure component with extra options
- if (componentOptions != null && !componentOptions.isEmpty()) {
- Map<String, Object> copy = new LinkedHashMap<>(componentOptions);
- IntrospectionSupport.setProperties(getCamelContext(), getCamelContext().getTypeConverter(), base, copy);
- }
-
- if (base instanceof Component) {
- getCamelContext().removeComponent(scheme);
- // ensure component is started and stopped when Camel shutdown
- getCamelContext().addService(base, true, true);
- getCamelContext().addComponent(scheme, (Component) base);
-
- return (Component) base;
+ if (options != null && !options.isEmpty()) {
+ // Get the list of options from the connector catalog that
+ // are configured to target the endpoint
+ List<String> endpointOptions = model.getEndpointOptions();
+
+ for (Map.Entry<String, Object> entry : options.entrySet()) {
+ // Only set options that are not targeting the endpoint
+ if (!endpointOptions.contains(entry.getKey())) {
+ log.debug("Using component option: {}={}", entry.getKey(), entry.getValue());
+ IntrospectionSupport.setProperty(context, base, entry.getKey(), entry.getValue());
+ }
+ }
}
}
}
- return null;
+ return base;
}
/**
@@ -366,8 +406,7 @@ public abstract class DefaultConnectorComponent extends DefaultComponent impleme
}
}
- private Map<String, String> buildEndpointOptions(String remaining, Map<String, Object> parameters) throws URISyntaxException {
- String scheme = model.getBaseScheme();
+ private Map<String, String> buildEndpointOptions(String remaining, Map<String, Object> parameters) throws URISyntaxException, NoTypeConversionAvailableException {
Map<String, String> defaultOptions = model.getDefaultEndpointOptions();
// gather all options to use when building the delegate uri
@@ -382,6 +421,22 @@ public abstract class DefaultConnectorComponent extends DefaultComponent impleme
});
}
+ // Extract options from options that are supposed to be set at the endpoint
+ // level, those options can be overridden and extended using by the query
+ // parameters.
+ List<String> endpointOptions = model.getEndpointOptions();
+ if (ObjectHelper.isNotEmpty(endpointOptions) && ObjectHelper.isNotEmpty(this.options)) {
+ for (String endpointOption : endpointOptions) {
+ Object value = this.options.get(endpointOption);
+ if (value != null) {
+ addConnectorOption(
+ options,
+ endpointOption,
+ getCamelContext().getTypeConverter().mandatoryConvertTo(String.class, value));
+ }
+ }
+ }
+
// options from query parameters
for (Map.Entry<String, Object> entry : parameters.entrySet()) {
String key = entry.getKey();
@@ -396,7 +451,7 @@ public abstract class DefaultConnectorComponent extends DefaultComponent impleme
// add extra options from remaining (context-path)
if (remaining != null) {
- String targetUri = scheme + ":" + remaining;
+ String targetUri = componentScheme + ":" + remaining;
Map<String, String> extra = catalog.endpointProperties(targetUri);
if (extra != null && !extra.isEmpty()) {
extra.forEach((key, value) -> {
http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/connectors/examples/petstore-connector/src/main/java/org/foo/connector/springboot/PetStoreConnectorAutoConfiguration.java
----------------------------------------------------------------------
diff --git a/connectors/examples/petstore-connector/src/main/java/org/foo/connector/springboot/PetStoreConnectorAutoConfiguration.java b/connectors/examples/petstore-connector/src/main/java/org/foo/connector/springboot/PetStoreConnectorAutoConfiguration.java
index b2739c5..85e27b0 100644
--- a/connectors/examples/petstore-connector/src/main/java/org/foo/connector/springboot/PetStoreConnectorAutoConfiguration.java
+++ b/connectors/examples/petstore-connector/src/main/java/org/foo/connector/springboot/PetStoreConnectorAutoConfiguration.java
@@ -18,9 +18,13 @@ package org.foo.connector.springboot;
import java.util.HashMap;
import java.util.Map;
+import javax.annotation.Generated;
+import javax.annotation.PostConstruct;
import org.apache.camel.CamelContext;
import org.apache.camel.util.IntrospectionSupport;
import org.foo.connector.PetStoreComponent;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
@@ -33,19 +37,23 @@ import org.springframework.context.annotation.Lazy;
/**
* Generated by camel-connector-maven-plugin - do not edit this file!
*/
+@Generated("org.apache.camel.maven.connector.SpringBootAutoConfigurationMojo")
@Configuration
@ConditionalOnBean(type = "org.apache.camel.spring.boot.CamelAutoConfiguration")
@AutoConfigureAfter(name = "org.apache.camel.spring.boot.CamelAutoConfiguration")
@EnableConfigurationProperties(PetStoreConnectorConfiguration.class)
public class PetStoreConnectorAutoConfiguration {
+ @Autowired
+ private CamelContext camelContext;
+ @Autowired
+ private PetStoreConnectorConfiguration configuration;
+
@Lazy
@Bean(name = "petstore-component")
@ConditionalOnClass(CamelContext.class)
- @ConditionalOnMissingBean(org.foo.connector.PetStoreComponent.class)
- public PetStoreComponent configurePetStoreComponent(
- CamelContext camelContext,
- PetStoreConnectorConfiguration configuration) throws Exception {
+ @ConditionalOnMissingBean(name = "petstore-component")
+ public PetStoreComponent configurePetStoreComponent() throws Exception {
PetStoreComponent connector = new PetStoreComponent();
connector.setCamelContext(camelContext);
Map<String, Object> parameters = new HashMap<>();
@@ -56,4 +64,29 @@ public class PetStoreConnectorAutoConfiguration {
connector.setComponentOptions(parameters);
return connector;
}
+
+ @PostConstruct
+ public void postConstructPetStoreComponent() {
+ if (camelContext != null) {
+ Map<String, Object> parameters = new HashMap<>();
+ for (Map.Entry<String, PetStoreConnectorConfigurationCommon> entry : configuration
+ .getConfigurations().entrySet()) {
+ parameters.clear();
+ PetStoreComponent connector = new PetStoreComponent();
+ connector.setCamelContext(camelContext);
+ try {
+ IntrospectionSupport.getProperties(entry.getValue(),
+ parameters, null, false);
+ IntrospectionSupport.setProperties(camelContext,
+ camelContext.getTypeConverter(), connector,
+ parameters);
+ connector.setComponentOptions(parameters);
+ camelContext.addComponent(entry.getKey(), connector);
+ } catch (Exception e) {
+ throw new BeanCreationException(entry.getKey(),
+ e.getMessage(), e);
+ }
+ }
+ }
+ }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/connectors/examples/petstore-connector/src/main/java/org/foo/connector/springboot/PetStoreConnectorConfiguration.java
----------------------------------------------------------------------
diff --git a/connectors/examples/petstore-connector/src/main/java/org/foo/connector/springboot/PetStoreConnectorConfiguration.java b/connectors/examples/petstore-connector/src/main/java/org/foo/connector/springboot/PetStoreConnectorConfiguration.java
index 0ae5ef3..fa19e29 100644
--- a/connectors/examples/petstore-connector/src/main/java/org/foo/connector/springboot/PetStoreConnectorConfiguration.java
+++ b/connectors/examples/petstore-connector/src/main/java/org/foo/connector/springboot/PetStoreConnectorConfiguration.java
@@ -16,34 +16,23 @@
*/
package org.foo.connector.springboot;
-import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.Generated;
import org.springframework.boot.context.properties.ConfigurationProperties;
-/**
- * An awesome REST endpoint backed by Swagger specifications.
- *
- * Generated by camel-connector-maven-plugin - do not edit this file!
- */
+@Generated("org.apache.camel.maven.connector.SpringBootAutoConfigurationMojo")
@ConfigurationProperties(prefix = "camel.connector.petstore")
-public class PetStoreConnectorConfiguration {
+public class PetStoreConnectorConfiguration
+ extends
+ PetStoreConnectorConfigurationCommon {
/**
- * Path to the Swagger specification file. The scheme host base path are
- * taken from this specification but these can be overriden with properties
- * on the component or endpoint level. If not given the component tries to
- * load swagger.json resource. Note that the host defined on the component
- * and endpoint of this Component should contain the scheme hostname and
- * optionally the port in the URI syntax (i.e.
- * https://api.example.com:8080). Can be overriden in endpoint
- * configuration.
+ * Define additional configuration definitions
*/
- private URI specificationUri;
-
- public URI getSpecificationUri() {
- return specificationUri;
- }
+ private Map<String, PetStoreConnectorConfigurationCommon> configurations = new HashMap<>();
- public void setSpecificationUri(URI specificationUri) {
- this.specificationUri = specificationUri;
+ public Map<String, PetStoreConnectorConfigurationCommon> getConfigurations() {
+ return configurations;
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/connectors/examples/petstore-connector/src/main/java/org/foo/connector/springboot/PetStoreConnectorConfigurationCommon.java
----------------------------------------------------------------------
diff --git a/connectors/examples/petstore-connector/src/main/java/org/foo/connector/springboot/PetStoreConnectorConfigurationCommon.java b/connectors/examples/petstore-connector/src/main/java/org/foo/connector/springboot/PetStoreConnectorConfigurationCommon.java
new file mode 100644
index 0000000..8af2c18
--- /dev/null
+++ b/connectors/examples/petstore-connector/src/main/java/org/foo/connector/springboot/PetStoreConnectorConfigurationCommon.java
@@ -0,0 +1,61 @@
+/**
+ * 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.foo.connector.springboot;
+
+import java.net.URI;
+import javax.annotation.Generated;
+
+/**
+ * An awesome REST endpoint backed by Swagger specifications.
+ *
+ * Generated by camel-package-maven-plugin - do not edit this file!
+ */
+@Generated("org.apache.camel.maven.connector.SpringBootAutoConfigurationMojo")
+public class PetStoreConnectorConfigurationCommon {
+
+ /**
+ * Path to the Swagger specification file. The scheme host base path are
+ * taken from this specification but these can be overriden with properties
+ * on the component or endpoint level. If not given the component tries to
+ * load swagger.json resource. Note that the host defined on the component
+ * and endpoint of this Component should contain the scheme hostname and
+ * optionally the port in the URI syntax (i.e.
+ * https://api.example.com:8080). Can be overriden in endpoint
+ * configuration.
+ */
+ private URI specificationUri;
+ /**
+ * ID of the operation from the Swagger specification.
+ */
+ private String operationId;
+
+ public URI getSpecificationUri() {
+ return specificationUri;
+ }
+
+ public void setSpecificationUri(URI specificationUri) {
+ this.specificationUri = specificationUri;
+ }
+
+ public String getOperationId() {
+ return operationId;
+ }
+
+ public void setOperationId(String operationId) {
+ this.operationId = operationId;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/connectors/examples/pom.xml
----------------------------------------------------------------------
diff --git a/connectors/examples/pom.xml b/connectors/examples/pom.xml
index 65bc229..8a4b10a 100644
--- a/connectors/examples/pom.xml
+++ b/connectors/examples/pom.xml
@@ -40,6 +40,8 @@
<module>wine-connector</module>
<module>foo-bar-wine-example</module>
<module>twitter-mention-connector</module>
+ <module>twitter-search-connector</module>
+ <module>twitter-search-example</module>
<module>twitter-salesforce-example</module>
<module>salesforce-upsert-contact-connector</module>
<module>petstore-connector</module>
http://git-wip-us.apache.org/repos/asf/camel/blob/3dd29006/connectors/examples/salesforce-upsert-contact-connector/src/main/java/org/foo/salesforce/contact/springboot/SalesforceUpsertContactConnectorAutoConfiguration.java
----------------------------------------------------------------------
diff --git a/connectors/examples/salesforce-upsert-contact-connector/src/main/java/org/foo/salesforce/contact/springboot/SalesforceUpsertContactConnectorAutoConfiguration.java b/connectors/examples/salesforce-upsert-contact-connector/src/main/java/org/foo/salesforce/contact/springboot/SalesforceUpsertContactConnectorAutoConfiguration.java
index c9045ed..89c4dee 100644
--- a/connectors/examples/salesforce-upsert-contact-connector/src/main/java/org/foo/salesforce/contact/springboot/SalesforceUpsertContactConnectorAutoConfiguration.java
+++ b/connectors/examples/salesforce-upsert-contact-connector/src/main/java/org/foo/salesforce/contact/springboot/SalesforceUpsertContactConnectorAutoConfiguration.java
@@ -18,9 +18,13 @@ package org.foo.salesforce.contact.springboot;
import java.util.HashMap;
import java.util.Map;
+import javax.annotation.Generated;
+import javax.annotation.PostConstruct;
import org.apache.camel.CamelContext;
import org.apache.camel.util.IntrospectionSupport;
import org.foo.salesforce.contact.SalesforceUpsertContactComponent;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
@@ -33,19 +37,23 @@ import org.springframework.context.annotation.Lazy;
/**
* Generated by camel-connector-maven-plugin - do not edit this file!
*/
+@Generated("org.apache.camel.maven.connector.SpringBootAutoConfigurationMojo")
@Configuration
@ConditionalOnBean(type = "org.apache.camel.spring.boot.CamelAutoConfiguration")
@AutoConfigureAfter(name = "org.apache.camel.spring.boot.CamelAutoConfiguration")
@EnableConfigurationProperties(SalesforceUpsertContactConnectorConfiguration.class)
public class SalesforceUpsertContactConnectorAutoConfiguration {
+ @Autowired
+ private CamelContext camelContext;
+ @Autowired
+ private SalesforceUpsertContactConnectorConfiguration configuration;
+
@Lazy
@Bean(name = "salesforce-upsert-contact-component")
@ConditionalOnClass(CamelContext.class)
- @ConditionalOnMissingBean(org.foo.salesforce.contact.SalesforceUpsertContactComponent.class)
- public SalesforceUpsertContactComponent configureSalesforceUpsertContactComponent(
- CamelContext camelContext,
- SalesforceUpsertContactConnectorConfiguration configuration)
+ @ConditionalOnMissingBean(name = "salesforce-upsert-contact-component")
+ public SalesforceUpsertContactComponent configureSalesforceUpsertContactComponent()
throws Exception {
SalesforceUpsertContactComponent connector = new SalesforceUpsertContactComponent();
connector.setCamelContext(camelContext);
@@ -57,4 +65,29 @@ public class SalesforceUpsertContactConnectorAutoConfiguration {
connector.setComponentOptions(parameters);
return connector;
}
+
+ @PostConstruct
+ public void postConstructSalesforceUpsertContactComponent() {
+ if (camelContext != null) {
+ Map<String, Object> parameters = new HashMap<>();
+ for (Map.Entry<String, SalesforceUpsertContactConnectorConfigurationCommon> entry : configuration
+ .getConfigurations().entrySet()) {
+ parameters.clear();
+ SalesforceUpsertContactComponent connector = new SalesforceUpsertContactComponent();
+ connector.setCamelContext(camelContext);
+ try {
+ IntrospectionSupport.getProperties(entry.getValue(),
+ parameters, null, false);
+ IntrospectionSupport.setProperties(camelContext,
+ camelContext.getTypeConverter(), connector,
+ parameters);
+ connector.setComponentOptions(parameters);
+ camelContext.addComponent(entry.getKey(), connector);
+ } catch (Exception e) {
+ throw new BeanCreationException(entry.getKey(),
+ e.getMessage(), e);
+ }
+ }
+ }
+ }
}
\ No newline at end of file