You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2013/09/18 15:29:20 UTC

[1/2] git commit: CAMEL-6368: Added support for outputClass to map to a bean like sql component can do.

Updated Branches:
  refs/heads/camel-2.12.x 606370284 -> edde4da81
  refs/heads/master a3e8b1bf8 -> 73184b220


CAMEL-6368: Added support for outputClass to map to a bean like sql component can do.


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

Branch: refs/heads/master
Commit: 73184b2200710cc85ddad57382a79f1568de2905
Parents: a3e8b1b
Author: Claus Ibsen <da...@apache.org>
Authored: Wed Sep 18 15:28:54 2013 +0200
Committer: Claus Ibsen <da...@apache.org>
Committed: Wed Sep 18 15:28:54 2013 +0200

----------------------------------------------------------------------
 .../camel/component/jdbc/BeanRowMapper.java     | 25 +++++++++
 .../component/jdbc/DefaultBeanRowMapper.java    | 54 ++++++++++++++++++++
 .../camel/component/jdbc/JdbcEndpoint.java      | 18 +++++++
 .../camel/component/jdbc/JdbcProducer.java      | 36 +++++++++++--
 .../camel/component/jdbc/CustomerModel.java     | 39 ++++++++++++++
 ...ducerOutputTypeSelectOneOutputClassTest.java | 51 ++++++++++++++++++
 .../JdbcProducerOutputTypeSelectOneTest.java    | 53 +++++++++++++++++++
 7 files changed, 271 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/73184b22/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/BeanRowMapper.java
----------------------------------------------------------------------
diff --git a/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/BeanRowMapper.java b/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/BeanRowMapper.java
new file mode 100644
index 0000000..e500f5e
--- /dev/null
+++ b/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/BeanRowMapper.java
@@ -0,0 +1,25 @@
+/**
+ * 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.jdbc;
+
+/**
+ * A mapper to map row names to java bean setter names, when using the <tt>outputClass</tt> option.
+ */
+public interface BeanRowMapper {
+
+    String map(String row, Object value);
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/73184b22/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/DefaultBeanRowMapper.java
----------------------------------------------------------------------
diff --git a/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/DefaultBeanRowMapper.java b/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/DefaultBeanRowMapper.java
new file mode 100644
index 0000000..0416573
--- /dev/null
+++ b/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/DefaultBeanRowMapper.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.jdbc;
+
+/**
+ * The default {@link BeanRowMapper} will map row names to lower case names,
+ * but use a single upper case letter after underscores or dashes (which is skipped).
+ * <p/>
+ * For example <tt>CUST_ID</tt> is mapped as <tt>custId</tt>.
+ */
+public class DefaultBeanRowMapper implements BeanRowMapper {
+
+    @Override
+    public String map(String row, Object value) {
+        // convert to lover case, and underscore as new upper case name;
+        return mapRowName(row);
+    }
+
+    protected String mapRowName(String row) {
+        StringBuilder sb = new StringBuilder();
+        boolean toUpper = false;
+        for (char ch : row.toCharArray()) {
+            if (ch == '_' || ch == '-') {
+                toUpper = true;
+                continue;
+            }
+            if (toUpper) {
+                char upper = Character.toLowerCase(ch);
+                sb.append(upper);
+                // reset flag
+                toUpper = false;
+            } else {
+                char lower = Character.toLowerCase(ch);
+                sb.append(lower);
+            }
+        }
+        return sb.toString();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/73184b22/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcEndpoint.java
----------------------------------------------------------------------
diff --git a/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcEndpoint.java b/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcEndpoint.java
index 9751aa2..f743928 100755
--- a/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcEndpoint.java
+++ b/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcEndpoint.java
@@ -40,6 +40,8 @@ public class JdbcEndpoint extends DefaultEndpoint {
     private boolean allowNamedParameters = true;
     private boolean useHeadersAsParameters;
     private JdbcOutputType outputType = JdbcOutputType.SelectList;
+    private String outputClass;
+    private BeanRowMapper beanRowMapper = new DefaultBeanRowMapper();
 
     public JdbcEndpoint() {
     }
@@ -160,6 +162,22 @@ public class JdbcEndpoint extends DefaultEndpoint {
         this.outputType = outputType;
     }
 
+    public String getOutputClass() {
+        return outputClass;
+    }
+
+    public void setOutputClass(String outputClass) {
+        this.outputClass = outputClass;
+    }
+
+    public BeanRowMapper getBeanRowMapper() {
+        return beanRowMapper;
+    }
+
+    public void setBeanRowMapper(BeanRowMapper beanRowMapper) {
+        this.beanRowMapper = beanRowMapper;
+    }
+
     @Override
     protected String createEndpointUri() {
         return "jdbc";

http://git-wip-us.apache.org/repos/asf/camel/blob/73184b22/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcProducer.java
----------------------------------------------------------------------
diff --git a/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcProducer.java b/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcProducer.java
index 6c35d83..d573587 100644
--- a/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcProducer.java
+++ b/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcProducer.java
@@ -331,12 +331,38 @@ public class JdbcProducer extends DefaultProducer {
         if (data.size() > 1) {
             throw new SQLDataException("Query result not unique for outputType=SelectOne. Got " + data.size() + " count instead.");
         } else if (data.size() == 1) {
-            // Set content depend on number of column from query result
-            Map<String, Object> row = data.get(0);
-            if (row.size() == 1) {
-                result = row.values().iterator().next();
+            if (getEndpoint().getOutputClass() == null) {
+                // Set content depend on number of column from query result
+                Map<String, Object> row = data.get(0);
+                if (row.size() == 1) {
+                    result = row.values().iterator().next();
+                } else {
+                    result = row;
+                }
             } else {
-                result = row;
+                Class<?> outputClzz = getEndpoint().getCamelContext().getClassResolver().resolveClass(getEndpoint().getOutputClass());
+                Object answer = getEndpoint().getCamelContext().getInjector().newInstance(outputClzz);
+
+                Map<String, Object> row = data.get(0);
+                Map<String, Object> properties = new LinkedHashMap<String, Object>(data.size());
+
+                // map row names using the bean row mapper
+                for (Map.Entry<String, Object> entry : row.entrySet()) {
+                    Object value = entry.getValue();
+                    String name = getEndpoint().getBeanRowMapper().map(entry.getKey(), value);
+                    properties.put(name, value);
+                }
+                try {
+                    IntrospectionSupport.setProperties(answer, properties);
+                } catch (Exception e) {
+                    throw new SQLException("Error setting properties on output class " + outputClzz, e);
+                }
+
+                // check we could map all properties to the bean
+                if (!properties.isEmpty()) {
+                    throw new IllegalArgumentException("Cannot map all properties to bean of type " + outputClzz + ". There are " + properties.size() + " unmapped properties. " + properties);
+                }
+                return answer;
             }
         }
 

http://git-wip-us.apache.org/repos/asf/camel/blob/73184b22/components/camel-jdbc/src/test/java/org/apache/camel/component/jdbc/CustomerModel.java
----------------------------------------------------------------------
diff --git a/components/camel-jdbc/src/test/java/org/apache/camel/component/jdbc/CustomerModel.java b/components/camel-jdbc/src/test/java/org/apache/camel/component/jdbc/CustomerModel.java
new file mode 100644
index 0000000..cef82f4
--- /dev/null
+++ b/components/camel-jdbc/src/test/java/org/apache/camel/component/jdbc/CustomerModel.java
@@ -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.
+ */
+package org.apache.camel.component.jdbc;
+
+public class CustomerModel {
+
+    private String id;
+    private String name;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/73184b22/components/camel-jdbc/src/test/java/org/apache/camel/component/jdbc/JdbcProducerOutputTypeSelectOneOutputClassTest.java
----------------------------------------------------------------------
diff --git a/components/camel-jdbc/src/test/java/org/apache/camel/component/jdbc/JdbcProducerOutputTypeSelectOneOutputClassTest.java b/components/camel-jdbc/src/test/java/org/apache/camel/component/jdbc/JdbcProducerOutputTypeSelectOneOutputClassTest.java
new file mode 100644
index 0000000..ba75b63
--- /dev/null
+++ b/components/camel-jdbc/src/test/java/org/apache/camel/component/jdbc/JdbcProducerOutputTypeSelectOneOutputClassTest.java
@@ -0,0 +1,51 @@
+/**
+ * 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.jdbc;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.Test;
+
+public class JdbcProducerOutputTypeSelectOneOutputClassTest extends AbstractJdbcTestSupport {
+
+    @EndpointInject(uri = "mock:result")
+    private MockEndpoint mock;
+
+    @SuppressWarnings({"unchecked"})
+    @Test
+    public void testOutputTypeSelectOneOutputClass() throws Exception {
+        mock.expectedMessageCount(1);
+
+        template.sendBody("direct:start", "select * from customer where ID = 'cust1'");
+
+        assertMockEndpointsSatisfied();
+
+        CustomerModel model = assertIsInstanceOf(CustomerModel.class, mock.getReceivedExchanges().get(0).getIn().getBody(CustomerModel.class));
+        assertEquals("cust1", model.getId());
+        assertEquals("jstrachan", model.getName());
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() throws Exception {
+                from("direct:start").to("jdbc:testdb?outputType=SelectOne&outputClass=org.apache.camel.component.jdbc.CustomerModel").to("mock:result");
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/73184b22/components/camel-jdbc/src/test/java/org/apache/camel/component/jdbc/JdbcProducerOutputTypeSelectOneTest.java
----------------------------------------------------------------------
diff --git a/components/camel-jdbc/src/test/java/org/apache/camel/component/jdbc/JdbcProducerOutputTypeSelectOneTest.java b/components/camel-jdbc/src/test/java/org/apache/camel/component/jdbc/JdbcProducerOutputTypeSelectOneTest.java
new file mode 100644
index 0000000..345de0b
--- /dev/null
+++ b/components/camel-jdbc/src/test/java/org/apache/camel/component/jdbc/JdbcProducerOutputTypeSelectOneTest.java
@@ -0,0 +1,53 @@
+/**
+ * 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.jdbc;
+
+import java.util.Map;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.Test;
+
+public class JdbcProducerOutputTypeSelectOneTest extends AbstractJdbcTestSupport {
+
+    @EndpointInject(uri = "mock:result")
+    private MockEndpoint mock;
+
+    @SuppressWarnings({"unchecked"})
+    @Test
+    public void testOutputTypeSelectOne() throws Exception {
+        mock.expectedMessageCount(1);
+
+        template.sendBody("direct:start", "select * from customer where ID = 'cust1'");
+
+        assertMockEndpointsSatisfied();
+
+        Map row = assertIsInstanceOf(Map.class, mock.getReceivedExchanges().get(0).getIn().getBody(Map.class));
+        assertEquals("cust1", row.get("ID"));
+        assertEquals("jstrachan", row.get("NAME"));
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() throws Exception {
+                from("direct:start").to("jdbc:testdb?outputType=SelectOne").to("mock:result");
+            }
+        };
+    }
+}


[2/2] git commit: CAMEL-6368: Added support for outputClass to map to a bean like sql component can do.

Posted by da...@apache.org.
CAMEL-6368: Added support for outputClass to map to a bean like sql component can do.


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

Branch: refs/heads/camel-2.12.x
Commit: edde4da817bcab6889f2a636f81e5bf591883af5
Parents: 6063702
Author: Claus Ibsen <da...@apache.org>
Authored: Wed Sep 18 15:28:54 2013 +0200
Committer: Claus Ibsen <da...@apache.org>
Committed: Wed Sep 18 15:29:08 2013 +0200

----------------------------------------------------------------------
 .../camel/component/jdbc/BeanRowMapper.java     | 25 +++++++++
 .../component/jdbc/DefaultBeanRowMapper.java    | 54 ++++++++++++++++++++
 .../camel/component/jdbc/JdbcEndpoint.java      | 18 +++++++
 .../camel/component/jdbc/JdbcProducer.java      | 36 +++++++++++--
 .../camel/component/jdbc/CustomerModel.java     | 39 ++++++++++++++
 ...ducerOutputTypeSelectOneOutputClassTest.java | 51 ++++++++++++++++++
 .../JdbcProducerOutputTypeSelectOneTest.java    | 53 +++++++++++++++++++
 7 files changed, 271 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/edde4da8/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/BeanRowMapper.java
----------------------------------------------------------------------
diff --git a/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/BeanRowMapper.java b/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/BeanRowMapper.java
new file mode 100644
index 0000000..e500f5e
--- /dev/null
+++ b/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/BeanRowMapper.java
@@ -0,0 +1,25 @@
+/**
+ * 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.jdbc;
+
+/**
+ * A mapper to map row names to java bean setter names, when using the <tt>outputClass</tt> option.
+ */
+public interface BeanRowMapper {
+
+    String map(String row, Object value);
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/edde4da8/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/DefaultBeanRowMapper.java
----------------------------------------------------------------------
diff --git a/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/DefaultBeanRowMapper.java b/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/DefaultBeanRowMapper.java
new file mode 100644
index 0000000..0416573
--- /dev/null
+++ b/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/DefaultBeanRowMapper.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.jdbc;
+
+/**
+ * The default {@link BeanRowMapper} will map row names to lower case names,
+ * but use a single upper case letter after underscores or dashes (which is skipped).
+ * <p/>
+ * For example <tt>CUST_ID</tt> is mapped as <tt>custId</tt>.
+ */
+public class DefaultBeanRowMapper implements BeanRowMapper {
+
+    @Override
+    public String map(String row, Object value) {
+        // convert to lover case, and underscore as new upper case name;
+        return mapRowName(row);
+    }
+
+    protected String mapRowName(String row) {
+        StringBuilder sb = new StringBuilder();
+        boolean toUpper = false;
+        for (char ch : row.toCharArray()) {
+            if (ch == '_' || ch == '-') {
+                toUpper = true;
+                continue;
+            }
+            if (toUpper) {
+                char upper = Character.toLowerCase(ch);
+                sb.append(upper);
+                // reset flag
+                toUpper = false;
+            } else {
+                char lower = Character.toLowerCase(ch);
+                sb.append(lower);
+            }
+        }
+        return sb.toString();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/edde4da8/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcEndpoint.java
----------------------------------------------------------------------
diff --git a/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcEndpoint.java b/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcEndpoint.java
index 9751aa2..f743928 100755
--- a/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcEndpoint.java
+++ b/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcEndpoint.java
@@ -40,6 +40,8 @@ public class JdbcEndpoint extends DefaultEndpoint {
     private boolean allowNamedParameters = true;
     private boolean useHeadersAsParameters;
     private JdbcOutputType outputType = JdbcOutputType.SelectList;
+    private String outputClass;
+    private BeanRowMapper beanRowMapper = new DefaultBeanRowMapper();
 
     public JdbcEndpoint() {
     }
@@ -160,6 +162,22 @@ public class JdbcEndpoint extends DefaultEndpoint {
         this.outputType = outputType;
     }
 
+    public String getOutputClass() {
+        return outputClass;
+    }
+
+    public void setOutputClass(String outputClass) {
+        this.outputClass = outputClass;
+    }
+
+    public BeanRowMapper getBeanRowMapper() {
+        return beanRowMapper;
+    }
+
+    public void setBeanRowMapper(BeanRowMapper beanRowMapper) {
+        this.beanRowMapper = beanRowMapper;
+    }
+
     @Override
     protected String createEndpointUri() {
         return "jdbc";

http://git-wip-us.apache.org/repos/asf/camel/blob/edde4da8/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcProducer.java
----------------------------------------------------------------------
diff --git a/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcProducer.java b/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcProducer.java
index 6c35d83..d573587 100644
--- a/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcProducer.java
+++ b/components/camel-jdbc/src/main/java/org/apache/camel/component/jdbc/JdbcProducer.java
@@ -331,12 +331,38 @@ public class JdbcProducer extends DefaultProducer {
         if (data.size() > 1) {
             throw new SQLDataException("Query result not unique for outputType=SelectOne. Got " + data.size() + " count instead.");
         } else if (data.size() == 1) {
-            // Set content depend on number of column from query result
-            Map<String, Object> row = data.get(0);
-            if (row.size() == 1) {
-                result = row.values().iterator().next();
+            if (getEndpoint().getOutputClass() == null) {
+                // Set content depend on number of column from query result
+                Map<String, Object> row = data.get(0);
+                if (row.size() == 1) {
+                    result = row.values().iterator().next();
+                } else {
+                    result = row;
+                }
             } else {
-                result = row;
+                Class<?> outputClzz = getEndpoint().getCamelContext().getClassResolver().resolveClass(getEndpoint().getOutputClass());
+                Object answer = getEndpoint().getCamelContext().getInjector().newInstance(outputClzz);
+
+                Map<String, Object> row = data.get(0);
+                Map<String, Object> properties = new LinkedHashMap<String, Object>(data.size());
+
+                // map row names using the bean row mapper
+                for (Map.Entry<String, Object> entry : row.entrySet()) {
+                    Object value = entry.getValue();
+                    String name = getEndpoint().getBeanRowMapper().map(entry.getKey(), value);
+                    properties.put(name, value);
+                }
+                try {
+                    IntrospectionSupport.setProperties(answer, properties);
+                } catch (Exception e) {
+                    throw new SQLException("Error setting properties on output class " + outputClzz, e);
+                }
+
+                // check we could map all properties to the bean
+                if (!properties.isEmpty()) {
+                    throw new IllegalArgumentException("Cannot map all properties to bean of type " + outputClzz + ". There are " + properties.size() + " unmapped properties. " + properties);
+                }
+                return answer;
             }
         }
 

http://git-wip-us.apache.org/repos/asf/camel/blob/edde4da8/components/camel-jdbc/src/test/java/org/apache/camel/component/jdbc/CustomerModel.java
----------------------------------------------------------------------
diff --git a/components/camel-jdbc/src/test/java/org/apache/camel/component/jdbc/CustomerModel.java b/components/camel-jdbc/src/test/java/org/apache/camel/component/jdbc/CustomerModel.java
new file mode 100644
index 0000000..cef82f4
--- /dev/null
+++ b/components/camel-jdbc/src/test/java/org/apache/camel/component/jdbc/CustomerModel.java
@@ -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.
+ */
+package org.apache.camel.component.jdbc;
+
+public class CustomerModel {
+
+    private String id;
+    private String name;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/edde4da8/components/camel-jdbc/src/test/java/org/apache/camel/component/jdbc/JdbcProducerOutputTypeSelectOneOutputClassTest.java
----------------------------------------------------------------------
diff --git a/components/camel-jdbc/src/test/java/org/apache/camel/component/jdbc/JdbcProducerOutputTypeSelectOneOutputClassTest.java b/components/camel-jdbc/src/test/java/org/apache/camel/component/jdbc/JdbcProducerOutputTypeSelectOneOutputClassTest.java
new file mode 100644
index 0000000..ba75b63
--- /dev/null
+++ b/components/camel-jdbc/src/test/java/org/apache/camel/component/jdbc/JdbcProducerOutputTypeSelectOneOutputClassTest.java
@@ -0,0 +1,51 @@
+/**
+ * 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.jdbc;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.Test;
+
+public class JdbcProducerOutputTypeSelectOneOutputClassTest extends AbstractJdbcTestSupport {
+
+    @EndpointInject(uri = "mock:result")
+    private MockEndpoint mock;
+
+    @SuppressWarnings({"unchecked"})
+    @Test
+    public void testOutputTypeSelectOneOutputClass() throws Exception {
+        mock.expectedMessageCount(1);
+
+        template.sendBody("direct:start", "select * from customer where ID = 'cust1'");
+
+        assertMockEndpointsSatisfied();
+
+        CustomerModel model = assertIsInstanceOf(CustomerModel.class, mock.getReceivedExchanges().get(0).getIn().getBody(CustomerModel.class));
+        assertEquals("cust1", model.getId());
+        assertEquals("jstrachan", model.getName());
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() throws Exception {
+                from("direct:start").to("jdbc:testdb?outputType=SelectOne&outputClass=org.apache.camel.component.jdbc.CustomerModel").to("mock:result");
+            }
+        };
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/edde4da8/components/camel-jdbc/src/test/java/org/apache/camel/component/jdbc/JdbcProducerOutputTypeSelectOneTest.java
----------------------------------------------------------------------
diff --git a/components/camel-jdbc/src/test/java/org/apache/camel/component/jdbc/JdbcProducerOutputTypeSelectOneTest.java b/components/camel-jdbc/src/test/java/org/apache/camel/component/jdbc/JdbcProducerOutputTypeSelectOneTest.java
new file mode 100644
index 0000000..345de0b
--- /dev/null
+++ b/components/camel-jdbc/src/test/java/org/apache/camel/component/jdbc/JdbcProducerOutputTypeSelectOneTest.java
@@ -0,0 +1,53 @@
+/**
+ * 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.jdbc;
+
+import java.util.Map;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.Test;
+
+public class JdbcProducerOutputTypeSelectOneTest extends AbstractJdbcTestSupport {
+
+    @EndpointInject(uri = "mock:result")
+    private MockEndpoint mock;
+
+    @SuppressWarnings({"unchecked"})
+    @Test
+    public void testOutputTypeSelectOne() throws Exception {
+        mock.expectedMessageCount(1);
+
+        template.sendBody("direct:start", "select * from customer where ID = 'cust1'");
+
+        assertMockEndpointsSatisfied();
+
+        Map row = assertIsInstanceOf(Map.class, mock.getReceivedExchanges().get(0).getIn().getBody(Map.class));
+        assertEquals("cust1", row.get("ID"));
+        assertEquals("jstrachan", row.get("NAME"));
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            public void configure() throws Exception {
+                from("direct:start").to("jdbc:testdb?outputType=SelectOne").to("mock:result");
+            }
+        };
+    }
+}