TheCoder4eu / BootsFaces-OSP

BootsFaces - Open Source Project
Apache License 2.0
247 stars 102 forks source link

Omnifaces CombinedResourceHandler #888

Closed chongma closed 4 weeks ago

chongma commented 6 years ago

I have been speaking to Google AdWords team regarding the performance of a website.

I have tried using the Omnifaces CombinedResourceHandler. It doesn't seem to combine the BootsFaces css and js files.

It says here that it should work OK http://showcase.bootsfaces.net/integration/OmniFaces.jsf.

Can someone confirm the issue?

chongma commented 6 years ago

hmmm...it seems to work ok on the showcase so i will check the code there

chongma commented 6 years ago

i am using omnifaces 2.4 but the showcase is using version 1.14. i cannot even see where the CombinedResourceHandler is configured. I thought it needed to be set in faces-config.xml like

<application>
    <resource-handler>org.omnifaces.resourcehandler.CombinedResourceHandler</resource-handler>
</application>
chongma commented 6 years ago

OK it seems to work fine with BootsFacesWeb on TomEE 7.0.3. But I cannot get it to work on my test project https://github.com/chongma/test even though it has more or less the same dependencies as BootsFacesWeb.

chongma commented 6 years ago

This is a MyFaces issue. By adding

<dependency>
            <groupId>com.sun.faces</groupId>
            <artifactId>jsf-api</artifactId>
            <version>2.2.13</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>com.sun.faces</groupId>
            <artifactId>jsf-impl</artifactId>
            <version>2.2.13</version>
            <scope>runtime</scope>
        </dependency>

the issue seems to be resolved

chongma commented 6 years ago

message from BalusC:

It appears that BootsFaces is adding its resources during PreRenderViewEvent instead of as @ResourceDependency.

The CombinedResourceHandler also runs during PreRenderViewEvent, which is the latest possible moment of safe component tree manipulation. However, when BootsFaces is loaded after OmniFaces, then the CombinedResourceHandler would run before BootsFaces adds its resource dependencies and therefore not have the chance to combine them. It looks like that your MyFaces setup is loading BootsFaces after OmniFaces and that your Mojarra setup is loading OmniFaces before BootsFaces.

@stephanrauh, perhaps you can explain why BootsFaces adds its resources during PreRenderViewEvent instead of as @ResourceDependency?

chongma commented 6 years ago

this was the response Thomas Andraschko at users@myfaces.apache.org: i would ask the omnifaces guys about that - they know their CombinedResourceHandler better then we do this led me to submit the issues at OmniFaces https://github.com/omnifaces/omnifaces/issues/415

stephanrauh commented 6 years ago

@chongma As for your question:

"However, when BootsFaces is loaded after OmniFaces"

If the application server respects the faces-config.xml of BootsFaces, this will never happen. I ran into the problem earlier and configured BootsFaces to be loaded after OmniFaces. At the moment, I'm just confused if it shouldn't be before OmniFaces.

    <ordering>
        <after>
            <name>omnifaces</name>
        </after>
    </ordering>
stephanrauh commented 6 years ago

@chongma The other question: well, BootsFaces loads a lot of resource files from the theme subfolders. There's no way to add variables of the @ResourceDependency annotations, so we reluctantly decided to write our own AddResourcesHandler and to add it to the PreRenderView phase.

chongma commented 6 years ago

@stephanrauh the questions were asked by @balusc not me. I was posting them here from the other issue. Sorry for the confusion.

Shall I ask the MyFaces mailing list why it is not respecting the ordering in BootsFaces faces-config? Also maybe @balusc knows how to fix the @ResourceDependency issue?

BalusC commented 6 years ago

I ran into the problem earlier and configured BootsFaces to be loaded after OmniFaces. At the moment, I'm just confused if it shouldn't be before OmniFaces.

OmniFaces has already an <after><others> since 2.0 / 1.10. Apparently Mojarra prioritizes this higher than MyFaces.

Also maybe @BalusC knows how to fix the @ResourceDependency issue?

Invoke UIViewRoot#addComponentResource() in either component constructor or PostAddToView listener.

chongma commented 6 years ago

net.bootsfaces.listeners.AddResourcesListener has many methods addResourceIfNecessary which end by root.addComponentResource(context, output, "head"); where root is an instance of UIViewRoot root which is type javax.faces.component.UIViewRoot. So it should be adding the resources correctly? Or maybe as you say this has to happen in the component constructor otherwise it will happen in the wrong phase?

BalusC commented 6 years ago

Or maybe as you say this has to happen in the component constructor otherwise it will happen in the wrong phase?

Correct.

chongma commented 6 years ago

Resources ARE added in the component constructor by calling addBasicJSResource, addExtCSSResource, addResourceIfNecessary and addResourceToHeadButAfterJQuery from https://github.com/TheCoder4eu/BootsFaces-OSP/blob/master/src/main/java/net/bootsfaces/listeners/AddResourcesListener.java. But the resources are added when processEvent is called (possibly by javax.faces.event.SystemEvent?)

stephanrauh commented 6 years ago

This thread is long enough to leave me confused. What precisely is the current question? @chongma If I get you right, you're working on a project that doesn't manage to combine the resources with OmniFaces. On the other hand, you say that our showcase does manage to do just that trick. Are you hunting down the bug yourself? If not, would you mind to send us a minimal viable reproducer?

chongma commented 6 years ago

@stephanrauh does it work if you run the showcase using myfaces profile? I believe it is myfaces issue but relates to the way it is loading the resources

dguna commented 6 years ago

Hello all, I am keep getting the following error. The application hungs for sometime and it start to rework again.

JSF1064: Unable to find or serve resource, eNpVi0EKwCAMBF_U5t7fJDFCQaO4Si99fO0xp2EYRgFKlnmVeSrwCvK1SeisVlhI27BQ0mg9tccPLKnmK0T2u_KMw-bvH5rsKRs.css, from library, omnifaces.combined.

I am using bootsfaces 1.3 and omnifaces 3.0. Please let me know if I am doing something wrong.

Thanks in advance

stephanrauh commented 6 years ago

@dguna That's a different issue. Plus, it's an issue we can't answer without seeing your source code. So I recommend you prepare a reproducer - i.e. a minimal, working application that shows the bug and runs without any configuration. In particular, it shouldn't use a database. When you've managed that, open a new issue, attach the reproducer to the issue (or publish it as a separate GitHub project).

Otherwise, we can't help you because we simply don't know what you're doing, and it's impossible to guess.

stephanrauh commented 6 years ago

@chongma I've uploaded a new developer snapshot of BootsFaces 1.3.1-SNAPSHOT to Maven Central. Can you please check if BootsFaces is now compatible to OmniFaces and MyFaces again?

@BalusC I've followed your advices and registered the PostAddToViewEvent. I hope there aren't too many side effects.

chongma commented 6 years ago

@stephanrauh if i set my bootsfaces to 1.3.1-SNAPSHOT i cannot load any page and get this stack trace. it may be my setup but i have cleaned my work directory and it seems to persist.

java.lang.NullPointerException
    at org.apache.myfaces.lifecycle.DefaultRestoreViewSupport.isPostback(DefaultRestoreViewSupport.java:240)
    at org.apache.myfaces.lifecycle.RestoreViewExecutor.execute(RestoreViewExecutor.java:132)
    at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:196)
    at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:143)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:198)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.openejb.server.httpd.EEFilter.doFilter(EEFilter.java:65)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.tomee.catalina.OpenEJBValve.invoke(OpenEJBValve.java:44)
    at org.keycloak.adapters.tomcat.AbstractAuthenticatedActionsValve.invoke(AbstractAuthenticatedActionsValve.java:67)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:610)
    at org.keycloak.adapters.tomcat.AbstractKeycloakAuthenticatorValve.invoke(AbstractKeycloakAuthenticatorValve.java:181)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
    at org.apache.tomee.catalina.OpenEJBSecurityListener$RequestCapturer.invoke(OpenEJBSecurityListener.java:97)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:650)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:800)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:800)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1471)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)
dguna commented 6 years ago

@stephanrauh Thanks. It may be related. I don't get any problem when using HTTP. As soon as I enable HTTPS, the problem starts to appear and it is very inconsistent. Here is my security constraint in web.xml

<security-constraint>
        <display-name>dataConstraint</display-name>
        <web-resource-collection>
            <web-resource-name>AllResources</web-resource-name>
            <description/>
            <url-pattern>/*</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
        </web-resource-collection>
        <user-data-constraint>
            <description/>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint>

Thanks.

stephanrauh commented 6 years ago

@chongma I was afraid of something like this... but the precise location of the exception is a tad unexpected. Unfortunately, I didn't manage to reproduce the bug. Would you mind to send me a reproducer?

BTW, I suspect we have to resort to plan B. We can combine every JavaScript and CSS file to a single file (respectively), and deliver these two files even if almost every BootsFaces application ignores 90% of it. From a SEO perspective, that's still the better approach, because you can put this large file on a CDN. We might explore this solution, but before we do, I'd like to understand why my first attempt didn't work.

stephanrauh commented 6 years ago

@BalusC After switching to MyFaces, I encountered this error message:

<partial-response>
    <error>
        <error-name>org.apache.myfaces.view.facelets.compiler.DuplicateIdException</error-name>
        <error-message>
            <![CDATA[Component with duplicate id "j_id__v_20" found. The first component is {Component-Path : [Class: javax.faces.component.UIViewRoot,ViewId: /forms/commandButton.xhtml][Class: org.apache.myfaces.component.ComponentResourceContainer,Id: javax_faces_location_head][Class: javax.faces.component.UIOutput,Id: j_id__v_20]}]]>
        </error-message>
    </error>
    <error>
        <error-name>org.apache.myfaces.view.facelets.compiler.DuplicateIdException</error-name>
        <error-message>
            <![CDATA[Component with duplicate id "j_id__v_20" found. The first component is {Component-Path : [Class: javax.faces.component.UIViewRoot,ViewId: /forms/commandButton.xhtml][Class: org.apache.myfaces.component.ComponentResourceContainer,Id: javax_faces_location_head][Class: javax.faces.component.UIOutput,Id: j_id__v_20]}]]>
        </error-message>
    </error>
</partial-response>

I'm at a loss. No idea what to do about this error message. The only idea is to take a whole evening off and start a long, long debugging session. Can you give me a clue?

chongma commented 6 years ago

@stephanrauh after the error message i went back to 1.3.0 and then 1.2.0 but the error persisted. then i realised that i had enabled these 2 lines in the faces-config.xml to test whether the CombinedResourceHandler was working. so it seems that error goes back to 1.2.0? removing the lines now everything works ok

<resource-handler>org.omnifaces.resourcehandler.CombinedResourceHandler</resource-handler>
<resource-handler>org.omnifaces.resourcehandler.CDNResourceHandler</resource-handler>
stephanrauh commented 6 years ago

@dguna As I've said yesterday: I believe that's a different issue, so I'd rather you opened another ticket. This thread is already long and convoluted, so it's better to start fresh.

That said, I don't have the slightest idea what your problem is. I've tried to google, but to no avail. I suppose the only way to help you is debugging a reproducer you give us. Remember, that's a minimal program requiring no configuration that shows the bug.

However, there's a remote chance Bauke Scholz can help us, since he's already chimed in to this channel. @BalusC Do you have an idea? I'm at a loss again, the second time in the same ticket, even if I'm convinced it should be two tickets :).

Thanks in advance, Stephan

stephanrauh commented 6 years ago

@chongma Phew. Difficult to say. I'd like to see a "cooking recipe": starting from this point, do this to reproduce the bug. You know, I'm not really surprise that activating the AddResourcesListener earlier causes errors. JSF serializes that state of the JSF page between requests. Mojarra is a bit lazy about that. MyFaces is much more eager. That, in turn, causes many compatibility issues if a library is developed with Mojarra. In our case, it's possible that MyFaces fails to deserialize our components properly.

But that's just a theory. Before acting, I'd like to see the confirmation of the theory in my debugger. :)

chongma commented 6 years ago

@stephanrauh i will try to knock together a reproducer. i am using a web fragment project which might be complicating things. i will try a clean version first. does it work on the showcase with MyFaces profile as that should be a pretty good test?

stephanrauh commented 6 years ago

@chongma Great! To answer your question: yes, I tried to run the showcase with the MyFaces profile. It managed to do so a couple of weeks ago. Just remember to remove the dependency on HighFaces. However, today I ran into the strange error message I reported above. Two duplicate components in the head, both with the same, non-standard ID. That's strange, isn't it?

stephanrauh commented 4 weeks ago

I'm afraid development of BootsFaces has slowed down considerably. We'll never manage to address this issue. Let's close it.