Skip to content

Commit 4adafd8

Browse files
authored
Merge pull request #434 from roycpro/jakarta-migration
Jakarta/Tomcat migration
2 parents d1d9b81 + 0304c40 commit 4adafd8

File tree

186 files changed

+9845
-9301
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

186 files changed

+9845
-9301
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ gradle unitTests
7373

7474
#### Integration Tests
7575

76-
Integration tests require an installation of Tomcat (the Archiver Appliance only support up to version 9).
76+
Integration tests require an installation of Tomcat (the Archiver Appliance only support up to version 11).
7777
The environment variable `TOMCAT_HOME` where a "conf" folder exists must then be set.
7878

7979
To run tests requiring a local installation of [EPICS](https://epics-controls.org/).
@@ -120,12 +120,12 @@ For a quick deploy of a single appliance:
120120

121121
1. Download the latest [release](https://github.com/archiver-appliance/epicsarchiverap/releases)
122122
and unpack the war files to a folder "archiver".
123-
2. In the same folder, download a release of [tomcat 9](https://tomcat.apache.org/download-90.cgi) without unpacking.
123+
2. In the same folder, download a release of [tomcat 11](https://tomcat.apache.org/download-11.cgi) without unpacking.
124124
3. Copy the quickstart.sh file from the extracted release to the folder.
125125
4. Run the quickstart script:
126126

127127
```bash
128-
./quickstart.sh apache-tomcat-9.*.tar.gz
128+
./quickstart.sh apache-tomcat-11.*.tar.gz
129129
```
130130

131131
For more information see the [quickstart documentation](https://epicsarchiver.readthedocs.io/en/latest/sysadmin/quickstart.html). For more complicated

build.gradle.kts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ dependencies {
9696
viewer("archiver-appliance:svg_viewer:v1.2.1@zip")
9797

9898
// Provided by Servlet Container (e.g., Tomcat)
99-
implementation("org.apache.tomcat:tomcat-servlet-api:9.0.74")
99+
implementation("org.apache.tomcat:tomcat-servlet-api:11.0.12")
100100

101101
// Core Libraries
102102
implementation("org.epics:jca:2.4.7")
@@ -106,15 +106,17 @@ dependencies {
106106
implementation("org.python:jython-standalone:2.7.3")
107107
implementation("com.google.protobuf:protobuf-java:3.23.0")
108108
implementation("org.phoebus:core-pva:5.0.2")
109+
implementation("jakarta.servlet:jakarta.servlet-api:6.0.0")
109110

110111
// Apache Commons
111112
implementation("commons-codec:commons-codec:1.15")
112-
implementation("commons-fileupload:commons-fileupload:1.6.0")
113+
implementation("org.apache.commons:commons-fileupload2-jakarta-servlet6:2.0.0-M3")
113114
implementation("commons-io:commons-io:2.14.0")
114115
implementation("org.apache.commons:commons-lang3:3.18.0")
115116
implementation("org.apache.commons:commons-math3:3.6.1")
116117
implementation("commons-validator:commons-validator:1.7")
117118

119+
118120
// HTTP Clients
119121
implementation("org.apache.httpcomponents:httpclient:4.5.14")
120122
implementation("org.apache.httpcomponents:httpcore:4.4.16")
@@ -146,7 +148,7 @@ dependencies {
146148
testImplementation(files("lib/test/BPLTaglets.jar"))
147149
testImplementation(project.files("lib/pbrawclient-0.2.1.jar"))
148150
testImplementation(":pbrawclient:0.2.1")
149-
testImplementation("org.apache.tomcat:tomcat-servlet-api:9.0.74")
151+
testImplementation("org.apache.tomcat:tomcat-servlet-api:11.0.12")
150152
}
151153

152154
// =================================================================
@@ -635,7 +637,7 @@ configure<SpotlessExtension> {
635637
removeUnusedImports()
636638
// apply a specific flavor of google-java-format
637639
palantirJavaFormat()
638-
importOrder("", "java|javax", "#")
640+
importOrder("", "java|javax|jakarta", "#")
639641
// fix formatting of type annotations
640642
formatAnnotations()
641643
}

docker/Dockerfile.dev

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,11 @@ RUN cd base && make -j$(nproc)
4747
# Stage: Download and extract Tomcat
4848
# This stage is responsible only for getting the Tomcat binaries.
4949
FROM --platform=$BUILDPLATFORM debian:bookworm-slim AS tomcat-download-extract
50-
ARG TOMCAT_VERSION=9.0.79
50+
ARG TOMCAT_VERSION=11.0.12
5151
SHELL ["/bin/bash", "-c"]
5252
RUN apt-get update && apt-get install -y --no-install-recommends wget ca-certificates \
5353
&& mkdir /tomcat \
54-
&& wget -q --show-progress "https://archive.apache.org/dist/tomcat/tomcat-9/v${TOMCAT_VERSION}/bin/apache-tomcat-${TOMCAT_VERSION}.tar.gz" -O /tmp/tomcat.tar.gz \
54+
&& wget -q --show-progress "https://archive.apache.org/dist/tomcat/tomcat-11/v${TOMCAT_VERSION}/bin/apache-tomcat-${TOMCAT_VERSION}.tar.gz" -O /tmp/tomcat.tar.gz \
5555
# Use --strip-components=1 to avoid the nested apache-tomcat-* directory
5656
&& tar -xf /tmp/tomcat.tar.gz -C /tomcat --strip-components=1 \
5757
&& rm /tmp/tomcat.tar.gz \

docs/docs/source/developer/details.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ These are the prerequisites for the EPICS archiver appliance.
5050
systems. If using RedHat, we should aim for RedHat 6.1.
5151
- JDK 1.16+ - definitely the 64 bit version for production systems. We
5252
need the JDK, **not** the JRE.
53-
- A recent version of Tomcat 9.x; preferably `apache-tomcat-9.0.20` or
53+
- A recent version of Tomcat 11.x; preferably `apache-tomcat-11.0.12` or
5454
later.
5555
- The management UI works best with a recent version of Firefox or
5656
Chrome.

docs/docs/source/samples/quickstart.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ fi
148148
mkdir quickstart_tomcat
149149
tar -C quickstart_tomcat -zxf "${TOMCAT_DISTRIBUTION}"
150150
cd quickstart_tomcat
151-
# eg. "apache-tomcat-9.0.20"
151+
# eg. "apache-tomcat-11.0.12"
152152
TOMCAT_VERSION_FOLDER=`ls -d apache-tomca* | head -1`
153153

154154
# Make sure we have a valid server.xml

docs/docs/source/sysadmin/installguide.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -443,12 +443,12 @@ argument that identifies the parent folder of the individual Tomcat
443443
containers.
444444

445445
```bash
446-
$ export TOMCAT_HOME=/arch/single_machine_install/tomcats/apache-tomcat-9.0.20
446+
$ export TOMCAT_HOME=/arch/single_machine_install/tomcats/apache-tomcat-11.0.12
447447
$ export ARCHAPPL_APPLIANCES=/arch/single_machine_install/sample_appliances.xml
448448
$ export ARCHAPPL_MYIDENTITY=appliance0
449449
$ ./install_scripts/deployMultipleTomcats.py /arch/single_machine_install/tomcats
450450
Using
451-
tomcat installation at /arch/single_machine_install/tomcats/apache-tomcat-9.0.20
451+
tomcat installation at /arch/single_machine_install/tomcats/apache-tomcat-11.0.12
452452
to generate deployments for appliance appliance0
453453
using configuration info from /arch/single_machine_install/sample_appliances.xml
454454
into folder /arch/single_machine_install/tomcats

docs/docs/source/sysadmin/quickstart.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ Here are the steps to get started quickly.
6565
5. Run the script like so
6666

6767
```bash
68-
$ ./quickstart.sh apache-tomcat-9.0.20.tar.gz
68+
$ ./quickstart.sh apache-tomcat-11.0.12.tar.gz
6969
```
7070

7171
6. This should start the Tomcat process in the foreground. Once all the
Lines changed: 67 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
package org.epics.archiverappliance.common;
22

3+
import com.hazelcast.projection.Projection;
4+
import com.hazelcast.query.Predicates;
5+
import org.epics.archiverappliance.config.ConfigService;
6+
import org.epics.archiverappliance.config.PVNames;
7+
import org.epics.archiverappliance.config.PVTypeInfo;
8+
39
import java.io.IOException;
410
import java.io.Serializable;
511
import java.util.Arrays;
@@ -8,75 +14,80 @@
814
import java.util.Map;
915
import java.util.stream.Collectors;
1016

11-
import javax.servlet.http.HttpServletRequest;
12-
13-
import org.epics.archiverappliance.config.ConfigService;
14-
import org.epics.archiverappliance.config.PVNames;
15-
import org.epics.archiverappliance.config.PVTypeInfo;
16-
import org.epics.archiverappliance.mgmt.bpl.PVsMatchingParameter;
17-
18-
import com.hazelcast.projection.Projection;
19-
import com.hazelcast.query.Predicates;
20-
2117
/*
2218
* Use a Hz query to determine the PV's that are being archived in this cluster.
2319
*/
2420
public class ArchivedPVsInList {
2521

26-
private static record OnlyFields ( String pvName, String[] archiveFields ) implements Serializable {};
22+
private static record OnlyFields(String pvName, String[] archiveFields) implements Serializable {}
23+
;
24+
2725
private static class FieldsProjection implements Projection<Map.Entry<String, PVTypeInfo>, OnlyFields> {
2826
@Override
2927
public OnlyFields transform(Map.Entry<String, PVTypeInfo> entry) {
3028
String pvName = entry.getKey();
3129
PVTypeInfo value = entry.getValue();
32-
return new OnlyFields(pvName, value.getArchiveFields()) ;
30+
return new OnlyFields(pvName, value.getArchiveFields());
3331
}
3432
}
3533

36-
public static List<String> getArchivedPVs(List<String> pvNames, ConfigService configService) throws IOException {
37-
record PVNameParts(String pvName, String plainPVName, boolean isField, String fieldName){};
38-
LinkedList<PVNameParts> pvnps = new LinkedList<>();
39-
for(String pvName : pvNames) {
40-
boolean isField = PVNames.isFieldOrFieldModifier(pvName);
41-
String plainPVName = PVNames.channelNamePVName(pvName);
42-
String fieldName = PVNames.getFieldName(pvName);
43-
String realName = configService.getRealNameForAlias(plainPVName);
44-
if(realName != null) {
45-
plainPVName = realName;
46-
}
47-
pvnps.add(new PVNameParts(pvName, plainPVName, isField, fieldName));
48-
}
34+
public static List<String> getArchivedPVs(List<String> pvNames, ConfigService configService) throws IOException {
35+
record PVNameParts(String pvName, String plainPVName, boolean isField, String fieldName) {}
36+
;
37+
LinkedList<PVNameParts> pvnps = new LinkedList<>();
38+
for (String pvName : pvNames) {
39+
boolean isField = PVNames.isFieldOrFieldModifier(pvName);
40+
String plainPVName = PVNames.channelNamePVName(pvName);
41+
String fieldName = PVNames.getFieldName(pvName);
42+
String realName = configService.getRealNameForAlias(plainPVName);
43+
if (realName != null) {
44+
plainPVName = realName;
45+
}
46+
pvnps.add(new PVNameParts(pvName, plainPVName, isField, fieldName));
47+
}
48+
49+
Map<String, String[]> pvFieldsForPVNames = configService
50+
.queryPVTypeInfos(
51+
Predicates.in(
52+
"__key",
53+
pvnps.stream()
54+
.map((x) -> x.pvName)
55+
.collect(Collectors.toList())
56+
.toArray(new String[0])),
57+
new FieldsProjection())
58+
.stream()
59+
.collect(Collectors.toMap(OnlyFields::pvName, OnlyFields::archiveFields));
4960

50-
Map<String, String[]> pvFieldsForPVNames = configService.queryPVTypeInfos(
51-
Predicates.in("__key", pvnps.stream().map((x) -> x.pvName).collect(Collectors.toList()).toArray(new String[0])),
52-
new FieldsProjection())
53-
.stream().collect(Collectors.toMap(OnlyFields::pvName, OnlyFields::archiveFields));
61+
Map<String, String[]> pvFieldsForPlainPVNames = configService
62+
.queryPVTypeInfos(
63+
Predicates.in(
64+
"__key",
65+
pvnps.stream()
66+
.map((x) -> x.plainPVName)
67+
.collect(Collectors.toList())
68+
.toArray(new String[0])),
69+
new FieldsProjection())
70+
.stream()
71+
.collect(Collectors.toMap(OnlyFields::pvName, OnlyFields::archiveFields));
5472

55-
Map<String, String[]> pvFieldsForPlainPVNames = configService.queryPVTypeInfos(
56-
Predicates.in("__key", pvnps.stream().map((x) -> x.plainPVName).collect(Collectors.toList()).toArray(new String[0])),
57-
new FieldsProjection())
58-
.stream().collect(Collectors.toMap(OnlyFields::pvName, OnlyFields::archiveFields));
59-
60-
String[] emptyFields = new String[0];
61-
LinkedList<String> archivedPVs = new LinkedList<String>();
62-
for(PVNameParts pvnp : pvnps) {
63-
if(pvnp.isField) {
64-
if(pvFieldsForPVNames.containsKey(pvnp.pvName)
65-
|| Arrays.asList(pvFieldsForPVNames.getOrDefault(pvnp.pvName, emptyFields)).contains(pvnp.fieldName)
66-
|| pvFieldsForPlainPVNames.containsKey(pvnp.pvName)
67-
|| Arrays.asList(pvFieldsForPlainPVNames.getOrDefault(pvnp.pvName, emptyFields)).contains(pvnp.fieldName)
68-
) {
69-
archivedPVs.add(pvnp.pvName);
70-
}
71-
} else {
72-
if(pvFieldsForPVNames.containsKey(pvnp.pvName)
73-
|| pvFieldsForPlainPVNames.containsKey(pvnp.pvName)
74-
) {
75-
archivedPVs.add(pvnp.pvName);
76-
}
77-
}
78-
}
79-
return archivedPVs;
80-
}
81-
73+
String[] emptyFields = new String[0];
74+
LinkedList<String> archivedPVs = new LinkedList<String>();
75+
for (PVNameParts pvnp : pvnps) {
76+
if (pvnp.isField) {
77+
if (pvFieldsForPVNames.containsKey(pvnp.pvName)
78+
|| Arrays.asList(pvFieldsForPVNames.getOrDefault(pvnp.pvName, emptyFields))
79+
.contains(pvnp.fieldName)
80+
|| pvFieldsForPlainPVNames.containsKey(pvnp.pvName)
81+
|| Arrays.asList(pvFieldsForPlainPVNames.getOrDefault(pvnp.pvName, emptyFields))
82+
.contains(pvnp.fieldName)) {
83+
archivedPVs.add(pvnp.pvName);
84+
}
85+
} else {
86+
if (pvFieldsForPVNames.containsKey(pvnp.pvName) || pvFieldsForPlainPVNames.containsKey(pvnp.pvName)) {
87+
archivedPVs.add(pvnp.pvName);
88+
}
89+
}
90+
}
91+
return archivedPVs;
92+
}
8293
}

src/main/org/epics/archiverappliance/common/BPLAction.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,23 @@
77
*******************************************************************************/
88
package org.epics.archiverappliance.common;
99

10-
import java.io.IOException;
11-
12-
import javax.servlet.http.HttpServletRequest;
13-
import javax.servlet.http.HttpServletResponse;
14-
1510
import org.epics.archiverappliance.config.ConfigService;
1611

12+
import java.io.IOException;
13+
import jakarta.servlet.http.HttpServletRequest;
14+
import jakarta.servlet.http.HttpServletResponse;
15+
1716
/**
18-
* A very simple struts like action for business processes.
17+
* A very simple struts like action for business processes.
1918
* Responses are typically JSON though this is not enforced.
2019
* We are not too far away from the servlet container here.
2120
* A handle to the configservice is passed in as part of the execute method.
22-
* The BPLAction is extected to handle all servlet container traffic like HTTP error codes etc.
21+
* The BPLAction is extected to handle all servlet container traffic like HTTP error codes etc.
2322
* If an exception is thrown, the servlet that calls BPLActions will send a Internal Server Error to the caller.
2423
* @author mshankar
2524
*
2625
*/
2726
public interface BPLAction {
28-
public void execute(HttpServletRequest req, HttpServletResponse resp, ConfigService configService) throws IOException;
27+
public void execute(HttpServletRequest req, HttpServletResponse resp, ConfigService configService)
28+
throws IOException;
2929
}

src/main/org/epics/archiverappliance/common/BasicDispatcher.java

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@
1616
import org.epics.archiverappliance.utils.ui.MimeTypeConstants;
1717
import org.json.simple.JSONObject;
1818

19-
import javax.servlet.http.HttpServletRequest;
20-
import javax.servlet.http.HttpServletResponse;
2119
import java.io.IOException;
2220
import java.io.PrintWriter;
2321
import java.util.HashMap;
2422
import java.util.Map;
23+
import jakarta.servlet.http.HttpServletRequest;
24+
import jakarta.servlet.http.HttpServletResponse;
2525

2626
/**
2727
* Glue code that is in all the BPL servlets.
@@ -31,10 +31,14 @@
3131
public class BasicDispatcher {
3232
private static final Logger logger = LogManager.getLogger(BasicDispatcher.class);
3333

34-
private BasicDispatcher() {
35-
}
34+
private BasicDispatcher() {}
3635

37-
public static void dispatch(HttpServletRequest req, HttpServletResponse resp, ConfigService configService, Map<String, Class<? extends BPLAction>> actions) throws IOException {
36+
public static void dispatch(
37+
HttpServletRequest req,
38+
HttpServletResponse resp,
39+
ConfigService configService,
40+
Map<String, Class<? extends BPLAction>> actions)
41+
throws IOException {
3842
String requestPath = req.getPathInfo();
3943
if (requestPath == null || requestPath.equals("")) {
4044
logger.warn("Request path is empty.");
@@ -46,21 +50,25 @@ public static void dispatch(HttpServletRequest req, HttpServletResponse resp, Co
4650
case "/ping" -> ping(resp, "pong");
4751
case "/postStartup" -> postStartup(resp, configService);
4852
case "/startupState" -> startupState(resp, configService);
49-
default ->
50-
handleBPLAction(req, resp, configService, actions, requestPath);
53+
default -> handleBPLAction(req, resp, configService, actions, requestPath);
5154
}
52-
5355
}
5456

55-
private static void handleBPLAction(HttpServletRequest req, HttpServletResponse resp, ConfigService configService, Map<String, Class<? extends BPLAction>> actions, String requestPath) throws IOException {
57+
private static void handleBPLAction(
58+
HttpServletRequest req,
59+
HttpServletResponse resp,
60+
ConfigService configService,
61+
Map<String, Class<? extends BPLAction>> actions,
62+
String requestPath)
63+
throws IOException {
5664
if (!configService.isStartupComplete()) {
5765
logger.warn("We do not let the other actions complete until the config service startup is complete...");
5866
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
5967
return;
6068
}
6169

62-
63-
if (configService.getWarFile() == WAR_FILE.MGMT && !configService.getMgmtRuntimeState().haveChildComponentsStartedUp()) {
70+
if (configService.getWarFile() == WAR_FILE.MGMT
71+
&& !configService.getMgmtRuntimeState().haveChildComponentsStartedUp()) {
6472
String header = req.getHeader(GetUrlContent.ARCHAPPL_COMPONENT);
6573
if (header == null || !header.equals("true")) {
6674
logger.error("We do not let the actions complete until all the components have started up");
@@ -71,7 +79,8 @@ private static void handleBPLAction(HttpServletRequest req, HttpServletResponse
7179

7280
Class<? extends BPLAction> actionClass = actions.get(requestPath);
7381
if (actionClass == null) {
74-
logger.error("Do not have a appropriate BPL action for " + requestPath + ". Please register the appropriate business method in getActions.");
82+
logger.error("Do not have a appropriate BPL action for " + requestPath
83+
+ ". Please register the appropriate business method in getActions.");
7584
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
7685
return;
7786
}
@@ -113,6 +122,6 @@ private static void ping(HttpServletResponse resp, String pong) throws IOExcepti
113122
resp.setContentType("text/plain");
114123
try (PrintWriter out = resp.getWriter()) {
115124
out.println(pong);
116-
}
125+
}
117126
}
118127
}

0 commit comments

Comments
 (0)