omn​​ifaces.SelectItemsConverter返回null

时间:2014-08-13 16:45:43

标签: jsf jsf-2 converter omnifaces

我正在使用jsf spring hibernate和primefaces开展一个项目。我有一个表单,我在其中添加项目。该表单的一个字段不是原始类型,而是自定义对象。我知道我必须使用转换器并获得我选择的对象。我已经尝试了一个没有运气的自定义转换器,因为我无法注入服务并且始终为null。所以我转向omnifaces让我的生活更轻松,继续前进。不幸的是我也遇到了问题。我仔细查看我的代码,但我看不出什么是错的。下面我添加与问题相关的代码: 首先我使用omnifaces的页面:

<html xmlns="http://www.w3.org/1999/xhtml"  
 xmlns:h="http://java.sun.com/jsf/html"      
  xmlns:f="http://java.sun.com/jsf/core"
  xmlns:p="http://primefaces.org/ui"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:o="http://omnifaces.org/ui"
    xmlns:of="http://omnifaces.org/functions">
<h:head><title>Welcome to OTV_JSF_Spring_Hibernate_Project</title></h:head>  
<h:body>
    <ui:include src="/pages/topMenu.xhtml"/>
    <h:form>
        <table>
            <tr>
                <td><h:outputLabel for="itemId" value="id: "/></td>
                <td><h:inputText id="itemId" value="#{inventoryItemsMB.itemId}"></h:inputText></td>
            </tr>


            <tr>
                <td><h:outputLabel for="RefItemCategories" value="Category Code"/></td>
                <td>
                    <h:selectOneMenu value="#{inventoryItemsMB.refItemCategories}" id="refItemCategories" immediate="true" converter="omnifaces.SelectItemsConverter">

                        <f:selectItems  value="#{refItemCategoriesMB.refItemCategoriesList}" var="ref" itemLabel="#{ref.itemCategoryDescription}" itemValue="#{ref}"/>
                        <!--<f:converter converterId="catConverter"/>-->
                    </h:selectOneMenu>
                </td>
            </tr>

            <tr>
                <td><h:outputLabel for="description" value="Description"/></td>
                <td><h:inputText id="description" value="#{inventoryItemsMB.description}" immediate="false"></h:inputText></td>
            </tr>

            <tr>
                <td><h:outputLabel for="AvgMonthlyUsage" value="Average Monthly Usage: "/></td>
                <td><h:inputText id="AvgMonthlyUsage" value="#{inventoryItemsMB.avgMonthlyUsage}"></h:inputText></td>
            </tr>
            <tr>
                <td><h:outputLabel for="reorderQuantity" value="Reorder Quantity: "/></td>
                <td><h:inputText id="reorderQuantity" value="#{inventoryItemsMB.reorderQuantity}"></h:inputText></td>
            </tr>
            <tr>
                <td><h:outputLabel for="Price" value="Price: "/></td>
                <td><h:inputText id="Price" value="#{inventoryItemsMB.price}"></h:inputText></td>
            </tr>
            <tr>
                <td><h:outputLabel for="ItemStockLevels" value="Item stock levels: "/></td>
                <td><h:inputText id="ItemStockLevels" value="#{itemStockLevelsMB.quantityInStock}"></h:inputText></td>
            </tr>
            <tr>
                <td><p:commandButton id="addInventoryItems" value="ADD" action="#{inventoryItemsMB.addInventoryItems}" ajax="false" immediate="false"/></td>
            </tr>
        </table>
    </h:form>

</h:body>

其次是我的managedBeans:

@ManagedBean(name="inventoryItemsMB")
   @RequestScoped
   public class InventoryItemsManagedBean implements Serializable {

private static final long serialVersionUID = 1L;
private static final String SUCCESS = "successInventoryItems";
private static final String ERROR   = "error";

@ManagedProperty(value="#{InventoryItemsService}")
IInventoryItemsService inventoryItemsService;

List<InventoryItems> inventoryItemsList;

private int id;
private String avgMonthlyUsage;
String description;
Set<ItemStockLevels> itemStockLevels;
float price;
String reorderQuantity;
RefItemCategories refItemCategories;
byte[] photo;

public String addInventoryItems(){
    try{
        InventoryItems inventoryItems = new InventoryItems();
        //RefItemCategories refItemCategories = new RefItemCategories();
        inventoryItems.setAvgMonthlyUsage(getAvgMonthlyUsage());//DONE is it a string?look at impl
        inventoryItems.setDescription(getDescription());//DONE
        inventoryItems.setItemId(getItemId());//DONE
        inventoryItems.setItemStockLevels(getItemStockLevels());//DONE ----- why is it a set?
        inventoryItems.setPhoto(getPhoto());
        inventoryItems.setPrice(getPrice());//DONE
        inventoryItems.setRefItemCategories(getRefItemCategories());//DONE---why refItemCategories
        inventoryItems.setReorderQuantity(getReorderQuantity());//DONE-----why string?
        //refItemCategories.getItemCategoryCode();
        //refItemCategories.getItemCategoryDescription();
        getInventoryItemsService().addInventoryItems(refItemCategories, inventoryItems);
        return SUCCESS;
    } catch (DataAccessException e) {
        e.printStackTrace();
    }
    return ERROR;
}

public List<InventoryItems> getInventoryItemsList() {
    inventoryItemsList = new ArrayList<InventoryItems>();
    inventoryItemsList.addAll(getInventoryItemsService().getInventoryItems());
    return inventoryItemsList;
}

public IInventoryItemsService getInventoryItemsService() {
return inventoryItemsService;
}


public void setInventoryItemsService(IInventoryItemsService inventoryItemsService) {
this.inventoryItemsService = inventoryItemsService;
}

public void setInventoryItemsList(List<InventoryItems> inventoryItemsList) {
this.inventoryItemsList = inventoryItemsList;
}

public int getItemId() {
    return id;
}

public void setItemId(int id) {
    this.id = id;
}

public void setAvgMonthlyUsage(String avgMonthlyUsage){
    this.avgMonthlyUsage = avgMonthlyUsage;
}

public String getAvgMonthlyUsage(){
    return avgMonthlyUsage;
}

public void setDescription(String description){
    this.description = description;
}

public String getDescription(){
    return description;
}

public void setItemStockLevelses(Set<ItemStockLevels> itemStockLevels){
    this.itemStockLevels = itemStockLevels;
}

public Set<ItemStockLevels> getItemStockLevels(){
    return itemStockLevels;
}

public void setPrice(float price){
    this.price = price;
}

public float getPrice(){
    return price;
}

public void setReorderQuantity(String reorderQuantity){
    this.reorderQuantity = reorderQuantity;
}

public String getReorderQuantity(){
    return reorderQuantity;
}

public void setRefItemCategories(RefItemCategories refItemCategories){
    this.refItemCategories = refItemCategories;
}

public RefItemCategories getRefItemCategories(){
    return refItemCategories;
}

public byte[] getPhoto(){
    return photo;
}

public void setPhoto(byte[] photo){
    this.photo = photo;
}

}

和其他管理的大豆

 @ManagedBean(name="refItemCategoriesMB")
@RequestScoped
public class RefItemCategoriesManagedBean implements Serializable{
    private static final long serialVersionUID = 1L;
    private static final String SUCCESS = "addCategorySuccess";
    private static final String ERROR   = "error";

@ManagedProperty(value="#{RefItemCategoriesService}")
IRefItemCategoriesService refItemCategoriesService;

List<RefItemCategories> refItemCategoriesList;

private int id;
private String description;

public String addRefItemCategories(){
    try{
        RefItemCategories refItemCategories = new RefItemCategories();
        refItemCategories.setItemCategoryCode(getItemCategoryCode());
        refItemCategories.setItemCategoryDescription(getItemCategoryDescription());
        getRefItemCategoriesService().addRefItemCategories(refItemCategories);
        return SUCCESS;
    } catch (DataAccessException e){
        e.printStackTrace();
    }
    return ERROR;
}

public List<RefItemCategories> getRefItemCategoriesList() {
    refItemCategoriesList = new ArrayList<RefItemCategories>();
    refItemCategoriesList.addAll(getRefItemCategoriesService().getRefItemCategories());
    return refItemCategoriesList;
}

public IRefItemCategoriesService getRefItemCategoriesService() {
return refItemCategoriesService;
}

public void setRefItemCategoriesService(IRefItemCategoriesService refItemCategoriesService) {
this.refItemCategoriesService = refItemCategoriesService;
}

public void setRefItemCategoriesList(List<RefItemCategories> refItemCategoriesList) {
this.refItemCategoriesList = refItemCategoriesList;
}

public String DeleteCategory(RefItemCategories refItemCategoriesList){
    getRefItemCategoriesService().deleteRefItemCategories(refItemCategoriesList);
    return SUCCESS;
}


public void setItemCategoryCode(int id){
    this.id = id;
}

public int getItemCategoryCode(){
    return id;
}

public void setItemCategoryDescription(String description){
    this.description = description;
}

public String getItemCategoryDescription(){
    return description;
}

 @Override
public boolean equals(Object object){
if(this.id == ((RefItemCategories) object).getItemCategoryCode()) {
    return true;
}else {
    return false;
}

}

}

服务我无法注入:

 @Transactional(readOnly = true)
@Service("RefItemCategoriesService")
public class RefItemCategoriesService implements IRefItemCategoriesService{

    @Autowired
    RefItemCategoriesDAOImpl refItemCategoriesDAO;

    @Transactional(readOnly = false)
    @Override
    public void addRefItemCategories(RefItemCategories refItemCategories) {
        getRefItemCategoriesDAO().addRefItemCategories(refItemCategories);
    }

    @Transactional(readOnly = false)
    @Override
    public void updateRefItemCategories(RefItemCategories refItemCategories) {
        getRefItemCategoriesDAO().updateRefItemCategoriesUser(refItemCategories);
    }

    @Transactional(readOnly = false)
    @Override
    public void deleteRefItemCategories(RefItemCategories refItemCategories) {
        getRefItemCategoriesDAO().deleteRefItemCategories(refItemCategories);
    }

    @Override
    public RefItemCategories getRefItemCategoriesByID(int id) {
        return getRefItemCategoriesDAO().getRefItemCategoriesById(id);
    }

    @Override
    public List<RefItemCategories> getRefItemCategories() {
        return getRefItemCategoriesDAO().getRefItemCategories();
    }

    public RefItemCategoriesDAO getRefItemCategoriesDAO(){
        return refItemCategoriesDAO;
    }
}

这样我得到一个事务错误,其中item_cat_code(db表)不能为null。 谢谢你的时间。

1 个答案:

答案 0 :(得分:3)

根据documentationomnifaces.SelectItemsConverter依赖于待转换对象的Object#toString()表示来正确匹配所选项目。您没有显示RefItemCategories实体的代码,所以它只是猜测,但症状表明您确实没有@Override您实体上的toString(),因此依靠default FQN@hashcode representation。只有在同一视图的回发中,可用项目(<f:selectItems>的值)完全时,这一切才有效。

但是,提供可用项的RefItemCategoriesManagedBean辅助bean是请求作用域,并将它们加载到getter中。每当getter被击中时,都会返回一个包含全新实例的全新列表。那些哈希码与已经加载在可用项列表中的哈希码没有相同的哈希码,因此提交的所选项永远不会与任何新加载的项匹配。

因此至少有2个设计问题。

  1. You should choose the right bean scope for the data it holds。至少要@ViewScoped
  2. You should never interact with the DB in a getter method。在@PostConstruct
  3. 中执行

    如果您同时解决这两个问题,那么问题就会消失。

    或者,只需为您的实体实施toString()即可。 E.g。

    public class RefItemCategories {
    
        @Override
        public String toString() {
            return "RefItemCategories[" + id + "]";
        }
    
    }
    

    顺便说一句,在equals()支持bean类上看到RefItemCategoriesManagedBean方法很奇怪。你不是故意把它放在RefItemCategories实体上吗?无论如何,请仔细阅读SelectItemsConverter {{1}}如何正确使用它以及如何正确设计您的实体。