服务未在JSF转换器中自动装配

时间:2013-11-12 09:14:30

标签: spring jsf primefaces

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

2 个答案:

答案 0 :(得分:2)

这里有两个选项:

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

AppContext类:

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中(受this帖子启发)

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

AbstractConverter类

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中创建一个存储位置。我们现在可以用它来存储我们需要的任何转换器对象。

以下是具体转换器的示例:

EntityConverter类

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

答案 1 :(得分:0)

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

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

应该有用......