Equivalent of JSP scriptlet method call in JSF - jsf

I need to convert a JSP file to an equivalent JSF file. The JSP is as follows:
Step 1: Class Import:
<%# page import="org.keycloak.constants.ServiceUrlConstants" %>
<%# page import="org.keycloak.common.util.KeycloakUriBuilder" %>
<%# page session="false" %>
<html>
Step 2: Define a variable:
<%
String logoutUri = KeycloakUriBuilder.fromUri("/auth").path(ServiceUrlConstants.TOKEN_SERVICE_LOGOUT_PATH).queryParam("redirect_uri", "/customer-portal").build("demo").toString(); %>
Step 3: Then refers to this variable:
logout
The imported library is an external library into the project. In JSF, I know how to do Step 3. But I don't know how to import the classes in Step 1 and how to define a variable as shown in Step 2 in JSF.
Is there an equivalent way of performing Step 1-3 in JSF? Thank you.

You can't call Methods directly in JSF or create variables, therefore you don't need imports.
The only way is to use EL-Expressions.
Since calling static Methods is not possible with EL, you'll have to create yourself a Bean, that makes the call of KeycloakUriBuilder.fromUri...
With a Named Bean you call its Methods:
Example:
import java.io.Serializable;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
//This Bean is available by default under the Name 'myBean', you can change it in the #Named Annotation if desired
#Named
#RequestScoped
public class MyBean implements Serializable {
public String myMethod(String inupt){
return "Hello " + input;
}
}
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core" >
<head></head>
<body>
<h:outputText value ="#{myBean.myMethod('world')}"/>
</body>
</html>
Will give you this HTML:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head></head>
<body>Hello world
</body>
</html>
The preferred way to show Something on the page is to use getters and setters, if you have a field with getter and Setter
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
You can just use
#{myBean.name}
JSF will call the getter if it needs the value (for output) or call the Setter if there is a value to set (from input-fields)
The <%# page session="false" %> is also neither needed nor possible.
In JSF the Bean has a Scope, this example with RequestScoped should be a good match for <%# page session="false" %> - a Request Scoped Bean lives only for one Request, after that the Bean is disposed. There are many other scopes, e.g. #SessionScoped (from javax.enterprise.context) for a Bean that lives as long as the Session is active.
As mentioned by another User, those Scopes exists in the CDI-Variant (Package javax.enterprise.context) and a JSF-variant (package javax.faces.bean). You should use the CDI-Variant, since the JSF-Variant might be deprecated soon (see here).
Explanation of the Scopes see here.

Related

jsf target unreachable, identifier [bean] resolved to null [duplicate]

This question already has answers here:
Identifying and solving javax.el.PropertyNotFoundException: Target Unreachable
(18 answers)
Closed 4 years ago.
After digging through links such as the following, I'm unable to solve the problem: Identifying and solving javax.el.PropertyNotFoundException: Target Unreachable
I am getting the following error: javax.servlet.ServletException: /Project9.xhtml #13,55 value="#{ProjectBean.income}": Target Unreachable, identifier [ProjectBean] resolved to null
My form:
<!DOCTYPE html>
<html xmlns="http://wwww3.org/1999/xhtml"
xmlns:a="http://xmlns.jcp.org/jsf/facelets"
xmlns:h="http://xmlns.jcp.org/jsf/html"
>
<h:head>
<title>Project9</title>
</h:head>
<h:body>
<h:form>
Income: <h:inputText value="#{ProjectBean.income}"/>
Number of people: <h:inputText value="#{ProjectBean.numPeople}"/>
<h:commandButton value= "Submit" action= "Project9response"/>
</h:form>
</h:body>
</html>
I am not sure whether the right convention is wwww3.org or www.3.org but I have tried them both.
My Response page:
<!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:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:h="http://xmlns.jcp.org/jsf/html"
>
<h:head>
<title><ui:insert name="title">Project 9 response</ui:insert></title>
</h:head>
<h:body>
Am I above the poverty level: #{ProjectBean.abovePovertyLevel()}
</h:body>
</html>
My Bean:
#ManagedBean
#SessionScoped
public class ProjectBean implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private double income;
private double numPeople;
//constructor is no arg
public ProjectBean() {
}
public double getIncome() {
return income;
}
public void setIncome(double income) {
this.income = income;
}
public double getNumPeople() {
return numPeople;
}
public void setNumPeople(double numPeople) {
this.numPeople = numPeople;
}
public boolean abovePovertyLevel() {
if ( income < (16460.00 + 4320.00) * (numPeople - 2)){
return false;
}
else {
return true;
}
}
}
My faces-config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<faces-config
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_3.xsd"
version="2.3">
</faces-config>
I have my faces-config.xml and my javax-faces.2.2.8.jar file in the lib folder of WEB-INF
I have my bean in the src folder of Java Resources
I have another project called helloworld with several little JSF projects that all work, and I have tried copying project9 into helloworld and running it, but I get the same error only on that project
I have tried cleaning my project as people have suggested
This is a student project and my first introduction to JSF and Tomcat. I'm using a Mac and Eclipse photon.
As I stated in a comment in my code, if I try to bypass the response xhtml file and go straight to the javabean method in my html form, I get an underline under ProjectBean.abovePovertyLevel() and the error "the action value does not match a navigation case outcome"
I'm not sure of some of the answers in the link above regarding CDI, etc, that all is above my head at this point.
Nevermind, I JUST solved this
Added a name to my annotation as such: #ManagedBean(name="ProjectBean")
Also I realized that my method was wrong if I didn't declare poverty level first
int povertyLevel = (16460 + 4230 * (numPeople-2));
if(income > povertyLevel)
return true;
else{
return false;
}
This seemed to work
Replace all the #{ProjectBean. by #{projectBean. (make the first character lowercase).
This is because you need to refer to the managed bean by name, not by the classname. By default, jsf will generate this name for you, as per the docs at https://docs.oracle.com/javaee/6/api/javax/faces/bean/ManagedBean.html :
If the value of the name attribute is unspecified or is the empty String, the managed-bean-name is derived from taking the unqualified class name portion of the fully qualified class name and converting the first character to lower case. For example, if the ManagedBean annotation is on a class with the fully qualified class name com.example.Bean, and there is no name attribute on the annotation, the managed-bean-name is taken to be bean.

JSF access private/protected property of a super class

I am very new to JSF and this is the first project I work on (got a bit too lazy with jsp) so please forgive me if the question is trivial.
So I have a Super Class Device
#Entity
#Table(name = "Devices")
public class Device
{
protected bool Authorized
public bool isAuthorized()
{ return this.Authorized;}
public void setAuthorized(bool Authorized)
{ this.Authorized = Authorized;}
}
and a sub class SensorDevice that extends the Super Class Device
public class SensorDevice extends Device
{
// has its own properties which dont matter
}
and a Managed Bean UIDeviceManager
#ManagedBean(name = "DeviceManager")
#SessionScoped
public class UIDeviceManager
{
private List<SensorDevice> Pending;
// in constructor, Pending List gets populated with the devices requiring Authorization
}
and an xhtml page which contains a Table for the Pending Devices
<p:dataTable var="device" value="#{DeviceManager.pending}">
<p:column headerText="Device Authorization">
<h:form>
<p:inputSwitch
value="#{device.isAuthorized()}"
binding="#{AuthorizationInputSwitch}"
offLabel="UnAuthorized"
onLabel="Authorized">
<p:ajax
event="change"
listener="#{device.setAuthorized(AuthorizationInputSwitch.value)}" />
</p:inputSwitch>
</h:form>
</p:column>
Now unless the syntax in the xhtml is completely messed up (I tried my best there and would appreciate guidance), the function setAuthorized for that particular device instance should be called (even with the wrong input, but will sort that later by modifying the setter function), but that doesnt happen, the Ajax doesnt get called. Instead, the inputSwitch tries to update its "value property source" and attempts to look for a property isAuthorized() in the class SensorDevice which it fails to find.
Now I am aware that this could be easily solved by making the Boolean Authorized public in the super class but as you can see it is also a JPA entity that is persisted in a database to keep track of the devices, so the only option is to keep it protected.
So how do I update parameters of a Super class from a sub-class instance in a Managed Bean from a public function rather than direct access to the parameter itself (I thought JSF looked for the setters and getters but whatever)
Btw value="#{device.isAuthorized()}"works correctly but if I try the property directly it fails ( I guess its obvious at this point )
One last thing, if the approach/architecture is wrong, please advise on what is the correct layout to achieve this functionality. I am sure there is a standard way to integrate JSF and JPA without duplicating entities and wrappers
I think you must use field name in value attribute of InputSwitch component like this:
<p:inputSwitch
value="#{device.authorized}"
binding="#{AuthorizationInputSwitch}"
offLabel="UnAuthorized"
onLabel="Authorized">
Instead of:
<p:inputSwitch
value="#{device.isAuthorized()}"
binding="#{AuthorizationInputSwitch}"
offLabel="UnAuthorized"
onLabel="Authorized">
JSF will use isAuthorized and setAuthorized method (uses Java Beans standard convention to recognize getter and setter methods)
So i think you don't need the ajax part to call setter method.
To emphasize Mojtaba's answer, this is how you access properties in JSF:
Facelets page:
<?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">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:outputText value="#{myBean.entity.someBool}"/>
</h:body>
</html>
Managed bean:
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean
#SessionScoped
public class MyBean {
private SomeEntity entity = new SomeEntity();
public SomeEntity getEntity() {
return entity;
}
}
Entity classes:
public class SomeEntity extends SomeParent {
}
public class SomeParent {
private boolean someBool = true;
public boolean isSomeBool() {
return someBool;
}
public void setSomeBool(boolean someBool) {
this.someBool = someBool;
}
}
JSF doesn't know or care that your objects are JPA entities, and standard inheritance and access rules apply.
See also
JavaBean conventions

How and when is a view scope bean removed from LRU cache in JSF?

I have read an excellent answer when view scoped bean is destroyed. (see How and when is a #ViewScoped bean destroyed in JSF?) and I automatically assumed that destroyed bean is also removed from the view scope cache. But I could see that bean is still in the cache, so I would like to know if destroyed view scoped bean should be also removed from the LRU view scope cache, if ever?
In our application we open all details in sepeare tabs/windows. After some opening/closing (depends on numberOfViewsInSession) we could see ViewExpiredException in case when the first detail window is still opened and user has been opening and closing another detail windows and after some time he wants to do some operation in the first window. I have done some debugging and I can see that closed view wasn't removed from the LRU cache.
So is it expected behaviour or is there something wrong in my code? And if it is expected behaviour, is there any useful strategy how to work with multitabs/multiwindow without lot of ViewExpiredException caused by the LRU cache?. I know I can change numberOfViewsInSession but it is the last choice that I want to use.
I prepared a simple testcase and when I'm opening/closing view.xhtml more times, I can see that LRUMap is growing.
Environment : JDK7, mojarra 2.2.4, tomcat 7.0.47
Thanks in advance
view.xhtml
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://xmlns.jcp.org/jsf/html">
<head>
<title>View Bean</title>
<meta charset="UTF-8"/>
</head>
<body>
<h:form id="viewForm">
<div>#{viewBean.text}</div>
<h:commandButton id="closeButton" value="Close" action="/ClosePage.xhtml"/>
</h:form>
</body>
</html>
index.xhtml
<!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://xmlns.jcp.org/jsf/html">
<h:head>
<title>Session bean</title>
</h:head>
<h:body>
<h:form id="sessionForm">
<h:outputText value="#{sessionBean.text}"/>
<br/>
<h:link id="linkView" value="Open view.xhmtl" outcome="/view.xhtml" target="_blank"/>
</h:form>
</h:body>
</html>
ClosePage.xhmtl
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head><title>Window will be closed</title></head>
<body>
<script>window.close();</script>
</body>
</html>
ViewBean.java
package com.mycompany.mavenproject2;
import com.sun.faces.util.LRUMap;
import java.io.Serializable;
import java.util.Map;
import javax.annotation.PreDestroy;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
#ManagedBean(name = "viewBean")
#ViewScoped
public class ViewBean implements Serializable {
private static final long serialVersionUID = 13920902390329L;
private int lruMapSize;
/**
* Creates a new instance of ViewBean
*/
public ViewBean() {
Map<String, Object> sessionMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
LRUMap<String, LRUMap> lruMap = (LRUMap) sessionMap.get("com.sun.faces.renderkit.ServerSideStateHelper.LogicalViewMap");
lruMapSize = lruMap == null ? 0 : lruMap.size();
}
#PreDestroy
void destroyed() {
System.out.println("View bean destroyed");
}
public String getText() {
return "ViewBean LRU cache size:" + Integer.toString(lruMapSize);
}
}
SessionBean.java
package com.mycompany.mavenproject2;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean(name = "sessionBean")
#SessionScoped
public class SessionBean implements Serializable {
private static final long serialVersionUID = 1777489347L;
/**
* Creates a new instance of SessionBean
*/
public SessionBean() {
}
public String getText() {
return "Session bean text";
}
}
I think every JSF developer runs up against this eventually. The true problem lies in the fact that you can't devise a truly reliable stateful system in which the browser will signal back to the ViewScoped bean that it is done with the page, allowing the backing bean to destroy itself. This is why JSF implementations have LRU caches to limit the memory used by a session, which is a great catch-all solution for everyday apps.
There are a few cases in which you know that you are done with the ViewScoped bean, such as a redirect from that bean. For these, you could write your own view handler to perform a smarter caching system, but that's not a trivial task, and frankly, not worth the effort.
The simplest solution I came up with is to use a javascript timer to execute an ajax postback to the server on every page with a ViewScoped bean. (Setting this timer to execute every 30 seconds seems reasonable.) This will move the ViewScoped bean(s) associated with the page to the bottom of the LRU cache, ensuring they aren't expired.
In particular, I use a primefaces poll component to pull this off and stick in a template to be used by all ViewScoped beans. By placing this component in its own form, the request size remains small.

jsf bean not working

This is my xhtml:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>Keep alive</title>
</h:head>
<f:metadata>
<f:viewParam name="value" id="value" value="#{myBean.val}" ></f:viewParam>
</f:metadata>
<h:body>
Hello.<h:form><h:outputLabel value="#{myBean.val}"></h:outputLabel></h:form>
</h:body>
</html>
And this is my bean:
import javax.faces.bean.RequestScoped;
import javax.faces.bean.ManagedBean;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
#RequestScoped
#ManagedBean
public class MyBean {
#PersistenceContext(unitName = "myPUhere")
private EntityManager em;
/**
* Creates a new instance of myBean
*/
public MyBean() {
System.out.println("mybeanload");
if (getWaarde() == "yes") {
System.out.println("IT WORKS!!");
}
}
private String val;
public String getVal() {
System.out.println("getting value");
return val;
}
public void setVal(String value) {
System.out.println("setting value to " + value);
this.val = value;
}
}
My Bean does not respond to this, what don't I see here? It does not display the value I enter in the URL, nor it displays my outputLabel.
So, you're retrieving the raw JSF source code in the browser instead of its generated HTML output. Browsers obviously don't understand JSF code (like as it doesn't understand JSP/PHP/ASP/etc code), but it only understands HTML code. This can happen when the FacesServlet hasn't been invoked, it's namely the one responsible for all the JSF works.
Perhaps your FacesServlet is based on some tutorial or IDE-autogenerated code been mapped on an URL pattern different than *.xhtml, such as *.jsf or *.faces. In that case, you've 2 options:
Fix the request URL in your browser's address bar to match exactly that URL pattern. So, assuming that it's *.jsf, then don't open the page by
http://localhost:8080/context/index.xhtml
but instead by
http://localhost:8080/context/index.jsf
Fix the URL pattern to be *.xhtml directly. This wasn't possible back in JSF 1.x as the FacesServlet would otherwise call itself in an infinite loop, but this is quite possible in JSF 2.x and a lot of books/tutorials/resources/IDEs didn't take this into account.
<url-pattern>*.xhtml</url-pattern>
See also:
JSF Facelets: Sometimes I see the URL is .jsf and sometimes .xhtml. Why?

valueChangeListener method is called on selectOneMenu even though I have not changed the value

I have the following problem. When I click the button "Enviar", this calls another method that is associated to a selectOneMenu (in the attribute
valueChangeListener called "validarSelect"), and later, calls the method that this button has associated in the attribute actionListener called "validarBoton".
I wonder, why this happens. I expect the valueChangeListener to be not called since I have not changed the dropdown.
This is my page JSF:
<?xml version='1.0' encoding='windows-1252'?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<f:view xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html">
<html xmlns="http://www.w3.org/1999/xhtml">
<h:head></h:head>
<h:body>
<h:form>
<h:commandButton value="Enviar..." id="validar" actionListener="#{Domiciliacion.validarBoton}"/>
<h:selectOneMenu valueChangeListener="#{Domiciliacion.validarSelect}"
binding="#{Domiciliacion.selectCombo}">
<f:selectItems value="#{Domiciliacion.lista}"/>
<f:ajax event="valueChange" render="#this"/>
</h:selectOneMenu>
</h:form>
</h:body>
</html>
And this, is the ManagedBean:
package domiciliaciontest;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.component.html.HtmlSelectOneMenu;
import javax.faces.event.ActionEvent;
import javax.faces.event.ValueChangeEvent;
#ManagedBean(name = "Domiciliacion")
#ViewScoped
public class MB0001 {
private HtmlSelectOneMenu selectCombo;
private List<String> lista = new ArrayList<String>();
public MB0001() {
super();
System.out.println("Entro al constructor...");
lista.add("Caracas");
lista.add("Bogota");
lista.add("Santiago");
}
public void validarBoton(ActionEvent actionEvent) {
System.out.println("Entro a validarBoton...");
// Add event code here...
}
public void validarSelect(ValueChangeEvent valueChangeEvent) {
// Add event code here...
System.out.println("Entro a validarSelect...");
}
public void setSelectCombo(HtmlSelectOneMenu selectCombo) {
this.selectCombo = selectCombo;
}
public HtmlSelectOneMenu getSelectCombo() {
return selectCombo;
}
public void setLista(List<String> lista) {
this.lista = lista;
}
public List<String> getLista() {
return lista;
}
}
this is the output when I click the button "Enviar":
Entro a validarSelect...
Entro a validarBoton...
The valueChangeListener method will be invoked when the submitted value is different from the initial value, regardless of whether you have changed it yourself or not. So, if the currently submitted value (which is "Caracas" in your case) is different from the initial value (which is null in your case), then the valueChangeListener method will be invoked.
See also:
When to use valueChangeListener or f:ajax listener?
Best way to add a "nothing selected" option to a selectOneMenu in JSF
Unrelated to the concrete problem, seeing this in combination with binding attribute gives me the impression that you're trying to achieve something which you've read in an article or answer targeted on JSF 1.x. This is namely recognizeable as part of a hack to populate child dropdowns in JSF 1.x. You do not need this approach for JSF 2.x. Further, your method names with "validar" ("validate") are misleading. Don't you actually need a fullworthy Validator? But as said, that's a different problem.
See also:
Make multiple dependent / cascading selectOneMenu dropdown lists in JSF

Resources