【问题标题】:Conversion Error setting value '52' for 'null Converter' [duplicate]'null Converter'的转换错误设置值'52'[重复]
【发布时间】:2012-10-22 08:52:54
【问题描述】:

我是 JSF 的新手,我一直在尝试从使用 h:selectOneMenu 获取产品类别的表单中存储数据。 h:selectOneMenu 是从数据库中填充的,但是,当尝试将产品存储在数据库中时,我收到一个错误:转换错误为“空转换器”设置值“52”。我已经在 StackOverflow 和在线教程中查看过类似的问题,但我仍然收到错误消息。

这是xhtml:

<h:selectOneMenu id="category_fk" value="#{productController.product.category_fk}" 
                                 converter="#{categoryConverter}" title="Category_fk" >
                    <!-- DONE: update below reference to list of available items-->
                    <f:selectItems value="#{productController.categoryList}" var="prodCat"
                                   itemValue="#{prodCat}" itemLabel="#{prodCat.name}"/>
                </h:selectOneMenu>

这是产品控制器:

@Named
@RequestScoped
public class ProductController {

    @EJB
    private ProductEJB productEjb;
    @EJB
    private CategoryEJB categoryEjb;

    private Product product = new Product();
    private List<Product> productList = new ArrayList<Product>();

    private Category category;
    private List<Category> categoryList = new ArrayList<Category>();

    public String doCreateProduct()
    {
        product = productEjb.createProduct(product);
        productList = productEjb.findAllProducts();
        return "listProduct";
    }

    @PostConstruct
    public void init()
    {
        categoryList = categoryEjb.findAllCategory();
        productList = productEjb.findAllProducts();
    }        

    // Getters/Setters and other methods omitted for simplicity

为简单起见,这是简化的 EJB:

   @Stateless
    public class ProductEJB{

        @PersistenceContext(unitName = "luavipuPU")
        private EntityManager em;

        public List<Product> findAllProducts()
        {
            TypedQuery<Product> query = em.createNamedQuery("findAllProducts", Product.class);
            return query.getResultList();
        }

        public Product createProduct(Product product)
        {
            em.persist(product);
            return product;
        }    

    }

这是为简单起见简化的产品实体:

@Entity
@NamedQueries({
    @NamedQuery(name="findAllProducts", query = "SELECT p from Product p")
})
public class Product implements Serializable
{
    private static final long serialVersionUID = 1L;

    @Id @GeneratedValue(strategy= GenerationType.AUTO)
    private int product_id;
    private String name;
    private String description;
    protected byte[] imageFile;
    private Float price;
    @Temporal(TemporalType.TIMESTAMP)
    private Date dateAdded;
    @ManyToOne    
    private Category category_fk;
    @ManyToOne
    private SaleDetails saleDetails_fk;

这是我正在使用的更新转换器:

@ManagedBean
@FacesConverter(value="categoryConverter")
public class CategoryConverter implements Converter{

    @PersistenceContext
    private transient EntityManager em;

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        return em.find(Category.class, new Integer(value));
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {

        Category category;
        category = (Category) value;
        return String.valueOf(category.getCategory_id());

    }

}

代码已从原始问题更新,代码现在完美运行。

【问题讨论】:

    标签: jsf jakarta-ee xhtml converter backing-beans


    【解决方案1】:

    如果不创建 JSF Converter,就不能在 &lt;h:selectOneMenu/&gt; 组件(或任何 &lt;h:selectXXXX/&gt;)上使用自定义类型。 JSF 中存在转换器以帮助将本质上自定义或服务器端项目/结构转换为网页友好/人类可读格式,并且还能够将选择从客户端保存回服务器端。因此,错误消息本质上告诉您的是,它无法充分理解从客户端提交的值 52 以将其作为 Category 对象/类型保存到服务器端

    因此,您需要做的是创建一个 JSF converter 的实现,它基本上可以帮助 JSF 理解您的 Category 对象。

    以下是您需要做的粗略估计:

    1. 为您的 Category 类型实现转换器:

      // You must annotate the converter as a managed bean, if you want to inject
      // anything into it, like your persistence unit for example.
      @ManagedBean(name = "categoryConverterBean") 
      @FacesConverter(value = "categoryConverter")
      public class CategoryConverter implements Converter {
      
          @PersistenceContext(unitName = "luavipuPU")
          // I include this because you will need to 
          // lookup  your entities based on submitted values
          private transient EntityManager em;  
      
          @Override
          public Object getAsObject(FacesContext ctx, UIComponent component,
                  String value) {
            // This will return the actual object representation
            // of your Category using the value (in your case 52) 
            // returned from the client side
            return em.find(Category.class, new BigInteger(value)); 
          }
      
          @Override
          public String getAsString(FacesContext fc, UIComponent uic, Object o) {
              //This will return view-friendly output for the dropdown menu
              return ((Category) o).getId().toString(); 
          }
      }
      
    2. 在您的 &lt;h:selectOneMenu/&gt; 中引用您的新转换器

      <h:selectOneMenu id="category_fk" 
        converter="#{categoryConverterBean}"
        value="#productController.product.category_fk}" 
        title="Category_fk" >
      <!-- DONE: update below reference to list of available items-->
          <f:selectItems value="#{productController.categoryList}" 
            var="prodCat" itemValue="#{prodCat.category_id}" 
            itemLabel="#{prodCat.name}"/>
      </h:selectOneMenu>
      

    我们使用名称 categoryConverterBean 是因为我们想利用您在转换器中使用的实体管理器技巧。在其他情况下,您将使用您在转换器注释上设置的名称。

    【讨论】:

    • 非常感谢。从昨天开始,我一直在阅读有关转换器的信息,但在您解释之前我无法真正理解它。我尝试实施您的建议,但是,我现在收到一个新错误,java.lang.ExceptionInInitializerError 'Caused by: java.lang.RuntimeException: Uncompilable source code - class CategoryConverterimplements 是公共的,应在名为 CategoryConverterimplements 的文件中声明.java 在 com.lv.Controllers.Converters.CategoryConverterimplements.(CategoryConverter.java:17)'
    • 我还使用转换器添加的代码以及清单的 xhtml 部分更新了帖子。如果您对如何解决此错误有任何想法,请告诉我。提前致谢。 java.lang.ExceptionInInitializerError 'Caused by: java.lang.RuntimeException: Uncompilable source code - class CategoryConverterimplements is public, should be declared in a file named CategoryConverterimplements.java at com.lv.Controllers.Converters.CategoryConverterimplements.&lt;clinit&gt;(CategoryConve‌​rter.java:17)'
    • @lv10 问题不在于您的源,看起来更像是您的源文件命名错误:转换器实现为一个名为CategoryConverter 的类,因此.java 文件应该是叫CategoryConverter.java。这是你有的吗?因为,从例外情况来看,您的班级似乎被命名为CategoryConverterimplements。另外,我看到您在 getAsString 实现中返回了 getName()。这行不通。无论您在 getAsString 中返回什么,都将作为 Value 提供给您的 getAsObject 实现。
    • @lv10 您在getAsString 实现中返回的内容应该是您可以在getAsObject 中使用的内容来搜索对象。为此,我建议使用独特的id 类型值
    • 再次感谢。我选择离开@ManagedBean,没有指定名称,并且错误停止显示。但是,对于getAsString,我试图返回如下内容:return ((Category)value).getCategory_id().toString();,但我不断收到int cannot be dereferenced,因此它甚至无法运行。我已经更新了反映最后更改的代码。提前致谢。
    【解决方案2】:

    Product.category_fk 似乎是 Category 类型,我怀疑 prodCat.category_id 是 Integer 或其他什么...

    在您的 xhtml 中,您似乎将 selectItems 的值设置为:itemValue="#{prodCat.category_id}"

    当 selectOneMenu 需要一个值 value="#{productController.product.category_fk}"

    很可能不是同一类型。

    【讨论】:

    • 我进行了更改,但是我没有收到另一个错误。我得到了这个:转换错误设置值 'Category{category_id=52, name=Libros - Conflicto Armado, description=lualvipu, product_fk={IndirectList: not instantiated}}' for 'null Converter'。
    • 所以我不完全确定这是否仍然与之前的问题有关。非常感谢
    • 我不确定是否理解您的错误消息,但您始终可以尝试将您的对象包装在 javax.faces.model.SelectItem 列表中...它可能会帮助您了解 selectOneMenu 需要什么上班
    猜你喜欢
    • 2021-05-12
    • 2013-03-17
    • 2012-10-31
    • 1970-01-01
    • 2012-06-06
    • 1970-01-01
    • 2012-11-19
    • 2011-09-23
    • 2011-10-31
    相关资源
    最近更新 更多