Closed melloware closed 3 months ago
I am still investigating this but I think it might be this Mojarra bug long since fixed that caused it to keep adding resources to the page that have already been added
@melloware Hi, Issue is resolved in PF 13.0.8 BUT it appears again in PF 13.0.10 again!!!!! Maybe a bad merge??????
Tested today.
@kaisernova the fix was reverted and was not in 13.0.10 because in 13.0.8 it introduced these bugs: https://github.com/primefaces/primefaces/issues/11780
So we need to get to the bottom of this core issue before we attempt another fix.
So are you saying you see the double resources? Can you give me details about your environment and how I can reproduce it?
@melloware Let me explain our environment (Java8, JEE7, Mojarra 2.3.x):
Thanks in advance for your help
sounds still like a broken view or a mojarra bug we would need a reproducer here and check the root problem, everything else is just hack on PF side
@kaisernova i totally feel your pain this is hard to replicate. I have one client on Mojarra 2.3.14 and its happening to them and they have a very complex app so i have not been able to nail down exactly what in Mojarra causes this.
2 things.
Have you tried upgrading to Mojarra 2.3.21 which is the latest and last Mojarra 2.3X release?
If this doesn't fix it here is a MonkeyPatch my client has been using for 3 months in Production and has not seen an issue since.
PrimeFaces.ajax.Utils.updateElement = function (id, content, xhr) {
if (id.indexOf(PrimeFaces.VIEW_STATE) !== -1) {
PrimeFaces.ajax.Utils.updateFormStateInput(PrimeFaces.VIEW_STATE, content, xhr);
} else if (id.indexOf(PrimeFaces.CLIENT_WINDOW) !== -1) {
PrimeFaces.ajax.Utils.updateFormStateInput(PrimeFaces.CLIENT_WINDOW, content, xhr);
}
// used by @all
else if (id === PrimeFaces.VIEW_ROOT) {
// backup our utils, we reset it soon
var ajaxUtils = PrimeFaces.ajax.Utils;
// reset PrimeFaces JS state because the view is completely replaced with a new one
window.PrimeFaces.resetState();
ajaxUtils.updateHead(content);
ajaxUtils.updateBody(content);
} else if (id === PrimeFaces.ajax.VIEW_HEAD) {
PrimeFaces.ajax.Utils.updateHead(content);
} else if (id === PrimeFaces.ajax.VIEW_BODY) {
PrimeFaces.ajax.Utils.updateBody(content);
} else if (id === PrimeFaces.ajax.RESOURCE) {
var $head = $("head");
try {
var $content = $(content);
var filteredContent = $content.length > 0 ? $content.filter("link[href], script[src]") : $();
if (filteredContent.length === 0) {
PrimeFaces.debug("Adding content to the head because it lacks any JavaScript or CSS links...");
$head.append(content);
} else {
// #11714 Iterate through each script and stylesheet tag in the content
// checking if resource is already attached to the head and adding it if not
filteredContent.each(function () {
var $resource = $(this);
var src = $resource.attr("href") || $resource.attr("src");
var type = this.tagName.toLowerCase();
var $resources = $head.find(type + '[src="' + src + '"], ' + type + '[href="' + src + '"]');
// Check if script or stylesheet already exists and add it to head if it does not
if ($resources.length === 0) {
PrimeFaces.debug("Appending " + type + " to head: " + src);
$head.append($resource);
}
});
}
} catch (error) {
PrimeFaces.debug("Adding content to the head since it consists solely of raw JavaScript code...");
$head.append(content);
}
} else if (id === $("head")[0].id) {
PrimeFaces.ajax.Utils.updateHead(content);
} else {
var target = $(PrimeFaces.escapeClientId(id));
if (target.length === 0) {
PrimeFaces.warn("DOM element with id '" + id + "' cant be found; skip update...");
} else {
var removed = target.replaceWith(content);
PrimeFaces.utils.cleanseDomElement(removed);
}
}
};
@melloware @tandraschko Hi again, I have some good news for you (maybe): Checking https://javaee.github.io/javaserverfaces/whats-new-in-jsf23.html and the ajax and partial docs, I found that the problem was that the Partial State Saving was not working in the update (I dont know why).
Then, I put the following context param with the value as "true" in our web.xml:
`
<param-value>true</param-value>
`
And the app works again like with the PF8 version. I checked the reponses and the "javax.faces.Resource" block don't appears again and the style in the page dont go crazy again.
Thanks for your attention, I hope this can help you.
Interesting from that doc you posted
The "jsf.js" script has to append every element from the update section with this new javax.faces.Resource identifier to the head of the HTML document, if that element is not already there Note that via the condition "if that element is not already there" in the above algorithm the "jsf.js" script now takes upon it a part of deduplicating resource references, a task that was previously done solely server side.
That is the part we are not seeing/doing in our PF JavaScript. I need to look at what JSF.js does
@tandraschko i think this is part of the Faces Spec and PrimeFaces is not adhering to it.
Mojarra and MyFaces both check and filters out duplicates that have already been loaded:
Didnt we apply and then revert? What was the reason?
We did because of a MyFaces bug which I document is the reason the catch is needed:
https://issues.apache.org/jira/browse/MYFACES-4378
} catch (error) {
// MYFACES-4378 is incorrectly sending executable code here in the Resource section
PrimeFaces.debug("Appending content to the head as it contains only raw JavaScript code...");
$head.append(content);
}
This solves the issue you disagreed with using a catch but its the safest way to work around the MyFaces bug
@melloware Also, note that the response from server is overloaded with the "javax.faces.Resource" with data that I don't need again in the page (Heavy response vs a light one with only the required element changes).
Also, in order to save memory in the server, we will use the "javax.faces.FULL_STATE_SAVING_VIEW_IDS" for the pages with the issue instead the "PARTIAL_STATE_SAVING" param (https://balusc.omnifaces.org/2011/09/communication-in-jsf-20.html#ViewScopedFailsInTagHandlers).
@kaisernova yes according to the spec "javax.faces.Resource
should only contain CSS or JS script links. No other code should be in that block.
Then its the job of JSF or PF to make sure it doesn't try to load any of that CSS or JS that is already loaded on the page and discard it.
Describe the bug
@tandraschko this was originally reported on a forum post in 2022: https://forum.primefaces.org/viewtopic.php?t=71210
We never got to the bottom of what was happening then...but my current client has this same issue. They do a LOT of dynamic removing and adding components to a single page app using
PrimeFaces.current().ajax().update()
as well as dynamically constructing components in Java. its a HUGE project.Here you can see duplicates in the head like
InputNumber
andFileUpload
. If I close one of their panels and open it again it will add 2 more copies.I shortened it for brevity but in
javax.faces.Resource
update the scripts are there again.Our
core.ajax
for those just automatically appends to thehead
without checking for existing CSS or JS already loaded.And thus over time our head is filling with more and more scripts and is part of their overall browser slowdown after using the app for an hour...
Reproducer
I have no idea quite how to reproduce it but I am seeing it in their code base same as that user from 2022. They are not using a Custom HeadRenderer or anything.
Expected behavior
No duplicate CSS or JS even if the head is sent duplicate scripts.
PrimeFaces edition
Community
PrimeFaces version
13.0.0
Theme
California
JSF implementation
Mojarra
JSF version
2.3
Java version
11
Browser(s)
No response