Getting errors when using p:selectOneMenu - primefaces

I am currently trying to make a stylish dropdown item with the help of p:selectOneMenu.
I am working on it because I am trying to migrate a project to Primefaces 10. The project was implemented more than 10 years ago. For this reason there is no CDI. The server used is an IBM WebSphere Liberty v21 (feature jsf-2.3 was deployed).
The xhtml part look like this:
<p:selectOneMenu id="techSpecsOneMenuId"
value="#{techSpecsTreeMBean.selectedCatalogNodeWrapper}"
var="catalogNodeWrapper" styleClass="techSpecsOneMenuClass"
converter="catalogNodeWrapperConverter">
<f:selectItems value="#{techSpecsTreeMBean.catalogNodes}"
var="catNode"
itemLabel="#{catNode.positionName}" itemValue="#{catNode}" />
<p:column>
<h:panelGroup layout="block" styleClass="fieldLabelSmall">
<ui:repeat value="#{catalogNodeWrapper.levelList}" var="level">
<h:graphicImage
value="resources/images/treetable/tree_line_blank.gif"
alt="treeLineBlank" style="vertical-align: middle;" />
</ui:repeat>
<h:graphicImage value="#{catalogNodeWrapper.positionIcon}"
style="vertical-align: top;" alt="posIcon"
rendered="#{catalogNodeWrapper.specificationNode.nodeType != 'OVERVIEW'}" />
<h:commandLink
action="#{catalogNodeWrapper.techNodeDropDownSelectedAction}"
value="#{catalogNodeWrapper.positionName}"
title="#{catalogNodeWrapper.positionTitle}"
style="vertical-align: middle;"
rendered="#{catalogNodeWrapper.specificationNode.nodeType != 'OVERVIEW'}" />
<h:outputText value="#{catalogNodeWrapper.positionName}"
rendered="#{catalogNodeWrapper.specificationNode.nodeType == 'OVERVIEW'}"
style="vertical-align: middle;" />
</h:panelGroup>
</p:column>
</p:selectOneMenu>
TechSpecsTreeMBean is a managed bean:
<managed-bean>
<managed-bean-name>techSpecsTreeMBean</managed-bean-name>
<managed-bean-class>....TechSpecsTreeMBean</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
CatalogNodeWrapper is just a Java-Bean:
public class CatalogNodeWrapper implements Serializable, Comparable<CatalogNodeWrapper>
And finally the CatalogNodeWrapperConverter is a "normal" JSF-Converter:
#FacesConverter(value = "catalogNodeWrapperConverter")
public class CatalogNodeWrapperConverter implements Converter<CatalogNodeWrapper> {
private static final Logger LOGGER = Logger.getLogger(CatalogNodeWrapperConverter.class.getName());
#Override
public CatalogNodeWrapper getAsObject(FacesContext arg0, UIComponent arg1, String arg2) throws ConverterException {
LOGGER.log(LapLevel.INFO, "CatalogNodeWrapperConverter.getAsObject");
TechSpecsTreeMBean tempTechSpecsTreeMBean =
(TechSpecsTreeMBean) MBeanUtil.getManagedBeanByElResolver(MBeanControllerInit.TECHSPECSTREE_CONTROLLER);
if (arg2 != null && arg2.trim().length() > 0) {
try {
return tempTechSpecsTreeMBean.getCatalogNodesMap().get(Integer.parseInt(arg2));
}
catch (NumberFormatException e) {
throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Conversion Error", "Not a valid catalogNode."));
}
} else {
return null;
}
}
#Override
public String getAsString(FacesContext arg0, UIComponent arg1, CatalogNodeWrapper arg2) throws ConverterException {
LOGGER.log(LapLevel.INFO, "CatalogNodeWrapperConverter.getAsString");
if (arg2 != null) {
return String.valueOf(arg2.getId());
} else {
return "";
}
}
}
For me everything looks fine, but I am getting the following error:
Caused by: javax.el.PropertyNotFoundException: Target Unreachable, identifier 'catalogNodeWrapper' resolved to null
at org.apache.el.parser.AstValue.getTarget(AstValue.java:72)
at org.apache.el.parser.AstValue.invoke(AstValue.java:226)
at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:267)
at org.apache.myfaces.view.facelets.el.ContextAwareTagMethodExpression.invoke(ContextAwareTagMethodExpression.java:96)
... 79 more
Same error is thrown if I register the converter in the faces-config.xml
<converter>
<converter-id>catalogNodeWrapperConverter</converter-id>
<converter-class>....CatalogNodeWrapperConverter</converter-class>
</converter>
If I am using the CDI Feature I have to change the annotation of the converter to:
#Named
#FacesConverter(value = "countryConverter", managed = true)
and the usage of the converter to:
converter="#{catalogNodeWrapperConverter}"
the following error is thrown:
javax.el.ELException: Cannot convert 24 of type class java.lang.String to class ....CatalogNodeWrapper
at org.apache.el.lang.ELSupport.coerceToType(ELSupport.java:658)
at org.apache.el.parser.AstValue.setValue(AstValue.java:201)
at org.apache.el.ValueExpressionImpl.setValue(ValueExpressionImpl.java:257)
at org.apache.myfaces.view.facelets.el.ContextAwareTagValueExpression.setValue(ContextAwareTagValueExpression.java:146)
at javax.faces.component.UIInput.updateModel(UIInput.java:429)
at javax.faces.component.UIInput.processUpdates(UIInput.java:347)
It seems that the converter is not used.
Any idea or solution will be highly appreciated.
And I have already checked tis guide - Identifying and solving javax.el.PropertyNotFoundException: Target Unreachable

Related

Trigger notification bar from <p:ajax> event

I'm looking to trigger a notification bar on checkbox click using <p:ajax>. The notification bar would have the save option to save data in the database. The update atribute within <p:ajax> doesn't seem to work. It's been quite a research, but couldn't derive at a solution. Am I missing something here ? I'm using JSF 2.1+Primefaces 3.5. Any help would be much appreciated.
xhtml page
<p:column headerText="#{msgs.ref}" styleClass="menuHeader textAlignLeft">
<p:notificationBar widgetVar="customSaveBar" position="top" styleClass="saveBar warningBar textAlignCenter" style="height: 25px;padding-top: 0; padding-bottom: 0;" effect="none" rendered="true">
<h:outputText value="There are pending changes on the page." styleClass="warningText"/>
<h:outputText value=" "/>
<p:commandLink action="#{abcDashboardBean.abcDTOValues}"
onclick="skipPageRedirectWarning = true;showPleaseWait();"
styleClass="warningText" id="saveFromBar"
onsuccess="customSaveBar.hide()"
oncomplete="placeRemoveIcon();"
update="#form"
process="#form"
value="#{msgs.save}"/>
</p:notificationBar>
<p:selectBooleanCheckbox styleClass="margin_left_10" value="#{abcDto.refBl}"
rendered="#{!authorizationBean.userADMIN or !authorizationBean.userPM or !authorizationBean.userINDM}">
<p:ajax event="click" partialSubmit="true" update="customSaveBar"></p:ajax>
</p:selectBooleanCheckbox>
</p:column>
abcDashboardBean.java
public Map<Object, Boolean> getAbcDTOValues(){
Map<Object, Boolean> map = new LinkedHashMap<Object, Boolean>();
//fill the map with the items defaulted to unchecked
for (AbcDTO abcDTO: abcList){
map.put(abcDTO.getPpcCode(), Boolean.FALSE);
}
Abc abc1 = dataAccessEjbService.find(Abc.class, abc.getId());
saveAbcRefChanges(map, abc1);
return map;
}
public void saveAbcRefChanges(Map<Object, Boolean> map, Abc abc) {
for (Map.Entry<Object, Boolean> entry : map.entrySet()) {
if (entry.getValue().equals(true) && abc != null) {
abc.setReferenceBl(true);
} else {
abc.setReferenceBl(false);
}
}
dataAccessEjbService.update(abc);
}
AbcDTO.java
private boolean refBl;
// getters + setters

How to set a converter dynamically for a PrimeFaces component?

I am using p:autoComplete inside column of a data table. And I am setting
converter by using variable assigned to the data table converter="#{fieldVar.possibleValues}"
but, it throws :
converter="#{fieldVar.possibleValues}": java.lang.IllegalArgumentException: Cannot convert userConverter of type class java.lang.String to interface javax.faces.convert.Converter
possibleValues is a string
If this is not possible then how we can change the converter dynamically.
<p:dataTable var="fieldVar" value="#{dynamicReportBean.screenMetadataDTOs}" id="edit_meta_data_datatable">
<p:column headerText="Filter Names">
<h:outputText value="#{fieldVar.filedName}"/>
</p:column>
<p:column headerText="Filter Values">
<p:inputText value ="#{fieldVar.filedValue}"
placeholder="#{fieldVar.filedName}"
rendered="#{dynamicReportBean.canRenderFieldType(fieldVar.fieldId, 'TEXTFIELD')}" style="width: 220px">
</p:inputText>
<p:selectOneMenu value="#{fieldVar.filedValue}"
rendered="#{dynamicReportBean.canRenderFieldType(fieldVar.fieldId, 'DROPDOWN')}" style="width: 220px">
<f:selectItems value="#{dynamicReportBean.retrievePossibleDropDownValues(fieldVar.fieldId, fieldVar.fieldType, fieldVar.possibleValues)}"/>
</p:selectOneMenu>
<p:selectManyMenu value="#{fieldVar.filedValue}"
style="width: 220px"
showCheckbox="true"
rendered="#{dynamicReportBean.canRenderFieldType(fieldVar.fieldId, 'SELECT_MANY_CHECKBOX')}">
<f:selectItems value="#{dynamicReportBean.retrievePossibleDropDownValues(fieldVar.fieldId, fieldVar.fieldType, fieldVar.possibleValues)}"/>
</p:selectManyMenu>
<p:autoComplete value="#{fieldVar.filedValue}"
style="width: 220px"
placeholder="autocomplete"
completeMethod="#{dynamicReportBean.getAutoCompleteMethod}"
rendered="#{dynamicReportBean.canRenderFieldType(fieldVar.fieldId, 'AUTOCOMPLETE')}"
scrollHeight="300"
converter="#{fieldVar.possibleValues}"
size="25">
<f:attribute name="converterName" value="#{fieldVar.possibleValues}" />
<p:ajax event="itemSelect" listener="#{dynamicReportBean.onHandleSelect}"/>
</p:autoComplete>
</p:column>
</p:dataTable>
if I pass converter = "userConverter" It works fine but instead of that I want converter values come dynamically
public class UserConverter implements Converter {
#Override
public Object getAsObject(FacesContext context, UIComponent component,
String value) {
UserLOVBean lOVBean = null;
try {
UserService service = new UserServiceImpl();
UserFilterDTO filterDTO = new UserFilterDTO();
UserContext userContext
= (UserContext) context.getExternalContext().getSessionMap().
get("USER_CONTEXT");
filterDTO.setCmpCode(userContext.getCmpCode());
filterDTO.setOrgCode(userContext.getOrgCode());
if (value != null) {
filterDTO.setUserId(value);
}
for (UserLOVDTO lOVDTO : service.retrieveUserForAutoComplete(
filterDTO)) {
if (value.equals(lOVDTO.getUserId())) {
lOVBean = new UserLOVBean();
CopyUtil.copyValues(lOVDTO, lOVBean);
}
}
} catch (Exception ex) {
ex.printStackTrace();
Logger.getLogger(UserConverter.class.getName()).log(Level.SEVERE,
null, ex);
}
return lOVBean;
}
#Override
public String getAsString(FacesContext context, UIComponent component,
Object value) {
return String.valueOf(((UserLOVBean) value).getUserId());
}
}
Setting a converter for p:autoComplete (and any other PrimeFaces component) using the converter attribute is documented as:
An EL expression or a literal text that defines a converter for the component. When it's an EL expression, it's resolved to a converter instance. In case it's a static text, it must refer to a converter id.
So, if you want to use an EL expression, it must point to an instance of a converter. In your bean you could simply add:
public UserConverter getUserConverter() {
return new UserConverter();
}
And then, in your XHTML, use:
<p:anyComponent converter="#{myBean.userConverter}"/>

Dynamic images with StreamedContent

I have implemented two StreamedContent beans to dynamic load a graphic image, following the solution found
here
1) With the first one I display images in a contentFlow (EVERYTHING OK)
<p:contentFlow value="#{imageBean.images}" var="image">
<p:graphicImage value="#{imageStreamer.fileContent}" styleClass="content" cache="false">
<f:param name="index" value="#{image.index}"/>
</p:graphicImage>
</p:contentFlow>
2) With the second one I try to display images using a foreach (or repeat):
<c:forEach items="#{imageBean.images}" var="item" varStatus="varStatus">
<p:graphicImage value="#{imageStreamer.fileContent}" cache="false">
<f:param name="index" value="#{varStatus.index}" />
</p:graphicImage>
</c:forEach>
This doesn't work. The check (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) is always true.
If I change the scope of the Bean to RequestScoped than it works! I'm confused... can someone help me?
Managed bean:
#ManagedBean
#ApplicationScoped
public class ImageStreamer{
public ImageStreamer(){}
public StreamedContent getFileContent(){
List<Link> links = this.getLinkItems();
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
FacesContext fc = FacesContext.getCurrentInstance();
String linkIndex = externalContext.getRequestParameterMap().get("index");
if(fc.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE){
return new DefaultStreamedContent();
}else{
int parsedIndex = Integer.parseInt(linkIndex);
Link ql = links.get(parsedIndex);
return new DefaultStreamedContent(new ByteArrayInputStream(ql.getBytes()), "image/png");
}
}
}
Since you are using primefaces, try using p:repeat
Repeat is an extension to standard repeat component to provide interoperability between JSF implementations and PrimeFaces components.
https://www.primefaces.org/showcase/ui/data/repeat.xhtml

Why can't I update a p:graphicImage twice after upload a file with p:uploadFile

I have been trying to upload an image with a p:uploadFile and it work fine at first time, but after the first uploaded file it not update the p:graphicImage, but if I reload the page the value of the graphicImage is fine and the image is showed. So, I think that is a problem with the primefaces uploadFile component, but I not sure.
My xhtml is this:
<h:form id="formNuevo" size="150%" enctype="multipart/form-data">
<h:outputLabel value="Diseño Neumatico: *" />
<p:fileUpload fileUploadListener="#{serviciosVentanaDiseno.manejarUploadedFile}" mode="advanced" auto="true" sizeLimit="9000000000" allowTypes="/(\.|\/)(gif|jpe?g|png)$/" update="mensajes graficImage"/>
<p:graphicImage id="graficImage" styleClass="disenoNeumatico" value="#{serviciosVentanaDiseno.streamedContentImagen}" ajax="true"/>
</h:form>
and my bean is a #SessionScoped bean, it's here:
public void manejarUploadedFile(FileUploadEvent event) {
UploadedFile uploadedFile = (UploadedFile)event.getFile();
try {
diseno.setImagen(uploadedFile.getContents());
streamedContentImagen = new DefaultStreamedContent(new ByteArrayInputStream(diseno.getImagen()));
} catch (IOException e) {
//log error
}
}
public StreamedContent getStreamedContentImagen() {
return streamedContentImagen;
}
public void setStreamedContentImagen(StreamedContent streamedContentImagen) {
this.streamedContentImagen = streamedContentImagen;
}
Try setting the cache attribute of the graphicImage component to false:
<p:graphicImage cache="false"
change scope #SessionScoped then <p:graphicImage cache="false">

PrimeFaces <f:attribute not working correctly with p:galleria attribute

I have issue when trying to make command link from inside p:galleria component
The problem is despite the fact at run time the link value value="Show present #{present.name} #{present.presentId}" contains the correct value of the id as example value="Show present Foo 1" , when pressing the command link it sends the wrong id of the second object every time
<h:form>
<p:galleria value="#{presentBean.allPresentList}" var="present" panelWidth="500" panelHeight="313" showCaption="true">
<f:facet name="content">
<h:commandLink value="Show present #{present.name} #{present.presentId}" action="pretty:present" actionListener="#{presentBean.setPresentObj}">
<f:attribute name="present" value="#{present.presentId}"/>
</h:commandLink>
</f:facet>
</p:galleria>
</h:form>
#ManagedBean(name="presentBean")
#SessionScoped
public class PresentBean implements Serializable{
ArrayList<Present> allUserPresentList = new ArrayList<Present>();
#PostConstruct
private void usersPresent(){
PresentDao presentDao = new PresentDaoImpl();
allPresentList = (ArrayList<Present>) presentDao.findAllPresents();
}
public ArrayList<Present> getAllUserPresentList() {
return allUserPresentList;
}
public void setAllUserPresentList(ArrayList<Present> allUserPresentList) {
this.allUserPresentList = allUserPresentList;
}
private String presentId ;
public String getPresentId() {
return presentId;
}
public void setPresentId(String presentId) {
this.presentId = presentId;
}
public void setPresentObj(ActionEvent ev){
Object presentOb = ev.getComponent().getAttributes().get("present");
if(presentOb != null){
this.presentId = (String) presentOb;
}else{
presentId = null ;
}
}
}
You need to use a setPropertyActionListener instead of <f:attribute name="present" value="#{present.presentId}"/> as the f:attribute tag is only evaluated when the component is created (only once) not when the component generates html based on the iterated rows.
So you'll need to instead use:
<f:setPropertyActionListener target="#{presentBean.presentId}" value="#{present.presentId}" />
That will set the value of the presentId in your managed bean, so in your action method you can just access the presentId itself already without having to work it out.
Alternatively if you're using a later version of JSF (using Servlet 3.0 or above), then you could create a method in the managed bean which takes the presentId or even the present object as a parameter
e.g. in your managed bean:
public void myAction(Present p){
//do whatever you want with the Present object
}
and in your .xhtml:
<h:commandLink value="Show present #{present.name} #{present.presentId}" actionListener="#{presentBean.myAction(present)}">
</h:commandLink>