How to use abstract class as CDI managed bean in JSF view - jsf

Can I use abstract class as CDI managed bean in JSF view? I want set or override attribute in derived class and use it in JSF page of parent abstract class. Derived view to set context which template parent view must show as common part all childs .
I heard that i can use abstract class with #Named annotation in JSF view, but i get error
Target Unreachable, identifier 'viewModel' resolved to null
If I change the abstract class to a typical class then its work. May be using abstract class in JSF view impossible?
ViewModel.java
#Named
#ConversationScoped
#Inherited
#Documented
#Stereotype
#Target({ TYPE })
#Retention(RUNTIME)
public abstract class ViewModel {
private String foo;
public void setFoo(String foo) {
this.foo = foo;
}
public String getFoo() {
return foo;
}
abstract void bar();
}
DerivedViewModel.java
#Named
#ConversationScoped
#Inherited
#Documented
#Stereotype
#Target({ TYPE })
#Retention(RUNTIME)
public class DerivedViewModel extends ViewModel {
public void init() {
this.setFoo("Foo");
}
#Override
void bar() {;}
}
View.xhtml
<ui:composition 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:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:fn="http://xmlns.jcp.org/jsp/jstl/functions" xmlns:pt="http://xmlns.jcp.org/jsf/passthrough"
xmlns:p="http://primefaces.org/ui" xmlns:pe="http://primefaces.org/ui/extensions"
xmlns:sys="http://argustelecom.ru/system" xmlns:o="http://omnifaces.org/ui">
<ui:param name="viewModel" value="#{viewModel}" />
<ui:define name="body">
<h:outputText value="#{viewModel.foo}" />
<ui:insert name="derived" />
</ui:define>
</ui:composition>
DerivedView.xhtml
<ui:composition template="View.xhtml" 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:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:fn="http://xmlns.jcp.org/jsp/jstl/functions" xmlns:pt="http://xmlns.jcp.org/jsf/passthrough"
xmlns:p="http://primefaces.org/ui" xmlns:pe="http://primefaces.org/ui/extensions"
xmlns:sys="http://argustelecom.ru/system" xmlns:o="http://omnifaces.org/ui">
<ui:param name="viewModel" value="#{derivedViewModel}" />
<ui:define name="metadata">
<f:metadata>
<f:viewAction action="#{derivedViewModel.init()}"/>
</f:metadata>
</ui:define>
<ui:define name="derived">
blablabla
</ui:define>
</ui:composition>

Forget EL or JSF. Think in terms of OO . Can you do this call.
viewModel.foo
Answer is no because it is abstract and viewModel can not exist as an instance of the abstract class ViewModel. For the exact same reason you can not use it in EL.

Related

PrimeFaces poll does not work

I need to use <p:poll /> in some other work. So I was trying out the PrimeFaces ShowCase code:-
<!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://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:rich="http://richfaces.org/rich"
xmlns:p="http://primefaces.prime.com.tr/ui"
xmlns:a4j="http://richfaces.org/a4j">
<h:form>
<h:outputText id="txt_count" value="#{counterView.number}" />
<p:poll interval="3" listener="#{counterView.increment()}" update="txt_count" />
</h:form>
</html>
And the backing bean is as below:-
package com.poll;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean (name="counterView")
#ViewScoped
public class CounterView implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private int number;
public int getNumber() {
return number;
}
public void increment() {
number++;
System.out.println(number);
}
}
It works as such: in browser number shows as 0 and doesn't change. In console I can see it printing as 1 once and then nothing.
What is wrong here? I am using PrimeFaces 3.4.2 on JSF 2.1
The p:poll tag does work for me with the following content, and I am on Primefaces 5.2.
NOTE: <h:head/> tag is needed and without that it does load primefaces related js files that are needed. I believe that is the reason why the refresh is not working in your case.
<!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://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head/>
<h:body>
<h:form>
<h:outputText id="txt_count" value="#{counterView.number}" />
<p:poll interval="3" listener="#{counterView.increment}" update="txt_count" />
</h:form>
</h:body>
</html>
And the managed bean:
#ManagedBean(name="counterView")
#ViewScoped
public class CounterView implements Serializable {
private int number = 100;
public int getNumber() {
return number;
}
public void increment() {
System.out.println("Incrementing....");
number++;
}
}
Can you try with these and compare if it works.
UPDATE: Final Solution
To summarize the solution, along the <h:head/> tag, upgrading to newer version (5.x) of Primefaces helped resolve the issue, as indicated in the comments section.

Primefaces composite component not rendering [duplicate]

This question already has an answer here:
Extended #FacesComponent as composite interface componentType renders nothing
(1 answer)
Closed 7 years ago.
I'm trying to build in a composite component in JSF with PrimeFaces.
in src/main/webapp/resources/components I have a component called editableLabel.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:composite="http://java.sun.com/jsf/composite"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head></h:head>
<h:body>
<composite:interface componentType="editableLabel">
<composite:attribute name="value" required="true"/>
<composite:attribute name="editMode" required="false" default="#{false}" type="java.lang.Boolean"/>
</composite:interface>
<composite:implementation>
<h:panelGroup id="editableLabelComponent">
<h:panelGroup rendered="#{cc.attrs.editMode}">
<p:inputText value="#{cc.attrs.value}"/>
<p:commandButton value="Update" actionListener="#{cc.update}"/>
<p:commandButton value="Cancel" actionListener="#{cc.cancel}"/>
</h:panelGroup>
<p:outputLabel id="display" value="#{cc.attrs.value}" rendered="#{!cc.attrs.editMode}">
<p:ajax event="click" listener="#{cc.toggleEditMode}" update="editableLabelComponent"/>
</p:outputLabel>
</h:panelGroup>
</composite:implementation>
</h:body>
</html>
Backed by a FacesComponent called EditableLabel.java
import javax.el.ValueExpression;
import javax.faces.component.FacesComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.context.FacesContext;
import java.io.Serializable;
/**
* Created by labraham on 1/14/16.
*/
#FacesComponent(value = "editableLabel")
public class EditableLabel extends UIComponentBase implements Serializable {
private static final long serialVersionUID = 108467781935083432L;
private String oldValue = "";
/**
* Constructor
*/
public EditableLabel() {
super();
}
#Override
public String getFamily() {
return "foo.bar.components";
}
/**
*
*/
public void update() {
toggleEditMode();
FacesContext context = FacesContext.getCurrentInstance();
this.oldValue = (String) getValueExpression("value").getValue(context.getELContext());
}
/**
*
*/
public void cancel() {
toggleEditMode();
FacesContext context = FacesContext.getCurrentInstance();
ValueExpression valueExpression = getValueExpression("value");
valueExpression.setValue(context.getELContext(), this.oldValue);
}
/**
*
*/
public void toggleEditMode() {
FacesContext context = FacesContext.getCurrentInstance();
Boolean editModeValue = (Boolean) getValueExpression("editMode").getValue(context.getELContext());
ValueExpression editModeVe = getValueExpression("editMode");
editModeVe.setValue(context.getELContext(), String.valueOf(!editModeValue));
}
}
Yet when I try to stick it in an another file like so
foo.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui" xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:comp="http://java.sun.com/jsf/composite/components"
>
...
<h3>Test</h3>
<comp:editableLabel value="#{foobean.testValue}"/>
It doesn't render. It tried removing the rendered attributes from the component (as well as editmode composite:attribute) and I've verified that it's looking for editableLabel.xhtml in the right place. foobean.testValue is just a string with a default value of "test value" and the appropriate getter and setter.
Why might PrimeFaces refuse to render this composite component?
Edit: I've also tried replacing the primefaces components in the composite component with their JSF equivalents and that didn't work. And I tried removing the ajax calls to see if maybe it was some issue with that. It wasn't.
Edit 2: Its an issue the my FacesComponent but I don't know what. Removing the component type attribute got it to render at least.
So I figured it out thanks to BalusC's answer to Extended #FacesComponent as composite interface componentType renders nothing
I needed to implement NamingContainer and getFamily() in EditableLabel.java

commandButton action method not invoked in Liferay

I've the below portlet view.xhtml:
<?xml version="1.0"?>
<f:view xmlns="http://www.w3.org/1999/xhtml"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:body>
<h:form>
<h:commandButton value="TESTButton" action="#{navigationViewBean.submit}" />
<h:outputText value="TESTGetter: #{navigationViewBean.testField}" />
</h:form>
</h:body>
</f:view>
And this managed bean:
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
#ManagedBean(name = "navigationViewBean")
#RequestScoped
public class NavigationViewBean {
private String testField;
public boolean lol = false;
public void submit() {
System.out.print("TEST BUTTON INVOKED");
}
public String getTestField() {
System.out.print("TEST GETTER INVOKEDx");
return testField;
}
public void setTestField(String testField) {
this.testField = testField;
}
}
The only thing I try to do, is to call a method which prints something to my console. The problem is that no matter what I do, the action method is never invoked. The getter method is properly called.
What am I doing wrong?
Im not sure why, but after adding this line to my liferay-portlet.xml it fixed it.
<requires-namespaced-parameters>false</requires-namespaced-parameters>
And here the whole block:
<portlet>
<portlet-name>Test1</portlet-name>
<icon>/icon.png</icon>
<requires-namespaced-parameters>false</requires-namespaced-parameters>
<header-portlet-css>/css/main.css</header-portlet-css>
</portlet>

JSF CommandButtons's action is not called when using rendered

When viewing this page with ?mode=test, the button doesn't work. It loads this page without ?mode=test, but h:panelGroup is rendered (because mode is set somewhere else). I use two methods of sending mode (h:inputHidden f:param) and to the server and nothing helps. View scoped bean is not available in CDI. What is the possible solution to this?
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://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<f:view>
<f:metadata>
<f:viewParam name="mode" value="#{test.mode}" />
</f:metadata>
<h:panelGroup layout="block" rendered="#{test.mode.equals('test')}">
<h:form>
<h:inputHidden value="#{test.mode}" />
<h:commandButton value="Run a method" action="#{test.method}">
<f:param name="mode" value="#{test.mode}" />
</h:commandButton>
</h:form>
</h:panelGroup>
<h:messages />
</f:view>
</html>
Java
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
#Named("test")
#RequestScoped
public class TestBean {
private String mode;
public void method() {
System.out.print(mode);
}
public String getMode() {
return mode;
}
public void setMode(String mode) {
this.mode = mode;
}
}
You've got a wide range of possibilities. The easiest one for you is not to bind the view parameter to the backing bean, just keep it bound to the view:
test.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<f:view>
<f:metadata>
<f:viewParam name="mode" value="#{mode}" />
</f:metadata>
<h:form rendered="#{mode eq 'test'}">
<h:commandButton value="Run a method" action="#{test.method(mode)}" />
</h:form>
<h:messages />
</f:view>
</html>
Test.java
#Named
#RequestScoped
public class Test {
public void method(String mode) {
System.out.print(mode);
}
}
If you however would like to switch to #ViewScoped, CDI compatible annotation is now available in JSF 2.2 version. The namespaces you're using suggest you do use that version, so go with it. For JSF prior versions, there's also the chance to do it with custom Omnifaces' annotation.
See also:
Omnifaces #ViewScoped annotation
#ViewScoped in CDI with JSF 2.2
Differences between EL 2.1 and 2.2

f:viewParam not working in dependent or view only in request scope

I'm wondering if I'm having the same findings but after creating a javaee6 web project generated from jboss maven archetype I have the following result.
f:viewParam, did not work on dependent or view scope only in request scope.
public class BaseBean {
protected boolean edit;
public boolean isEdit() {
System.out.println("get edit=" + edit);
return edit;
}
public void setEdit(boolean edit) {
System.out.println("set edit=" + edit);
this.edit = edit;
}
}
#Named
#RequestScoped
public class RequestBean extends BaseBean { }
#Named
public class DependentBean extends BaseBean { }
#Named
#ViewScoped
public class ViewBean extends BaseBean { }
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
template="/WEB-INF/templates/default.xhtml">
<ui:define name="metadata">
<f:metadata>
<f:viewParam name="edit" value="#{dependentBean.edit}" />
</f:metadata>
</ui:define>
<ui:define name="content">
<h:outputText value="#{dependentBean.edit}"></h:outputText>
</ui:define>
</ui:composition>
For the request and view scope views, it's almost the same as the one above except for the manage bean used.
Any idea?
The problem is that you're mixing JSF annotations from package javax.faces.bean with CDI annotations (noticed by the usage of #Named) from package javax.enterprise.context and they can't be used altogether for being handled by different managers (JSF and CDI managers). In your application, your managed beans should be from JSF or from CDI, not from a mix of both.
Note that CDI doesn't support #ViewScoped yet, this scope is available only for JSF. More info: CDI missing #ViewScoped and #FlashScoped

Resources