From 4e317bc887fc8bed7c81769eceebc5c1cb856622 Mon Sep 17 00:00:00 2001 From: Summer Boot Framework Date: Thu, 26 Dec 2024 13:00:08 -0500 Subject: [PATCH 1/5] Virtual Thread, and the four (VirtualThread, CPU, IO, Mixed) mode are supported in the configuration file for HTTP server, HTTP client, gRPC server and BackOffice --- pom.xml | 6 +++--- .../summerboot/jexpress/boot/BootConstant.java | 2 +- .../jexpress/boot/config/BootConfig.java | 16 +++++++++++++++- .../boot/config/NamedDefaultThreadFactory.java | 4 +++- 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 0be6495..5e989a5 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 org.summerboot jexpress - 2.4.18 + 2.5.0-SNAPSHOT jar Summer Boot jExpress Summer Boot jExpress focuses on solving non-functional and operational maintainability requirements, @@ -60,7 +60,7 @@ release UTF-8 - 17 + 21 2.1.0 3.3.1 3.11.2 @@ -181,7 +181,7 @@ UTF-8 - 17 + 21 3.4.0 3.13.0 3.8.1 diff --git a/src/main/java/org/summerboot/jexpress/boot/BootConstant.java b/src/main/java/org/summerboot/jexpress/boot/BootConstant.java index a63734c..0f4d404 100644 --- a/src/main/java/org/summerboot/jexpress/boot/BootConstant.java +++ b/src/main/java/org/summerboot/jexpress/boot/BootConstant.java @@ -27,7 +27,7 @@ public interface BootConstant { String APP_ID = String.format("%06d", new Random().nextInt(999999)); //version - String VERSION = "jExpress 2.4.18"; + String VERSION = "jExpress 2.5.0"; String JEXPRESS_PACKAGE_NAME = "org.summerboot.jexpress"; String DEFAULT_ADMIN_MM = "changeit"; diff --git a/src/main/java/org/summerboot/jexpress/boot/config/BootConfig.java b/src/main/java/org/summerboot/jexpress/boot/config/BootConfig.java index af358ef..f59eb5e 100644 --- a/src/main/java/org/summerboot/jexpress/boot/config/BootConfig.java +++ b/src/main/java/org/summerboot/jexpress/boot/config/BootConfig.java @@ -606,7 +606,21 @@ public static ThreadPoolExecutor buildThreadPoolExecutor(ThreadPoolExecutor tpe, boolean prestartAllCoreThreads, boolean allowCoreThreadTimeOut, boolean isSingleton) { boolean useVirtualThread = false; switch (threadingMode) { - case Mixed, VirtualThread -> {// manual config is required when it is mixed + case VirtualThread -> { // Java 21+ only + useVirtualThread = true; + if (core < 1) { + core = Integer.MAX_VALUE; + allowCoreThreadTimeOut = true; + } + if (max < 1) { + max = Integer.MAX_VALUE; + } + if (max < core) { + //helper.addError("BizExecutor.MaxSize should not less than BizExecutor.CoreSize"); + max = core; + } + } + case Mixed/*, VirtualThread*/ -> {// manual config is required when it is mixed if (core < 1) { core = CPU_CORE * 2 + 1; } diff --git a/src/main/java/org/summerboot/jexpress/boot/config/NamedDefaultThreadFactory.java b/src/main/java/org/summerboot/jexpress/boot/config/NamedDefaultThreadFactory.java index 1f6aae7..10bef82 100644 --- a/src/main/java/org/summerboot/jexpress/boot/config/NamedDefaultThreadFactory.java +++ b/src/main/java/org/summerboot/jexpress/boot/config/NamedDefaultThreadFactory.java @@ -31,6 +31,8 @@ public static ThreadFactory build(String tpeName, boolean useVirtualThread) { String namePrefix = tpeName + "-" + poolNumber.getAndIncrement() + (useVirtualThread ? "-vt-" : "-pt-"); - return new NamedDefaultThreadFactory(namePrefix); + return useVirtualThread + ? Thread.ofVirtual().name(namePrefix, 0).factory() // Java 21+ only + : new NamedDefaultThreadFactory(namePrefix); } } From bb1e0794ffe9f84654c29ad301dc36078330fa25 Mon Sep 17 00:00:00 2001 From: Summer Boot Framework Date: Sun, 5 Jan 2025 12:29:44 -0500 Subject: [PATCH 2/5] enhanded logging when 200-> 204 due to no content --- .../java/org/summerboot/jexpress/nio/server/NioHttpUtil.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/summerboot/jexpress/nio/server/NioHttpUtil.java b/src/main/java/org/summerboot/jexpress/nio/server/NioHttpUtil.java index 37952a3..3e0bf32 100644 --- a/src/main/java/org/summerboot/jexpress/nio/server/NioHttpUtil.java +++ b/src/main/java/org/summerboot/jexpress/nio/server/NioHttpUtil.java @@ -153,6 +153,7 @@ public static long sendResponse(ChannelHandlerContext ctx, boolean isKeepAlive, if (serviceContext.autoConvertBlank200To204() && HttpResponseStatus.OK.equals(status)) { status = HttpResponseStatus.NO_CONTENT; + serviceContext.status(status); } return sendText(ctx, isKeepAlive, serviceContext.responseHeaders(), status, null, serviceContext.contentType(), serviceContext.charsetName(), true, responseEncoder); } From cc7d2cf3712be597fdca6208babaf6f2745267c7 Mon Sep 17 00:00:00 2001 From: Summer Boot Framework Date: Sun, 12 Jan 2025 15:30:15 -0500 Subject: [PATCH 3/5] refactoring --- pom.xml | 2 +- .../jexpress/nio/server/NioHttpUtil.java | 47 ++++++++----------- .../jexpress/nio/server/domain/LoginVo.java | 8 ++++ .../nio/server/ws/rs/BootController.java | 3 +- .../security/auth/BootAuthenticator.java | 2 +- 5 files changed, 32 insertions(+), 30 deletions(-) diff --git a/pom.xml b/pom.xml index 5e989a5..38a6881 100644 --- a/pom.xml +++ b/pom.xml @@ -211,7 +211,7 @@ 1.69.0 33.4.0-jre - 4.29.2 + 4.29.3 2.2.27 diff --git a/src/main/java/org/summerboot/jexpress/nio/server/NioHttpUtil.java b/src/main/java/org/summerboot/jexpress/nio/server/NioHttpUtil.java index 3e0bf32..d785570 100644 --- a/src/main/java/org/summerboot/jexpress/nio/server/NioHttpUtil.java +++ b/src/main/java/org/summerboot/jexpress/nio/server/NioHttpUtil.java @@ -105,6 +105,7 @@ private static void sendRedirect(ChannelHandlerContext ctx, String newUri, HttpR ctx.writeAndFlush(resp).addListener(ChannelFutureListener.CLOSE); } + public static long sendResponse(ChannelHandlerContext ctx, boolean isKeepAlive, final ServiceContext serviceContext, final ErrorAuditor errorAuditor, final ProcessorSettings processorSettings) { String headerKey_reference; String headerKey_serverTimestamp; @@ -117,45 +118,40 @@ public static long sendResponse(ChannelHandlerContext ctx, boolean isKeepAlive, } serviceContext.responseHeader(headerKey_reference, serviceContext.txId()); serviceContext.responseHeader(headerKey_serverTimestamp, OffsetDateTime.now().format(TimeUtil.ISO_ZONED_DATE_TIME3)); + final HttpResponseStatus status = serviceContext.status(); if (serviceContext.file() != null) { return sendFile(ctx, isKeepAlive, serviceContext); } + if (serviceContext.redirect() != null) { + sendRedirect(ctx, serviceContext.redirect(), status); + return 0; + } - HttpResponseStatus status = serviceContext.status(); - ResponseEncoder responseEncoder = serviceContext.responseEncoder(); - if (StringUtils.isBlank(serviceContext.txt()) && status.code() >= 400) { + boolean hasErrorContent = StringUtils.isEmpty(serviceContext.txt()) && status.code() >= 400; + if (hasErrorContent) { if (serviceContext.error() == null) { serviceContext.error(null); } - String clientAcceptContentType = serviceContext.clientAcceptContentType(); - String textResponse; + String errorResponse; if (clientAcceptContentType != null && clientAcceptContentType.contains("xml")) { - textResponse = serviceContext.error().toXML(); + errorResponse = serviceContext.error().toXML(); serviceContext.contentType(MediaType.APPLICATION_XML); } else { - textResponse = serviceContext.error().toJson(); + errorResponse = serviceContext.error().toJson(); serviceContext.contentType(MediaType.APPLICATION_JSON); } if (errorAuditor != null) { - textResponse = errorAuditor.beforeSendingError(textResponse); + errorResponse = errorAuditor.beforeSendingError(errorResponse); } - serviceContext.txt(textResponse); - } - if (StringUtils.isNotBlank(serviceContext.txt())) { - return sendText(ctx, isKeepAlive, serviceContext.responseHeaders(), status, serviceContext.txt(), serviceContext.contentType(), serviceContext.charsetName(), true, responseEncoder); - } - if (serviceContext.redirect() != null) { - sendRedirect(ctx, serviceContext.redirect(), status); - return 0; + serviceContext.txt(errorResponse); } - if (serviceContext.autoConvertBlank200To204() && HttpResponseStatus.OK.equals(status)) { - status = HttpResponseStatus.NO_CONTENT; - serviceContext.status(status); + if (HttpResponseStatus.OK.equals(status) && serviceContext.autoConvertBlank200To204() && StringUtils.isEmpty(serviceContext.txt())) { + serviceContext.status(HttpResponseStatus.NO_CONTENT); } - return sendText(ctx, isKeepAlive, serviceContext.responseHeaders(), status, null, serviceContext.contentType(), serviceContext.charsetName(), true, responseEncoder); + return sendText(ctx, isKeepAlive, serviceContext.responseHeaders(), serviceContext.status(), serviceContext.txt(), serviceContext.contentType(), serviceContext.charsetName(), true, serviceContext.responseEncoder()); } protected static final String DEFAULT_CHARSET = "UTF-8"; @@ -196,13 +192,8 @@ protected static long sendText(ChannelHandlerContext ctx, boolean isKeepAlive, H if (contentType != null) { h.set(HttpHeaderNames.CONTENT_TYPE, contentType + ";charset=" + charsetName); } - long contentLength = resp.content().readableBytes(); - - if (contentLength > Integer.MAX_VALUE) { - h.set(HttpHeaderNames.CONTENT_LENGTH, String.valueOf(contentLength)); - } else { - h.setInt(HttpHeaderNames.CONTENT_LENGTH, (int) contentLength); - } + int contentLength = resp.content().readableBytes(); + h.set(HttpHeaderNames.CONTENT_LENGTH, String.valueOf(contentLength)); // send if (isKeepAlive) {//HttpUtil.isKeepAlive(req); @@ -222,6 +213,7 @@ protected static long sendText(ChannelHandlerContext ctx, boolean isKeepAlive, H ctx.write(resp).addListener(ChannelFutureListener.CLOSE); } } + serviceHeaders.set(h); return contentLength; } @@ -232,6 +224,7 @@ private static long sendFile(ChannelHandlerContext ctx, boolean isKeepAlive, fin long fileLength = -1; final RandomAccessFile randomAccessFile; File file = serviceContext.file(); + serviceContext.memo("sendFile", file.getAbsolutePath()); String filePath = file.getName(); try { randomAccessFile = new RandomAccessFile(file, "r"); diff --git a/src/main/java/org/summerboot/jexpress/nio/server/domain/LoginVo.java b/src/main/java/org/summerboot/jexpress/nio/server/domain/LoginVo.java index 742bfdc..2efc919 100644 --- a/src/main/java/org/summerboot/jexpress/nio/server/domain/LoginVo.java +++ b/src/main/java/org/summerboot/jexpress/nio/server/domain/LoginVo.java @@ -1,7 +1,15 @@ package org.summerboot.jexpress.nio.server.domain; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; + public class LoginVo { + @NotNull + @NotEmpty protected String username; + + @NotNull + @NotEmpty protected String password; public LoginVo() { diff --git a/src/main/java/org/summerboot/jexpress/nio/server/ws/rs/BootController.java b/src/main/java/org/summerboot/jexpress/nio/server/ws/rs/BootController.java index 19961b7..f91d829 100644 --- a/src/main/java/org/summerboot/jexpress/nio/server/ws/rs/BootController.java +++ b/src/main/java/org/summerboot/jexpress/nio/server/ws/rs/BootController.java @@ -35,6 +35,7 @@ import io.swagger.v3.oas.annotations.servers.Server; import jakarta.annotation.Nonnull; import jakarta.annotation.security.RolesAllowed; +import jakarta.validation.Valid; import jakarta.ws.rs.Consumes; import jakarta.ws.rs.DELETE; import jakarta.ws.rs.FormParam; @@ -384,7 +385,7 @@ public Caller longin_jSecurityCheck(@Parameter(required = true) @Nonnull @FormPa @Deamon //@CaptureTransaction("user.signJWT") @Log(requestBody = false, responseHeader = false) - public Caller longin_JSON(@Nonnull LoginVo loginVo, + public Caller longin_JSON(@Valid @Nonnull LoginVo loginVo, @Parameter(hidden = true) final ServiceContext context) throws IOException, NamingException { return login(auth, loginVo.getUsername(), loginVo.getPassword(), context); } diff --git a/src/main/java/org/summerboot/jexpress/security/auth/BootAuthenticator.java b/src/main/java/org/summerboot/jexpress/security/auth/BootAuthenticator.java index 89e56e3..dd7f362 100644 --- a/src/main/java/org/summerboot/jexpress/security/auth/BootAuthenticator.java +++ b/src/main/java/org/summerboot/jexpress/security/auth/BootAuthenticator.java @@ -85,6 +85,7 @@ public String signJWT(String username, String pwd, E metaData, int validForMinut Caller caller = authenticate(username, pwd, (E) metaData, authenticatorListener, context); context.poi(BootPOI.LDAP_END); + context.caller(caller); return signJWT(caller, validForMinutes, context); } @@ -109,7 +110,6 @@ public String signJWT(Caller caller, int validForMinutes, final ServiceContext c if (authenticatorListener != null) { authenticatorListener.onLoginSuccess(caller.getUid(), token); } - context.caller(caller); return token; } From f4353e18866a606154dbf0ea60c5faca6e9fee21 Mon Sep 17 00:00:00 2001 From: Summer Boot Framework Date: Sun, 26 Jan 2025 14:11:33 -0500 Subject: [PATCH 4/5] refactoring --- pom.xml | 12 ++++++------ .../summerboot/jexpress/nio/server/NioHttpUtil.java | 4 +++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 38a6881..37b98ea 100644 --- a/pom.xml +++ b/pom.xml @@ -201,19 +201,19 @@ 2.0.1 - 1.79 + 1.80 0.12.6 - 4.1.116.Final + 4.1.117.Final 2.0.69.Final - 1.69.0 + 1.70.0 33.4.0-jre 4.29.3 - 2.2.27 + 2.2.28 @@ -235,7 +235,7 @@ 7.0.0 - 6.6.4.Final + 6.6.5.Final 6.2.1 @@ -259,7 +259,7 @@ 7.10.2 - 9.1.0 + 9.2.0 diff --git a/src/main/java/org/summerboot/jexpress/nio/server/NioHttpUtil.java b/src/main/java/org/summerboot/jexpress/nio/server/NioHttpUtil.java index d785570..74222be 100644 --- a/src/main/java/org/summerboot/jexpress/nio/server/NioHttpUtil.java +++ b/src/main/java/org/summerboot/jexpress/nio/server/NioHttpUtil.java @@ -213,7 +213,9 @@ protected static long sendText(ChannelHandlerContext ctx, boolean isKeepAlive, H ctx.write(resp).addListener(ChannelFutureListener.CLOSE); } } - serviceHeaders.set(h); + if (serviceHeaders != null) { + serviceHeaders.set(h); + } return contentLength; } From 1fa75134eb9bcd1ff97e5a33339b649978381999 Mon Sep 17 00:00:00 2001 From: Summer Boot Framework Date: Thu, 30 Jan 2025 19:36:47 -0500 Subject: [PATCH 5/5] release 2.5.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 37b98ea..c73bd45 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 org.summerboot jexpress - 2.5.0-SNAPSHOT + 2.5.0 jar Summer Boot jExpress Summer Boot jExpress focuses on solving non-functional and operational maintainability requirements,