[java] 通用JSF实体转换器



2 Answers

我正在使用JSF 2.0视图:

@FacesConverter("entityConverter")
public class EntityConverter implements Converter {

private static final String key = "com.example.jsf.EntityConverter";
private static final String empty = "";

private Map<String, Object> getViewMap(FacesContext context) {
    Map<String, Object> viewMap = context.getViewRoot().getViewMap();
    @SuppressWarnings({ "unchecked", "rawtypes" })
    Map<String, Object> idMap = (Map) viewMap.get(key);
    if (idMap == null) {
        idMap = new HashMap<String, Object>();
        viewMap.put(key, idMap);
    }
    return idMap;
}

@Override
public Object getAsObject(FacesContext context, UIComponent c, String value) {
    if (value.isEmpty()) {
        return null;
    }
    return getViewMap(context).get(value);
}

@Override
public String getAsString(FacesContext context, UIComponent c, Object value) {
    if (value == null) {
        return empty;
    }
    String id = ((Persistent) value).getId().toString();
    getViewMap(context).put(id, value);
    return id;
}
}
Question

这个问题在这里已有答案:

我正在编写我的第一个Java EE 6 Web应用程序作为学习练习。 我没有使用框架,只有JPA 2.0,EJB 3.1和JSF 2.0。

我有一个自定义转换器将存储在SelectOne组件中的JPA实体转换回实体。 我正在使用InitialContext.lookup来获取对会话Bean的引用以查找相关的实体。

我想创建一个通用的实体转换器,所以我不必为每个实体创建一个转换器。 我以为我会创建一个抽象实体并让所有实体扩展它。 然后为抽象实体创建自定义转换器,并将其用作所有实体的转换器。

这听起来合理和/或切实可行吗?

是不是有一个抽象的实体,只是一个转换器来转换任何实体更有意义? 在那种情况下,我不确定如何获得对相应会话Bean的引用。

我已经包含了我当前的转换器,因为我不确定我是否以最有效的方式获得了对Session Bean的引用。

package com.mycom.rentalstore.converters;

import com.mycom.rentalstore.ejbs.ClassificationEJB;
import com.mycom.rentalstore.entities.Classification;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.convert.FacesConverter;
import javax.naming.InitialContext;
import javax.naming.NamingException;

@FacesConverter(forClass = Classification.class)
public class ClassificationConverter implements Converter {

    private InitialContext ic;
    private ClassificationEJB classificationEJB;

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

        try {
            ic = new InitialContext();
            classificationEJB = (ClassificationEJB) ic.lookup("java:global/com.mycom.rentalstore_RentalStore_war_1.0-SNAPSHOT/ClassificationEJB");

        } catch (NamingException e) {
            throw new ConverterException(new FacesMessage(String.format("Cannot obtain InitialContext - %s", e)), e);
        }

        try {
            return classificationEJB.getClassificationById(Long.valueOf(value));
        } catch (Exception e) {
            throw new ConverterException(new FacesMessage(String.format("Cannot convert %s to Classification - %s", value, e)), e);
        }
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        return String.valueOf(((Classification) value).getId());
    }
}






我正在使用这样的东西:

@Named
public class EntityConverter implements Converter {

    @Inject
    private EntityManager entityManager;

    @Inject
    private ConversionService conversionService;

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        Class<?> entityType = component.getValueExpression("value").getType(context.getELContext());
        Class<?> idType = this.entityManager.getMetamodel().entity(entityType).getIdType().getJavaType();
        Object id = this.conversionService.convert(idType, value);
        return this.entityManager.getReference(entityType, id); // find() is possible too
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        Object id = this.entityManager.getEntityManagerFactory().getPersistenceUnitUtil().getIdentifier(value);
        return this.conversionService.convert(String.class, id);
    }   
}

ConversionService定义如下(这里的实现超出了范围):

public interface ConversionService {

    <T> T convert(Class<T> targetType, Object source);
}

在模板中,使用<f:converter binding="#{entityConverter}" />






Related



Tags

java java   jsf   jsf-2