Have an issue with a Java Web App when using JSF + PrettyFaces to handle navigation and bean actions.
using versions:
JSF - 2.1
PrettyFaces - 3.3.3
Error happens when handling navigation using PrettyFaces Filter from link:
<div class="product_img">
<pretty:link mappingId="viewProduct">
<img src="#{request.contextPath}/image?id=#{product.mainImage.fileReference.id}" />
<f:param value="#{productMB.filters.productCategoryName}" />
<f:param value="#{product.name}" />
</pretty:link>
</div>
pretty-config.xml mapping is:
<url-mapping id="viewProduct">
<pattern value="/shop/product/#{ productCategoryName : productMB.filters.productCategoryName }/#{ productName : productMB.filters.productName }/" />
<view-id value="/pages/productDetails.faces" />
<action>#{productMB.openProductDetails}</action>
</url-mapping>
bean action:
public String openProductDetails() {
if (filters.getProductCategoryName() != null && !filters.getProductName().equals("")) {
loadProductDetailsByName(filters.getProductCategoryName());
}
return "/pages/productDetails.faces";
}
User lands in Product Details Page where he can select product Features like color, size, etc...
<ui:fragment rendered="#{productMB.productVO.featureColorAvailable}">
<span class="productFeatureLabel">#{msg.color}</span>
<h:selectOneMenu id="colorSelect"
value="#{productMB.productVO.colorSelected}"
valueChangeListener="#{productMB.colorSelectedValueChanged}">
<f:selectItem itemLabel="#{msg['select']}" noSelectionOption="true" />
<f:selectItems value="#{productMB.productFeatureAvailableApplMap['color']}" var="colorItem" itemValue="#{colorItem}"
itemLabel="#{msg[colorItem.name]}" />
<f:ajax event="valueChange"
listener="#{productMB.colorSelectedValueChanged}"
render="@this productDetailImage productSubImage productSubImage2 productSubImage3 sizeSelect"></f:ajax>
</h:selectOneMenu>
</ui:fragment>
//... Bean action methods
public void colorSelectedValueChanged(ValueChangeEvent event) {
if (null != event.getNewValue()) {
ProductFeatureAppl prodFeatureAppl = (ProductFeatureAppl) event.getNewValue();
filterProductFeatureSelectItem(AppConstants.SIZE, prodFeatureAppl.getProductFeature().getName() );
} else {
filterProductFeatureSelectItem(AppConstants.SIZE, null );
}
}
public void colorSelectedValueChanged(AjaxBehaviorEvent event) throws javax.faces.event.AbortProcessingException {
try {
if (null != productVO.getColorSelected()) {
ProductFeatureAppl prodFeatureAppl = productVO.getColorSelected();
filterProductFeatureSelectItem(AppConstants.SIZE, prodFeatureAppl.getProductFeature().getName() );
String prodFeatName = prodFeatureAppl.getProductFeature().getName();
// switch selected pics.
productVO.setCurrentDetailImageName(productVO.getProduct().getProductImageByTypeAndFeatureName(
NameConstants.DETAIL, prodFeatName).getFileReference().getId());
productVO.setCurrentBigImageName(productVO.getProduct().getProductImageByTypeAndFeatureName(
NameConstants.BIG, prodFeatName).getFileReference().getId());
} else {
filterProductFeatureSelectItem(AppConstants.SIZE, null );
filterProductFeatureSelectItem(AppConstants.COLOR, null );
// reset to default
productVO.setCurrentDetailImageName(productVO.getProduct().getProductImageByType(ProductImageType.DETAIL1.toString()).getFileReference().getId());
productVO.setCurrentBigImageName(productVO.getProduct().getProductImageByType(ProductImageType.BIG1.toString()).getFileReference().getId());
}
} catch (Exception ex) {
addErrorMessage(getMessage("error"));
if (screenComponent.isDisplayException()) {
addErrorMessage(ex.getMessage());
}
}
}
After first navigation to product details page, whenever selecting a value from selectOneMenu id="colorSelect" the valueChangeListener and ajax listener aren't called. Besides that, productMB.openProductDetails action is called.
The ajax call is completed with no errors I can see in the logs but no listener methods are called. Does someone know why these JSF ajax listeners are being skipped ?
Thanks in advance.
Does the page work if you access it directly from the URL? Does it work if PrettyFaces is disabled?
I doubt this is an issue with the link or with PrettyFaces. I'm betting that it has more to do with AJAX and partial-state-saving.
It's possible that it has to do with this:
public String openProductDetails() {
if (filters.getProductCategoryName()
!= null && !filters.getProductName().equals("")) {
loadProductDetailsByName(filters.getProductCategoryName());
}
return "/pages/productDetails.faces"; // why is this being returned?
}
You are returning a page name there. PrettyFaces may actually try to navigate on this String. If you wish to display the page that you have configured in your mapping, simply return null, return "" empty string, or return nothing.
Hope this helps.