Skip to content

Commit af6cab1

Browse files
Feature2.4.11 (#283)
* BootHttpFileUploadHandler<T>.T onFileUploaded() accepts return object T * enhanced email alert and logging * enhanced email alert and logging * updated dependencies * fixed log file name issue * refactoring * migrate to jjwt 0.12 * repleace Glassfish EL impl with Tomcat Embed EL; refactoring * version 2.5.0 * refactoring * refactor gRPC status logging * refactoring grpc client * wip * wip * refactoring * enhanced GRPC client config * enhanced GRPC client config * enhanced GRPC client config * release
1 parent d68cd3e commit af6cab1

23 files changed

+851
-491
lines changed

pom.xml

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<modelVersion>4.0.0</modelVersion>
55
<groupId>org.summerboot</groupId>
66
<artifactId>jexpress</artifactId>
7-
<version>2.4.10</version>
7+
<version>2.4.11</version>
88
<packaging>jar</packaging>
99
<name>Summer Boot jExpress</name>
1010
<description>Summer Boot jExpress focuses on solving non-functional and operational maintainability requirements,
@@ -190,8 +190,8 @@
190190
<maven.resources.version>3.3.1</maven.resources.version>
191191
<maven-surefire.version>3.2.5</maven-surefire.version>
192192
<!-- Commons -->
193-
<commons-lang3.version>3.15.0</commons-lang3.version>
194-
<commons-cli.version>1.8.0</commons-cli.version>
193+
<commons-lang3.version>3.17.0</commons-lang3.version>
194+
<commons-cli.version>1.9.0</commons-cli.version>
195195
<commons-io.version>2.16.1</commons-io.version>
196196
<!-- <commons-text.version>1.11.0</commons-text.version>-->
197197
<!-- <owasp.encoder.version>1.2.3</owasp.encoder.version>-->
@@ -203,15 +203,15 @@
203203
<!-- Security -->
204204
<bouncycastle.version>1.78.1</bouncycastle.version>
205205
<!-- JWT -->
206-
<jwt.version>0.11.5</jwt.version>
206+
<jwt.version>0.12.6</jwt.version>
207207

208208
<!-- NIO Netty -->
209209
<netty.version>4.1.112.Final</netty.version>
210-
<netty-tcnative.version>2.0.65.Final</netty-tcnative.version>
210+
<netty-tcnative.version>2.0.66.Final</netty-tcnative.version>
211211
<!-- gRPC and protobuf -->
212-
<grpc.version>1.65.1</grpc.version>
213-
<guava.version>33.2.1-jre</guava.version>
214-
<protobuf.version>4.27.3</protobuf.version>
212+
<grpc.version>1.66.0</grpc.version>
213+
<guava.version>33.3.0-jre</guava.version>
214+
<protobuf.version>4.28.0</protobuf.version>
215215
<!-- Web JAX-RS -->
216216
<swagger.core.version>2.2.22</swagger.core.version>
217217
<!--<elastic-apm.version>1.36.0</elastic-apm.version>-->
@@ -227,18 +227,19 @@
227227
<!-- JSON/XML/Bean Validation -->
228228
<jackson.version>2.17.2</jackson.version>
229229
<!-- Bean Validation -->
230-
<hibernate-validator.version>8.0.1.Final</hibernate-validator.version>
231230
<jakarta.el.version>6.0.1</jakarta.el.version>
231+
<tomcat-embed-el.version>11.0.0-M24</tomcat-embed-el.version>
232+
<hibernate-validator.version>8.0.1.Final</hibernate-validator.version>
232233

233234
<!-- IOC Injection -->
234235
<guice.version>7.0.0</guice.version>
235236

236237
<!-- JPA -->
237-
<hibernate.version>6.5.2.Final</hibernate.version>
238+
<hibernate.version>6.6.0.Final</hibernate.version>
238239
<hikari-cp.version>5.1.0</hikari-cp.version>
239240

240241
<!-- Cache -->
241-
<jedis.version>5.1.4</jedis.version>
242+
<jedis.version>5.1.5</jedis.version>
242243

243244
<quartz.version>2.5.0-rc1</quartz.version>
244245
<mqtt.version>1.2.5</mqtt.version>
@@ -263,12 +264,6 @@
263264

264265
<dependencies>
265266
<!-- Commons -->
266-
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 Apache 2.0-->
267-
<dependency>
268-
<groupId>org.apache.commons</groupId>
269-
<artifactId>commons-lang3</artifactId>
270-
<version>${commons-lang3.version}</version>
271-
</dependency>
272267
<!-- https://mvnrepository.com/artifact/commons-cli/commons-cli Apache 2.0-->
273268
<dependency>
274269
<groupId>commons-cli</groupId>
@@ -282,6 +277,12 @@
282277
<artifactId>commons-io</artifactId>
283278
<version>${commons-io.version}</version>
284279
</dependency>
280+
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 Apache 2.0-->
281+
<dependency>
282+
<groupId>org.apache.commons</groupId>
283+
<artifactId>commons-lang3</artifactId>
284+
<version>${commons-lang3.version}</version>
285+
</dependency>
285286
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-text -->
286287
<!-- <dependency>
287288
<groupId>org.apache.commons</groupId>
@@ -540,23 +541,29 @@
540541

541542

542543
<!-- Bean Validation -->
543-
<!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->
544+
<!-- https://mvnrepository.com/artifact/jakarta.el/jakarta.el-api -->
544545
<dependency>
545-
<groupId>org.hibernate.validator</groupId>
546-
<artifactId>hibernate-validator</artifactId>
547-
<version>${hibernate-validator.version}</version>
546+
<groupId>jakarta.el</groupId>
547+
<artifactId>jakarta.el-api</artifactId>
548+
<version>${jakarta.el.version}</version>
548549
</dependency>
549550
<!-- https://mvnrepository.com/artifact/org.glassfish/jakarta.el -->
551+
<!-- <dependency>-->
552+
<!-- <groupId>org.glassfish</groupId>-->
553+
<!-- <artifactId>jakarta.el</artifactId>-->
554+
<!-- <version>4.0.2</version>-->
555+
<!-- </dependency>-->
556+
<!-- https://mvnrepository.com/artifact/org.apache.tomcat.embed/tomcat-embed-el -->
550557
<dependency>
551-
<groupId>org.glassfish</groupId>
552-
<artifactId>jakarta.el</artifactId>
553-
<version>4.0.2</version>
558+
<groupId>org.apache.tomcat.embed</groupId>
559+
<artifactId>tomcat-embed-el</artifactId>
560+
<version>${tomcat-embed-el.version}</version>
554561
</dependency>
555-
<!-- https://mvnrepository.com/artifact/jakarta.el/jakarta.el-api -->
562+
<!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->
556563
<dependency>
557-
<groupId>jakarta.el</groupId>
558-
<artifactId>jakarta.el-api</artifactId>
559-
<version>${jakarta.el.version}</version>
564+
<groupId>org.hibernate.validator</groupId>
565+
<artifactId>hibernate-validator</artifactId>
566+
<version>${hibernate-validator.version}</version>
560567
</dependency>
561568

562569

src/main/java/org/summerboot/jexpress/boot/BootConstant.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public interface BootConstant {
2525
String APP_ID = String.format("%06d", new Random().nextInt(999999));
2626

2727
//version
28-
String VERSION = "SummerBoot.jExpress 2.4.10";
28+
String VERSION = "jExpress 2.4.11";
2929
String JEXPRESS_PACKAGE_NAME = "org.summerboot.jexpress";
3030

3131
String DEFAULT_ADMIN_MM = "changeit";

src/main/java/org/summerboot/jexpress/boot/BootGuiceModule.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.quartz.Scheduler;
2626
import org.summerboot.jexpress.boot.annotation.Controller;
2727
import org.summerboot.jexpress.boot.annotation.Inspector;
28+
import org.summerboot.jexpress.boot.annotation.Service;
2829
import org.summerboot.jexpress.boot.event.AppLifecycleHandler;
2930
import org.summerboot.jexpress.boot.event.AppLifecycleListener;
3031
import org.summerboot.jexpress.boot.event.HttpExceptionHandler;
@@ -76,7 +77,7 @@ public BootGuiceModule(Object caller, Class callerClass, Set<String> userSpecifi
7677
this.memo = memo;
7778
}
7879

79-
protected boolean isCliUseImplTag(String implTag) {
80+
protected boolean isTagSpecifiedViaCLI(String implTag) {
8081
return userSpecifiedImplTags != null && userSpecifiedImplTags.contains(implTag);
8182
}
8283

@@ -171,13 +172,20 @@ protected void scanAnnotation_BindInstance(Binder binder, Class<? extends Annota
171172
if (Modifier.isAbstract(mod) || Modifier.isInterface(mod)) {
172173
continue;
173174
}
175+
String implTag = null;
174176
if (a instanceof Controller) {
175177
Controller ca = (Controller) a;
176-
String implTag = ca.implTag();
177-
if (StringUtils.isNotBlank(implTag) && !isCliUseImplTag(implTag)) {
178-
continue;
178+
implTag = ca.implTag();
179+
} else if (a instanceof Inspector) {
180+
Service sa = (Service) c.getAnnotation(Service.class);
181+
if (sa != null) {
182+
implTag = sa.implTag();
179183
}
180184
}
185+
// no tag = always use this controller, with tag = only use this controller when -use <tag> specified
186+
if (StringUtils.isNotBlank(implTag) && !isTagSpecifiedViaCLI(implTag)) {
187+
continue;
188+
}
181189
classesAll.add(c);
182190
}
183191
//}

src/main/java/org/summerboot/jexpress/boot/ScanedGuiceModule.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public ScanedGuiceModule(Map<Class, Map<String, List<SummerSingularity.ServiceMe
5050
this.memo = memo;
5151
}
5252

53-
protected boolean isCliUseImplTag(String implTag) {
53+
protected boolean isTagSpecifiedViaCLI(String implTag) {
5454
return userSpecifiedImplTags.contains(implTag);
5555
}
5656

@@ -72,7 +72,7 @@ public void configure() {
7272
continue;
7373
}
7474
String implTag = serviceImpl.getImplTag();
75-
boolean isCliUseImplTag = isCliUseImplTag(implTag);
75+
boolean isCliUseImplTag = isTagSpecifiedViaCLI(implTag);
7676
memo.append(INFO_FOUND).append(interfaceClass.getName()).append(", implTag=").append(uniqueKey).append(BIND_TO).append(serviceImpl).append(", isCliUseImplTag=").append(isCliUseImplTag);
7777

7878
String named = serviceImpl.getNamed();

src/main/java/org/summerboot/jexpress/boot/SummerApplication.java

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@
2222
import io.grpc.ServerInterceptor;
2323
import io.grpc.ServerServiceDefinition;
2424
import org.apache.commons.lang3.exception.ExceptionUtils;
25+
import org.apache.logging.log4j.Level;
26+
import org.apache.logging.log4j.core.Appender;
27+
import org.apache.logging.log4j.core.Filter;
28+
import org.apache.logging.log4j.core.appender.ConsoleAppender;
29+
import org.apache.logging.log4j.core.filter.LevelRangeFilter;
2530
import org.quartz.SchedulerException;
2631
import org.summerboot.jexpress.boot.config.ConfigUtil;
2732
import org.summerboot.jexpress.boot.event.AppLifecycleListener;
@@ -40,9 +45,11 @@
4045
import org.summerboot.jexpress.nio.server.NioServer;
4146
import org.summerboot.jexpress.util.ApplicationUtil;
4247

48+
import java.io.File;
4349
import java.net.InetSocketAddress;
4450
import java.util.ArrayList;
4551
import java.util.List;
52+
import java.util.Map;
4653

4754
/**
4855
* In Code We Trust
@@ -282,12 +289,13 @@ public void start() {
282289
log.info(() -> sb.toString());
283290
}
284291

285-
long timeoutMs = BackOffice.agent.getProcessTimeoutMilliseconds();
286-
String timeoutDesc = BackOffice.agent.getProcessTimeoutAlertMessage();
287292
// 4. health inspection
288293
log.trace("4. health inspection");
289-
String serviceStatus = HealthMonitor.start(true);
294+
String serviceStatus = HealthMonitor.start(true, guiceInjector);
290295

296+
long timeoutMs = BackOffice.agent.getProcessTimeoutMilliseconds();
297+
String timeoutDesc = BackOffice.agent.getProcessTimeoutAlertMessage();
298+
StringBuilder startingMemo = new StringBuilder();
291299
// 5a. start server: gRPC
292300
if (hasGRPCImpl) {
293301
log.trace("5a. start server: gRPC hasGRPCImpl.bs={}", gRPCBindableServiceImplClasses);
@@ -316,7 +324,7 @@ public void start() {
316324
serverBuilder.addService(impl);
317325
}
318326
if (gRPCCfg.isAutoStart()) {
319-
gRPCServer.start();
327+
gRPCServer.start(startingMemo);
320328
}
321329
gRPCServerList.add(gRPCServer);
322330
}
@@ -330,14 +338,16 @@ public void start() {
330338
NioChannelInitializer channelInitializer = super.guiceInjector.getInstance(NioChannelInitializer.class);
331339
NIOStatusListener nioListener = super.guiceInjector.getInstance(NIOStatusListener.class);
332340
httpServer = new NioServer(channelInitializer.init(guiceInjector, channelHandlerNames), nioListener);
333-
httpServer.bind(NioConfig.cfg);
341+
httpServer.bind(NioConfig.cfg, startingMemo);
334342
}
335343
}
336344

337345
// 6. announcement
346+
startingMemo.append(BootConstant.BR).append(serviceStatus);
347+
startingMemo.append(BootConstant.BR).append("pid#" + BootConstant.PID);
338348
log.info(() -> BootConstant.BR + BootConstant.BR + I18n.info.launched.format(userSpecifiedResourceBundle, appVersion + " pid#" + BootConstant.PID) + serviceStatus);
339349
if (appLifecycleListener != null) {
340-
appLifecycleListener.onApplicationStart(super.appVersion, serviceStatus);
350+
appLifecycleListener.onApplicationStart(super.appVersion, startingMemo.toString());
341351
}
342352
} catch (java.net.BindException ex) {// from NioServer
343353
log.fatal(ex + BootConstant.BR + BackOffice.agent.getPortInUseAlertMessage());
@@ -350,11 +360,42 @@ public void start() {
350360
log.fatal(I18n.info.unlaunched.format(userSpecifiedResourceBundle), ex);
351361
}
352362
System.exit(1);
363+
} finally {
364+
// show prompt only with default log4j2.xml in case user is not familiar with log4j2.xml (only one ConsoleAppender with maxLevel is NOT "ALL"), no prompt if user modify the default log4j2.xml due to user knows what he/she is doing
365+
String prompt = null;
366+
try {
367+
org.apache.logging.log4j.core.Logger c = (org.apache.logging.log4j.core.Logger) log;
368+
Map<String, Appender> as = c.getContext().getConfiguration().getAppenders();
369+
int countConsoleAppender = 0;
370+
for (Map.Entry<String, Appender> entry : as.entrySet()) {
371+
Appender appender = entry.getValue();
372+
if (appender instanceof ConsoleAppender) {
373+
countConsoleAppender++;
374+
if (countConsoleAppender > 1) {
375+
prompt = null;
376+
break;
377+
}
378+
ConsoleAppender sa = (ConsoleAppender) appender;
379+
Filter f = sa.getFilter();
380+
if (f instanceof LevelRangeFilter) {
381+
LevelRangeFilter lrf = (LevelRangeFilter) f;
382+
Level maxLevel = lrf.getMaxLevel();
383+
if (!Level.ALL.equals(maxLevel)) {
384+
prompt = "\nTo show logs in console, please edit " + this.userSpecifiedConfigDir + File.separator
385+
+ "log4j2.xml \n\t<Configuration ...>\n\t <Appenders>\n\t <Console name=\"" + sa.getName() + "\" target=\"" + sa.getTarget() + "\">\n\t <LevelRangeFilter maxLevel=\"" + maxLevel + "\"/>\n\tchange around line#13: set maxLevel=\"" + Level.ALL + "\"";
386+
}
387+
}
388+
}
389+
}
390+
} catch (Throwable ex) {
391+
log.error("Failed to inspect " + this.userSpecifiedConfigDir + File.separator + "log4j2.xml", ex);
392+
}
393+
if (prompt != null) {
394+
System.out.println(prompt);
395+
}
353396
}
354397
}
355398

356-
protected static boolean a = true;
357-
358399
public void shutdown() {
359400
log.trace("");
360401
if (gRPCServerList != null && !gRPCServerList.isEmpty()) {

src/main/java/org/summerboot/jexpress/boot/SummerBigBang.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
import com.google.inject.Module;
2222
import com.google.inject.Stage;
2323
import com.google.inject.util.Modules;
24-
import io.jsonwebtoken.SignatureAlgorithm;
24+
import io.jsonwebtoken.Jwts;
25+
import io.jsonwebtoken.security.MacAlgorithm;
2526
import org.apache.commons.cli.CommandLineParser;
2627
import org.apache.commons.cli.DefaultParser;
2728
import org.apache.commons.cli.Option;
@@ -310,8 +311,17 @@ protected boolean runCLI_Utils() {
310311
// generate CLI_JWT root signing key
311312
if (cli.hasOption(BootConstant.CLI_JWT)) {
312313
continueCLI = false;
313-
String algorithm = cli.getOptionValue(BootConstant.CLI_JWT);
314-
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.forName(algorithm);
314+
String algorithm = cli.getOptionValue(BootConstant.CLI_JWT);// <HS256, HS384, HS512>
315+
MacAlgorithm signatureAlgorithm;
316+
switch (algorithm) {
317+
case "HS256" -> signatureAlgorithm = Jwts.SIG.HS256;
318+
case "HS384" -> signatureAlgorithm = Jwts.SIG.HS384;
319+
case "HS512" -> signatureAlgorithm = Jwts.SIG.HS512;
320+
default -> {
321+
System.out.println("invalid -" + BootConstant.CLI_JWT + " value: " + algorithm + ", valid -" + BootConstant.CLI_JWT + " values: <HS256, HS384, HS512>");
322+
return false;
323+
}
324+
}
315325
String jwt = JwtUtil.buildSigningKey(signatureAlgorithm);
316326
System.out.println(jwt);
317327
}

src/main/java/org/summerboot/jexpress/boot/event/AppLifecycleHandler.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@
1919
import com.google.inject.Singleton;
2020
import org.apache.logging.log4j.LogManager;
2121
import org.apache.logging.log4j.Logger;
22+
import org.summerboot.jexpress.boot.BootConstant;
2223
import org.summerboot.jexpress.boot.config.JExpressConfig;
2324
import org.summerboot.jexpress.boot.instrumentation.HealthMonitor;
2425
import org.summerboot.jexpress.integration.smtp.PostOffice;
2526
import org.summerboot.jexpress.integration.smtp.SMTPClientConfig;
2627

2728
import java.io.File;
28-
import java.time.OffsetDateTime;
2929

3030
/**
3131
* @author Changski Tie Zheng Zhang 张铁铮, 魏泽北, 杜旺财, 杜富贵
@@ -41,15 +41,15 @@ public class AppLifecycleHandler implements AppLifecycleListener {
4141
@Override
4242
public void onApplicationStart(String appVersion, String fullConfigInfo) {
4343
if (postOffice != null) {
44-
postOffice.sendAlertAsync(SMTPClientConfig.cfg.getEmailToAppSupport(), "Started at " + OffsetDateTime.now(), fullConfigInfo, null, false);
44+
postOffice.sendAlertAsync(SMTPClientConfig.cfg.getEmailToAppSupport(), "Started", fullConfigInfo, null, false);
4545
}
4646
}
4747

4848
@Override
4949
public void onApplicationStop(String appVersion) {
50-
log.info(appVersion);
50+
log.warn(appVersion);
5151
if (postOffice != null) {
52-
postOffice.sendAlertSync(SMTPClientConfig.cfg.getEmailToAppSupport(), "Shutdown at " + OffsetDateTime.now() + " - " + appVersion, "EOM", null, false);
52+
postOffice.sendAlertSync(SMTPClientConfig.cfg.getEmailToAppSupport(), "Shutdown", "pid#" + BootConstant.PID, null, false);
5353
}
5454
}
5555

@@ -68,7 +68,7 @@ public void onApplicationStatusUpdated(boolean healthOk, boolean paused, boolean
6868
boolean serviceAvaliable = healthOk && !paused;
6969
String content = HealthMonitor.buildMessage();
7070
if (postOffice != null) {
71-
postOffice.sendAlertAsync(SMTPClientConfig.cfg.getEmailToAppSupport(), "Service Status Changed at " + OffsetDateTime.now(), content, null, false);
71+
postOffice.sendAlertAsync(SMTPClientConfig.cfg.getEmailToAppSupport(), "Service Status Changed", content, null, false);
7272
}
7373
}
7474
}

0 commit comments

Comments
 (0)