2.1.1 Added h2 storage using camel-mybatis

experiment
Yan 4 weeks ago
parent 21b1e672ff
commit ee7b4028de

@ -0,0 +1,20 @@
meta {
name: findUser
type: http
seq: 4
}
get {
url: http://localhost:9091/services/api/user/2
body: none
auth: basic
}
headers {
operationName: findUsers
}
auth:basic {
username: cxfrs
password: password
}

@ -5,7 +5,7 @@ meta {
}
get {
url: http://localhost:9090/services/api/user
url: http://localhost:9091/services/api/user
body: none
auth: basic
}

@ -5,7 +5,7 @@ meta {
}
post {
url: http://localhost:9091/services/api/user
url: http://localhost:9090/services/api/user
body: json
auth: basic
}
@ -22,7 +22,7 @@ auth:basic {
body:json {
{
"id": 3,
"name": "Bruce Wayne"
"id": 2,
"name": "Wallie West"
}
}

@ -19,3 +19,8 @@ app:
zookeeper:
url: "127.0.0.1:2181"
group-name: "UserServiceGroup"
database:
url: "jdbc:h2:tcp://localhost/~/h2/db/appdb"
username: "app"
password: "app"
mapper-package: "com.example.sbcamel.mapper"

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Copyright 2009-2016 the original author or authors.
Licensed 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.
-->
<!ELEMENT configuration (properties?, settings?, typeAliases?, typeHandlers?, objectFactory?, objectWrapperFactory?, reflectorFactory?, plugins?, environments?, databaseIdProvider?, mappers?)>
<!ELEMENT databaseIdProvider (property*)>
<!ATTLIST databaseIdProvider
type CDATA #REQUIRED
>
<!ELEMENT properties (property*)>
<!ATTLIST properties
resource CDATA #IMPLIED
url CDATA #IMPLIED
>
<!ELEMENT property EMPTY>
<!ATTLIST property
name CDATA #REQUIRED
value CDATA #REQUIRED
>
<!ELEMENT settings (setting+)>
<!ELEMENT setting EMPTY>
<!ATTLIST setting
name CDATA #REQUIRED
value CDATA #REQUIRED
>
<!ELEMENT typeAliases (typeAlias*,package*)>
<!ELEMENT typeAlias EMPTY>
<!ATTLIST typeAlias
type CDATA #REQUIRED
alias CDATA #IMPLIED
>
<!ELEMENT typeHandlers (typeHandler*,package*)>
<!ELEMENT typeHandler EMPTY>
<!ATTLIST typeHandler
javaType CDATA #IMPLIED
jdbcType CDATA #IMPLIED
handler CDATA #REQUIRED
>
<!ELEMENT objectFactory (property*)>
<!ATTLIST objectFactory
type CDATA #REQUIRED
>
<!ELEMENT objectWrapperFactory EMPTY>
<!ATTLIST objectWrapperFactory
type CDATA #REQUIRED
>
<!ELEMENT reflectorFactory EMPTY>
<!ATTLIST reflectorFactory
type CDATA #REQUIRED
>
<!ELEMENT plugins (plugin+)>
<!ELEMENT plugin (property*)>
<!ATTLIST plugin
interceptor CDATA #REQUIRED
>
<!ELEMENT environments (environment+)>
<!ATTLIST environments
default CDATA #REQUIRED
>
<!ELEMENT environment (transactionManager,dataSource)>
<!ATTLIST environment
id CDATA #REQUIRED
>
<!ELEMENT transactionManager (property*)>
<!ATTLIST transactionManager
type CDATA #REQUIRED
>
<!ELEMENT dataSource (property*)>
<!ATTLIST dataSource
type CDATA #REQUIRED
>
<!ELEMENT mappers (mapper*,package*)>
<!ELEMENT mapper EMPTY>
<!ATTLIST mapper
resource CDATA #IMPLIED
url CDATA #IMPLIED
class CDATA #IMPLIED
>
<!ELEMENT package EMPTY>
<!ATTLIST package
name CDATA #REQUIRED
>

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="org.h2.Driver" />
<property name="url" value="${dbUrl}" />
<property name="username" value="${dbUsername}" />
<property name="password" value="${dbPassword}" />
</dataSource>
</environment>
</environments>
</configuration>

@ -19,3 +19,8 @@ app:
zookeeper:
url: "127.0.0.1:2181"
group-name: "UserServiceGroup"
database:
url: "jdbc:h2:tcp://localhost/~/h2/db/appdb"
username: "app"
password: "app"
mapper-package: "com.example.sbcamel.mapper"

Binary file not shown.

@ -0,0 +1,105 @@
2025-03-08 12:36:27.115360+08:00 jdbc[3]: exception
org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement "MERGE INTO [*]USER (?) VALUES (?, ?)"; expected "identifier"; SQL statement:
MERGE INTO USER (?) VALUES (?, ?) [42001-224]
2025-03-08 12:41:38.334685+08:00 jdbc[3]: exception
org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement "CREATE TABLE IF NOT EXISTS public.[*]user (id BIGINT not null, name CHARACTER VARYING not null, PRIMARY KEY (id))"; expected "identifier"; SQL statement:
CREATE TABLE IF NOT EXISTS public.user (id BIGINT not null, name CHARACTER VARYING not null, PRIMARY KEY (id)) [42001-224]
2025-03-08 12:45:24.184967+08:00 jdbc[3]: exception
org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement "MERGE INTO public.""user"" ([*]?) VALUES (?, ?)"; expected "identifier"; SQL statement:
MERGE INTO public."user" (?) VALUES (?, ?) [42001-224]
2025-03-08 15:26:55.471296+08:00 database: flush
org.h2.message.DbException: General error: "org.h2.mvstore.MVStoreException: The file is locked: C:/Users/Yan/eclipse-workspace/camel-springboot-activemq6-example/db/appdb.mv.db [2.2.224/7]" [50000-224]
at org.h2.message.DbException.get(DbException.java:212)
at org.h2.message.DbException.convert(DbException.java:407)
at org.h2.mvstore.db.Store.lambda$new$0(Store.java:122)
at org.h2.mvstore.MVStore.handleException(MVStore.java:1546)
at org.h2.mvstore.MVStore.panic(MVStore.java:371)
at org.h2.mvstore.MVStore.<init>(MVStore.java:291)
at org.h2.mvstore.MVStore$Builder.open(MVStore.java:2035)
at org.h2.mvstore.db.Store.<init>(Store.java:133)
at org.h2.engine.Database.<init>(Database.java:326)
at org.h2.engine.Engine.openSession(Engine.java:92)
at org.h2.engine.Engine.openSession(Engine.java:222)
at org.h2.engine.Engine.createSession(Engine.java:201)
at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:343)
at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:125)
at org.h2.Driver.connect(Driver.java:59)
at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:137)
at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:360)
at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:202)
at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:461)
at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:550)
at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:98)
at com.zaxxer.hikari.HikariDataSource.<init>(HikariDataSource.java:80)
at com.example.sbcamel.DatabaseConfig.dataSource(DatabaseConfig.java:69)
at com.example.sbcamel.DatabaseConfig$$SpringCGLIB$$0.CGLIB$dataSource$0(<generated>)
at com.example.sbcamel.DatabaseConfig$$SpringCGLIB$$FastClass$$1.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:258)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:372)
at com.example.sbcamel.DatabaseConfig$$SpringCGLIB$$0.dataSource(<generated>)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:146)
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:644)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:636)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1355)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1448)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1358)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:904)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:782)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:542)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1355)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:313)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1448)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1358)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:785)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:768)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:145)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:509)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1439)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:971)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:625)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:335)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352)
at com.example.sbcamel.Boot.main(Boot.java:27)
Caused by: org.h2.jdbc.JdbcSQLNonTransientException: General error: "org.h2.mvstore.MVStoreException: The file is locked: C:/Users/Yan/eclipse-workspace/camel-springboot-activemq6-example/db/appdb.mv.db [2.2.224/7]" [50000-224]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:566)
at org.h2.message.DbException.getJdbcSQLException(DbException.java:489)
... 83 more
Caused by: org.h2.mvstore.MVStoreException: The file is locked: C:/Users/Yan/eclipse-workspace/camel-springboot-activemq6-example/db/appdb.mv.db [2.2.224/7]
at org.h2.mvstore.DataUtils.newMVStoreException(DataUtils.java:996)
at org.h2.mvstore.SingleFileStore.lockFileChannel(SingleFileStore.java:143)
at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:117)
at org.h2.mvstore.SingleFileStore.open(SingleFileStore.java:81)
at org.h2.mvstore.MVStore.<init>(MVStore.java:286)
... 77 more

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>camel-springboot-activemq6-example</artifactId>
<version>2.1.0</version>
<version>2.1.1</version>
<name>camel-springboot-activemq6-example</name>
<parent>
<groupId>org.springframework.boot</groupId>
@ -17,6 +17,8 @@
<maven.compiler.target>17</maven.compiler.target>
<camel.version>4.8.3</camel.version>
<springboot.version>${project.parent.version}</springboot.version>
<mybatis.version>3.5.19</mybatis.version>
<mybatis-spring.version>3.0.4</mybatis-spring.version>
</properties>
<dependencyManagement>
@ -56,6 +58,10 @@
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-ldap</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<!-- Camel -->
<dependency>
<groupId>org.apache.camel.springboot</groupId>
@ -82,12 +88,35 @@
<artifactId>camel-jackson-starter</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jakarta.rs</groupId>
<artifactId>jackson-jakarta-rs-json-provider</artifactId>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-zookeeper-master-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-zookeeper-master-starter</artifactId>
<artifactId>camel-mybatis-starter</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${mybatis-spring.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jakarta.rs</groupId>
<artifactId>jackson-jakarta-rs-json-provider</artifactId>
</dependency>
</dependencies>
<build>

@ -6,6 +6,7 @@
ApacheDS Server 2.0.0.AM27
Apache ActiveMQ 6.1.5
Apache Zookeeper 3.9.3
H2 Database Version 2.3.232
```
2. Please see conf/springboot.yml for LDAP/ActiveMQ Address
@ -207,3 +208,16 @@ C:\Users\XXX\apache-zookeeper-3.9.3-bin>call "C:\Users\XXX\graalvm-jdk-17.0.14+8
2025-03-01 15:28:22,213 [myid:] - INFO [SyncThread:0:o.a.z.s.p.FileTxnLog@291] - Creating new log file: log.1
```
**4. H2 Database Version 2.3.232**
```
C:\Users\XXX\Desktop>SET JAVA_HOME=C:\Users\XXX\graalvm-jdk-17.0.14+8.1
C:\Users\XXX\Desktop>SET PATH=C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Program Files\NVIDIA Corporation\NVIDIA NvDLISR;C:\Program Files\PuTTY\;C:\Users\XXX\AppData\Local\Microsoft\WindowsApps;C:\Users\XXX\graalvm-jdk-17.0.14+8.1\bin;;C:\Users\XXX\graalvm-jdk-17.0.14+8.1\bin
C:\Users\XXX\Desktop>cd C:\Users\XXX\h2\bin
C:\Users\XXX\h2\bin>h2.bat -tcp -web
Web Console server running at http://127.0.0.1:8082?key=8c2f1bfb9fb08604f1e3a7849e8b338514438c2c729b87ecc98108b6102818c6 (only local connections)
TCP server running at tcp://127.0.0.1:9092 (only local connections)
```

@ -18,12 +18,12 @@ public class Boot {
configDirectory = args[0];
}
logger.info("config directory: {}", configDirectory);
if (new File(configDirectory).exists() && new File(configDirectory).isDirectory()) {
System.setProperty("spring.config.location", configDirectory + "/springboot.yml");
System.setProperty("logging.config", configDirectory + "/logback.xml");
}
System.setProperty("org.apache.activemq.SERIALIZABLE_PACKAGES","*");
System.setProperty("org.apache.activemq.SERIALIZABLE_PACKAGES", "*");
SpringApplication.run(Boot.class, args);
}

@ -2,16 +2,24 @@ package com.example.sbcamel;
import org.apache.camel.Exchange;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.bean.BeanConstants;
import org.apache.camel.component.bean.validator.BeanValidationException;
import org.apache.camel.component.cxf.common.message.CxfConstants;
import org.apache.camel.component.zookeepermaster.policy.MasterRoutePolicy;
import org.apache.camel.model.dataformat.JsonLibrary;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import jakarta.annotation.PostConstruct;
import jakarta.ws.rs.core.Response;
@Component
public class CamelRouter extends RouteBuilder {
private static final String createUserSql = "CREATE TABLE IF NOT EXISTS public.\"user\" (id BIGINT not null, "
+ "name CHARACTER VARYING not null, PRIMARY KEY (id))";
@Value("${app.queue-name}")
private String queueName;
@ -22,6 +30,14 @@ public class CamelRouter extends RouteBuilder {
@Value("${app.zookeeper.group-name}")
private String groupName;
@Autowired
private JdbcTemplate jdbcTemplate;
@PostConstruct
private void init() {
jdbcTemplate.execute(createUserSql);
}
@Override
public void configure() throws Exception {
// very raw way, just to handle the validation responses
@ -29,17 +45,36 @@ public class CamelRouter extends RouteBuilder {
.setHeader(Exchange.HTTP_RESPONSE_CODE, constant(Response.Status.BAD_REQUEST.getStatusCode()))
.setBody(simple("${exchangeProperty.CamelExceptionCaught.getMessage()}"));
from("cxfrs:/api?resourceClasses=" + UserService.class.getName() + "&bindingStyle=SimpleConsumer"
+ "&providers=jaxrsProvider&loggingFeatureEnabled=true").to("log:cxfrs-log?showAll=true")
.setHeader(Exchange.BEAN_METHOD_NAME, simple("${header.operationName}"))
.to("activemq6:queue:" + queueName);
onException(jakarta.ws.rs.NotFoundException.class).handled(true)
.setHeader(Exchange.HTTP_RESPONSE_CODE, constant(Response.Status.NOT_FOUND.getStatusCode()))
.setBody(simple("${exchangeProperty.CamelExceptionCaught.getMessage()}"));
from("cxfrs:/api?resourceClasses=" + UserService.class.getName() + "&bindingStyle=Default"
+ "&providers=jaxrsProvider&loggingFeatureEnabled=true").to("log:cxfrs?showAll=true")
.to("bean-validator:user").to("activemq6:queue:" + queueName).process(exchange -> {
if (exchange.getMessage().getBody() != null && exchange.getMessage().getBody() instanceof byte[]
&& new String((byte[]) exchange.getMessage().getBody()).equals("null")) {
if (exchange.getIn().getHeader(Exchange.HTTP_METHOD).equals("GET")) {
throw new jakarta.ws.rs.NotFoundException();
}
}
});
MasterRoutePolicy masterRoutePolicy = new MasterRoutePolicy();
masterRoutePolicy.setZooKeeperUrl(zookeeperUrl);
masterRoutePolicy.setGroupName(groupName);
from("activemq6:queue:" + queueName).autoStartup("false").routePolicy(masterRoutePolicy)
.to("bean-validator:user").bean(UserServiceImpl.class).marshal().json(JsonLibrary.Jackson);
.process(exchange -> exchange.getIn().setHeader(BeanConstants.BEAN_METHOD_NAME,
exchange.getIn().getHeader(CxfConstants.OPERATION_NAME.toLowerCase())))
.to("log:activemq?showAll=true").transacted("propagationRequired").choice()
.when(header(BeanConstants.BEAN_METHOD_NAME).isEqualTo("updateUser"))
.to("mybatis:com.example.sbcamel.mapper.UserMapper.updateUser?statementType=Update")
.when(header(BeanConstants.BEAN_METHOD_NAME).isEqualTo("findUsers"))
.to("mybatis:com.example.sbcamel.mapper.UserMapper.findUsers?statementType=SelectList")
.when(header(BeanConstants.BEAN_METHOD_NAME).isEqualTo("findUser"))
.to("mybatis:com.example.sbcamel.mapper.UserMapper.findUser?statementType=SelectOne").end().marshal()
.json(JsonLibrary.Jackson);
}
}

@ -0,0 +1,120 @@
package com.example.sbcamel;
import java.io.IOException;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import javax.sql.DataSource;
import org.apache.camel.component.mybatis.MyBatisComponent;
import org.apache.camel.spring.spi.SpringTransactionPolicy;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;
import org.springframework.transaction.PlatformTransactionManager;
import com.google.common.reflect.ClassPath;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
@Configuration
public class DatabaseConfig {
private static final Logger logger = LoggerFactory.getLogger(DatabaseConfig.class);
public static final String CFG_APP_DATABASE_URL = "${app.database.url}";
public static final String CFG_APP_DATABASE_USERNAME = "${app.database.username:}";
public static final String CFG_APP_DATABASE_PASSWORD = "${app.database.password:}";
public static final String CFG_APP_DATABASE_MAPPER_PACKAGE = "${app.database.mapper-package}";
public static final String CFG_APP_DATABASE_SPRINGBOOT_CLASS_PREFIX = "${app.database.springboot-class-prefix:BOOT-INF.classes.}";
@Value(CFG_APP_DATABASE_URL)
private String dbUrl;
@Value(CFG_APP_DATABASE_USERNAME)
private String dbUsername;
@Value(CFG_APP_DATABASE_PASSWORD)
private String dbPassword;
@Value(CFG_APP_DATABASE_MAPPER_PACKAGE)
private String mapperPackage;
@Value(CFG_APP_DATABASE_SPRINGBOOT_CLASS_PREFIX)
private String springBootClassPrefix;
@Bean
HikariConfig hikariConfig() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl(dbUrl);
config.setUsername(dbUsername);
config.setPassword(dbPassword);
config.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("prepStmtCacheSize", "250");
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
return config;
}
@Bean
DataSource dataSource(HikariConfig hikariConfig) {
return new TransactionAwareDataSourceProxy(new HikariDataSource(hikariConfig));
}
@Bean
PlatformTransactionManager txManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean
SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
Environment environment = new Environment("development", new JdbcTransactionFactory(), dataSource);
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration(
environment);
Set<Class<?>> mapperClasses = findAllClassesUsingGuava(mapperPackage);
mapperClasses.forEach(configuration::addMapper);
return new SqlSessionFactoryBuilder().build(configuration);
}
@Bean
MyBatisComponent mybatis(SqlSessionFactory sqlSessionFactory) {
MyBatisComponent mybatis = new MyBatisComponent();
mybatis.setSqlSessionFactory(sqlSessionFactory);
return mybatis;
}
@Bean
SpringTransactionPolicy propagationRequired(PlatformTransactionManager txManager) {
SpringTransactionPolicy propagationRequired = new SpringTransactionPolicy();
propagationRequired.setTransactionManager(txManager);
propagationRequired.setPropagationBehaviorName("PROPAGATION_REQUIRED");
return propagationRequired;
}
private Set<Class<?>> findAllClassesUsingGuava(String packageName) throws IOException {
logger.trace("Orm mappers packageName: {}", packageName);
return ClassPath.from(ClassLoader.getSystemClassLoader()).getAllClasses().stream()
.peek(clazz -> logger.trace("candidate class: {}, package name: {}", clazz, clazz.getPackageName()))
.filter(clazz -> clazz.getPackageName().endsWith(packageName))
.peek(clazz -> logger.info("accepted class: {}, package name: {}", clazz, clazz.getPackageName()))
.map(clazz -> {
try {
if (clazz.getName().startsWith(springBootClassPrefix)) {
return Class.forName(clazz.getName().replace(springBootClassPrefix, ""));
}
return Class.forName(clazz.getName());
} catch (ClassNotFoundException e) {
logger.error("cannot convert this class name to class: {}", clazz.getName());
}
return null;
}).filter(Objects::nonNull).collect(Collectors.toSet());
}
}

@ -35,9 +35,8 @@ public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(
(authorize) -> authorize.requestMatchers(HttpMethod.GET, "/**").hasAuthority(ROLE_BACKEND)
.requestMatchers(HttpMethod.POST, "/**").hasAuthority(ROLE_SERVER))
http.authorizeHttpRequests((authorize) -> authorize.requestMatchers(HttpMethod.GET, "/**")
.hasAuthority(ROLE_BACKEND).requestMatchers(HttpMethod.POST, "/**").hasAuthority(ROLE_SERVER))
.httpBasic(Customizer.withDefaults()).csrf(csrf -> csrf.disable());
return http.build();
}

@ -13,42 +13,40 @@ import jakarta.validation.constraints.Size;
@SuppressWarnings("serial")
public class User implements Serializable {
@NotNull(message = "custom message")
private Integer id;
@NotNull
@Size(min = 3, max = 20)
private String name;
public User() {
}
public User(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return new StringJoiner(", ", User.class.getSimpleName() + "[", "]")
.add("id=" + id)
.add("name='" + name + "'")
.toString();
}
@NotNull(message = "custom message")
private Integer id;
@NotNull
@Size(min = 3, max = 20)
private String name;
public User() {
}
public User(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return new StringJoiner(", ", User.class.getSimpleName() + "[", "]").add("id=" + id).add("name='" + name + "'")
.toString();
}
}

@ -16,37 +16,35 @@ import jakarta.ws.rs.core.MediaType;
*/
public interface UserService {
/**
* Find a user by the given ID
*
* @param id
* the ID of the user
* @return the user, or <code>null</code> if user not found.
*/
@GET
@Path("/user/{id}")
@Produces(MediaType.APPLICATION_JSON)
User findUser(@PathParam("id") Integer id);
/**
* Find a user by the given ID
*
* @param id the ID of the user
* @return the user, or <code>null</code> if user not found.
*/
@GET
@Path("/user/{id}")
@Produces(MediaType.APPLICATION_JSON)
User findUser(@PathParam("id") Integer id);
/**
* Find all users
*
* @return a collection of all users
*/
@GET
@Path("/user")
@Produces(MediaType.APPLICATION_JSON)
Collection<User> findUsers();
/**
* Find all users
*
* @return a collection of all users
*/
@GET
@Path("/user")
@Produces(MediaType.APPLICATION_JSON)
Collection<User> findUsers();
/**
* Update the given user
*
* @param user
* the user
*/
@POST
@Path("/user")
@Consumes(MediaType.APPLICATION_JSON)
User updateUser(@Valid User user);
/**
* Update the given user
*
* @param user the user
*/
@POST
@Path("/user")
@Consumes(MediaType.APPLICATION_JSON)
User updateUser(@Valid User user);
}

@ -1,33 +0,0 @@
package com.example.sbcamel;
import java.util.Collection;
import java.util.Map;
import java.util.TreeMap;
public class UserServiceImpl implements UserService {
private final Map<Integer, User> users = new TreeMap<>();
public UserServiceImpl() {
users.put(1, new User(1, "John Coltrane"));
users.put(2, new User(2, "Miles Davis"));
users.put(3, new User(3, "Sonny Rollins"));
}
@Override
public User findUser(Integer id) {
return users.get(id);
}
@Override
public Collection<User> findUsers() {
return users.values();
}
@Override
public User updateUser(User user) {
users.put(user.getId(), user);
return user;
}
}

@ -0,0 +1,24 @@
package com.example.sbcamel.mapper;
import java.util.Collection;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import com.example.sbcamel.User;
public interface UserMapper {
@Insert({ "<script>", "MERGE INTO public.\"user\" (id, name) KEY (id) VALUES (#{id}, #{name}) ", "</script>" })
User updateUser(User user);
@Results({ @Result(property = "id", column = "id"), @Result(property = "name", column = "name") })
@Select({ "<script>", "select id, name from public.\"user\" where id=#{list[0]}", "</script>" })
User findUser(Integer id);
@Results({ @Result(property = "id", column = "id"), @Result(property = "name", column = "name") })
@Select({ "<script>", "select id, name from public.\"user\" order by id", "</script>" })
Collection<User> findUsers();
}
Loading…
Cancel
Save