我正在练习JSF + JPA并遇到以下异常:
19/03/2013 00:04:18 org.apache.catalina.core.StandardWrapperValve invoke
GRAVE: Servlet.service() for servlet [Faces Servlet] in context with path [/K19-Futebol] threw exception [/times.xhtml @11,60 <ui:include src="formulario-novo-time.xhtml"> Invalid path : formulario-novo-time.xhtml] with root cause
javax.faces.view.facelets.TagAttributeException: /times.xhtml @11,60 <ui:include src="formulario-novo-time.xhtml"> Invalid path : formulario-novo-time.xhtml
[...]
at filters.JPAFilter.doFilter(JPAFilter.java:42)
[...]
当我按照BalusC链接(How to include another XHTML in XHTML using JSF 2.0 Facelets?)时,我认为问题与Facelets无关,但是这个过滤器:
@WebFilter(servletNames = {"Faces Servlet"})
public class JPAFilter implements Filter {
private EntityManagerFactory factory;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.factory = Persistence.createEntityManagerFactory("K19-Futebol-PU");
}
@Override
public void destroy() {
this.factory.close();
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// CHEGADA
EntityManager manager = this.factory.createEntityManager();
request.setAttribute("EntityManager", manager);
manager.getTransaction().begin();
// CHEGADA
// FACES SERVLET
chain.doFilter(request, response);
// FACES SERVLET
// SAÍDA
try {
manager.getTransaction().commit();
} catch (Exception e) {
manager.getTransaction().rollback();
} finally {
manager.close();
}
// SAÍDA
}
}
我也问你的意见,如果以这种方式使用过滤器是一个很好的实践,我的意思是,使用模型/持久层的过滤器。
其他要澄清的课程:
@Entity
public class Time implements Serializable { //in portuguese 'Time' means Team (e.g.:football Team)
@Id
@GeneratedValue
private Long id;
private String nome;
private String tecnico;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getTecnico() {
return tecnico;
}
public void setTecnico(String tecnico) {
this.tecnico = tecnico;
}
}
托管bean:
@ManagedBean
public class TimeBean {
public Time getTime() {
return time;
}
public void setTime(Time time) {
this.time = time;
}
public void setTimes(List<Time> times) {
this.times = times;
}
private Time time = new Time();
private List<Time> times;
public void adiciona() {
EntityManager manager = this.getManager();
TimeRepository repository = new TimeRepository(manager);
if (this.time.getId() == null) {
repository.adiciona(this.time);
} else {
repository.atualiza(this.time);
}
this.time = new Time();
this.times = null;
}
public void preparaAlteracao() {
Map<String, String> params = FacesContext.getCurrentInstance()
.getExternalContext().getRequestParameterMap();
Long id = Long.parseLong(params.get("id"));
EntityManager manager = this.getManager();
TimeRepository repository = new TimeRepository(manager);
this.time = repository.procura(id);
}
public void remove() {
Map<String, String> params = FacesContext.getCurrentInstance()
.getExternalContext().getRequestParameterMap();
Long id = Long.parseLong(params.get("id"));
EntityManager manager = this.getManager();
TimeRepository repository = new TimeRepository(manager);
repository.remove(id);
this.times = null;
}
public List<Time> getTimes() {
if (this.times == null) {
EntityManager manager = this.getManager();
TimeRepository repository = new TimeRepository(manager);
this.times = repository.getLista();
}
return this.times;
}
private EntityManager getManager() {
FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext ec = fc.getExternalContext();
HttpServletRequest request = (HttpServletRequest) ec.getRequest();
return (EntityManager) request.getAttribute(" EntityManager ");
}
}
“存储库”类:
public class TimeRepository {
private EntityManager manager;
public TimeRepository(EntityManager manager) {
this.manager = manager;
}
public void adiciona(Time time) {
this.manager.persist(time);
}
@SuppressWarnings("unchecked")
public void remove(Long id) {
Time time = this.procura(id);
Query query = this.manager.createQuery("select x from Jogador x");
List<Jogador> jogadores = query.getResultList();
for (Jogador jogador : jogadores) {
jogador.setTime(null);
}
this.manager.remove(time);
}
public Time atualiza(Time time) {
return this.manager.merge(time);
}
public Time procura(Long id) {
return this.manager.find(Time.class, id);
}
@SuppressWarnings("unchecked")
public List<Time> getLista() {
Query query = this.manager.createQuery("select x from Time x");
return query.getResultList();
}
}
我该如何解决这个问题?
答案 0 :(得分:4)
javax.faces.view.facelets.TagAttributeException:/times.xhtml @ 11,60
<ui:include src="formulario-novo-time.xhtml">
路径无效:formulario-novo-time.xhtml
此问题不是由过滤器引起的。它恰好位于调用堆栈中,因为它是在faces servlet之前调用的。
当FaceletContext#includeFacelet()
投掷IOException
时,将抛出此特定异常。遗憾的是,此IOException
未被包装为根本原因,它仅记录在FINE
级别。您可能需要启用FINE
(或ALL
)日志记录才能查看。另请参阅此答案如何为JSF配置日志记录:JSF2 logs with tomcat
最常见的原因之一是文件不在您认为的位置。例如。路径真的无效。相对于父文件的路径解析<ui:include>
路径。您应该努力在<ui:xxx>
标记中使用绝对路径,以避免在重构文件层次结构时出现维护问题,即使用/
启动路径,从而基本上使其相对于webcontent根目录。 E.g。
<ui:include src="/WEB-INF/includes/foo.xhtml" />
如果你绝对肯定路径是正确的,另一个可能的原因是使用未知或错误的字符编码保存了所需的包含文件,这在解析XML树期间会导致问题。您需要验证编辑器是否已正确配置为将所有文件保存为UTF-8。