Skip to content

Feature2.6.1 #294

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Aug 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,22 @@ jobs:
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main


# --- Start of Custom Build Steps ---
# Set up JDK version to Java 21
- name: Set up JDK 21
uses: actions/setup-java@v3
with:
java-version: '21'
distribution: 'temurin' # Recommended to use Temurin, can also be 'adopt', 'zulu', etc.

# Build the project with Maven
- name: Build with Maven
run: |
mvn clean package -DskipTests # mvn clean package -f pom.xml -B -V -e -Dfindbugs.skip -Dcheckstyle.skip -Dpmd.skip=true -Dspotbugs.skip -Denforcer.skip -Dmaven.javadoc.skip -DskipTests -Dmaven.test.skip.exec -Dlicense.skip=true -Drat.skip=true -Dspotless.check.skip=true
# --- End of Custom Build Steps ---


# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
Expand Down
32 changes: 26 additions & 6 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
-domain dev -use RoleBased WebBased
mvn clean deploy -Dmaven.test.skip=true -P release
-- release 2.6.1

- enhanced logging: log detailed information and stack trace health check failure
- enhanced logging: Netty channel handler exception will be logged only when:
1. run with -debug
2. or caller address is in enabled whitelist or not in enabled blacklist

- Config change: Regex.Prefix is no longer used in CallerAddressFilter, the whitelist and blacklist no longer need a prefix to mark a value as regex.
1. cfg_nio.properties
- removed: CallerAddressFilter.Regex.Prefix
- default value changed: CallerAddressFilter.option=String (was "HostName")
2. cfg_grpc.properties
- removed: gRpc.server.CallerAddressFilter.Regex.Prefix
- default value changed: gRpc.server.CallerAddressFilter.option=String (was "HostName")

Maven Central Repository:
https://repo.maven.apache.org/maven2/org/summerboot/jexpress/2.6.1/
https://central.sonatype.com/artifact/org.summerboot/jexpress/2.6.1

mvnrepository.com:
https://mvnrepository.com/artifact/org.summerboot/jexpress/2.6.1


-- release 2.6.0
- enhanced security 1: this change use enhanced encryption/decryption to protect sensitive data, like password in config files.
Expand All @@ -17,8 +37,8 @@ mvn clean deploy -Dmaven.test.skip=true -P release
- refactoring CLI exit code

- API new: added @UniqueIgnore to mute @Unique check alert for expected duplicated values
- API new: added @Inspector.name and @Deamon.requiredHealthChecks (array of @Inspector.names, empty/null means ignore all HealthChecks)
this is to set Controller and/or its methods on deamon mode (accessable when pause/health failed but not for specified @Inspector.name
- API new: added @Inspector.name and @Daemon.requiredHealthChecks (array of @Inspector.names, empty/null means ignore all HealthChecks)
this is to set Controller and/or its methods on daemon mode (accessable when pause/health failed but not for specified @Inspector.name

- API renamed: @Controller.implTag renamed to @Controller.AlternativeName
- API renamed: @Service.implTag renamed to with @Service.AlternativeName
Expand Down Expand Up @@ -119,7 +139,7 @@ mvn clean deploy -Dmaven.test.skip=true -P release
- enhancement: Err with args
- enhancement: add nio.JAX-RS.toJson.showRefInServiceError in cfg_nio.properties, default false to not show ref field in JSON/XML response
- enhancement: verify Bearer Token if provided in request header for regardless of a @Controller method is role-based or not
- enhancement: added GrpcTestBase for gRPC test (uased example in https://github.com/SummerBootFramework/jExpressDemo-HelloSummer/blob/main/HelloSummer-demo02/src/test/java/test/integration/grpc/GrpcTest.java)
- enhancement: added GrpcTestBase for gRPC test (usage and example see https://github.com/SummerBootFramework/jExpressDemo-HelloSummer/blob/main/HelloSummer-demo02/src/test/java/test/integration/grpc/GrpcTest.java)
2-way TLS (server and client verify each other certificate)
client verify server certificate, server trust all client certificate
server verify server certificate, client trust all client certificate
Expand Down Expand Up @@ -197,7 +217,7 @@ https://mvnrepository.com/artifact/org.summerboot/jexpress/2.6.0

-- release 2.4.5 --
- Refactoring: SummerInitializer init before and after Ioc is initialized
- Enhancement: Reject with 503 asap when paused or health check failed, unless @Controller or its method has @Deamon
- Enhancement: Reject with 503 asap when paused or health check failed, unless @Controller or its method has @Daemon

-- release 2.4.4 --
- Enhancement: command line arguments end with /r bu mistake in service script no longer impact application
Expand Down
14 changes: 7 additions & 7 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.summerboot</groupId>
<artifactId>jexpress</artifactId>
<version>2.6.0</version>
<version>2.6.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Summer Boot jExpress ${project.version}</name>
<description>Summer Boot jExpress focuses on solving non-functional and operational maintainability requirements,
Expand Down Expand Up @@ -154,7 +154,7 @@
<maven-install.version>3.1.4</maven-install.version>
<!-- Commons -->
<commons-lang3.version>3.18.0</commons-lang3.version>
<commons-cli.version>1.9.0</commons-cli.version>
<commons-cli.version>1.10.0</commons-cli.version>
<commons-io.version>2.20.0</commons-io.version>
<commons-text.version>1.14.0</commons-text.version>
<!-- <owasp.encoder.version>1.2.3</owasp.encoder.version>-->
Expand Down Expand Up @@ -182,7 +182,7 @@


<!-- MIME-Type -->
<tika.version>3.2.1</tika.version>
<tika.version>3.2.2</tika.version>
<!-- JAX-RS -->
<rs-api.version>4.0.0</rs-api.version>
<jakarta.annotation.version>3.0.0</jakarta.annotation.version>
Expand All @@ -192,18 +192,18 @@
<jackson.version>2.19.2</jackson.version>
<!-- Bean Validation -->
<jakarta.el.version>6.0.1</jakarta.el.version>
<tomcat-embed-el.version>11.0.9</tomcat-embed-el.version>
<tomcat-embed-el.version>11.0.10</tomcat-embed-el.version>
<hibernate-validator.version>9.0.1.Final</hibernate-validator.version>

<!-- IOC Injection -->
<guice.version>7.0.0</guice.version>

<!-- JPA -->
<hibernate.version>7.0.9.Final</hibernate.version>
<hikari-cp.version>7.0.0</hikari-cp.version>
<hibernate.version>7.1.0.Final</hibernate.version>
<hikari-cp.version>7.0.1</hikari-cp.version>

<!-- Cache -->
<jedis.version>6.0.0</jedis.version>
<jedis.version>6.1.0</jedis.version>

<quartz.version>2.5.0</quartz.version>
<mqtt.version>1.2.5</mqtt.version>
Expand Down
6 changes: 6 additions & 0 deletions sample-service.service
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
# sudo nano /etc/systemd/system/myapp-service.service
# sudo systemctl daemon-reload
# sudo systemctl start myapp-service
# sudo systemctl enable myapp-service
# sudo systemctl status myapp-service
# sudo journalctl -u myapp-service -f

[Unit]
Description=myapp-name: (Java 21 + Netty 4.2.x + ZGC + OpenSSL on Linux)
#After=network.target
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ static boolean isDebugMode() {
String APP_ID = String.format("%06d", APP_ID_VALUE);

//version
String VERSION = "jExpress 2.6.0";
String VERSION = "jExpress 2.6.1";
String JEXPRESS_PACKAGE_NAME = "org.summerboot.jexpress";

String JSONFILTER_NAME_SERVICEERROR = "ServiceErrorFilter";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
@Retention(RetentionPolicy.RUNTIME)
@Documented
@BindingAnnotation
public @interface Deamon {
public @interface Daemon {

boolean ignorePause() default true;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,8 @@ public static void inspect(HealthInspector... healthInspectors) {
setHealthStatus(healthCheckAllPassed, inspectionReport);
} else {
try {
inspectionReport = BeanUtil.toJson(healthCheckFailedReport, true, true);
//inspectionReport = BeanUtil.toJson(healthCheckFailedReport, true, true);
inspectionReport = healthCheckFailedReport.toStringWithStackTrace();
} catch (Throwable ex) {
inspectionReport = " toJson failed " + ex;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,13 @@ public void setAppVersion(String appVersion) {
protected Logger log = LogManager.getLogger(getClass());

/**
* Update alert title
* Update alert subject
*
* @param title
* @param subject
* @return
*/
protected String updateAlertTitle(String title) {
return "Alert@" + SummerApplication.HOST + " " + appVersion + "[" + BootConstant.APP_ID + "] - " + title + " [" + OffsetDateTime.now() + "]";
protected String updateAlertEmailSubject(String subject) {
return "Alert@" + SummerApplication.HOST + " " + appVersion + "[" + BootConstant.APP_ID + "] - " + subject + " [" + OffsetDateTime.now() + "]";
}

/**
Expand All @@ -74,29 +74,29 @@ protected String updateAlertContent(String content, Throwable cause) {
}

@Override
public void sendAlertAsync(Collection<String> to, final String title, final String content, final Throwable cause, boolean debouncing) {
sendAlert(to, title, content, cause, debouncing, true);
public void sendAlertAsync(Collection<String> to, final String subject, final String content, final Throwable cause, boolean debouncing) {
sendAlert(to, subject, content, cause, debouncing, true);
}

@Override
public void sendAlertSync(Collection<String> to, final String title, final String content, final Throwable cause, boolean debouncing) {
sendAlert(to, title, content, cause, debouncing, false);
public void sendAlertSync(Collection<String> to, final String subject, final String content, final Throwable cause, boolean debouncing) {
sendAlert(to, subject, content, cause, debouncing, false);
}

/**
* The implementation of both sendAlertAsync and sendAlertSync
*
* @param to
* @param title
* @param subject
* @param content
* @param cause
* @param debouncing
* @param async
*/
@Override
public void sendAlert(Collection<String> to, final String title, final String content, final Throwable cause, boolean debouncing, boolean async) {
public void sendAlert(Collection<String> to, final String subject, final String content, final Throwable cause, boolean debouncing, boolean async) {
if (debouncing) {
String key = title;
String key = subject;
Throwable rootCause = ExceptionUtils.getRootCause(cause);
if (rootCause == null) {
rootCause = cause;
Expand All @@ -108,22 +108,22 @@ public void sendAlert(Collection<String> to, final String title, final String co
return;
}
}
sendEmail(to, updateAlertTitle(title), updateAlertContent(content, cause), false, async);
sendEmail(to, updateAlertEmailSubject(subject), updateAlertContent(content, cause), false, async);
}

@Override
public boolean sendEmailAsync(Collection<String> to, String title, String content, boolean isHTMLFormat) {
return this.sendEmail(to, title, content, isHTMLFormat, true);
public boolean sendEmailAsync(Collection<String> to, String subject, String content, boolean isHTMLFormat) {
return this.sendEmail(to, subject, content, isHTMLFormat, true);
}

@Override
public boolean sendEmailSync(Collection<String> to, String title, String content, boolean isHTMLFormat) {
return this.sendEmail(to, title, content, isHTMLFormat, false);
public boolean sendEmailSync(Collection<String> to, String subject, String content, boolean isHTMLFormat) {
return this.sendEmail(to, subject, content, isHTMLFormat, false);
}

@Override
public boolean sendEmail(Collection<String> to, String title, String content, boolean isHTMLFormat, boolean async) {
Email email = Email.compose(title, content, isHTMLFormat ? Email.Format.html : Email.Format.text).to(to);
public boolean sendEmail(Collection<String> to, String subject, String content, boolean isHTMLFormat, boolean async) {
Email email = Email.compose(subject, content, isHTMLFormat ? Email.Format.html : Email.Format.text).to(to);
if (to == null || to.isEmpty()) {
log.warn(() -> "unknown recipient: " + email);
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,69 +28,69 @@ public interface PostOffice extends HealthInspector<String> {
* send email
*
* @param to
* @param title
* @param subject
* @param content
* @param isHTMLFormat
* @param async
* @return
*/
boolean sendEmail(Collection<String> to, String title, String content, boolean isHTMLFormat, boolean async);
boolean sendEmail(Collection<String> to, String subject, String content, boolean isHTMLFormat, boolean async);

/**
* send alert email
*
* @param to
* @param title
* @param subject
* @param content
* @param cause
* @param debouncing
* @param async
*/
void sendAlert(Collection<String> to, final String title, final String content, final Throwable cause, boolean debouncing, boolean async);
void sendAlert(Collection<String> to, final String subject, final String content, final Throwable cause, boolean debouncing, boolean async);

/**
* send alert email in async mode
*
* @param to
* @param title
* @param subject
* @param content
* @param cause
* @param debouncing
*/
void sendAlertAsync(Collection<String> to, String title, String content, final Throwable cause, boolean debouncing);
void sendAlertAsync(Collection<String> to, String subject, String content, final Throwable cause, boolean debouncing);

/**
* send alert email in sync mode
*
* @param to
* @param title
* @param subject
* @param content
* @param cause
* @param debouncing
*/
void sendAlertSync(Collection<String> to, String title, String content, final Throwable cause, boolean debouncing);
void sendAlertSync(Collection<String> to, String subject, String content, final Throwable cause, boolean debouncing);

/**
* send email in sync mode
*
* @param to
* @param title
* @param subject
* @param content
* @param isHTMLFormat
* @return true is success
*/
boolean sendEmailSync(Collection<String> to, String title, String content, boolean isHTMLFormat);
boolean sendEmailSync(Collection<String> to, String subject, String content, boolean isHTMLFormat);

/**
* send email in async mode
*
* @param to
* @param title
* @param subject
* @param content
* @param isHTMLFormat
* @return
*/
boolean sendEmailAsync(Collection<String> to, String title, String content, boolean isHTMLFormat);
boolean sendEmailAsync(Collection<String> to, String subject, String content, boolean isHTMLFormat);

void setAppVersion(String appVersion);
}
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public void shutdown() {

public static final String KEY_DEBOUCING_INTERVAL = "debouncing.emailalert_minute";
@Config(key = KEY_DEBOUCING_INTERVAL, defaultValue = "30",
desc = "Alert message with the same title will not be sent out within this minutes")
desc = "Alert message with the same subject will not be sent out within this minutes")
protected volatile int emailAlertDebouncingIntervalMinutes = 30;

//3. mail session for Json display only
Expand Down
Loading