NullPointerException no JSF Converter (CDI) !

Precisei implementar um converter JSF para minha classe de Clientes. E ao injetar a classe de serviços (@Inject ClienteService clienteService), estou recebendo NullPointerException. Alguém já passou por isso?

  @Inject ClienteService clienteService;

  @Override
  public Object getAsObject(FacesContext fc, UIComponent uic, String string) {
    if (string == null || string.length() == 0 || string.startsWith("-")) {
      return null;
    }
    try {
      Integer id = Integer.parseInt(string);
      return clienteService.findById(id); // NPE aqui
        } catch (NumberFormatException | ConverterException e) {
      FacesUtils.error("Erro no converter: " + e.getMessage());
      throw new ConverterException("Erro de conversão do JSF - Valor " + string + " não conversível", e);
    }
  }

@leorbarbosa seguinte o converter não tem nenhum contexto, então não ocorre a injeção de dependência e por isto está null. Converter’s não tem responsabilidade de carregar uma entidade/objeto e sim apenas Converter.

A JavaServer Faces converter class converts strings to objects and objects to strings as required. Several standard converters are provided by JavaServer Faces for this purpose… http://docs.oracle.com/javaee/6/tutorial/doc/bnaus.html

Ou seja ela irá converter um objeto em string e uma string em objeto atuando entre a pagina JSF e seu ManagedBean. Uma dica particular, cria um converter geral pras entidades.

1 curtida

Valeu demais. E como seria um converter geral para entidades?

Eu uso este converter em um dos meus projetos:

@FacesConverter(value="entityConverter", forClass= BaseEntity.class)
public class EntityConverter implements Converter {

    public Object getAsObject(FacesContext ctx, UIComponent component,
            String value) {
        if (value != null) {
            return this.getAttributesFrom(component).get(value);
        }
        return null;
    }
 
    public String getAsString(FacesContext ctx, UIComponent component,
            Object value) {
 
        if (value != null && ! "".equals(value)) {
        	BaseEntity entity = (BaseEntity) value;
 
            if (entity.getId() != null) {
                this.addAttribute(component, entity);
 
                if (entity.getId() != null) {
                    return String.valueOf(entity.getId());
                }
                return (String) value;
            }
        }
        return "";
    }
 
    private void addAttribute(UIComponent component, BaseEntity o) {
        this.getAttributesFrom(component).put(o.getId().toString(), o);
    }
 
    private Map<String, Object> getAttributesFrom(UIComponent component) {
        return component.getAttributes();
    }

}

E está é a classe abstrata que extende nas minhas entidades, assim generalizo p/ todas classes que extender a classe BaseEntity pode usar este converter. Ignora a interface você não irá precisar.

@MappedSuperclass
public abstract class BaseEntity implements Serializable, IEntity {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id", nullable = false, columnDefinition = "BIGINT UNSIGNED")
    protected Long id;
    

    @Column(name = "version")
    @Version
    private Long version;

    public Long getId() {
        return id;
    }
    
    public void setId(Long id) {
        this.id = id;
    }
    
    public Long getVersion() {
        return version;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (this.getId() != null ? this.getId().hashCode() : 0);

        return hash;
    }

    @Override
    public boolean equals(Object object) {
	if (this == object)
            return true;
        if (object == null)
            return false;
        if (getClass() != object.getClass())
            return false;

        BaseEntity other = (BaseEntity) object;
        if (this.getId() != other.getId() && (this.getId() == null || !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }
    
}

Fica a vontade p/ melhorar a implementação.