Compare commits
No commits in common. 'prototype' and 'master' have entirely different histories.
@ -1,8 +1,4 @@
|
||||
/target/
|
||||
/.classpath
|
||||
/.project
|
||||
/.settings
|
||||
/conf/
|
||||
/conf2/
|
||||
/bruno/
|
||||
/backup/
|
||||
/.settings
|
||||
@ -0,0 +1,9 @@
|
||||
{
|
||||
"version": "1",
|
||||
"name": "camel-springboot-xml-example",
|
||||
"type": "collection",
|
||||
"ignore": [
|
||||
"node_modules",
|
||||
".git"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
auth {
|
||||
mode: basic
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username:
|
||||
password:
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
meta {
|
||||
name: findUsers
|
||||
type: http
|
||||
seq: 2
|
||||
}
|
||||
|
||||
get {
|
||||
url: http://localhost:9090/services/api/user
|
||||
body: none
|
||||
auth: basic
|
||||
}
|
||||
|
||||
headers {
|
||||
operationName: findUsers
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: cxfrs
|
||||
password: password
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
meta {
|
||||
name: updateUser
|
||||
type: http
|
||||
seq: 3
|
||||
}
|
||||
|
||||
post {
|
||||
url: http://localhost:9090/services/api/user
|
||||
body: json
|
||||
auth: basic
|
||||
}
|
||||
|
||||
headers {
|
||||
Content-Type: application/json
|
||||
X-MethodName: updateUser
|
||||
}
|
||||
|
||||
auth:basic {
|
||||
username: cxfrs
|
||||
password: password
|
||||
}
|
||||
|
||||
body:json {
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Bruce Wayne"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration scan="true">
|
||||
<appender name="STDOUT"
|
||||
class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%-5level %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
<appender name="FILE"
|
||||
class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>logs/server.log</file>
|
||||
<rollingPolicy
|
||||
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>logs/server.%d{yyyy-MM-dd}.log.gz</fileNamePattern>
|
||||
<maxHistory>3</maxHistory>
|
||||
<totalSizeCap>300MB</totalSizeCap>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>%-5level %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
<logger name="org.springframework.security.ldap.userdetails" level="TRACE" />
|
||||
<logger name="org.springframework.security" level="DEBUG" />
|
||||
<logger name="com.example.camel" level="DEBUG" />
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
||||
@ -0,0 +1,19 @@
|
||||
server:
|
||||
port: 9090
|
||||
|
||||
camel:
|
||||
springboot:
|
||||
main-run-controller: true
|
||||
|
||||
spring:
|
||||
activemq:
|
||||
broker-url: "tcp://localhost:61616"
|
||||
ldap:
|
||||
urls: ldap://localhost:10389
|
||||
base: dc=example,dc=com
|
||||
username: uid=admin,ou=system
|
||||
password: secret
|
||||
|
||||
app:
|
||||
queue-name: "UserServiceQueue"
|
||||
|
||||
Binary file not shown.
@ -1,105 +0,0 @@
|
||||
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
|
||||
@ -0,0 +1,34 @@
|
||||
package com.example.camel;
|
||||
|
||||
import org.apache.camel.Exchange;
|
||||
import org.apache.camel.builder.RouteBuilder;
|
||||
import org.apache.camel.component.bean.validator.BeanValidationException;
|
||||
import org.apache.camel.model.dataformat.JsonLibrary;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
@Component
|
||||
public class CamelRouter extends RouteBuilder {
|
||||
|
||||
@Value("${app.queue-name}")
|
||||
private String queueName;
|
||||
|
||||
@Override
|
||||
public void configure() throws Exception {
|
||||
// very raw way, just to handle the validation responses
|
||||
onException(BeanValidationException.class).handled(true)
|
||||
.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);
|
||||
|
||||
from("activemq6:queue:" + queueName).to("bean-validator:user").bean(UserServiceImpl.class).marshal()
|
||||
.json(JsonLibrary.Jackson);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
package com.example.camel;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
/**
|
||||
* User entity
|
||||
*
|
||||
*/
|
||||
@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();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
package com.example.camel;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
|
||||
/**
|
||||
* Service interface for managing users.
|
||||
*/
|
||||
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 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);
|
||||
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
package com.example.camel;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,64 +0,0 @@
|
||||
package com.example.sbcamel.init;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
||||
import org.apache.hc.client5.http.impl.classic.HttpClients;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportResource;
|
||||
|
||||
import com.example.sbcamel.processor.InspectionProcessor;
|
||||
import com.example.sbcamel.processor.TestProcessor;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import com.fasterxml.jackson.jakarta.rs.json.JacksonJsonProvider;
|
||||
|
||||
@Configuration
|
||||
@ImportResource("classpath:schedule.xml")
|
||||
public class AppConfig {
|
||||
|
||||
@Value("${app.inspection-client.javamail-config}")
|
||||
private String javamailCfg;
|
||||
|
||||
@Bean
|
||||
public Properties javaMailProperties() throws IOException {
|
||||
Properties javaMailProperties = new Properties();
|
||||
FileInputStream fis = new FileInputStream(javamailCfg);
|
||||
javaMailProperties.load(fis);
|
||||
fis.close();
|
||||
return javaMailProperties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CloseableHttpClient httpClient() {
|
||||
return HttpClients.createDefault();
|
||||
}
|
||||
|
||||
@Bean("objectMapper")
|
||||
public ObjectMapper objectMapper() {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.registerModule(new JavaTimeModule());
|
||||
mapper.registerModule(new Jdk8Module());
|
||||
return mapper;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JacksonJsonProvider jaxrsProvider() {
|
||||
return new JacksonJsonProvider();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public InspectionProcessor inspectionProcessor() {
|
||||
return new InspectionProcessor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TestProcessor testProcessor() {
|
||||
return new TestProcessor();
|
||||
}
|
||||
}
|
||||
@ -1,87 +0,0 @@
|
||||
package com.example.sbcamel.init;
|
||||
|
||||
import org.apache.camel.Exchange;
|
||||
import org.apache.camel.builder.RouteBuilder;
|
||||
import org.apache.camel.component.bean.BeanConstants;
|
||||
import org.apache.camel.component.cxf.common.message.CxfConstants;
|
||||
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 com.example.sbcamel.mapper.SessionMapper;
|
||||
import com.example.sbcamel.processor.InspectionProcessor;
|
||||
import com.example.sbcamel.processor.TestProcessor;
|
||||
import com.example.sbcamel.service.SessionService;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
@Component
|
||||
public class CamelRouter extends RouteBuilder {
|
||||
|
||||
private static final String createSessionSql = "CREATE TABLE IF NOT EXISTS public.session (sessionId UUID not null, "
|
||||
+ "username CHARACTER VARYING not null, password CHARACTER VARYING not null, PRIMARY KEY (sessionId))";
|
||||
private static final String addSelector1Sql = "ALTER TABLE IF EXISTS public.session ADD COLUMN IF NOT EXISTS selector1 CHARACTER VARYING NULL";
|
||||
private static final String addSelector2Sql = "ALTER TABLE IF EXISTS public.session ADD COLUMN IF NOT EXISTS selector2 CHARACTER VARYING NULL";
|
||||
private static final String addSelector3Sql = "ALTER TABLE IF EXISTS public.session ADD COLUMN IF NOT EXISTS selector3 CHARACTER VARYING NULL";
|
||||
|
||||
@Value("${app.queue-name}")
|
||||
private String queueName;
|
||||
|
||||
@Autowired
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
|
||||
@Autowired
|
||||
protected InspectionProcessor inspectionProcessor;
|
||||
|
||||
@Autowired
|
||||
protected TestProcessor testProcessor;
|
||||
|
||||
@PostConstruct
|
||||
private void init() {
|
||||
org.apache.ibatis.logging.LogFactory.useSlf4jLogging();
|
||||
jdbcTemplate.execute(createSessionSql);
|
||||
jdbcTemplate.execute(addSelector1Sql);
|
||||
jdbcTemplate.execute(addSelector2Sql);
|
||||
jdbcTemplate.execute(addSelector3Sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure() throws Exception {
|
||||
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=" + SessionService.class.getName() + "&bindingStyle=Default"
|
||||
+ "&providers=jaxrsProvider&loggingFeatureEnabled=true").to("log:cxfrs?showAll=true")
|
||||
.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();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
from("activemq6:queue:" + queueName)
|
||||
.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("updateSession"))
|
||||
.to("mybatis:" + SessionMapper.class.getName()
|
||||
+ ".updateSession?statementType=Update&outputHeader=X-UpdateResult")
|
||||
.process(exchange -> {
|
||||
exchange.getMessage().setBody(exchange.getIn().getBody());
|
||||
}).when(header(BeanConstants.BEAN_METHOD_NAME).isEqualTo("findSessions"))
|
||||
.to("mybatis:" + SessionMapper.class.getName() + ".findSessions?statementType=SelectList")
|
||||
.when(header(BeanConstants.BEAN_METHOD_NAME).isEqualTo("findSession"))
|
||||
.to("mybatis:" + SessionMapper.class.getName() + ".findSession?statementType=SelectOne")
|
||||
.when(header(BeanConstants.BEAN_METHOD_NAME).isEqualTo("inspect"))
|
||||
.to("mybatis:" + SessionMapper.class.getName() + ".findSession?statementType=SelectOne")
|
||||
.process(inspectionProcessor).when(header(BeanConstants.BEAN_METHOD_NAME).isEqualTo("test"))
|
||||
.process(testProcessor).end().marshal().json(JsonLibrary.Jackson);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,120 +0,0 @@
|
||||
package com.example.sbcamel.init;
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
@ -1,45 +0,0 @@
|
||||
package com.example.sbcamel.mapper;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
|
||||
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 org.apache.ibatis.type.JdbcType;
|
||||
|
||||
import com.example.sbcamel.service.Session;
|
||||
import com.example.sbcamel.service.UuidTypeHandler;
|
||||
|
||||
public interface SessionMapper {
|
||||
|
||||
@Insert({ "<script>",
|
||||
"MERGE INTO public.session (sessionId, username, password, selector1, selector2, selector3) KEY (sessionId) VALUES (#{sessionId, javaType=java.util.UUID, "
|
||||
+ "jdbcType=OTHER, typeHandler=com.example.sbcamel.service.UuidTypeHandler}, #{username}, #{password}, #{selector1}, #{selector2}, #{selector3}) ",
|
||||
"</script>" })
|
||||
int updateSession(Session session);
|
||||
|
||||
@Results({
|
||||
@Result(property = "sessionId", column = "sessionId", javaType = UUID.class, jdbcType = JdbcType.OTHER, typeHandler = UuidTypeHandler.class),
|
||||
@Result(property = "username", column = "username"), @Result(property = "password", column = "password"),
|
||||
@Result(property = "selector1", column = "selector1"),
|
||||
@Result(property = "selector2", column = "selector2"),
|
||||
@Result(property = "selector3", column = "selector3") })
|
||||
@Select({ "<script>",
|
||||
"select sessionId, username, password, selector1, selector2, selector3 from public.session where sessionId=#{list[0], javaType=java.util.UUID, "
|
||||
+ "jdbcType=OTHER, typeHandler=com.example.sbcamel.service.UuidTypeHandler}",
|
||||
"</script>" })
|
||||
Session findSession(UUID sessionId);
|
||||
|
||||
@Results({
|
||||
@Result(property = "sessionId", column = "sessionId", javaType = UUID.class, jdbcType = JdbcType.OTHER, typeHandler = UuidTypeHandler.class),
|
||||
@Result(property = "username", column = "username"), @Result(property = "password", column = "password"),
|
||||
@Result(property = "selector1", column = "selector1"),
|
||||
@Result(property = "selector2", column = "selector2"),
|
||||
@Result(property = "selector3", column = "selector3") })
|
||||
@Select({ "<script>",
|
||||
"select sessionId, username, password, selector1, selector2, selector3 from public.session order by sessionId",
|
||||
"</script>" })
|
||||
Collection<Session> findSessions();
|
||||
}
|
||||
@ -1,142 +0,0 @@
|
||||
package com.example.sbcamel.processor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.camel.Exchange;
|
||||
import org.apache.camel.Processor;
|
||||
import org.htmlunit.FailingHttpStatusCodeException;
|
||||
import org.htmlunit.WebClient;
|
||||
import org.htmlunit.html.HtmlButton;
|
||||
import org.htmlunit.html.HtmlForm;
|
||||
import org.htmlunit.html.HtmlPage;
|
||||
import org.htmlunit.html.HtmlPasswordInput;
|
||||
import org.htmlunit.html.HtmlTextInput;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.select.Elements;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
||||
import com.example.sbcamel.service.Session;
|
||||
|
||||
public class InspectionProcessor implements Processor {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(InspectionProcessor.class);
|
||||
|
||||
@Value("${app.htmlunit.login-url}")
|
||||
private String loginUrl;
|
||||
|
||||
@Value("${app.htmlunit.login-btn-selector}")
|
||||
private String loginBtnSelector;
|
||||
|
||||
@Value("${app.htmlunit.login-wait-millis:3000}")
|
||||
private Long loginWaitMillis;
|
||||
|
||||
@Value("${app.htmlunit.user-page-url}")
|
||||
private String userPageUrl;
|
||||
|
||||
@Value("${app.htmlunit.vip11-page-url}")
|
||||
private String vip11PageUrl;
|
||||
|
||||
@Value("${app.htmlunit.vip12-page-url}")
|
||||
private String vip12PageUrl;
|
||||
|
||||
@Value("${app.htmlunit.vip13-page-url}")
|
||||
private String vip13PageUrl;
|
||||
|
||||
@Value("${app.htmlunit.vip21-page-url}")
|
||||
private String vip21PageUrl;
|
||||
|
||||
@Value("${app.htmlunit.vip22-page-url}")
|
||||
private String vip22PageUrl;
|
||||
|
||||
@Value("${app.htmlunit.vip23-page-url}")
|
||||
private String vip23PageUrl;
|
||||
|
||||
@Value("${app.htmlunit.vip31-page-url}")
|
||||
private String vip31PageUrl;
|
||||
|
||||
@Value("${app.htmlunit.vip32-page-url}")
|
||||
private String vip32PageUrl;
|
||||
|
||||
@Value("${app.htmlunit.vip33-page-url}")
|
||||
private String vip33PageUrl;
|
||||
|
||||
@Value("${app.htmlunit.logout-url}")
|
||||
private String logoutUrl;
|
||||
|
||||
@Override
|
||||
public void process(Exchange exchange) throws Exception {
|
||||
Session session = (Session) exchange.getMessage().getBody();
|
||||
logger.debug("session: {}", session);
|
||||
|
||||
try (final WebClient webClient = new WebClient()) {
|
||||
|
||||
final HtmlPage loginPage = webClient.getPage(loginUrl);
|
||||
logger.debug("loginPage: {}", loginPage.asXml());
|
||||
|
||||
final HtmlForm form = loginPage.getForms().get(0);
|
||||
final HtmlTextInput usernameField = form.getInputByName("username");
|
||||
usernameField.type(session.getUsername());
|
||||
logger.debug("entered username: {}", session.getUsername());
|
||||
|
||||
final HtmlPasswordInput passwordField = form.getInputByName("password");
|
||||
passwordField.type(session.getPassword());
|
||||
logger.debug("entered password: {}", session.getPassword());
|
||||
|
||||
HtmlButton loginBtn = loginPage.querySelector(loginBtnSelector);
|
||||
logger.debug("loginBtn type: {}", loginBtn.getType());
|
||||
loginBtn.click();
|
||||
|
||||
Thread.sleep(loginWaitMillis);
|
||||
|
||||
HtmlPage userPage = webClient.getPage(userPageUrl);
|
||||
logger.debug("userPage hashcode: {}", userPage.hashCode());
|
||||
|
||||
Map<String, List<String>> reply11 = fillResponseMap(webClient, session, vip11PageUrl);
|
||||
Map<String, List<String>> reply12 = fillResponseMap(webClient, session, vip12PageUrl);
|
||||
Map<String, List<String>> reply13 = fillResponseMap(webClient, session, vip13PageUrl);
|
||||
|
||||
Map<String, List<String>> reply21 = fillResponseMap(webClient, session, vip21PageUrl);
|
||||
Map<String, List<String>> reply22 = fillResponseMap(webClient, session, vip22PageUrl);
|
||||
Map<String, List<String>> reply23 = fillResponseMap(webClient, session, vip23PageUrl);
|
||||
|
||||
Map<String, List<String>> reply31 = fillResponseMap(webClient, session, vip31PageUrl);
|
||||
Map<String, List<String>> reply32 = fillResponseMap(webClient, session, vip32PageUrl);
|
||||
Map<String, List<String>> reply33 = fillResponseMap(webClient, session, vip33PageUrl);
|
||||
|
||||
webClient.getPage(logoutUrl);
|
||||
exchange.getMessage().setBody(Map.of("vip11Page", reply11, "vip12Page", reply12, "vip13Page", reply13,
|
||||
"vip21Page", reply21, "vip22Page", reply22, "vip23Page", reply23,
|
||||
"vip31Page", reply31, "vip32Page", reply32, "vip33Page", reply33));
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("LoginProcessor process error!", e);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, List<String>> fillResponseMap(WebClient webClient, Session session, String url)
|
||||
throws FailingHttpStatusCodeException, MalformedURLException, IOException {
|
||||
Map<String, List<String>> reply = new HashMap<>();
|
||||
HtmlPage vipPage = webClient.getPage(url);
|
||||
Document doc = Jsoup.parse(vipPage.asXml());
|
||||
for (String selector : List.of(session.getSelector1(), session.getSelector2(), session.getSelector3())) {
|
||||
Elements elements = doc.select(selector);
|
||||
List<String> selectedList = new ArrayList<>();
|
||||
for (Element element : elements) {
|
||||
logger.debug("[fillResponseMap] {} -> {}", selector, element.html());
|
||||
selectedList.add(element.html());
|
||||
}
|
||||
reply.put(selector, selectedList);
|
||||
}
|
||||
return reply;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,54 +0,0 @@
|
||||
package com.example.sbcamel.processor;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.camel.Exchange;
|
||||
import org.apache.camel.Processor;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.cxf.message.MessageContentsList;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.select.Elements;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
||||
public class TestProcessor implements Processor {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(TestProcessor.class);
|
||||
|
||||
@Value("${app.jsoup.html-file}")
|
||||
private String htmlFilePath;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void process(Exchange exchange) throws Exception {
|
||||
logger.info("in class: {}", exchange.getIn().getBody().getClass().getName());
|
||||
MessageContentsList mcl = (MessageContentsList) exchange.getIn().getBody();
|
||||
List<String> selectors = (List<String>) mcl.get(0);
|
||||
logger.info("selectors: {}", selectors);
|
||||
|
||||
File htmlFile = new File(htmlFilePath);
|
||||
String html = FileUtils.readFileToString(htmlFile, StandardCharsets.UTF_8);
|
||||
Document doc = Jsoup.parse(html);
|
||||
Map<String, List<String>> reply = new HashMap<>();
|
||||
|
||||
for (String selector : selectors) {
|
||||
Elements elements = doc.select(selector);
|
||||
List<String> selectedList = new ArrayList<>();
|
||||
for (Element element : elements) {
|
||||
logger.info("{} -> {}", selector, element.html());
|
||||
selectedList.add(element.html());
|
||||
}
|
||||
reply.put(selector, selectedList);
|
||||
}
|
||||
exchange.getMessage().setBody(reply);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,70 +0,0 @@
|
||||
package com.example.sbcamel.service;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.mail.Message;
|
||||
import javax.mail.Session;
|
||||
import javax.mail.Transport;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class EmailService {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(EmailService.class);
|
||||
|
||||
@Autowired
|
||||
private Properties javaMailProperties;
|
||||
|
||||
public boolean sendEmail(String fromAddress, String smtpPassword, String[] toAddresses, String subject,
|
||||
String content) {
|
||||
try {
|
||||
logger.debug("[sendEmail] fromAddress: {}, toAddresses: {}", fromAddress, toAddresses);
|
||||
if (StringUtils.isEmpty(subject) || StringUtils.isEmpty(smtpPassword) || StringUtils.isEmpty(fromAddress)
|
||||
|| toAddresses.length == 0) {
|
||||
logger.warn("[sendEmail] subject, smtp-password, source-address or target-address is not set");
|
||||
return false;
|
||||
}
|
||||
String emailHost = javaMailProperties.getProperty("mail.smtp.host");
|
||||
logger.debug("[sendEmail] {} -> {}, mail.smtp.host: {}", fromAddress, List.of(toAddresses), emailHost);
|
||||
if (StringUtils.isNotBlank(emailHost) && StringUtils.isNotBlank(fromAddress) && toAddresses.length > 0) {
|
||||
logger.debug("[sendEmail] starting to send message from: {}", fromAddress);
|
||||
Session session = Session.getInstance(javaMailProperties);
|
||||
|
||||
MimeMessage message = new MimeMessage(session);
|
||||
message.setContent(content, "text/html; charset=utf-8");
|
||||
message.setFrom(new InternetAddress(fromAddress));
|
||||
|
||||
Arrays.asList(toAddresses).forEach(toAddress -> {
|
||||
try {
|
||||
message.addRecipient(Message.RecipientType.TO, new InternetAddress(toAddress));
|
||||
} catch (Exception e) {
|
||||
logger.error("sendEmail error!", e);
|
||||
}
|
||||
});
|
||||
message.setSubject(subject);
|
||||
|
||||
Transport transport = session.getTransport("smtp");
|
||||
transport.connect(emailHost, fromAddress, smtpPassword);
|
||||
transport.sendMessage(message, message.getAllRecipients());
|
||||
transport.close();
|
||||
logger.debug("sendEmail to: {}", Arrays.asList(toAddresses));
|
||||
|
||||
return true;
|
||||
} else {
|
||||
logger.warn("[sendEmail] missing either from-field, to-field or host address!");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("sendEmail error!", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1,161 +0,0 @@
|
||||
package com.example.sbcamel.service;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;
|
||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
||||
import org.apache.hc.core5.http.ClassicHttpResponse;
|
||||
import org.apache.hc.core5.http.HttpException;
|
||||
import org.apache.hc.core5.http.io.HttpClientResponseHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.common.collect.MapDifference;
|
||||
import com.google.common.collect.MapDifference.ValueDifference;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
public class InspectionClient {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(InspectionClient.class);
|
||||
|
||||
@Autowired
|
||||
private CloseableHttpClient httpClient;
|
||||
|
||||
@Autowired
|
||||
private EmailService emailService;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@Value("${app.inspection-client.email-password:}")
|
||||
private String smtpPassword;
|
||||
|
||||
@Value("${app.inspection-client.email-sender:}")
|
||||
private String fromAddress;
|
||||
|
||||
@Value("${app.inspection-client.email-recipient:}")
|
||||
private String[] toAddresses;
|
||||
|
||||
@Value("${app.inspection-client.http-url}")
|
||||
private String url;
|
||||
|
||||
@Value("${app.inspection-client.http-method}")
|
||||
private String httpMethod;
|
||||
|
||||
@Value("${app.inspection-client.expected-result-file-path}")
|
||||
private String expectedResultFilePath;
|
||||
|
||||
@Value("${app.inspection-client.alert-subject}")
|
||||
private String alertSubject;
|
||||
|
||||
@Value("${app.inspection-client.http-username}")
|
||||
private String username;
|
||||
|
||||
@Value("${app.inspection-client.http-password}")
|
||||
private String password;
|
||||
|
||||
private static final String getBasicAuthenticationHeader(String username, String password) {
|
||||
String valueToEncode = username + ":" + password;
|
||||
return "Basic " + Base64.getEncoder().encodeToString(valueToEncode.getBytes());
|
||||
}
|
||||
|
||||
public void sendMessage() {
|
||||
try {
|
||||
File jsonFile = new File(expectedResultFilePath);
|
||||
if (!jsonFile.exists()) {
|
||||
logger.info("file does not exist: {}", expectedResultFilePath);
|
||||
return;
|
||||
}
|
||||
String jsonString = FileUtils.readFileToString(jsonFile, StandardCharsets.UTF_8);
|
||||
logger.info("expected result: {}", jsonString);
|
||||
HashMap<String, Object> expectedMap = convertStringToMap(jsonString);
|
||||
logger.info("calling {} {}", httpMethod, url);
|
||||
|
||||
HttpUriRequestBase req = new HttpUriRequestBase(httpMethod, URI.create(url));
|
||||
req.addHeader("Authorization", getBasicAuthenticationHeader(username, password));
|
||||
Pair<Boolean, Boolean> sendEmailResult = httpClient.execute(req,
|
||||
new HttpClientResponseHandler<Pair<Boolean, Boolean>>() {
|
||||
|
||||
@Override
|
||||
public Pair<Boolean, Boolean> handleResponse(ClassicHttpResponse result)
|
||||
throws HttpException, IOException {
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
result.getEntity().writeTo(baos);
|
||||
String responseText = new String(baos.toByteArray(), StandardCharsets.UTF_8);
|
||||
logger.info("actual result: {}", responseText);
|
||||
|
||||
if (StringUtils.isEmpty(responseText)) {
|
||||
logger.error("actual result is empty!");
|
||||
return Pair.of(Boolean.FALSE, Boolean.FALSE);
|
||||
}
|
||||
baos.close();
|
||||
try {
|
||||
HashMap<String, Object> resultMap = convertStringToMap(responseText);
|
||||
MapDifference<String, Object> diff = Maps.difference(expectedMap, resultMap);
|
||||
logger.info("diff.areEqual: {}", diff.areEqual());
|
||||
StringBuilder contentBuilder = new StringBuilder();
|
||||
if (!diff.areEqual()) {
|
||||
Map<String, ValueDifference<Object>> entriesDiffering = diff.entriesDiffering();
|
||||
entriesDiffering.entrySet().stream().forEach(entry -> {
|
||||
logger.info("entriesDiffering key: {}", entry.getKey());
|
||||
logger.info("entriesDiffering expected: {}", entry.getValue().leftValue());
|
||||
logger.info("entriesDiffering actual: {}", entry.getValue().rightValue());
|
||||
contentBuilder.append(entry.getKey() + "<br/>\n");
|
||||
contentBuilder.append("EXPECTED: " + entry.getValue().leftValue() + "<br/>\n");
|
||||
contentBuilder.append("ACTUAL: " + entry.getValue().rightValue() + "<br/>\n");
|
||||
contentBuilder.append("<br/>\n");
|
||||
});
|
||||
return Pair.of(Boolean.TRUE, emailService.sendEmail(fromAddress, smtpPassword,
|
||||
toAddresses, alertSubject, contentBuilder.toString()));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.error("Error occurred while parsing message", e);
|
||||
}
|
||||
return Pair.of(Boolean.FALSE, Boolean.FALSE);
|
||||
}
|
||||
|
||||
});
|
||||
logger.info("send email result: {}", sendEmailResult);
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("Error occurred while preparing to send message", e);
|
||||
}
|
||||
}
|
||||
|
||||
public HashMap<String, Object> convertStringToMap(String jsonString) throws IOException {
|
||||
TypeReference<java.util.HashMap<String, Object>> ref = new TypeReference<>() {
|
||||
};
|
||||
return new HashMap<>(objectMapper.readValue(jsonString, ref));
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getHttpMethod() {
|
||||
return httpMethod;
|
||||
}
|
||||
|
||||
public void setHttpMethod(String httpMethod) {
|
||||
this.httpMethod = httpMethod;
|
||||
}
|
||||
}
|
||||
@ -1,99 +0,0 @@
|
||||
package com.example.sbcamel.service;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
/**
|
||||
* User entity
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class Session implements Serializable {
|
||||
|
||||
private UUID sessionId;
|
||||
|
||||
@NotNull
|
||||
@Size(min = 3, max = 40)
|
||||
private String username;
|
||||
|
||||
@NotNull
|
||||
@Size(min = 3, max = 40)
|
||||
private String password;
|
||||
|
||||
@NotNull
|
||||
private String selector1;
|
||||
|
||||
@NotNull
|
||||
private String selector2;
|
||||
|
||||
@NotNull
|
||||
private String selector3;
|
||||
|
||||
public Session() {
|
||||
}
|
||||
|
||||
public Session(UUID sessionId, @NotNull @Size(min = 3, max = 40) String username,
|
||||
@NotNull @Size(min = 3, max = 40) String password) {
|
||||
this.sessionId = sessionId;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public UUID getSessionId() {
|
||||
return sessionId;
|
||||
}
|
||||
|
||||
public void setSessionId(UUID sessionId) {
|
||||
this.sessionId = sessionId;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getSelector1() {
|
||||
return selector1;
|
||||
}
|
||||
|
||||
public void setSelector1(String selector1) {
|
||||
this.selector1 = selector1;
|
||||
}
|
||||
|
||||
public String getSelector2() {
|
||||
return selector2;
|
||||
}
|
||||
|
||||
public void setSelector2(String selector2) {
|
||||
this.selector2 = selector2;
|
||||
}
|
||||
|
||||
public String getSelector3() {
|
||||
return selector3;
|
||||
}
|
||||
|
||||
public void setSelector3(String selector3) {
|
||||
this.selector3 = selector3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ReflectionToStringBuilder.toString(this);
|
||||
}
|
||||
}
|
||||
@ -1,46 +0,0 @@
|
||||
package com.example.sbcamel.service;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
|
||||
/**
|
||||
* Service interface for managing sessions.
|
||||
*/
|
||||
public interface SessionService {
|
||||
|
||||
@POST
|
||||
@Path("/session")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
Session updateSession(@Valid Session session);
|
||||
|
||||
@GET
|
||||
@Path("/session/{sessionId}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
Session findSession(@PathParam("sessionId") UUID sessionId);
|
||||
|
||||
@GET
|
||||
@Path("/session")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
Collection<Session> findSessions();
|
||||
|
||||
@POST
|
||||
@Path("/inspect/{sessionId}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
Map<String, List<String>> inspect(@PathParam("sessionId") UUID sessionId);
|
||||
|
||||
@POST
|
||||
@Path("/test")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
Map<String, Map<String, List<String>>> test(List<String> selectors);
|
||||
}
|
||||
@ -1,33 +0,0 @@
|
||||
package com.example.sbcamel.service;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.ibatis.type.BaseTypeHandler;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
|
||||
public class UuidTypeHandler extends BaseTypeHandler<UUID> {
|
||||
@Override
|
||||
public void setNonNullParameter(PreparedStatement ps, int i, UUID parameter, JdbcType jdbcType)
|
||||
throws SQLException {
|
||||
ps.setObject(i, parameter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getNullableResult(ResultSet rs, String columnName) throws SQLException {
|
||||
return rs.getObject(columnName, UUID.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
|
||||
return rs.getObject(columnIndex, UUID.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
|
||||
return cs.getObject(columnIndex, UUID.class);
|
||||
}
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:task="http://www.springframework.org/schema/task"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/task https://www.springframework.org/schema/task/spring-task.xsd
|
||||
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<task:scheduler id="inspectionScheduler" pool-size="2" />
|
||||
|
||||
<bean id="inspectionClient"
|
||||
class="com.example.sbcamel.service.InspectionClient">
|
||||
</bean>
|
||||
|
||||
<task:scheduled-tasks scheduler="inspectionScheduler">
|
||||
<task:scheduled ref="inspectionClient"
|
||||
method="sendMessage" cron="0 * * * * ?" />
|
||||
</task:scheduled-tasks>
|
||||
|
||||
</beans>
|
||||
Loading…
Reference in new issue