Return-Path: X-Original-To: apmail-camel-commits-archive@www.apache.org Delivered-To: apmail-camel-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id D4E5118431 for ; Mon, 5 Oct 2015 09:50:48 +0000 (UTC) Received: (qmail 5627 invoked by uid 500); 5 Oct 2015 09:50:26 -0000 Delivered-To: apmail-camel-commits-archive@camel.apache.org Received: (qmail 5555 invoked by uid 500); 5 Oct 2015 09:50:26 -0000 Mailing-List: contact commits-help@camel.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@camel.apache.org Delivered-To: mailing list commits@camel.apache.org Received: (qmail 5535 invoked by uid 99); 5 Oct 2015 09:50:26 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 05 Oct 2015 09:50:26 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 5AB76DFAF3; Mon, 5 Oct 2015 09:50:26 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: davsclaus@apache.org To: commits@camel.apache.org Date: Mon, 05 Oct 2015 09:50:26 -0000 Message-Id: <9b0a007fe16a435b8e75fb89d53d995f@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [01/10] camel git commit: CAMEL-9162: camel-elsql component Repository: camel Updated Branches: refs/heads/master f5614efb8 -> 5fc96ef45 CAMEL-9162: camel-elsql component Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/ed0f42a1 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/ed0f42a1 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/ed0f42a1 Branch: refs/heads/master Commit: ed0f42a1434cda23b85a140a40a54bdf3ae0c8b5 Parents: 6cf9956 Author: Claus Ibsen Authored: Sun Oct 4 14:33:06 2015 +0200 Committer: Claus Ibsen Committed: Mon Oct 5 10:54:53 2015 +0200 ---------------------------------------------------------------------- components/camel-elsql/pom.xml | 1 + .../camel/component/elsql/ElsqlComponent.java | 55 +++++++------ .../camel/component/elsql/ElsqlEndpoint.java | 21 ++--- .../camel/component/elsql/ElsqlProducer.java | 19 +++-- .../component/elsql/ElsqlSqlMapSource.java | 54 +++++++++++++ .../camel/component/elsql/ElsqlSqlParams.java | 68 ---------------- .../elsql/ElsqlSqlProcessingStrategy.java | 6 +- .../component/elsql/ElSqlDataSourceTest.java | 85 ++++++++++++++++++++ .../src/test/resources/elsql/projects.elsql | 5 ++ .../src/test/resources/log4j.properties | 39 +++++++++ .../resources/sql/createAndPopulateDatabase.sql | 23 ++++++ .../camel/component/sql/SqlComponent.java | 4 + .../apache/camel/component/sql/SqlEndpoint.java | 73 ++++++++++------- 13 files changed, 314 insertions(+), 139 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/ed0f42a1/components/camel-elsql/pom.xml ---------------------------------------------------------------------- diff --git a/components/camel-elsql/pom.xml b/components/camel-elsql/pom.xml index d82bb05..f45f7e6 100644 --- a/components/camel-elsql/pom.xml +++ b/components/camel-elsql/pom.xml @@ -34,6 +34,7 @@ org.apache.camel.component.elsql.*;${camel.osgi.version} + org.apache.camel.component.sql.*, !org.apache.camel.component.elsql.*, ${camel.osgi.import.defaults}, * http://git-wip-us.apache.org/repos/asf/camel/blob/ed0f42a1/components/camel-elsql/src/main/java/org/apache/camel/component/elsql/ElsqlComponent.java ---------------------------------------------------------------------- diff --git a/components/camel-elsql/src/main/java/org/apache/camel/component/elsql/ElsqlComponent.java b/components/camel-elsql/src/main/java/org/apache/camel/component/elsql/ElsqlComponent.java index ddea39d..40e6530 100644 --- a/components/camel-elsql/src/main/java/org/apache/camel/component/elsql/ElsqlComponent.java +++ b/components/camel-elsql/src/main/java/org/apache/camel/component/elsql/ElsqlComponent.java @@ -20,20 +20,20 @@ import java.util.Map; import javax.sql.DataSource; import com.opengamma.elsql.ElSqlConfig; -import org.apache.camel.CamelContext; import org.apache.camel.Endpoint; -import org.apache.camel.component.sql.SqlComponent; +import org.apache.camel.impl.UriEndpointComponent; import org.apache.camel.util.CamelContextHelper; import org.apache.camel.util.IntrospectionSupport; -import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; -public class ElsqlComponent extends SqlComponent { +public class ElsqlComponent extends UriEndpointComponent { + private DataSource dataSource; private ElSqlConfig elSqlConfig; private String resourceUri; - public ElsqlComponent(CamelContext context) { - super(context, ElsqlEndpoint.class); + public ElsqlComponent() { + super(ElsqlEndpoint.class); } @Override @@ -57,12 +57,12 @@ public class ElsqlComponent extends SqlComponent { throw new IllegalArgumentException("DataSource must be configured"); } - JdbcTemplate jdbcTemplate = new JdbcTemplate(target); + NamedParameterJdbcTemplate jdbcTemplate = new NamedParameterJdbcTemplate(target); IntrospectionSupport.setProperties(jdbcTemplate, parameters, "template."); String elsqlName = remaining; String resUri = resourceUri; - String[] part = remaining.split("/"); + String[] part = remaining.split(":"); if (part.length == 2) { elsqlName = part[0]; resUri = part[1]; @@ -104,6 +104,27 @@ public class ElsqlComponent extends SqlComponent { return endpoint; } + @Override + protected void doStart() throws Exception { + super.doStart(); + + if (elSqlConfig == null) { + elSqlConfig = ElSqlConfig.DEFAULT; + } + } + + @Override + protected void doStop() throws Exception { + super.doStop(); + } + + public DataSource getDataSource() { + return dataSource; + } + + /** + * Sets the DataSource to use to communicate with the database. + */ public ElSqlConfig getElSqlConfig() { return elSqlConfig; } @@ -126,22 +147,4 @@ public class ElsqlComponent extends SqlComponent { this.resourceUri = resourceUri; } - /** - * Sets the DataSource to use to communicate with the database. - */ - @Override - public void setDataSource(DataSource dataSource) { - super.setDataSource(dataSource); - } - - /** - * Sets whether to use placeholder and replace all placeholder characters with ? sign in the SQL queries. - *

- * This option is default true - */ - @Override - public void setUsePlaceholder(boolean usePlaceholder) { - super.setUsePlaceholder(usePlaceholder); - } - } http://git-wip-us.apache.org/repos/asf/camel/blob/ed0f42a1/components/camel-elsql/src/main/java/org/apache/camel/component/elsql/ElsqlEndpoint.java ---------------------------------------------------------------------- diff --git a/components/camel-elsql/src/main/java/org/apache/camel/component/elsql/ElsqlEndpoint.java b/components/camel-elsql/src/main/java/org/apache/camel/component/elsql/ElsqlEndpoint.java index 8ef9845..9025d30 100644 --- a/components/camel-elsql/src/main/java/org/apache/camel/component/elsql/ElsqlEndpoint.java +++ b/components/camel-elsql/src/main/java/org/apache/camel/component/elsql/ElsqlEndpoint.java @@ -25,20 +25,19 @@ import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; import org.apache.camel.component.sql.SqlEndpoint; -import org.apache.camel.component.sql.SqlPrepareStatementStrategy; -import org.apache.camel.component.sql.SqlProcessingStrategy; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; import org.apache.camel.spi.UriPath; import org.apache.camel.util.ObjectHelper; import org.apache.camel.util.ResourceHelper; -import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; -@UriEndpoint(scheme = "elsql", title = "SQL", syntax = "elsql:elsqlName/resourceUri", consumerClass = ElsqlConsumer.class, label = "database,sql") +@UriEndpoint(scheme = "elsql", title = "SQL", syntax = "elsql:elsqlName:resourceUri", consumerClass = ElsqlConsumer.class, label = "database,sql") public class ElsqlEndpoint extends SqlEndpoint { private volatile ElSql elSql; + private NamedParameterJdbcTemplate jdbcTemplate; @UriPath @Metadata(required = "true") @@ -48,18 +47,21 @@ public class ElsqlEndpoint extends SqlEndpoint { @UriParam private ElSqlConfig elSqlConfig; - public ElsqlEndpoint(String uri, Component component, JdbcTemplate jdbcTemplate, String elsqlName, String resourceUri) { - super(uri, component, jdbcTemplate, null); + public ElsqlEndpoint(String uri, Component component, NamedParameterJdbcTemplate jdbcTemplate, String elsqlName, String resourceUri) { + super(uri, component, null, null); this.elsqlName = elsqlName; this.resourceUri = resourceUri; + this.jdbcTemplate = jdbcTemplate; } @Override public Consumer createConsumer(Processor processor) throws Exception { + // TODO: must be named + /* SqlProcessingStrategy proStrategy = new ElsqlSqlProcessingStrategy(elsqlName, elSql); SqlPrepareStatementStrategy preStategy = new ElsqlSqlPrepareStatementStrategy(); - ElsqlConsumer consumer = new ElsqlConsumer(this, processor, getJdbcTemplate(), elsqlName, preStategy, proStrategy); + ElsqlConsumer consumer = new ElsqlConsumer(this, processor, jdbcTemplate, elsqlName, preStategy, proStrategy); consumer.setMaxMessagesPerPoll(getMaxMessagesPerPoll()); consumer.setOnConsume(getOnConsume()); consumer.setOnConsumeFailed(getOnConsumeFailed()); @@ -70,11 +72,13 @@ public class ElsqlEndpoint extends SqlEndpoint { consumer.setRouteEmptyResultSet(isRouteEmptyResultSet()); configureConsumer(consumer); return consumer; + */ + return null; } @Override public Producer createProducer() throws Exception { - ElsqlProducer result = new ElsqlProducer(this, elSql, elsqlName, getJdbcTemplate()); + ElsqlProducer result = new ElsqlProducer(this, elSql, elsqlName, jdbcTemplate); return result; } @@ -86,7 +90,6 @@ public class ElsqlEndpoint extends SqlEndpoint { ObjectHelper.notNull(resourceUri, "resourceUri", this); URL url = ResourceHelper.resolveMandatoryResourceAsUrl(getCamelContext().getClassResolver(), resourceUri); - elSql = ElSql.parse(elSqlConfig, url); } http://git-wip-us.apache.org/repos/asf/camel/blob/ed0f42a1/components/camel-elsql/src/main/java/org/apache/camel/component/elsql/ElsqlProducer.java ---------------------------------------------------------------------- diff --git a/components/camel-elsql/src/main/java/org/apache/camel/component/elsql/ElsqlProducer.java b/components/camel-elsql/src/main/java/org/apache/camel/component/elsql/ElsqlProducer.java index 73925d3..fa3f5df 100644 --- a/components/camel-elsql/src/main/java/org/apache/camel/component/elsql/ElsqlProducer.java +++ b/components/camel-elsql/src/main/java/org/apache/camel/component/elsql/ElsqlProducer.java @@ -22,14 +22,16 @@ import java.sql.SQLException; import java.util.List; import com.opengamma.elsql.ElSql; +import com.opengamma.elsql.SpringSqlParams; import org.apache.camel.Exchange; import org.apache.camel.component.sql.SqlConstants; import org.apache.camel.component.sql.SqlEndpoint; import org.apache.camel.component.sql.SqlOutputType; import org.apache.camel.impl.DefaultProducer; import org.springframework.dao.DataAccessException; -import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.PreparedStatementCallback; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.core.namedparam.SqlParameterSource; import static org.springframework.jdbc.support.JdbcUtils.closeResultSet; @@ -37,9 +39,9 @@ public class ElsqlProducer extends DefaultProducer { private final ElSql elSql; private final String elSqlName; - private final JdbcTemplate jdbcTemplate; + private final NamedParameterJdbcTemplate jdbcTemplate; - public ElsqlProducer(SqlEndpoint endpoint, ElSql elSql, String elSqlName, JdbcTemplate jdbcTemplate) { + public ElsqlProducer(SqlEndpoint endpoint, ElSql elSql, String elSqlName, NamedParameterJdbcTemplate jdbcTemplate) { super(endpoint); this.elSql = elSql; this.elSqlName = elSqlName; @@ -55,19 +57,22 @@ public class ElsqlProducer extends DefaultProducer { public void process(final Exchange exchange) throws Exception { Object data = exchange.getIn().getBody(); - final String sql = elSql.getSql(elSqlName, new ElsqlSqlParams(exchange, data)); + final SqlParameterSource param = new ElsqlSqlMapSource(exchange, data); + final String sql = elSql.getSql(elSqlName, new SpringSqlParams(param)); + log.debug("ElSql @{} using sql: {}", elSqlName, sql); - jdbcTemplate.execute(sql, new PreparedStatementCallback() { + jdbcTemplate.execute(sql, param, new PreparedStatementCallback() { @Override public Object doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException { ResultSet rs = null; try { boolean isResultSet = ps.execute(); if (isResultSet) { + rs = ps.getResultSet(); + // preserve headers first, so we can override the SQL_ROW_COUNT header exchange.getOut().getHeaders().putAll(exchange.getIn().getHeaders()); - rs = ps.getResultSet(); SqlOutputType outputType = getEndpoint().getOutputType(); log.trace("Got result list from query: {}, outputType={}", rs, outputType); if (outputType == SqlOutputType.SelectList) { @@ -99,8 +104,6 @@ public class ElsqlProducer extends DefaultProducer { } else { throw new IllegalArgumentException("Invalid outputType=" + outputType); } - } else { - exchange.getIn().setHeader(SqlConstants.SQL_UPDATE_COUNT, ps.getUpdateCount()); } } finally { closeResultSet(rs); http://git-wip-us.apache.org/repos/asf/camel/blob/ed0f42a1/components/camel-elsql/src/main/java/org/apache/camel/component/elsql/ElsqlSqlMapSource.java ---------------------------------------------------------------------- diff --git a/components/camel-elsql/src/main/java/org/apache/camel/component/elsql/ElsqlSqlMapSource.java b/components/camel-elsql/src/main/java/org/apache/camel/component/elsql/ElsqlSqlMapSource.java new file mode 100644 index 0000000..e8035b0 --- /dev/null +++ b/components/camel-elsql/src/main/java/org/apache/camel/component/elsql/ElsqlSqlMapSource.java @@ -0,0 +1,54 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.elsql; + +import java.util.Collections; +import java.util.Map; + +import org.apache.camel.Exchange; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; + +public class ElsqlSqlMapSource extends MapSqlParameterSource { + + private final Exchange exchange; + private final Map bodyMap; + private final Map headersMap; + + public ElsqlSqlMapSource(Exchange exchange, Object body) { + this.exchange = exchange; + this.bodyMap = safeMap(exchange.getContext().getTypeConverter().tryConvertTo(Map.class, body)); + this.headersMap = safeMap(exchange.getIn().getHeaders()); + + addValue("body", body); + + for (Map.Entry entry : bodyMap.entrySet()) { + String name = entry.getKey().toString(); + Object value = entry.getValue(); + addValue(name, value); + } + for (Map.Entry entry : headersMap.entrySet()) { + String name = entry.getKey().toString(); + Object value = entry.getValue(); + addValue(name, value); + } + } + + private static Map safeMap(Map map) { + return (map == null || map.isEmpty()) ? Collections.emptyMap() : map; + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/ed0f42a1/components/camel-elsql/src/main/java/org/apache/camel/component/elsql/ElsqlSqlParams.java ---------------------------------------------------------------------- diff --git a/components/camel-elsql/src/main/java/org/apache/camel/component/elsql/ElsqlSqlParams.java b/components/camel-elsql/src/main/java/org/apache/camel/component/elsql/ElsqlSqlParams.java deleted file mode 100644 index 6822e8b..0000000 --- a/components/camel-elsql/src/main/java/org/apache/camel/component/elsql/ElsqlSqlParams.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.camel.component.elsql; - -import java.util.Collections; -import java.util.Map; - -import com.opengamma.elsql.SqlParams; -import org.apache.camel.Exchange; -import org.apache.camel.language.simple.SimpleLanguage; - -public class ElsqlSqlParams implements SqlParams { - - private final Exchange exchange; - private final Map bodyMap; - private final Map headersMap; - - public ElsqlSqlParams(Exchange exchange, Object body) { - this.exchange = exchange; - this.bodyMap = safeMap(exchange.getContext().getTypeConverter().tryConvertTo(Map.class, body)); - this.headersMap = safeMap(exchange.getIn().getHeaders()); - } - - private static Map safeMap(Map map) { - return (map == null || map.isEmpty()) ? Collections.emptyMap() : map; - } - - @Override - public boolean contains(String variable) { - if (variable.startsWith("${") && variable.endsWith("}")) { - return SimpleLanguage.expression(variable).evaluate(exchange, Object.class) != null; - } else if (bodyMap.containsKey(variable)) { - return true; - } else if (headersMap.containsKey(variable)) { - return true; - } - - return false; - } - - @Override - public Object get(String variable) { - if (variable.startsWith("${") && variable.endsWith("}")) { - return SimpleLanguage.expression(variable).evaluate(exchange, Object.class) != null; - } else if (bodyMap.containsKey(variable)) { - return bodyMap.get(variable); - } else if (headersMap.containsKey(variable)) { - return headersMap.get(variable); - } - - return null; - } - -} http://git-wip-us.apache.org/repos/asf/camel/blob/ed0f42a1/components/camel-elsql/src/main/java/org/apache/camel/component/elsql/ElsqlSqlProcessingStrategy.java ---------------------------------------------------------------------- diff --git a/components/camel-elsql/src/main/java/org/apache/camel/component/elsql/ElsqlSqlProcessingStrategy.java b/components/camel-elsql/src/main/java/org/apache/camel/component/elsql/ElsqlSqlProcessingStrategy.java index d22c33e..1134088 100644 --- a/components/camel-elsql/src/main/java/org/apache/camel/component/elsql/ElsqlSqlProcessingStrategy.java +++ b/components/camel-elsql/src/main/java/org/apache/camel/component/elsql/ElsqlSqlProcessingStrategy.java @@ -20,6 +20,7 @@ import java.sql.PreparedStatement; import java.sql.SQLException; import com.opengamma.elsql.ElSql; +import com.opengamma.elsql.SpringSqlParams; import org.apache.camel.Exchange; import org.apache.camel.component.sql.SqlEndpoint; import org.apache.camel.component.sql.SqlProcessingStrategy; @@ -28,6 +29,7 @@ import org.slf4j.LoggerFactory; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.PreparedStatementCallback; +import org.springframework.jdbc.core.namedparam.SqlParameterSource; public class ElsqlSqlProcessingStrategy implements SqlProcessingStrategy { @@ -42,7 +44,9 @@ public class ElsqlSqlProcessingStrategy implements SqlProcessingStrategy { @Override public int commit(final SqlEndpoint endpoint, final Exchange exchange, final Object data, final JdbcTemplate jdbcTemplate, final String query) throws Exception { - String sql = elSql.getSql(elSqlName, new ElsqlSqlParams(exchange, data)); + final SqlParameterSource param = new ElsqlSqlMapSource(exchange, data); + final String sql = elSql.getSql(elSqlName, new SpringSqlParams(param)); + LOG.debug("ElSql @{} using sql: {}", elSqlName, sql); return jdbcTemplate.execute(sql, new PreparedStatementCallback() { @Override http://git-wip-us.apache.org/repos/asf/camel/blob/ed0f42a1/components/camel-elsql/src/test/java/org/apache/camel/component/elsql/ElSqlDataSourceTest.java ---------------------------------------------------------------------- diff --git a/components/camel-elsql/src/test/java/org/apache/camel/component/elsql/ElSqlDataSourceTest.java b/components/camel-elsql/src/test/java/org/apache/camel/component/elsql/ElSqlDataSourceTest.java new file mode 100644 index 0000000..858daf4 --- /dev/null +++ b/components/camel-elsql/src/test/java/org/apache/camel/component/elsql/ElSqlDataSourceTest.java @@ -0,0 +1,85 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.elsql; + +import java.util.List; +import java.util.Map; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.impl.JndiRegistry; +import org.apache.camel.test.junit4.CamelTestSupport; +import org.junit.After; +import org.junit.Test; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; + +public class ElSqlDataSourceTest extends CamelTestSupport { + + private EmbeddedDatabase db; + + @Override + protected JndiRegistry createRegistry() throws Exception { + JndiRegistry jndi = super.createRegistry(); + + // this is the database we create with some initial data for our unit test + db = new EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.DERBY).addScript("sql/createAndPopulateDatabase.sql").build(); + + jndi.bind("dataSource", db); + + return jndi; + } + + @Test + public void testSimpleBody() throws Exception { + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedMessageCount(1); + + template.sendBody("direct:simple", "XXX"); + + mock.assertIsSatisfied(); + + // the result is a List + List received = assertIsInstanceOf(List.class, mock.getReceivedExchanges().get(0).getIn().getBody()); + + // and each row in the list is a Map + Map row = assertIsInstanceOf(Map.class, received.get(0)); + + // and we should be able the get the project from the map that should be Linux + assertEquals("Linux", row.get("PROJECT")); + } + + @After + public void tearDown() throws Exception { + super.tearDown(); + + db.shutdown(); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + public void configure() { + from("direct:simple") + .to("elsql:projects:elsql/projects.elsql?dataSource=dataSource") + .to("mock:result"); + } + }; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/ed0f42a1/components/camel-elsql/src/test/resources/elsql/projects.elsql ---------------------------------------------------------------------- diff --git a/components/camel-elsql/src/test/resources/elsql/projects.elsql b/components/camel-elsql/src/test/resources/elsql/projects.elsql new file mode 100644 index 0000000..75dfe51 --- /dev/null +++ b/components/camel-elsql/src/test/resources/elsql/projects.elsql @@ -0,0 +1,5 @@ +@NAME(projects) + SELECT * + FROM projects + WHERE license = :body + ORDER BY id http://git-wip-us.apache.org/repos/asf/camel/blob/ed0f42a1/components/camel-elsql/src/test/resources/log4j.properties ---------------------------------------------------------------------- diff --git a/components/camel-elsql/src/test/resources/log4j.properties b/components/camel-elsql/src/test/resources/log4j.properties new file mode 100755 index 0000000..d5af410 --- /dev/null +++ b/components/camel-elsql/src/test/resources/log4j.properties @@ -0,0 +1,39 @@ +## ------------------------------------------------------------------------ +## 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. +## ------------------------------------------------------------------------ + +# +# The logging properties used for testing +# +log4j.rootLogger=INFO, out + +#log4j.logger.org.apache.camel.component.sql=DEBUG +#log4j.logger.org.apache.camel.component.sql=TRACE +log4j.logger.org.apache.camel.component.elsql=DEBUG +#log4j.logger.org.apache.camel.component.elsql=TRACE + +# CONSOLE appender not used by default +log4j.appender.out=org.apache.log4j.ConsoleAppender +log4j.appender.out.layout=org.apache.log4j.PatternLayout +log4j.appender.out.layout.ConversionPattern=[%30.30t] %-30.30c{1} %-5p %m%n +#log4j.appender.out.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n + +# File appender +log4j.appender.file=org.apache.log4j.FileAppender +log4j.appender.file.layout=org.apache.log4j.PatternLayout +log4j.appender.file.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n +log4j.appender.file.file=target/camel-elsql-test.log +log4j.appender.file.append=true http://git-wip-us.apache.org/repos/asf/camel/blob/ed0f42a1/components/camel-elsql/src/test/resources/sql/createAndPopulateDatabase.sql ---------------------------------------------------------------------- diff --git a/components/camel-elsql/src/test/resources/sql/createAndPopulateDatabase.sql b/components/camel-elsql/src/test/resources/sql/createAndPopulateDatabase.sql new file mode 100644 index 0000000..65206c2 --- /dev/null +++ b/components/camel-elsql/src/test/resources/sql/createAndPopulateDatabase.sql @@ -0,0 +1,23 @@ +-- ------------------------------------------------------------------------ +-- 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. +-- ------------------------------------------------------------------------ + +-- START SNIPPET: e1 +create table projects (id integer primary key, project varchar(10), license varchar(5)); +insert into projects values (1, 'Camel', 'ASF'); +insert into projects values (2, 'AMQ', 'ASF'); +insert into projects values (3, 'Linux', 'XXX'); +-- END SNIPPET: e1 \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/ed0f42a1/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlComponent.java ---------------------------------------------------------------------- diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlComponent.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlComponent.java index 1d9ada5..7236392 100755 --- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlComponent.java +++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlComponent.java @@ -41,6 +41,10 @@ public class SqlComponent extends UriEndpointComponent { super(SqlEndpoint.class); } + public SqlComponent(Class endpointClass) { + super(endpointClass); + } + public SqlComponent(CamelContext context) { super(context, SqlEndpoint.class); } http://git-wip-us.apache.org/repos/asf/camel/blob/ed0f42a1/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlEndpoint.java ---------------------------------------------------------------------- diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlEndpoint.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlEndpoint.java index af0d4ad..761c125 100644 --- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlEndpoint.java +++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/SqlEndpoint.java @@ -49,52 +49,73 @@ import org.springframework.jdbc.core.RowMapperResultSetExtractor; public class SqlEndpoint extends DefaultPollingEndpoint { private JdbcTemplate jdbcTemplate; - @UriPath @Metadata(required = "true") + @UriPath(description = "Sets the SQL query to perform") @Metadata(required = "true") + private String query; - @UriParam + @UriParam(description = "Sets the reference to a DataSource to lookup from the registry, to use for communicating with the database.") @Deprecated private String dataSourceRef; - @UriParam + @UriParam(description = "Sets the DataSource to use to communicate with the database.") private DataSource dataSource; - @UriParam(label = "producer") + @UriParam(label = "producer", description = "Enables or disables batch mode") private boolean batch; - @UriParam(label = "consumer") + @UriParam(label = "consumer", description = "Sets the maximum number of messages to poll") private int maxMessagesPerPoll; - @UriParam(label = "consumer,advanced") + @UriParam(label = "consumer,advanced", + description = "Allows to plugin to use a custom org.apache.camel.component.sql.SqlProcessingStrategy to execute queries when the consumer has processed the rows/batch.") private SqlProcessingStrategy processingStrategy; - @UriParam(label = "advanced") + @UriParam(label = "advanced", + description = "Allows to plugin to use a custom org.apache.camel.component.sql.SqlPrepareStatementStrategy to control preparation of the query and prepared statement.") private SqlPrepareStatementStrategy prepareStatementStrategy; - @UriParam(label = "consumer") + @UriParam(label = "consumer", + description = "After processing each row then this query can be executed, if the Exchange was processed successfully, for example to mark the row as processed. The query can have parameter.") private String onConsume; - @UriParam(label = "consumer") + @UriParam(label = "consumer", + description = "After processing each row then this query can be executed, if the Exchange failed, for example to mark the row as failed. The query can have parameter.") private String onConsumeFailed; - @UriParam(label = "consumer") + @UriParam(label = "consumer", + description = "After processing the entire batch, this query can be executed to bulk update rows etc. The query cannot have parameters.") private String onConsumeBatchComplete; - @UriParam(label = "consumer", defaultValue = "true") + @UriParam(label = "consumer", defaultValue = "true", + description = "Sets how resultset should be delivered to route. Indicates delivery as either a list or individual object. defaults to true.") private boolean useIterator = true; - @UriParam(label = "consumer") + @UriParam(label = "consumer", + description = "Sets whether empty resultset should be allowed to be sent to the next hop. Defaults to false. So the empty resultset will be filtered out.") private boolean routeEmptyResultSet; - @UriParam(label = "consumer", defaultValue = "-1") + @UriParam(label = "consumer", defaultValue = "-1", description = "Sets an expected update count to validate when using onConsume.") private int expectedUpdateCount = -1; - @UriParam(label = "consumer") + @UriParam(label = "consumer", description = "Sets whether to break batch if onConsume failed.") private boolean breakBatchOnConsumeFail; - @UriParam(defaultValue = "true") + @UriParam(defaultValue = "true", description = "Whether to allow using named parameters in the queries.") private boolean allowNamedParameters = true; - @UriParam(label = "producer,advanced") + @UriParam(label = "producer,advanced", + description = "If enabled then the populateStatement method from org.apache.camel.component.sql.SqlPrepareStatementStrategy is always invoked, " + + "also if there is no expected parameters to be prepared. When this is false then the populateStatement is only invoked if there is 1" + + " or more expected parameters to be set; for example this avoids reading the message body/headers for SQL queries with no parameters.") private boolean alwaysPopulateStatement; - @UriParam(defaultValue = ",") + @UriParam(defaultValue = ",", + description = "The separator to use when parameter values is taken from message body (if the body is a String type), to be inserted at # placeholders." + + "Notice if you use named parameters, then a Map type is used instead. The default value is ,") private char separator = ','; - @UriParam(defaultValue = "SelectList") + @UriParam(defaultValue = "SelectList", description = "Make the output of consumer or producer to SelectList as List of Map, or SelectOne as single Java object in the following way:" + + "a) If the query has only single column, then that JDBC Column object is returned. (such as SELECT COUNT( * ) FROM PROJECT will return a Long object." + + "b) If the query has more than one column, then it will return a Map of that result." + + "c) If the outputClass is set, then it will convert the query result into an Java bean object by calling all the setters that match the column names." + + "It will assume your class has a default constructor to create instance with." + + "d) If the query resulted in more than one rows, it throws an non-unique result exception.") private SqlOutputType outputType = SqlOutputType.SelectList; - @UriParam + @UriParam(description = "Specify the full package and class name to use as conversion when outputType=SelectOne.") private String outputClass; - @UriParam(label = "producer,advanced") + @UriParam(label = "producer,advanced", description = "If set greater than zero, then Camel will use this count value of parameters to replace instead of" + + " querying via JDBC metadata API. This is useful if the JDBC vendor could not return correct parameters count, then user may override instead.") private int parametersCount; - @UriParam(label = "producer") + @UriParam(label = "producer", description = "If set, will ignore the results of the SQL query and use the existing IN message as the OUT message for the continuation of processing") private boolean noop; - @UriParam + @UriParam(description = "Store the query result in a header instead of the message body. By default, outputHeader == null and the query result is stored" + + " in the message body, any existing content in the message body is discarded. If outputHeader is set, the value is used as the name of the header" + + " to store the query result and the original message body is preserved.") private String outputHeader; - @UriParam(label = "producer") + @UriParam(label = "producer", description = "Whether to use the message body as the SQL and then headers for parameters. If this option is enabled then the SQL in the uri is not used.") private boolean useMessageBodyForSql; public SqlEndpoint() { @@ -372,9 +393,7 @@ public class SqlEndpoint extends DefaultPollingEndpoint { } /** - * Sets how resultset should be delivered to route. - * Indicates delivery as either a list or individual object. - * defaults to true. + * Sets how resultset should be delivered to route. Indicates delivery as either a list or individual object. defaults to true. */ public void setUseIterator(boolean useIterator) { this.useIterator = useIterator; @@ -386,7 +405,7 @@ public class SqlEndpoint extends DefaultPollingEndpoint { /** * Sets whether empty resultset should be allowed to be sent to the next hop. - * defaults to false. So the empty resultset will be filtered out. + * Defaults to false. So the empty resultset will be filtered out. */ public void setRouteEmptyResultSet(boolean routeEmptyResultSet) { this.routeEmptyResultSet = routeEmptyResultSet;