v3.1.0 Added test-api, update-session/inspection response body

prototype
Yan 7 months ago
parent 4bfe1461d2
commit be9d328eee

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>camel-springboot-activemq6-example</artifactId>
<version>3.0.4</version>
<version>3.1.0</version>
<name>camel-springboot-activemq6-example</name>
<properties>
@ -18,6 +18,7 @@
<mybatis-spring.version>3.0.4</mybatis-spring.version>
<guava.version>33.1.0-jre</guava.version>
<maven-compiler-plugin.version>3.14.0</maven-compiler-plugin.version>
<jsoup.version>1.19.1</jsoup.version>
</properties>
<dependencyManagement>
@ -139,6 +140,11 @@
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>${jsoup.version}</version>
</dependency>
</dependencies>
<build>
<plugins>

@ -4,6 +4,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.example.sbcamel.processor.InspectionProcessor;
import com.example.sbcamel.processor.TestProcessor;
import com.fasterxml.jackson.jakarta.rs.json.JacksonJsonProvider;
@Configuration
@ -18,4 +19,9 @@ public class AppConfig {
public InspectionProcessor inspectionProcessor() {
return new InspectionProcessor();
}
@Bean
public TestProcessor testProcessor() {
return new TestProcessor();
}
}

@ -3,10 +3,8 @@ 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.bean.validator.BeanValidationException;
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;
@ -14,6 +12,7 @@ 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;
@ -21,8 +20,12 @@ 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;
@ -33,26 +36,27 @@ public class CamelRouter extends RouteBuilder {
@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 {
// 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()}"));
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("bean-validator:user").to("activemq6:queue:" + queueName).process(exchange -> {
.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")) {
@ -66,14 +70,20 @@ public class CamelRouter extends RouteBuilder {
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")
.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("login"))
.when(header(BeanConstants.BEAN_METHOD_NAME).isEqualTo("inspect"))
.to("mybatis:" + SessionMapper.class.getName() + ".findSession?statementType=SelectOne")
.process(inspectionProcessor).end().marshal().json(JsonLibrary.Jackson);
.process(inspectionProcessor)
.when(header(BeanConstants.BEAN_METHOD_NAME).isEqualTo("test"))
.process(testProcessor)
.end().marshal().json(JsonLibrary.Jackson);
}
}

@ -15,20 +15,31 @@ import com.example.sbcamel.service.UuidTypeHandler;
public interface SessionMapper {
@Insert({ "<script>",
"MERGE INTO public.session (sessionId, username, password) KEY (sessionId) VALUES (#{sessionId, javaType=java.util.UUID, "
+ "jdbcType=OTHER, typeHandler=com.example.sbcamel.service.UuidTypeHandler}, #{username}, #{password}) ",
"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>" })
Session updateSession(Session session);
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") })
@Select({ "<script>", "select sessionId, username, password from public.session where sessionId=#{list[0], javaType=java.util.UUID, "
@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") })
@Select({ "<script>", "select sessionId, username, password from public.session order by sessionId", "</script>" })
@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,5 +1,10 @@
package com.example.sbcamel.processor;
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.WebClient;
@ -8,6 +13,10 @@ 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;
@ -66,20 +75,51 @@ public class InspectionProcessor implements Processor {
loginBtn.click();
Thread.sleep(loginWaitMillis);
HtmlPage userPage = webClient.getPage(userPageUrl);
logger.info("userPage: {}", userPage.asXml());
logger.info("userPage hashcode: {}", userPage.hashCode());
Map<String, List<String>> reply1 = new HashMap<>();
HtmlPage vip1Page = webClient.getPage(vip1PageUrl);
logger.info("vip1Page: {}", vip1Page.asXml());
Document doc = Jsoup.parse(vip1Page.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.info("[vip1Page] {} -> {}", selector, element.html());
selectedList.add(element.html());
}
reply1.put(selector, selectedList);
}
Map<String, List<String>> reply2 = new HashMap<>();
HtmlPage vip2Page = webClient.getPage(vip2PageUrl);
logger.info("vip2Page: {}", vip2Page.asXml());
doc = Jsoup.parse(vip2Page.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.info("[vip2Page] {} -> {}", selector, element.html());
selectedList.add(element.html());
}
reply2.put(selector, selectedList);
}
Map<String, List<String>> reply3 = new HashMap<>();
HtmlPage vip3Page = webClient.getPage(vip3PageUrl);
logger.info("vip3Page: {}", vip3Page.asXml());
doc = Jsoup.parse(vip3Page.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.info("[vip3Page] {} -> {}", selector, element.html());
selectedList.add(element.html());
}
reply3.put(selector, selectedList);
}
HtmlPage logoutPage = webClient.getPage(logoutUrl);
logger.info("logoutPage: {}", logoutPage.asXml());
webClient.getPage(logoutUrl);
exchange.getMessage().setBody(Map.of("vip1Page", reply1, "vip2Page", reply2, "vip3Page", reply3));
} catch (Exception e) {
logger.error("LoginProcessor process error!", e);

@ -0,0 +1,54 @@
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);
}
}

@ -25,6 +25,15 @@ public class Session implements Serializable {
@Size(min = 3, max = 40)
private String password;
@NotNull
private String selector1;
@NotNull
private String selector2;
@NotNull
private String selector3;
public Session() {
}
@ -59,6 +68,30 @@ public class Session implements Serializable {
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,6 +1,8 @@
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;
@ -33,7 +35,12 @@ public interface SessionService {
Collection<Session> findSessions();
@POST
@Path("/login/{sessionId}")
@Path("/inspect/{sessionId}")
@Produces(MediaType.APPLICATION_JSON)
Session login(@PathParam("sessionId") UUID sessionId);
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);
}
Loading…
Cancel
Save