Skip to content

Commit 330fea4

Browse files
authored
Merge pull request #1820 from steve-community/1819-migrate-to-spring-boot-refactor-as-preparation
Prep for Spring Boot migration
2 parents 3ff3f14 + a351e3a commit 330fea4

18 files changed

+189
-410
lines changed

pom.xml

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,12 @@
518518
<groupId>org.springdoc</groupId>
519519
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
520520
<version>2.8.13</version>
521+
<exclusions>
522+
<exclusion>
523+
<artifactId>tomcat-embed-el</artifactId>
524+
<groupId>org.apache.tomcat.embed</groupId>
525+
</exclusion>
526+
</exclusions>
521527
</dependency>
522528

523529
<dependency>
@@ -529,11 +535,21 @@
529535
<groupId>com.github.steve-community</groupId>
530536
<artifactId>ocpp-jaxb</artifactId>
531537
<version>0.0.9</version>
538+
<exclusions>
539+
<exclusion>
540+
<artifactId>jakarta.activation</artifactId>
541+
<groupId>com.sun.activation</groupId>
542+
</exclusion>
543+
<exclusion>
544+
<artifactId>jakarta.activation-api</artifactId>
545+
<groupId>jakarta.activation</groupId>
546+
</exclusion>
547+
</exclusions>
532548
</dependency>
533549
<dependency>
534-
<groupId>com.sun.mail</groupId>
535-
<artifactId>jakarta.mail</artifactId>
536-
<version>2.0.2</version>
550+
<groupId>jakarta.mail</groupId>
551+
<artifactId>jakarta.mail-api</artifactId>
552+
<version>2.1.3</version>
537553
</dependency>
538554
<dependency>
539555
<groupId>org.jetbrains</groupId>

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

Lines changed: 40 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -19,36 +19,25 @@
1919
package de.rwth.idsg.steve;
2020

2121
import lombok.extern.slf4j.Slf4j;
22+
import org.eclipse.jetty.ee10.webapp.WebAppContext;
2223
import org.eclipse.jetty.http.HttpScheme;
2324
import org.eclipse.jetty.http.HttpVersion;
24-
import org.eclipse.jetty.server.Connector;
2525
import org.eclipse.jetty.server.ForwardedRequestCustomizer;
26+
import org.eclipse.jetty.server.Handler;
2627
import org.eclipse.jetty.server.HttpConfiguration;
2728
import org.eclipse.jetty.server.HttpConnectionFactory;
2829
import org.eclipse.jetty.server.SecureRequestCustomizer;
2930
import org.eclipse.jetty.server.Server;
3031
import org.eclipse.jetty.server.ServerConnector;
3132
import org.eclipse.jetty.server.SslConnectionFactory;
33+
import org.eclipse.jetty.server.handler.gzip.GzipHandler;
3234
import org.eclipse.jetty.util.ssl.SslContextFactory;
3335
import org.eclipse.jetty.util.thread.QueuedThreadPool;
3436
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
37+
import org.springframework.core.io.ClassPathResource;
3538

36-
import java.net.DatagramSocket;
37-
import java.net.Inet4Address;
38-
import java.net.InetAddress;
39-
import java.net.InetSocketAddress;
40-
import java.net.NetworkInterface;
41-
import java.net.Socket;
42-
import java.util.ArrayList;
43-
import java.util.Arrays;
44-
import java.util.Collection;
45-
import java.util.Collections;
46-
import java.util.Enumeration;
47-
import java.util.HashSet;
48-
import java.util.List;
49-
import java.util.Set;
39+
import java.io.IOException;
5040
import java.util.concurrent.TimeUnit;
51-
import java.util.stream.Collectors;
5241

5342
import static de.rwth.idsg.steve.SteveConfiguration.CONFIG;
5443

@@ -60,18 +49,21 @@
6049
public class JettyServer {
6150

6251
private Server server;
63-
private SteveAppContext steveAppContext;
6452

6553
private static final int MIN_THREADS = 4;
6654
private static final int MAX_THREADS = 50;
6755

6856
private static final long STOP_TIMEOUT = TimeUnit.SECONDS.toMillis(5);
6957
private static final long IDLE_TIMEOUT = TimeUnit.MINUTES.toMillis(1);
7058

59+
// scan all jars in the classpath for ServletContainerInitializers
60+
// (e.g. Spring's WebApplicationInitializer)
61+
private static final String SCAN_PATTERN = ".*\\.jar$|.*/classes/.*";
62+
7163
/**
7264
* A fully configured Jetty Server instance
7365
*/
74-
private void prepare() {
66+
private void prepare() throws IOException {
7567

7668
// === jetty.xml ===
7769
// Setup Threadpool
@@ -114,8 +106,7 @@ private void prepare() {
114106
server.addConnector(httpsConnector(httpConfig));
115107
}
116108

117-
steveAppContext = new SteveAppContext();
118-
server.setHandler(steveAppContext.getHandlers());
109+
server.setHandler(getWebApp());
119110
}
120111

121112
private ServerConnector httpConnector(HttpConfiguration httpConfig) {
@@ -149,6 +140,35 @@ private ServerConnector httpsConnector(HttpConfiguration httpConfig) {
149140
return https;
150141
}
151142

143+
private Handler getWebApp() throws IOException {
144+
var webAppContext = new WebAppContext();
145+
webAppContext.setContextPath(CONFIG.getContextPath());
146+
webAppContext.setBaseResourceAsString(new ClassPathResource("webapp").getURI().toString());
147+
148+
// if during startup an exception happens, do not swallow it, throw it
149+
webAppContext.setThrowUnavailableOnStartupException(true);
150+
151+
// Disable directory listings if no index.html is found.
152+
webAppContext.setInitParameter("org.eclipse.jetty.servlet.Default.dirAllowed", "false");
153+
154+
// Crucial for Spring's WebApplicationInitializer to be discovered
155+
// and for the DispatcherServlet to be initialized.
156+
// It tells Jetty to scan for classes implementing WebApplicationInitializer.
157+
// The pattern ensures that Jetty finds the Spring classes in the classpath.
158+
//
159+
// https://jetty.org/docs/jetty/12.1/programming-guide/maven-jetty/jetty-maven-plugin.html
160+
// https://jetty.org/docs/jetty/12.1/operations-guide/annotations/index.html#og-container-include-jar-pattern
161+
webAppContext.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", SCAN_PATTERN);
162+
163+
if (CONFIG.getJetty().isGzipEnabled()) {
164+
// Wraps the whole web app in a gzip handler to make Jetty return compressed content
165+
// http://www.eclipse.org/jetty/documentation/current/gzip-filter.html
166+
return new GzipHandler(webAppContext);
167+
} else {
168+
return webAppContext;
169+
}
170+
}
171+
152172
/**
153173
* Starts the Jetty Server instance
154174
*/
@@ -157,8 +177,6 @@ public void start() throws Exception {
157177

158178
if (server != null) {
159179
server.start();
160-
steveAppContext.configureWebSocket();
161-
populateEndpointInfo();
162180
}
163181
}
164182

@@ -176,124 +194,4 @@ public void stop() throws Exception {
176194
server.stop();
177195
}
178196
}
179-
180-
public boolean isStarted() {
181-
return server != null && server.isStarted();
182-
}
183-
184-
public void populateEndpointInfo() {
185-
List<String> list = getConnectorPathList();
186-
187-
// EndpointInfo info = EndpointInfo.INSTANCE;
188-
//
189-
// info.getWebInterface().setData(buildList(list, false));
190-
// info.getOcppSoap().setData(buildList(list, false));
191-
// info.getOcppWebSocket().setData(buildList(list, true));
192-
}
193-
194-
private List<String> getConnectorPathList() {
195-
if (server == null) {
196-
return Collections.emptyList();
197-
}
198-
199-
return Arrays.stream(server.getConnectors())
200-
.map(JettyServer::getConnectorPath)
201-
.flatMap(Collection::stream)
202-
.collect(Collectors.toList());
203-
}
204-
205-
private static List<String> getConnectorPath(Connector c) {
206-
ServerConnector sc = (ServerConnector) c;
207-
208-
final String prefix;
209-
if (sc.getDefaultConnectionFactory() instanceof SslConnectionFactory) {
210-
prefix = "https";
211-
} else {
212-
prefix = "http";
213-
}
214-
215-
Set<String> ips = new HashSet<>();
216-
String host = sc.getHost();
217-
if (host == null || host.equals("0.0.0.0")) {
218-
ips.addAll(getPossibleIpAddresses());
219-
} else {
220-
ips.add(host);
221-
}
222-
223-
String layout = "%s://%s:%d" + CONFIG.getContextPath();
224-
225-
return ips.stream()
226-
.map(k -> String.format(layout, prefix, k, sc.getPort()))
227-
.collect(Collectors.toList());
228-
}
229-
230-
private List<String> buildList(List<String> list, boolean replaceHttp) {
231-
return list.stream()
232-
.map(s -> getElementPrefix(s, replaceHttp))
233-
.collect(Collectors.toList());
234-
}
235-
236-
private String getElementPrefix(String str, boolean replaceHttp) {
237-
if (replaceHttp) {
238-
return str.replaceFirst("http", "ws");
239-
} else {
240-
return str;
241-
}
242-
}
243-
244-
/**
245-
* Uses different APIs to find out the IP of this machine.
246-
*/
247-
private static List<String> getPossibleIpAddresses() {
248-
final String host = "treibhaus.informatik.rwth-aachen.de";
249-
final List<String> ips = new ArrayList<>();
250-
251-
try {
252-
ips.add(InetAddress.getLocalHost().getHostAddress());
253-
} catch (Exception e) {
254-
// fail silently
255-
}
256-
257-
try {
258-
Socket socket = new Socket();
259-
socket.connect(new InetSocketAddress(host, 80));
260-
ips.add(socket.getLocalAddress().getHostAddress());
261-
} catch (Exception e) {
262-
// fail silently
263-
}
264-
265-
// https://stackoverflow.com/a/38342964
266-
try (DatagramSocket socket = new DatagramSocket()) {
267-
socket.connect(InetAddress.getByName("8.8.8.8"), 10002);
268-
ips.add(socket.getLocalAddress().getHostAddress());
269-
} catch (Exception e) {
270-
// fail silently
271-
}
272-
273-
// https://stackoverflow.com/a/20418809
274-
try {
275-
for (Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements();) {
276-
NetworkInterface iface = ifaces.nextElement();
277-
for (Enumeration<InetAddress> inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements();) {
278-
InetAddress inetAddr = inetAddrs.nextElement();
279-
if (!inetAddr.isLoopbackAddress() && (inetAddr instanceof Inet4Address)) {
280-
ips.add(inetAddr.getHostAddress());
281-
}
282-
}
283-
}
284-
285-
} catch (Exception e) {
286-
// fail silently
287-
}
288-
289-
ips.removeIf("0.0.0.0"::equals);
290-
291-
if (ips.isEmpty()) {
292-
// Well, we failed to read from system, fall back to application.properties.
293-
// Better than nothing
294-
ips.add(CONFIG.getJetty().getServerHost());
295-
}
296-
297-
return ips;
298-
}
299197
}

0 commit comments

Comments
 (0)