服务未在 JSF 转换器中自动连线



我正在使用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>

在这里你有两个选择:

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;
    }
}

应用程序上下文提供程序类:

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 anyware的引用:

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;
    }
}

一个较晚的响应,但我遇到了同样的问题,无法将 Spring bean 自动连接到 JSF 转换器中,所以我删除了@FacesConverter注释并将转换器组件声明为会话范围,然后,像您所做的那样,使用带有绑定属性的 f:converter 标记解决了这个问题。在您的情况下:

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

应该工作...

最新更新