From 3abdd61dc2af68e4c57003aa9adee5bfb2feb15c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rinaldo=20Pitzer=20J=C3=BAnior?=
<16694899+rinaldodev@users.noreply.github.com>
Date: Thu, 8 Aug 2024 13:54:20 -0300
Subject: [PATCH 1/5] add tomcat-jdbc example (#136)
---
tomcat-jdbc/pom.xml | 150 ++++++++++++++++++
tomcat-jdbc/readme.adoc | 58 +++++++
.../src/main/java/sample/camel/MyBean.java | 40 +++++
.../java/sample/camel/MyCamelApplication.java | 50 ++++++
.../main/java/sample/camel/MyCamelRouter.java | 59 +++++++
.../src/main/resources/application.properties | 51 ++++++
tomcat-jdbc/src/main/resources/schema.sql | 5 +
.../camel/MyCamelApplicationJUnit5Test.java | 71 +++++++++
8 files changed, 484 insertions(+)
create mode 100644 tomcat-jdbc/pom.xml
create mode 100644 tomcat-jdbc/readme.adoc
create mode 100644 tomcat-jdbc/src/main/java/sample/camel/MyBean.java
create mode 100644 tomcat-jdbc/src/main/java/sample/camel/MyCamelApplication.java
create mode 100644 tomcat-jdbc/src/main/java/sample/camel/MyCamelRouter.java
create mode 100644 tomcat-jdbc/src/main/resources/application.properties
create mode 100644 tomcat-jdbc/src/main/resources/schema.sql
create mode 100644 tomcat-jdbc/src/test/java/sample/camel/MyCamelApplicationJUnit5Test.java
diff --git a/tomcat-jdbc/pom.xml b/tomcat-jdbc/pom.xml
new file mode 100644
index 000000000..03ad5be73
--- /dev/null
+++ b/tomcat-jdbc/pom.xml
@@ -0,0 +1,150 @@
+
+
+
+
+ 4.0.0
+
+
+ org.apache.camel.springboot.example
+ examples
+ 4.7.0-SNAPSHOT
+
+
+ camel-example-spring-boot
+ Camel SB Examples :: Tomcat JDBC
+ An example showing how to deploy a Camel Spring Boot application in Tomcat using its JDBC Data Source
+ war
+
+
+ Beginner
+
+ UTF-8
+ UTF-8
+
+
+
+
+
+
+ org.apache.camel.springboot
+ camel-spring-boot-bom
+ ${camel-version}
+ pom
+ import
+
+
+
+ org.springframework.boot
+ spring-boot-dependencies
+ ${spring-boot-version}
+ pom
+ import
+
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+
+ com.zaxxer
+ HikariCP
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-tomcat
+ provided
+
+
+ org.apache.tomcat
+ tomcat-jdbc
+ provided
+
+
+
+
+ org.postgresql
+ postgresql
+
+
+
+
+ org.apache.camel.springboot
+ camel-spring-boot-starter
+
+
+ org.apache.camel.springboot
+ camel-spring-jdbc-starter
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.apache.camel
+ camel-test-spring-junit5
+ test
+
+
+ com.h2database
+ h2
+ test
+
+
+
+
+ ${artifactId}
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ ${spring-boot-version}
+
+
+
+ repackage
+
+
+
+
+
+
+
diff --git a/tomcat-jdbc/readme.adoc b/tomcat-jdbc/readme.adoc
new file mode 100644
index 000000000..1d6b9b663
--- /dev/null
+++ b/tomcat-jdbc/readme.adoc
@@ -0,0 +1,58 @@
+== Camel Spring Boot example with Tomcat and database connection
+
+This example shows how to work with a simple Apache Camel Spring Boot application deploying to Tomcat and using its JDBC data source.
+
+The example generates 2 routes:
+
+. The first route is triggered by a timer and writes messages to the database.
+. The second route is triggered by a timer and read the COUNT of messages from the database.
+
+=== Classes
+
+* `MyCamelRouter`: where the camel routes are defined
+* `MyBean`: used to generate a simple message with a counter
+* `MyCamelApplication`: the Spring Boot servlet initializer
+
+=== How to deploy
+
+. Run the database container
+[source,console]
+podman run --rm --name db -e POSTGRES_PASSWORD=password -p 5432:5432 docker.io/library/postgres:latest
+
+. Run the tests and package the `war` file
+[source,console]
+mvn clean package
+
+. Copy the `war` file to your tomcat `webapps` directory
+[source,console]
+cp target/camel-example-spring-boot.war /webapps/
+
+. Run tomcat
+[source,console]
+sh /bin/catalina.sh run
+
+. Look for the log messages in the console
+[source,log]
+[- timer://hello] ... Body: insert into messages(message) values('Hello World I am invoked 1 times')]
+[- timer://query] ... Body: There are 0 messages in the database.]
+[- timer://query] ... Body: There are 1 messages in the database.]
+[- timer://hello] ... Body: insert into messages(message) values('Hello World I am invoked 2 times')]
+[- timer://query] ... Body: There are 2 messages in the database.]
+[- timer://hello] ... Body: insert into messages(message) values('Hello World I am invoked 3 times')]
+[- timer://query] ... Body: There are 3 messages in the database.]
+[- timer://hello] ... Body: insert into messages(message) values('Hello World I am invoked 4 times')]
+[- timer://hello] ... Body: insert into messages(message) values('Hello World I am invoked 5 times')]
+[- timer://query] ... Body: There are 4 messages in the database.]
+
+=== Help and contributions
+
+If you hit any problem using Camel or have some feedback, then please
+https://camel.apache.org/support.html[let us know].
+
+We also love contributors, so
+https://camel.apache.org/contributing.html[get involved] :-)
+
+The Camel riders!
+
+
+
diff --git a/tomcat-jdbc/src/main/java/sample/camel/MyBean.java b/tomcat-jdbc/src/main/java/sample/camel/MyBean.java
new file mode 100644
index 000000000..45b9aa8f9
--- /dev/null
+++ b/tomcat-jdbc/src/main/java/sample/camel/MyBean.java
@@ -0,0 +1,40 @@
+/*
+ * 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 sample.camel;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+/**
+ * A bean that returns a message when you call the {@link #saySomething()} method.
+ *
+ * Uses @Component("myBean") to register this bean with the name myBean
+ * that we use in the Camel route to lookup this bean.
+ */
+@Component("myBean")
+public class MyBean {
+
+ private int counter;
+
+ @Value("${greeting}")
+ private String say;
+
+ public String saySomething(String body) {
+ return String.format("%s I am invoked %d times", say, ++counter);
+ }
+
+}
diff --git a/tomcat-jdbc/src/main/java/sample/camel/MyCamelApplication.java b/tomcat-jdbc/src/main/java/sample/camel/MyCamelApplication.java
new file mode 100644
index 000000000..d680eadbf
--- /dev/null
+++ b/tomcat-jdbc/src/main/java/sample/camel/MyCamelApplication.java
@@ -0,0 +1,50 @@
+/*
+ * 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 sample.camel;
+
+import org.springframework.boot.Banner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+import org.springframework.context.annotation.Configuration;
+
+//CHECKSTYLE:OFF
+/**
+ * A sample Spring Boot application that starts the Camel routes.
+ *
+ * Having both the {@link #configure} and {@link #main} methods call the same builder ensures the configuration
+ * will be applied either by starting the application as a .war or by running as an executable.
+ */
+@SpringBootApplication
+public class MyCamelApplication extends SpringBootServletInitializer {
+
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
+ return customizerBuilder(builder);
+ }
+
+ public static void main(String[] args) {
+ customizerBuilder(new SpringApplicationBuilder()).run(args);
+ }
+
+ private static SpringApplicationBuilder customizerBuilder(SpringApplicationBuilder builder) {
+ return builder.sources(MyCamelApplication.class);
+ }
+
+}
+//CHECKSTYLE:ON
diff --git a/tomcat-jdbc/src/main/java/sample/camel/MyCamelRouter.java b/tomcat-jdbc/src/main/java/sample/camel/MyCamelRouter.java
new file mode 100644
index 000000000..71fedd383
--- /dev/null
+++ b/tomcat-jdbc/src/main/java/sample/camel/MyCamelRouter.java
@@ -0,0 +1,59 @@
+/*
+ * 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 sample.camel;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * A simple Camel route that triggers from a timer and calls a bean and prints to system out.
+ *
+ * Use @Component to make Camel auto-detect this route when starting.
+ */
+@Component
+public class MyCamelRouter extends RouteBuilder {
+
+ // we can use spring dependency injection
+ @Autowired
+ MyBean myBean;
+
+ @Override
+ public void configure() throws Exception {
+ // route to keep inserting messages in the database
+ // start from a timer
+ from("timer:hello?period={{myPeriod}}")
+ .routeId("hello")
+ // store the message from the bean in a header
+ .setHeader("message").method(myBean, "saySomething")
+ // prepare the insert SQL
+ .setBody(simple("insert into messages(message) values('${header.message}')"))
+ // insert the message into the database
+ .to("spring-jdbc:default")
+ // print the body
+ .to("log:info");
+
+ // route to print inserted messages
+ from("timer:query?period={{myPeriod}}")
+ .routeId("query")
+ .setBody(constant("select count(*) as \"C\" from messages"))
+ .to("spring-jdbc:default")
+ .setBody(simple("There are ${body[0][C]} messages in the database."))
+ .to("log:info");
+ }
+
+}
diff --git a/tomcat-jdbc/src/main/resources/application.properties b/tomcat-jdbc/src/main/resources/application.properties
new file mode 100644
index 000000000..cec869a9b
--- /dev/null
+++ b/tomcat-jdbc/src/main/resources/application.properties
@@ -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.
+## ---------------------------------------------------------------------------
+
+# the name of Camel
+camel.springboot.name = MyCamel
+
+spring.datasource.type=org.apache.tomcat.jdbc.pool.DataSource
+// other spring datasource properties
+#database configuration
+spring.datasource.driver-class-name=org.postgresql.Driver
+spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
+spring.datasource.username=postgres
+spring.datasource.password=password
+#init schema.sql -- this should be changed for production use!
+spring.sql.init.mode=always
+
+# what to say
+greeting = Hello World
+
+# how often to trigger the timer (millis)
+myPeriod = 2000
+
+# expose actuator endpoint via HTTP
+#management.endpoints.web.exposure.include=info,health,camel
+
+# show verbose health details (/actuator/health) so you can see Camel information also
+management.endpoint.health.show-details=always
+
+# to turn off Camel info in (/actuator/info)
+#management.info.camel.enabled=false
+
+# to configure logging levels
+#logging.level.org.springframework = INFO
+#logging.level.org.apache.camel.spring.boot = INFO
+#logging.level.org.apache.camel.impl = DEBUG
+#logging.level.sample.camel = DEBUG
+
diff --git a/tomcat-jdbc/src/main/resources/schema.sql b/tomcat-jdbc/src/main/resources/schema.sql
new file mode 100644
index 000000000..16e8eb57f
--- /dev/null
+++ b/tomcat-jdbc/src/main/resources/schema.sql
@@ -0,0 +1,5 @@
+DROP TABLE IF EXISTS messages;
+CREATE TABLE messages (
+ message VARCHAR(255),
+ ts TIMESTAMP NOT NULL DEFAULT now()
+);
\ No newline at end of file
diff --git a/tomcat-jdbc/src/test/java/sample/camel/MyCamelApplicationJUnit5Test.java b/tomcat-jdbc/src/test/java/sample/camel/MyCamelApplicationJUnit5Test.java
new file mode 100644
index 000000000..4952c3454
--- /dev/null
+++ b/tomcat-jdbc/src/test/java/sample/camel/MyCamelApplicationJUnit5Test.java
@@ -0,0 +1,71 @@
+/*
+ * 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 sample.camel;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.NotifyBuilder;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.apache.camel.test.spring.junit5.EnableRouteCoverage;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.jdbc.EmbeddedDatabaseConnection;
+import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
+import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Import;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+import org.springframework.transaction.annotation.Transactional;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Example test class with Camel coverage. When running tests a mock web server will be running, simulating a web environment.
+ */
+@CamelSpringBootTest
+@SpringBootTest(classes = MyCamelApplication.class)
+@AutoConfigureTestDatabase(connection = EmbeddedDatabaseConnection.H2)
+@EnableRouteCoverage
+public class MyCamelApplicationJUnit5Test {
+
+ @Autowired
+ private CamelContext camelContext;
+
+ @Autowired
+ private JdbcTemplate jdbcTemplate;
+
+ @Test
+ public void shouldProduceMessages() throws Exception {
+ // we expect that one or more messages is automatically done by the Camel
+ // route as it uses a timer to trigger
+ NotifyBuilder notify = new NotifyBuilder(camelContext).whenDone(1).create();
+ assertTrue(notify.matches(5, TimeUnit.SECONDS));
+
+ // check if the correct message is in the database
+ List