Build, pipeline no GitLab, geração de imagem docker de aplicação com jsf 1.2 + Facelets + JBoss EAP 6.4, deploy no OpenShift, ambientes totalmente iguais e comportamentos diferentes ⏩ Troubleshooting

📋 A série Diário de Bordo não tem a inteção de explicar detalhes técnicos e soluçãoes bem elebadoras, é apenas uma história real contada.

Spoiler: é claro que existia diferença nos ambientes!

História

Tenho - na prática mesmo não é meu, então só modo de falar - um pipeline montado de uma aplicação Java que gera um EAR. Dentro do EAR existe um WAR e alguns JARs.

O pipeline basicamente executa em sequência: compilação, testes, geração do EAR, geração da imagem docker por meio do s2i (source-to-image) e por fim deploy dessa imagem docker no OpenShift.

Embora o s2i sugira código para imagem, estamos utilizando ele para, a partir de um binário compilado, no caso o EAR, montar a imagem docker da aplicação.

No nosso cenário cada branch no Git gera automaticamente uma aplicação no OpenShift.

A partir daqui vou chamar as aplicações de app-master e app-branch.

Ao acessar ambas as aplicações, app-master e app-branch, e mandar pesquisar em uma tela de pesquisa simples, nada ocorria na tela, ao mandar pesquisa novamente nada ocorria e ao mandar pesquisa pela terceira vez a aplicação quebrava com a stack abaixo:

Stacktrace - Clique para ver (não é relevante) ```stacktrace 16:46:35,717 SEVERE [javax.enterprise.resource.webcontainer.jsf.lifecycle] (http-10.129.2.161:8080-6) JSF1054: (Phase ID: PROCESS_VALIDATIONS 3, View ID: /pages/cidade/pesquisa.xhtml) Exception thrown during phase execution: javax.faces.event.PhaseEvent[source=com.sun.faces.lifecycle.LifecycleImpl@47d599aa] 16:46:35,719 ERROR [org.jboss.seam.exception.Exceptions] (http-10.129.2.161:8080-6) handled and logged exception: javax.servlet.ServletException: For input string: "org.jboss.seam.ui.NoSelectionConverter.noSelectionValue" at javax.faces.webapp.FacesServlet.service(Unknown Source) [jsf-api-1.2.15.b01-SP2-redhat-1.jar:1.2.15.b01-SP2-redhat-1] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:295) [jbossweb-7.5.28.Final-redhat-1.jar:7.5.28.Final-redhat-1] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214) [jbossweb-7.5.28.Final-redhat-1.jar:7.5.28.Final-redhat-1] at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:83) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.web.IdentityFilter.doFilter(IdentityFilter.java:40) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:60) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:73) [jboss-seam.jar:2.2.6.EAP5] at com.myapp.sso.SamlSSOObserver.processSamlAuth(SamlSSOObserver.java:157) [grpfor-core.jar:] at com.myapp.sso.SamlSSOObserver.doFilter(SamlSSOObserver.java:135) [grpfor-core.jar:] at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:90) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:64) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:45) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) [jboss-seam.jar:2.2.6.EAP5] at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:530) [richfaces-impl-3.3.4.Final.SEFINv1.jar:3.3.4.Final.SEFINv1] at org.jboss.seam.web.Ajax4jsfFilter.doFilter(Ajax4jsfFilter.java:56) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:158) [jboss-seam.jar:2.2.6.EAP5] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:246) [jbossweb-7.5.28.Final-redhat-1.jar:7.5.28.Final-redhat-1] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214) [jbossweb-7.5.28.Final-redhat-1.jar:7.5.28.Final-redhat-1] at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:206) [richfaces-impl-3.3.4.Final.SEFINv1.jar:3.3.4.Final.SEFINv1] at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:290) [richfaces-impl-3.3.4.Final.SEFINv1.jar:3.3.4.Final.SEFINv1] at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:388) [richfaces-impl-3.3.4.Final.SEFINv1.jar:3.3.4.Final.SEFINv1] at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:515) [richfaces-impl-3.3.4.Final.SEFINv1.jar:3.3.4.Final.SEFINv1] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:246) [jbossweb-7.5.28.Final-redhat-1.jar:7.5.28.Final-redhat-1] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214) [jbossweb-7.5.28.Final-redhat-1.jar:7.5.28.Final-redhat-1] at com.myapp.FiltroCorrecaoIE.doFilter(FiltroCorrecaoIE.java:28) [grpfor.jar:] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:246) [jbossweb-7.5.28.Final-redhat-1.jar:7.5.28.Final-redhat-1] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214) [jbossweb-7.5.28.Final-redhat-1.jar:7.5.28.Final-redhat-1] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:231) [jbossweb-7.5.28.Final-redhat-1.jar:7.5.28.Final-redhat-1] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:149) [jbossweb-7.5.28.Final-redhat-1.jar:7.5.28.Final-redhat-1] at org.jboss.as.web.security.SubjectInfoSetupValve.invoke(SubjectInfoSetupValve.java:34) [jboss-as-web-7.5.20.Final-redhat-1.jar:7.5.20.Final-redhat-1] at org.jboss.as.jpa.interceptor.WebNonTxEmCloserValve.invoke(WebNonTxEmCloserValve.java:50) [jboss-as-jpa-7.5.20.Final-redhat-1.jar:7.5.20.Final-redhat-1] at org.jboss.as.jpa.interceptor.WebNonTxEmCloserValve.invoke(WebNonTxEmCloserValve.java:50) [jboss-as-jpa-7.5.20.Final-redhat-1.jar:7.5.20.Final-redhat-1] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:512) [jbossweb-7.5.28.Final-redhat-1.jar:7.5.28.Final-redhat-1] at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:169) [jboss-as-web-7.5.20.Final-redhat-1.jar:7.5.20.Final-redhat-1] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:151) [jbossweb-7.5.28.Final-redhat-1.jar:7.5.28.Final-redhat-1] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:97) [jbossweb-7.5.28.Final-redhat-1.jar:7.5.28.Final-redhat-1] at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:560) [jbossweb-7.5.28.Final-redhat-1.jar:7.5.28.Final-redhat-1] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:102) [jbossweb-7.5.28.Final-redhat-1.jar:7.5.28.Final-redhat-1] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [jbossweb-7.5.28.Final-redhat-1.jar:7.5.28.Final-redhat-1] at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:856) [jbossweb-7.5.28.Final-redhat-1.jar:7.5.28.Final-redhat-1] at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:656) [jbossweb-7.5.28.Final-redhat-1.jar:7.5.28.Final-redhat-1] at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:926) [jbossweb-7.5.28.Final-redhat-1.jar:7.5.28.Final-redhat-1] at java.lang.Thread.run(Thread.java:748) [rt.jar:1.8.0_242] Caused by: java.lang.NumberFormatException: For input string: "org.jboss.seam.ui.NoSelectionConverter.noSelectionValue" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) [rt.jar:1.8.0_242] at java.lang.Integer.parseInt(Integer.java:580) [rt.jar:1.8.0_242] at java.lang.Integer.<init>(Integer.java:867) [rt.jar:1.8.0_242] at org.jboss.seam.ui.EntityIdentifierStore.get(EntityIdentifierStore.java:46) [jboss-seam-ui-2.2.6.EAP5.jar:2.2.6.EAP5] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.8.0_242] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) [rt.jar:1.8.0_242] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [rt.jar:1.8.0_242] at java.lang.reflect.Method.invoke(Method.java:498) [rt.jar:1.8.0_242] at org.jboss.seam.util.Reflections.invoke(Reflections.java:22) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.intercept.RootInvocationContext.proceed(RootInvocationContext.java:32) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:56) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.transaction.RollbackInterceptor.aroundInvoke(RollbackInterceptor.java:28) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.core.MethodContextInterceptor.aroundInvoke(MethodContextInterceptor.java:44) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.core.SynchronizationInterceptor.aroundInvoke(SynchronizationInterceptor.java:32) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:107) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.intercept.JavaBeanInterceptor.interceptInvocation(JavaBeanInterceptor.java:185) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.intercept.JavaBeanInterceptor.invoke(JavaBeanInterceptor.java:103) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.ui.EntityIdentifierStore_$$_javassist_seam_34.get(EntityIdentifierStore_$$_javassist_seam_34.java) [jboss-seam-ui-2.2.6.EAP5.jar:2.2.6.EAP5] at org.jboss.seam.ui.AbstractEntityLoader.get(AbstractEntityLoader.java:27) [jboss-seam-ui-2.2.6.EAP5.jar:2.2.6.EAP5] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.8.0_242] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) [rt.jar:1.8.0_242] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [rt.jar:1.8.0_242] at java.lang.reflect.Method.invoke(Method.java:498) [rt.jar:1.8.0_242] at org.jboss.seam.util.Reflections.invoke(Reflections.java:22) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.intercept.RootInvocationContext.proceed(RootInvocationContext.java:32) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:56) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.transaction.RollbackInterceptor.aroundInvoke(RollbackInterceptor.java:28) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.transaction.TransactionInterceptor$1.work(TransactionInterceptor.java:97) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.util.Work.workInTransaction(Work.java:61) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.transaction.TransactionInterceptor.aroundInvoke(TransactionInterceptor.java:91) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.core.MethodContextInterceptor.aroundInvoke(MethodContextInterceptor.java:44) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:107) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.intercept.JavaBeanInterceptor.interceptInvocation(JavaBeanInterceptor.java:185) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.intercept.JavaBeanInterceptor.invoke(JavaBeanInterceptor.java:103) [jboss-seam.jar:2.2.6.EAP5] at org.jboss.seam.ui.JpaEntityLoader_$$_javassist_seam_33.get(JpaEntityLoader_$$_javassist_seam_33.java) [jboss-seam-ui-2.2.6.EAP5.jar:2.2.6.EAP5] at org.jboss.seam.ui.EntityConverter.getAsObject(EntityConverter.java:76) [jboss-seam-ui-2.2.6.EAP5.jar:2.2.6.EAP5] at com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer.getConvertedValue(Unknown Source) [jsf-impl-1.2.15.b01-SP2-redhat-1.jar:1.2.15.b01-SP2-redhat-1] at com.sun.faces.renderkit.html_basic.MenuRenderer.convertSelectOneValue(Unknown Source) [jsf-impl-1.2.15.b01-SP2-redhat-1.jar:1.2.15.b01-SP2-redhat-1] at com.sun.faces.renderkit.html_basic.MenuRenderer.getConvertedValue(Unknown Source) [jsf-impl-1.2.15.b01-SP2-redhat-1.jar:1.2.15.b01-SP2-redhat-1] at javax.faces.component.UIInput.getConvertedValue(Unknown Source) [jsf-api-1.2.15.b01-SP2-redhat-1.jar:1.2.15.b01-SP2-redhat-1] at javax.faces.component.UIInput.validate(Unknown Source) [jsf-api-1.2.15.b01-SP2-redhat-1.jar:1.2.15.b01-SP2-redhat-1] at javax.faces.component.UIInput.executeValidate(Unknown Source) [jsf-api-1.2.15.b01-SP2-redhat-1.jar:1.2.15.b01-SP2-redhat-1] at javax.faces.component.UIInput.processValidators(Unknown Source) [jsf-api-1.2.15.b01-SP2-redhat-1.jar:1.2.15.b01-SP2-redhat-1] at javax.faces.component.UIComponentBase.processValidators(Unknown Source) [jsf-api-1.2.15.b01-SP2-redhat-1.jar:1.2.15.b01-SP2-redhat-1] at javax.faces.component.UIComponentBase.processValidators(Unknown Source) [jsf-api-1.2.15.b01-SP2-redhat-1.jar:1.2.15.b01-SP2-redhat-1] at javax.faces.component.UIComponentBase.processValidators(Unknown Source) [jsf-api-1.2.15.b01-SP2-redhat-1.jar:1.2.15.b01-SP2-redhat-1] at javax.faces.component.UIComponentBase.processValidators(Unknown Source) [jsf-api-1.2.15.b01-SP2-redhat-1.jar:1.2.15.b01-SP2-redhat-1] at javax.faces.component.UIComponentBase.processValidators(Unknown Source) [jsf-api-1.2.15.b01-SP2-redhat-1.jar:1.2.15.b01-SP2-redhat-1] at org.ajax4jsf.component.UIAjaxForm.processValidators(UIAjaxForm.java:82) [richfaces-ui-3.3.4.Final.jar:3.3.4.Final] at org.ajax4jsf.component.AjaxViewRoot$3.invokeContextCallback(AjaxViewRoot.java:447) [richfaces-impl-3.3.4.Final.SEFINv1.jar:3.3.4.Final] at org.ajax4jsf.component.AjaxViewRoot.processPhase(AjaxViewRoot.java:240) [richfaces-impl-3.3.4.Final.SEFINv1.jar:3.3.4.Final] at org.ajax4jsf.component.AjaxViewRoot.processValidators(AjaxViewRoot.java:463) [richfaces-impl-3.3.4.Final.SEFINv1.jar:3.3.4.Final] at com.sun.faces.lifecycle.ProcessValidationsPhase.execute(Unknown Source) [jsf-impl-1.2.15.b01-SP2-redhat-1.jar:1.2.15.b01-SP2-redhat-1] at com.sun.faces.lifecycle.Phase.doPhase(Unknown Source) [jsf-impl-1.2.15.b01-SP2-redhat-1.jar:1.2.15.b01-SP2-redhat-1] at com.sun.faces.lifecycle.LifecycleImpl.execute(Unknown Source) [jsf-impl-1.2.15.b01-SP2-redhat-1.jar:1.2.15.b01-SP2-redhat-1] ... 49 more ```


Resumindo o stack, o erro era: Caused by: java.lang.NumberFormatException: For input string: "org.jboss.seam.ui.NoSelectionConverter.noSelectionValue"

A string "org.jboss.seam.ui.NoSelectionConverter.noSelectionValue" era submetida por um combobox quando nenhum valor era selecionado. E ok, esse é o valor esperado.

O stack acima nem é tão relevante.

Então eu fui debugar o código e para minha frustração as classes do jsf e facelets foram compiladas sem informação de debug. É um parto debugar assim. Pelo debug não consegui ver o problema e eu acabava perdendo tempo demais por ter que debugar “no escuro”, então deixei isso de lado, embora eu tenha até chegado a fazer debug remoto, informando para a JVM: -agentlib:jdwp=transport=dt_socket,server=y,address=8000,suspend=n.

Eu também observei no log, na primeira vez que mandava pesquisar, diversas mensagens como essa:

19:17:15,290 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/layout/template.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50

Mais dessas mensagens aqui - Clique para ver ```log 19:17:15,290 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/layout/template.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,293 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/layout/cabecalho.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:49 19:17:15,293 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/layout/cabecalho.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:49 19:17:15,297 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/layout/menu.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,297 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/layout/menu.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,297 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/layout/menu.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,297 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/layout/menu.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,297 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/layout/menu.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,297 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/layout/menu.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,297 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/layout/menu.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,297 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/layout/menu.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,298 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/layout/menu.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,298 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/layout/menu.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,298 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/layout/menu.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,298 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/layout/menu.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,298 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/layout/menu.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,298 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/layout/menu.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,298 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/layout/menu.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,298 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/layout/menu.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,298 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/layout/menu.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,298 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/layout/menu.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,386 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/WEB-INF/facelets/tags/status.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,386 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/WEB-INF/facelets/tags/status.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,386 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/WEB-INF/facelets/tags/status.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,387 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/WEB-INF/facelets/tags/status.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,387 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/WEB-INF/facelets/tags/status.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,387 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/WEB-INF/facelets/tags/status.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,387 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/WEB-INF/facelets/tags/status.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,389 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/WEB-INF/facelets/tags/mensagens.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,393 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/WEB-INF/facelets/tags/toolBarPesquisa.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,396 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/layout/editColuna.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,397 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/layout/editColuna.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,397 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/layout/editColuna.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,397 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/layout/editColuna.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,401 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/WEB-INF/facelets/tags/label.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,401 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/WEB-INF/facelets/tags/label.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,401 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/WEB-INF/facelets/tags/label.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,402 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/WEB-INF/facelets/tags/label.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,402 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/WEB-INF/facelets/tags/label.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,402 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/WEB-INF/facelets/tags/label.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,405 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/WEB-INF/facelets/tags/footer.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 19:17:15,405 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/WEB-INF/facelets/tags/footer.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50 ```


Spoiler: se eu tivesse dado atenção a essas mensagens acima e se minha memória tivesse funcionado, eu teria matado a charada sem ter perdido muito tempo.

Mas porque nos ambientes do OpenShift essa simples pesquisa não funcionava e em ambientes que já existiam funcionava?

Na imagem docker executada no Openshift (onte tínhamos problemas):

  • GitLab 12.9 + GitLab Runner 13
  • Imagem do agente do GitLab (onde o build da aplicação é feito): Openjdk 1.8.0_252 e Apache Maven 3.6.3
  • Runtime: Openjdk 1.8.0_252
  • SO RHEL 7 + JBoss EAP 6.4.20

No ambiente que já funcionava (sem problemas):

  • Jenkins
  • Apache Maven 3.2.1 + Oracle JDK 1.8.0_171
  • Runtime: Oracle JDK 1.8.0_171
  • SO RHEL 7 + JBoss EAP 6.4.20

Diferenças existiam, então executei a aplicação na minha máquina local por meio da imagem docker e também tive o mesmo problema da exeução no OpenShift.

Verifiquei se o código no ambiente com problema estava o mesmo do ambiente que funcionava e estava.

Baixei o fonte da aplicação, subi no meu Eclipse + JBoss local e não dava problema. No meu ambeinte local eu usava Oracle JDK 1.8.0_171 e resolvi usar Openjdk 1.8.0_252 (a versão do container docker, que dava problema), e continuou sem dar problema.

Nessa altura do campeonado eu já tinha feito quase tudo. Já tinha checado versão de SO, versão de JVM, versão de JBoss, versão dos módulos do JBoss, versão de código (inclusive o código estava binariamente igual), locale, timezone, configurações de JVM, configurações do JBoss, system properties, tudo… ou quase tudo…!

Para piorar, uma das aplicações que citei lá em cima, a aplicação app-branch, passou a funcionar, do nada! Nesse momento app-branch e app-master estavam iguais (compiladas a partir do mesmo código fonte). E daí eu comecei a perceber uma alternância de hora funcionar, hora não. Existia um padrão, mas até então eu não tinha observado.

Pensando… pensando… pensando… resolvi comparar o EAR gerado pelo Jenkins com o EAR gerado pelo pipeline do GitLab, e tinha diferença! Me animei por um tempo, mas quando vi as diferenças, desanimei, eram:

  • o arquivo META-INF\maven\com.myapp\myapp-ear\pom.properties
  • o arquivo META-INF\MANIFEST.MF

E a única diferença entre eles eram o usuário do build, horário do build e versão da JDK.

Nesse momento a versão JDK diferente foi irrelevante, pois eu já sabia disso e já havia feito testes com a mesma JDK usada no container docker.

Subi o EAR gerado pelo Jenkins no meu JBoss local (já nem lembro que JDK usei, eu fiz muita coisa!, rs), e a aplicação funcionou ok. Daí resolvi subir também no meu JBoss local o EAR gerado pelo pipeline do GitLab, e, para minha surpresa e alegria, deu problema no meu ambiente local!

Então aqui ficou claro para mim uma coisa muito importante: o problema era no EAR! O EAR do Jenkins dava certo, o EAR do GitLab não!

Eu olhava para o EAR e não via nada de diferente, exceto o que falei acima. Então, já apelando para o impossível, deixei o EAR com problema no JBoss e alterei nele apenas o pom.properties e o MANIFEST.MF para ficar igual ao do EAR que dava certo… e… continuou dando problema!

E agora? Não tinha mais nada diferente. Os EAR estavam binariamente iguais. Mas um dava certo e o outro não. E no mesmo ambiente! Sinistro!

Nesse testes locais eu vi novamente a mensagem que não dei importância, que citei lá em cima, essa:

19:17:15,290 INFO [facelets.facelet] (http-0.0.0.0:8080-6) Facelet[/layout/template.xhtml] was modified @ 19:17:15, flushing component applied @ 19:16:50

💭 Porque eu não olhei para isso antes! 💭

Agora eu resolvi dar importância, então dá-lhe Google, e tome logo no primeiro link, no Stackoverflow, mas não na primeira resposta, mas nessa aqui.

Bom… lendo o post, o cara fala do atributo facelets.REFRESH_PERIOD e quando eu bati o olho nisso lembrei de umas coisas. Então fui checar as datas de modificação dos arquivos xhtml em ambos os EAR. No EAR problemático a data de todos eles estava no futuro!

Na primeira requisição, quando esses xhtml eram acessados, o facelets entedia que eles haviam mudado e os recompilava, o que acaba por recriar a árvore de componentes, o que acabava por perder os dados do request e fazer surgir o problema.

Informei para o facelets não checar as mudanças nos xhtml, adicionando ao web.xml:

<context-param>
    <param-name>facelets.REFRESH_PERIOD</param-name>
    <param-value>-1</param-value> <!-- padrão: 2 segundos -->
</context-param>

E o prolema foi embora! 🎉🎉🎉

Mas porque a data de modificação dos xhtml estava no futuro? Porque o runner do GitLab estava em UTC, quando deveria estar em UTC-3. Então, se na verdade eram 20:23:56, para o runner eram 23:23:56 (3h na frente).

Runner é um container docker, iniciado pelo GitLab, que possui as ferramentas para buildar a aplicação. O build da aplicação, no caso aqui geração do EAR, é feito dentro desse container.

Porque a aplicação app-branch passou a funcionar do nada? Na verdade não foi do nada. Quando a hora do container docker ficou na frente da hora de modicação dos arquivos xhtml, o facelets deixou de re-compilar os xhtml por entender que eles não foram modificados.

🧩 Dica: em produção o parâmetro facelets.REFRESH_PERIOD deve ser -1, já que os xhtml não vão mudar, mas em desenvolvimento, com hot deploy, o interessante é que seja 0, para que as mudanças feitas no código surtam efeito o quanto antes.

Até a próxima!

ps: é claro que a hora do runner tem que ser ajustada!

Referências