Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UnsupportedOperationException in chain.doFilter(request, response); when using WebFilter with SSL #483

Closed
ramiswailem opened this issue Oct 1, 2024 · 9 comments
Assignees
Labels
bug Something isn't working

Comments

@ramiswailem
Copy link
Contributor

Env:
quarkus-faces 14.0.5 on JVM (powered by Quarkus 3.15.1)
OmniFaces version 4.5.1
PrimeFaces 14.0.5
PrimeFaces Extensions 14.0.5

chain.doFilter(request, response);2024-10-01 09:16:38,479 SEVERE [org.pri.app.exc.PrimeExceptionHandler] (executor-thread-3) null

Exception in AdminFilter.java:182
	   180                  response.setHeader("Pragma", "no-cache");
	   181  
	-> 182                  chain.doFilter(request, response);
	   183              } catch (FileNotFoundException e) {
	   184                  System.out.println("File not found: " + e);

: java.lang.UnsupportedOperationException
	at java.base/java.util.AbstractList.remove(AbstractList.java:169)
	at java.base/java.util.AbstractList$Itr.remove(AbstractList.java:389)
	at io.undertow.servlet.spec.PushBuilderImpl.<init>(PushBuilderImpl.java:120)
	at io.undertow.servlet.spec.HttpServletRequestImpl.newPushBuilder(HttpServletRequestImpl.java:1184)
	at org.apache.myfaces.context.servlet.ServletExternalContextImpl.pushResource(ServletExternalContextImpl.java:402)
	at org.apache.myfaces.context.servlet.ServletExternalContextImpl.encodeResourceURL(ServletExternalContextImpl.java:383)
	at jakarta.faces.context.ExternalContextWrapper.encodeResourceURL(ExternalContextWrapper.java:107)
	at jakarta.faces.context.ExternalContextWrapper.encodeResourceURL(ExternalContextWrapper.java:107)
	at org.apache.myfaces.renderkit.html.HtmlStylesheetRenderer.encodeEnd(HtmlStylesheetRenderer.java:236)
	at jakarta.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:634)
	at jakarta.faces.component.UIComponentBase.encodeAll(UIComponentBase.java:523)
	at org.apache.myfaces.renderkit.html.HtmlHeadRenderer.encodeEnd(HtmlHeadRenderer.java:81)
	at jakarta.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:634)
	at jakarta.faces.component.UIComponentBase.encodeAll(UIComponentBase.java:523)
	at jakarta.faces.component.UIComponentBase.encodeAll(UIComponentBase.java:519)
	at org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage.renderView(FaceletViewDeclarationLanguage.java:1783)
	at org.apache.myfaces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:316)
	at jakarta.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:74)
	at org.omnifaces.viewhandler.OmniViewHandler.renderView(OmniViewHandler.java:166)
	at jakarta.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:74)
	at org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:122)
	at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:241)
	at jakarta.faces.lifecycle.LifecycleWrapper.render(LifecycleWrapper.java:43)
	at jakarta.faces.webapp.FacesServlet.service(FacesServlet.java:225)
	at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
	at org.swailem.infra.security.AdminFilter.doFilter(AdminFilter.java:182)
	at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
	at org.omnifaces.filter.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:123)
	at org.omnifaces.filter.HttpFilter.doFilter(HttpFilter.java:108)
	at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
	at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
	at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:63)
	at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
	at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
	at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:67)
	at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:133)
	at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
	at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:65)
	at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
	at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
	at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
	at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:247)
	at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:111)
	at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:108)
	at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
	at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
	at io.quarkus.undertow.runtime.UndertowDeploymentRecorder$9$1.call(UndertowDeploymentRecorder.java:645)
	at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:227)
	at io.undertow.servlet.handlers.ServletInitialHandler.handleRequest(ServletInitialHandler.java:152)
	at io.undertow.server.handlers.CanonicalPathHandler.handleRequest(CanonicalPathHandler.java:49)
	at io.quarkus.undertow.runtime.UndertowDeploymentRecorder$1.handleRequest(UndertowDeploymentRecorder.java:126)
	at io.undertow.server.Connectors.executeRootHandler(Connectors.java:284)
	at io.undertow.server.DefaultExchangeHandler.handle(DefaultExchangeHandler.java:18)
	at io.quarkus.undertow.runtime.UndertowDeploymentRecorder$5$2.run(UndertowDeploymentRecorder.java:445)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
	at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:635)
	at org.jboss.threads.EnhancedQueueExecutor$Task.doRunWith(EnhancedQueueExecutor.java:2516)
	at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2495)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1521)
	at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:11)
	at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:11)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:1583)
    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {

        req.setCharacterEncoding(StandardCharsets.UTF_8.name());
        resp.setCharacterEncoding(StandardCharsets.UTF_8.name());

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

       if (request.getRequestURI().equals(request.getContextPath() + "/")
                || (loginBean.isLoggedIn() && request.getRequestURI().endsWith(loginPage))) {
        
            try {
                response.sendRedirect(getRedirectPrefix(request) + request.getContextPath() + "/" + indexPage);

            } catch (Exception ex) {
                LOG.error("Exception: " , ex);

            }
            return;
        }

        if (request.getRequestURI().contains(request.getContextPath() + "/public/")) {
            try {
                chain.doFilter(req, resp);
            } catch (Exception ex) {
                LOG.error("Exception: " , ex);

            }
            return;
        }

        if (skipResource(request, response) || loginBean.isLoggedIn()) {
           if (!loginBean.isUserRedirected() && loginBean.isLoggedIn() && null!=request.getHeader("Referer") && request.getHeader("Referer").contains("?page=")) {
                loginBean.setUserRedirected(true);
                                String pageFromURL = request.getContextPath() + extractPageFromURL(request.getHeader("Referer"));
                System.out.println("Redirecting user back to: " + pageFromURL);
                try {
                    response.sendRedirect(getRedirectPrefix(request) + pageFromURL);
                } catch (Exception ex) {
                LOG.error("Exception: " , ex);

                }
                return;
            }
            try {
                response.setHeader("Cache-Control", "no-store,"
                        + "no-cache, must-revalidate, max-age=0");
                response.setDateHeader("Expires", 0);
                response.setHeader("Pragma", "no-cache");

                chain.doFilter(request, response);
            } catch (FileNotFoundException e) {
                System.out.println("File not found: " + e);
                LOG.error("File not found Exception: " , e);

                response.sendError(404);
            } catch (Exception e) {
                LOG.error("Exception: " , e);

            }
        } else { //resource not skipped (e.g a page that is not logon page) AND user not logged in
            System.out.println("redirectToLogon");

            redirectToLogon(request, (HttpServletResponse) resp);
        }

    }
@melloware
Copy link
Owner

@ramiswailem i can't reproduce:
quarkus-filter.zip

Run mvn quarkus:dev and you will see my Filter applied? Can you modify my sample to try and show the issue?

@melloware melloware added the bug Something isn't working label Oct 1, 2024
@ramiswailem
Copy link
Contributor Author

@melloware yes, I can reproduce it

rami@mac ~/quarkus-filter $ ls cert 
fullchain.pem privkey.pem
QUARKUS_HTTP_SSL_CERTIFICATE_FILES=./cert/fullchain.pem
QUARKUS_HTTP_SSL_CERTIFICATE_KEY_FILES=./cert/privkey.pem
QUARKUS_HTTP_HOST=0.0.0.0
QUARKUS_HTTP_PORT=9001
QUARKUS_HTTP_SSL_PORT=9002
2024-10-01 14:55:15,128 DEBUG [io.net.han.ssl.BouncyCastlePemReader] (vert.x-eventloop-thread-1) Bouncy Castle provider available
2024-10-01 14:55:15,178 DEBUG [io.net.han.ssl.BouncyCastlePemReader] (vert.x-eventloop-thread-1) Parsed PEM object of type org.bouncycastle.asn1.pkcs.PrivateKeyInfo and assume key is not encrypted
2024-10-01 14:55:15,745 DEBUG [jdk.eve.security] (vert.x-eventloop-thread-1)  TLSHandshake: null:-1, TLSv1.3, TLS_AES_256_GCM_SHA384, 0
2024-10-01 14:55:15,789 DEBUG [io.net.han.ssl.SslHandler] (vert.x-eventloop-thread-1) [id: 0x516102ee, L:/127.0.0.1:9002 - R:/127.0.0.1:61919] HANDSHAKEN: protocol:TLSv1.3 cipher suite:TLS_AES_256_GCM_SHA384
2024-10-01 14:55:15,953 INFO  [com.mel.qua.SecureServletFilter] (executor-thread-1) SecureServletFilter ...
2024-10-01 14:55:15,953 INFO  [com.mel.qua.SecureServletFilter] (executor-thread-7) SecureServletFilter ...
java.lang.UnsupportedOperationException
	at java.base/java.util.AbstractList.remove(AbstractList.java:169)
	at java.base/java.util.AbstractList$Itr.remove(AbstractList.java:389)
	at io.undertow.servlet.spec.PushBuilderImpl.<init>(PushBuilderImpl.java:120)
	at io.undertow.servlet.spec.HttpServletRequestImpl.newPushBuilder(HttpServletRequestImpl.java:1184)
	at org.apache.myfaces.context.servlet.ServletExternalContextImpl.pushResource(ServletExternalContextImpl.java:402)
	at org.apache.myfaces.context.servlet.ServletExternalContextImpl.encodeResourceURL(ServletExternalContextImpl.java:383)
	at jakarta.faces.context.ExternalContextWrapper.encodeResourceURL(ExternalContextWrapper.java:107)
	at jakarta.faces.context.ExternalContextWrapper.encodeResourceURL(ExternalContextWrapper.java:107)
	at org.primefaces.renderkit.HeadRenderer.encodeCSS(HeadRenderer.java:185)
	at org.primefaces.renderkit.HeadRenderer.encodeBegin(HeadRenderer.java:105)
	at jakarta.faces.component.UIComponentBase.encodeBegin(UIComponentBase.java:561)
	at jakarta.faces.component.UIComponentBase.encodeAll(UIComponentBase.java:495)
	at jakarta.faces.component.UIComponentBase.encodeAll(UIComponentBase.java:519)
	at org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage.renderView(FaceletViewDeclarationLanguage.java:1783)
	at org.apache.myfaces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:316)
	at jakarta.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:74)
	at org.omnifaces.viewhandler.OmniViewHandler.renderView(OmniViewHandler.java:166)
	at jakarta.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:74)
	at org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:122)
	at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:241)
	at jakarta.faces.webapp.FacesServlet.service(FacesServlet.java:225)
	at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
	at org.omnifaces.filter.CacheControlFilter.doFilter(CacheControlFilter.java:239)
	at org.omnifaces.filter.HttpFilter.doFilter(HttpFilter.java:108)
	at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
	at com.melloware.quarkus.SecureServletFilter.doFilter(SecureServletFilter.java:48)
	at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
	at org.omnifaces.filter.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:123)
	at org.omnifaces.filter.HttpFilter.doFilter(HttpFilter.java:108)
	at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
	at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
	at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:63)
	at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
	at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
	at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:67)
	at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:133)
	at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
	at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:65)
	at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
	at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
	at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
	at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:247)
	at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:111)
	at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:108)
	at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
	at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
	at io.quarkus.undertow.runtime.UndertowDeploymentRecorder$9$1.call(UndertowDeploymentRecorder.java:645)
	at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:227)
	at io.undertow.servlet.handlers.ServletInitialHandler.handleRequest(ServletInitialHandler.java:152)
	at io.undertow.server.handlers.CanonicalPathHandler.handleRequest(CanonicalPathHandler.java:49)
	at io.quarkus.undertow.runtime.UndertowDeploymentRecorder$1.handleRequest(UndertowDeploymentRecorder.java:126)
	at io.undertow.server.Connectors.executeRootHandler(Connectors.java:284)
	at io.undertow.server.DefaultExchangeHandler.handle(DefaultExchangeHandler.java:18)
	at io.quarkus.undertow.runtime.UndertowDeploymentRecorder$5$2.run(UndertowDeploymentRecorder.java:445)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
	at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:635)
	at org.jboss.threads.EnhancedQueueExecutor$Task.doRunWith(EnhancedQueueExecutor.java:2516)
	at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2495)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1495)
	at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:11)
	at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:11)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:1583)
java.lang.UnsupportedOperationException
	at java.base/java.util.AbstractList.remove(AbstractList.java:169)
	at java.base/java.util.AbstractList$Itr.remove(AbstractList.java:389)
	at io.undertow.servlet.spec.PushBuilderImpl.<init>(PushBuilderImpl.java:120)
	at io.undertow.servlet.spec.HttpServletRequestImpl.newPushBuilder(HttpServletRequestImpl.java:1184)
	at org.apache.myfaces.context.servlet.ServletExternalContextImpl.pushResource(ServletExternalContextImpl.java:402)
	at org.apache.myfaces.context.servlet.ServletExternalContextImpl.encodeResourceURL(ServletExternalContextImpl.java:383)
	at jakarta.faces.context.ExternalContextWrapper.encodeResourceURL(ExternalContextWrapper.java:107)
	at jakarta.faces.context.ExternalContextWrapper.encodeResourceURL(ExternalContextWrapper.java:107)
	at org.primefaces.renderkit.HeadRenderer.encodeCSS(HeadRenderer.java:185)
	at org.primefaces.renderkit.HeadRenderer.encodeBegin(HeadRenderer.java:105)
	at jakarta.faces.component.UIComponentBase.encodeBegin(UIComponentBase.java:561)
	at jakarta.faces.component.UIComponentBase.encodeAll(UIComponentBase.java:495)
	at jakarta.faces.component.UIComponentBase.encodeAll(UIComponentBase.java:519)
	at org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage.renderView(FaceletViewDeclarationLanguage.java:1783)
	at org.apache.myfaces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:316)
	at jakarta.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:74)
2024-10-01 14:55:16,060 SEVERE [org.pri.app.exc.PrimeExceptionHandler] (executor-thread-7) null

Exception in SecureServletFilter.java:48
	   46          httpResponse.setHeader("X-XSS-Protection", "1; mode=block");
	   47          httpResponse.setHeader("Strict-Transport-Security", "max-age=31536000; includeSubDomains");
	-> 48         chain.doFilter(request, response);
	   49      }
	   50  }

@melloware
Copy link
Owner

Ahhh OK this is a Quarkus bug in Undertow with SSL not a JSF bug.

I just reported it at Quarkus: quarkusio/quarkus#43628

@melloware
Copy link
Owner

Looks like this future Quarkus fix will fix it: quarkusio/quarkus-http#166

@ramiswailem
Copy link
Contributor Author

Thank you so much @melloware
When merged I will test it again

@melloware
Copy link
Owner

Yep i will find out what version of Quarkus this is going in 3.15.X or 3.16.0

@ramiswailem
Copy link
Contributor Author

Fixed in Quarkus 3.16.0.CR1
Thank you so much @melloware and @geoand

@geoand
Copy link

geoand commented Oct 18, 2024

Thanks for the update!

@melloware
Copy link
Owner

@ramiswailem its good to get feedback that someone is using Quarkus Faces in the real world!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants