iterator = load.iterator();
+ while (iterator.hasNext()) {
+ cacheList.add(iterator.next());
+ }
+ }
+ }
+
+
+ public static HttpMessageConverter
getSupportedConverter(P p, R r, ServletAdapter adapter) {
+ synchronized (HttpMessageConvertFactory.class) {
+ if (CollectionUtil.isNotEmpty(cacheList)) {
+ for (HttpMessageConverter converter : cacheList) {
+ if (converter.match(p, r, adapter)) {
+ return converter;
+ }
+ }
+ }
+ return DefaultHttpMessageConverter.getInstance();
+ }
+ }
+
+
+}
diff --git a/arex-instrumentation/servlet/arex-httpservlet/src/main/java/io/arex/inst/httpservlet/convert/HttpMessageConverter.java b/arex-instrumentation/servlet/arex-httpservlet/src/main/java/io/arex/inst/httpservlet/convert/HttpMessageConverter.java
new file mode 100644
index 000000000..52f2f94ea
--- /dev/null
+++ b/arex-instrumentation/servlet/arex-httpservlet/src/main/java/io/arex/inst/httpservlet/convert/HttpMessageConverter.java
@@ -0,0 +1,10 @@
+package io.arex.inst.httpservlet.convert;
+
+import io.arex.inst.httpservlet.adapter.ServletAdapter;
+
+public interface HttpMessageConverter {
+
+ boolean match(HttpServletRequest request,HttpServletResponse response, ServletAdapter adapter);
+ byte[] getRequest(HttpServletRequest request, ServletAdapter adapter);
+ byte[] getResponse(HttpServletResponse request, ServletAdapter adapter);
+}
diff --git a/arex-instrumentation/servlet/arex-httpservlet/src/main/java/io/arex/inst/httpservlet/convert/impl/ApplicationJsonBodyConverter.java b/arex-instrumentation/servlet/arex-httpservlet/src/main/java/io/arex/inst/httpservlet/convert/impl/ApplicationJsonBodyConverter.java
new file mode 100644
index 000000000..4e5d760b8
--- /dev/null
+++ b/arex-instrumentation/servlet/arex-httpservlet/src/main/java/io/arex/inst/httpservlet/convert/impl/ApplicationJsonBodyConverter.java
@@ -0,0 +1,36 @@
+package io.arex.inst.httpservlet.convert.impl;
+
+import io.arex.agent.bootstrap.util.StringUtil;
+import io.arex.inst.httpservlet.adapter.ServletAdapter;
+import io.arex.inst.httpservlet.convert.HttpMessageConverter;
+
+public class ApplicationJsonBodyConverter implements HttpMessageConverter {
+
+ private static final String CONTENT_TYPE = "application/json";
+
+ @Override
+ public boolean match(HttpServletRequest request, HttpServletResponse response, ServletAdapter adapter) {
+ if (request == null || response ==null || adapter == null) {
+ return false;
+ }
+ String contentType = adapter.getContentType(request);
+ return StringUtil.isNotEmpty(contentType) && contentType.contains(CONTENT_TYPE);
+ }
+
+ @Override
+ public byte[] getRequest(HttpServletRequest request, ServletAdapter adapter) {
+ if (request == null || adapter == null) {
+ return new byte[0];
+ }
+ return adapter.getRequestBytes(request);
+ }
+
+ @Override
+ public byte[] getResponse(HttpServletResponse response, ServletAdapter adapter) {
+ return new byte[0];
+ }
+}
+
+
+
+
diff --git a/arex-instrumentation/servlet/arex-httpservlet/src/main/java/io/arex/inst/httpservlet/convert/impl/ApplicationXmlBodyConverter.java b/arex-instrumentation/servlet/arex-httpservlet/src/main/java/io/arex/inst/httpservlet/convert/impl/ApplicationXmlBodyConverter.java
new file mode 100644
index 000000000..aa84bd6d4
--- /dev/null
+++ b/arex-instrumentation/servlet/arex-httpservlet/src/main/java/io/arex/inst/httpservlet/convert/impl/ApplicationXmlBodyConverter.java
@@ -0,0 +1,31 @@
+package io.arex.inst.httpservlet.convert.impl;
+
+import io.arex.agent.bootstrap.util.StringUtil;
+import io.arex.inst.httpservlet.adapter.ServletAdapter;
+import io.arex.inst.httpservlet.convert.HttpMessageConverter;
+
+
+public class ApplicationXmlBodyConverter implements HttpMessageConverter {
+
+ private static final String CONTENT_TYPE = "application/xml";
+
+ @Override
+ public boolean match(HttpServletRequest request, HttpServletResponse response, ServletAdapter adapter) {
+ if (request == null || response ==null || adapter == null) {
+ return false;
+ }
+ String contentType = adapter.getContentType(request);
+ return StringUtil.isNotEmpty(contentType) && contentType.contains(CONTENT_TYPE);
+ }
+
+ @Override
+ public byte[] getRequest(HttpServletRequest request, ServletAdapter adapter) {
+ return new byte[0];
+ }
+
+ @Override
+ public byte[] getResponse(HttpServletResponse response, ServletAdapter adapter) {
+ return new byte[0];
+ }
+
+}
\ No newline at end of file
diff --git a/arex-instrumentation/servlet/arex-httpservlet/src/main/java/io/arex/inst/httpservlet/convert/impl/DefaultHttpMessageConverter.java b/arex-instrumentation/servlet/arex-httpservlet/src/main/java/io/arex/inst/httpservlet/convert/impl/DefaultHttpMessageConverter.java
new file mode 100644
index 000000000..33ddf83ee
--- /dev/null
+++ b/arex-instrumentation/servlet/arex-httpservlet/src/main/java/io/arex/inst/httpservlet/convert/impl/DefaultHttpMessageConverter.java
@@ -0,0 +1,35 @@
+package io.arex.inst.httpservlet.convert.impl;
+
+import io.arex.inst.httpservlet.adapter.ServletAdapter;
+import io.arex.inst.httpservlet.convert.HttpMessageConverter;
+
+public class DefaultHttpMessageConverter implements HttpMessageConverter {
+
+ private DefaultHttpMessageConverter() {
+
+ }
+
+ private static class SingletonHolder {
+ private static final DefaultHttpMessageConverter INSTANCE = new DefaultHttpMessageConverter();
+ }
+
+ public static DefaultHttpMessageConverter getInstance() {
+ return SingletonHolder.INSTANCE;
+ }
+
+
+ @Override
+ public boolean match(HttpServletRequest request, HttpServletResponse response, ServletAdapter adapter) {
+ return false;
+ }
+
+ @Override
+ public byte[] getRequest(HttpServletRequest request, ServletAdapter adapter) {
+ return new byte[0];
+ }
+
+ @Override
+ public byte[] getResponse(HttpServletResponse response, ServletAdapter adapter) {
+ return new byte[0];
+ }
+}
diff --git a/arex-instrumentation/servlet/arex-httpservlet/src/main/resources/META-INF/services/io.arex.inst.httpservlet.convert.HttpMessageConverter b/arex-instrumentation/servlet/arex-httpservlet/src/main/resources/META-INF/services/io.arex.inst.httpservlet.convert.HttpMessageConverter
new file mode 100644
index 000000000..24bad6272
--- /dev/null
+++ b/arex-instrumentation/servlet/arex-httpservlet/src/main/resources/META-INF/services/io.arex.inst.httpservlet.convert.HttpMessageConverter
@@ -0,0 +1,2 @@
+io.arex.inst.httpservlet.convert.impl.ApplicationJsonBodyConverter
+io.arex.inst.httpservlet.convert.impl.ApplicationXmlBodyConverter
\ No newline at end of file
diff --git a/arex-instrumentation/servlet/arex-httpservlet/src/test/java/io/arex/inst/httpservlet/convert/HttpMessageConvertFactoryTest.java b/arex-instrumentation/servlet/arex-httpservlet/src/test/java/io/arex/inst/httpservlet/convert/HttpMessageConvertFactoryTest.java
new file mode 100644
index 000000000..6778462f2
--- /dev/null
+++ b/arex-instrumentation/servlet/arex-httpservlet/src/test/java/io/arex/inst/httpservlet/convert/HttpMessageConvertFactoryTest.java
@@ -0,0 +1,51 @@
+package io.arex.inst.httpservlet.convert;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.when;
+
+import io.arex.inst.httpservlet.adapter.impl.ServletAdapterImplV3;
+import io.arex.inst.httpservlet.adapter.impl.ServletAdapterImplV5;
+import io.arex.inst.httpservlet.convert.impl.DefaultHttpMessageConverter;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class HttpMessageConvertFactoryTest {
+
+ HttpServletRequest mockRequest = Mockito.mock(HttpServletRequest.class);
+ HttpServletResponse mockResponse = Mockito.mock(HttpServletResponse.class);
+ ServletAdapterImplV3 instance3 = ServletAdapterImplV3.getInstance();
+ ServletAdapterImplV5 instance5 = ServletAdapterImplV5.getInstance();
+ jakarta.servlet.http.HttpServletRequest mockRequest5 = Mockito.mock(jakarta.servlet.http.HttpServletRequest.class);
+ jakarta.servlet.http.HttpServletResponse mockResponse5 = Mockito.mock(jakarta.servlet.http.HttpServletResponse.class);
+
+ @BeforeEach
+ void setUp() {
+ }
+
+ @AfterEach
+ void tearDown() {
+ }
+
+ @Test
+ void getOne(){
+ when(mockRequest.getContentType()).thenReturn("application/json");
+ when(mockRequest5.getContentType()).thenReturn("application/json");
+ assertNotNull(HttpMessageConvertFactory.getSupportedConverter(mockRequest,mockResponse,instance3));
+ assertNotNull(HttpMessageConvertFactory.getSupportedConverter(mockRequest5,mockResponse5,instance5));
+ }
+
+ @Test
+ void getDefault(){
+ when(mockRequest.getContentType()).thenReturn("application/jn");
+ when(mockRequest5.getContentType()).thenReturn("application/jn");
+
+ assertTrue(HttpMessageConvertFactory.getSupportedConverter(mockRequest,mockResponse,instance3) instanceof DefaultHttpMessageConverter);
+ assertTrue(HttpMessageConvertFactory.getSupportedConverter(mockRequest5,mockResponse5,instance5) instanceof DefaultHttpMessageConverter);
+ }
+
+}
diff --git a/arex-instrumentation/servlet/arex-httpservlet/src/test/java/io/arex/inst/httpservlet/convert/impl/ApplicationJsonBodyConvertTest.java b/arex-instrumentation/servlet/arex-httpservlet/src/test/java/io/arex/inst/httpservlet/convert/impl/ApplicationJsonBodyConvertTest.java
new file mode 100644
index 000000000..38830c02f
--- /dev/null
+++ b/arex-instrumentation/servlet/arex-httpservlet/src/test/java/io/arex/inst/httpservlet/convert/impl/ApplicationJsonBodyConvertTest.java
@@ -0,0 +1,87 @@
+package io.arex.inst.httpservlet.convert.impl;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.when;
+
+
+import io.arex.inst.httpservlet.adapter.impl.ServletAdapterImplV3;
+import io.arex.inst.httpservlet.adapter.impl.ServletAdapterImplV5;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class ApplicationJsonBodyConvertTest {
+
+ HttpServletRequest mockRequest = Mockito.mock(HttpServletRequest.class);
+ HttpServletResponse mockResponse = Mockito.mock(HttpServletResponse.class);
+
+ ServletAdapterImplV3 instance3 = ServletAdapterImplV3.getInstance();
+ ServletAdapterImplV5 instance5 = ServletAdapterImplV5.getInstance();
+ jakarta.servlet.http.HttpServletRequest mockRequest5 = Mockito.mock(jakarta.servlet.http.HttpServletRequest.class);
+ jakarta.servlet.http.HttpServletResponse mockResponse5 = Mockito.mock(jakarta.servlet.http.HttpServletResponse.class);
+
+
+ static ApplicationJsonBodyConverter applicationJsonBodyConvert = null;
+
+
+
+ @BeforeEach
+ void setUp() {
+ applicationJsonBodyConvert = new ApplicationJsonBodyConverter();
+
+ }
+
+ @AfterEach
+ void tearDown() {
+ }
+
+ @Test
+ void match() {
+ when(mockRequest.getContentType()).thenReturn("application/json");
+ when(mockRequest5.getContentType()).thenReturn("application/json");
+ assertEquals(true, applicationJsonBodyConvert.match(mockRequest,mockResponse,instance3));
+ assertEquals(true, applicationJsonBodyConvert.match(mockRequest5,mockResponse5,instance5));
+ }
+
+
+ @Test
+ void notMatch1() {
+ when(mockRequest.getContentType()).thenReturn("application/jn");
+ when(mockRequest5.getContentType()).thenReturn("application/n");
+ assertEquals(false, applicationJsonBodyConvert.match(mockRequest,mockResponse,instance3));
+ assertEquals(false, applicationJsonBodyConvert.match(mockRequest5,mockResponse5,instance5));
+ }
+
+
+ @Test
+ void notMatch2() {
+ assertEquals(false, applicationJsonBodyConvert.match(null,mockResponse,instance3));
+ assertEquals(false, applicationJsonBodyConvert.match(null,mockResponse5,instance5));
+ }
+
+
+ @Test
+ void get0Request() {
+ assertEquals(0, applicationJsonBodyConvert.getRequest(null,instance3).length);
+ assertEquals(0, applicationJsonBodyConvert.getRequest(null,instance5).length);
+ }
+
+ @Test
+ void getRequest() {
+ assertEquals(0, applicationJsonBodyConvert.getRequest(instance3.wrapRequest(mockRequest),instance3).length);
+ assertEquals(0, applicationJsonBodyConvert.getRequest(instance5.wrapRequest(mockRequest5),instance5).length);
+ }
+
+
+ @Test
+ void getResponse() {
+ assertEquals(0, applicationJsonBodyConvert.getResponse(instance3.wrapResponse(mockResponse),instance3).length);
+ assertEquals(0, applicationJsonBodyConvert.getResponse(instance5.wrapResponse(mockResponse5),instance5).length);
+ }
+
+}
diff --git a/arex-instrumentation/servlet/arex-httpservlet/src/test/java/io/arex/inst/httpservlet/convert/impl/ApplicationXmlBodyConvertTest.java b/arex-instrumentation/servlet/arex-httpservlet/src/test/java/io/arex/inst/httpservlet/convert/impl/ApplicationXmlBodyConvertTest.java
new file mode 100644
index 000000000..09cb0276f
--- /dev/null
+++ b/arex-instrumentation/servlet/arex-httpservlet/src/test/java/io/arex/inst/httpservlet/convert/impl/ApplicationXmlBodyConvertTest.java
@@ -0,0 +1,86 @@
+package io.arex.inst.httpservlet.convert.impl;
+
+import io.arex.inst.httpservlet.adapter.impl.ServletAdapterImplV3;
+import io.arex.inst.httpservlet.adapter.impl.ServletAdapterImplV5;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.mockito.Mockito.when;
+
+public class ApplicationXmlBodyConvertTest {
+
+ HttpServletRequest mockRequest = Mockito.mock(HttpServletRequest.class);
+ HttpServletResponse mockResponse = Mockito.mock(HttpServletResponse.class);
+
+ ServletAdapterImplV3 instance3 = ServletAdapterImplV3.getInstance();
+ ServletAdapterImplV5 instance5 = ServletAdapterImplV5.getInstance();
+ jakarta.servlet.http.HttpServletRequest mockRequest5 = Mockito.mock(jakarta.servlet.http.HttpServletRequest.class);
+ jakarta.servlet.http.HttpServletResponse mockResponse5 = Mockito.mock(jakarta.servlet.http.HttpServletResponse.class);
+
+
+ static ApplicationXmlBodyConverter applicationXmlBodyConvert = null;
+
+
+
+ @BeforeEach
+ void setUp() {
+ applicationXmlBodyConvert = new ApplicationXmlBodyConverter();
+
+ }
+
+ @AfterEach
+ void tearDown() {
+ }
+
+ @Test
+ void match() {
+ when(mockRequest.getContentType()).thenReturn("application/xml");
+ when(mockRequest5.getContentType()).thenReturn("application/xml");
+ assertEquals(true, applicationXmlBodyConvert.match(mockRequest,mockResponse,instance3));
+ assertEquals(true, applicationXmlBodyConvert.match(mockRequest5,mockResponse5,instance5));
+ }
+
+
+ @Test
+ void notMatch1() {
+ when(mockRequest.getContentType()).thenReturn("application/xl");
+ when(mockRequest5.getContentType()).thenReturn("application/xl");
+ assertEquals(false, applicationXmlBodyConvert.match(mockRequest,mockResponse,instance3));
+ assertEquals(false, applicationXmlBodyConvert.match(mockRequest5,mockResponse5,instance5));
+ }
+
+
+ @Test
+ void notMatch2() {
+ assertEquals(false, applicationXmlBodyConvert.match(null,mockResponse,instance3));
+ assertEquals(false, applicationXmlBodyConvert.match(null,mockResponse5,instance5));
+ }
+
+
+ @Test
+ void get0Request() {
+ assertEquals(0, applicationXmlBodyConvert.getRequest(null,instance3).length);
+ assertEquals(0, applicationXmlBodyConvert.getRequest(null,instance5).length);
+ }
+
+ @Test
+ void getRequest() {
+ assertEquals(0, applicationXmlBodyConvert.getRequest(instance3.wrapRequest(mockRequest),instance3).length);
+ assertEquals(0, applicationXmlBodyConvert.getRequest(instance5.wrapRequest(mockRequest5),instance5).length);
+ }
+
+
+ @Test
+ void getResponse() {
+ assertEquals(0, applicationXmlBodyConvert.getResponse(instance3.wrapResponse(mockResponse),instance3).length);
+ assertEquals(0, applicationXmlBodyConvert.getResponse(instance5.wrapResponse(mockResponse5),instance5).length);
+ }
+
+}
diff --git a/arex-instrumentation/servlet/arex-httpservlet/src/test/resources/META-INF.services/io.arex.inst.httpservlet.convert.BodyConverters b/arex-instrumentation/servlet/arex-httpservlet/src/test/resources/META-INF.services/io.arex.inst.httpservlet.convert.BodyConverters
new file mode 100644
index 000000000..4937f54ab
--- /dev/null
+++ b/arex-instrumentation/servlet/arex-httpservlet/src/test/resources/META-INF.services/io.arex.inst.httpservlet.convert.BodyConverters
@@ -0,0 +1,2 @@
+io.arex.inst.httpservlet.convert.impl.ApplicationJsonBodyConvert
+io.arex.inst.httpservlet.convert.impl.ApplicationXmlBodyConvert
\ No newline at end of file
From 72aac4e286fc3c7c84a4c2474ad565677a1d57c1 Mon Sep 17 00:00:00 2001
From: Montos <1367654518@qq.com>
Date: Thu, 27 Apr 2023 18:45:20 +0800
Subject: [PATCH 4/5] =?UTF-8?q?=E5=8E=BB=E9=99=A4=E5=85=B6=E4=BB=96task?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
修复tkmybatis序列化循环引用
修复tkmybatis序列化循环引用
去除其他task
---
.../java/io/arex/foundation/serializer/JacksonSerializer.java | 3 ---
1 file changed, 3 deletions(-)
diff --git a/arex-instrumentation-foundation/src/main/java/io/arex/foundation/serializer/JacksonSerializer.java b/arex-instrumentation-foundation/src/main/java/io/arex/foundation/serializer/JacksonSerializer.java
index 2be504b8f..2fd90d476 100644
--- a/arex-instrumentation-foundation/src/main/java/io/arex/foundation/serializer/JacksonSerializer.java
+++ b/arex-instrumentation-foundation/src/main/java/io/arex/foundation/serializer/JacksonSerializer.java
@@ -23,7 +23,6 @@
import org.apache.commons.lang3.time.FastDateFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import tk.mybatis.mapper.entity.EntityTable;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
@@ -169,8 +168,6 @@ private void configMapper() {
MAPPER.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false);
MAPPER.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true);
MAPPER.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
-
- MAPPER.addMixIn(EntityTable.class,IgnoreType.class);
}
private void customTimeFormatSerializer(SimpleModule module) {
From 5321bdc5253fc86fc27f148046a26413eaa68dfe Mon Sep 17 00:00:00 2001
From: MentosL <1367654518@qq.com>
Date: Sun, 7 May 2023 23:38:39 +0800
Subject: [PATCH 5/5] =?UTF-8?q?=E5=A2=9E=E5=8A=A0mqtt=E7=9B=B8=E5=85=B3?=
=?UTF-8?q?=E4=BB=A3=E7=A0=81=E9=80=BB=E8=BE=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
增加mqtt相关代码逻辑
Update pom.xml
新增mqtt
新增mqtt组件
调整
提交
Update MessageHeaderWarp.java
提交warp
增加mqtt代码
提交代码
提交部分代码
Delete io.arex.inst.httpservlet.convert.HttpMessageConverter
---
.../mq/arex-integration-mqtt/pom.xml | 8 +-
.../io/arex/inst/mqtt/MQTTAdapterHelper.java | 79 ++++++++-
.../arex/inst/mqtt/MessageQueueExtractor.java | 78 ++++++++
.../inst/mqtt/adapter/MessageAdapter.java | 28 +++
.../inst/mqtt/adapter/MessageAdapterImpl.java | 166 ++++++++++++++++++
.../mqtt/inst/EclipseInstrumentationV3.java | 63 -------
.../mqtt/inst/MQGenericInstrumentationV3.java | 66 +++++++
.../MQTTAdapterModuleInstrumentation.java | 4 +-
.../inst/mqtt/warp/GenericMessageWarp.java | 53 ++++++
.../inst/mqtt/warp/MessageHeaderWarp.java | 47 +++++
.../inst/mqtt/inst/MQTTAdapterHelperTest.java | 106 +++++++++++
.../mqtt/inst/MessageQueueExtractorTest.java | 115 ++++++++++++
.../inst/adapter/impl/MessageAdapterTest.java | 109 ++++++++++++
.../inst/MQGenericInstrumentationV3Test.java | 65 +++++++
.../MQTTAdapterModuleInstrumentationTest.java | 30 ++++
.../inst/warp/GenericMessageWarpTest.java | 65 +++++++
.../mqtt/inst/warp/MessageHeaderWarpTest.java | 54 ++++++
...t.httpservlet.convert.HttpMessageConverter | 2 -
...ex.inst.httpservlet.convert.BodyConverters | 2 -
19 files changed, 1061 insertions(+), 79 deletions(-)
create mode 100644 arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/MessageQueueExtractor.java
create mode 100644 arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/adapter/MessageAdapter.java
create mode 100644 arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/adapter/MessageAdapterImpl.java
delete mode 100644 arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/inst/EclipseInstrumentationV3.java
create mode 100644 arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/inst/MQGenericInstrumentationV3.java
create mode 100644 arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/warp/GenericMessageWarp.java
create mode 100644 arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/warp/MessageHeaderWarp.java
create mode 100644 arex-instrumentation/mq/arex-integration-mqtt/src/test/java/io/arex/inst/mqtt/inst/MQTTAdapterHelperTest.java
create mode 100644 arex-instrumentation/mq/arex-integration-mqtt/src/test/java/io/arex/inst/mqtt/inst/MessageQueueExtractorTest.java
create mode 100644 arex-instrumentation/mq/arex-integration-mqtt/src/test/java/io/arex/inst/mqtt/inst/adapter/impl/MessageAdapterTest.java
create mode 100644 arex-instrumentation/mq/arex-integration-mqtt/src/test/java/io/arex/inst/mqtt/inst/inst/MQGenericInstrumentationV3Test.java
create mode 100644 arex-instrumentation/mq/arex-integration-mqtt/src/test/java/io/arex/inst/mqtt/inst/inst/MQTTAdapterModuleInstrumentationTest.java
create mode 100644 arex-instrumentation/mq/arex-integration-mqtt/src/test/java/io/arex/inst/mqtt/inst/warp/GenericMessageWarpTest.java
create mode 100644 arex-instrumentation/mq/arex-integration-mqtt/src/test/java/io/arex/inst/mqtt/inst/warp/MessageHeaderWarpTest.java
delete mode 100644 arex-instrumentation/servlet/arex-httpservlet/src/main/resources/META-INF/services/io.arex.inst.httpservlet.convert.HttpMessageConverter
delete mode 100644 arex-instrumentation/servlet/arex-httpservlet/src/test/resources/META-INF.services/io.arex.inst.httpservlet.convert.BodyConverters
diff --git a/arex-instrumentation/mq/arex-integration-mqtt/pom.xml b/arex-instrumentation/mq/arex-integration-mqtt/pom.xml
index 6e84a2f46..92bf444c5 100644
--- a/arex-instrumentation/mq/arex-integration-mqtt/pom.xml
+++ b/arex-instrumentation/mq/arex-integration-mqtt/pom.xml
@@ -5,7 +5,7 @@
arex-instrumentation-parent
io.arex
- 0.2.0
+ ${revision}
../../pom.xml
4.0.0
@@ -14,9 +14,9 @@
- org.springframework.integration
- spring-integration-mqtt
- 5.5.10
+ org.springframework
+ spring-messaging
+ 5.3.4
provided
diff --git a/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/MQTTAdapterHelper.java b/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/MQTTAdapterHelper.java
index 3b816a64f..622a5e87c 100644
--- a/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/MQTTAdapterHelper.java
+++ b/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/MQTTAdapterHelper.java
@@ -1,16 +1,83 @@
package io.arex.inst.mqtt;
-import io.arex.agent.bootstrap.model.Mocker;
-import io.arex.inst.runtime.util.MockUtils;
+import io.arex.agent.bootstrap.internal.Pair;
+import io.arex.agent.bootstrap.util.StringUtil;
+import io.arex.inst.mqtt.adapter.MessageAdapter;
+import io.arex.inst.runtime.config.Config;
+import io.arex.inst.runtime.listener.CaseEvent;
+import io.arex.inst.runtime.listener.CaseEventDispatcher;
+import io.arex.inst.runtime.listener.EventSource;
+import io.arex.inst.runtime.model.ArexConstants;
+import io.arex.inst.runtime.util.IgnoreUtils;
/**
* MQTTAdapterHelper
*/
public class MQTTAdapterHelper {
- public static Mocker createMocker(String operationName) {
- Mocker mocker = MockUtils.createMqttConsumer(operationName);
- mocker.getTargetRequest().setType(Byte.class.getName());
- return mocker;
+ public static final String PROCESSED_FLAG = "arex-processed-flag";
+
+
+ public static Pair onServiceEnter(MessageAdapter adapter, Object messageChannel, Object message) {
+ Msg msg = adapter.warpMessage(message);
+ if (msg == null) {
+ return null;
+ }
+ if (adapter.markProcessed(msg, PROCESSED_FLAG)) {
+ return null;
+ }
+ MC mc = adapter.warpMC(messageChannel);
+ if (mc == null){
+ return null;
+ }
+ CaseEventDispatcher.onEvent(CaseEvent.ofEnterEvent());
+ if (shouldSkip(adapter, mc, msg)) {
+ return null;
+ }
+ String caseId = adapter.getHeader(mc, msg, ArexConstants.RECORD_ID);
+ String excludeMockTemplate = adapter.getHeader(mc, msg, ArexConstants.HEADER_EXCLUDE_MOCK);
+ CaseEventDispatcher.onEvent(CaseEvent.ofCreateEvent(EventSource.of(caseId, excludeMockTemplate)));
+ return Pair.of(mc,msg);
+ }
+
+
+ public static void onServiceExit(MessageAdapter adapter, Object messageChannel, Object message){
+ Msg msg = adapter.warpMessage(message);
+ MC mc = adapter.warpMC(messageChannel);
+ if (msg == null || mc == null) {
+ return;
+ }
+ adapter.removeHeader(mc,msg,PROCESSED_FLAG);
+ new MessageQueueExtractor<>( mc, msg,adapter).execute();
+ }
+
+
+
+
+ private static boolean shouldSkip(MessageAdapter adapter,MC mc, Msg msg){
+ String caseId = adapter.getHeader(mc, msg, ArexConstants.RECORD_ID);
+ // Replay scene
+ if (StringUtil.isNotEmpty(caseId)) {
+ return Config.get().getBoolean("arex.disable.replay", false);
+ }
+
+ String forceRecord = adapter.getHeader(mc, msg, ArexConstants.FORCE_RECORD);
+ // Do not skip if header with arex-force-record=true
+ if (Boolean.parseBoolean(forceRecord)) {
+ return false;
+ }
+ // Skip if request header with arex-replay-warm-up=true
+ if (Boolean.parseBoolean(adapter.getHeader(mc, msg, ArexConstants.REPLAY_WARM_UP))) {
+ return true;
+ }
+ String topic = adapter.getHeader(mc, msg, ArexConstants.REPLAY_WARM_UP);
+ if (StringUtil.isEmpty(topic)) {
+ return false;
+ }
+ if (IgnoreUtils.ignoreOperation(topic)) {
+ return true;
+ }
+ return Config.get().invalidRecord(topic);
}
+
}
diff --git a/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/MessageQueueExtractor.java b/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/MessageQueueExtractor.java
new file mode 100644
index 000000000..fd2c79fce
--- /dev/null
+++ b/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/MessageQueueExtractor.java
@@ -0,0 +1,78 @@
+package io.arex.inst.mqtt;
+
+import io.arex.agent.bootstrap.model.Mocker;
+import io.arex.inst.mqtt.adapter.MessageAdapter;
+import io.arex.inst.runtime.context.ContextManager;
+import io.arex.inst.runtime.model.ArexConstants;
+import io.arex.inst.runtime.util.LogUtil;
+import io.arex.inst.runtime.util.MockUtils;
+import org.springframework.messaging.MessageHeaders;
+
+import java.util.Base64;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author : MentosL
+ * @date : 2023/5/9 22:16
+ */
+public class MessageQueueExtractor {
+ private final MC messageChannel;
+ private final Msg message;
+ private final MessageAdapter adapter;
+
+
+ public MessageQueueExtractor(MC messageChannel, Msg message, MessageAdapter adapter) {
+ this.messageChannel = messageChannel;
+ this.message = message;
+ this.adapter = adapter;
+ }
+
+
+ public void execute() {
+ try {
+ if (message == null || messageChannel == null || adapter == null) {
+ return;
+ }
+ if (!ContextManager.needRecordOrReplay()) {
+ return;
+ }
+ executeBeforeProcess();
+ doExecute();
+ executeAfterProcess();
+ } catch (Exception e) {
+ LogUtil.warn("MessageQueue.execute", e);
+ }
+ }
+
+ private void executeBeforeProcess() {
+ if (ContextManager.needRecord()) {
+ adapter.addHeader(messageChannel,message, ArexConstants.RECORD_ID,ContextManager.currentContext().getCaseId());
+ }
+ if (ContextManager.needReplay()) {
+ adapter.addHeader(messageChannel,message, ArexConstants.REPLAY_ID,ContextManager.currentContext().getReplayId());
+ }
+ }
+ private void executeAfterProcess(){
+ // Think about other ways to replace the head
+ adapter.resetMsg(message);
+ }
+
+ private void doExecute() {
+ Mocker mocker = MockUtils.createMqttConsumer(adapter.getHeader(messageChannel,message,"mqtt_receivedTopic"));
+ MessageHeaders header = adapter.getHeader(messageChannel, message);
+ Map requestOrigin = new HashMap<>();
+ for (Map.Entry entry : header.entrySet()) {
+ requestOrigin.put(entry.getKey(), entry.getValue());
+ }
+ Map requestAttributes = Collections.singletonMap("Headers", requestOrigin);
+ mocker.getTargetRequest().setAttributes(requestAttributes);
+ mocker.getTargetRequest().setBody(Base64.getEncoder().encodeToString(adapter.getMsg(messageChannel,message)));
+ if (ContextManager.needReplay()) {
+ MockUtils.replayMocker(mocker);
+ } else if (ContextManager.needRecord()) {
+ MockUtils.recordMocker(mocker);
+ }
+ }
+}
diff --git a/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/adapter/MessageAdapter.java b/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/adapter/MessageAdapter.java
new file mode 100644
index 000000000..c573aadf7
--- /dev/null
+++ b/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/adapter/MessageAdapter.java
@@ -0,0 +1,28 @@
+package io.arex.inst.mqtt.adapter;
+
+import org.springframework.messaging.MessageHeaders;
+
+/**
+ * MessageAdapter
+ */
+public interface MessageAdapter {
+
+ MC warpMC(Object messageChannel);
+
+ Msg warpMessage(Object message);
+
+ byte[] getMsg(MC c, Msg msg);
+
+ MessageHeaders getHeader(MC c, Msg msg);
+
+ boolean markProcessed(Msg msg,String flagKey);
+
+ String getHeader(MC mc,Msg msg,String key);
+
+ boolean removeHeader(MC mc,Msg msg,String key);
+
+ boolean addHeader(MC mc,Msg msg,String key,String value);
+
+ Msg resetMsg(Msg msg);
+
+}
diff --git a/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/adapter/MessageAdapterImpl.java b/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/adapter/MessageAdapterImpl.java
new file mode 100644
index 000000000..79bd509fb
--- /dev/null
+++ b/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/adapter/MessageAdapterImpl.java
@@ -0,0 +1,166 @@
+package io.arex.inst.mqtt.adapter;
+
+import io.arex.agent.bootstrap.util.StringUtil;
+import io.arex.inst.mqtt.warp.GenericMessageWarp;
+import io.arex.inst.mqtt.warp.MessageHeaderWarp;
+import io.arex.inst.runtime.util.LogUtil;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.MessageChannel;
+import org.springframework.messaging.MessageHeaders;
+import org.springframework.messaging.support.GenericMessage;
+
+import java.lang.reflect.Field;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * MessageImpl
+ */
+public class MessageAdapterImpl implements MessageAdapter {
+
+ private static final MessageAdapterImpl INSTANCE = new MessageAdapterImpl();
+
+ public static MessageAdapterImpl getInstance() {
+ return INSTANCE;
+ }
+
+ @Override
+ public byte[] getMsg(MessageChannel messageChannel, Message msg) {
+ if (msg == null){
+ return new byte[]{};
+ }
+ Object payload = msg.getPayload();
+ if (payload == null){
+ return new byte[]{};
+ }
+ if (payload instanceof byte[]){
+ return ((byte[]) payload);
+ }
+ return payload.toString().getBytes(StandardCharsets.UTF_8);
+ }
+
+ @Override
+ public MessageChannel warpMC(Object messageChannel) {
+ if (messageChannel == null){
+ return null;
+ }
+ if (messageChannel instanceof MessageChannel){
+ return (MessageChannel) messageChannel;
+ }
+ return null;
+ }
+
+ @Override
+ public Message warpMessage(Object message) {
+ if (message == null){
+ return null;
+ }
+ if (message instanceof GenericMessageWarp){
+ return (GenericMessageWarp) message;
+ }
+
+ if (message instanceof GenericMessage) {
+ GenericMessage messageTemp = (GenericMessage) message;
+ MessageHeaders headers = messageTemp.getHeaders();
+ MessageHeaderWarp messageHeaderWarp = new MessageHeaderWarp(headers);
+ return new GenericMessageWarp(messageTemp.getPayload(), messageHeaderWarp);
+ }
+ if (message instanceof Message){
+ return (Message)message;
+ }
+ return null;
+ }
+
+ @Override
+ public MessageHeaders getHeader(MessageChannel messageChannel, Message msg) {
+ if (msg == null){
+ return null;
+ }
+ if (msg instanceof GenericMessageWarp){
+ GenericMessageWarp messageTemp = (GenericMessageWarp) msg;
+ return messageTemp.getMessageHeaderWarp();
+ }
+ return msg.getHeaders();
+ }
+
+ @Override
+ public boolean markProcessed(Message message, String flagKey) {
+ if (message == null){
+ return true;
+ }
+ if (message instanceof GenericMessageWarp){
+ GenericMessageWarp genericMessageWarp = (GenericMessageWarp)message;
+ genericMessageWarp.put(flagKey,Boolean.TRUE.toString());
+ }
+ return false;
+ }
+
+ @Override
+ public String getHeader(MessageChannel messageChannel, Message message, String key) {
+ if (message == null || StringUtil.isEmpty(key)){
+ return null;
+ }
+ if (message instanceof GenericMessageWarp) {
+ GenericMessageWarp genericMessageWarp = (GenericMessageWarp) message;
+ Object object = genericMessageWarp.get(key);
+ return object != null ? object.toString() : null;
+ }
+
+ if(message instanceof GenericMessage){
+ Object obj = message.getHeaders().get(key);
+ return obj != null ? obj.toString() : null;
+ }
+ if (message.getHeaders() != null){
+ Object obj = message.getHeaders().get(key);
+ return obj != null ? obj.toString() : null ;
+ }
+ return null;
+ }
+
+ @Override
+ public boolean removeHeader(MessageChannel messageChannel, Message message, String key) {
+ if (message == null || StringUtil.isEmpty(key)){
+ return false;
+ }
+ if (message instanceof GenericMessageWarp){
+ GenericMessageWarp genericMessageWarp = (GenericMessageWarp) message;
+ genericMessageWarp.removeHeader(key);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean addHeader(MessageChannel messageChannel, Message message, String key, String value) {
+ if (message == null ){
+ return false;
+ }
+ if (message instanceof GenericMessageWarp){
+ GenericMessageWarp genericMessageWarp = (GenericMessageWarp) message;
+ genericMessageWarp.put(key,value);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public Message resetMsg(Message message) {
+ if (message == null){
+ return null;
+ }
+ if (message instanceof GenericMessageWarp){
+ try {
+ GenericMessageWarp messageWarp = (GenericMessageWarp) message;
+ Field headers = message.getClass().getSuperclass().getDeclaredField("headers");
+ headers.setAccessible(true);
+ headers.set(message, messageWarp.getMessageHeaderWarp());
+ } catch (NoSuchFieldException e) {
+ LogUtil.warn("MessageAdapterImpl.resetMsg - NoSuchFieldException", e);
+ } catch (IllegalAccessException e) {
+ LogUtil.warn("MessageAdapterImpl.resetMsg - IllegalAccessException", e);
+ }
+ }
+ return message;
+ }
+
+
+}
diff --git a/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/inst/EclipseInstrumentationV3.java b/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/inst/EclipseInstrumentationV3.java
deleted file mode 100644
index 94f13ce4f..000000000
--- a/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/inst/EclipseInstrumentationV3.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package io.arex.inst.mqtt.inst;
-
-import io.arex.agent.bootstrap.model.Mocker;
-import io.arex.agent.bootstrap.util.StringUtil;
-import io.arex.inst.extension.MethodInstrumentation;
-import io.arex.inst.extension.TypeInstrumentation;
-import io.arex.inst.mqtt.MQTTAdapterHelper;
-import io.arex.inst.runtime.context.ContextManager;
-import io.arex.inst.runtime.util.MockUtils;
-import net.bytebuddy.asm.Advice;
-import net.bytebuddy.description.method.MethodDescription;
-import net.bytebuddy.description.type.TypeDescription;
-import net.bytebuddy.matcher.ElementMatcher;
-import org.eclipse.paho.client.mqttv3.MqttMessage;
-
-import java.util.Base64;
-import java.util.Collections;
-import java.util.List;
-
-import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
-import static net.bytebuddy.matcher.ElementMatchers.isInterface;
-import static net.bytebuddy.matcher.ElementMatchers.named;
-import static net.bytebuddy.matcher.ElementMatchers.not;
-import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
-
-/**
- * EclipseInstrumentationV3
- */
-public class EclipseInstrumentationV3 extends TypeInstrumentation {
- @Override
- protected ElementMatcher typeMatcher() {
- return not(isInterface()).and(hasSuperType(named("org.eclipse.paho.client.mqttv3.MqttCallback")));
- }
-
- @Override
- public List methodAdvices() {
- ElementMatcher matcher = named("messageArrived")
- .and(takesArgument(0, named("java.lang.String")))
- .and(takesArgument(1, named("org.eclipse.paho.client.mqttv3.MqttMessage")));
- return Collections.singletonList(new MethodInstrumentation(matcher, ArrivedAdvice.class.getName()));
- }
-
- public static class ArrivedAdvice {
-
- @Advice.OnMethodEnter(suppress = Throwable.class)
- public static void onEnter(@Advice.Argument(value = 0, readOnly = false) String topic,
- @Advice.Argument(value = 1, readOnly = false) MqttMessage mqttMessage) {
- if (StringUtil.isEmpty(topic) || mqttMessage == null) {
- return;
- }
- if (ContextManager.needRecordOrReplay()){
- Mocker mocker = MQTTAdapterHelper.createMocker(topic);
- mocker.getTargetRequest().setBody(Base64.getEncoder().encodeToString(mqttMessage.getPayload()));
- if (ContextManager.needReplay()) {
- MockUtils.replayMocker(mocker);
- } else if (ContextManager.needRecord()) {
- MockUtils.recordMocker(mocker);
- }
- }
- }
- }
-
-}
diff --git a/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/inst/MQGenericInstrumentationV3.java b/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/inst/MQGenericInstrumentationV3.java
new file mode 100644
index 000000000..92656bc56
--- /dev/null
+++ b/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/inst/MQGenericInstrumentationV3.java
@@ -0,0 +1,66 @@
+package io.arex.inst.mqtt.inst;
+
+import io.arex.agent.bootstrap.internal.Pair;
+import io.arex.inst.extension.MethodInstrumentation;
+import io.arex.inst.extension.TypeInstrumentation;
+import io.arex.inst.mqtt.MQTTAdapterHelper;
+import io.arex.inst.mqtt.adapter.MessageAdapterImpl;
+import net.bytebuddy.asm.Advice;
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.description.type.TypeDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.MessageChannel;
+
+import java.util.Collections;
+import java.util.List;
+
+import static io.arex.inst.extension.matcher.SafeExtendsClassMatcher.extendsClass;
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
+
+/**
+ * EclipseInstrumentationV3
+ */
+public class MQGenericInstrumentationV3 extends TypeInstrumentation {
+ @Override
+ public ElementMatcher typeMatcher() {
+ return extendsClass(named("org.springframework.messaging.core.AbstractMessageSendingTemplate"), false)
+ .and(named("org.springframework.messaging.core.GenericMessagingTemplate"));
+ }
+
+ @Override
+ public List methodAdvices() {
+ ElementMatcher matcher = named("doSend")
+ .and(takesArgument(0, named("org.springframework.messaging.MessageChannel")))
+ .and(takesArgument(1, named("org.springframework.messaging.Message")));
+ return Collections.singletonList(new MethodInstrumentation(matcher, ArrivedAdvice.class.getName()));
+ }
+
+ public static class ArrivedAdvice {
+
+ @Advice.OnMethodEnter(suppress = Throwable.class)
+ public static void onEnter(@Advice.Argument(value = 0, readOnly = false) MessageChannel messageChannel,
+ @Advice.Argument(value = 1, readOnly = false) Message> message,
+ @Advice.Local("channelMsgPair") Pair pair) {
+ Pair messageChannelMessagePair =
+ MQTTAdapterHelper.onServiceEnter(MessageAdapterImpl.getInstance(), messageChannel, message);
+ if (messageChannelMessagePair == null){
+ return;
+ }
+ pair = messageChannelMessagePair;
+ }
+
+ @Advice.OnMethodExit(suppress = Throwable.class)
+ public static void onExit(@Advice.Argument(value = 0, readOnly = false) MessageChannel messageChannel,
+ @Advice.Argument(value = 1, readOnly = false) Message> message,
+ @Advice.Local("channelMsgPair") Pair pair) {
+ if (pair != null){
+ message = pair.getSecond();
+ }
+ MQTTAdapterHelper.onServiceExit(MessageAdapterImpl.getInstance(), messageChannel, message);
+ }
+
+ }
+
+}
diff --git a/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/inst/MQTTAdapterModuleInstrumentation.java b/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/inst/MQTTAdapterModuleInstrumentation.java
index ac079daef..6c3aaa6ed 100644
--- a/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/inst/MQTTAdapterModuleInstrumentation.java
+++ b/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/inst/MQTTAdapterModuleInstrumentation.java
@@ -14,11 +14,11 @@
public class MQTTAdapterModuleInstrumentation extends ModuleInstrumentation {
public MQTTAdapterModuleInstrumentation() {
- super("mqtt-adapter");
+ super("mqtt");
}
@Override
public List instrumentationTypes() {
- return Arrays.asList(new EclipseInstrumentationV3());
+ return Arrays.asList(new MQGenericInstrumentationV3());
}
}
diff --git a/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/warp/GenericMessageWarp.java b/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/warp/GenericMessageWarp.java
new file mode 100644
index 000000000..7b509411c
--- /dev/null
+++ b/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/warp/GenericMessageWarp.java
@@ -0,0 +1,53 @@
+package io.arex.inst.mqtt.warp;
+
+import org.springframework.messaging.MessageHeaders;
+import org.springframework.messaging.support.GenericMessage;
+
+import java.util.Map;
+
+/**
+ * @author : MentosL
+ * @date : 2023/5/10 20:53
+ */
+public class GenericMessageWarp extends GenericMessage {
+
+ private MessageHeaderWarp messageHeaderWarp;
+
+ public GenericMessageWarp(Object payload) {
+ super(payload);
+ this.messageHeaderWarp = new MessageHeaderWarp(super.getHeaders());
+ }
+
+ public GenericMessageWarp(Object payload, Map headers) {
+ super(payload, headers);
+ this.messageHeaderWarp = new MessageHeaderWarp(headers);
+ }
+
+ public GenericMessageWarp(Object payload, MessageHeaders headers) {
+ super(payload, headers);
+ this.messageHeaderWarp = new MessageHeaderWarp(headers);
+ }
+
+ public void removeHeader(String key) {
+ if (this.messageHeaderWarp != null){
+ this.messageHeaderWarp.remove(key);
+ }
+ }
+
+ public void put(String key, String value) {
+ if (this.messageHeaderWarp != null) {
+ this.messageHeaderWarp.put(key, value);
+ }
+ }
+
+ public Object get(String key){
+ if (this.messageHeaderWarp != null) {
+ return this.messageHeaderWarp.get(key);
+ }
+ return getHeaders().get(key);
+ }
+
+ public MessageHeaderWarp getMessageHeaderWarp() {
+ return messageHeaderWarp;
+ }
+}
diff --git a/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/warp/MessageHeaderWarp.java b/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/warp/MessageHeaderWarp.java
new file mode 100644
index 000000000..a8284bfa4
--- /dev/null
+++ b/arex-instrumentation/mq/arex-integration-mqtt/src/main/java/io/arex/inst/mqtt/warp/MessageHeaderWarp.java
@@ -0,0 +1,47 @@
+package io.arex.inst.mqtt.warp;
+
+import org.springframework.messaging.MessageHeaders;
+
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * @author : MentosL
+ * @date : 2023/5/9 23:12
+ */
+public class MessageHeaderWarp extends MessageHeaders {
+
+
+ public MessageHeaderWarp(MessageHeaders messageHeaders) {
+ super(messageHeaders);
+ if (messageHeaders != null && messageHeaders.size() > 0){
+ if (messageHeaders.get(ID) != null){
+ this.put(ID,messageHeaders.get(ID));
+ }
+ if (messageHeaders.get(TIMESTAMP) != null){
+ this.put(TIMESTAMP,messageHeaders.get(TIMESTAMP));
+ }
+ }
+ }
+
+ public MessageHeaderWarp(Map headers) {
+ super(headers);
+ }
+
+ public MessageHeaderWarp(Map headers, UUID id, Long timestamp) {
+ super(headers, id, timestamp);
+ }
+
+ public Object put(String key, Object value){
+ if (value == null){
+ return null;
+ }
+ super.getRawHeaders().put(key,value);
+ return value;
+ }
+
+ public void remove(String key){
+ super.getRawHeaders().remove(key);
+ }
+
+}
diff --git a/arex-instrumentation/mq/arex-integration-mqtt/src/test/java/io/arex/inst/mqtt/inst/MQTTAdapterHelperTest.java b/arex-instrumentation/mq/arex-integration-mqtt/src/test/java/io/arex/inst/mqtt/inst/MQTTAdapterHelperTest.java
new file mode 100644
index 000000000..8b3aba92a
--- /dev/null
+++ b/arex-instrumentation/mq/arex-integration-mqtt/src/test/java/io/arex/inst/mqtt/inst/MQTTAdapterHelperTest.java
@@ -0,0 +1,106 @@
+package io.arex.inst.mqtt.inst;
+
+import io.arex.agent.bootstrap.internal.Pair;
+import io.arex.inst.mqtt.MQTTAdapterHelper;
+import io.arex.inst.mqtt.adapter.MessageAdapter;
+import io.arex.inst.mqtt.adapter.MessageAdapterImpl;
+import io.arex.inst.runtime.context.ContextManager;
+import io.arex.inst.runtime.context.RecordLimiter;
+import io.arex.inst.runtime.model.ArexConstants;
+import io.arex.inst.runtime.util.IgnoreUtils;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.MessageChannel;
+
+import java.util.Objects;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.params.provider.Arguments.arguments;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+
+/**
+ * @author : MentosL
+ * @date : 2023/5/16 20:53
+ */
+@ExtendWith(MockitoExtension.class)
+public class MQTTAdapterHelperTest {
+ static MessageAdapter messageAdapter;
+ static MessageChannel messageChannel;
+ static Message message;
+
+ @BeforeAll
+ static void setUp() {
+ messageAdapter = Mockito.mock(MessageAdapter.class);
+ messageChannel = Mockito.mock(MessageChannel.class);
+ message = Mockito.mock(Message.class);
+ }
+
+ @AfterAll
+ static void tearDown() {
+ messageAdapter = null;
+ messageChannel = null;
+ message = null;
+ Mockito.clearAllCaches();
+ }
+
+ @ParameterizedTest
+ @MethodSource("onServiceEnterCase")
+ void onServiceEnter(Runnable mocker, Predicate predicate) {
+ mocker.run();
+ Pair result = MQTTAdapterHelper.onServiceEnter(messageAdapter, new Object(), new Object());
+ assertTrue(predicate.test(result));
+ }
+
+ static Stream onServiceEnterCase() {
+ Runnable emptyMocker = () -> {};
+ Runnable mocker1 = () -> {
+ Mockito.when(messageAdapter.warpMessage(any())).thenReturn("mock");
+ Mockito.when(messageAdapter.markProcessed(any(), any())).thenReturn(true);
+ };
+ Runnable mocker2 = () -> {
+ Mockito.when(messageAdapter.markProcessed(any(), any())).thenReturn(false);
+ };
+ Runnable mocker3 = () -> {
+ Mockito.when(messageAdapter.getMsg(any(),any())).thenReturn(null);
+ };
+
+ Runnable mocker4 = () -> {
+ Mockito.when(messageAdapter.getHeader(any(), any())).thenReturn(null);
+ };
+ Runnable mocker5 = () -> {
+ Mockito.when(messageAdapter.getHeader(any(), any(),eq(ArexConstants.RECORD_ID))).thenReturn("mock");
+ };
+ Runnable mocker6 = () -> {
+ Mockito.when(messageAdapter.removeHeader(any(), any(),eq(ArexConstants.RECORD_ID))).thenReturn(true);
+ };
+ Runnable mocker7 = () -> {
+ Mockito.when(messageAdapter.addHeader(any(), any(),eq(ArexConstants.RECORD_ID),eq("mock"))).thenReturn(true);
+ };
+ Runnable mocker8 = () -> {
+ Mockito.when(messageAdapter.resetMsg(any())).thenReturn("mock");
+ };
+ Predicate> predicate1 = Objects::isNull;
+ return Stream.of(
+ arguments(emptyMocker, predicate1),
+ arguments(mocker1, predicate1),
+ arguments(mocker2, predicate1),
+ arguments(mocker3, predicate1),
+ arguments(mocker4, predicate1),
+ arguments(mocker5, predicate1),
+ arguments(mocker6, predicate1),
+ arguments(mocker7, predicate1),
+ arguments(mocker8, predicate1)
+ );
+ }
+
+}
diff --git a/arex-instrumentation/mq/arex-integration-mqtt/src/test/java/io/arex/inst/mqtt/inst/MessageQueueExtractorTest.java b/arex-instrumentation/mq/arex-integration-mqtt/src/test/java/io/arex/inst/mqtt/inst/MessageQueueExtractorTest.java
new file mode 100644
index 000000000..57856b682
--- /dev/null
+++ b/arex-instrumentation/mq/arex-integration-mqtt/src/test/java/io/arex/inst/mqtt/inst/MessageQueueExtractorTest.java
@@ -0,0 +1,115 @@
+package io.arex.inst.mqtt.inst;
+
+import io.arex.agent.bootstrap.model.ArexMocker;
+import io.arex.agent.bootstrap.model.Mocker;
+import io.arex.inst.mqtt.MessageQueueExtractor;
+import io.arex.inst.mqtt.adapter.MessageAdapter;
+import io.arex.inst.runtime.context.ArexContext;
+import io.arex.inst.runtime.context.ContextManager;
+import io.arex.inst.runtime.model.ArexConstants;
+import io.arex.inst.runtime.util.MockUtils;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.mockito.Mockito;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.MessageChannel;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.params.provider.Arguments.arguments;
+import static org.mockito.ArgumentMatchers.any;
+
+/**
+ * @author : MentosL
+ * @date : 2023/5/22 10:27
+ */
+public class MessageQueueExtractorTest {
+ static MessageAdapter adapter;
+ static Message message;
+ static MessageChannel messageChannel;
+
+ @BeforeAll
+ static void setUp() {
+ adapter = Mockito.mock(MessageAdapter.class);
+ message = Mockito.mock(Message.class);
+ messageChannel = Mockito.mock(MessageChannel.class);
+ Mockito.mockStatic(ContextManager.class);
+ Mockito.mockStatic(MockUtils.class);
+ }
+
+ @AfterAll
+ static void tearDown() {
+ adapter = null;
+ message = null;
+ messageChannel = null;
+ Mockito.clearAllCaches();
+ }
+
+
+
+ @ParameterizedTest(name = "[{index}] {2}")
+ @MethodSource("executeCase")
+ void execute(String log, Runnable mock, Runnable verify) throws IOException {
+ mock.run();
+ new MessageQueueExtractor<>(messageChannel,message, adapter).execute();
+ assertDoesNotThrow(verify::run);
+ }
+
+
+ static Stream executeCase() {
+ Runnable mock1 = () -> Mockito.when(adapter.addHeader(messageChannel,message, ArexConstants.REPLAY_ID,"mock-replay-id")).thenReturn(true);
+
+ Runnable verify1 = () -> {
+ try {
+ adapter.resetMsg(message);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ };
+
+ Runnable mock2 = () -> {
+ Mockito.when(adapter.getHeader(messageChannel,message, ArexConstants.REPLAY_ID)).thenReturn(null);
+ Mockito.when(ContextManager.needRecordOrReplay()).thenReturn(false);
+ };
+
+ Runnable mock3 = () -> {
+ Mockito.when(adapter.getHeader(messageChannel,message, ArexConstants.REPLAY_ID)).thenReturn(null);
+ Mockito.when(ContextManager.needRecordOrReplay()).thenReturn(true);
+
+ ArexMocker mocker = new ArexMocker();
+ mocker.setTargetRequest(new Mocker.Target());
+ mocker.setTargetResponse(new Mocker.Target());
+ Mockito.when(MockUtils.createServlet(any())).thenReturn(mocker);
+
+ Mockito.when(adapter.getMsg(messageChannel,message)).thenReturn(new byte[0]);
+ Mockito.when(ContextManager.needRecord()).thenReturn(true);
+ Mockito.when(ContextManager.currentContext()).thenReturn(ArexContext.of("mock-trace-id"));
+ };
+ Runnable verify2 = () -> {
+ Mockito.verify(adapter).addHeader(messageChannel,message, ArexConstants.RECORD_ID, "mock-trace-id");
+ };
+
+ Runnable mock4 = () -> {
+ Mockito.when(ContextManager.needRecord()).thenReturn(false);
+ Mockito.when(ContextManager.needReplay()).thenReturn(true);
+ };
+
+ Runnable verify3 = () -> {
+ Mockito.verify(adapter).addHeader(messageChannel,message, ArexConstants.REPLAY_ID, null);
+ };
+
+ return Stream.of(
+ arguments("response header contains arex trace", mock1, verify1),
+ arguments("no need record or replay", mock2, verify1),
+ arguments("record execute", mock3, verify2),
+ arguments("replay execute", mock4, verify3)
+ );
+ }
+
+}
diff --git a/arex-instrumentation/mq/arex-integration-mqtt/src/test/java/io/arex/inst/mqtt/inst/adapter/impl/MessageAdapterTest.java b/arex-instrumentation/mq/arex-integration-mqtt/src/test/java/io/arex/inst/mqtt/inst/adapter/impl/MessageAdapterTest.java
new file mode 100644
index 000000000..0e4a831a5
--- /dev/null
+++ b/arex-instrumentation/mq/arex-integration-mqtt/src/test/java/io/arex/inst/mqtt/inst/adapter/impl/MessageAdapterTest.java
@@ -0,0 +1,109 @@
+package io.arex.inst.mqtt.inst.adapter.impl;
+
+import io.arex.inst.mqtt.adapter.MessageAdapterImpl;
+import io.arex.inst.mqtt.warp.GenericMessageWarp;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.MessageChannel;
+import org.springframework.messaging.MessageHeaders;
+import org.springframework.messaging.support.GenericMessage;
+
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+/**
+ * @author : MentosL
+ * @date : 2023/5/11 16:27
+ */
+public class MessageAdapterTest {
+
+ MessageAdapterImpl instance = MessageAdapterImpl.getInstance();
+ MessageChannel messageChannel = Mockito.mock(MessageChannel.class);
+ Message message = Mockito.mock(Message.class);
+ GenericMessage genericMessage = Mockito.mock(GenericMessage.class);
+ GenericMessageWarp genericMessageWarp = Mockito.mock(GenericMessageWarp.class);
+
+
+ @Test
+ void getInstance() {
+ assertNotNull(instance);
+ }
+
+ @Test
+ void getMsg(){
+ assertNotNull(instance.getMsg(messageChannel,message));
+ assertTrue(instance.getMsg(messageChannel,message).length == 0);
+ assertInstanceOf(byte[].class,instance.getMsg(messageChannel,message));
+ }
+
+ @Test
+ void warpMC(){
+ assertNotNull(instance.warpMC(messageChannel));
+ assertInstanceOf(MessageChannel.class,instance.warpMC(messageChannel));
+ assertNull(instance.warpMC(new Object()));
+ }
+
+ @Test
+ void warpMessage(){
+ assertNotNull(instance.warpMessage(message));
+ assertNull(instance.warpMessage(null));
+ assertInstanceOf(GenericMessageWarp.class,instance.warpMessage(genericMessageWarp));
+ when(genericMessage.getPayload()).thenReturn(new Object());
+ assertInstanceOf(GenericMessage.class,instance.warpMessage(genericMessage));
+ }
+
+ @Test
+ void getHeader(){
+ assertNull(instance.getHeader(messageChannel,message,null));
+ assertNull(instance.getHeader(messageChannel,message,""));
+ Map temp = new HashMap<>();
+ temp.put("mock-key","mock-value");
+ when(genericMessage.getHeaders()).thenReturn(new MessageHeaders(temp));
+ assertSame("mock-value",instance.getHeader(messageChannel,genericMessage,"mock-key"));
+ }
+
+ @Test
+ void removeHeader(){
+ assertFalse(instance.removeHeader(messageChannel,null,"mock-key"));
+ assertFalse(instance.removeHeader(messageChannel,genericMessageWarp,""));
+ Map temp = new HashMap<>();
+ temp.put("mock-key","mock-value");
+ when(genericMessageWarp.getHeaders()).thenReturn(new MessageHeaders(temp));
+ assertTrue(instance.removeHeader(messageChannel,genericMessageWarp,"mock-key"));
+
+ assertFalse(instance.removeHeader(messageChannel,message,"mock-key"));
+ assertFalse(instance.removeHeader(messageChannel,genericMessage,"mock-key"));
+ }
+
+ @Test
+ void addHeader(){
+ assertFalse(instance.addHeader(messageChannel,null,"mock-key","mock-value"));
+ assertFalse(instance.addHeader(messageChannel,message,"mock-key","mock-value"));
+ assertFalse(instance.addHeader(messageChannel,genericMessage,"mock-key","mock-value"));
+
+ when(genericMessageWarp.getHeaders()).thenReturn(new MessageHeaders(new HashMap<>()));
+ assertTrue(instance.addHeader(messageChannel,genericMessageWarp,"mock-key","mock-value"));
+ }
+
+ @Test
+ void resetMsg(){
+ assertNull(instance.resetMsg(null));
+
+ Map temp = new HashMap<>();
+ temp.put("mock-key","mock-value");
+ when(genericMessageWarp.getHeaders()).thenReturn(new MessageHeaders(temp));
+
+ assertNotNull(instance.resetMsg(genericMessageWarp));
+ assertTrue(instance.resetMsg(genericMessageWarp).getHeaders().size() == 3);
+ assertSame("mock-value",instance.resetMsg(genericMessageWarp).getHeaders().get("mock-key"));
+ }
+}
diff --git a/arex-instrumentation/mq/arex-integration-mqtt/src/test/java/io/arex/inst/mqtt/inst/inst/MQGenericInstrumentationV3Test.java b/arex-instrumentation/mq/arex-integration-mqtt/src/test/java/io/arex/inst/mqtt/inst/inst/MQGenericInstrumentationV3Test.java
new file mode 100644
index 000000000..62e30ea2c
--- /dev/null
+++ b/arex-instrumentation/mq/arex-integration-mqtt/src/test/java/io/arex/inst/mqtt/inst/inst/MQGenericInstrumentationV3Test.java
@@ -0,0 +1,65 @@
+package io.arex.inst.mqtt.inst.inst;
+
+
+import io.arex.agent.bootstrap.internal.Pair;
+import io.arex.inst.mqtt.MQTTAdapterHelper;
+import io.arex.inst.mqtt.inst.MQGenericInstrumentationV3;
+import net.bytebuddy.description.type.TypeDescription;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.MessageChannel;
+import org.springframework.messaging.core.AbstractMessageSendingTemplate;
+import org.springframework.messaging.core.GenericMessagingTemplate;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+
+public class MQGenericInstrumentationV3Test {
+ MQGenericInstrumentationV3 inst = new MQGenericInstrumentationV3();
+
+
+ @BeforeAll
+ static void setUp() {
+ Mockito.mockStatic(MQTTAdapterHelper.class);
+ }
+
+ @AfterAll
+ static void tearDown() {
+ Mockito.clearAllCaches();
+ }
+
+
+ @Test
+ void typeMatcher() {
+ assertFalse(inst.typeMatcher().matches(TypeDescription.ForLoadedType.of(AbstractMessageSendingTemplate.class)));
+ assertTrue(inst.typeMatcher().matches(TypeDescription.ForLoadedType.of(GenericMessagingTemplate.class)));
+ }
+
+ @Test
+ void methodAdvices() {
+ assertEquals(1, inst.methodAdvices().size());
+ }
+
+
+ @Test
+ void ServiceAdvice_onEnter() {
+ Mockito.when(MQTTAdapterHelper.onServiceEnter(any(), any(), any())).thenReturn(null);
+ assertDoesNotThrow(() -> MQGenericInstrumentationV3.ArrivedAdvice.onEnter(null, null,null));
+
+ MessageChannel messageChannel = Mockito.mock(MessageChannel.class);
+ Message message = Mockito.mock(Message.class);
+ Mockito.when(MQTTAdapterHelper.onServiceEnter(any(), any(), any())).thenReturn(Pair.of(messageChannel, message));
+ assertDoesNotThrow(() -> MQGenericInstrumentationV3.ArrivedAdvice.onEnter(null, null,null));
+ }
+
+ @Test
+ void ServiceAdvice_onExit() {
+ assertDoesNotThrow(() -> MQGenericInstrumentationV3.ArrivedAdvice.onExit(null, null,null));
+ }
+}
diff --git a/arex-instrumentation/mq/arex-integration-mqtt/src/test/java/io/arex/inst/mqtt/inst/inst/MQTTAdapterModuleInstrumentationTest.java b/arex-instrumentation/mq/arex-integration-mqtt/src/test/java/io/arex/inst/mqtt/inst/inst/MQTTAdapterModuleInstrumentationTest.java
new file mode 100644
index 000000000..76ecfcbe3
--- /dev/null
+++ b/arex-instrumentation/mq/arex-integration-mqtt/src/test/java/io/arex/inst/mqtt/inst/inst/MQTTAdapterModuleInstrumentationTest.java
@@ -0,0 +1,30 @@
+package io.arex.inst.mqtt.inst.inst;
+
+import io.arex.inst.mqtt.inst.MQTTAdapterModuleInstrumentation;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * @author : MentosL
+ * @date : 2023/5/21 15:19
+ */
+public class MQTTAdapterModuleInstrumentationTest {
+ MQTTAdapterModuleInstrumentation module = new MQTTAdapterModuleInstrumentation();
+
+
+ @BeforeEach
+ void setUp() {
+ }
+
+ @AfterEach
+ void tearDown() {
+ }
+
+ @Test
+ void instrumentationTypes() {
+ assertEquals(1, module.instrumentationTypes().size());
+ }
+}
diff --git a/arex-instrumentation/mq/arex-integration-mqtt/src/test/java/io/arex/inst/mqtt/inst/warp/GenericMessageWarpTest.java b/arex-instrumentation/mq/arex-integration-mqtt/src/test/java/io/arex/inst/mqtt/inst/warp/GenericMessageWarpTest.java
new file mode 100644
index 000000000..760c7e7aa
--- /dev/null
+++ b/arex-instrumentation/mq/arex-integration-mqtt/src/test/java/io/arex/inst/mqtt/inst/warp/GenericMessageWarpTest.java
@@ -0,0 +1,65 @@
+package io.arex.inst.mqtt.inst.warp;
+
+import io.arex.inst.mqtt.warp.GenericMessageWarp;
+import org.junit.jupiter.api.Test;
+import org.springframework.messaging.MessageHeaders;
+
+import java.util.HashMap;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * @author : MentosL
+ * @date : 2023/5/21 16:16
+ */
+public class GenericMessageWarpTest {
+
+
+ @Test
+ void GenericMessageWarp1(){
+ assertNotNull(new GenericMessageWarp(new Object()));
+ assertThrows(IllegalArgumentException.class,()-> new GenericMessageWarp(null));
+ }
+
+ @Test
+ void GenericMessageWarp2(){
+ assertNotNull(new GenericMessageWarp(new Object(),new HashMap()));
+ assertThrows(IllegalArgumentException.class,()-> new GenericMessageWarp(null,new HashMap()));
+ }
+
+
+ @Test
+ void GenericMessageWarp3(){
+ assertNotNull(new GenericMessageWarp(new Object(),new MessageHeaders(new HashMap<>())));
+ assertThrows(IllegalArgumentException.class,()-> new GenericMessageWarp(null,new MessageHeaders(new HashMap<>())));
+ assertThrows(IllegalArgumentException.class,()-> new GenericMessageWarp(new Object(),null));
+ }
+
+ @Test
+ void removeHeader(){
+ GenericMessageWarp genericMessageWarp = new GenericMessageWarp(new Object());
+ genericMessageWarp.removeHeader("id");
+ assertEquals(1, genericMessageWarp.getMessageHeaderWarp().size());
+ assertEquals(2, genericMessageWarp.getHeaders().size());
+ }
+
+
+ @Test
+ void put(){
+ GenericMessageWarp genericMessageWarp = new GenericMessageWarp(new Object());
+ genericMessageWarp.put("mock-key","mock-value");
+ assertEquals(3, genericMessageWarp.getMessageHeaderWarp().size());
+ assertEquals(2, genericMessageWarp.getHeaders().size());
+ }
+
+
+ @Test
+ void get(){
+ GenericMessageWarp genericMessageWarp = new GenericMessageWarp(new Object());
+ genericMessageWarp.put("mock-key","mock-value");
+ assertEquals(3, genericMessageWarp.getMessageHeaderWarp().size());
+ assertEquals(2, genericMessageWarp.getHeaders().size());
+ assertSame("mock-value",genericMessageWarp.get("mock-key"));
+ }
+
+}
diff --git a/arex-instrumentation/mq/arex-integration-mqtt/src/test/java/io/arex/inst/mqtt/inst/warp/MessageHeaderWarpTest.java b/arex-instrumentation/mq/arex-integration-mqtt/src/test/java/io/arex/inst/mqtt/inst/warp/MessageHeaderWarpTest.java
new file mode 100644
index 000000000..d0915b651
--- /dev/null
+++ b/arex-instrumentation/mq/arex-integration-mqtt/src/test/java/io/arex/inst/mqtt/inst/warp/MessageHeaderWarpTest.java
@@ -0,0 +1,54 @@
+package io.arex.inst.mqtt.inst.warp;
+
+import io.arex.inst.mqtt.warp.MessageHeaderWarp;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+import org.springframework.messaging.MessageHeaders;
+
+import java.util.HashMap;
+import java.util.UUID;
+
+import static org.junit.jupiter.api.Assertions.*;
+/**
+ * @author : MentosL
+ * @date : 2023/5/21 15:39
+ */
+public class MessageHeaderWarpTest {
+
+ MessageHeaders messageHeaders = Mockito.mock(MessageHeaders.class);
+
+ @Test
+ void MessageHeaderWarp1(){
+ assertNotNull(new MessageHeaderWarp(messageHeaders));
+ MessageHeaders messageHeadersTemp = new MessageHeaders(new HashMap<>());
+ assertTrue(new MessageHeaderWarp(messageHeadersTemp).size() == 2);
+ }
+
+ @Test
+ void MessageHeaderWarp2(){
+ assertNotNull(new MessageHeaderWarp(new HashMap<>()));
+ assertTrue(new MessageHeaderWarp(new HashMap<>()).size() == 2);
+ }
+
+ @Test
+ void MessageHeaderWarp3(){
+ assertNotNull(new MessageHeaderWarp(new HashMap<>(), UUID.randomUUID(),System.currentTimeMillis()));
+ assertTrue(new MessageHeaderWarp(new HashMap<>(), UUID.randomUUID(),System.currentTimeMillis()).size() == 2);
+ }
+
+ @Test
+ void put(){
+ assertNotNull(new MessageHeaderWarp(new HashMap<>()).put("mock-key","mock-value"));
+ }
+
+ @Test
+ void remove(){
+ assertDoesNotThrow(() -> new MessageHeaderWarp(new HashMap<>()).remove("mock-key"));
+ MessageHeaderWarp messageHeaderWarp = new MessageHeaderWarp(new HashMap<>(), UUID.randomUUID(), System.currentTimeMillis());
+ assertSame(2,messageHeaderWarp.size());
+ messageHeaderWarp.remove("id");
+ assertSame(1,messageHeaderWarp.size());
+ }
+
+
+}
diff --git a/arex-instrumentation/servlet/arex-httpservlet/src/main/resources/META-INF/services/io.arex.inst.httpservlet.convert.HttpMessageConverter b/arex-instrumentation/servlet/arex-httpservlet/src/main/resources/META-INF/services/io.arex.inst.httpservlet.convert.HttpMessageConverter
deleted file mode 100644
index 24bad6272..000000000
--- a/arex-instrumentation/servlet/arex-httpservlet/src/main/resources/META-INF/services/io.arex.inst.httpservlet.convert.HttpMessageConverter
+++ /dev/null
@@ -1,2 +0,0 @@
-io.arex.inst.httpservlet.convert.impl.ApplicationJsonBodyConverter
-io.arex.inst.httpservlet.convert.impl.ApplicationXmlBodyConverter
\ No newline at end of file
diff --git a/arex-instrumentation/servlet/arex-httpservlet/src/test/resources/META-INF.services/io.arex.inst.httpservlet.convert.BodyConverters b/arex-instrumentation/servlet/arex-httpservlet/src/test/resources/META-INF.services/io.arex.inst.httpservlet.convert.BodyConverters
deleted file mode 100644
index 4937f54ab..000000000
--- a/arex-instrumentation/servlet/arex-httpservlet/src/test/resources/META-INF.services/io.arex.inst.httpservlet.convert.BodyConverters
+++ /dev/null
@@ -1,2 +0,0 @@
-io.arex.inst.httpservlet.convert.impl.ApplicationJsonBodyConvert
-io.arex.inst.httpservlet.convert.impl.ApplicationXmlBodyConvert
\ No newline at end of file