Skip to content

Commit a69601e

Browse files
authored
Merge pull request #1886 from steve-community/1884-migrate-to-spring-boot-4-REAL
Migrate to Spring Boot 4
2 parents d02b459 + d014447 commit a69601e

28 files changed

+199
-240
lines changed

pom.xml

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<parent>
1010
<groupId>org.springframework.boot</groupId>
1111
<artifactId>spring-boot-starter-parent</artifactId>
12-
<version>3.5.7</version>
12+
<version>4.0.0</version>
1313
<relativePath/> <!-- lookup parent from repository -->
1414
</parent>
1515

@@ -170,7 +170,7 @@
170170
<plugin>
171171
<groupId>com.github.spotbugs</groupId>
172172
<artifactId>spotbugs-maven-plugin</artifactId>
173-
<version>4.9.8.1</version>
173+
<version>4.9.8.2</version>
174174
<configuration>
175175
<failOnError>false</failOnError>
176176
<onlyAnalyze>de.rwth.idsg.steve.-</onlyAnalyze>
@@ -400,11 +400,11 @@
400400
<dependencies>
401401
<dependency>
402402
<groupId>org.springframework.boot</groupId>
403-
<artifactId>spring-boot-starter-web</artifactId>
403+
<artifactId>spring-boot-starter-webmvc</artifactId>
404404
<exclusions>
405405
<exclusion>
406-
<artifactId>spring-boot-starter-tomcat</artifactId>
407406
<groupId>org.springframework.boot</groupId>
407+
<artifactId>spring-boot-starter-tomcat</artifactId>
408408
</exclusion>
409409
</exclusions>
410410
</dependency>
@@ -428,11 +428,15 @@
428428
<groupId>org.springframework.boot</groupId>
429429
<artifactId>spring-boot-starter-validation</artifactId>
430430
</dependency>
431+
<dependency>
432+
<groupId>org.springframework.boot</groupId>
433+
<artifactId>spring-boot-starter-jackson</artifactId>
434+
</dependency>
431435

432436
<dependency>
433437
<groupId>org.springdoc</groupId>
434438
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
435-
<version>2.8.13</version>
439+
<version>3.0.0</version>
436440
</dependency>
437441

438442
<dependency>
@@ -443,7 +447,7 @@
443447
<dependency>
444448
<groupId>com.github.steve-community</groupId>
445449
<artifactId>ocpp-jaxb</artifactId>
446-
<version>0.0.12</version>
450+
<version>0.0.13</version>
447451
</dependency>
448452
<dependency>
449453
<groupId>org.jetbrains</groupId>
@@ -464,11 +468,11 @@
464468
</dependency>
465469

466470
<dependency>
467-
<groupId>com.fasterxml.jackson.core</groupId>
471+
<groupId>tools.jackson.core</groupId>
468472
<artifactId>jackson-databind</artifactId>
469473
</dependency>
470474
<dependency>
471-
<groupId>com.fasterxml.jackson.module</groupId>
475+
<groupId>tools.jackson.module</groupId>
472476
<artifactId>jackson-module-jakarta-xmlbind-annotations</artifactId>
473477
</dependency>
474478
<dependency>
@@ -477,7 +481,7 @@
477481
</dependency>
478482
<!-- Needed for Joda fields in de.rwth.idsg.steve.web.api -->
479483
<dependency>
480-
<groupId>com.fasterxml.jackson.datatype</groupId>
484+
<groupId>tools.jackson.datatype</groupId>
481485
<artifactId>jackson-datatype-joda</artifactId>
482486
</dependency>
483487
<dependency>
@@ -490,6 +494,12 @@
490494
<groupId>org.apache.cxf</groupId>
491495
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
492496
<version>${cxf.version}</version>
497+
<exclusions>
498+
<exclusion>
499+
<groupId>org.springframework.boot</groupId>
500+
<artifactId>spring-boot-starter-tomcat</artifactId>
501+
</exclusion>
502+
</exclusions>
493503
</dependency>
494504
<dependency>
495505
<groupId>org.apache.cxf</groupId>
@@ -499,8 +509,8 @@
499509

500510
<!-- JSP related dependencies -->
501511
<dependency>
502-
<groupId>org.eclipse.jetty.ee10</groupId>
503-
<artifactId>jetty-ee10-apache-jsp</artifactId>
512+
<groupId>org.eclipse.jetty.ee11</groupId>
513+
<artifactId>jetty-ee11-apache-jsp</artifactId>
504514
</dependency>
505515
<dependency>
506516
<groupId>jakarta.servlet.jsp.jstl</groupId>

src/main/java/de/rwth/idsg/steve/SteveApplication.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import org.joda.time.DateTimeZone;
2727
import org.springframework.boot.SpringApplication;
2828
import org.springframework.boot.autoconfigure.SpringBootApplication;
29-
import org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration;
3029
import org.springframework.boot.context.event.ApplicationStartedEvent;
3130
import org.springframework.context.ConfigurableApplicationContext;
3231
import org.springframework.context.event.EventListener;
@@ -38,7 +37,7 @@
3837
* @since 19.09.2025
3938
*/
4039
@Slf4j
41-
@SpringBootApplication(exclude = {JooqAutoConfiguration.class})
40+
@SpringBootApplication
4241
public class SteveApplication {
4342

4443
static {

src/main/java/de/rwth/idsg/steve/config/ApiAuthenticationManager.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
*/
1919
package de.rwth.idsg.steve.config;
2020

21-
import com.fasterxml.jackson.databind.ObjectMapper;
21+
import tools.jackson.databind.ObjectMapper;
2222
import com.google.common.base.Strings;
2323
import de.rwth.idsg.steve.service.WebUserService;
2424
import de.rwth.idsg.steve.web.api.ApiControllerAdvice;

src/main/java/de/rwth/idsg/steve/config/BeanConfiguration.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
*/
1919
package de.rwth.idsg.steve.config;
2020

21-
import com.fasterxml.jackson.datatype.joda.JodaModule;
2221
import com.mysql.cj.conf.PropertyKey;
2322
import com.zaxxer.hikari.HikariConfig;
2423
import com.zaxxer.hikari.HikariDataSource;
@@ -33,8 +32,8 @@
3332
import org.jooq.impl.DSL;
3433
import org.jooq.impl.DataSourceConnectionProvider;
3534
import org.jooq.impl.DefaultConfiguration;
36-
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
37-
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
35+
import org.springframework.boot.jackson.autoconfigure.JsonMapperBuilderCustomizer;
36+
import org.springframework.boot.jdbc.autoconfigure.DataSourceProperties;
3837
import org.springframework.context.annotation.Bean;
3938
import org.springframework.context.annotation.ComponentScan;
4039
import org.springframework.context.annotation.Configuration;
@@ -46,11 +45,12 @@
4645
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
4746
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
4847
import org.springframework.web.servlet.view.InternalResourceViewResolver;
48+
import tools.jackson.datatype.joda.JodaModule;
4949

5050
import javax.sql.DataSource;
5151

52-
import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
53-
import static com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS;
52+
import static tools.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
53+
import static tools.jackson.databind.cfg.DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS;
5454

5555
/**
5656
* Configuration and beans of Spring Framework.
@@ -194,14 +194,14 @@ public void addResourceHandlers(final ResourceHandlerRegistry registry) {
194194
// -------------------------------------------------------------------------
195195

196196
@Bean
197-
public Jackson2ObjectMapperBuilderCustomizer jacksonCustomizer() {
197+
public JsonMapperBuilderCustomizer jacksonCustomizer() {
198198
return builder -> {
199199
// default is true
200-
builder.featuresToDisable(WRITE_DATES_AS_TIMESTAMPS);
200+
builder.disable(WRITE_DATES_AS_TIMESTAMPS);
201201
// if the client sends unknown props, just ignore them instead of failing
202-
builder.featuresToDisable(FAIL_ON_UNKNOWN_PROPERTIES);
202+
builder.disable(FAIL_ON_UNKNOWN_PROPERTIES);
203203
// we still use joda DateTime...
204-
builder.modulesToInstall(new JodaModule());
204+
builder.addModule(new JodaModule());
205205
};
206206
}
207207
}

src/main/java/de/rwth/idsg/steve/ocpp/soap/ClientProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
import org.apache.cxf.transport.http.HTTPConduit;
2727
import org.apache.cxf.ws.addressing.WSAddressingFeature;
2828
import org.jetbrains.annotations.Nullable;
29-
import org.springframework.boot.autoconfigure.web.ServerProperties;
3029
import org.springframework.boot.web.server.Ssl;
30+
import org.springframework.boot.web.server.autoconfigure.ServerProperties;
3131
import org.springframework.stereotype.Component;
3232
import org.springframework.util.StringUtils;
3333

src/main/java/de/rwth/idsg/steve/ocpp/ws/JsonObjectMapper.java

Lines changed: 31 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,20 @@
1919
package de.rwth.idsg.steve.ocpp.ws;
2020

2121
import com.fasterxml.jackson.annotation.JsonInclude;
22-
import com.fasterxml.jackson.databind.AnnotationIntrospector;
23-
import com.fasterxml.jackson.databind.ObjectMapper;
24-
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
25-
import com.fasterxml.jackson.datatype.joda.JodaModule;
26-
import com.fasterxml.jackson.module.jakarta.xmlbind.JakartaXmlBindAnnotationIntrospector;
2722
import de.rwth.idsg.steve.ocpp.ws.custom.CustomStringModule;
2823
import de.rwth.idsg.steve.ocpp.ws.ocpp12.Ocpp12JacksonModule;
2924
import de.rwth.idsg.steve.ocpp.ws.ocpp15.Ocpp15JacksonModule;
3025
import de.rwth.idsg.steve.ocpp.ws.ocpp16.Ocpp16JacksonModule;
26+
import tools.jackson.databind.AnnotationIntrospector;
27+
import tools.jackson.databind.ObjectMapper;
28+
import tools.jackson.databind.introspect.JacksonAnnotationIntrospector;
29+
import tools.jackson.databind.json.JsonMapper;
30+
import tools.jackson.datatype.joda.JodaModule;
31+
import tools.jackson.module.jakarta.xmlbind.JakartaXmlBindAnnotationIntrospector;
3132

32-
import static com.fasterxml.jackson.core.JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN;
33-
import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES;
34-
import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
33+
import static tools.jackson.core.StreamWriteFeature.WRITE_BIGDECIMAL_AS_PLAIN;
34+
import static tools.jackson.databind.DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES;
35+
import static tools.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
3536

3637
/**
3738
* Because ObjectMapper can and should be reused, if config does not change after init.
@@ -45,34 +46,30 @@ public enum JsonObjectMapper {
4546
private final ObjectMapper mapper;
4647

4748
JsonObjectMapper() {
48-
mapper = new ObjectMapper();
49-
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
50-
51-
// OCPP messages contain some mandatory primitive fields (like transactionId), that are not allowed
52-
// to be null. any misinterpretation/mapping of these fields like "null -> 0" is a mistake.
53-
//
54-
// true story: while testing with abusive-charge-point, it sends stopTransactions where transactionId=null
55-
// in communication flows, where a startTransaction before causes an Exception and we cannot send a regular
56-
// response with a transactionId, but an error message. if we do not fail early, it will fail at the database
57-
// level which we want to prevent.
58-
mapper.configure(FAIL_ON_NULL_FOR_PRIMITIVES, true);
59-
60-
mapper.configure(WRITE_BIGDECIMAL_AS_PLAIN, true);
61-
62-
mapper.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);
63-
64-
mapper.registerModule(new CustomStringModule());
65-
mapper.registerModule(new Ocpp12JacksonModule());
66-
mapper.registerModule(new Ocpp15JacksonModule());
67-
mapper.registerModule(new Ocpp16JacksonModule());
68-
mapper.registerModule(new JodaModule());
69-
70-
mapper.setAnnotationIntrospector(
49+
mapper = JsonMapper.builder()
50+
.changeDefaultPropertyInclusion(incl -> incl.withValueInclusion(JsonInclude.Include.NON_NULL))
51+
// OCPP messages contain some mandatory primitive fields (like transactionId), that are not allowed
52+
// to be null. any misinterpretation/mapping of these fields like "null -> 0" is a mistake.
53+
//
54+
// true story: while testing with abusive-charge-point, it sends stopTransactions where transactionId=null
55+
// in communication flows, where a startTransaction before causes an Exception and we cannot send a regular
56+
// response with a transactionId, but an error message. if we do not fail early, it will fail at the database
57+
// level which we want to prevent.
58+
.enable(FAIL_ON_NULL_FOR_PRIMITIVES)
59+
.enable(WRITE_BIGDECIMAL_AS_PLAIN)
60+
.disable(FAIL_ON_UNKNOWN_PROPERTIES)
61+
.addModule(new CustomStringModule())
62+
.addModule(new Ocpp12JacksonModule())
63+
.addModule(new Ocpp15JacksonModule())
64+
.addModule(new Ocpp16JacksonModule())
65+
.addModule(new JodaModule())
66+
.annotationIntrospector(
7167
AnnotationIntrospector.pair(
72-
new JacksonAnnotationIntrospector(),
73-
new JakartaXmlBindAnnotationIntrospector(mapper.getTypeFactory())
68+
new JacksonAnnotationIntrospector(),
69+
new JakartaXmlBindAnnotationIntrospector()
7470
)
75-
);
71+
)
72+
.build();
7673
}
7774

7875
public ObjectMapper getMapper() {

src/main/java/de/rwth/idsg/steve/ocpp/ws/custom/CustomStringModule.java

Lines changed: 21 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,21 @@
1818
*/
1919
package de.rwth.idsg.steve.ocpp.ws.custom;
2020

21-
import com.fasterxml.jackson.core.JsonGenerator;
22-
import com.fasterxml.jackson.core.JsonParser;
23-
import com.fasterxml.jackson.core.Version;
24-
import com.fasterxml.jackson.databind.DeserializationContext;
25-
import com.fasterxml.jackson.databind.JavaType;
26-
import com.fasterxml.jackson.databind.JsonMappingException;
27-
import com.fasterxml.jackson.databind.JsonNode;
28-
import com.fasterxml.jackson.databind.SerializerProvider;
29-
import com.fasterxml.jackson.databind.deser.std.StringDeserializer;
30-
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
31-
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
32-
import com.fasterxml.jackson.databind.module.SimpleModule;
33-
import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer;
3421
import org.owasp.encoder.Encode;
35-
36-
import java.io.IOException;
37-
import java.io.Serial;
38-
import java.lang.reflect.Type;
22+
import tools.jackson.core.JacksonException;
23+
import tools.jackson.core.JsonGenerator;
24+
import tools.jackson.core.JsonParser;
25+
import tools.jackson.core.Version;
26+
import tools.jackson.databind.DatabindException;
27+
import tools.jackson.databind.DeserializationContext;
28+
import tools.jackson.databind.JavaType;
29+
import tools.jackson.databind.SerializationContext;
30+
import tools.jackson.databind.deser.jdk.StringDeserializer;
31+
import tools.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
32+
import tools.jackson.databind.jsontype.TypeSerializer;
33+
import tools.jackson.databind.module.SimpleModule;
34+
import tools.jackson.databind.ser.jdk.StringSerializer;
35+
import tools.jackson.databind.ser.std.StdScalarSerializer;
3936

4037
/**
4138
* @author Sevket Goekay <sevketgokay@gmail.com>
@@ -51,42 +48,33 @@ public CustomStringModule() {
5148
}
5249

5350
/**
54-
* Since {@link com.fasterxml.jackson.databind.ser.std.StringSerializer} is marked as final, its contents are
55-
* copied here (and adjusted as needed).
51+
* Since {@link StringSerializer} is marked as final, its contents are copied here (and adjusted as needed).
5652
*/
5753
private static class CustomStringSerializer extends StdScalarSerializer<Object> {
5854

59-
@Serial
60-
private static final long serialVersionUID = 1L;
61-
6255
public CustomStringSerializer() {
6356
super(String.class, false);
6457
}
6558

6659
@Override
67-
public boolean isEmpty(SerializerProvider prov, Object value) {
60+
public boolean isEmpty(SerializationContext prov, Object value) {
6861
String str = (String) value;
6962
return str.isEmpty();
7063
}
7164

7265
@Override
73-
public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
66+
public void serialize(Object value, JsonGenerator gen, SerializationContext provider) throws JacksonException {
7467
gen.writeString(objectToString(value));
7568
}
7669

7770
@Override
78-
public final void serializeWithType(Object value, JsonGenerator gen, SerializerProvider provider,
79-
TypeSerializer typeSer) throws IOException {
71+
public final void serializeWithType(Object value, JsonGenerator gen, SerializationContext provider,
72+
TypeSerializer typeSer) throws JacksonException {
8073
gen.writeString(objectToString(value));
8174
}
8275

8376
@Override
84-
public JsonNode getSchema(SerializerProvider provider, Type typeHint) {
85-
return createSchemaNode("string", true);
86-
}
87-
88-
@Override
89-
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException {
77+
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws DatabindException {
9078
visitStringFormat(visitor, typeHint);
9179
}
9280

@@ -97,11 +85,8 @@ private static String objectToString(Object value) {
9785

9886
private static class CustomStringDeserializer extends StringDeserializer {
9987

100-
@Serial
101-
private static final long serialVersionUID = 1L;
102-
10388
@Override
104-
public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
89+
public String deserialize(JsonParser p, DeserializationContext ctxt) throws JacksonException {
10590
String val = super.deserialize(p, ctxt);
10691
return Encode.forHtml(val);
10792
}

0 commit comments

Comments
 (0)