Thanks for retesting, Greg! Good catch on the single quotes. I fixed it in a separate PR: https://github.com/apache/roller/pull/159.
It now builds the same double-quoted markup as the media chooser you compared it against. Cheers, Matt > On Aug 13, 2026, at 01:32, Greg Huber <[email protected]> wrote: > > Matt > > Using branch > https://github.com/mraible/roller/tree/feature/jakarta-ee-10-migration > > Upload now works. > > Will do some more testing, but all looks OK. > > #### > > One minor point I noticed, not related to your mods I think, the uploaded > confirmation page has a link "Create new weblog post" where it adds the image > to a new weblog post, but uses single quotes and the image does not show > correctly after saving/publishing (but should). Add media file from the New > Entry page works, and uses double quotes. > > "Create new weblog post" link - incorrect - single quote > > <a > href='http://127.0.0.1/app/testuser/mediaresource/cfc4d3cc-c498-4de9-8246-4b7281cd3ae6'><img > > src='http://127.0.0.1/app/testuser/mediaresource/cfc4d3cc-c498-4de9-8246-4b7281cd3ae6?t=true' > alt='back.jpg' width='120' height='120'></img></a> > > "New Entry, Add media file" link. - correct - double quotes > > <a > href="http://127.0.0.1/app/testuser/mediaresource/9fe0d227-a43b-4a93-9f30-a7e3c935dab3"><img > > src="http://127.0.0.1/app/testuser/mediaresource/9fe0d227-a43b-4a93-9f30-a7e3c935dab3?t=true" > alt="back.jpg" /></a> > > > On 12/08/2026 14:39, Matt Raible wrote: >> Good catch, thanks Greg! >> >> You were right about UploadedFilesAware. I migrated MediaFileAdd, >> MediaFileEdit, and BookmarksImport (the three actions that receive uploads) >> to it on the PR branch. The interceptor hands the action UploadedFile >> objects directly now, so I also dropped the old FileName/ContentType arrays >> and read the original name and content type straight off the upload. >> >> On the renamed variable: I didn't need it. I kept the field private with no >> getter/setter pair at all, so there's nothing for the params interceptor to >> collide with and the natural name works fine. >> >> I verified it end to end against a fresh install: a PNG uploads and is >> served back byte-identical with the right content type, and an OPML bookmark >> import works too. There's also a Playwright test in the stack now that >> registers a user, enables uploads from the server admin page (they ship >> disabled), uploads a file, and fetches it back, so this can't regress >> silently again. CI is green. >> >> One thing to note if you're testing on that branch: the intermediate jakarta >> PR still pairs the new bootstrap plugin's markup with the old Bootstrap 3 >> CSS, so a few forms look a little rough there (stacked buttons, missing >> tooltip icons). That all cleans up in the Bootstrap 5 PR that's stacked on >> top of it. >> >> Cheers, >> >> Matt >> >>> On Aug 12, 2026, at 02:13, Greg Huber<[email protected]> wrote: >>> >>> Matt, >>> >>> I gave it a quick spinup (not using docker, from your git repo), and it >>> works great. >>> >>> I had to manually create the database (mariabd), which is normal, then >>> roller did the rest. >>> >>> create database rollerdb; >>> grant all on rollerdb.* to scott@'%' identified by 'tiger'; >>> grant all on rollerdb.* to scott@localhost identified by 'tiger'; >>> >>> One thing that did not work was the media upload. In struts 7 the upload >>> logic is changed, now have to implement UploadedFilesAware. Also, for some >>> reason the uploadedFiles variable needs to be different. >>> >>> eg >>> >>> public class MediaFileBase extends UIAction implements UploadedFilesAware { >>> >>> // uploaded files >>> private List<UploadedFile> uploadedFilesz = null; >>> >>> /** >>> * With uploaded files. >>> * >>> * @param uploadedFiles the uploaded files >>> */ >>> @Override >>> public void withUploadedFiles(List<UploadedFile> uploadedFiles) { >>> >>> this.uploadedFilesz = uploadedFiles; >>> >>> } >>> >>> public List<UploadedFile> getUploadedFilesz() { >>> return uploadedFilesz; >>> } >>> >>> } >>> >>> Then use in MediaFileAdd >>> >>> List<String> uploaded = new ArrayList<String>(); >>> // File[] uploads = getUploadedFiles(); >>> List<UploadedFile> uploads = getUploadedFilesz(); >>> if (uploads != null && uploads.size() > 0) { >>> >>> for (UploadedFile uploadedFile : uploads) { >>> >>> String fileName = uploadedFile.getOriginalName(); >>> >>> etc... >>> >>> } >>> >>> } >>> >>> Thanks. >>> >>> On 12/08/2026 00:24, Matt Raible wrote: >>>> Hi all, >>>> >>>> I've been working on ROL-2183 >>>> (https://issues.apache.org/jira/browse/ROL-2183) and have a PR up that >>>> migrates Roller from Java EE 8 to Jakarta EE >>>> 10:https://github.com/apache/roller/pull/154 >>>> >>>> The short version: Java 17 is now the minimum, and the big frameworks all >>>> moved to their Jakarta-native versions. Struts 7.1, Spring Framework 7, >>>> Spring Security 7, EclipseLink 5, and Tomcat 10.1 in the Docker image. The >>>> Jetty plugin moved to Jetty 12, so mvn jetty:run works again for quick >>>> local development with an in-memory Derby database. >>>> >>>> A couple of things went away. OAuth 1.0a and OpenID 2.0 are both obsolete >>>> and their libraries have no Jakarta-compatible releases, so I removed >>>> them. The replacement is OAuth 2.0/OIDC login built on Spring Security's >>>> OAuth2 client, and that's where the follow-up work comes in. >>>> >>>> To keep #154 reviewable, I've stacked the follow-ups in my fork. OIDC >>>> login with a seeded Keycloak in docker-compose is mraible/roller#3. >>>> Converting the admin and editor UI from Bootstrap 3 to 5.3 is #4 >>>> (struts2-bootstrap-plugin 6.1.0 targets Jakarta and emits Bootstrap 5 >>>> markup). And #5 replaces the old it-selenium module with Playwright >>>> browser tests that CI runs three ways: database auth on Jetty, plus OIDC >>>> and mixed db-oidc against the Docker stack. Each PR only shows its own >>>> diff, and I'll retarget them to apache/roller as the level below merges. >>>> >>>> Getting CI green on the migration branch turned up a few traps worth >>>> knowing about if you're reviewing. Spring Security 7's XML config denies >>>> any request that doesn't match an intercept-url rule, where the old >>>> FilterSecurityInterceptor allowed them, so every page including the login >>>> page redirected to the login page until I added an explicit permitAll >>>> catch-all. The old webjars servlet still extends the javax HttpServlet and >>>> took the whole webapp down on a Jakarta container; WebJar assets are >>>> served natively from META-INF/resources now. And struts2-bootstrap-plugin >>>> turned out to supply the FreeMarker templates behind the theme="bootstrap" >>>> attribute on nearly every form, so removing it as an unused taglib broke >>>> every form page. Restoring the Jakarta-native 6.1.0 fixed that, and the >>>> old Selenium journey (register, log in, create a weblog, publish an entry) >>>> passes on the migration branch again. >>>> >>>> If you want to try it, the quickest path is mvn -DskipTests install >>>> followed by mvn jetty:run, thenhttp://localhost:8080/roller. For the OIDC >>>> branch, docker compose up brings up Roller, PostgreSQL, and Keycloak >>>> seeded with admin/admin and user/user. You'll need a "127.0.0.1 keycloak" >>>> line in /etc/hosts so the browser and the container resolve the issuer the >>>> same way. >>>> >>>> CI is green on the PR across JDK 17, 21, and 23, and I've been running the >>>> Playwright suite against all three auth configurations locally. Review and >>>> testing on other setups would be welcome, especially from anyone running >>>> LDAP or container-managed auth, since those paths got mechanical updates >>>> but I don't have an environment to exercise them. >>>> >>>> Cheers, >>>> >>>> Matt
