gpt4 book ai didi

带有 noSelectionOption 的 JSF SelectOneMenu 使用标签作为值?

转载 作者:行者123 更新时间:2023-12-04 14:34:57 24 4
gpt4 key购买 nike

在“创建新用户”jsf 页面中,我有一个带有自定义转换器的 SelectOneMenu 和一个 noSelectionOption selectItem,如下所示:(省略了不相关的代码)

新用户.xhtml

<h:form>
<h:selectOneMenu value="#{newUserController.user.department}"
required="true" converter="departmentConverter">
<f:selectItem itemLabel="Select a department" noSelectionOption="true"/>
<f:selectItems value="#{newUserController.departments}"
var="dep" itemLabel="#{dep.name}" itemValue="#{dep}"/>
</h:selectOneMenu>
<p:commandButton action="#{newUserController.saveUser}"
value="#{bundle.Save}"
ajax="false"/>
</h:form>

新用户 Controller .java
@ManagedBean
@ViewScoped
public class NewUserController implements Serializable {
private static final long serialVersionUID = 10L;

@EJB private UserBean userBean;
private List<Department> departments;
private User user;

public NewUserController () {
}

@PostConstruct
public void init(){
user = new User();
departments = userBean.findAllDepartments();
}

public User getUser() {
return user;
}

public void setUser(User user) {
this.user = user;
}

public List<Department> getDepartments(){
return departments;
}

public String saveUser() {
// Business logic
}
}

部门转换器.java
@FacesConverter(value="departmentConverter")
public class DepartmentConverter extends EntityConverter {
public DepartmentConverter(){
super(Department.class);
}
}

所有实体的 super 转换器
public class EntityConverter<E> implements Converter{
protected Class<E> entityClass;

public EntityConverter(Class<E> type) {
entityClass = type;
}

@Override
public Object getAsObject(FacesContext facesContext, UIComponent component, String value) {
if (value == null || value.length() == 0) {
return null;
}
try {
InitialContext ic = new InitialContext();
UserBean ub = (UserBean)ic.lookup("java:global/CompetenceRegister/UserBean");
return ub.find(entityClass, getKey(value));
} catch (NamingException e) {
return null;
}
}

Long getKey(String value) {
Long key;
key = Long.valueOf(value);
return key;
}

String getStringKey(Long value) {
StringBuilder sb = new StringBuilder();
sb.append(value);
return sb.toString();
}

@Override
public String getAsString(FacesContext facesContext, UIComponent component, Object object) {
if (object == null) {
return null;
}
if (object instanceof AbstractEntity) {
AbstractEntity e = (AbstractEntity) object;
return getStringKey(e.getId());
}
else
throw new IllegalArgumentException("object " + object + " is of type " + object.getClass().getName() + "; expected type: " + entityClass.getName());
}

}

但是,当我发布选择了“选择部门”选项的表单时,它会发送 标签到转换器中的 getAsObject 而不是 null,从而导致转换器在 getKey 中抛出异常(尝试将包含 id 的 String 转换为 Long)。将 selectItem 的 itemValue 属性设置为 null 不起作用。集合中的项目与转换器完美兼容。有没有人知道是什么导致了这种情况?

更新 一件有趣的事我忘了提;如果我从 SelectOneMenu 中删除转换器属性,则 noSelectionAttribute 会正常工作,但是由于默认转换器不知道如何转换我的对象,因此该帖子在选择真正的部门时会失败。这是否意味着 noSelectionOption=true 应该改为发送其标签,并且转换器以某种方式处理它?

最佳答案

我的问题是切换到使用 SelectOneMenu 的转换器属性,而不是使用 FacesConverter 的 forClass 属性。

交换

@FacesConverter(value="departmentConverter")
public class DepartmentConverter extends EntityConverter {
public DepartmentConverter(){
super(Department.class);
}
}


@FacesConverter(forClass=Department.class)
public class DepartmentConverter extends EntityConverter {
public DepartmentConverter(){
super(Department.class);
}
}

当 NoSelectionOption 属性设置为 true 时,会导致我自己的转换器用于实际值,而默认转换器(空转换器?我无法找到它的源代码)被使用。我的理论是,将此属性设置为 true 会将值的类型设置为 null,并将标签作为值,导致它转到一个始终返回 null 或类似值的特殊转换器。使用转换器属性而不是 forClass 会导致始终使用我自己的转换器而不管类型如何,因此我必须自己处理作为值发送的标签。

关于带有 noSelectionOption 的 JSF SelectOneMenu 使用标签作为值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4595280/

24 4 0