【问题标题】:Service not Autowired in JSF Converter [duplicate]JSF转换器中未自动装配服务[重复]
【发布时间】:2013-11-12 09:14:30
【问题描述】:

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

我的 JSF p:selectOneMenu 有一个转换器。我的问题是,当我运行我的应用程序时,Service 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>

【问题讨论】:

    标签: spring jsf primefaces


    【解决方案1】:

    这里有两种选择:

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

    【讨论】:

      【解决方案2】:

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

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

      应该可以...

      【讨论】:

      • 'should' or 'does' work?
      • 好吧,我说“应该”是因为我没有 Safwen Khalloufi 的代码来测试它。在我的项目中确实有效。
      猜你喜欢
      • 2014-09-13
      • 1970-01-01
      • 2013-08-15
      • 2020-06-26
      • 1970-01-01
      • 2016-08-19
      • 2019-01-19
      • 2013-03-02
      • 2011-04-04
      相关资源
      最近更新 更多