How to reference static variables using EL 3.0? - java

I am trying to get a static variable in my JSF page.
I followed instructions on this post. I am able to get the variables using the Primefaces extension, however, I am not getting anything in the xhtml when doing the following.
I have a constants file:
public class Test {
public static final String NAME = "EL Test";
}
And following the post by balusC, I added an application scoped bean (however, this is being called with every request):
import java.lang.reflect.Field;
import javax.annotation.PostConstruct;
import javax.el.ELContextEvent;
import javax.el.ELContextListener;
import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;
import javax.faces.context.FacesContext;
#ManagedBean(eager = true)
#ApplicationScoped
public class Config {
#PostConstruct
public void init() {
FacesContext.getCurrentInstance().getApplication().addELContextListener(new ELContextListener() {
#Override
public void contextCreated(ELContextEvent event) {
event.getELContext().getImportHandler().importClass("my.package.constants.Test");
Class<?> clazz = event.getELContext().getImportHandler().resolveClass("Test");
for (Field field : clazz.getFields()) {
System.out.println(field.getName());
}
System.out.println("clazz = " + clazz);
System.out.println(clazz.getPackage());
}
});
}
}
And my xhtml page:
<!DOCTYPE html >
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
<meta charset="utf-8"></meta>
<meta http-equiv="X-UA-Compatible" content="IE=edge"></meta>
<meta name="viewport" content="width=device-width, initial-scale=1"></meta>
</h:head>
<h:body>
<h:outputText value="#{Test}"></h:outputText>
<h:outputText value="#{Test.NAME}"></h:outputText>
</h:body>
</html>
Is there anything I am missing?

p:importConstants was added in PrimeFaces 6.x.
XHTML:
<p:importConstants type="com.example.Constants" var="Constants" />
<h:outputText value="#{Constants.TEST}" />
Java:
package com.example;
public class Constants {
public final static String TEST = "Imported Constant";
}

JSF 2.3 supports referencing static variables in EL using the f:importConstants tag.
Your constants file
public class Test {
public static final String NAME = "EL Test";
}
can be imported in the view by adding the following metadata.
<f:metadata>
<f:importConstants type="mypackage.Test" />
</f:metadata>
And then be referenced using EL.
#{Test.NAME}
So your view becomes:
<!DOCTYPE html >
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<f:metadata>
<f:importConstants type="mypackage.Test" />
</f:metadata>
<h:head>
<meta charset="utf-8"></meta>
<meta http-equiv="X-UA-Compatible" content="IE=edge"></meta>
<meta name="viewport" content="width=device-width, initial-scale=1"> </meta>
</h:head>
<h:body>
<h:outputText value="#{Test.NAME}"></h:outputText>
</h:body>
</html>
Source: Arjan Tijms' Weblog.

You can use o:importConstants by omnifaces for that
For example:
public class Foo {
public static final String FOO1 = "foo1";
public static final String FOO2 = "foo2";
}
public interface Bar {
public String BAR1 = "bar1";
public String BAR2 = "bar2";
}
public enum Baz {
BAZ1, BAZ2;
}
The constant field values of the above types can be mapped into the request scope as follows:
<o:importConstants type="com.example.Foo" />
<o:importConstants type="com.example.Bar" />
<o:importConstants type="com.example.Baz" var="Bazzz" />
...
#{Foo.FOO1}, #{Foo.FOO2}, #{Bar.BAR1}, #{Bar.BAR2}, #{Bazzz.BAZ1}, #{Bazzz.BAZ2}

As I see you're using JSF 2, you could go with the Omnifaces library:
public class Test {
public static final String NAME = "EL Test";
}
Then in the facelet:
<o:importConstants type="com.example.Test " />
#{Test.NAME}
Otherwise, if you want to avoid using third party libraries, use an #ApplicationScoped managed bean with a getter for this aim:
#ManagedBean
#ApplicationScoped
public class Test{
public static final String name = "EL Test";
public String getName(){
return name;
}
}
Which you can reference with:
#{test.name}
See also:
The importConstants tag

Related

PrimeFaces 6.2 issue with CDI Conversations

I updated the PrimeFaces version to 6.2. Everything went good, except for an issue with CDI conversations management.
After the update, it seems like the conversation is initialized at the first access to a page, but it is lost just before the first call to the controller. In fact, when accessing to a page a new conversation is been initialized (and this is correct). But after the first call to a controller method a new conversation is initialized, losing the previous one and all its parameter values. The following calls maintain the last conversation as usual.
With PrimeFaces 6.1 (and previous) this never happened.
Is this a bug or a lack of mine?
After the access to the page, the text displayed is "Init value with conversation id = 1".
By clicking the button, the displayed text changes to "Value set with conversation id = 2".
The following clicks mantain the cid = 2.
Controller
#Named
#ConversationScoped
#LoggedIn
public class TestController implements Serializable {
static final long serialVersionUID = 69823746898775L;
#Inject protected Conversation conversation;
#Inject protected FacesContext facesContext;
rivate String outputValue;
#PostConstruct
public void init() throws IOException {
if (conversation.isTransient()) {
conversation.begin();
conversation.setTimeout(1800000);
}
outputValue = "Init value with conversation id = " + conversation.getId();
}
public void handleCall() {
outputValue = "Value set with conversation id = " + conversation.getId();
}
public String getOutputValue() {
return outputValue;
}
public void setOutputValue(String outputValue) {
this.outputValue = outputValue;
}
}
JSF page
<?xml version="1.0" encoding="UTF-8"?>
<f:view xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui" contentType="text/html">
<html>
<h:head>
<meta http-equiv="X-UA-Compatible" content="IE=8" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="shortcut icon" type='image/x-icon' href='favicon.ico'/>
<ui:insert name="head" />
</h:head>
<h:body onload="javascript: if ('#{param.sessionExpired}'.length != 0) PF('loginDialog').show()">
<h:form id="testForm">
<p:commandButton action="#{testController.handleCall()}" value="Make a call" update="#form" />
<h:outputText value="#{testController.outputValue}" />
</h:form>
</h:body>
</html>
</f:view>

Primefaces datatable onrowselect event doesn't work in IE 8

I'm trying to make the following code work in IE 8 with no result (though it works in Google chrome fine):
xhtml:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
</h:head>
<h:body>
<h:form id="form">
<p:dataTable id="eventsDT" var="answer" value="#{verify.answers}" rowKey="#{answer.id}" selectionMode="single" >
<p:ajax event="rowSelect" listener="#{verify.onRowSelectTest}" />
<p:column headerText="Id">
<h:outputText value="#{answer.id}" />
</p:column>
<p:column headerText="Text">
<h:outputText value="#{answer.text}" />
</p:column>
</p:dataTable>
</h:form>
</h:body>
</html>
Answer.java:
package ru.trust.appVerification;
public class Answer {
private int id;
private String text = "Undefined";
public Answer(int id, String text) {
this.id = id;
this.text = text;
}
public int getId() {
return id;
}
public String getText() {
return text;
}
public void setId(int id) {
this.id = id;
}
public void setText(String text) {
this.text = text;
}
}
Verify.java
package ru.trust.appVerification;
import java.io.Serializable;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.*;
import java.util.stream.*;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.AjaxBehaviorEvent;
import org.primefaces.event.SelectEvent;
#ManagedBean
#ViewScoped
public class Verify implements Serializable {
public List<Answer> getAnswers() {
List<Answer> answers = new ArrayList<Answer>();
answers.add(new Answer(1, "Yes"));
answers.add( new Answer(2, "No"));
return answers;
}
public void onRowSelectTest(SelectEvent event) {
Answer answer = (Answer)event.getObject();
}
}
Is anything wrong in my code or Internet Explorer 8 does not support it at all?
Try adding this at the top of your xhtml :
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<f:facet name="first">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta content="text/html; charset=UTF-8" http-equiv="content-type"/>
</f:facet>
// other head code goes here
</h:head>
in place of :
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
</h:head>
I had a similar issue.Adding this worked fine for me.

ConversationScoped bean action not fired using a rendered commandlink

I'm having trouble understanding why a action method on my ConversationScope'd bean doesnt fire. The bean is:
package org.work;
import java.io.Serializable;
import javax.enterprise.context.ConversationScoped;
import javax.faces.event.ComponentSystemEvent;
import javax.inject.Named;
#Named
#ConversationScoped
public class NewClass implements Serializable {
private static final long serialVersionUID = 6470665657635110586L;
private boolean b1;
public boolean isB1() {
return b1;
}
public void setB1(boolean b1) {
this.b1 = b1;
}
public void preRenderView(ComponentSystemEvent evt) {
}
public String peformAction() {
return null;
}
}
and my XHTML is:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<f:view>
<h:head>
</h:head>
<f:metadata>
<f:viewParam name="b1"
value="#{newClass.b1}" />
<f:event type="preRenderView"
listener="#{newClass.preRenderView}"/>
</f:metadata>
<h:body>
<h:form>
<h:commandLink action="#{newClass.setB1(!newClass.b1)}"
style="background-color: #{newClass.b1 ? 'darkorchid' : 'aquamarine'};"
value="btn3"/>
<h:panelGrid rendered="#{newClass.b1}"
columns="1">
<h:commandLink value="edit"
action="#{newClass.peformAction()}" />
</h:panelGrid>
</h:form>
</h:body>
</f:view>
</html>
The performAction() method is not fired after I press the commandLink that should invert the boolean making the other commandLink rendered. When debugging I can see that the boolean is set to true, but it seems to me the "rendered" attribute is evaluated before the viewparams is set. Is this true?
The example works fine with #ManagedBean and #javax.faces.bean.ViewScoped.
I think that you don't have long-running conversation. You could read more information on this site: http://docs.oracle.com/javaee/6/api/javax/enterprise/context/ConversationScoped.html
If you have transient conversation this bean is recreated after every request

Ajax is not working with richfaces

I'm trying to use AJAX to change the content of my page and include some other contents, but it just does not work. I tried a lot of different solutions. I need that my menuItem_Cursos call that managed bean changePage and render the component panelGroup_Target. When i try to debug the java it just doesn't get there. Please help.
This is the page
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:rich="http://richfaces.org/rich"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:a4j="http://richfaces.org/a4j">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>PenSAE</title>
<f:metadata>
<f:event listener="#{logon.verificaLogon}" type="preRenderView" />
</f:metadata>
<h:outputScript name="common.js" />
</h:head>
<h:body>
<f:view id="view_Principal">
<rich:toolbar id="toolbar_Principal" itemSeparator="">
<rich:menuItem id="menuItem_Cursos" label="Cursos" mode="ajax"
actionListener="#{principalProfessor.changePage}" render="panelGroup_Target"/>
<rich:menuItem id="menuItem_Estudos" label="Estudos de Casos"
value="Estudos de Casos" />
<rich:dropDownMenu id="dropDownMenu_Acompanhamento"
label="Acompanhamento" value="Acompanhamento" mode="ajax">
<rich:menuItem label="Acompanhamento por Estudante" />
<rich:menuItem label="Acompanhamento por Estudo de Caso" />
</rich:dropDownMenu>
<rich:dropDownMenu id="dropDownMenu_Sobre" label="Sobre o Sistema"
value="Sobre o Sistema">
<rich:menuItem label="Mapa do Software" />
<rich:menuItem label="Ajuda" />
</rich:dropDownMenu>
</rich:toolbar>
<h:panelGroup id="panelGroup_Target">
<rich:panel rendered="#{principalProfessor.page == 'listaCursos'}">
<ui:include src="#{principalProfessor.page}" />
</rich:panel>
</h:panelGroup>
</f:view>
</h:body>
</html>
And this is my java code:
package magicBeans.professor;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.ActionEvent;
import classesBasicas.Curso;
import classesBasicas.Pessoa;
import fachada.Fachada;
/**
* #author Jesus
*
*/
#ManagedBean(name="principalProfessor")
#ViewScoped
public class PrincipalProfessorBean {
#SuppressWarnings("unused")
private static Fachada fachada;
private Pessoa usuarioLogado;
private Curso curso;
private String page = "";
public PrincipalProfessorBean(){
fachada = Fachada.getInstance();
}
/**
* #return the usuarioLogado
*/
public Pessoa getUsuarioLogado() {
return usuarioLogado;
}
/**
* #param usuarioLogado the usuarioLogado to set
*/
public void setUsuarioLogado(Pessoa usuarioLogado) {
this.usuarioLogado = usuarioLogado;
}
/**
* #return the curso
*/
public Curso getCurso() {
return curso;
}
/**
* #param curso the curso to set
*/
public void setCurso(Curso curso) {
this.curso = curso;
}
public String getPage() {
return page;
}
public void setPage(String page) {
this.page = page;
}
public void changePage() {
page = "listaCursos.xhtml";
System.out.println("AJAX PEGOU!");
}
}
Thanks to chrome (ctrl+shift+j) on chrome, the console told that it needed a form around anything with ajax to work. =]

Passing a backing bean instance as parameter for another backing bean method

After the user fills my backing bean with info through the forms, I want to process the instance in Java code (such as JAXB marshalling).
So at the moment i'm doing this like so:
<% OtherBean.method(myBackingBean); %>
which is - if i'm right - not quite an up to date solution :) So how can I make this happen in a 'better' way?
Thanks in advance,
Daniel.
One solution is to add an action method to the bean - it is possible to have it process itself.
For example, this simple bean:
public class SimpleBean {
private String forename;
private String surname;
public String processData() {
// TODO: real work
System.out.println("forename=" + forename);
System.out.println("surname=" + surname);
return null; // optional navigation rule
}
public String getForename() {
return forename;
}
public void setForename(String forename) {
this.forename = forename;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
}
...defined in WEB-INF/faces-config.xml:
<managed-bean>
<managed-bean-name>simpleBean</managed-bean-name>
<managed-bean-class>simplebean.SimpleBean</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
...can be processed using the this JSP:
<?xml version="1.0" encoding="UTF-8" ?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<jsp:directive.page language="java"
contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" />
<jsp:text>
<![CDATA[<?xml version="1.0" encoding="UTF-8" ?>]]>
</jsp:text>
<jsp:text>
<![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">]]>
</jsp:text>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Enter Name</title>
</head>
<body>
<f:view>
<h:form>
<h:panelGrid columns="2">
<h:outputText value="forename:" />
<h:inputText id="it1" value="#{simpleBean.forename}" />
<h:outputText value="surname:" />
<h:inputText id="it2" value="#{simpleBean.surname}" />
</h:panelGrid>
<h:commandButton action="#{simpleBean.processData}"
value="process" />
</h:form>
</f:view>
</body>
</html>
</jsp:root>
Note the method binding #{simpleBean.processData}. This must be a public method that takes no arguments and returns a String argument (which can be used for page navigation if desired).
This isn't the only way to go about this, but it is fairly straightforward.
you could have one backing bean as an instance variable of the other bean. and configure it in spring or whatever you are using.

Categories

Resources