Solucionado (ver solução)
Solucionado
(ver solução)
39
respostas

Java e JSF: Sua aplicação web com JSF2 - Temas

Quando use EL dentro do web.xml eu recebo a seguinte mensagem de erro:

HTTP Status 500 - Error loading css, cannot find "theme.css" resource of "primefaces-" library

type Exception report

message Error loading css, cannot find "theme.css" resource of "primefaces-" library

description The server encountered an internal error that prevented it from fulfilling this request.

exception

javax.servlet.ServletException: Error loading css, cannot find "theme.css" resource of "primefaces-" library
javax.faces.webapp.FacesServlet.service(FacesServlet.java:671)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

root cause

javax.faces.FacesException: Error loading css, cannot find "theme.css" resource of "primefaces-" library
org.primefaces.renderkit.HeadRenderer.encodeCSS(HeadRenderer.java:139)
org.primefaces.renderkit.HeadRenderer.encodeBegin(HeadRenderer.java:76)
javax.faces.component.UIComponentBase.encodeBegin(UIComponentBase.java:865)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:1854)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:458)
com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:134)
com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:120)
com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:659)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

note The full stack trace of the root cause is available in the Apache Tomcat/8.0.30 logs.
Apache Tomcat/8.0.30

Meu web.xml e minha classe TemaBean.java seguem abaixo:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">
    <display-name>livraria</display-name>

    <!-- Configuração do JSF -->
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.xhtml</url-pattern>
    </servlet-mapping>

    <!-- Definição do thema no Primefaces -->
    <context-param>
        <param-name>primefaces.THEME</param-name>
        <param-value>#{temaBean.tema}</param-value>
    </context-param>
</web-app>
package br.com.caelum.livraria.bean;

import java.io.Serializable;
import java.util.Arrays;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean
@SessionScoped
public class TemaBean implements Serializable {

private static final long serialVersionUID = 1L;
private String tema = "blitzer"; // "pepper-grinder";

public String getTema() {
return tema;
}

public void setTema(String tema) {
this.tema = tema;
}

public List getTemas() {
return Arrays.asList( "afterdark", "afternoon", "afterwork", "black-tie", "blitzer", "bluesky", "bootstrap", "casablanca", "cruze", "cupertino", "dark-hive",
"delta", "dot-luv", "eggplant", "excite-bike", "flick", "glass-x","home", "hot-sneaks", "humanity", "le-frog",
"midnight", "mint-choc", "overcast", "pepper-grinder", "redmond", "rocket", "sam", "smoothness",
"south-street", "start", "sunny", "swanky-purse", "trontastic", "ui-darkness", "ui-lightness", "vader");
}

}
39 respostas

Acredito que você não pode usar uma expressão EL dentro de um arquivo XML. Será que não existe outro meio de setar o tema?

Olá Rogério, você colocou o jar all-themes-1.0.9.jar dentro da pasta WEB_COTENT/lib? Os temas ficam nesse arquivo.

Boa noite Flávio. Eu estou usando Maven e quando coloco literalmente o nome do tema no xml ele é aplicado normalmente, segue o pom.xml do projeto abaixo:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>livraria</groupId>
    <artifactId>livraria</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <build>
        <sourceDirectory>src</sourceDirectory>
        <resources>
            <resource>
                <directory>src</directory>
                <excludes>
                    <exclude>**/*.java</exclude>
                </excludes>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.6</version>
                <configuration>
                    <warSourceDirectory>WebContent</warSourceDirectory>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>prime-repo</id>
            <name>PrimeFaces Maven Repository</name>
            <url>http://repository.primefaces.org</url>
            <layout>default</layout>
        </repository>
    </repositories>

    <dependencies>
        <!-- JSF - Primefaces 5.3 -->
        <dependency>
            <groupId>org.primefaces</groupId>
            <artifactId>primefaces</artifactId>
            <version>5.3</version>
        </dependency>

        <dependency>
            <groupId>org.primefaces.themes</groupId>
            <artifactId>all-themes</artifactId>
            <version>1.0.9</version>
        </dependency>


        <!-- JSF Mojarra 2.2.12 -->
        <dependency>
            <groupId>com.sun.faces</groupId>
            <artifactId>jsf-api</artifactId>
            <version>2.2.12</version>
        </dependency>
        <dependency>
            <groupId>com.sun.faces</groupId>
            <artifactId>jsf-impl</artifactId>
            <version>2.2.12</version>
        </dependency>

        <!-- JPA - Hibernate 5.0.7 -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>5.0.7.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-osgi</artifactId>
            <version>5.0.7.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-envers</artifactId>
            <version>5.0.7.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-c3p0</artifactId>
            <version>5.0.7.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-proxool</artifactId>
            <version>5.0.7.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-infinispan</artifactId>
            <version>5.0.7.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-ehcache</artifactId>
            <version>5.0.7.Final</version>
        </dependency>

        <!-- Drive Postgres -->
        <dependency>
            <groupId>postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>9.1-901-1.jdbc4</version>
        </dependency>

    </dependencies>
</project>

Será algo do Maven? Bizarro. Não faço idéia do que seja. Até agora já evoluiu? Descobriu algo?

Infelizmente não. Vejo dois comportamentos estranhos na realidade:

1) A aplicação não reconhece EL, conforme especificado na última aula, no web.xml para o tema do Primefaces. Somente valor literal.

2) Quando coloco o componente themeSwitcher dentro das tags ... ele simplesmente não é renderezado. Quando coloco antes ele aparece e funciona normalmente, conforme o fragmento do código abaixo:

````

```

Faltou eu enviar o fragmento do código.

        <h:graphicImage library="img" name="logo.png" />

            <p:themeSwitcher value="#{temaBean.tema}" style="position: absolute; right: 10px;">
                <f:selectItems value="#{temaBean.temas}"/>
                <f:ajax execute="@this" />
            </p:themeSwitcher>

        <h:form>
            <p:menubar>
                <p:submenu label="Cadastros">
                    <p:menuitem value="Autor" action="autor?faces-redirect=true" />
                    <p:separator />
                    <p:menuitem value="Livro" action="livro?faces-redirect=true" />
                </p:submenu>
            </p:menubar>
        </h:form>

Seu servlet container e qual versão ? JÁ fez como ensinado, sem Maven? Se funcionar é alguma lib aí.

Olá,

Quando fiz o curso também aconteceu o mesmo problema devido a essa configuração específica do web.xml.

O que é relevante, o curso deveria usar uma versão recente estável do Primefaces. E nas explicações, mostrar a diferença entre o antigo novo e o antigo, se houver.

Olá,

A seguir possível solução: http://stackoverflow.com/questions/28020121/error-loading-theme-cannot-find-theme-css-resource-of-primefaces-start-libr

Irei testá-la na minha aplicação.

Se estiver usando um servlet container que não suporte El mo web.XML vai dar problema. E usar a mesma versão do prime e jsf do curso. Se mudaram a api vc terá problema. Pelo que vi vc usou lib diferentes.

Olá,

E usar as bibliotecas diretamente ao invés de um gerenciador de dependências e construtor como Maven é outro ponto fraco desses projetos. Pois se o aluno quiser seguir adiante e usar bibliotecas mais recentes terá dificuldades. Se fosse um projeto baseado em Maven facilitaria as coisas.

Olá Cassius, entendo quando você diz que o Maven facilitaria (isso se a pessoa sabe usar e configurar o Maven). Mas a questão aqui é que, para descobrirmos o que está acontecendo, sugeri para que o Rogério usasse as mesmas versões do treinamento. Se não funcionar, é alguma coisa no seu código ou infraespecífica. Se funcionar, ótimo, daí ele pode partir para o Maven e , se algum problema ocorrer, teremos certeza que é o Maven.

A questão é isolar o problema, algo comum no mundo do desenvolvimento.

Sobre facilitar, o Graddle facilitaria muito mais do que o Maven, é algo a se pensar, porque a pessoa tem que sacar de Graddle e nem todo mundo saca.

Aliás, Cassius, você pode submeter uma sugestão lá quando for fazer os exercícios. Já usou desse recurso? Isso ajuda a separar a sugestão da solução de problemas e facilita a nossa vida de moderadores.

Rogério, aguardo seu feedback.

Oi Cassuis,

estamos atualizando o treinamento com primefaces novo e mais capitulos. acredito que isso vai ajudar muito.

sobre o maven: há muitas polemicas ai :) eu acho que um pre-requisito desnecessário para esse treinamento. nao sei se seria justo para quem quer focar no JSF aprender o Maven antes.

abs e obrigado pelo feedback, Nico

Olá,

Sobre o Gradle, concordo com você, inclusive fiz vários projetos de aprendizado usando o Spring Boot e o Gradle. E além de projetos para Android usando o Android Studio.

Oi Flávio,

Importei da Caelum e incluindo as bibliotecas na pasta lib, disponibilizadas pelo site do curso. Apresentou o mesmo comportamento do projeto usando Maven.

  <context-param>
    <param-name>primefaces.THEME</param-name>
    <param-value>humanity</param-value> <!-- funciona-->
<!--     <param-value>#{temaBean.tema}</param-value> -->  <!-- Não funciona-->
  </context-param>

Muito obrigado pelo teste Rogério. Só uma coisa: qual servlet container você está usando? Expression Language no Web.xml só funciona a partir de determinada versão, até onde eu sei, mas não lembro a versão.

Seria legal você compartilhar seu web.xml completinho. Estou curioso para saber que problema é esse, mas o que me consola por enquanto é que isso não bloqueia sua progressão no JSF.

Aguardo o código do seu arquivo. :)

O Container que estou usando é o tomcat 8.0.30. Quando tentei publicar o novo projeto no Glassfish 4, obtive a seguinte mensagem de erro:

cannot Deploy livraria
deploy is failing=Error occurred during deployment: Exception while loading the app : java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: java.lang.RuntimeException: com.sun.faces.config.ConfigurationException: 
  Source Document: jar:file:/Applications/NetBeans/glassfish-4.1.1/glassfish/domains/domain1/eclipseApps/livraria/WEB-INF/lib/primefaces-3.4.2.jar!/META-INF/faces-config.xml
  Cause: Class 'org.primefaces.component.fileupload.FileUploadRenderer' is missing a runtime dependency: java.lang.NoClassDefFoundError: org/apache/commons/fileupload/FileItem. Please see server.log for more details.

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
  <display-name>livraria</display-name>

  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.xhtml</url-pattern>
  </servlet-mapping>

  <context-param>
    <param-name>primefaces.THEME</param-name>
    <param-value>humanity</param-value>
<!--     <param-value>#{temaBean.tema}</param-value> -->
  </context-param>


</web-app>

O problema é que a EL não está sendo avaliada no web.xml. Isso faz com que o nome do tema passado seja branco. Por isso não funciona. Agora, saber porque no seu projeto a EL não está sendo avaliada que é o lance. Eu vi qual versão do servlet container você está usando. Mas você ainda não me disse qual servidor está usando. Qual? Servlet containers mais antigos não interpolam EL.

Desculpe, não deve está entendendo a sua pergunta. Deve ser um erro conceitual meu. Para mim o servlet container seria o tomcat 8.0.30 que eu havia mencionado.

Oi Rogerio,

pelo que vi na mensagem vc está usando Glassfish e nao Tomcat.

Tem como trocar para Tomcat? Glassfish vem com suas próprias implementações do JSF, é vai dar conflito com as dependências que vc definiu no seu pom.xml.

abs

Oi Nico,

Estou usando Tomcat 8.0.30 desde o início. Um dos testes que fiz hoje foi tentar usar o Glassfish, e nele eu obtive a mensagem de erro "cannot Deploy livraria ..." que eu postei.

Abs.

glassfish não!!!!!!!!!!!!!!!!!!! :) A Oracle acabou até com o suporte comercial desse servidor de aplicação!

Continue no Tomcat mesmo... o problema que você teve no Glassfish é de library não encontrada. A versão do seu Tomcat 8.0 está ok, não deve ser esse o problema.

hahahaha.

Nem falo mais em Glassfish então!

Olá,

Ainda não testei minhas próprias sugestões, mas mais uma sugestão é definir o TemaBean como @ApplicationScoped ao invés de @SessionScoped.

E outra coisa, usando projeto Maven, o artefato de temas não se encontra no reposítório do Maven, encontra-se somente no próprio repositório do Primefaces.

Annotation Type ApplicationScoped: https://docs.oracle.com/javaee/7/api/javax/enterprise/context/ApplicationScoped.html

Oi Cassius,

Sua sugestão de colocar @ApplicationScoped não funcionou.

Realmente como Flavio estava suspeitando, a instrução EL não está sendo reconhecida. Não sabemos a razão, pois, o tomcat que estou usando é o 8.0.30. Deveria funcionar.

Abs.

Olá,

Também testei minhas sugestões, mas infelizmente não funcionaram.

Oi Rogerio,

tem como me mandar o seu projeto?

nico.steppat@caelum.com.br

abs

Olá,

Achei a solução, basta implementar somente o getTema do TemaBean, e não implementar o setTema desse. Assim, o EL #{temaBean.tema} não tentará escrever no web.xml, dessa forma, o erro não ocorre.

Olá,

A solução anterior não estava correta. Quando se mudava de tema na página livro.xhtml, não ocorria a alteração de tema na página autor.xhtml . Obviamente, pois havia excluído o método setTema(String tema).

Olá,

Finalmente, consegui resolver os problemas.

  1. O seletor de temas não estava aparecendo devido ao layout;
  2. A aplicação falhava quando pulava de uma página para outra (de livro.xhtml para autor.xhtml e vice-versa).

Abaixo a solução, alterar o trecho _template.xhtml conforme abaixo:

Olá,

Esqueci de colocar o trecho em formato de código, então ai está:

<h:outputStylesheet library="primefaces-#{temaBean.tema}"
        name="theme.css" />
    <div id="cabecalho">
        <h:graphicImage library="img" name="logo.png" />
        <h:form>
            <h:panelGrid columns="2" cellpadding="40">
                <p:themeSwitcher value="#{temaBean.tema}"
                    style="position: absolute; right: 10px;">
                    <f:selectItems value="#{temaBean.temas}" />
                    <p:ajax />
                </p:themeSwitcher>
            </h:panelGrid>
        </h:form>

Oi Cassius,

o problema do Rogerio conseguimos resolver. O erro aconteceu por causa do context-param no web.xml. A expression language nao funciona no web.xml e consequentemente nao achou o tema do primefaces.

A documentacao do primefaces fala que EL no context-param deve rolar mas nem rezando firme funciona!

Resumindo, colocamos o seguinte context-param:

  <context-param>
    <param-name>primefaces.THEME</param-name>
    <param-value>blitzer</param-value>
  </context-param>

Ai tudo funcionou, tbm com Maven. Se quiser te mando o projeto, pode entrar em contato comigo.

Tbm já corrigi a explicação do capitulo.

abs

Olá,

Funciona sim !

Como expliquei acima faltou a linha do h:outputStylesheet e o p:themeSwitcher estar encapsulado por h:form para o valor do tema ser atualizado, caso contrário o setTema recebe null. Também coloquei cellpadding 40 pois o seletor de temas estava escodindo pelo cabeçalho do template.

Abaixo os meus repositório do projeto JSF (baseado em projeto do Eclipse) e do projeto Java EE (baseado em JBoss Forge e Maven):

https://gitlab.com/cviniciusm/jsf-livraria-alura

https://gitlab.com/cviniciusm/relatorio

Agora fiquei confuso de vez :)

Vi que vc está usando JSF 2.2 com Primefaces 5.3, talvez isso seja a razão. Vou investigar isso amanha e darei retorno.

Abs, Nico

Obs: Isso aqui é o post mais longo da historia do Alura!!!

Olá,

Espero que não seja o último ;)

Post longo, mas, produtivo. Obrigado pela colaboração de todos!!!

solução!

Oi Rogerio,

Testei o projeto do Cassius e realmente funciona. E o bizarro é que o seu projeto tbm está funcionando agora!

Tem como fazer um pequeno teste para mim?

Crie na pasta WebContent/META-INF (não WEB-INF) um novo arquivo chamado de context.xml com o conteúdo seguinte:

<?xml version="1.0" encoding="UTF-8" ?>
<Context>
    <Manager pathname="" />
</Context>

Isso faz que o Tomcat não recupera os dados da sessão entre restart. Como o TemaBean fica na sessão o Tomcat tenta recuperar os dados dele. Isso pode atrapalhar.

Depois me fale se ajudou.

Abs, Nico

Oi Nico, Cassius e Flavio,

A alteração que Nico sugeriu resolveu o problema com o EL. E, como Cassuis já havia detectado o problema de posicionamento do componente themeSwitcher no formulário, tudo está funcionando!

Obrigado.