Skip to content
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
9 changes: 8 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,15 @@
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<artifactId>hibernate-validator-bom</artifactId>
<version>9.0.1.Final</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>jakarta.annotation</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@
import org.springdoc.core.properties.SwaggerUiOAuthProperties;
import org.springdoc.webmvc.core.configuration.SpringDocWebMvcConfiguration;
import org.springdoc.webmvc.ui.SwaggerConfig;
import org.springdoc.webmvc.ui.SwaggerUiHome;
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.Import;

import java.util.List;
Expand All @@ -46,7 +48,10 @@
* @since 15.09.2022
*/
@Configuration
@ComponentScan(basePackages = {"org.springdoc"})
@ComponentScan(
basePackages = {"org.springdoc"},
// exclude because SwaggerUiHome's root redirect clashes with our own RootRedirectController
excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = SwaggerUiHome.class))
@Import({
SpringDocConfiguration.class,
SpringDocWebMvcConfiguration.class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
Expand Down Expand Up @@ -327,7 +326,9 @@ public void test12() throws Exception {
.contentType(MediaType.APPLICATION_JSON)))
.hasStatusOk();

verify(ocppTagsService).updateOcppTag(eq(form));
var captor = ArgumentCaptor.forClass(OcppTagForm.class);
verify(ocppTagsService).updateOcppTag(captor.capture());
assertThat(captor.getValue()).usingRecursiveComparison().isEqualTo(form);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public static class Paths {
private final String timeZoneId;
private final String steveVersion;
private final @Nullable String gitDescribe;
private final ApplicationProfile profile;
private final String profile;
private final Ocpp ocpp;
private final Auth auth;
private final WebApi webApi;
Expand Down
4 changes: 4 additions & 0 deletions steve-ocpp-transport-websocket/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
<artifactId>jakarta.websocket-client-api</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>jetty-websocket-jetty-api</artifactId>
</dependency>
Comment on lines +36 to +39
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

🧩 Analysis chain

Jetty WS dependency: verify correct artifact and scope.

jetty-websocket-jetty-api may be insufficient at runtime; JettyRequestUpgradeStrategy typically needs Jetty WebSocket SERVER classes. Consider adding jetty-websocket-jetty-server (or mark API as provided if the server brings it).

Proposed addition if needed:

   <dependency>
     <groupId>org.eclipse.jetty.websocket</groupId>
     <artifactId>jetty-websocket-jetty-api</artifactId>
   </dependency>
+  <dependency>
+    <groupId>org.eclipse.jetty.websocket</groupId>
+    <artifactId>jetty-websocket-jetty-server</artifactId>
+  </dependency>

Web check to confirm exact artifacts for Spring 6.2 + Jetty 12:


🌐 Web query:

For Spring Framework 6.2.x and Jetty 12, which Jetty WebSocket artifacts are required at runtime when using org.springframework.web.socket.server.jetty.JettyRequestUpgradeStrategy?

💡 Result:

Short answer — include Jetty's WebSocket API + server implementation for Jetty 12 (and the Jakarta WebSocket implementation if you rely on the standard jakarta.websocket API). In practice add these runtime artifacts:

  • org.eclipse.jetty.websocket:jetty-websocket-jetty-api. [1]
  • org.eclipse.jetty.websocket:jetty-websocket-jetty-server (the server implementation). [1]
  • If you use the standard Jakarta WebSocket API endpoints (jakarta.websocket), also include jakarta.websocket:jakarta.websocket-api plus Jetty's Jakarta implementation: org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jakarta-server. [2]

Sources: Spring 6.2 API (JettyRequestUpgradeStrategy for Jetty 12 EE10). [3] Jetty 12 WebSocket docs. [1][2]

References
[1] Jetty WebSocket docs (Jetty 12).
[2] Jetty EE10 Jakarta WebSocket implementation docs.
[3] Spring Framework 6.2 Javadoc — JettyRequestUpgradeStrategy.


Add Jetty server WebSocket implementation (runtime)

File: steve-ocpp-transport-websocket/pom.xml

jetty-websocket-jetty-api is only the API; add the server implementation at runtime or mark the API as provided if your runtime supplies it. If using Jakarta WebSocket endpoints, also include jakarta.websocket:jakarta.websocket-api and org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jakarta-server.

   <dependency>
     <groupId>org.eclipse.jetty.websocket</groupId>
     <artifactId>jetty-websocket-jetty-api</artifactId>
   </dependency>
+  <dependency>
+    <groupId>org.eclipse.jetty.websocket</groupId>
+    <artifactId>jetty-websocket-jetty-server</artifactId>
+  </dependency>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>jetty-websocket-jetty-api</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>jetty-websocket-jetty-api</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>jetty-websocket-jetty-server</artifactId>
</dependency>
🤖 Prompt for AI Agents
In steve-ocpp-transport-websocket/pom.xml around lines 36 to 39, the POM
currently declares only the jetty-websocket-jetty-api (the API) which lacks a
runtime server implementation; either add the Jetty server implementation
dependency (e.g.,
org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jakarta-server) with
appropriate scope (runtime) or change the API dependency to
<scope>provided</scope> if your runtime supplies it, and if you use Jakarta
WebSocket endpoints also add jakarta.websocket:jakarta.websocket-api (and keep
the Jetty EE10 Jakarta server dependency) so the runtime has both API and server
implementation available.

<dependency>
<groupId>org.owasp.encoder</groupId>
<artifactId>encoder</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import org.springframework.web.socket.server.jetty.JettyRequestUpgradeStrategy;
import org.springframework.web.socket.server.support.DefaultHandshakeHandler;

import java.time.Duration;
Expand Down Expand Up @@ -62,12 +63,28 @@ public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {

OcppWebSocketHandshakeHandler handshakeHandler = new OcppWebSocketHandshakeHandler(
chargeBoxIdValidator,
new DefaultHandshakeHandler(),
createHandshakeHandler(),
Lists.newArrayList(ocpp16WebSocketEndpoint, ocpp15WebSocketEndpoint, ocpp12WebSocketEndpoint),
chargePointRegistrationService);

registry.addHandler(handshakeHandler.getDummyWebSocketHandler(), PATH_INFIX + "*")
.setHandshakeHandler(handshakeHandler)
.setAllowedOrigins("*");
}

/**
* https://docs.spring.io/spring-framework/reference/web/websocket/server.html#websocket-server-runtime-configurationCheck failure[checkstyle] src/main/java/de/rwth/idsg/steve/config/WebSocketConfiguration.java#L73 <com.puppycrawl.tools.checkstyle.checks.sizes.LineLengthCheck>Check failure: [checkstyle] src/main/java/de/rwth/idsg/steve/config/WebSocketConfiguration.java#L73 <com.puppycrawl.tools.checkstyle.checks.sizes.LineLengthCheck>Line is longer than 120 characters (found 121).build and run tests / checkstyleView detailsCode has alerts. Press enter to view.
*
* Otherwise, defaults come from {@link WebSocketConstants}
*/
private static DefaultHandshakeHandler createHandshakeHandler() {
JettyRequestUpgradeStrategy strategy = new JettyRequestUpgradeStrategy();

strategy.addWebSocketConfigurer(configurable -> {
configurable.setMaxTextMessageSize(MAX_MSG_SIZE);
configurable.setIdleTimeout(IDLE_TIMEOUT);
});

return new DefaultHandshakeHandler(strategy);
}
}
1 change: 0 additions & 1 deletion steve-ocpp/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>jakarta.xml.soap</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

Expand All @@ -48,10 +46,4 @@ public InternalResourceViewResolver urlBasedViewResolver() {
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("static/");
}

@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/manager/signin").setViewName("signin");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,22 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.rwth.idsg.steve;
package de.rwth.idsg.steve.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

/**
* @author Sevket Goekay <sevketgokay@gmail.com>
* @since 05.11.2015
* @since 17.09.2025
*/
public enum ApplicationProfile {
DEV,
TEST,
PROD;

public static ApplicationProfile fromName(String v) {
for (ApplicationProfile ap : ApplicationProfile.values()) {
if (ap.name().equalsIgnoreCase(v)) {
return ap;
}
}
throw new IllegalArgumentException(v);
}
@Controller
@RequestMapping("/")
public class RootRedirectController {

public boolean isProd() {
return this == PROD;
@GetMapping
public String redirectToManager() {
return "redirect:/manager";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,12 @@
*/
@Controller
@RequestMapping(value = "/manager")
public class SignOutController {
public class SignInOutController {

@GetMapping(value = "/signin")
public String signIn() {
return "signin";
}

@GetMapping(value = "/signout")
public String signOut(HttpServletRequest request, HttpServletResponse response) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import de.rwth.idsg.steve.SteveConfiguration;
import lombok.Getter;
import lombok.ToString;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.List;
Expand All @@ -31,6 +32,7 @@
*/
@Getter
@ToString
@Component
public class EndpointInfo {

private final ItemsWithInfo webInterface;
Expand Down
7 changes: 6 additions & 1 deletion steve/src/main/java/de/rwth/idsg/steve/Application.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
package de.rwth.idsg.steve;

import de.rwth.idsg.steve.config.WebConfig;
import de.rwth.idsg.steve.utils.LogFileRetriever;
import de.rwth.idsg.steve.utils.SteveConfigurationReader;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -36,11 +37,13 @@
public class Application {

private final SteveConfiguration config;
private final LogFileRetriever logFileRetriever;
private final JettyServer server;

public Application(SteveConfiguration config, LogFileRetriever logFileRetriever) {
this.config = config;
this.server = new JettyServer(config, logFileRetriever);
this.logFileRetriever = logFileRetriever;
this.server = new JettyServer(config);
}

public static void main(String[] args) throws Exception {
Expand Down Expand Up @@ -82,6 +85,7 @@ public static void main(String[] args) throws Exception {
}

public void start() throws Exception {
WebConfig.initialize(config, logFileRetriever);
server.start();
}
Comment on lines 87 to 90
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Ensure cleanup if start() fails

If server.start() (or initialize) throws, WebConfig.clear() should still run to avoid leaking static state when embedders don’t call stop().

-    public void start() throws Exception {
-        WebConfig.initialize(config, logFileRetriever);
-        server.start();
-    }
+    public void start() throws Exception {
+        try {
+            WebConfig.initialize(config, logFileRetriever);
+            server.start();
+        } catch (Exception e) {
+            try {
+                WebConfig.clear();
+            } catch (Exception suppressed) {
+                e.addSuppressed(suppressed);
+            }
+            throw e;
+        }
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public void start() throws Exception {
WebConfig.initialize(config, logFileRetriever);
server.start();
}
public void start() throws Exception {
try {
WebConfig.initialize(config, logFileRetriever);
server.start();
} catch (Exception e) {
try {
WebConfig.clear();
} catch (Exception suppressed) {
e.addSuppressed(suppressed);
}
throw e;
}
}
🤖 Prompt for AI Agents
In steve/src/main/java/de/rwth/idsg/steve/Application.java around lines 87 to
90, calling WebConfig.initialize(...) and server.start() can throw and currently
WebConfig.clear() won't run if start() fails; wrap the initialize/start sequence
in a try block and ensure WebConfig.clear() is invoked in a finally (or call
clear in the catch before rethrowing) so static state is cleaned on failure,
then rethrow the exception to preserve original behavior.


Expand All @@ -91,5 +95,6 @@ public void join() throws Exception {

public void stop() throws Exception {
server.stop();
WebConfig.clear();
}
Comment on lines 96 to 99
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Always clear WebConfig even if server.stop() throws

Run clear() in a finally block so static state is released even when Jetty shutdown fails.

-    public void stop() throws Exception {
-        server.stop();
-        WebConfig.clear();
-    }
+    public void stop() throws Exception {
+        try {
+            server.stop();
+        } finally {
+            WebConfig.clear();
+        }
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public void stop() throws Exception {
server.stop();
WebConfig.clear();
}
public void stop() throws Exception {
try {
server.stop();
} finally {
WebConfig.clear();
}
}
🤖 Prompt for AI Agents
In steve/src/main/java/de/rwth/idsg/steve/Application.java around lines 96 to
99, ensure WebConfig.clear() is always executed even if server.stop() throws by
moving the clear call into a finally block: call server.stop() inside a try
(handling or letting the exception propagate) and invoke WebConfig.clear()
inside the corresponding finally so static state is released regardless of
shutdown failures.

}
Loading
Loading