Skip to content

Feature/1004 update javalin drop tomcat - #1985

Open
MikeNeilson wants to merge 76 commits into
developfrom
feature/1004-update-javalin-drop-tomcat
Open

MikeNeilson wants to merge 76 commits into
developfrom
feature/1004-update-javalin-drop-tomcat

Conversation

@MikeNeilson

@MikeNeilson MikeNeilson commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Move to latest javalin (7.2.3)

Remove Use of Tomcat, no Tomcat 11+ in our local environment so will just use Javalin's default jetty and package it up.

NOTE: Due to Javalin updating the annotation plugin (this happened in javalin 5) this is going to be a large change as it touches every file and will need to alter how the OpenAPI static test works.

TODO:

  • - Make a decision on examples (thinking a follow up given the current size)
  • - Security operations behaving correctly. (I may give up for now and just put a note on the Swagger UI about the lock icons.)
  • - Get the version behaving correctly.
  • - LRTS selection Header Handled.

Related Issue

Validation

Existing integration tests

Checklist

  • AI tools used

@MikeNeilson

Copy link
Copy Markdown
Contributor Author

NOTE: at best I will have the annotations updated today. Getting the API running again in it's standalone mode will likely take until the end of the week if not longer.

@MikeNeilson

Copy link
Copy Markdown
Contributor Author

For the record. I have considered keeping with tomcat and just using like embedded tomcat for the packaging, but Javalin was made for Jetty so since that would be a fair amount of work anyway, better to use a tool that was actually built for this given style of packaging an app.

@MikeNeilson

Copy link
Copy Markdown
Contributor Author

FYI, I am aware this PR is rather huge.

The OpenAPI changes basically have to be all or nothing. I think we can all agree on that.

It also requires the migration to Jakarta EE (javalin update) which would may or may not (java.security.Principal so probably not) affect the CwmsAaaIdentityProvider.

So fair amount of changes to Tomcat anyway.

So is this likely to be a pain... yes, but I'm arguing it's worth it.

I could pivot back and do the move to standalone Javalin (e.g. Jetty whatever version that was) first, but then without updating javalin frankly it wouldn't be in a releasable state (security concerns, that's a really old Jetty)

So. for now I'm going to barrel through. I'm open to addressing concerns and pivoting if they're strong enough.

We do have a lot of plans. and the bulk are passing. What's failing is most likely various validation I've intentionally disabled due to the location of initialization changing.

@MikeNeilson
MikeNeilson force-pushed the feature/1004-update-javalin-drop-tomcat branch 2 times, most recently from e041252 to 0263cc0 Compare October 7, 2026 21:46
@MikeNeilson
MikeNeilson marked this pull request as ready for review October 8, 2026 15:06
@MikeNeilson

Copy link
Copy Markdown
Contributor Author

I'm still working through dealing with the lock icons. the behavior as a whole has change. I may need to be drastic and take the given out put to json, and put it through the Swagger OpenAPI object, but i'm hoping to do it all within the javalin openapi annotations.

I think most of issue is assumptions we previously made that are no longer required that may be getting in the way.

The primary work of the Javalin update and removal of Tomcat are finished and should be reviewed. I think I got all of the paths in correctly, but it's definitely possible that some have been missed that also weren't detected by the various validations, new and old.

NOTE: This does break /CWMSLogin. That is intentional and will be dealt with in a follow up. Once merged CDA is a standalone app like the CWMS Server apps and thus won't be getting randomly deployed to a T7 any time soon.

@MikeNeilson
MikeNeilson force-pushed the feature/1004-update-javalin-drop-tomcat branch from 33e7c77 to c7d3788 Compare October 8, 2026 16:31
Comment thread cwms-data-api/src/main/java/cwms/cda/CwmsDataApi.java
.withUiWar(new File(uiPath))
.withDataSource(ds)
.build();
api.start();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
api.start();
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
api.stop();
if (ds instanceof AutoCloseable closeable) {
try {
closeable.close();
} catch (Exception ex) {
logger.atWarning().withCause(ex).log("Error closing data source.");
}
}
}, "cda-shutdown"));
api.start();

Comment thread cwms-data-api/src/main/java/cwms/cda/CwmsDataApi.java Outdated
Comment thread cwms-data-api/src/test/java/fixtures/TestSessionHandler.java
Comment thread cda-gui/src/main/java/cwms/cda/ui/SpaErrorStatusFilter.java
Comment thread cwms-data-api/src/main/java/cwms/cda/CwmsDataApi.java Outdated
Comment thread cwms-data-api/src/main/java/picocli/CommandLine.java Outdated
Comment thread cwms-data-api/src/main/java/picocli/CommandLine.java Outdated
Comment thread cwms-data-api/src/main/java/cwms/cda/api/ProjectController.java Outdated
Comment thread cwms-data-api/src/main/java/cwms/cda/api/ProjectController.java Outdated
Comment thread cwms-data-api/src/main/java/cwms/cda/api/ParametersController.java Outdated
Comment thread cwms-data-api/src/main/java/cwms/cda/api/StreamLocationController.java Outdated
Comment thread cwms-data-api/src/main/java/cwms/cda/api/TurbineController.java Outdated
Comment thread cwms-data-api/src/main/java/cwms/cda/api/MeasurementTimeExtentsGetController.java Outdated



//TODO: The rest

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Are these gonna get added back or dropped. Some of this commented out stuff seems important

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Still figuring that out. I did get the scheme processor working,

but the returned OpenAPI object is now a builder from javalin-openapi that doesn't behave the same way... plus most of what we were doing here can no be moved to the controllers, like examples.

so I might decide to let those go for this PR, and then come back and do a follow up on them. As much as I want it all to work. at a minimum if this gets merged into main it needs to work for existing usage. And there's already new work that not going to be super trivial to rebase into this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Put a comment in explaining, got the security elements working again. Decided to drop the examples as the method of handjamming it in like that will change and the new system should handle it better so it should just be migrated.

Comment thread cwms-data-api/src/main/java/cwms/cda/api/TimeSeriesController.java Outdated
Comment thread cwms-data-api/build.gradle Outdated
Comment thread cwms-data-api/src/main/webapp/WEB-INF/web.xml Outdated
Comment thread cwms-data-api/build.gradle Outdated
@MikeNeilson
MikeNeilson force-pushed the feature/1004-update-javalin-drop-tomcat branch from b3c754c to b34c4d2 Compare October 15, 2026 19:01

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I thought you were going to delete this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yep... and then totally forgot about it.

@rma-rripken

Copy link
Copy Markdown
Collaborator

Or we occasionally use some AI to make a punch-list and fix everything on it.

Do you want a list of controllers that mismatch? Otherwise this PR is going to break a bunch of clients - right? I asked Claude to check the paths vs the ApiServletRouteConfiguration. Thats this list:

ProjectController POST /project and PATCH/DELETE /project/{name} (route /projects),
EmbankmentController /projects/embankment (route /projects/embankments, five places),
LocationCategoryController /locations/category (route /location/category, four),
OfficeController getOne /office/{office} (route /offices/{office}),
PropertyController /property (route /properties),
SpecifiedLevelController /specified-level,
StandardTextController /text (route /standard-text-id, four),
StreamLocationController POST /stream-location,
TimeSeriesIdentifierDescriptorController /timeseries/identitifer-descriptor/{name} and /timeseries/identifier/{id},
TimeZoneController /timezone,
TurbineController getOne /project/turbines/{name},
OutletController /project/outlets,
ProjectLockGetOneV1 /projects/lock/{name} (route /project-locks/{name}) and V2 /project/lock/...,
UserList controllers /user/lists and /users/list (route /user/list),
ForecastInstanceController /forecasts-instance,
ForecastSpecController V1/V2 /forecasts-spec and /forecasts/spec (route /forecast-spec), TimeSeriesGroupControllerV1 /timeseries/groups (route /timeseries/group), TimeSeriesProfileParserCatalogController /timeseries/profile-catalog,
AccountingCreateController (missing {project-id}), the water-supply catalog, update and delete paths ('water-users', 'all-users', /projects/contracts/{office}/contract-types).
Two other V2 paths (TextTimeSeriesControllerV2 create and TimeSeriesGroupControllerV2 getAll at /v2/timeseries/group) look suspect and need checking.
only LocationValidationIT validates against the spec

@MikeNeilson

Copy link
Copy Markdown
Contributor Author

Do you want a list of controllers that mismatch? Otherwise this PR is going to break a bunch of clients - right? I asked Claude to check the paths vs the ApiServletRouteConfiguration. Thats this list:

Yeah, that would be helpful for sure. I thought I went from top to bottom, though even if I did I clearly missed a bunch.

description = "Update CWMS Property",
method = HttpMethod.PATCH,
methods = HttpMethod.PATCH,
path = "/properties{" + NAME + "}",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

this probably needs a slash

}, tags = {TAG}
}, tags = {TAG},
headers = {@OpenApiParam (name = CwmsDataApi.IS_NEW_LRTS, description = CwmsDataApi.LRTS_DESCRIPTION)},
path = "/timeseries/identitifer-descriptor/{" + TIMESERIES_ID + "}"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
path = "/timeseries/identitifer-descriptor/{" + TIMESERIES_ID + "}"
path = "/timeseries/identifer-descriptor/{" + TIMESERIES_ID + "}"

methods = {HttpMethod.DELETE},
tags = {TAG},
headers = {@OpenApiParam (name = CwmsDataApi.IS_NEW_LRTS, description = CwmsDataApi.LRTS_DESCRIPTION)},
path = "/timeseries/identifier/{" + TIMESERIES_ID + "}"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
path = "/timeseries/identifier/{" + TIMESERIES_ID + "}"
path = "/timeseries/identifier-descriptor/{" + TIMESERIES_ID + "}"

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants