0

我正在使用 PrimeFaces、JPA、Hibernate 和 JSF 2.0 开发一个 Web 应用程序。

我的 JSF 有一个转换器p:selectOneMenu。我的问题是,当我运行我的应用程序时,服务descriptifService没有自动装配,它返回NULL

转换器:

@Component
@FacesConverter(value = "descriptifConverter")
public class DescriptifConverter implements Converter {

@Autowired
@RmiClient
private IDescriptifService descriptifService;

@Override
public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) {
    if (arg2 == null || arg2.isEmpty()) {
        return null;
    }

    String descriptif = arg2;
    Long value = Long.valueOf(descriptif);
    DescriptifDto result = new DescriptifDto();
    result = descriptifService.findById(value);
    return result;
}

@Override
public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2) {

    if(arg2 == null || ((DescriptifDto) arg2).getIdDescriptif() == null) return null;

    DescriptifDto descriptif = new DescriptifDto();

    if(arg2 instanceof DescriptifDto) {
        descriptif = (DescriptifDto) arg2;
        String idDescriptif = descriptif.getIdDescriptif().toString();
        return (idDescriptif != null) ? String.valueOf(idDescriptif) : null;
    } else throw new ConverterException("Something wrong!" + arg2.hashCode() + arg2.toString());

}
}

JSF 代码:

                        <p:selectOneMenu value="#{lotController.selectedDescriptif}"
                            effect="fade">
                            <f:selectItems value="#{lotController.listDescriptifs}" var="descriptif"
                                itemLabel="#{descriptif.libelle}" itemValue="#{descriptif}" />
                                <f:converter binding="#{descriptifConverter}" />
                        </p:selectOneMenu>
4

2 回答 2

2

在这里,您有两个选择:

1 - 注册一个上下文提供者 bean:

应用上下文类:

import org.springframework.context.ApplicationContext;

public class AppContext {

    private static ApplicationContext ctx;

    public static void setApplicationContext(
            ApplicationContext applicationContext) {
        ctx = applicationContext;
    }

    public static ApplicationContext getApplicationContext() {
        return ctx;
    }

}

ApplicationContextProvider 类:

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class ApplicationContextProvider implements ApplicationContextAware {

    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
        AppContext.setApplicationContext(applicationContext);
    }

}

注册 bean:

<bean id="contextApplicationContextProvider" class="com.example.ApplicationContextProvider" />

现在,通过上下文,您可以随时获取对服务 bean 的引用:

IDescriptifService descriptifService = AppContext.getApplicationContext().getBean(IDescriptifService.class);

2 - 将转换后的值存储在 ViewMap 中(受本文启发)

我喜欢这个解决方案,因为它不需要数据库访问,从而提高了应用程序的性能。

抽象转换器类

import java.util.HashMap;
import java.util.Map;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;

public abstract class AbstractConverter implements Converter {

    private static final String KEY = "com.example.converters.AbstractConverter";

    protected 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 final Object getAsObject(FacesContext context, UIComponent c,
            String value) {
        if (value == null || value.isEmpty()) {
            return null;
        }
        return getViewMap(context).get(value);
    }

    @Override
    public final String getAsString(FacesContext context, UIComponent c,
            Object value) {
        if (value != null) {
            String id = getConversionId(value);
            if (id == null || id.isEmpty()) {
                throw new IllegalArgumentException(
                        "Objeto não pode ser convertido.");
            }
            getViewMap(context).put(id, value);
            return id;
        }
        return null;
    }
    //Every concrete class must provide an unique conversionId String
    //to every instance of the converted object
    public abstract String getConversionId(Object value);
}

这里我们在 ViewMap 内部创建了一个存储位置。我们现在可以使用它来存储我们需要的任何转换器对象。

这是一个具体转换器的示例:

实体转换器类

import javax.faces.convert.FacesConverter;

import com.example.AbstractEntity;

@FacesConverter("entity")
public class EntityConverter extends AbstractConverter {

    @Override
    public String getConversionId(Object value) {

        if (value instanceof AbstractEntity) {
            AbstractEntity entity = (AbstractEntity) value;
            StringBuilder sb = new StringBuilder();
            sb.append(entity.getClass().getSimpleName());
            sb.append("@");
            sb.append(entity.getId());
            return sb.toString();
        }

        return null;
    }
}
于 2013-11-12T10:10:31.503 回答
0

响应迟了,但我遇到了同样的问题,即无法将 Spring bean 自动装配到 JSF 转换器中,因此我删除了 @FacesConverter 注释并将转换器组件声明为会话范围,然后像您一样使用 f:converter带有绑定属性的标签解决了这个问题。在你的情况下:

@Component
@Scope(WebApplicationContext.SCOPE_SESSION)
public class DescriptifConverter implements Converter {
...
}

应该管用...

于 2015-04-15T11:03:05.350 回答