mirror of
https://github.com/dromara/hertzbeat.git
synced 2026-09-17 09:40:58 +00:00
refactor: update to Springboot4 and Hibernate 7 (#4057)
Co-authored-by: lynx009 <2030509072@qq.com>
This commit is contained in:
Vendored
+2
-2
@@ -3,5 +3,5 @@ FROM gitpod/workspace-full
|
||||
USER gitpod
|
||||
|
||||
RUN bash -c ". /home/gitpod/.sdkman/bin/sdkman-init.sh && \
|
||||
sdk install java 17.0.3-ms && \
|
||||
sdk default java 17.0.3-ms"
|
||||
sdk install java 21.0.2-tem && \
|
||||
sdk default java 21.0.2-tem"
|
||||
|
||||
+2
-2
@@ -32,7 +32,7 @@ Even small corrections to typos are very welcome :)
|
||||
|
||||
#### Backend start
|
||||
|
||||
1. Requires `maven3+`, `java17` and `lombok` environments
|
||||
1. Requires `maven3+`, `java21` and `lombok` environments
|
||||
|
||||
2. (Optional) Modify the configuration file: `hertzbeat-startup/src/main/resources/application.yml`
|
||||
|
||||
@@ -172,7 +172,7 @@ Add WeChat account `ahertzbeat` to pull you into the WeChat group.
|
||||
|
||||
#### 后端启动
|
||||
|
||||
1. 需要 `maven3+`, `java17` 和 `lombok` 环境
|
||||
1. 需要 `maven3+`, `java21` 和 `lombok` 环境
|
||||
|
||||
2. (可选)修改配置文件配置信息-`hertzbeat-startup/src/main/resources/application.yml`
|
||||
|
||||
|
||||
@@ -156,7 +156,7 @@ Detailed config refer to [Install HertzBeat via Package](https://hertzbeat.apach
|
||||
##### 3:Start via source code
|
||||
|
||||
1. Local source code debugging needs to start the back-end project `hertzbeat-startup` and the front-end project `web-app`.
|
||||
2. Backend:need `maven3+`, `java17`, `lombok`, add VM options in IDE: ` --add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED `, then start the `hertzbeat-startup` service.
|
||||
2. Backend:need `maven3+`, `java21`, `lombok`, add VM options in IDE: ` --add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED `, then start the `hertzbeat-startup` service.
|
||||
3. Web:need `nodejs npm angular-cli` environment, Run `ng serve --open` in `web-app` directory after backend startup.
|
||||
4. Access `http://localhost:4200` to start, default account: `admin/hertzbeat`
|
||||
|
||||
|
||||
+1
-1
@@ -153,7 +153,7 @@
|
||||
##### 方式三:本地代码启动
|
||||
|
||||
1. 此为前后端分离项目,本地代码调试需要分别启动后端工程 `hertzbeat-startup` 和前端工程 `web-app`
|
||||
2. 后端:需要 `maven3+`, `java17` 和 `lombok` 环境,修改 `YML` 配置信息,添加JVM参数`--add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED`后启动 `hertzbeat-startup` 服务即可。
|
||||
2. 后端:需要 `maven3+`, `java21` 和 `lombok` 环境,修改 `YML` 配置信息,添加JVM参数`--add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED`后启动 `hertzbeat-startup` 服务即可。
|
||||
3. 前端:需要 `nodejs npm angular-cli`环境,待本地后端启动后,在 `web-app` 目录下启动 `ng serve --open`
|
||||
4. 浏览器访问 `http://localhost:4200` 即可开始,默认账号密码 `admin/hertzbeat`
|
||||
|
||||
|
||||
+1
-1
@@ -156,7 +156,7 @@
|
||||
##### 方式3:ローカルの実行
|
||||
|
||||
1. ローカルの実行には、バックエンドのプロジェクト`hertzbeat-startup`とフロントエンドのプロジェクト`web-app`を起動する必要があります。
|
||||
2. バックエンド:`maven3+`、`java17`と`lombok`の環境は必要です。`YML` 設定を修正し、Java仮想マシンパラメータに`--add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED` を追加し、`hertzbeat-startup` を起動します。
|
||||
2. バックエンド:`maven3+`、`Java21`と`lombok`の環境は必要です。`YML` 設定を修正し、Java仮想マシンパラメータに`--add-opens=java.base/java.nio=org.apache.arrow.memory.core,ALL-UNNAMED` を追加し、`hertzbeat-startup` を起動します。
|
||||
3. フロントエンド:`nodejs npm angular-cli`の環境は必要です。ローカルのバックエンドが立ち上がったら、`web-app` ディレクトリで `ng serve --open` というコマンドを実行します。
|
||||
4. スタート:`http://localhost:4200`にアクセスします。デフォルトのアカウントとパスワード:`admin/hertzbeat`。
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
<version>${hertzbeat.version}</version>
|
||||
<properties>
|
||||
<spring-ai.version>1.1.1</spring-ai.version>
|
||||
<java.version>17</java.version>
|
||||
<java.version>21</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@@ -78,10 +78,7 @@
|
||||
<groupId>com.usthe.sureness</groupId>
|
||||
<artifactId>spring-boot3-starter-sureness</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.dataformat</groupId>
|
||||
<artifactId>jackson-dataformat-yaml</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
|
||||
@@ -41,7 +41,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import jakarta.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
|
||||
|
||||
@@ -26,7 +26,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -17,8 +17,7 @@
|
||||
|
||||
package org.apache.hertzbeat.ai.sop.registry;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
|
||||
import tools.jackson.databind.ObjectMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.ai.sop.model.SopDefinition;
|
||||
import org.springframework.core.io.Resource;
|
||||
@@ -28,6 +27,7 @@ import org.springframework.stereotype.Service;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import tools.jackson.dataformat.yaml.YAMLFactory;
|
||||
|
||||
/**
|
||||
* Loader for AI SOP definitions from YAML files.
|
||||
|
||||
+3
-3
@@ -17,9 +17,9 @@
|
||||
|
||||
package org.apache.hertzbeat.ai.tools.impl;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import tools.jackson.databind.ObjectMapper;
|
||||
import tools.jackson.databind.node.ArrayNode;
|
||||
import tools.jackson.databind.node.ObjectNode;
|
||||
import com.usthe.sureness.subject.SubjectSum;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.ai.config.McpContextHolder;
|
||||
|
||||
@@ -17,9 +17,8 @@
|
||||
|
||||
package org.apache.hertzbeat.ai.utils;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import tools.jackson.databind.node.ArrayNode;
|
||||
import tools.jackson.databind.node.ObjectNode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.time.Instant;
|
||||
@@ -31,6 +30,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.apache.hertzbeat.manager.pojo.dto.Hierarchy;
|
||||
import tools.jackson.databind.ObjectMapper;
|
||||
|
||||
/**
|
||||
* Utility class providing helper methods for field expression validation, parsing,
|
||||
|
||||
@@ -35,6 +35,11 @@
|
||||
<artifactId>hertzbeat-base</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.hertzbeat</groupId>
|
||||
<artifactId>hertzbeat-common-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- plugin -->
|
||||
<dependency>
|
||||
<groupId>org.apache.hertzbeat</groupId>
|
||||
|
||||
+2
-2
@@ -18,6 +18,8 @@
|
||||
package org.apache.hertzbeat.alert.calculate.realtime;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.PreDestroy;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.alert.calculate.realtime.window.LogWorker;
|
||||
import org.apache.hertzbeat.alert.calculate.realtime.window.TimeService;
|
||||
@@ -28,8 +30,6 @@ import org.apache.hertzbeat.common.util.BackoffUtils;
|
||||
import org.apache.hertzbeat.common.util.ExponentialBackoff;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
+2
-2
@@ -19,14 +19,14 @@ package org.apache.hertzbeat.alert.calculate.realtime.window;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
import jakarta.annotation.PreDestroy;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
+2
-2
@@ -18,6 +18,7 @@
|
||||
package org.apache.hertzbeat.alert.calculate.realtime.window;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
@@ -25,8 +26,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.common.entity.alerter.AlertDefine;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
import jakarta.annotation.PreDestroy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
|
||||
+8
-7
@@ -17,12 +17,10 @@
|
||||
|
||||
package org.apache.hertzbeat.alert.notice.impl;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.mail.internet.MimeMessage;
|
||||
import java.util.Date;
|
||||
import java.util.Properties;
|
||||
import java.util.ResourceBundle;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.common.entity.dto.MailServerConfig;
|
||||
import org.apache.hertzbeat.alert.notice.AlertNoticeException;
|
||||
@@ -31,6 +29,7 @@ import org.apache.hertzbeat.common.entity.manager.GeneralConfig;
|
||||
import org.apache.hertzbeat.common.entity.alerter.NoticeReceiver;
|
||||
import org.apache.hertzbeat.common.entity.alerter.NoticeTemplate;
|
||||
import org.apache.hertzbeat.common.support.event.SystemConfigChangeEvent;
|
||||
import org.apache.hertzbeat.common.util.JsonUtil;
|
||||
import org.apache.hertzbeat.common.util.ResourceBundleUtil;
|
||||
import org.apache.hertzbeat.base.dao.GeneralConfigDao;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@@ -44,7 +43,6 @@ import org.springframework.stereotype.Component;
|
||||
* Send alarm information through email
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class EmailAlertNotifyHandlerImpl extends AbstractAlertNotifyHandlerImpl {
|
||||
|
||||
@@ -70,12 +68,15 @@ public class EmailAlertNotifyHandlerImpl extends AbstractAlertNotifyHandlerImpl
|
||||
|
||||
private final GeneralConfigDao generalConfigDao;
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
private static final String TYPE = "email";
|
||||
|
||||
private ResourceBundle bundle = ResourceBundleUtil.getBundle("alerter");
|
||||
|
||||
public EmailAlertNotifyHandlerImpl(JavaMailSender javaMailSender, GeneralConfigDao generalConfigDao) {
|
||||
this.javaMailSender = javaMailSender;
|
||||
this.generalConfigDao = generalConfigDao;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(NoticeReceiver receiver, NoticeTemplate noticeTemplate, GroupAlert alert) throws AlertNoticeException {
|
||||
try {
|
||||
@@ -88,8 +89,8 @@ public class EmailAlertNotifyHandlerImpl extends AbstractAlertNotifyHandlerImpl
|
||||
if (emailConfig != null && emailConfig.getContent() != null) {
|
||||
// enable database configuration
|
||||
String content = emailConfig.getContent();
|
||||
MailServerConfig emailNoticeSenderConfig = objectMapper.readValue(content, MailServerConfig.class);
|
||||
if (emailNoticeSenderConfig.isEnable()) {
|
||||
MailServerConfig emailNoticeSenderConfig = JsonUtil.fromJson(content, MailServerConfig.class);
|
||||
if (emailNoticeSenderConfig != null && emailNoticeSenderConfig.isEnable()) {
|
||||
sender.setHost(emailNoticeSenderConfig.getEmailHost());
|
||||
sender.setPort(emailNoticeSenderConfig.getEmailPort());
|
||||
sender.setUsername(emailNoticeSenderConfig.getEmailUsername());
|
||||
|
||||
+6
-9
@@ -18,9 +18,6 @@
|
||||
package org.apache.hertzbeat.alert.notice.impl;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
@@ -49,6 +46,7 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
import tools.jackson.databind.JsonNode;
|
||||
|
||||
/**
|
||||
* FeiShu app alert notify impl
|
||||
@@ -78,7 +76,6 @@ public class FeiShuAppAlertNotifyHandlerImpl extends AbstractAlertNotifyHandlerI
|
||||
*/
|
||||
private static final String APP_BATCH_MESSAGE_URL = "https://open.feishu.cn/open-apis/message/v4/batch_send/";
|
||||
|
||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||
private static final byte USER_RECEIVE_TYPE = 0;
|
||||
private static final byte CHAT_RECEIVE_TYPE = 1;
|
||||
private static final byte PART_RECEIVE_TYPE = 2;
|
||||
@@ -134,7 +131,7 @@ public class FeiShuAppAlertNotifyHandlerImpl extends AbstractAlertNotifyHandlerI
|
||||
* @param messageContent Message content
|
||||
* @see <a href="https://open.feishu.cn/document/server-docs/im-v1/batch_message/send-messages-in-batches">send message</a>
|
||||
*/
|
||||
private void sendLarkMessage(String accessToken, String receiverIdType, String receiverId, JsonNode messageContent) throws JsonProcessingException {
|
||||
private void sendLarkMessage(String accessToken, String receiverIdType, String receiverId, JsonNode messageContent) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
headers.setBearerAuth(accessToken);
|
||||
@@ -246,7 +243,7 @@ public class FeiShuAppAlertNotifyHandlerImpl extends AbstractAlertNotifyHandlerI
|
||||
return response.getBody();
|
||||
}
|
||||
|
||||
private JsonNode createLarkMessage(NoticeReceiver receiver, String notificationContent) throws JsonProcessingException {
|
||||
private JsonNode createLarkMessage(NoticeReceiver receiver, String notificationContent) {
|
||||
String larkCardMessage = """
|
||||
{
|
||||
"schema": "2.0",
|
||||
@@ -359,12 +356,12 @@ public class FeiShuAppAlertNotifyHandlerImpl extends AbstractAlertNotifyHandlerI
|
||||
String jsonStr = String.format(larkCardMessage,
|
||||
notificationContent.replace("\"", "\\\"") + atUserElement,
|
||||
alerterProperties.getConsoleUrl());
|
||||
return OBJECT_MAPPER.readTree(jsonStr);
|
||||
return JsonUtil.fromJson(jsonStr);
|
||||
}
|
||||
|
||||
|
||||
private String escapedCompactJson(JsonNode json) throws JsonProcessingException {
|
||||
return OBJECT_MAPPER.writeValueAsString(json);
|
||||
private String escapedCompactJson(JsonNode json) {
|
||||
return json.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
-5
@@ -17,7 +17,6 @@
|
||||
|
||||
package org.apache.hertzbeat.alert.service;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.common.entity.dto.sms.SmsConfig;
|
||||
import org.apache.hertzbeat.alert.service.impl.SmsLocalSmsClientImpl;
|
||||
@@ -30,6 +29,7 @@ import org.apache.hertzbeat.base.dao.GeneralConfigDao;
|
||||
import org.apache.hertzbeat.common.constants.GeneralConfigTypeEnum;
|
||||
import org.apache.hertzbeat.common.entity.manager.GeneralConfig;
|
||||
import org.apache.hertzbeat.common.support.event.SmsConfigChangeEvent;
|
||||
import org.apache.hertzbeat.common.util.JsonUtil;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -50,14 +50,12 @@ public class SmsClientFactory {
|
||||
private static final String TYPE = GeneralConfigTypeEnum.sms.name();
|
||||
|
||||
private final GeneralConfigDao generalConfigDao;
|
||||
private final ObjectMapper objectMapper;
|
||||
private final SmsConfig yamlSmsConfig;
|
||||
|
||||
private volatile SmsClient currentSmsClient;
|
||||
|
||||
public SmsClientFactory(GeneralConfigDao generalConfigDao, ObjectMapper objectMapper, SmsConfig yamlSmsConfig) {
|
||||
public SmsClientFactory(GeneralConfigDao generalConfigDao, SmsConfig yamlSmsConfig) {
|
||||
this.generalConfigDao = generalConfigDao;
|
||||
this.objectMapper = objectMapper;
|
||||
this.yamlSmsConfig = yamlSmsConfig;
|
||||
}
|
||||
|
||||
@@ -118,7 +116,7 @@ public class SmsClientFactory {
|
||||
try {
|
||||
GeneralConfig config = generalConfigDao.findByType(TYPE);
|
||||
if (config != null && config.getContent() != null) {
|
||||
return objectMapper.readValue(config.getContent(), SmsConfig.class);
|
||||
return JsonUtil.fromJson(config.getContent(), SmsConfig.class);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("[SmsClientFactory] Failed to load database configuration", e);
|
||||
|
||||
+1
-1
@@ -19,7 +19,6 @@ package org.apache.hertzbeat.alert.service.impl;
|
||||
|
||||
import static org.apache.hertzbeat.common.constants.ExportFileConstants.ExcelFile.FILE_SUFFIX;
|
||||
import static org.apache.hertzbeat.common.constants.ExportFileConstants.ExcelFile.TYPE;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
@@ -42,6 +41,7 @@ import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
|
||||
/**
|
||||
* Configure the import and export EXCEL format
|
||||
|
||||
+5
-20
@@ -19,27 +19,22 @@ package org.apache.hertzbeat.alert.service.impl;
|
||||
|
||||
import static org.apache.hertzbeat.common.constants.ExportFileConstants.JsonFile.FILE_SUFFIX;
|
||||
import static org.apache.hertzbeat.common.constants.ExportFileConstants.JsonFile.TYPE;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.alert.dto.ExportAlertDefineDTO;
|
||||
import org.apache.hertzbeat.common.util.JsonUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
|
||||
/**
|
||||
* Configure the import and export JSON format
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class AlertDefineJsonImExportServiceImpl extends AlertDefineAbstractImExportServiceImpl {
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
@Override
|
||||
public String type() {
|
||||
return TYPE;
|
||||
@@ -52,22 +47,12 @@ public class AlertDefineJsonImExportServiceImpl extends AlertDefineAbstractImExp
|
||||
|
||||
@Override
|
||||
public List<ExportAlertDefineDTO> parseImport(InputStream is) {
|
||||
try {
|
||||
return objectMapper.readValue(is, new TypeReference<>() {
|
||||
});
|
||||
} catch (IOException ex) {
|
||||
log.error("import alertDefine failed.", ex);
|
||||
throw new RuntimeException("import alertDefine failed");
|
||||
}
|
||||
return JsonUtil.fromJson(is, new TypeReference<>() {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeOs(List<ExportAlertDefineDTO> exportAlertDefineList, OutputStream os) {
|
||||
try {
|
||||
objectMapper.writeValue(os, exportAlertDefineList);
|
||||
} catch (IOException ex) {
|
||||
log.error("export alertDefine failed.", ex);
|
||||
throw new RuntimeException("export alertDefine failed");
|
||||
}
|
||||
JsonUtil.toJson(exportAlertDefineList, os);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-10
@@ -17,9 +17,8 @@
|
||||
|
||||
package org.apache.hertzbeat.alert.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
@@ -39,6 +38,7 @@ import org.apache.hertzbeat.common.entity.alerter.AlertDefine;
|
||||
import org.apache.hertzbeat.common.entity.manager.Label;
|
||||
import org.apache.hertzbeat.common.util.FileUtil;
|
||||
import org.apache.hertzbeat.common.util.JexlExpressionRunner;
|
||||
import org.apache.hertzbeat.common.util.JsonUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
@@ -51,7 +51,6 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@@ -185,14 +184,9 @@ public class AlertDefineServiceImpl implements AlertDefineService {
|
||||
@Override
|
||||
public Page<AlertDefine> getAlertDefines(List<Long> defineIds, String search, String sort, String order, int pageIndex, int pageSize) {
|
||||
// parse translation content list
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
List<String> searchList = Collections.emptyList();
|
||||
if (StringUtils.hasText(search)) {
|
||||
try {
|
||||
searchList = objectMapper.readValue(URLDecoder.decode(search, StandardCharsets.UTF_8), new TypeReference<>() {});
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new IllegalArgumentException("Failed to parse search parameter", e);
|
||||
}
|
||||
searchList = JsonUtil.fromJson(URLDecoder.decode(search, StandardCharsets.UTF_8), new TypeReference<>() {});
|
||||
}
|
||||
List<String> finalSearchList = searchList;
|
||||
// build search condition
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
|
||||
package org.apache.hertzbeat.alert.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
+1
-1
@@ -17,7 +17,6 @@
|
||||
|
||||
package org.apache.hertzbeat.alert.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.common.entity.dto.sms.AlibabaSmsProperties;
|
||||
import org.apache.hertzbeat.alert.service.SmsClient;
|
||||
@@ -45,6 +44,7 @@ import java.util.Map;
|
||||
import java.util.SimpleTimeZone;
|
||||
import java.util.TreeMap;
|
||||
import java.util.UUID;
|
||||
import tools.jackson.databind.JsonNode;
|
||||
|
||||
import static org.apache.hertzbeat.common.constants.SmsConstants.ALIBABA;
|
||||
|
||||
|
||||
+5
-3
@@ -17,8 +17,7 @@
|
||||
|
||||
package org.apache.hertzbeat.alert.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import tools.jackson.databind.JsonNode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.common.entity.dto.sms.AwsSmsProperties;
|
||||
import org.apache.hertzbeat.alert.service.SmsClient;
|
||||
@@ -110,7 +109,10 @@ public class AwsSmsClientImpl implements SmsClient {
|
||||
String endpoint = "https://" + SERVICE + "." + region + ".amazonaws.com";
|
||||
|
||||
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
|
||||
String payloadInString = new ObjectMapper().writeValueAsString(payload);
|
||||
String payloadInString = JsonUtil.toJson(payload);
|
||||
if (payloadInString == null) {
|
||||
throw new SendMessageException("Failed to serialize SMS payload");
|
||||
}
|
||||
URI requestUri = new URI(endpoint);
|
||||
|
||||
HttpPost httpPost = createHttpPost(requestUri, amzDate, payloadInString);
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
|
||||
package org.apache.hertzbeat.alert.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import tools.jackson.databind.JsonNode;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
|
||||
package org.apache.hertzbeat.alert.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
import java.time.Instant;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
+1
-1
@@ -17,7 +17,6 @@
|
||||
|
||||
package org.apache.hertzbeat.alert.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.alert.dto.SkyWalkingExternAlert;
|
||||
import org.apache.hertzbeat.alert.reduce.AlarmCommonReduce;
|
||||
@@ -32,6 +31,7 @@ import java.time.Instant;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
|
||||
/**
|
||||
* SkyWalking external alarm service impl
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
|
||||
package org.apache.hertzbeat.alert.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import tools.jackson.databind.JsonNode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.apache.hertzbeat.common.util.JsonUtil;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import tools.jackson.databind.JsonNode;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
|
||||
package org.apache.hertzbeat.alert.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import tools.jackson.databind.JsonNode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.common.entity.dto.sms.TwilioSmsProperties;
|
||||
import org.apache.hertzbeat.alert.service.SmsClient;
|
||||
|
||||
+1
-1
@@ -31,7 +31,6 @@ import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.apache.hertzbeat.alert.util.CryptoUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -41,6 +40,7 @@ import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
import tools.jackson.databind.JsonNode;
|
||||
|
||||
import static org.apache.hertzbeat.common.constants.SmsConstants.UNISMS;
|
||||
|
||||
|
||||
+6
-6
@@ -17,10 +17,8 @@
|
||||
|
||||
package org.apache.hertzbeat.alert.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import tools.jackson.databind.JsonNode;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.hertzbeat.alert.dto.VolcEngineExternEventAlert;
|
||||
@@ -56,10 +54,12 @@ public class VolcEngineExternAlertService implements ExternAlertService {
|
||||
);
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void addExternAlert(String content) {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
JsonNode root = mapper.readTree(content);
|
||||
JsonNode root = JsonUtil.fromJson(content);
|
||||
if (root == null) {
|
||||
log.warn("parse extern alert content failed! content: {}", content);
|
||||
return;
|
||||
}
|
||||
String type = root.get("Type").asText();
|
||||
if (VolcEngineExternMetricAlert.ALERT_TYPE_EVENT.equals(type)) {
|
||||
VolcEngineExternEventAlert eventAlert = JsonUtil.fromJson(content, VolcEngineExternEventAlert.class);
|
||||
|
||||
+6
-10
@@ -19,13 +19,10 @@ package org.apache.hertzbeat.alert.notice.impl;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.lenient;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.util.Properties;
|
||||
import org.apache.hertzbeat.common.entity.dto.MailServerConfig;
|
||||
import org.apache.hertzbeat.base.dao.GeneralConfigDao;
|
||||
@@ -35,6 +32,7 @@ import org.apache.hertzbeat.common.entity.alerter.NoticeTemplate;
|
||||
import org.apache.hertzbeat.common.entity.alerter.SingleAlert;
|
||||
import org.apache.hertzbeat.alert.notice.AlertNoticeException;
|
||||
import org.apache.hertzbeat.common.entity.manager.GeneralConfig;
|
||||
import org.apache.hertzbeat.common.util.JsonUtil;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
@@ -67,9 +65,6 @@ class EmailAlertNotifyHandlerImplTest {
|
||||
@Mock
|
||||
private MimeMessage mimeMessage;
|
||||
|
||||
@Mock
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@InjectMocks
|
||||
private EmailAlertNotifyHandlerImpl emailAlertNotifyHandler;
|
||||
|
||||
@@ -78,7 +73,7 @@ class EmailAlertNotifyHandlerImplTest {
|
||||
private NoticeTemplate template;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() throws JsonProcessingException {
|
||||
public void setUp() {
|
||||
receiver = new NoticeReceiver();
|
||||
receiver.setId(1L);
|
||||
receiver.setName("test-receiver");
|
||||
@@ -106,10 +101,11 @@ class EmailAlertNotifyHandlerImplTest {
|
||||
mailServerConfig.setEmailUsername("sender@example.com");
|
||||
mailServerConfig.setEmailPassword("password");
|
||||
mailServerConfig.setEnable(true);
|
||||
GeneralConfig generalConfig = GeneralConfig.builder().content("").build();
|
||||
|
||||
GeneralConfig generalConfig = GeneralConfig.builder()
|
||||
.content(JsonUtil.toJson(mailServerConfig))
|
||||
.build();
|
||||
when(generalConfigDao.findByType(any())).thenReturn(generalConfig);
|
||||
when(objectMapper.readValue(any(String.class), eq(MailServerConfig.class)))
|
||||
.thenReturn(mailServerConfig);
|
||||
when(mailSender.getJavaMailProperties()).thenReturn(new Properties());
|
||||
}
|
||||
|
||||
|
||||
+21
-54
@@ -19,20 +19,11 @@ package org.apache.hertzbeat.alert.service;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import org.apache.hertzbeat.alert.dto.AlertDefineDTO;
|
||||
@@ -40,22 +31,13 @@ import org.apache.hertzbeat.alert.dto.ExportAlertDefineDTO;
|
||||
import org.apache.hertzbeat.alert.service.impl.AlertDefineJsonImExportServiceImpl;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
/**
|
||||
* test case for {@link AlertDefineJsonImExportServiceImpl}
|
||||
*/
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class AlertDefineJsonImExportServiceTest {
|
||||
|
||||
@Mock
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@InjectMocks
|
||||
private AlertDefineJsonImExportServiceImpl service;
|
||||
|
||||
@SuppressWarnings("checkstyle:OperatorWrap")
|
||||
@@ -68,6 +50,7 @@ class AlertDefineJsonImExportServiceTest {
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
service = new AlertDefineJsonImExportServiceImpl();
|
||||
|
||||
inputStream = new ByteArrayInputStream(JSON_DATA.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
@@ -87,59 +70,43 @@ class AlertDefineJsonImExportServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseImport() throws IOException {
|
||||
|
||||
when(objectMapper.readValue(
|
||||
any(InputStream.class),
|
||||
any(TypeReference.class))
|
||||
).thenReturn(alertDefineList);
|
||||
|
||||
void testParseImport() {
|
||||
List<ExportAlertDefineDTO> result = service.parseImport(inputStream);
|
||||
|
||||
assertNotNull(result);
|
||||
assertEquals(1, result.size());
|
||||
assertEquals(alertDefineList, result);
|
||||
verify(objectMapper, times(1)).readValue(any(InputStream.class), any(TypeReference.class));
|
||||
assertEquals("App1", result.get(0).getAlertDefine().getName());
|
||||
assertEquals("realtime", result.get(0).getAlertDefine().getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseImportFailed() throws IOException {
|
||||
void testParseImportFailed() {
|
||||
InputStream invalidInputStream = new ByteArrayInputStream("invalid json".getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
when(objectMapper.readValue(
|
||||
any(InputStream.class),
|
||||
any(TypeReference.class))
|
||||
).thenThrow(new IOException("Test Exception"));
|
||||
List<ExportAlertDefineDTO> result = service.parseImport(invalidInputStream);
|
||||
|
||||
RuntimeException exception = assertThrows(RuntimeException.class, () -> service.parseImport(inputStream));
|
||||
|
||||
assertEquals("import alertDefine failed", exception.getMessage());
|
||||
verify(objectMapper, times(1)).readValue(any(InputStream.class), any(TypeReference.class));
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWriteOs() throws IOException {
|
||||
|
||||
void testWriteOs() {
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
|
||||
service.writeOs(alertDefineList, outputStream);
|
||||
|
||||
verify(objectMapper, times(1)).writeValue(any(OutputStream.class), eq(alertDefineList));
|
||||
String result = outputStream.toString(StandardCharsets.UTF_8);
|
||||
assertNotNull(result);
|
||||
assertTrue(result.contains("App1"));
|
||||
assertTrue(result.contains("realtime"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWriteOsFailed() throws IOException {
|
||||
|
||||
doThrow(new IOException("Test Exception")).when(objectMapper).writeValue(any(OutputStream.class), any());
|
||||
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
|
||||
RuntimeException exception = assertThrows(
|
||||
RuntimeException.class,
|
||||
() -> service.writeOs(alertDefineList, outputStream)
|
||||
);
|
||||
|
||||
assertEquals("export alertDefine failed", exception.getMessage());
|
||||
verify(objectMapper, times(1)).writeValue(any(OutputStream.class), eq(alertDefineList));
|
||||
void testType() {
|
||||
assertEquals("JSON", service.type());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetFileName() {
|
||||
assertTrue(service.getFileName().endsWith(".json"));
|
||||
}
|
||||
}
|
||||
|
||||
+1
-7
@@ -17,8 +17,6 @@
|
||||
|
||||
package org.apache.hertzbeat.alert.service;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.apache.hertzbeat.common.entity.dto.sms.SmsConfig;
|
||||
import org.apache.hertzbeat.common.entity.dto.sms.SmslocalSmsProperties;
|
||||
import org.apache.hertzbeat.base.dao.GeneralConfigDao;
|
||||
@@ -46,9 +44,6 @@ public class SmsClientFactoryTest {
|
||||
@Mock
|
||||
private GeneralConfigDao generalConfigDao;
|
||||
|
||||
@Mock
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@Mock
|
||||
private SmsConfig yamlSmsConfig;
|
||||
|
||||
@@ -57,7 +52,7 @@ public class SmsClientFactoryTest {
|
||||
|
||||
|
||||
@Test
|
||||
void testloadDbConfig() throws JsonProcessingException {
|
||||
void testloadDbConfig() {
|
||||
GeneralConfig generalConfig = new GeneralConfig();
|
||||
|
||||
SmsConfig smsConfig = new SmsConfig();
|
||||
@@ -66,7 +61,6 @@ public class SmsClientFactoryTest {
|
||||
smsConfig.setSmslocal(new SmslocalSmsProperties("11"));
|
||||
|
||||
generalConfig.setContent(JsonUtil.toJson(smsConfig));
|
||||
when(objectMapper.readValue(generalConfig.getContent(), SmsConfig.class)).thenReturn(smsConfig);
|
||||
when(generalConfigDao.findByType(GeneralConfigTypeEnum.sms.name())).thenReturn(generalConfig);
|
||||
|
||||
assertNotNull(smsClientFactory.getSmsClient());
|
||||
|
||||
+1
-1
@@ -17,7 +17,6 @@
|
||||
|
||||
package org.apache.hertzbeat.collector.collect.push;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -48,6 +47,7 @@ import org.apache.http.client.protocol.HttpClientContext;
|
||||
import org.apache.http.protocol.HttpContext;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.springframework.http.MediaType;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
|
||||
/**
|
||||
* push style collect
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
|
||||
package org.apache.hertzbeat.collector.collect.sd;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
import com.google.common.collect.Lists;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
+10
-14
@@ -21,9 +21,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import java.util.ArrayList;
|
||||
@@ -36,6 +33,7 @@ import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import org.apache.hertzbeat.common.entity.job.Configmap;
|
||||
import org.apache.hertzbeat.common.entity.job.Metrics;
|
||||
import org.apache.hertzbeat.common.util.JsonUtil;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
@@ -46,8 +44,6 @@ import org.junit.jupiter.params.provider.MethodSource;
|
||||
*/
|
||||
class CollectUtilTest {
|
||||
|
||||
private static final ObjectMapper JSON_MAPPER = new ObjectMapper();
|
||||
|
||||
@Test
|
||||
void countMatchKeyword() {
|
||||
int keyword = CollectUtil.countMatchKeyword("hertzbeat", "e");
|
||||
@@ -115,7 +111,7 @@ class CollectUtilTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void replaceCryPlaceholder() throws JsonMappingException, JsonProcessingException {
|
||||
void replaceCryPlaceholder() {
|
||||
Metrics metrics = Metrics.builder().name("^o^name^o^").build();
|
||||
JsonElement jsonElement = new Gson().toJsonTree(metrics);
|
||||
Map<String, Configmap> configmap = new HashMap<>();
|
||||
@@ -125,7 +121,7 @@ class CollectUtilTest {
|
||||
|
||||
Metrics metricsTarget = Metrics.builder().name("张三").build();
|
||||
JsonElement jsonElementTarget = new Gson().toJsonTree(metricsTarget);
|
||||
assertEquals(JSON_MAPPER.readTree(jsonElementTarget.toString()), JSON_MAPPER.readTree(res1.toString()));
|
||||
assertEquals(JsonUtil.fromJson(jsonElementTarget.toString()), JsonUtil.fromJson(res1.toString()));
|
||||
|
||||
List<Metrics> metricsList = new ArrayList<>();
|
||||
metricsList.add(metrics);
|
||||
@@ -137,7 +133,7 @@ class CollectUtilTest {
|
||||
metricsListTarget.add(metricsTarget);
|
||||
metricsListTarget.add(metricsTarget);
|
||||
JsonElement jsonArrayTarget = new Gson().toJsonTree(metricsListTarget);
|
||||
assertEquals(JSON_MAPPER.readTree(jsonArrayTarget.toString()), JSON_MAPPER.readTree(res2.toString()));
|
||||
assertEquals(JsonUtil.fromJson(jsonArrayTarget.toString()), JsonUtil.fromJson(res2.toString()));
|
||||
}
|
||||
|
||||
static Stream<Arguments> testParamsForShouldVerifyReplaceCryPlaceholder() {
|
||||
@@ -181,10 +177,10 @@ class CollectUtilTest {
|
||||
@MethodSource("testParamsForShouldVerifyReplaceCryPlaceholder")
|
||||
void shouldVerifyReplaceCryPlaceholder(JsonObject jsonObject,
|
||||
Map<String, Configmap> configmap,
|
||||
JsonObject jsonObjectTarget) throws JsonProcessingException {
|
||||
JsonObject jsonObjectTarget) {
|
||||
|
||||
JsonElement res1 = CollectUtil.replaceCryPlaceholder(jsonObject, configmap);
|
||||
assertEquals(JSON_MAPPER.readTree(jsonObjectTarget.toString()), JSON_MAPPER.readTree(res1.toString()));
|
||||
assertEquals(JsonUtil.fromJson(jsonObjectTarget.toString()), JsonUtil.fromJson(res1.toString()));
|
||||
|
||||
List<JsonObject> metricsList = new ArrayList<>();
|
||||
metricsList.add(jsonObject);
|
||||
@@ -195,11 +191,11 @@ class CollectUtilTest {
|
||||
|
||||
metricsListTarget.add(jsonObjectTarget);
|
||||
JsonElement jsonArrayTarget = new Gson().toJsonTree(metricsListTarget);
|
||||
assertEquals(JSON_MAPPER.readTree(jsonArrayTarget.toString()), JSON_MAPPER.readTree(res2.toString()));
|
||||
assertEquals(JsonUtil.fromJson(jsonArrayTarget.toString()), JsonUtil.fromJson(res2.toString()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void replaceSmilingPlaceholder() throws JsonMappingException, JsonProcessingException {
|
||||
void replaceSmilingPlaceholder() {
|
||||
Metrics metrics = Metrics.builder().name("^_^name^_^").build();
|
||||
JsonElement jsonElement = new Gson().toJsonTree(metrics);
|
||||
HashMap<String, Configmap> configmap = new HashMap<>();
|
||||
@@ -208,7 +204,7 @@ class CollectUtilTest {
|
||||
JsonElement res = CollectUtil.replaceSmilingPlaceholder(jsonElement, configmap);
|
||||
Metrics metricsTarget = Metrics.builder().name("张三").build();
|
||||
JsonElement jsonElement2 = new Gson().toJsonTree(metricsTarget);
|
||||
assertEquals(JSON_MAPPER.readTree(jsonElement2.toString()), JSON_MAPPER.readTree(res.toString()));
|
||||
assertEquals(JsonUtil.fromJson(jsonElement2.toString()), JsonUtil.fromJson(res.toString()));
|
||||
|
||||
List<Metrics> metricsList = new ArrayList<>();
|
||||
metricsList.add(metrics);
|
||||
@@ -220,7 +216,7 @@ class CollectUtilTest {
|
||||
metricsListTarget.add(metricsTarget);
|
||||
metricsListTarget.add(metricsTarget);
|
||||
JsonElement jsonArrayTarget = new Gson().toJsonTree(metricsListTarget);
|
||||
assertEquals(JSON_MAPPER.readTree(jsonArrayTarget.toString()), JSON_MAPPER.readTree(res2.toString()));
|
||||
assertEquals(JsonUtil.fromJson(jsonArrayTarget.toString()), JsonUtil.fromJson(res2.toString()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -57,10 +57,6 @@
|
||||
<artifactId>sshd-core</artifactId>
|
||||
<version>${sshd-core.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
|
||||
package org.apache.hertzbeat.collector.dispatch.entrance.processor;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.collector.dispatch.entrance.CollectServer;
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
package org.apache.hertzbeat.collector.util;
|
||||
|
||||
import com.beetstra.jutf7.CharsetProvider;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<name>${project.artifactId}</name>
|
||||
<packaging>pom</packaging>
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
<java.version>21</java.version>
|
||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
@@ -131,26 +131,36 @@
|
||||
<version>${javaparser.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- Test dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.jsqlparser</groupId>
|
||||
<artifactId>jsqlparser</artifactId>
|
||||
</dependency>
|
||||
<!-- jackson for optional json processing -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<groupId>tools.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.dataformat</groupId>
|
||||
<groupId>tools.jackson.dataformat</groupId>
|
||||
<artifactId>jackson-dataformat-xml</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>tools.jackson.dataformat</groupId>
|
||||
<artifactId>jackson-dataformat-yaml</artifactId>
|
||||
</dependency>
|
||||
<!-- swagger annotations (optional) -->
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
|
||||
+16
-13
@@ -6,7 +6,7 @@
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -17,14 +17,8 @@
|
||||
|
||||
package org.apache.hertzbeat.common.entity.dto;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.ObjectCodec;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -32,6 +26,11 @@ import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import lombok.experimental.Accessors;
|
||||
import tools.jackson.core.JsonParser;
|
||||
import tools.jackson.databind.DeserializationContext;
|
||||
import tools.jackson.databind.JsonNode;
|
||||
import tools.jackson.databind.ValueDeserializer;
|
||||
import tools.jackson.databind.annotation.JsonDeserialize;
|
||||
|
||||
/**
|
||||
* prometheus vector or matrix entity
|
||||
@@ -42,6 +41,7 @@ import lombok.experimental.Accessors;
|
||||
@Accessors(chain = true)
|
||||
@ToString
|
||||
@Getter
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class PromVectorOrMatrix {
|
||||
private String status;
|
||||
private Data data;
|
||||
@@ -81,15 +81,18 @@ public class PromVectorOrMatrix {
|
||||
@lombok.Data
|
||||
@NoArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
public static class MetricJsonObjectDeserializer extends JsonDeserializer<JsonObject>{
|
||||
public static class MetricJsonObjectDeserializer extends ValueDeserializer<JsonObject> {
|
||||
|
||||
@Override
|
||||
public JsonObject deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
|
||||
ObjectCodec oc = jp.getCodec();
|
||||
JsonNode node = oc.readTree(jp);
|
||||
public JsonObject deserialize(JsonParser jp, DeserializationContext ctxt) {
|
||||
JsonNode node = jp.objectReadContext().readTree(jp);
|
||||
|
||||
JsonObject metric = new JsonObject();
|
||||
node.fields().forEachRemaining(entry -> metric.addProperty(entry.getKey(), entry.getValue().asText()));
|
||||
if (node != null && node.isObject()) {
|
||||
node.properties().forEach(entry ->
|
||||
metric.addProperty(entry.getKey(), entry.getValue().asString())
|
||||
);
|
||||
}
|
||||
|
||||
return metric;
|
||||
}
|
||||
|
||||
+4
-3
@@ -17,15 +17,16 @@
|
||||
|
||||
package org.apache.hertzbeat.common.entity.sd;
|
||||
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
import tools.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
|
||||
import tools.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
import tools.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
|
||||
|
||||
/**
|
||||
* eureka service discovery entity
|
||||
|
||||
+6
-14
@@ -17,12 +17,11 @@
|
||||
|
||||
package org.apache.hertzbeat.common.serialize;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.common.entity.log.LogEntry;
|
||||
import org.apache.hertzbeat.common.util.JsonUtil;
|
||||
import org.apache.kafka.common.header.Headers;
|
||||
import org.apache.kafka.common.serialization.Deserializer;
|
||||
|
||||
@@ -32,12 +31,6 @@ import org.apache.kafka.common.serialization.Deserializer;
|
||||
@Slf4j
|
||||
public class KafkaLogEntryDeserializer implements Deserializer<LogEntry> {
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
public KafkaLogEntryDeserializer() {
|
||||
this.objectMapper = new ObjectMapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(Map<String, ?> configs, boolean isKey) {
|
||||
Deserializer.super.configure(configs, isKey);
|
||||
@@ -49,13 +42,12 @@ public class KafkaLogEntryDeserializer implements Deserializer<LogEntry> {
|
||||
log.warn("Empty data received for topic: {}", topic);
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
String jsonString = new String(data, StandardCharsets.UTF_8);
|
||||
return objectMapper.readValue(jsonString, LogEntry.class);
|
||||
} catch (JsonProcessingException e) {
|
||||
log.error("Failed to deserialize LogEntry from JSON for topic: {}", topic, e);
|
||||
return null;
|
||||
String jsonString = new String(data, StandardCharsets.UTF_8);
|
||||
LogEntry logEntry = JsonUtil.fromJson(jsonString, LogEntry.class);
|
||||
if (logEntry == null) {
|
||||
log.warn("Failed to deserialize LogEntry from topic: {}", topic);
|
||||
}
|
||||
return logEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+5
-13
@@ -17,12 +17,11 @@
|
||||
|
||||
package org.apache.hertzbeat.common.serialize;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.common.entity.log.LogEntry;
|
||||
import org.apache.hertzbeat.common.util.JsonUtil;
|
||||
import org.apache.kafka.common.header.Headers;
|
||||
import org.apache.kafka.common.serialization.Serializer;
|
||||
|
||||
@@ -32,12 +31,6 @@ import org.apache.kafka.common.serialization.Serializer;
|
||||
@Slf4j
|
||||
public class KafkaLogEntrySerializer implements Serializer<LogEntry> {
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
public KafkaLogEntrySerializer() {
|
||||
this.objectMapper = new ObjectMapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(Map<String, ?> configs, boolean isKey) {
|
||||
Serializer.super.configure(configs, isKey);
|
||||
@@ -49,13 +42,12 @@ public class KafkaLogEntrySerializer implements Serializer<LogEntry> {
|
||||
log.warn("LogEntry is null for topic: {}", topic);
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
String jsonString = objectMapper.writeValueAsString(logEntry);
|
||||
return jsonString.getBytes(StandardCharsets.UTF_8);
|
||||
} catch (JsonProcessingException e) {
|
||||
log.error("Failed to serialize LogEntry to JSON for topic: {}", topic, e);
|
||||
String jsonString = JsonUtil.toJson(logEntry);
|
||||
if (jsonString == null) {
|
||||
log.error("Failed to serialize LogEntry for topic: {}", topic);
|
||||
return null;
|
||||
}
|
||||
return jsonString.getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+10
-18
@@ -17,11 +17,11 @@
|
||||
|
||||
package org.apache.hertzbeat.common.serialize;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.lettuce.core.codec.RedisCodec;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.common.entity.log.LogEntry;
|
||||
import org.apache.hertzbeat.common.util.JsonUtil;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@@ -32,12 +32,6 @@ import java.nio.charset.StandardCharsets;
|
||||
@Slf4j
|
||||
public class RedisLogEntryCodec implements RedisCodec<String, LogEntry> {
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
public RedisLogEntryCodec() {
|
||||
this.objectMapper = new ObjectMapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String decodeKey(ByteBuffer byteBuffer) {
|
||||
return Unpooled.wrappedBuffer(byteBuffer).toString(StandardCharsets.UTF_8);
|
||||
@@ -48,13 +42,12 @@ public class RedisLogEntryCodec implements RedisCodec<String, LogEntry> {
|
||||
if (byteBuffer == null || !byteBuffer.hasRemaining()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
String jsonString = Unpooled.wrappedBuffer(byteBuffer).toString(StandardCharsets.UTF_8);
|
||||
return objectMapper.readValue(jsonString, LogEntry.class);
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to decode LogEntry from JSON: {}", e.getMessage());
|
||||
return null;
|
||||
String jsonString = Unpooled.wrappedBuffer(byteBuffer).toString(StandardCharsets.UTF_8);
|
||||
LogEntry logEntry = JsonUtil.fromJson(jsonString, LogEntry.class);
|
||||
if (logEntry == null) {
|
||||
log.error("Failed to decode LogEntry from JSON");
|
||||
}
|
||||
return logEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -64,12 +57,11 @@ public class RedisLogEntryCodec implements RedisCodec<String, LogEntry> {
|
||||
|
||||
@Override
|
||||
public ByteBuffer encodeValue(LogEntry logEntry) {
|
||||
try {
|
||||
String jsonString = objectMapper.writeValueAsString(logEntry);
|
||||
return ByteBuffer.wrap(jsonString.getBytes(StandardCharsets.UTF_8));
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to encode LogEntry to JSON: {}", e.getMessage());
|
||||
String jsonString = JsonUtil.toJson(logEntry);
|
||||
if (jsonString == null) {
|
||||
log.error("Failed to encode LogEntry to JSON");
|
||||
return null;
|
||||
}
|
||||
return ByteBuffer.wrap(jsonString.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -19,7 +19,6 @@
|
||||
|
||||
package org.apache.hertzbeat.common.util;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.apache.commons.jexl3.JexlBuilder;
|
||||
import org.apache.commons.jexl3.JexlContext;
|
||||
@@ -32,6 +31,7 @@ import org.apache.hertzbeat.common.constants.CommonConstants;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
|
||||
/**
|
||||
* jexl express runner
|
||||
|
||||
+81
-31
@@ -19,15 +19,18 @@ package org.apache.hertzbeat.common.util;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import tools.jackson.core.JacksonException;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
import tools.jackson.databind.DeserializationFeature;
|
||||
import tools.jackson.databind.JsonNode;
|
||||
import tools.jackson.databind.ObjectMapper;
|
||||
import tools.jackson.databind.SerializationFeature;
|
||||
import tools.jackson.databind.json.JsonMapper;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* json util
|
||||
@@ -36,27 +39,25 @@ import lombok.extern.slf4j.Slf4j;
|
||||
@Slf4j
|
||||
public final class JsonUtil {
|
||||
|
||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||
|
||||
private static final ObjectMapper OBJECT_MAPPER = JsonMapper.builder()
|
||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||
.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false)
|
||||
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
|
||||
.changeDefaultVisibility(vc -> vc.withVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY))
|
||||
.build();
|
||||
|
||||
private JsonUtil() {
|
||||
}
|
||||
|
||||
static {
|
||||
OBJECT_MAPPER
|
||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
|
||||
.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)
|
||||
.registerModule(new JavaTimeModule());
|
||||
}
|
||||
|
||||
public static String toJson(Object source) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return OBJECT_MAPPER.writeValueAsString(source);
|
||||
} catch (JsonProcessingException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
} catch (JacksonException e) {
|
||||
log.error("Error converting object to JSON: {}", e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -67,8 +68,8 @@ public final class JsonUtil {
|
||||
}
|
||||
try {
|
||||
return OBJECT_MAPPER.readValue(jsonStr, clazz);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
} catch (JacksonException e) {
|
||||
log.error("Error parsing JSON to class {}: {}", clazz.getName(), e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -79,8 +80,8 @@ public final class JsonUtil {
|
||||
}
|
||||
try {
|
||||
return OBJECT_MAPPER.readValue(jsonStr, type);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
} catch (JacksonException e) {
|
||||
log.error("Error parsing JSON to TypeReference: {}", e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -91,8 +92,8 @@ public final class JsonUtil {
|
||||
}
|
||||
try {
|
||||
return OBJECT_MAPPER.readTree(jsonStr);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
} catch (JacksonException e) {
|
||||
log.error("Error reading JSON tree: {}", e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -102,21 +103,18 @@ public final class JsonUtil {
|
||||
* @param jsonStr json string
|
||||
* @return true if the string is a json string
|
||||
*/
|
||||
|
||||
|
||||
public static boolean isJsonStr(String jsonStr) {
|
||||
if (jsonStr == null || jsonStr.trim().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
jsonStr = jsonStr.trim();
|
||||
if (!(jsonStr.startsWith("{") && jsonStr.endsWith("}"))
|
||||
&& !(jsonStr.startsWith("[") && jsonStr.endsWith("]"))) {
|
||||
if (!isJsonLike(jsonStr)) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
OBJECT_MAPPER.readTree(jsonStr);
|
||||
return true;
|
||||
} catch (Exception ignored) {
|
||||
} catch (JacksonException ignored) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -128,7 +126,7 @@ public final class JsonUtil {
|
||||
try {
|
||||
JsonNode jsonNode = OBJECT_MAPPER.readTree(jsonStr);
|
||||
return jsonNode.isArray();
|
||||
} catch (Exception ignore) {
|
||||
} catch (JacksonException ignore) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -142,4 +140,56 @@ public final class JsonUtil {
|
||||
char end = jsonStr.charAt(jsonStr.length() - 1);
|
||||
return (start == '{' && end == '}') || (start == '[' && end == ']');
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse JSON from InputStream to object
|
||||
* @param is input stream
|
||||
* @param type type reference
|
||||
* @return parsed object or null if error
|
||||
*/
|
||||
public static <T> T fromJson(InputStream is, TypeReference<T> type) {
|
||||
if (is == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return OBJECT_MAPPER.readValue(is, type);
|
||||
} catch (JacksonException e) {
|
||||
log.error("Error parsing JSON from InputStream to TypeReference: {}", e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write object to OutputStream as JSON
|
||||
* @param source object to serialize
|
||||
* @param os output stream
|
||||
*/
|
||||
public static void toJson(Object source, OutputStream os) {
|
||||
if (source == null || os == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
OBJECT_MAPPER.writeValue(os, source);
|
||||
} catch (JacksonException e) {
|
||||
log.error("Error writing object to OutputStream as JSON: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a value from one type to another using JSON serialization/deserialization
|
||||
* @param fromValue source value
|
||||
* @param toValueType target type
|
||||
* @return converted value or null if error
|
||||
*/
|
||||
public static <T> T convertValue(Object fromValue, Class<T> toValueType) {
|
||||
if (fromValue == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return OBJECT_MAPPER.convertValue(fromValue, toValueType);
|
||||
} catch (JacksonException e) {
|
||||
log.error("Error converting value to {}: {}", toValueType.getName(), e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.hertzbeat.common.util;
|
||||
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import tools.jackson.core.JacksonException;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
import tools.jackson.databind.DeserializationFeature;
|
||||
import tools.jackson.databind.SerializationFeature;
|
||||
import tools.jackson.dataformat.xml.XmlMapper;
|
||||
|
||||
/**
|
||||
* xml util
|
||||
*/
|
||||
@Slf4j
|
||||
public class XmlUtil {
|
||||
|
||||
private static final XmlMapper XML_MAPPER = XmlMapper.builder()
|
||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
|
||||
.build();
|
||||
|
||||
private XmlUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert object to XML string
|
||||
*/
|
||||
public static String toXml(Object source) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
return XML_MAPPER.writeValueAsString(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert XML string to object
|
||||
*/
|
||||
public static <T> T fromXml(String xml, Class<T> clazz) {
|
||||
if (StringUtils.isEmpty(xml)) {
|
||||
return null;
|
||||
}
|
||||
return XML_MAPPER.readValue(xml, clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert XML string to object with TypeReference
|
||||
*/
|
||||
public static <T> T fromXml(String xml, TypeReference<T> type) {
|
||||
if (!StringUtils.isEmpty(xml)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return XML_MAPPER.readValue(xml, type);
|
||||
} catch (JacksonException e) {
|
||||
log.error("Error parsing XML to TypeReference: {}", e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -24,7 +24,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
import java.util.Map;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -47,7 +47,7 @@ class JsonUtilTest {
|
||||
void testFromJson() {
|
||||
assertNull(JsonUtil.fromJson("", new TypeReference<>() {
|
||||
}));
|
||||
assertNull(JsonUtil.fromJson(null, new TypeReference<>() {
|
||||
assertNull(JsonUtil.fromJson((String) null, new TypeReference<>() {
|
||||
}));
|
||||
assertNull(JsonUtil.fromJson(" ", new TypeReference<>() {
|
||||
}));
|
||||
|
||||
@@ -52,20 +52,9 @@
|
||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||
</dependency>
|
||||
<!-- jpa -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.persistence</groupId>
|
||||
<artifactId>org.eclipse.persistence.jpa</artifactId>
|
||||
<version>${eclipse-jpa.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.hibernate.orm</groupId>
|
||||
<artifactId>hibernate-core</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!-- validation -->
|
||||
<dependency>
|
||||
@@ -78,11 +67,6 @@
|
||||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- jackson -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.dataformat</groupId>
|
||||
<artifactId>jackson-dataformat-xml</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
-68
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.apache.hertzbeat.common.config;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.persistence.config.SessionCustomizer;
|
||||
import org.eclipse.persistence.descriptors.ClassDescriptor;
|
||||
import org.eclipse.persistence.mappings.DatabaseMapping;
|
||||
import org.eclipse.persistence.sessions.Session;
|
||||
|
||||
/**
|
||||
* change column name that from upper-case to lower-case-with-underscore
|
||||
*/
|
||||
@Slf4j
|
||||
public class EclipseLinkCustomizer implements SessionCustomizer {
|
||||
|
||||
@Override
|
||||
public void customize(Session session) throws Exception {
|
||||
for (ClassDescriptor descriptor : session.getDescriptors().values()) {
|
||||
for (DatabaseMapping mapping : descriptor.getMappings()) {
|
||||
if (mapping.isDirectToFieldMapping()) {
|
||||
// update the column name to lower case with underscore
|
||||
if (!mapping.getField().getName().equalsIgnoreCase(mapping.getAttributeName())) {
|
||||
// already custom define the column name, ignore
|
||||
continue;
|
||||
}
|
||||
// todo here i try to change column name that from upper-case to lower-case-with-underscore
|
||||
// but failed, when update name, something relate exception happen more
|
||||
mapping.getField().setName(convertCamelCase(mapping.getAttributeName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private String convertCamelCase(String camelCase) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
if (camelCase != null && !camelCase.isEmpty()) {
|
||||
result.append(Character.toLowerCase(camelCase.charAt(0)));
|
||||
for (int i = 1; i < camelCase.length(); i++) {
|
||||
char currentChar = camelCase.charAt(i);
|
||||
if (Character.isUpperCase(currentChar)) {
|
||||
result.append('_').append(Character.toLowerCase(currentChar));
|
||||
} else {
|
||||
result.append(currentChar);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
}
|
||||
-61
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.apache.hertzbeat.common.config;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.sql.DataSource;
|
||||
import org.eclipse.persistence.config.PersistenceUnitProperties;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration;
|
||||
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter;
|
||||
import org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter;
|
||||
import org.springframework.transaction.jta.JtaTransactionManager;
|
||||
|
||||
/**
|
||||
* jpa eclipselink impl config
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(prefix = "spring.datasource", name = "url")
|
||||
public class EclipseLinkJpaConfiguration extends JpaBaseConfiguration {
|
||||
|
||||
protected EclipseLinkJpaConfiguration(DataSource dataSource, JpaProperties properties,
|
||||
ObjectProvider<JtaTransactionManager> jtaTransactionManager) {
|
||||
super(dataSource, properties, jtaTransactionManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractJpaVendorAdapter createJpaVendorAdapter() {
|
||||
return new EclipseLinkJpaVendorAdapter();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> getVendorProperties() {
|
||||
HashMap<String, Object> map = new HashMap<>(8);
|
||||
map.put(PersistenceUnitProperties.DDL_GENERATION, "create-or-extend-tables");
|
||||
map.put(PersistenceUnitProperties.SESSION_CUSTOMIZER, "org.apache.hertzbeat.common.config.EclipseLinkCustomizer");
|
||||
map.put(PersistenceUnitProperties.ALLOW_NATIVE_SQL_QUERIES, "true");
|
||||
map.put(PersistenceUnitProperties.WEAVING, "true");
|
||||
return map;
|
||||
}
|
||||
}
|
||||
+1
-3
@@ -24,7 +24,6 @@ import jakarta.persistence.EntityListeners;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.Table;
|
||||
import org.springframework.data.annotation.CreatedBy;
|
||||
@@ -78,7 +77,6 @@ public class ChatConversation {
|
||||
/**
|
||||
* List of messages in this conversation (one-to-many relationship)
|
||||
*/
|
||||
@OneToMany
|
||||
@JoinColumn(name = "conversation_id")
|
||||
@OneToMany(mappedBy = "conversation")
|
||||
private List<ChatMessage> messages;
|
||||
}
|
||||
|
||||
+9
-1
@@ -19,14 +19,16 @@ package org.apache.hertzbeat.common.entity.ai;
|
||||
|
||||
import static io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_ONLY;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EntityListeners;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Index;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.Lob;
|
||||
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import java.time.LocalDateTime;
|
||||
@@ -59,8 +61,14 @@ public class ChatMessage {
|
||||
private Long id;
|
||||
|
||||
@Schema(title = "conversation id")
|
||||
@Column(name = "conversation_id", insertable = false, updatable = false)
|
||||
private Long conversationId;
|
||||
|
||||
@Schema(title = "conversation", hidden = true)
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "conversation_id")
|
||||
private ChatConversation conversation;
|
||||
|
||||
@Schema(title = "message content")
|
||||
@Lob
|
||||
@NotBlank
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
|
||||
package org.apache.hertzbeat.common.entity.alerter;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.Converter;
|
||||
import java.util.HashMap;
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
|
||||
package org.apache.hertzbeat.common.entity.manager;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.Converter;
|
||||
import java.util.List;
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
|
||||
package org.apache.hertzbeat.common.entity.manager;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.Converter;
|
||||
import java.util.List;
|
||||
|
||||
+1
-1
@@ -17,13 +17,13 @@
|
||||
|
||||
package org.apache.hertzbeat.common.entity.manager;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.Converter;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.apache.hertzbeat.common.util.JsonUtil;
|
||||
import org.springframework.stereotype.Component;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
|
||||
/**
|
||||
* json map list str converter
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
|
||||
package org.apache.hertzbeat.common.entity.manager;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.Converter;
|
||||
import java.util.List;
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
|
||||
package org.apache.hertzbeat.common.entity.manager;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.Converter;
|
||||
import java.util.List;
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.hertzbeat.common.util;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* xml util
|
||||
*/
|
||||
@Slf4j
|
||||
public class XmlUtil {
|
||||
|
||||
private static final XmlMapper XML_MAPPER = new XmlMapper();
|
||||
|
||||
static {
|
||||
XML_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
|
||||
.registerModule(new JavaTimeModule());
|
||||
}
|
||||
|
||||
public String toXml(Object source) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return XML_MAPPER.writeValueAsString(source);
|
||||
} catch (JsonProcessingException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T fromXml(String xml, Class<T> clazz) {
|
||||
if (!StringUtils.hasText(xml)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return XML_MAPPER.readValue(xml, clazz);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T fromXml(String xml, TypeReference<T> type) {
|
||||
if (!StringUtils.hasText(xml)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return XML_MAPPER.readValue(xml, type);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -39,6 +39,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.mockito.Mockito.lenient;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@@ -71,7 +72,7 @@ public abstract class AbstractCollectE2eTest {
|
||||
public void setUp() throws Exception {
|
||||
// Initialize mocks
|
||||
MockitoAnnotations.openMocks(this);
|
||||
when(defineDao.findAll()).thenReturn(new ArrayList<>());
|
||||
lenient().when(defineDao.findAll()).thenReturn(new ArrayList<>());
|
||||
when(timeout.task()).thenReturn(timerJob);
|
||||
when(timerJob.getJob()).thenReturn(job);
|
||||
metricsCollect = new MetricsCollect(mock(Metrics.class), timeout, mock(CollectDataDispatch.class), null, List.of());
|
||||
|
||||
@@ -31,8 +31,6 @@
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<okhttp.version>4.12.0</okhttp.version>
|
||||
<jackson.version>2.15.2</jackson.version>
|
||||
<maven.resources.plugin.version>3.3.1</maven.resources.plugin.version>
|
||||
<maven.dependency.plugin.version>3.6.1</maven.dependency.plugin.version>
|
||||
|
||||
@@ -84,6 +82,11 @@
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-test-autoconfigure</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- JUnit 5 -->
|
||||
<dependency>
|
||||
|
||||
+30
-18
@@ -28,10 +28,11 @@ import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.mock.mockito.SpyBean;
|
||||
import org.springframework.boot.test.web.server.LocalServerPort;
|
||||
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;
|
||||
import org.springframework.test.context.DynamicPropertyRegistry;
|
||||
import org.springframework.test.context.DynamicPropertySource;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
import org.testcontainers.containers.Network;
|
||||
import org.testcontainers.containers.wait.strategy.Wait;
|
||||
@@ -44,6 +45,7 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.awaitility.Awaitility.await;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
@@ -59,6 +61,10 @@ import static org.mockito.Mockito.doAnswer;
|
||||
* E2E tests for periodic log alert processing.
|
||||
*/
|
||||
@SpringBootTest(classes = org.apache.hertzbeat.startup.HertzBeatApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
@TestPropertySource(properties = {
|
||||
"warehouse.store.duckdb.enabled=false",
|
||||
"warehouse.store.greptime.enabled=true"
|
||||
})
|
||||
@Slf4j
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
public class LogPeriodicAlertE2eTest {
|
||||
@@ -81,7 +87,7 @@ public class LogPeriodicAlertE2eTest {
|
||||
AlertDefine errorCountAlertByGroup;
|
||||
AlertDefine errorCountAlertByIndividual;
|
||||
|
||||
@SpyBean
|
||||
@MockitoSpyBean
|
||||
private AlarmCommonReduce alarmCommonReduce;
|
||||
|
||||
static GenericContainer<?> vector;
|
||||
@@ -101,9 +107,7 @@ public class LogPeriodicAlertE2eTest {
|
||||
|
||||
@DynamicPropertySource
|
||||
static void greptimeProps(DynamicPropertyRegistry r) {
|
||||
// Configure GreptimeDB storage
|
||||
r.add("warehouse.store.duckdb.enabled", () -> "false");
|
||||
r.add("warehouse.store.greptime.enabled", () -> "true");
|
||||
// Configure GreptimeDB storage endpoints (dynamic ports)
|
||||
r.add("warehouse.store.greptime.http-endpoint", () -> "http://localhost:" + greptimedb.getMappedPort(GREPTIME_HTTP_PORT));
|
||||
r.add("warehouse.store.greptime.grpc-endpoints", () -> "localhost:" + greptimedb.getMappedPort(GREPTIME_GRPC_PORT));
|
||||
r.add("warehouse.store.greptime.username", () -> "");
|
||||
@@ -111,10 +115,15 @@ public class LogPeriodicAlertE2eTest {
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
void setUpAll() {
|
||||
void setUpAll() throws InterruptedException {
|
||||
// Setup test alert definitions
|
||||
setupTestAlertDefines();
|
||||
Testcontainers.exposeHostPorts(port);
|
||||
|
||||
// Wait for HertzBeat to be fully ready before starting Vector
|
||||
log.info("Waiting for HertzBeat to be fully ready on port {}...", port);
|
||||
Thread.sleep(5000); // Give HertzBeat time to fully initialize
|
||||
|
||||
vector = new GenericContainer<>(DockerImageName.parse(VECTOR_IMAGE))
|
||||
.withExposedPorts(VECTOR_PORT)
|
||||
.withCopyFileToContainer(MountableFile.forClasspathResource("vector.yml"), VECTOR_CONFIG_PATH)
|
||||
@@ -171,19 +180,22 @@ public class LogPeriodicAlertE2eTest {
|
||||
|
||||
await().atMost(Duration.ofSeconds(60))
|
||||
.pollInterval(Duration.ofSeconds(3))
|
||||
.untilAsserted(() -> assertFalse(capturedGroupAlerts.isEmpty(),
|
||||
"Should have generated periodic error count group alert"));
|
||||
.untilAsserted(() -> {
|
||||
Optional<SingleAlert> matchedAlert = capturedGroupAlerts.stream()
|
||||
.flatMap(List::stream)
|
||||
.filter(alert -> alert.getLabels() != null)
|
||||
.filter(alert -> String.valueOf(errorCountAlertByGroup.getId())
|
||||
.equals(alert.getLabels().get(CommonConstants.LABEL_DEFINE_ID)))
|
||||
.findFirst();
|
||||
|
||||
List<SingleAlert> groupAlerts = capturedGroupAlerts.get(0);
|
||||
|
||||
assertNotNull(groupAlerts, "Group alerts should not be null");
|
||||
assertFalse(groupAlerts.isEmpty(), "Group alerts should not be empty");
|
||||
|
||||
SingleAlert anyAlert = groupAlerts.get(0);
|
||||
assertEquals(CommonConstants.ALERT_STATUS_FIRING, anyAlert.getStatus(), "Alert should be in firing status");
|
||||
assertNotNull(anyAlert.getLabels(), "Alert should have labels");
|
||||
assertEquals(CommonConstants.ALERT_SEVERITY_CRITICAL, anyAlert.getLabels().get(CommonConstants.LABEL_ALERT_SEVERITY), "Alert should have critical severity");
|
||||
assertTrue(anyAlert.getTriggerTimes() >= 1, "Alert should indicate aggregated trigger times");
|
||||
assertTrue(matchedAlert.isPresent(), "Should have captured group alert from target alert define");
|
||||
SingleAlert anyAlert = matchedAlert.get();
|
||||
assertEquals(CommonConstants.ALERT_STATUS_FIRING, anyAlert.getStatus(), "Alert should be in firing status");
|
||||
assertEquals(CommonConstants.ALERT_SEVERITY_CRITICAL,
|
||||
anyAlert.getLabels().get(CommonConstants.LABEL_ALERT_SEVERITY),
|
||||
"Alert should have critical severity");
|
||||
assertTrue(anyAlert.getTriggerTimes() >= 1, "Alert should indicate aggregated trigger times");
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+12
-6
@@ -27,8 +27,8 @@ import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.mock.mockito.SpyBean;
|
||||
import org.springframework.boot.test.web.server.LocalServerPort;
|
||||
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
import org.testcontainers.containers.Network;
|
||||
import org.testcontainers.containers.wait.strategy.Wait;
|
||||
@@ -64,7 +64,8 @@ public class LogRealTimeAlertE2eTest {
|
||||
private static final int VECTOR_PORT = 8686;
|
||||
private static final String VECTOR_CONFIG_PATH = "/etc/vector/vector.yml";
|
||||
private static final String ENV_HERTZBEAT_PORT = "HERTZBEAT_PORT";
|
||||
private static final Duration CONTAINER_STARTUP_TIMEOUT = Duration.ofSeconds(120);
|
||||
private static final Duration CONTAINER_STARTUP_TIMEOUT = Duration.ofSeconds(180);
|
||||
private static final Duration TEST_WAIT_TIMEOUT = Duration.ofSeconds(120);
|
||||
|
||||
@LocalServerPort
|
||||
private int port;
|
||||
@@ -72,18 +73,23 @@ public class LogRealTimeAlertE2eTest {
|
||||
private final List<SingleAlert> capturedAlerts = new ArrayList<>();
|
||||
private final ArrayList<List<SingleAlert>> capturedGroupAlerts = new ArrayList<>();
|
||||
|
||||
@SpyBean
|
||||
@MockitoSpyBean
|
||||
private AlarmCommonReduce alarmCommonReduce;
|
||||
|
||||
static GenericContainer<?> vector;
|
||||
|
||||
@BeforeAll
|
||||
void setUpAll() {
|
||||
void setUpAll() throws InterruptedException {
|
||||
// Setup test alert definitions
|
||||
setupTestAlertDefines();
|
||||
|
||||
// Expose host ports for testcontainers
|
||||
Testcontainers.exposeHostPorts(port);
|
||||
|
||||
// Wait for HertzBeat to be fully ready before starting Vector
|
||||
log.info("Waiting for HertzBeat to be fully ready on port {}...", port);
|
||||
Thread.sleep(5000); // Give HertzBeat time to fully initialize
|
||||
|
||||
vector = new GenericContainer<>(DockerImageName.parse(VECTOR_IMAGE))
|
||||
.withExposedPorts(VECTOR_PORT)
|
||||
.withCopyFileToContainer(MountableFile.forClasspathResource("vector.yml"), VECTOR_CONFIG_PATH)
|
||||
@@ -107,8 +113,8 @@ public class LogRealTimeAlertE2eTest {
|
||||
capturedAlerts.clear();
|
||||
|
||||
// Wait for real alert to be generated through AlarmCommonReduce
|
||||
await().atMost(Duration.ofSeconds(60))
|
||||
.pollInterval(Duration.ofSeconds(2))
|
||||
await().atMost(TEST_WAIT_TIMEOUT)
|
||||
.pollInterval(Duration.ofSeconds(3))
|
||||
.untilAsserted(() -> assertFalse(capturedAlerts.isEmpty(),
|
||||
"Should have generated at least one alert for error logs"));
|
||||
|
||||
|
||||
+6
-1
@@ -64,8 +64,13 @@ public class LogIngestionE2eTest {
|
||||
static GenericContainer<?> vector;
|
||||
|
||||
@BeforeAll
|
||||
void setUpAll() {
|
||||
void setUpAll() throws InterruptedException {
|
||||
Testcontainers.exposeHostPorts(port);
|
||||
|
||||
// Wait for HertzBeat to be fully ready before starting Vector
|
||||
log.info("Waiting for HertzBeat to be fully ready on port {}...", port);
|
||||
Thread.sleep(5000); // Give HertzBeat time to fully initialize
|
||||
|
||||
vector = new GenericContainer<>(DockerImageName.parse(VECTOR_IMAGE))
|
||||
.withExposedPorts(VECTOR_PORT)
|
||||
.withCopyFileToContainer(MountableFile.forClasspathResource("vector.yml"), VECTOR_CONFIG_PATH)
|
||||
|
||||
+31
-10
@@ -29,6 +29,10 @@ import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.web.server.LocalServerPort;
|
||||
import org.springframework.test.context.DynamicPropertyRegistry;
|
||||
import org.springframework.test.context.DynamicPropertySource;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
import org.testcontainers.containers.Network;
|
||||
import org.testcontainers.containers.wait.strategy.Wait;
|
||||
@@ -37,8 +41,6 @@ import org.testcontainers.utility.DockerImageName;
|
||||
import org.testcontainers.utility.MountableFile;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.awaitility.Awaitility.await;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
@@ -48,6 +50,10 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
* E2E tests for GreptimeDB log storage.
|
||||
*/
|
||||
@SpringBootTest(classes = org.apache.hertzbeat.startup.HertzBeatApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
@TestPropertySource(properties = {
|
||||
"warehouse.store.duckdb.enabled=false",
|
||||
"warehouse.store.greptime.enabled=true"
|
||||
})
|
||||
@Slf4j
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
public class GreptimeLogStorageE2eTest {
|
||||
@@ -86,8 +92,6 @@ public class GreptimeLogStorageE2eTest {
|
||||
|
||||
@DynamicPropertySource
|
||||
static void greptimeProps(DynamicPropertyRegistry r) {
|
||||
r.add("warehouse.store.duckdb.enabled", () -> "false");
|
||||
r.add("warehouse.store.greptime.enabled", () -> "true");
|
||||
r.add("warehouse.store.greptime.http-endpoint", () -> "http://localhost:" + greptimedb.getMappedPort(GREPTIME_HTTP_PORT));
|
||||
r.add("warehouse.store.greptime.grpc-endpoints", () -> "localhost:" + greptimedb.getMappedPort(GREPTIME_GRPC_PORT));
|
||||
r.add("warehouse.store.greptime.username", () -> "");
|
||||
@@ -96,10 +100,14 @@ public class GreptimeLogStorageE2eTest {
|
||||
|
||||
|
||||
@BeforeAll
|
||||
void setUpAll() {
|
||||
void setUpAll() throws InterruptedException {
|
||||
// Expose host ports for testcontainers
|
||||
Testcontainers.exposeHostPorts(port);
|
||||
|
||||
// Wait for HertzBeat to be fully ready before starting Vector
|
||||
log.info("Waiting for HertzBeat to be fully ready on port {}...", port);
|
||||
Thread.sleep(5000); // Give HertzBeat time to fully initialize
|
||||
|
||||
vector = new GenericContainer<>(DockerImageName.parse(VECTOR_IMAGE))
|
||||
.withExposedPorts(VECTOR_PORT)
|
||||
.withCopyFileToContainer(MountableFile.forClasspathResource("vector.yml"), VECTOR_CONFIG_PATH)
|
||||
@@ -114,6 +122,7 @@ public class GreptimeLogStorageE2eTest {
|
||||
|
||||
@Test
|
||||
void testLogStorageToGreptimeDb() {
|
||||
log.info("GreptimeDbDataStorage serverAvailable: {}", greptimeDbDataStorage.isServerAvailable());
|
||||
|
||||
List<LogEntry> capturedLogs = new ArrayList<>();
|
||||
|
||||
@@ -143,12 +152,24 @@ public class GreptimeLogStorageE2eTest {
|
||||
assertNotNull(firstLog.getBody(), "Log body should not be null");
|
||||
assertNotNull(firstLog.getSeverityText(), "Severity text should not be null");
|
||||
|
||||
// Directly write logs to GreptimeDB to test storage functionality
|
||||
log.info("Directly writing {} captured logs to GreptimeDB", capturedLogs.size());
|
||||
greptimeDbDataStorage.saveLogDataBatch(capturedLogs);
|
||||
|
||||
// Give some time for the write to complete
|
||||
try {
|
||||
Thread.sleep(2000);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
// Additional wait to ensure logs are persisted to GreptimeDB
|
||||
await().atMost(Duration.ofSeconds(30))
|
||||
.pollInterval(Duration.ofSeconds(2))
|
||||
.untilAsserted(() -> {
|
||||
// Query GreptimeDB directly to verify data persistence
|
||||
List<LogEntry> storedLogs = queryStoredLogs();
|
||||
log.info("Queried {} logs from GreptimeDB", storedLogs.size());
|
||||
assertFalse(storedLogs.isEmpty(), "Should have logs stored in GreptimeDB");
|
||||
});
|
||||
}
|
||||
@@ -157,10 +178,10 @@ public class GreptimeLogStorageE2eTest {
|
||||
* Helper method to query stored logs directly from GreptimeDB
|
||||
*/
|
||||
private List<LogEntry> queryStoredLogs() {
|
||||
long endTime = System.currentTimeMillis();
|
||||
long startTime = endTime - Duration.ofMinutes(5).toMillis(); // Look back 5 minutes
|
||||
|
||||
return greptimeDbDataStorage.queryLogsByMultipleConditions(
|
||||
startTime, endTime, null, null, null, null, null);
|
||||
// Query without time condition to verify data exists
|
||||
List<LogEntry> result = greptimeDbDataStorage.queryLogsByMultipleConditions(
|
||||
null, null, null, null, null, null, null);
|
||||
log.info("queryLogsByMultipleConditions returned {} entries", result.size());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ sinks:
|
||||
encoding:
|
||||
codec: json
|
||||
|
||||
# Send to HertzBeat
|
||||
# Send to HertzBeat with increased timeout and retry
|
||||
emit_syslog:
|
||||
inputs: [ "remap_syslog" ]
|
||||
type: opentelemetry
|
||||
@@ -114,4 +114,13 @@ sinks:
|
||||
strategy: basic
|
||||
user: admin
|
||||
password: hertzbeat
|
||||
|
||||
# Increase timeout and retry settings for stability in CI environments
|
||||
request:
|
||||
timeout_secs: 60
|
||||
retry_attempts: 10
|
||||
retry_initial_backoff_secs: 2
|
||||
retry_max_duration_secs: 120
|
||||
# Batch settings for better throughput
|
||||
batch:
|
||||
max_bytes: 524288
|
||||
timeout_secs: 5
|
||||
|
||||
@@ -42,6 +42,11 @@
|
||||
<groupId>org.apache.hertzbeat</groupId>
|
||||
<artifactId>hertzbeat-warehouse</artifactId>
|
||||
</dependency>
|
||||
<!-- hertzbeat common-core -->
|
||||
<dependency>
|
||||
<groupId>org.apache.hertzbeat</groupId>
|
||||
<artifactId>hertzbeat-common-core</artifactId>
|
||||
</dependency>
|
||||
<!-- jpa -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
||||
+5
-5
@@ -17,8 +17,7 @@
|
||||
|
||||
package org.apache.hertzbeat.grafana.service;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import tools.jackson.databind.JsonNode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.hertzbeat.base.dao.GeneralConfigDao;
|
||||
@@ -77,8 +76,6 @@ public class DashboardService {
|
||||
@Autowired
|
||||
private GeneralConfigDao generalConfigDao;
|
||||
|
||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||
|
||||
/**
|
||||
* Creates or updates a dashboard in Grafana.
|
||||
* The "id" field will be removed from the dashboard JSON before sending
|
||||
@@ -275,7 +272,10 @@ public class DashboardService {
|
||||
try {
|
||||
GeneralConfig config = generalConfigDao.findByType(GeneralConfigTypeEnum.system.name());
|
||||
if (config != null && config.getContent() != null) {
|
||||
JsonNode root = OBJECT_MAPPER.readTree(config.getContent());
|
||||
JsonNode root = JsonUtil.fromJson(config.getContent());
|
||||
if (root == null) {
|
||||
return ThemeEnum.LIGHT.getValue();
|
||||
}
|
||||
JsonNode node = root.get("theme");
|
||||
if (node != null && !node.isNull()) {
|
||||
return ThemeEnum.convert(node.asText());
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ import static org.apache.hertzbeat.grafana.common.GrafanaConstants.CREATE_SERVIC
|
||||
import static org.apache.hertzbeat.grafana.common.GrafanaConstants.CREATE_SERVICE_TOKEN_API;
|
||||
import static org.apache.hertzbeat.grafana.common.GrafanaConstants.GET_SERVICE_ACCOUNTS_API;
|
||||
import static org.apache.hertzbeat.grafana.common.GrafanaConstants.GRAFANA_CONFIG;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import tools.jackson.databind.JsonNode;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
@@ -138,10 +138,10 @@
|
||||
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||
</dependency>
|
||||
<!-- database migration -->
|
||||
<dependency>
|
||||
<groupId>org.flywaydb</groupId>
|
||||
<artifactId>flyway-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-flyway</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.flywaydb</groupId>
|
||||
<artifactId>flyway-mysql</artifactId>
|
||||
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.usthe.sureness.configuration;
|
||||
|
||||
import com.usthe.sureness.mgt.SecurityManager;
|
||||
import com.usthe.sureness.processor.exception.DisabledAccountException;
|
||||
import com.usthe.sureness.processor.exception.ExcessiveAttemptsException;
|
||||
import com.usthe.sureness.processor.exception.ExpiredCredentialsException;
|
||||
import com.usthe.sureness.processor.exception.IncorrectCredentialsException;
|
||||
import com.usthe.sureness.processor.exception.NeedDigestInfoException;
|
||||
import com.usthe.sureness.processor.exception.UnauthorizedException;
|
||||
import com.usthe.sureness.processor.exception.UnknownAccountException;
|
||||
import com.usthe.sureness.subject.SubjectSum;
|
||||
import com.usthe.sureness.util.SurenessContextHolder;
|
||||
import jakarta.servlet.Filter;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.FilterConfig;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import jakarta.servlet.ServletResponse;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* Override the default servlet filter
|
||||
*/
|
||||
public class SurenessJakartaServletFilter implements Filter {
|
||||
|
||||
private final SecurityManager securityManager;
|
||||
|
||||
public SurenessJakartaServletFilter(SecurityManager securityManager) {
|
||||
this.securityManager = securityManager;
|
||||
}
|
||||
|
||||
/** logger **/
|
||||
private static final Logger logger = LoggerFactory.getLogger(SurenessJakartaServletFilter.class);
|
||||
|
||||
private static final String UPGRADE = "Upgrade";
|
||||
|
||||
private static final String WEBSOCKET = "websocket";
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) {
|
||||
logger.info("servlet surenessFilter initialized");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
logger.info("servlet surenessFilter destroyed");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
|
||||
FilterChain filterChain)
|
||||
throws IOException, ServletException {
|
||||
|
||||
try {
|
||||
SubjectSum subject = securityManager.checkIn(servletRequest);
|
||||
// You can consider using SurenessContextHolder to bind subject in threadLocal
|
||||
// if bind, please remove it when end
|
||||
if (subject != null) {
|
||||
SurenessContextHolder.bindSubject(subject);
|
||||
}
|
||||
} catch (IncorrectCredentialsException | UnknownAccountException | ExpiredCredentialsException e1) {
|
||||
logger.debug("this request account info is illegal, {}", e1.getMessage());
|
||||
responseWrite(ResponseEntity
|
||||
.status(HttpStatus.UNAUTHORIZED)
|
||||
.body("Username or password is incorrect or token expired"), servletResponse);
|
||||
return;
|
||||
} catch (DisabledAccountException | ExcessiveAttemptsException e2) {
|
||||
logger.debug("the account is disabled, {}", e2.getMessage());
|
||||
responseWrite(ResponseEntity
|
||||
.status(HttpStatus.UNAUTHORIZED).body("Account is disabled"), servletResponse);
|
||||
return;
|
||||
} catch (NeedDigestInfoException e3) {
|
||||
logger.debug("you should try once again with digest auth information");
|
||||
responseWrite(ResponseEntity
|
||||
.status(HttpStatus.UNAUTHORIZED)
|
||||
.header("WWW-Authenticate", e3.getAuthenticate()).build(), servletResponse);
|
||||
return;
|
||||
} catch (UnauthorizedException e4) {
|
||||
logger.debug("this account can not access this resource, {}", e4.getMessage());
|
||||
responseWrite(ResponseEntity
|
||||
.status(HttpStatus.FORBIDDEN)
|
||||
.body("This account has no permission to access this resource"), servletResponse);
|
||||
return;
|
||||
} catch (RuntimeException e) {
|
||||
logger.error("other exception happen: ", e);
|
||||
responseWrite(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(),
|
||||
servletResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// if ok, doFilter and add subject in request
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
} finally {
|
||||
int statusCode = ((HttpServletResponse) servletResponse).getStatus();
|
||||
String upgrade = ((HttpServletResponse) servletResponse).getHeader(UPGRADE);
|
||||
if (statusCode != HttpStatus.SWITCHING_PROTOCOLS.value() || !WEBSOCKET.equals(upgrade)) {
|
||||
SurenessContextHolder.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* write response json data
|
||||
* @param content content
|
||||
* @param response response
|
||||
*/
|
||||
private static void responseWrite(ResponseEntity content, ServletResponse response) {
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
((HttpServletResponse) response).setStatus(content.getStatusCode().value());
|
||||
content.getHeaders().forEach((key, value) ->
|
||||
((HttpServletResponse) response).addHeader(key, value.get(0)));
|
||||
try (PrintWriter printWriter = response.getWriter()) {
|
||||
if (content.getBody() != null) {
|
||||
printWriter.write(content.getBody().toString());
|
||||
} else {
|
||||
printWriter.flush();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.error("responseWrite response error: ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
-47
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.hertzbeat.manager.component.listener;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.TimeZone;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.common.support.event.SystemConfigChangeEvent;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Listener for config Jackson timezone
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class TimeZoneListener {
|
||||
@Resource
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@EventListener(SystemConfigChangeEvent.class)
|
||||
public void onEvent(SystemConfigChangeEvent event) {
|
||||
log.info("{} receive system config change event: {}.", this.getClass().getName(), event.getSource());
|
||||
|
||||
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
|
||||
simpleDateFormat.setTimeZone(TimeZone.getDefault());
|
||||
objectMapper.setTimeZone(TimeZone.getDefault())
|
||||
.setDateFormat(simpleDateFormat);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
|
||||
package org.apache.hertzbeat.manager.component.validator.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
import org.apache.hertzbeat.common.entity.manager.Param;
|
||||
import org.apache.hertzbeat.common.entity.manager.ParamDefine;
|
||||
import org.apache.hertzbeat.common.util.JsonUtil;
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider;
|
||||
import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProviders;
|
||||
import org.springframework.boot.autoconfigure.web.WebProperties;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorViewResolver;
|
||||
import org.springframework.boot.webmvc.autoconfigure.error.ErrorViewResolver;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
+12
-17
@@ -6,7 +6,7 @@
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
package org.apache.hertzbeat.manager.config;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.usthe.sureness.util.JsonWebTokenUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.security.SecureRandom;
|
||||
@@ -29,6 +28,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.hertzbeat.common.constants.CommonConstants;
|
||||
import org.apache.hertzbeat.common.entity.manager.GeneralConfig;
|
||||
import org.apache.hertzbeat.common.util.AesUtil;
|
||||
import org.apache.hertzbeat.common.util.JsonUtil;
|
||||
import org.apache.hertzbeat.common.util.TimeZoneUtil;
|
||||
import org.apache.hertzbeat.base.dao.GeneralConfigDao;
|
||||
import org.apache.hertzbeat.manager.pojo.dto.MuteConfig;
|
||||
@@ -56,9 +56,9 @@ public class ConfigInitializer implements SmartLifecycle {
|
||||
private boolean running = false;
|
||||
|
||||
private static final String DEFAULT_JWT_SECRET = "CyaFv0bwq2Eik0jdrKUtsA6bx3sDJeFV643R "
|
||||
+ "LnfKefTjsIfJLBa2YkhEqEGtcHDTNe4CU6+9 "
|
||||
+ "8tVt4bisXQ13rbN0oxhUZR73M6EByXIO+SV5 "
|
||||
+ "dKhaX0csgOCTlCxq20yhmUea6H6JIpSE2Rwp";
|
||||
+ "LnfKefTjsIfJLBa2YkhEqEGtcHDTNe4CU6+9 "
|
||||
+ "8tVt4bisXQ13rbN0oxhUZR73M6EByXIO+SV5 "
|
||||
+ "dKhaX0csgOCTlCxq20yhmUea6H6JIpSE2Rwp";
|
||||
|
||||
@Value("${sureness.jwt.secret:" + DEFAULT_JWT_SECRET + "}")
|
||||
private String currentJwtSecret;
|
||||
@@ -84,9 +84,6 @@ public class ConfigInitializer implements SmartLifecycle {
|
||||
@Resource
|
||||
protected GeneralConfigDao generalConfigDao;
|
||||
|
||||
@Resource
|
||||
protected ObjectMapper objectMapper;
|
||||
|
||||
@SneakyThrows
|
||||
public void initConfig() {
|
||||
// for system config
|
||||
@@ -96,19 +93,17 @@ public class ConfigInitializer implements SmartLifecycle {
|
||||
|
||||
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
|
||||
simpleDateFormat.setTimeZone(TimeZone.getDefault());
|
||||
objectMapper.setTimeZone(TimeZone.getDefault())
|
||||
.setDateFormat(simpleDateFormat);
|
||||
} else {
|
||||
// init system config data
|
||||
systemConfig = SystemConfig.builder().timeZoneId(TimeZone.getDefault().getID()).theme("default")
|
||||
.locale(Locale.getDefault().getLanguage() + CommonConstants.LOCALE_SEPARATOR
|
||||
+ Locale.getDefault().getCountry())
|
||||
.build();
|
||||
String contentJson = objectMapper.writeValueAsString(systemConfig);
|
||||
.locale(Locale.getDefault().getLanguage() + CommonConstants.LOCALE_SEPARATOR
|
||||
+ Locale.getDefault().getCountry())
|
||||
.build();
|
||||
String contentJson = JsonUtil.toJson(systemConfig);
|
||||
GeneralConfig generalConfig2Save = GeneralConfig.builder()
|
||||
.type(systemGeneralConfigService.type())
|
||||
.content(contentJson)
|
||||
.build();
|
||||
.type(systemGeneralConfigService.type())
|
||||
.content(contentJson)
|
||||
.build();
|
||||
generalConfigDao.save(generalConfig2Save);
|
||||
}
|
||||
// for template config, flush the template config in db to memory
|
||||
|
||||
+16
-6
@@ -19,28 +19,35 @@ package org.apache.hertzbeat.manager.config;
|
||||
|
||||
import org.flywaydb.core.Flyway;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.flyway.FlywayMigrationInitializer;
|
||||
import org.springframework.boot.autoconfigure.flyway.FlywayProperties;
|
||||
import org.springframework.boot.flyway.autoconfigure.FlywayMigrationInitializer;
|
||||
import org.springframework.boot.flyway.autoconfigure.FlywayProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.DependsOn;
|
||||
|
||||
/**
|
||||
* flyway database migration config
|
||||
* Flyway database migration config.
|
||||
* Delays Flyway execution until after Hibernate has created/updated the schema.
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(prefix = "spring.flyway", name = "enabled", havingValue = "true")
|
||||
public class FlywayConfiguration {
|
||||
|
||||
/**
|
||||
* Disable the default FlywayMigrationInitializer by providing an empty callback.
|
||||
*/
|
||||
@Bean
|
||||
public FlywayMigrationInitializer flywayInitializer(Flyway flyway) {
|
||||
return new FlywayMigrationInitializer(flyway, (f) -> {
|
||||
// Empty callback - we'll run migrations manually after Hibernate
|
||||
});
|
||||
}
|
||||
|
||||
static class Dummy {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delayed Flyway migration that runs after EntityManagerFactory is initialized.
|
||||
* This ensures Hibernate's ddl-auto runs first to create/update tables,
|
||||
* then Flyway can perform additional migrations if needed.
|
||||
*/
|
||||
@Bean
|
||||
@DependsOn("entityManagerFactory")
|
||||
Dummy delayedFlywayInitializer(Flyway flyway, FlywayProperties flywayProperties) {
|
||||
@@ -49,4 +56,7 @@ public class FlywayConfiguration {
|
||||
}
|
||||
return new Dummy();
|
||||
}
|
||||
|
||||
static class Dummy {
|
||||
}
|
||||
}
|
||||
|
||||
+15
-22
@@ -6,7 +6,7 @@
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -17,39 +17,32 @@
|
||||
|
||||
package org.apache.hertzbeat.manager.config;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.TimeZone;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
|
||||
import org.springframework.boot.jackson.autoconfigure.JsonMapperBuilderCustomizer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||
import tools.jackson.databind.DeserializationFeature;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* jackson config
|
||||
* Jackson config.
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class JacksonConfig {
|
||||
|
||||
@Bean
|
||||
public Jackson2ObjectMapperBuilderCustomizer jacksonCustomizer() {
|
||||
public JsonMapperBuilderCustomizer jsonMapperBuilderCustomizer() {
|
||||
return builder -> {
|
||||
JavaTimeModule javaTimeModule = new JavaTimeModule();
|
||||
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
|
||||
final String dateTimeFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSX";
|
||||
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateTimeFormat);
|
||||
simpleDateFormat.setTimeZone(TimeZone.getDefault());
|
||||
|
||||
builder.modules(javaTimeModule)
|
||||
.timeZone(TimeZone.getDefault())
|
||||
.dateFormat(simpleDateFormat);
|
||||
builder.defaultTimeZone(TimeZone.getDefault());
|
||||
builder.defaultDateFormat(simpleDateFormat);
|
||||
|
||||
builder.disable(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES);
|
||||
builder.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+18
-19
@@ -6,7 +6,7 @@
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -17,24 +17,25 @@
|
||||
|
||||
package org.apache.hertzbeat.manager.config;
|
||||
|
||||
import java.net.http.HttpClient;
|
||||
import java.time.Duration;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import okhttp3.ConnectionPool;
|
||||
import okhttp3.OkHttpClient;
|
||||
import org.apache.hertzbeat.common.constants.NetworkConstants;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
|
||||
import org.springframework.http.client.JdkClientHttpRequestFactory;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* restTemplate config
|
||||
* todo thread pool
|
||||
* RestTemplate configuration using JDK native HttpClient for Spring 7.0.
|
||||
*/
|
||||
@Configuration
|
||||
public class RestTemplateConfig {
|
||||
|
||||
/**
|
||||
* Create RestTemplate with JDK native request factory and custom interceptors.
|
||||
*/
|
||||
@Bean
|
||||
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
|
||||
RestTemplate restTemplate = new RestTemplate(factory);
|
||||
@@ -43,19 +44,17 @@ public class RestTemplateConfig {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
|
||||
public ClientHttpRequestFactory clientHttpRequestFactory() {
|
||||
HttpClient httpClient = HttpClient.newBuilder()
|
||||
.connectTimeout(Duration.ofSeconds(NetworkConstants.HttpClientConstants.CONNECT_TIME_OUT))
|
||||
.followRedirects(HttpClient.Redirect.NORMAL)
|
||||
.build();
|
||||
|
||||
return new OkHttp3ClientHttpRequestFactory(
|
||||
new OkHttpClient.Builder()
|
||||
.readTimeout(NetworkConstants.HttpClientConstants.READ_TIME_OUT, TimeUnit.SECONDS)
|
||||
.writeTimeout(NetworkConstants.HttpClientConstants.WRITE_TIME_OUT, TimeUnit.SECONDS)
|
||||
.connectTimeout(NetworkConstants.HttpClientConstants.CONNECT_TIME_OUT, TimeUnit.SECONDS)
|
||||
.connectionPool(new ConnectionPool(
|
||||
NetworkConstants.HttpClientConstants.MAX_IDLE_CONNECTIONS,
|
||||
NetworkConstants.HttpClientConstants.KEEP_ALIVE_TIMEOUT,
|
||||
TimeUnit.SECONDS)
|
||||
).build()
|
||||
);
|
||||
JdkClientHttpRequestFactory factory = new JdkClientHttpRequestFactory(httpClient);
|
||||
|
||||
factory.setReadTimeout(Duration.ofSeconds(NetworkConstants.HttpClientConstants.READ_TIME_OUT));
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+16
-43
@@ -17,14 +17,13 @@
|
||||
|
||||
package org.apache.hertzbeat.manager.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.common.entity.manager.GeneralConfig;
|
||||
import org.apache.hertzbeat.base.dao.GeneralConfigDao;
|
||||
import org.apache.hertzbeat.base.service.GeneralConfigService;
|
||||
import org.apache.hertzbeat.common.entity.manager.GeneralConfig;
|
||||
import org.apache.hertzbeat.common.util.JsonUtil;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
|
||||
/**
|
||||
* <p>Abstract implementation of GeneralConfigService, providing CRUD operations for configurations.</p>
|
||||
@@ -34,61 +33,35 @@ abstract class AbstractGeneralConfigServiceImpl<T> implements GeneralConfigServi
|
||||
|
||||
protected final GeneralConfigDao generalConfigDao;
|
||||
|
||||
protected final ObjectMapper objectMapper;
|
||||
|
||||
/**
|
||||
* <p>Constructor, passing in GeneralConfigDao, ObjectMapper and type.</p>
|
||||
* @param generalConfigDao Dao object
|
||||
* @param objectMapper JSON tool object
|
||||
*/
|
||||
protected AbstractGeneralConfigServiceImpl(GeneralConfigDao generalConfigDao, ObjectMapper objectMapper) {
|
||||
protected AbstractGeneralConfigServiceImpl(GeneralConfigDao generalConfigDao) {
|
||||
this.generalConfigDao = generalConfigDao;
|
||||
this.objectMapper = objectMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Save a configuration.</p>
|
||||
* @param config need to save configuration object
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void saveConfig(T config) {
|
||||
try {
|
||||
String contentJson = objectMapper.writeValueAsString(config);
|
||||
|
||||
GeneralConfig generalConfig2Save = GeneralConfig.builder()
|
||||
.type(type())
|
||||
.content(contentJson)
|
||||
.build();
|
||||
generalConfigDao.save(generalConfig2Save);
|
||||
log.info("Configuration saved successfully");
|
||||
handler(getConfig());
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new IllegalArgumentException("Configuration saved failed: " + e.getMessage());
|
||||
String contentJson = JsonUtil.toJson(config);
|
||||
if (contentJson == null) {
|
||||
log.error("Failed to serialize configuration for type {}", type());
|
||||
throw new RuntimeException("Save config failed: serialization error");
|
||||
}
|
||||
GeneralConfig generalConfig2Save = GeneralConfig.builder()
|
||||
.type(type())
|
||||
.content(contentJson)
|
||||
.build();
|
||||
generalConfigDao.save(generalConfig2Save);
|
||||
log.info("Configuration of type {} saved successfully", type());
|
||||
handler(getConfig());
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Get a configuration.</p>
|
||||
* @return query configuration object
|
||||
*/
|
||||
@Override
|
||||
public T getConfig() {
|
||||
GeneralConfig generalConfig = generalConfigDao.findByType(type());
|
||||
if (generalConfig == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return objectMapper.readValue(generalConfig.getContent(), getTypeReference());
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new IllegalArgumentException("Get configuration failed: " + e.getMessage());
|
||||
}
|
||||
return JsonUtil.fromJson(generalConfig.getContent(), getTypeReference());
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Get TypeReference object of configuration type.</p>
|
||||
* @return TypeReference object
|
||||
*/
|
||||
protected abstract TypeReference<T> getTypeReference();
|
||||
|
||||
}
|
||||
|
||||
+96
-181
@@ -6,7 +6,7 @@
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -32,7 +32,6 @@ import org.apache.hertzbeat.common.entity.manager.Param;
|
||||
import org.apache.hertzbeat.common.entity.manager.ParamDefine;
|
||||
import org.apache.hertzbeat.common.entity.message.CollectRep;
|
||||
import org.apache.hertzbeat.common.support.SpringContextHolder;
|
||||
import org.apache.hertzbeat.common.support.exception.CommonException;
|
||||
import org.apache.hertzbeat.common.util.CommonUtil;
|
||||
import org.apache.hertzbeat.common.util.HertzBeatKeywordsUtil;
|
||||
import org.apache.hertzbeat.common.util.JexlCheckerUtil;
|
||||
@@ -48,6 +47,7 @@ import org.apache.hertzbeat.manager.service.MonitorService;
|
||||
import org.apache.hertzbeat.manager.service.ObjectStoreService;
|
||||
import org.apache.hertzbeat.warehouse.service.WarehouseService;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
@@ -57,7 +57,6 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.StreamUtils;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
@@ -89,26 +88,31 @@ public class AppServiceImpl implements AppService, InitializingBean {
|
||||
|
||||
private static final String PUSH_PROTOCOL_METRICS_NAME = "metrics";
|
||||
|
||||
@Resource
|
||||
private MonitorDao monitorDao;
|
||||
|
||||
@Resource
|
||||
private ObjectStoreConfigServiceImpl objectStoreConfigService;
|
||||
|
||||
@Resource
|
||||
private ParamDao paramDao;
|
||||
|
||||
@Resource
|
||||
private DefineDao defineDao;
|
||||
|
||||
@Resource
|
||||
private WarehouseService warehouseService;
|
||||
private final MonitorDao monitorDao;
|
||||
private final ObjectStoreConfigServiceImpl objectStoreConfigService;
|
||||
private final ParamDao paramDao;
|
||||
private final DefineDao defineDao;
|
||||
private final WarehouseService warehouseService;
|
||||
|
||||
private final Map<String, Job> appDefines = new ConcurrentHashMap<>();
|
||||
|
||||
private AppDefineStore appDefineStore;
|
||||
private final AppDefineStore jarAppDefineStore = new JarAppDefineStoreImpl();
|
||||
|
||||
/**
|
||||
* warehouseService is marked @Lazy to prevent potential circular dependencies.
|
||||
*/
|
||||
public AppServiceImpl(MonitorDao monitorDao,
|
||||
ObjectStoreConfigServiceImpl objectStoreConfigService,
|
||||
ParamDao paramDao,
|
||||
DefineDao defineDao,
|
||||
@Lazy WarehouseService warehouseService) {
|
||||
this.monitorDao = monitorDao;
|
||||
this.objectStoreConfigService = objectStoreConfigService;
|
||||
this.paramDao = paramDao;
|
||||
this.defineDao = defineDao;
|
||||
this.warehouseService = warehouseService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ParamDefine> getAppParamDefines(String app) {
|
||||
if (StringUtils.isNotBlank(app)){
|
||||
@@ -132,8 +136,8 @@ public class AppServiceImpl implements AppService, InitializingBean {
|
||||
if (PUSH_PROTOCOL_METRICS_NAME.equals(metric.getName())) {
|
||||
List<Param> params = paramDao.findParamsByMonitorId(monitorId);
|
||||
List<Configmap> configmaps = params.stream()
|
||||
.map(param -> new Configmap(param.getField(), param.getParamValue(),
|
||||
param.getType())).toList();
|
||||
.map(param -> new Configmap(param.getField(), param.getParamValue(),
|
||||
param.getType())).toList();
|
||||
Map<String, Configmap> configmap = configmaps.stream().collect(Collectors.toMap(Configmap::getKey, item -> item, (key1, key2) -> key1));
|
||||
CollectUtil.replaceFieldsForPushStyleMonitor(metric, configmap);
|
||||
metricsTmp.add(metric);
|
||||
@@ -145,7 +149,6 @@ public class AppServiceImpl implements AppService, InitializingBean {
|
||||
|
||||
@Override
|
||||
public Job getAutoGenerateDynamicDefine(Long monitorId) {
|
||||
// todo now only for prometheus
|
||||
Job job = getAppDefine(DispatchConstants.PROTOCOL_PROMETHEUS);
|
||||
List<CollectRep.MetricsData> metricsDataList = warehouseService.queryMonitorMetricsData(monitorId);
|
||||
Metrics tmpMetrics = job.getMetrics().get(0);
|
||||
@@ -153,18 +156,18 @@ public class AppServiceImpl implements AppService, InitializingBean {
|
||||
for (CollectRep.MetricsData metricsData : metricsDataList) {
|
||||
List<Metrics.Field> fields = metricsData.getFields().stream().map(item ->
|
||||
Metrics.Field.builder()
|
||||
.field(item.getName())
|
||||
.type((byte) item.getType())
|
||||
.label(item.getLabel())
|
||||
.unit(item.getUnit())
|
||||
.build())
|
||||
.collect(Collectors.toList());
|
||||
.field(item.getName())
|
||||
.type((byte) item.getType())
|
||||
.label(item.getLabel())
|
||||
.unit(item.getUnit())
|
||||
.build())
|
||||
.collect(Collectors.toList());
|
||||
Metrics metrics = Metrics.builder()
|
||||
.visible(true)
|
||||
.name(metricsData.getMetrics())
|
||||
.fields(fields)
|
||||
.prometheus(tmpMetrics.getPrometheus())
|
||||
.build();
|
||||
.visible(true)
|
||||
.name(metricsData.getMetrics())
|
||||
.fields(fields)
|
||||
.prometheus(tmpMetrics.getPrometheus())
|
||||
.build();
|
||||
metricsList.add(metrics);
|
||||
}
|
||||
job.setMetrics(metricsList);
|
||||
@@ -203,7 +206,7 @@ public class AppServiceImpl implements AppService, InitializingBean {
|
||||
metricNames.addAll(appDefine.getMetrics().stream().map(Metrics::getName).toList());
|
||||
} else {
|
||||
appDefines.forEach((k, v) ->
|
||||
metricNames.addAll(v.getMetrics().stream().map(Metrics::getName).toList()));
|
||||
metricNames.addAll(v.getMetrics().stream().map(Metrics::getName).toList()));
|
||||
}
|
||||
return metricNames;
|
||||
}
|
||||
@@ -283,7 +286,6 @@ public class AppServiceImpl implements AppService, InitializingBean {
|
||||
public List<Hierarchy> getAppHierarchy(String app, String lang) {
|
||||
LinkedList<Hierarchy> hierarchies = new LinkedList<>();
|
||||
Job job = appDefines.get(app.toLowerCase());
|
||||
// TODO temporarily filter out push to solve the front-end problem, and open it after the subsequent design optimization
|
||||
if (DispatchConstants.PROTOCOL_PUSH.equalsIgnoreCase(job.getApp())) {
|
||||
return hierarchies;
|
||||
}
|
||||
@@ -313,17 +315,16 @@ public class AppServiceImpl implements AppService, InitializingBean {
|
||||
hierarchyMetric.setValue(metricsData.getMetrics());
|
||||
hierarchyMetric.setLabel(metricsData.getMetrics());
|
||||
List<Hierarchy> hierarchyFieldList = metricsData.getFields().stream()
|
||||
.map(item -> {
|
||||
var hierarchyField = new Hierarchy();
|
||||
hierarchyField.setValue(item.getName());
|
||||
hierarchyField.setLabel(item.getName());
|
||||
hierarchyField.setIsLeaf(true);
|
||||
hierarchyField.setType((byte) item.getType());
|
||||
hierarchyField.setUnit(item.getUnit());
|
||||
return hierarchyField;
|
||||
}).collect(Collectors.toList());
|
||||
.map(item -> {
|
||||
var hierarchyField = new Hierarchy();
|
||||
hierarchyField.setValue(item.getName());
|
||||
hierarchyField.setLabel(item.getName());
|
||||
hierarchyField.setIsLeaf(true);
|
||||
hierarchyField.setType((byte) item.getType());
|
||||
hierarchyField.setUnit(item.getUnit());
|
||||
return hierarchyField;
|
||||
}).collect(Collectors.toList());
|
||||
hierarchyMetric.setChildren(hierarchyFieldList);
|
||||
// combine Hierarchy Metrics
|
||||
combineHierarchyMetrics(hierarchyMetricList, hierarchyMetric);
|
||||
}
|
||||
}
|
||||
@@ -344,7 +345,6 @@ public class AppServiceImpl implements AppService, InitializingBean {
|
||||
var metricI18nName = CommonUtil.getLangMappingValueFromI18nMap(lang, field.getI18n());
|
||||
hierarchyField.setLabel(metricI18nName != null ? metricI18nName : field.getField());
|
||||
hierarchyField.setIsLeaf(true);
|
||||
// for metric
|
||||
hierarchyField.setType(field.getType());
|
||||
hierarchyField.setUnit(field.getUnit());
|
||||
hierarchyFieldList.add(hierarchyField);
|
||||
@@ -361,15 +361,15 @@ public class AppServiceImpl implements AppService, InitializingBean {
|
||||
|
||||
private void combineHierarchyMetrics(List<Hierarchy> hierarchyMetricList, Hierarchy hierarchyMetric) {
|
||||
Optional<Hierarchy> preHierarchyOptional = hierarchyMetricList.stream()
|
||||
.filter(item -> item.getValue().equals(hierarchyMetric.getValue()))
|
||||
.findFirst();
|
||||
.filter(item -> item.getValue().equals(hierarchyMetric.getValue()))
|
||||
.findFirst();
|
||||
|
||||
if (preHierarchyOptional.isPresent()) {
|
||||
Hierarchy preHierarchy = preHierarchyOptional.get();
|
||||
List<Hierarchy> children = preHierarchy.getChildren();
|
||||
Set<String> childrenKey = children.stream()
|
||||
.map(Hierarchy::getValue)
|
||||
.collect(Collectors.toSet());
|
||||
.map(Hierarchy::getValue)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
for (Hierarchy child : hierarchyMetric.getChildren()) {
|
||||
if (!childrenKey.contains(child.getValue())) {
|
||||
@@ -408,18 +408,14 @@ public class AppServiceImpl implements AppService, InitializingBean {
|
||||
log.error(e.getMessage());
|
||||
throw new IllegalArgumentException("parse yml error: " + e.getMessage());
|
||||
}
|
||||
// app params verify
|
||||
verifyDefineAppContent(app, isModify);
|
||||
appDefineStore.save(app.getApp(), ymlContent);
|
||||
// get and reset hide value
|
||||
Job originalJob = appDefines.get(app.getApp().toLowerCase());
|
||||
if (Objects.nonNull(originalJob)) {
|
||||
boolean hide = originalJob.isHide();
|
||||
app.setHide(hide);
|
||||
}
|
||||
|
||||
appDefines.put(app.getApp().toLowerCase(), app);
|
||||
// resolve: after the template is modified, all monitoring instances of the same type of template need to be reissued in the task status
|
||||
SpringContextHolder.getBean(MonitorService.class).updateAppCollectJob(app);
|
||||
}
|
||||
|
||||
@@ -442,7 +438,7 @@ public class AppServiceImpl implements AppService, InitializingBean {
|
||||
}
|
||||
if (!isModify) {
|
||||
Assert.isNull(appDefines.get(app.getApp().toLowerCase()),
|
||||
"monitoring template name " + app.getApp() + " already exists.");
|
||||
"monitoring template name " + app.getApp() + " already exists.");
|
||||
}
|
||||
Set<String> fieldsSet = new HashSet<>(16);
|
||||
for (Metrics metrics : app.getMetrics()) {
|
||||
@@ -454,19 +450,19 @@ public class AppServiceImpl implements AppService, InitializingBean {
|
||||
HertzBeatKeywordsUtil.verifyKeywords(field.getField());
|
||||
if (fieldsSet.contains(field.getField())) {
|
||||
throw new IllegalArgumentException(app.getApp() + " " + metrics.getName() + " "
|
||||
+ field.getField() + " can not duplicated.");
|
||||
+ field.getField() + " can not duplicated.");
|
||||
}
|
||||
if (JexlCheckerUtil.verifyKeywords(field.getField())) {
|
||||
throw new IllegalArgumentException(app.getApp() + " " + metrics.getName() + " "
|
||||
+ field.getField() + " prohibited keywords.");
|
||||
+ field.getField() + " prohibited keywords.");
|
||||
}
|
||||
if (JexlCheckerUtil.verifyStartCharacter(field.getField())) {
|
||||
throw new IllegalArgumentException(app.getApp() + " " + metrics.getName() + " "
|
||||
+ field.getField() + " illegal start character.");
|
||||
+ field.getField() + " illegal start character.");
|
||||
}
|
||||
if (JexlCheckerUtil.verifySpaces(field.getField())) {
|
||||
throw new IllegalArgumentException(app.getApp() + " " + metrics.getName() + " "
|
||||
+ field.getField() + " no spaces allowed.");
|
||||
+ field.getField() + " no spaces allowed.");
|
||||
}
|
||||
fieldsSet.add(field.getField());
|
||||
}
|
||||
@@ -475,7 +471,6 @@ public class AppServiceImpl implements AppService, InitializingBean {
|
||||
|
||||
@Override
|
||||
public void deleteMonitorDefine(String app) {
|
||||
// if app has monitors now, delete failed
|
||||
var monitors = monitorDao.findMonitorsByAppEquals(app);
|
||||
if (monitors != null && !monitors.isEmpty()) {
|
||||
throw new IllegalArgumentException("Can not delete define which has monitoring instances.");
|
||||
@@ -508,6 +503,7 @@ public class AppServiceImpl implements AppService, InitializingBean {
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
// Guaranteed to be non-null due to constructor injection
|
||||
var objectStoreConfig = objectStoreConfigService.getConfig();
|
||||
refreshStore(objectStoreConfig);
|
||||
}
|
||||
@@ -517,11 +513,6 @@ public class AppServiceImpl implements AppService, InitializingBean {
|
||||
refreshStore(event.getConfig());
|
||||
}
|
||||
|
||||
/**
|
||||
* flush config store
|
||||
*
|
||||
* @param objectStoreConfig file service configuration
|
||||
*/
|
||||
private void refreshStore(ObjectStoreDTO<?> objectStoreConfig) {
|
||||
if (objectStoreConfig == null) {
|
||||
appDefineStore = new DatabaseAppDefineStoreImpl();
|
||||
@@ -535,7 +526,6 @@ public class AppServiceImpl implements AppService, InitializingBean {
|
||||
}
|
||||
}
|
||||
jarAppDefineStore.loadAppDefines();
|
||||
// merge define yml files inside jars
|
||||
appDefineStore.loadAppDefines();
|
||||
}
|
||||
|
||||
@@ -561,7 +551,6 @@ public class AppServiceImpl implements AppService, InitializingBean {
|
||||
}
|
||||
|
||||
private class JarAppDefineStoreImpl implements AppDefineStore {
|
||||
|
||||
@Override
|
||||
public boolean loadAppDefines() {
|
||||
try {
|
||||
@@ -575,7 +564,6 @@ public class AppServiceImpl implements AppService, InitializingBean {
|
||||
appDefines.put(app.getApp().toLowerCase(), app);
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
log.error("Ignore this template file: {}.", resource.getFilename());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -587,8 +575,6 @@ public class AppServiceImpl implements AppService, InitializingBean {
|
||||
|
||||
@Override
|
||||
public String loadAppDefine(String app) {
|
||||
// load define app yml in jar
|
||||
log.info("load define app yml in internal jar");
|
||||
var resolver = new PathMatchingResourcePatternResolver();
|
||||
var resource = resolver.getResource("classpath:define/app-" + app + ".yml");
|
||||
try (var inputStream = resource.getInputStream()) {
|
||||
@@ -606,51 +592,25 @@ public class AppServiceImpl implements AppService, InitializingBean {
|
||||
|
||||
@Override
|
||||
public void delete(String app) {
|
||||
throw new UnsupportedOperationException("define yml inside jars cannot be deleted");
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class LocalFileAppDefineStoreImpl implements AppDefineStore {
|
||||
|
||||
@Override
|
||||
public boolean loadAppDefines() {
|
||||
var rootUrl = this.getClass().getClassLoader().getResource("");
|
||||
if (rootUrl == null) {
|
||||
return false;
|
||||
}
|
||||
var classpath = rootUrl.getPath();
|
||||
var defineAppPath = classpath + "define";
|
||||
var directory = new File(defineAppPath);
|
||||
if (!directory.exists() || directory.listFiles() == null) {
|
||||
rootUrl = this.getClass().getResource(File.separator);
|
||||
if (rootUrl == null) {
|
||||
return false;
|
||||
}
|
||||
classpath = rootUrl.getPath();
|
||||
defineAppPath = classpath + "define";
|
||||
directory = new File(defineAppPath);
|
||||
if (!directory.exists() || directory.listFiles() == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
log.info("load define path {}", defineAppPath);
|
||||
if (rootUrl == null) return false;
|
||||
var directory = new File(rootUrl.getPath() + "define");
|
||||
if (!directory.exists()) return false;
|
||||
Yaml yaml = new Yaml();
|
||||
for (var appFile : Objects.requireNonNull(directory.listFiles())) {
|
||||
if (appFile.exists() && appFile.isFile()) {
|
||||
if (appFile.isHidden()
|
||||
|| (!appFile.getName().endsWith("yml") && !appFile.getName().endsWith("yaml"))) {
|
||||
log.error("Ignore this template file: {}.", appFile.getName());
|
||||
continue;
|
||||
}
|
||||
try (var fileInputStream = new FileInputStream(appFile)) {
|
||||
var app = yaml.loadAs(fileInputStream, Job.class);
|
||||
if (app != null) {
|
||||
appDefines.put(app.getApp().toLowerCase(), app);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
log.error("Ignore this template file: {}.", appFile.getName());
|
||||
if (appFile.isFile() && (appFile.getName().endsWith("yml") || appFile.getName().endsWith("yaml"))) {
|
||||
try (var is = new FileInputStream(appFile)) {
|
||||
var app = yaml.loadAs(is, Job.class);
|
||||
if (app != null) appDefines.put(app.getApp().toLowerCase(), app);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -659,132 +619,93 @@ public class AppServiceImpl implements AppService, InitializingBean {
|
||||
|
||||
@Override
|
||||
public String loadAppDefine(String app) {
|
||||
var classpath = Objects.requireNonNull(this.getClass().getClassLoader().getResource("")).getPath();
|
||||
var defineAppPath = classpath + "define" + File.separator + "app-" + app + ".yml";
|
||||
var defineAppFile = new File(defineAppPath);
|
||||
if (defineAppFile.exists() && defineAppFile.isFile()) {
|
||||
log.info("load {} define app yml in file: {}", app, defineAppPath);
|
||||
try {
|
||||
return FileUtils.readFileToString(defineAppFile, StandardCharsets.UTF_8);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
var rootUrl = this.getClass().getClassLoader().getResource("");
|
||||
if (rootUrl == null) return null;
|
||||
var file = new File(rootUrl.getPath() + "define" + File.separator + "app-" + app + ".yml");
|
||||
try {
|
||||
return file.exists() ? FileUtils.readFileToString(file, StandardCharsets.UTF_8) : null;
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(String app, String ymlContent) {
|
||||
var classpath = Objects.requireNonNull(this.getClass().getClassLoader().getResource("")).getPath();
|
||||
var defineAppPath = classpath + "define" + File.separator + "app-" + app + ".yml";
|
||||
var defineAppFile = new File(defineAppPath);
|
||||
var rootUrl = this.getClass().getClassLoader().getResource("");
|
||||
if (rootUrl == null) return;
|
||||
var file = new File(rootUrl.getPath() + "define" + File.separator + "app-" + app + ".yml");
|
||||
try {
|
||||
FileUtils.writeStringToFile(defineAppFile, ymlContent, StandardCharsets.UTF_8, false);
|
||||
FileUtils.writeStringToFile(file, ymlContent, StandardCharsets.UTF_8, false);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
throw new RuntimeException("flush file " + defineAppPath + " error: " + e.getMessage());
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String app) {
|
||||
var classpath = Objects.requireNonNull(this.getClass().getClassLoader().getResource("")).getPath();
|
||||
var defineAppPath = classpath + "define" + File.separator + "app-" + app + ".yml";
|
||||
var defineAppFile = new File(defineAppPath);
|
||||
|
||||
if (!defineAppFile.exists() && appDefines.containsKey(app.toLowerCase())){
|
||||
throw new CommonException("the app define file is not in current file server provider");
|
||||
}
|
||||
|
||||
if (defineAppFile.exists() && defineAppFile.isFile()) {
|
||||
defineAppFile.delete();
|
||||
}
|
||||
var rootUrl = this.getClass().getClassLoader().getResource("");
|
||||
if (rootUrl == null) return;
|
||||
var file = new File(rootUrl.getPath() + "define" + File.separator + "app-" + app + ".yml");
|
||||
if (file.exists()) file.delete();
|
||||
appDefines.remove(app.toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
private class ObjectStoreAppDefineStoreImpl implements AppDefineStore {
|
||||
|
||||
@Override
|
||||
public boolean loadAppDefines() {
|
||||
var objectStoreService = getObjectStoreService();
|
||||
Yaml yaml = new Yaml();
|
||||
objectStoreService.list("define")
|
||||
.forEach(it -> {
|
||||
if (it.getInputStream() != null) {
|
||||
var app = yaml.loadAs(it.getInputStream(), Job.class);
|
||||
if (app != null) {
|
||||
appDefines.put(app.getApp().toLowerCase(), app);
|
||||
}
|
||||
}
|
||||
});
|
||||
objectStoreService.list("define").forEach(it -> {
|
||||
if (it.getInputStream() != null) {
|
||||
var app = yaml.loadAs(it.getInputStream(), Job.class);
|
||||
if (app != null) appDefines.put(app.getApp().toLowerCase(), app);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String loadAppDefine(String app) {
|
||||
var objectStoreService = getObjectStoreService();
|
||||
var file = objectStoreService.download(getDefineAppPath(app));
|
||||
if (isNull(file)) {
|
||||
return null;
|
||||
}
|
||||
var file = objectStoreService.download("define/app-" + app + ".yml");
|
||||
try {
|
||||
return IOUtils.toString(file.getInputStream(), StandardCharsets.UTF_8);
|
||||
return file != null ? IOUtils.toString(file.getInputStream(), StandardCharsets.UTF_8) : null;
|
||||
} catch (IOException e) {
|
||||
log.error("load app define from object store service error", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(String app, String ymlContent) {
|
||||
var objectStoreService = getObjectStoreService();
|
||||
objectStoreService.upload(getDefineAppPath(app), IOUtils.toInputStream(ymlContent, StandardCharsets.UTF_8));
|
||||
getObjectStoreService().upload("define/app-" + app + ".yml", IOUtils.toInputStream(ymlContent, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String app) {
|
||||
var objectStoreService = getObjectStoreService();
|
||||
String defineAppPath = getDefineAppPath(app);
|
||||
boolean exist = objectStoreService.isExist(defineAppPath);
|
||||
if (!exist && appDefines.containsKey(app.toLowerCase())){
|
||||
throw new CommonException("the app define file is not in current file server provider");
|
||||
}
|
||||
if (exist){
|
||||
objectStoreService.remove(defineAppPath);
|
||||
}
|
||||
getObjectStoreService().remove("define/app-" + app + ".yml");
|
||||
appDefines.remove(app.toLowerCase());
|
||||
}
|
||||
|
||||
private ObjectStoreService getObjectStoreService() {
|
||||
return SpringContextHolder.getBean(ObsObjectStoreServiceImpl.class);
|
||||
}
|
||||
|
||||
private String getDefineAppPath(String app) {
|
||||
return "define/app-" + app + ".yml";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class DatabaseAppDefineStoreImpl implements AppDefineStore {
|
||||
|
||||
@Override
|
||||
public boolean loadAppDefines() {
|
||||
Yaml yaml = new Yaml();
|
||||
List<Define> defines = defineDao.findAll();
|
||||
for (Define define : defines) {
|
||||
defineDao.findAll().forEach(define -> {
|
||||
var app = yaml.loadAs(define.getContent(), Job.class);
|
||||
if (app != null){
|
||||
appDefines.put(define.getApp().toLowerCase(), app);
|
||||
}
|
||||
}
|
||||
if (app != null) appDefines.put(define.getApp().toLowerCase(), app);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String loadAppDefine(String app) {
|
||||
Optional<Define> defineOptional = defineDao.findById(app);
|
||||
return defineOptional.map(Define::getContent).orElse(null);
|
||||
return defineDao.findById(app).map(Define::getContent).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -797,13 +718,7 @@ public class AppServiceImpl implements AppService, InitializingBean {
|
||||
|
||||
@Override
|
||||
public void delete(String app) {
|
||||
Optional<Define> defineOptional = defineDao.findById(app);
|
||||
if (defineOptional.isEmpty() && appDefines.containsKey(app.toLowerCase())){
|
||||
throw new CommonException("the app define file is not in current file server provider");
|
||||
}
|
||||
if (defineOptional.isPresent()){
|
||||
defineDao.deleteById(app);
|
||||
}
|
||||
defineDao.deleteById(app);
|
||||
appDefines.remove(app.toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -19,7 +19,6 @@ package org.apache.hertzbeat.manager.service.impl;
|
||||
|
||||
import static org.apache.hertzbeat.common.constants.ExportFileConstants.ExcelFile.FILE_SUFFIX;
|
||||
import static org.apache.hertzbeat.common.constants.ExportFileConstants.ExcelFile.TYPE;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
@@ -45,6 +44,7 @@ import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.apache.poi.ss.util.RegionUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
|
||||
/**
|
||||
* Configure the import and export EXCEL format
|
||||
|
||||
+13
-20
@@ -5,7 +5,9 @@
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -17,44 +19,35 @@ package org.apache.hertzbeat.manager.service.impl;
|
||||
|
||||
import static org.apache.hertzbeat.common.constants.ExportFileConstants.JsonFile.FILE_SUFFIX;
|
||||
import static org.apache.hertzbeat.common.constants.ExportFileConstants.JsonFile.TYPE;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.hertzbeat.common.util.JsonUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* Configure the import and export JSON format
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class JsonImExportServiceImpl extends AbstractImExportServiceImpl {
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
@Override
|
||||
public List<ExportMonitorDTO> parseImport(InputStream is) {
|
||||
try {
|
||||
return objectMapper.readValue(is, new TypeReference<>(){});
|
||||
} catch (IOException ex) {
|
||||
log.error("import monitor failed.", ex);
|
||||
throw new RuntimeException("import monitor failed");
|
||||
List<ExportMonitorDTO> result = JsonUtil.fromJson(is, new TypeReference<List<ExportMonitorDTO>>(){});
|
||||
if (result == null) {
|
||||
throw new RuntimeException("Parse JSON failed");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeOs(List<ExportMonitorDTO> monitorList, OutputStream os) {
|
||||
try {
|
||||
objectMapper.writeValue(os, monitorList);
|
||||
} catch (IOException ex) {
|
||||
log.error("export monitor failed.", ex);
|
||||
throw new RuntimeException("export monitor failed");
|
||||
}
|
||||
JsonUtil.toJson(monitorList, os);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-12
@@ -17,8 +17,7 @@
|
||||
|
||||
package org.apache.hertzbeat.manager.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
import java.lang.reflect.Type;
|
||||
import org.apache.hertzbeat.common.constants.GeneralConfigTypeEnum;
|
||||
import org.apache.hertzbeat.base.dao.GeneralConfigDao;
|
||||
@@ -33,16 +32,8 @@ import org.springframework.stereotype.Service;
|
||||
@Service
|
||||
public class MailGeneralConfigServiceImpl extends AbstractGeneralConfigServiceImpl<MailServerConfig> {
|
||||
|
||||
/**
|
||||
* MailGeneralConfigServiceImpl's constructor creates an instance of this class
|
||||
* through the default constructor or deserialization construction (setBeanProps).
|
||||
* The parameter generalConfigDao is used for dao layer operation data,
|
||||
* and objectMapper is used for object mapping.
|
||||
* @param generalConfigDao dao layer operation data, needed to create an instance of this class
|
||||
* @param objectMapper object mapping , needed to create an instance of this class
|
||||
*/
|
||||
public MailGeneralConfigServiceImpl(GeneralConfigDao generalConfigDao, ObjectMapper objectMapper) {
|
||||
super(generalConfigDao, objectMapper);
|
||||
public MailGeneralConfigServiceImpl(GeneralConfigDao generalConfigDao) {
|
||||
super(generalConfigDao);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-11
@@ -17,8 +17,7 @@
|
||||
|
||||
package org.apache.hertzbeat.manager.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
import java.lang.reflect.Type;
|
||||
import org.apache.hertzbeat.common.entity.dto.ModelProviderConfig;
|
||||
import org.apache.hertzbeat.base.dao.GeneralConfigDao;
|
||||
@@ -35,15 +34,8 @@ public class ModelProviderConfigServiceImpl extends AbstractGeneralConfigService
|
||||
|
||||
private final ApplicationContext applicationContext;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>Constructor, passing in GeneralConfigDao, ObjectMapper and type.</p>
|
||||
*
|
||||
* @param generalConfigDao ConfigDao object
|
||||
* @param objectMapper JSON tool object
|
||||
*/
|
||||
public ModelProviderConfigServiceImpl(ApplicationContext applicationContext, GeneralConfigDao generalConfigDao, ObjectMapper objectMapper) {
|
||||
super(generalConfigDao, objectMapper);
|
||||
public ModelProviderConfigServiceImpl(ApplicationContext applicationContext, GeneralConfigDao generalConfigDao) {
|
||||
super(generalConfigDao);
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
|
||||
+3
-10
@@ -18,8 +18,7 @@
|
||||
|
||||
package org.apache.hertzbeat.manager.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
import java.lang.reflect.Type;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.base.dao.GeneralConfigDao;
|
||||
@@ -37,14 +36,8 @@ import org.springframework.stereotype.Service;
|
||||
@Slf4j
|
||||
public class MuteGeneralConfigServiceImpl extends AbstractGeneralConfigServiceImpl<MuteConfig> {
|
||||
|
||||
/**
|
||||
* <p>Constructor, passing in GeneralConfigDao, ObjectMapper and type.</p>
|
||||
*
|
||||
* @param generalConfigDao Dao object
|
||||
* @param objectMapper JSON tool object
|
||||
*/
|
||||
protected MuteGeneralConfigServiceImpl(GeneralConfigDao generalConfigDao, ObjectMapper objectMapper) {
|
||||
super(generalConfigDao, objectMapper);
|
||||
protected MuteGeneralConfigServiceImpl(GeneralConfigDao generalConfigDao) {
|
||||
super(generalConfigDao);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+7
-13
@@ -17,12 +17,12 @@
|
||||
|
||||
package org.apache.hertzbeat.manager.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
import com.obs.services.ObsClient;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.common.constants.GeneralConfigTypeEnum;
|
||||
import org.apache.hertzbeat.base.dao.GeneralConfigDao;
|
||||
import org.apache.hertzbeat.common.util.JsonUtil;
|
||||
import org.apache.hertzbeat.manager.pojo.dto.ObjectStoreConfigChangeEvent;
|
||||
import org.apache.hertzbeat.manager.pojo.dto.ObjectStoreDTO;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
@@ -33,7 +33,7 @@ import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.lang.reflect.Type;
|
||||
import java.net.URL;
|
||||
|
||||
@@ -52,14 +52,8 @@ public class ObjectStoreConfigServiceImpl extends
|
||||
@Resource
|
||||
private ApplicationContext ctx;
|
||||
|
||||
/**
|
||||
* <p>Constructor, passing in GeneralConfigDao, ObjectMapper and type.</p>
|
||||
*
|
||||
* @param generalConfigDao configDao object
|
||||
* @param objectMapper JSON tool object
|
||||
*/
|
||||
public ObjectStoreConfigServiceImpl(GeneralConfigDao generalConfigDao, ObjectMapper objectMapper) {
|
||||
super(generalConfigDao, objectMapper);
|
||||
public ObjectStoreConfigServiceImpl(GeneralConfigDao generalConfigDao) {
|
||||
super(generalConfigDao);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -94,7 +88,7 @@ public class ObjectStoreConfigServiceImpl extends
|
||||
* init Huawei Cloud OBS
|
||||
*/
|
||||
private void initObs(ObjectStoreDTO<ObjectStoreDTO.ObsConfig> config) {
|
||||
var obsConfig = objectMapper.convertValue(config.getConfig(), ObjectStoreDTO.ObsConfig.class);
|
||||
var obsConfig = JsonUtil.convertValue(config.getConfig(), ObjectStoreDTO.ObsConfig.class);
|
||||
Assert.hasText(obsConfig.getAccessKey(), "cannot find obs accessKey");
|
||||
Assert.hasText(obsConfig.getSecretKey(), "cannot find obs secretKey");
|
||||
Assert.hasText(obsConfig.getEndpoint(), "cannot find obs endpoint");
|
||||
@@ -114,7 +108,7 @@ public class ObjectStoreConfigServiceImpl extends
|
||||
/**
|
||||
* Verify Huawei Cloud OBS endpoint domain name
|
||||
* Only myhuaweicloud.com domain name is allowed
|
||||
* Refer: https://console-intl.huaweicloud.com/apiexplorer/#/endpoint
|
||||
* Refer: <a href="https://console-intl.huaweicloud.com/apiexplorer/#/endpoint">...</a>
|
||||
*/
|
||||
public void validateObsEndpoint(String endpoint) {
|
||||
try {
|
||||
|
||||
+1
-1
@@ -17,6 +17,7 @@
|
||||
|
||||
package org.apache.hertzbeat.manager.service.impl;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
@@ -45,7 +46,6 @@ import java.util.function.Consumer;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.annotation.PostConstruct;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
+3
-12
@@ -17,8 +17,7 @@
|
||||
|
||||
package org.apache.hertzbeat.manager.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
@@ -40,16 +39,8 @@ public class SmsGeneralConfigServiceImpl extends AbstractGeneralConfigServiceImp
|
||||
@Resource
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
/**
|
||||
* SmsGeneralConfigServiceImpl's constructor creates an instance of this class
|
||||
* through the default constructor or deserialization construction (setBeanProps).
|
||||
* The parameter generalConfigDao is used for dao layer operation data,
|
||||
* and objectMapper is used for object mapping.
|
||||
* @param generalConfigDao dao layer operation data, needed to create an instance of this class
|
||||
* @param objectMapper object mapping , needed to create an instance of this class
|
||||
*/
|
||||
public SmsGeneralConfigServiceImpl(GeneralConfigDao generalConfigDao, ObjectMapper objectMapper) {
|
||||
super(generalConfigDao, objectMapper);
|
||||
public SmsGeneralConfigServiceImpl(GeneralConfigDao generalConfigDao) {
|
||||
super(generalConfigDao);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
-11
@@ -17,8 +17,7 @@
|
||||
|
||||
package org.apache.hertzbeat.manager.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Objects;
|
||||
@@ -38,15 +37,8 @@ public class SystemGeneralConfigServiceImpl extends AbstractGeneralConfigService
|
||||
@Resource
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>Constructor, passing in GeneralConfigDao, ObjectMapper and type.</p>
|
||||
*
|
||||
* @param generalConfigDao ConfigDao object
|
||||
* @param objectMapper JSON tool object
|
||||
*/
|
||||
public SystemGeneralConfigServiceImpl(GeneralConfigDao generalConfigDao, ObjectMapper objectMapper) {
|
||||
super(generalConfigDao, objectMapper);
|
||||
public SystemGeneralConfigServiceImpl(GeneralConfigDao generalConfigDao) {
|
||||
super(generalConfigDao);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-11
@@ -17,13 +17,12 @@
|
||||
|
||||
package org.apache.hertzbeat.manager.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.lang.reflect.Type;
|
||||
import org.apache.hertzbeat.common.constants.GeneralConfigTypeEnum;
|
||||
import org.apache.hertzbeat.base.dao.GeneralConfigDao;
|
||||
import org.apache.hertzbeat.manager.pojo.dto.SystemSecret;
|
||||
import org.springframework.stereotype.Service;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
|
||||
/**
|
||||
* system config service impl
|
||||
@@ -31,15 +30,8 @@ import org.springframework.stereotype.Service;
|
||||
@Service
|
||||
public class SystemSecretServiceImpl extends AbstractGeneralConfigServiceImpl<SystemSecret> {
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>Constructor, passing in GeneralConfigDao, ObjectMapper and type.</p>
|
||||
*
|
||||
* @param generalConfigDao ConfigDao object
|
||||
* @param objectMapper JSON tool object
|
||||
*/
|
||||
public SystemSecretServiceImpl(GeneralConfigDao generalConfigDao, ObjectMapper objectMapper) {
|
||||
super(generalConfigDao, objectMapper);
|
||||
public SystemSecretServiceImpl(GeneralConfigDao generalConfigDao) {
|
||||
super(generalConfigDao);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-11
@@ -17,8 +17,7 @@
|
||||
|
||||
package org.apache.hertzbeat.manager.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import tools.jackson.core.type.TypeReference;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.lang.reflect.Type;
|
||||
import org.apache.hertzbeat.common.constants.GeneralConfigTypeEnum;
|
||||
@@ -36,15 +35,8 @@ public class TemplateConfigServiceImpl extends AbstractGeneralConfigServiceImpl<
|
||||
@Resource
|
||||
private AppService appService;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>Constructor, passing in GeneralConfigDao, ObjectMapper and type.</p>
|
||||
*
|
||||
* @param generalConfigDao configDao object
|
||||
* @param objectMapper JSON tool object
|
||||
*/
|
||||
public TemplateConfigServiceImpl(GeneralConfigDao generalConfigDao, ObjectMapper objectMapper) {
|
||||
super(generalConfigDao, objectMapper);
|
||||
public TemplateConfigServiceImpl(GeneralConfigDao generalConfigDao) {
|
||||
super(generalConfigDao);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ import static org.apache.hertzbeat.common.constants.CommonConstants.FAIL_CODE;
|
||||
import static org.apache.hertzbeat.common.constants.CommonConstants.MONITOR_CONFLICT_CODE;
|
||||
import static org.apache.hertzbeat.common.constants.CommonConstants.PARAM_INVALID_CODE;
|
||||
import java.util.Objects;
|
||||
import javax.validation.ConstraintViolationException;
|
||||
import jakarta.validation.ConstraintViolationException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.hertzbeat.common.entity.dto.Message;
|
||||
import org.apache.hertzbeat.common.support.exception.CommonException;
|
||||
|
||||
-75
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.hertzbeat.manager.component.listener;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.TimeZone;
|
||||
import org.apache.hertzbeat.common.support.event.SystemConfigChangeEvent;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
/**
|
||||
* test case for {@link TimeZoneListener}
|
||||
*/
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class TimeZoneListenerTest {
|
||||
|
||||
@Mock
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@InjectMocks
|
||||
private TimeZoneListener timeZoneListener;
|
||||
|
||||
@Mock
|
||||
private SystemConfigChangeEvent event;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
|
||||
ReflectionTestUtils.setField(timeZoneListener, "objectMapper", objectMapper);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testOnEvent() {
|
||||
|
||||
when(objectMapper.setTimeZone(any(TimeZone.class))).thenReturn(objectMapper);
|
||||
when(objectMapper.setDateFormat(any(SimpleDateFormat.class))).thenReturn(objectMapper);
|
||||
|
||||
Object eventSource = new Object();
|
||||
when(event.getSource()).thenReturn(eventSource);
|
||||
|
||||
timeZoneListener.onEvent(event);
|
||||
|
||||
SimpleDateFormat expectedDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
|
||||
expectedDateFormat.setTimeZone(TimeZone.getDefault());
|
||||
|
||||
verify(objectMapper).setTimeZone(TimeZone.getDefault());
|
||||
verify(objectMapper).setDateFormat(expectedDateFormat);
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -91,7 +91,7 @@ class GeneralConfigControllerTest {
|
||||
|
||||
mockMvc.perform(put("/api/config/template/appName")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("{\"templateKey\":\"templateValue\"}"))
|
||||
.content("{\"templateKey\":\"templateValue\",\"hide\":true}"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE));
|
||||
}
|
||||
|
||||
+2
-2
@@ -125,7 +125,7 @@ class StatusPageControllerTest {
|
||||
|
||||
mockMvc.perform(post("/api/status/page/component")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("{\"name\":\"New Component\"}")
|
||||
.content("{\"name\":\"New Component\",\"method\":0,\"configState\":0,\"state\":0}")
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE))
|
||||
@@ -137,7 +137,7 @@ class StatusPageControllerTest {
|
||||
|
||||
mockMvc.perform(put("/api/status/page/component")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("{\"name\":\"Updated Component\"}")
|
||||
.content("{\"name\":\"Updated Component\",\"method\":0,\"configState\":0,\"state\":0}")
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value((int) CommonConstants.SUCCESS_CODE))
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user