Skip to content

Commit c51286c

Browse files
Feature2.5.0 (#291)
* 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 * enhanded logging when 200-> 204 due to no content * refactoring * refactoring * release 2.5.0
1 parent e0aed41 commit c51286c

File tree

8 files changed

+62
-41
lines changed

8 files changed

+62
-41
lines changed

pom.xml

Lines changed: 10 additions & 10 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.18</version>
7+
<version>2.5.0</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,
@@ -60,7 +60,7 @@
6060
<id>release</id>
6161
<properties>
6262
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
63-
<maven.compiler.release>17</maven.compiler.release>
63+
<maven.compiler.release>21</maven.compiler.release>
6464
<maven-scm.version>2.1.0</maven-scm.version>
6565
<maven-source.version>3.3.1</maven-source.version>
6666
<maven-javadoc.version>3.11.2</maven-javadoc.version>
@@ -181,7 +181,7 @@
181181
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
182182
<!-- <maven.compiler.source>21</maven.compiler.source>-->
183183
<!-- <maven.compiler.target>21</maven.compiler.target>-->
184-
<maven.compiler.release>17</maven.compiler.release>
184+
<maven.compiler.release>21</maven.compiler.release>
185185
<maven-clean.version>3.4.0</maven-clean.version>
186186
<maven-compiler.version>3.13.0</maven-compiler.version>
187187
<maven-dependency.version>3.8.1</maven-dependency.version>
@@ -201,19 +201,19 @@
201201
<!-- Mail -->
202202
<jakarta-mail.version>2.0.1</jakarta-mail.version>
203203
<!-- Security -->
204-
<bouncycastle.version>1.79</bouncycastle.version>
204+
<bouncycastle.version>1.80</bouncycastle.version>
205205
<!-- JWT -->
206206
<jwt.version>0.12.6</jwt.version>
207207

208208
<!-- NIO Netty -->
209-
<netty.version>4.1.116.Final</netty.version>
209+
<netty.version>4.1.117.Final</netty.version>
210210
<netty-tcnative.version>2.0.69.Final</netty-tcnative.version>
211211
<!-- gRPC and protobuf -->
212-
<grpc.version>1.69.0</grpc.version>
212+
<grpc.version>1.70.0</grpc.version>
213213
<guava.version>33.4.0-jre</guava.version>
214-
<protobuf.version>4.29.2</protobuf.version>
214+
<protobuf.version>4.29.3</protobuf.version>
215215
<!-- Web JAX-RS -->
216-
<swagger.core.version>2.2.27</swagger.core.version>
216+
<swagger.core.version>2.2.28</swagger.core.version>
217217
<!--<elastic-apm.version>1.36.0</elastic-apm.version>-->
218218

219219

@@ -235,7 +235,7 @@
235235
<guice.version>7.0.0</guice.version>
236236

237237
<!-- JPA -->
238-
<hibernate.version>6.6.4.Final</hibernate.version>
238+
<hibernate.version>6.6.5.Final</hibernate.version>
239239
<hikari-cp.version>6.2.1</hikari-cp.version>
240240

241241
<!-- Cache -->
@@ -259,7 +259,7 @@
259259

260260
<!-- Testing -->
261261
<testng.version>7.10.2</testng.version>
262-
<jdbc.version>9.1.0</jdbc.version>
262+
<jdbc.version>9.2.0</jdbc.version>
263263
</properties>
264264

265265
<dependencies>

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

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

2929
//version
30-
String VERSION = "jExpress 2.4.18";
30+
String VERSION = "jExpress 2.5.0";
3131
String JEXPRESS_PACKAGE_NAME = "org.summerboot.jexpress";
3232

3333
String DEFAULT_ADMIN_MM = "changeit";

src/main/java/org/summerboot/jexpress/boot/config/BootConfig.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,21 @@ public static ThreadPoolExecutor buildThreadPoolExecutor(ThreadPoolExecutor tpe,
606606
boolean prestartAllCoreThreads, boolean allowCoreThreadTimeOut, boolean isSingleton) {
607607
boolean useVirtualThread = false;
608608
switch (threadingMode) {
609-
case Mixed, VirtualThread -> {// manual config is required when it is mixed
609+
case VirtualThread -> { // Java 21+ only
610+
useVirtualThread = true;
611+
if (core < 1) {
612+
core = Integer.MAX_VALUE;
613+
allowCoreThreadTimeOut = true;
614+
}
615+
if (max < 1) {
616+
max = Integer.MAX_VALUE;
617+
}
618+
if (max < core) {
619+
//helper.addError("BizExecutor.MaxSize should not less than BizExecutor.CoreSize");
620+
max = core;
621+
}
622+
}
623+
case Mixed/*, VirtualThread*/ -> {// manual config is required when it is mixed
610624
if (core < 1) {
611625
core = CPU_CORE * 2 + 1;
612626
}

src/main/java/org/summerboot/jexpress/boot/config/NamedDefaultThreadFactory.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ public static ThreadFactory build(String tpeName, boolean useVirtualThread) {
3131
String namePrefix = tpeName + "-"
3232
+ poolNumber.getAndIncrement()
3333
+ (useVirtualThread ? "-vt-" : "-pt-");
34-
return new NamedDefaultThreadFactory(namePrefix);
34+
return useVirtualThread
35+
? Thread.ofVirtual().name(namePrefix, 0).factory() // Java 21+ only
36+
: new NamedDefaultThreadFactory(namePrefix);
3537
}
3638
}

src/main/java/org/summerboot/jexpress/nio/server/NioHttpUtil.java

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ private static void sendRedirect(ChannelHandlerContext ctx, String newUri, HttpR
105105
ctx.writeAndFlush(resp).addListener(ChannelFutureListener.CLOSE);
106106
}
107107

108+
108109
public static long sendResponse(ChannelHandlerContext ctx, boolean isKeepAlive, final ServiceContext serviceContext, final ErrorAuditor errorAuditor, final ProcessorSettings processorSettings) {
109110
String headerKey_reference;
110111
String headerKey_serverTimestamp;
@@ -117,44 +118,40 @@ public static long sendResponse(ChannelHandlerContext ctx, boolean isKeepAlive,
117118
}
118119
serviceContext.responseHeader(headerKey_reference, serviceContext.txId());
119120
serviceContext.responseHeader(headerKey_serverTimestamp, OffsetDateTime.now().format(TimeUtil.ISO_ZONED_DATE_TIME3));
121+
final HttpResponseStatus status = serviceContext.status();
120122

121123
if (serviceContext.file() != null) {
122124
return sendFile(ctx, isKeepAlive, serviceContext);
123125
}
126+
if (serviceContext.redirect() != null) {
127+
sendRedirect(ctx, serviceContext.redirect(), status);
128+
return 0;
129+
}
124130

125-
HttpResponseStatus status = serviceContext.status();
126-
ResponseEncoder responseEncoder = serviceContext.responseEncoder();
127-
if (StringUtils.isBlank(serviceContext.txt()) && status.code() >= 400) {
131+
boolean hasErrorContent = StringUtils.isEmpty(serviceContext.txt()) && status.code() >= 400;
132+
if (hasErrorContent) {
128133
if (serviceContext.error() == null) {
129134
serviceContext.error(null);
130135
}
131-
132136
String clientAcceptContentType = serviceContext.clientAcceptContentType();
133-
String textResponse;
137+
String errorResponse;
134138
if (clientAcceptContentType != null && clientAcceptContentType.contains("xml")) {
135-
textResponse = serviceContext.error().toXML();
139+
errorResponse = serviceContext.error().toXML();
136140
serviceContext.contentType(MediaType.APPLICATION_XML);
137141
} else {
138-
textResponse = serviceContext.error().toJson();
142+
errorResponse = serviceContext.error().toJson();
139143
serviceContext.contentType(MediaType.APPLICATION_JSON);
140144
}
141145
if (errorAuditor != null) {
142-
textResponse = errorAuditor.beforeSendingError(textResponse);
146+
errorResponse = errorAuditor.beforeSendingError(errorResponse);
143147
}
144-
serviceContext.txt(textResponse);
145-
}
146-
if (StringUtils.isNotBlank(serviceContext.txt())) {
147-
return sendText(ctx, isKeepAlive, serviceContext.responseHeaders(), status, serviceContext.txt(), serviceContext.contentType(), serviceContext.charsetName(), true, responseEncoder);
148-
}
149-
if (serviceContext.redirect() != null) {
150-
sendRedirect(ctx, serviceContext.redirect(), status);
151-
return 0;
148+
serviceContext.txt(errorResponse);
152149
}
153150

154-
if (serviceContext.autoConvertBlank200To204() && HttpResponseStatus.OK.equals(status)) {
155-
status = HttpResponseStatus.NO_CONTENT;
151+
if (HttpResponseStatus.OK.equals(status) && serviceContext.autoConvertBlank200To204() && StringUtils.isEmpty(serviceContext.txt())) {
152+
serviceContext.status(HttpResponseStatus.NO_CONTENT);
156153
}
157-
return sendText(ctx, isKeepAlive, serviceContext.responseHeaders(), status, null, serviceContext.contentType(), serviceContext.charsetName(), true, responseEncoder);
154+
return sendText(ctx, isKeepAlive, serviceContext.responseHeaders(), serviceContext.status(), serviceContext.txt(), serviceContext.contentType(), serviceContext.charsetName(), true, serviceContext.responseEncoder());
158155
}
159156

160157
protected static final String DEFAULT_CHARSET = "UTF-8";
@@ -195,13 +192,8 @@ protected static long sendText(ChannelHandlerContext ctx, boolean isKeepAlive, H
195192
if (contentType != null) {
196193
h.set(HttpHeaderNames.CONTENT_TYPE, contentType + ";charset=" + charsetName);
197194
}
198-
long contentLength = resp.content().readableBytes();
199-
200-
if (contentLength > Integer.MAX_VALUE) {
201-
h.set(HttpHeaderNames.CONTENT_LENGTH, String.valueOf(contentLength));
202-
} else {
203-
h.setInt(HttpHeaderNames.CONTENT_LENGTH, (int) contentLength);
204-
}
195+
int contentLength = resp.content().readableBytes();
196+
h.set(HttpHeaderNames.CONTENT_LENGTH, String.valueOf(contentLength));
205197

206198
// send
207199
if (isKeepAlive) {//HttpUtil.isKeepAlive(req);
@@ -221,6 +213,9 @@ protected static long sendText(ChannelHandlerContext ctx, boolean isKeepAlive, H
221213
ctx.write(resp).addListener(ChannelFutureListener.CLOSE);
222214
}
223215
}
216+
if (serviceHeaders != null) {
217+
serviceHeaders.set(h);
218+
}
224219
return contentLength;
225220
}
226221

@@ -231,6 +226,7 @@ private static long sendFile(ChannelHandlerContext ctx, boolean isKeepAlive, fin
231226
long fileLength = -1;
232227
final RandomAccessFile randomAccessFile;
233228
File file = serviceContext.file();
229+
serviceContext.memo("sendFile", file.getAbsolutePath());
234230
String filePath = file.getName();
235231
try {
236232
randomAccessFile = new RandomAccessFile(file, "r");

src/main/java/org/summerboot/jexpress/nio/server/domain/LoginVo.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
package org.summerboot.jexpress.nio.server.domain;
22

3+
import jakarta.validation.constraints.NotEmpty;
4+
import jakarta.validation.constraints.NotNull;
5+
36
public class LoginVo {
7+
@NotNull
8+
@NotEmpty
49
protected String username;
10+
11+
@NotNull
12+
@NotEmpty
513
protected String password;
614

715
public LoginVo() {

src/main/java/org/summerboot/jexpress/nio/server/ws/rs/BootController.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import io.swagger.v3.oas.annotations.servers.Server;
3636
import jakarta.annotation.Nonnull;
3737
import jakarta.annotation.security.RolesAllowed;
38+
import jakarta.validation.Valid;
3839
import jakarta.ws.rs.Consumes;
3940
import jakarta.ws.rs.DELETE;
4041
import jakarta.ws.rs.FormParam;
@@ -384,7 +385,7 @@ public Caller longin_jSecurityCheck(@Parameter(required = true) @Nonnull @FormPa
384385
@Deamon
385386
//@CaptureTransaction("user.signJWT")
386387
@Log(requestBody = false, responseHeader = false)
387-
public Caller longin_JSON(@Nonnull LoginVo loginVo,
388+
public Caller longin_JSON(@Valid @Nonnull LoginVo loginVo,
388389
@Parameter(hidden = true) final ServiceContext context) throws IOException, NamingException {
389390
return login(auth, loginVo.getUsername(), loginVo.getPassword(), context);
390391
}

src/main/java/org/summerboot/jexpress/security/auth/BootAuthenticator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ public String signJWT(String username, String pwd, E metaData, int validForMinut
8585
Caller caller = authenticate(username, pwd, (E) metaData, authenticatorListener, context);
8686
context.poi(BootPOI.LDAP_END);
8787

88+
context.caller(caller);
8889
return signJWT(caller, validForMinutes, context);
8990
}
9091

@@ -109,7 +110,6 @@ public String signJWT(Caller caller, int validForMinutes, final ServiceContext c
109110
if (authenticatorListener != null) {
110111
authenticatorListener.onLoginSuccess(caller.getUid(), token);
111112
}
112-
context.caller(caller);
113113
return token;
114114
}
115115

0 commit comments

Comments
 (0)