Camel SQL Stored Component is used to call stored procedures.
As a developer, You have to write only a mapper class to transform input/output parameters to your pojo class.
In this example, we will see how to use this component to call stored procedures using an embedded derby database.
Step 1: DataSource Setup
CREATE TABLE books (
BookId VARCHAR(10) NOT NULL,
BookName VARCHAR(100) NOT NULL,
author VARCHAR(50) NOT NULL,
price VARCHAR(20),
CreateDate VARCHAR(50) NOT NULL
);
// Inserting two books data
INSERT INTO books(BookId, BookName, Author, Price, CreateDate) VALUES
('FICT3', 'The Ruins', 'Scott Smith', '$9', 'July 18, 2006');
INSERT INTO books(BookId, BookName, Author, Price, CreateDate) VALUES
('FICT4', 'Velocity', 'Dean Koontz', '$11', 'July 20, 2006');
// Stored procedure to fetch all books
CREATE PROCEDURE GET_ALL_BOOKS() PARAMETER STYLE JAVA LANGUAGE JAVA MODIFIES SQL DATA DYNAMIC RESULT SETS 1 EXTERNAL NAME 'com.kswaughs.db.util.BookStoredProcedure.findAllBooks';
// Stored procedure to fetch requested book
CREATE PROCEDURE GET_BOOK(IN book_name VARCHAR(100)) PARAMETER STYLE JAVA LANGUAGE JAVA MODIFIES SQL DATA DYNAMIC RESULT SETS 1 EXTERNAL NAME 'com.kswaughs.db.util.BookStoredProcedure.findBook';
Stored procedure implementation class is BookStoredProcedure. This is Apache Derby's way of implementation, purely written in Java. This has nothing to do with camel.
package com.kswaughs.db.util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.support.JdbcUtils;
public class BookStoredProcedure {
/**
* Derby Stored Procedure implementation to read all books
* @param bookResults
* @throws SQLException
*/
public static void findAllBooks(ResultSet[] bookResults)
throws SQLException {
Connection connection = null;
PreparedStatement statement = null;
try {
connection = DriverManager.getConnection("jdbc:default:connection");
String sql = "select * from books";
statement = connection.prepareStatement(sql);
bookResults[0] = statement.executeQuery();
} finally {
JdbcUtils.closeConnection(connection);
}
}
/**
* Derby Stored Procedure implementation to read requested book
* @param bookResults
* @throws SQLException
*/
public static void findBook(String book_name, ResultSet[] bookResults)
throws SQLException {
Connection connection = null;
PreparedStatement statement = null;
try {
connection = DriverManager.getConnection("jdbc:default:connection");
String query = "select * from books where BookName = ?";
statement = connection.prepareStatement(query);
statement.setString(1, book_name);
bookResults[0] = statement.executeQuery();
} finally {
JdbcUtils.closeConnection(connection);
}
}
}
Step 2: Application Context Configuration
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cxf="http://camel.apache.org/schema/cxf"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/cxf
http://camel.apache.org/schema/cxf/camel-cxf.xsd
http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd ">
<!-- this is the JDBC data source which uses an in-memory only Apache Derby database -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="org.apache.derby.jdbc.EmbeddedDriver" />
<property name="url" value="jdbc:derby:memory:orders;create=true" />
<property name="username" value="" />
<property name="password" value="" />
</bean>
<jdbc:initialize-database data-source="dataSource" enabled="true">
<jdbc:script location="classpath:db-schema.sql" />
</jdbc:initialize-database>
<!-- configure the Camel SQL Stored component to use the JDBC data source -->
<bean id="sqlStored" class="org.apache.camel.component.sql.stored.SqlStoredComponent">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="bookMapper" class="com.kswaughs.db.util.BookMapper" />
<bean id="bookRouter" class="com.kswaughs.router.BookRouter" />
<camelContext id="bookCtx" xmlns="http://camel.apache.org/schema/spring">
<routeBuilder ref="bookRouter" />
</camelContext>
</beans>
Step 3: Define Routers for calling two stored procedures using Java DSL
package com.kswaughs.router;
import org.apache.camel.builder.RouteBuilder;
public class BookRouter extends RouteBuilder {
@Override
public void configure() throws Exception {
from("direct:sp")
.to("sqlStored:GET_ALL_BOOKS()")
.bean("bookMapper", "readAllBooks")
.log("${body}");
from("direct:sp-getbook")
.bean("bookMapper", "buildReqMap")
.to("sqlStored:GET_BOOK(VARCHAR :#BookName)")
.bean("bookMapper", "readAllBooks")
.log("${body}");
}
}
Step 4: Create POJO class & Row mapper class
package com.kswaughs.beans;
public class Book {
private String bookId;
private String bookName;
private String author;
private String price;
private String createDate;
public String getBookId() {
return bookId;
}
public void setBookId(String bookId) {
this.bookId = bookId;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getCreateDate() {
return createDate;
}
public void setCreateDate(String createDate) {
this.createDate = createDate;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Book [bookId=");
builder.append(bookId);
builder.append(", bookName=");
builder.append(bookName);
builder.append(", author=");
builder.append(author);
builder.append(", price=");
builder.append(price);
builder.append(", createDate=");
builder.append(createDate);
builder.append("]");
return builder.toString();
}
}
package com.kswaughs.db.util;
import com.kswaughs.beans.Book;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class BookMapper {
/**
* Transforms input request to request map
* @param bookName
* @return
*/
public Map<String, Object> buildReqMap(String bookName) {
Map<String, Object> answer = new HashMap<String, Object>();
answer.put("BookName", bookName);
return answer;
}
/**
* Transforms Resultsets into List of Books objects
* @param resultSets
* @return
* @throws Exception
*/
public List<Book> readAllBooks(Map<String, List<Map<String, String>>> resultSets)
throws Exception {
List<Book> books = new ArrayList<Book>();
System.out.println("resultSets:"+resultSets);
Set<String> keys = resultSets.keySet();
for (String key : keys) {
List<Map<String, String>> rsts = resultSets.get(key);
for (Map<String, String> rst: rsts) {
Book book = new Book();
book.setBookId(rst.get("BookId"));
book.setBookName(rst.get("BookName"));
book.setAuthor(rst.get("Author"));
book.setPrice(rst.get("Price"));
book.setCreateDate(rst.get("CreateDate"));
books.add(book);
}
}
return books;
}
}
Step 5: Test the application
package com.kswaughs.app;
import com.kswaughs.beans.Book;
import java.util.Date;
import java.util.List;
import org.apache.camel.CamelContext;
import org.apache.camel.ProducerTemplate;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.kswaughs.db.util.Book;
public class CamelBookApp {
public static void main(String[] args) {
try {
ApplicationContext springCtx = new ClassPathXmlApplicationContext(
"database-context.xml");
CamelContext context = springCtx.getBean("bookCtx", CamelContext.class);
context.start();
ProducerTemplate producerTemplate = context.createProducerTemplate();
// Fetch all books
List<Book> resp = producerTemplate.requestBody("direct:sp", null, List.class);
System.out.println("SP resp:"+resp);
// Fetch book by name
List<Book> resp1 = producerTemplate
.requestBody("direct:sp-getbook", "Velocity", List.class);
System.out.println("SP resp1:"+resp1);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Console Logs
resultSets:{#result-set-1=[{BOOKID=FICT3, BOOKNAME=The Ruins, AUTHOR=Scott Smith, PRICE=$9, CREATEDATE=July 18, 2006}, {BOOKID=FICT4, BOOKNAME=Velocity, AUTHOR=Dean Koontz, PRICE=$11, CREATEDATE=July 20, 2006}]}
INFO|09/13/2016 11:39:18 980|[Book [bookId=FICT3, bookName=The Ruins, author=Scott Smith, price=$9, createDate=July 18, 2006], Book [bookId=FICT4, bookName=Velocity, author=Dean Koontz, price=$11, createDate=July 20, 2006]]
SP resp:[Book [bookId=FICT3, bookName=The Ruins, author=Scott Smith, price=$9, createDate=July 18, 2006], Book [bookId=FICT4, bookName=Velocity, author=Dean Koontz, price=$11, createDate=July 20, 2006]]
resultSets:{#result-set-1=[{BOOKID=FICT4, BOOKNAME=Velocity, AUTHOR=Dean Koontz, PRICE=$11, CREATEDATE=July 20, 2006}]}
INFO|09/13/2016 11:39:19 000|[Book [bookId=FICT4, bookName=Velocity, author=Dean Koontz, price=$11, createDate=July 20, 2006]]
SP resp1:[Book [bookId=FICT4, bookName=Velocity, author=Dean Koontz, price=$11, createDate=July 20, 2006]]
Maven dependencies
<properties>
<spring.version>4.1.6.RELEASE</spring.version>
<camelspring.version>2.16.0</camelspring.version>
</properties>
<dependencies>
<!-- Camel Dependencies -->
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
<version>${camelspring.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-cxf</artifactId>
<version>${camelspring.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring</artifactId>
<version>${camelspring.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-sql</artifactId>
<version>2.17.1</version>
</dependency>
<!-- End of Camel Dependencies -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>commons-pool</groupId>
<artifactId>commons-pool</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<version>10.11.1.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
Related Links