Skip to content

IQSS/12715 payara 7.2026.9 update - #12719

Merged
landreev merged 18 commits into
IQSS:developfrom
GlobalDataverseCommunityConsortium:12715-payara-7.2026.9
Sep 25, 2026
Merged

landreev merged 18 commits into
IQSS:developfrom
GlobalDataverseCommunityConsortium:12715-payara-7.2026.9

Conversation

@qqmyers

@qqmyers qqmyers commented Sep 16, 2026 •

Copy link
Copy Markdown
Member

What this PR does / why we need it: This PR includes the basic update to Payara 7.2026.9 as well as fixes required due to changes in Payara and/or the libraries it uses. Issues identified/fixed so far include:

  • The @context annotation we used in the ApiBlockingFilter has been ~deprecated/removed. There are several potential fixes being explored in various PRs. This PR switches to using the JAX-RS DynamicFeature mechanism to avoid having to dynamically inject the ResourceInfo instance on every call and instead registers filters for api calls at app startup. The overall logic related to blocking doesn't change, but scanning for @path annotations only happens at startup now.
  • Changes to Mojarra appear to cause the ContactFormFragment validation to run when the form is not actually shown on a page. This PR changes to dynamically loading so the contact dialog should not be in the source at all unless/until it is shown. Related changes to other dialogs and buttons to not load when not used and to constrain processing to the form or @this rather than everything, as suggested by AI, have also been made and lightly tested.

The PR also fixes some minor issues discovered when testing:

  • When signing up, having a null value for the required email field was not flagged as a validation error and instead triggered a silent bean constraint error only seen in the log (leaving the dialog open when you click save). This could be due to 8531 refactor validators #8534 or may have existed before that refactoring - not a new issue regardless.
  • Cancelling edits on the Account Info page did not clear validation errors in the messagePanel (if they occurred).

FWIW: I noticed a similar issue in the group creation page/dialog - a validation error, e.g. for null group name, pops up a warning in the messagePanel (grayed out behind the dialog in this case) and cancel doesn't clear it. As it seems odd to put a warning in the grayed-out background to begin with, I didn't just add code to update the messagePanel on cancel (also more work than with the account page since the cancel is not a p:commandButton here).

Which issue(s) this PR closes:

Special notes for your reviewer: FWIW: Azul mentions the DynamicFeature approach in a blog post (although the post is primarily about simpler, but less flexible approaches). It sounds like this is more of a pure JAX-RS approach that relying on @Inject, and it should be slightly more efficient that we had (since api endpoint paths are all calculated once at startup instead of happening repeatedly during the filtering (for whatever api call is made). I think a key benefit of this fix is that it retains the idea of getting the path from JAX-RS itself, rather than our code trying to infer what the path is from the URL as was the case < v6.7).

Suggestions on how to test this: As this changes the API Blocking filter, testing that the admin API etc. are still blocked by the settings is important (and not just by the proxy), though I don't think there will be any issues. The main change was to when the api paths are calculated (not how, which we had to update for 6.7, and the code to implement the policy moved to a new class but isn't really different). I haven't seen any issues in my testing.

Does this PR introduce a user interface change? If mockups are available, please link/include them here:

Is there a release notes update needed for this change?:

Additional documentation:

@qqmyers

qqmyers commented Sep 17, 2026

Copy link
Copy Markdown
Member Author

FWIW: AI says: Analysis of Validator Triggering in JSF 4.0 / Payara 7
The issue where validators in the contactFormFragment are triggered during unrelated actions (like saving a template) is caused by a
combination of two factors in the JSF/PrimeFaces environment:

  1. Global Inclusion and DOM Presence: Since contactFormFragment.xhtml is included in the dataverse_template.xhtml, the p:dialog and
    all its inputs are part of the JSF component tree for almost every page in the application. By default, p:dialog renders its content
    into the DOM (hidden via CSS), meaning the inputs are active and visible to the JSF lifecycle.
  2. Broad Execution Scope (process="@ALL"): Many PrimeFaces components (like p:commandButton) default to process="@ALL" if no process
    attribute is specified. This instructs JSF to run the "Execute" phases (Apply Request Values, Process Validations, Update Model) for
    the entire component tree, not just the form being submitted.

In Jakarta EE 11 (JSF 4.0), Mojarra has become stricter about processing the tree, and if jakarta.faces.VALIDATE_EMPTY_FIELDS is
enabled (or due to other lifecycle changes), it will trigger validators for any input it finds in the "execute" scope, even if those
inputs are empty and hidden.

Best Practices to Avoid Unnecessary Validation
To prevent hidden or unrelated dialogs from interfering with page actions, the following best practices are recommended:

  1. Lazy Loading with dynamic="true" (Recommended)
    Add dynamic="true" to your p:dialog components, especially those included in global templates.

ΓÇó How it works: When dynamic="true", PrimeFaces does not render the dialog's content into the component tree until the dialog is
actually shown.
ΓÇó Benefit: The inputs and their validators simply do not exist in the JSF lifecycle during postbacks of other forms, completely
eliminating the possibility of them being triggered unnecessarily.
ΓÇó Implementation: I have updated contactFormFragment.xhtml to use this setting:
<p:dialog id="contactDialog" ... dynamic="true">

  1. Narrowing the Execution Scope (process)
    Avoid using the default @ALL scope for buttons. Instead, explicitly define what should be processed.

ΓÇó Best Practice: Use process="@Form" for most save/submit actions. This ensures that only the inputs within the current form are
validated and updated.
ΓÇó Example:
<p:commandButton value="Save" action="#{bean.save}" process="@Form" update="@Form" />

  1. Conditional Validation Logic
    Continue using the pattern of conditional required attributes and null-safe validators as a safeguard.

ΓÇó Safe Validators: Validators should check if the component is actually required in the current context (e.g., via ((UIInput)
component).isRequired()) before throwing exceptions for null values. This allows the validator to "stand down" when the field is empty
but not mandatory for the current request.

@qqmyers
qqmyers marked this pull request as ready for review September 17, 2026 19:21
@qqmyers qqmyers moved this to Ready for Triage in IQSS Dataverse Project Sep 17, 2026
@qqmyers qqmyers added the Size: 10 A percentage of a sprint. 7 hours. label Sep 17, 2026
@pdurbin pdurbin moved this from Ready for Triage to Ready for Review ⏩ in IQSS Dataverse Project Sep 22, 2026
Comment on lines -122 to -123
Method method = resourceInfo.getResourceMethod();
Class<?> clazz = resourceInfo.getResourceClass();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

A smaller fix instead of complete remodelling, only dropping the injection of ResourceInfo above:

        // Jersey-specific, but avoids any reliance on @Context/@Inject of ResourceInfo,
        // which is not available to CDI-managed providers on Payara 7.
        ResourceMethod matched = requestContext.getUriInfo() instanceof ExtendedUriInfo extendedUriInfo
            ? extendedUriInfo.getMatchedResourceMethod()
            : null;
        
        if (matched == null) {
            // Fail closed: a blocking filter must never let a request through it cannot classify.
            logger.severe("Could not determine matched resource method for "
                + requestContext.getUriInfo().getRequestUri() + " - denying request.");
            requestContext.abortWith(Response.status(Response.Status.SERVICE_UNAVAILABLE).entity(errorJson)
                .type(jakarta.ws.rs.core.MediaType.APPLICATION_JSON).build());
            return;
        }
        
        Invocable invocable = matched.getInvocable();
        Method method = invocable.getHandlingMethod();
        Class<?> clazz = invocable.getHandler().getHandlerClass();

@poikilotherm

Copy link
Copy Markdown
Contributor

I also found a usage of @Context in LDNInbox.java which should be replaced due to the JAX-RS CDI bridge update:

-   @Context
+   @Inject
    protected HttpServletRequest httpRequest;

@pdurbin pdurbin added this to the 6.12.1 milestone Sep 22, 2026
@qqmyers

qqmyers commented Sep 22, 2026

Copy link
Copy Markdown
Member Author

I also found a usage of @Context in LDNInbox.java which should be replaced due to the JAX-RS CDI bridge update:

-   @Context
+   @Inject
    protected HttpServletRequest httpRequest;

Thanks for the catch! FWIW: The test was mocking the httpRequest and hence didn't catch this.

@cmbz cmbz added FY27 Sprint 6 FY27 Sprint 6 (2026-09-09 - 2026-09-23) FY27 Sprint 7 FY27 Sprint 7 (2026-09-23 - 2026-10-07) labels Sep 23, 2026
<p:tabView id="themeWidgetsTabView" rendered="#{themeWidgetFragment.editDv!=null}" widgetVar="content">
<p:tabView id="themeWidgetsTabView" rendered="#{themeWidgetFragment.editDv!=null}" widgetVar="content" dynamic="true">
<p:tab id="themeTab" title="#{bundle['dataverse.theme.title']}" rendered="#{not settingsWrapper.rootDataverseThemeDisabled or themeWidgetFragment.editDv.owner != null}">
<p:fragment>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just noting at the bottom that API tests failed but it's just a search test:

SearchIT.testSearchWithInvalidDateField

Hopefully merging the following PR will help:

Comment thread doc/release-notes/21715-Payara-7.2026.9-update.md Outdated
Comment thread doc/release-notes/21715-Payara-7.2026.9-update.md Outdated
@pdurbin pdurbin moved this from Ready for Review ⏩ to In Review 🔎 in IQSS Dataverse Project Sep 23, 2026
Comment thread doc/release-notes/21715-Payara-7.2026.9-update.md Outdated
qqmyers and others added 3 commits September 23, 2026 16:00
@landreev landreev self-assigned this Sep 24, 2026
@landreev

Copy link
Copy Markdown
Contributor

@pdurbin lol, I'm not making this up: rather than fixing it, they have doubledtripled-down on it:

/usr/local/payara7/bin/asadmin list-applications
pppdataverse-frontend  <web>  
Command list-applications executed successfully.

@landreev

Copy link
Copy Markdown
Contributor

Builds and deploys fine, main pages are looking ok so far.

@landreev

landreev commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

As I reported on slack earlier:

A re-run of the standard Locust test shows that the "payara7 premium", first encountered when testing 6.10-RC appears to be gone. I.e., the results are back to what was recorded for 6.11-RC deployed under payara6 3 months ago. The spreadsheet reflects that it was still there when testing under payara7.2026.8 for 6.12-RC 10 days ago.

The granular results and the html report are checked in in the usual place.

I said in an earlier conversation about 7.2026.9 that I had a "glimmer of hope" that maybe it would fix this (still a mystery of a) problem; based on the updated components in it. But it really was a glimmer only.

@landreev

landreev commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

FWIW, some words from ai re: potential explanation behind the observed speedup.

[warning: unfiltered/unverified, potential slop]

Why Jersey Was Slowing Down Your JSF Pages

Even if your JSF pages don't explicitly fetch data from a REST endpoint, Jersey sits in the global deployment pipeline of your web application. When you upgraded from Payara 6 to Payara 7 (the transition into Jakarta EE 11), application servers intensified how aggressively they scan packages for annotations.

There are two massive reasons Jersey can cause a blanket overhead that ruins JSF page-load performance:

  1. The Class and Annotation Scanning Overhead:
    By default, when a Payara application starts up or processes a request context, Jersey scans the classpath for REST annotations (like @Path, @Provider, and @Context). If this scanning isn't tightly bounded, Jersey attempts to parse all the classes in your deployment—including your JSF backing beans, EJBs, and UI controllers. This adds a massive CPU and thread-blocking tax to request cycles.
  2. Context Injection Bottlenecks:
    Jersey manages an internal InjectionManager to handle dependency injection for web requests. If Jersey's filters or servlet mappings are globally intercepting requests, it will constantly evaluate context threads.

What Fixed It in Payara 7.2026.9?

The Payara 7.2026.9 release explicitly resolved severe internal context and injection overhead bugs.

Specifically, two major fixes directly correlate with the performance recovery you observed:

  • The Injection Manager Leak/Overhead Fix: Payara closed a severe community-tracked bug ([FISH-14203]) titled "Fix Logs Leaking Injection Manager Found in the Current Thread". This issue caused Jersey's internal dependency injection manager to repeatedly leak or mismanage thread contexts during general web traffic, which bogs down the entire server thread pool and impacts sibling technologies like JSF.
  • Optimized Annotation Processing: Upstream updates in this release cycle changed how Jersey scans for resources. Instead of evaluating dynamically injected resources on every single call via heavy filters, major structural changes forced Jersey to restrict resource scanning strictly to application startup.

Because Payara resolved Jersey's thread-context pollution and streamlined how it hooks into the global request pipeline, your JSF pages are finally free from that hidden processing tax.

@qqmyers

qqmyers commented Sep 25, 2026

Copy link
Copy Markdown
Member Author

Re:

Optimized Annotation Processing: Upstream updates in this release cycle changed how Jersey scans for resources. Instead of evaluating dynamically injected resources on every single call via heavy filters, major structural changes forced Jersey to restrict resource scanning strictly to application startup

we started dynamic scanning in 6.7 so the timing isn't right for this to be the issue unless there were other Payara changes that interacted.

@landreev
landreev merged commit 2553300 into IQSS:develop Sep 25, 2026
18 checks passed
@landreev landreev removed their assignment Sep 25, 2026
@pdurbin pdurbin moved this from Merged 🚀 to Done 🧹 in IQSS Dataverse Project Sep 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

FY27 Sprint 6 FY27 Sprint 6 (2026-09-09 - 2026-09-23) FY27 Sprint 7 FY27 Sprint 7 (2026-09-23 - 2026-10-07) Size: 10 A percentage of a sprint. 7 hours.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Upgrade to Payara 7.2026.9

5 participants