유효성 검사 오류 : 값이 유효하지 않습니다.


80

ap : selectOneMenu에 문제가 있습니다. 내가 무엇을하든 JSF가 JPA 엔티티에서 setter를 호출하도록 할 수 없습니다. 다음 메시지와 함께 JSF 유효성 검사가 실패합니다.

양식 : 위치 : 유효성 검사 오류 : 값이 유효하지 않습니다.

나는 같은 유형의 여러 다른 클래스 (즉, 조인 테이블 클래스)에서이 작업을 수행하고 있지만 평생이 작업을 수행 할 수는 없습니다.

누군가가 이런 종류의 문제에 대한 문제 해결 / 디버깅 팁을 던질 수 있다면 대단히 감사하겠습니다.

로그 문을 사용하여 다음을 확인했습니다.

  1. 에서 Conveter올바른 null값이 아닌 값을 반환 합니다.
  2. 내 JPA 엔터티에 Bean 유효성 검사가 없습니다.
  3. setter setLocation(Location location)는 호출되지 않습니다.

이것은 내가 할 수있는 가장 간단한 예이며 단순히 작동하지 않을 것입니다.

<h:body>
    <h:form id="form">
        <p:messages id="messages" autoUpdate="true" />
        <p:selectOneMenu id="location" value="#{locationStockList.selected.location}" converter="locationConverter">
            <p:ajax event="change" update=":form:lblLocation"/>
            <f:selectItems value="#{locationStockList.locationSelection}"/>
        </p:selectOneMenu>
    </h:form>
</h:body>

변환기:

@FacesConverter(forClass=Location.class, value="locationConverter")
public class LocationConverter implements Converter, Serializable {
    private static final Logger logger = Logger.getLogger(LocationConverter.class.getName());

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        if (value.isEmpty())
            return null;
        try {
            Long id = Long.parseLong(value);
            Location location = ((LocationManagedBean) context.getApplication().getELResolver().getValue(context.getELContext(), null, "location")).find(id);
            logger.log(Level.SEVERE, "Converted {0} to {1}" , new Object[] {value, location});
            return location;
        } catch (NumberFormatException e) {
            return new Location();
        }
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        if (value == null || value.toString().isEmpty() || !(value instanceof Location))
            return "";
        return String.valueOf(((Location) value).getId());
    }    
}

콘솔 출력 :

// Getter method
INFO: Current value=ejb.locations.Location[id=null, name=null, latitude=0.0, longitude=0.0] 
// Session Bean
INFO: Finding ejb.locations.Location with id=3 
// Session Bean
INFO: ### Returning : ejb.locations.Location[id=3, name=mdmd, latitude=4.5, longitude=2.3] 
// Converter
SEVERE: Converted 3 to ejb.locations.Location[id=3, name=mdmd, latitude=4.5, longitude=2.3] 
// Getter method -> Where did my selected Location go ??
INFO: Current value=ejb.locations.Location[id=null, name=null, latitude=0.0, longitude=0.0] 

답변:


143

"form : location : Validation Error : Value is not valid"메시지와 함께 유효성 검사가 실패합니다.

이 오류는 선택한 항목이 <f:selectItem(s)> 양식 제출 요청을 처리하는 동안 중첩 된 태그로 지정된 사용 가능한 선택 항목 값과 일치하지 않기 때문에 귀결됩니다 .

변조 / 해킹 된 요청에 대한 보호의 일환으로 JSF는 사용 가능한 모든 선택 항목 값을 반복하고 하나 이상의 사용 가능한 항목 값이 selectedItem.equals(availableItem) 반환 되는지 테스트 true합니다. 일치하는 항목 값이 하나도 없으면이 유효성 검사 오류가 발생합니다.

이 프로세스는 기본적으로 아래와 같이 커버되며,에 bean.getAvailableItems()의해 정의 된 사용 가능한 선택 항목의 전체 목록을 가상으로 나타냅니다 <f:selectItem(s)>.

String submittedValue = request.getParameter(component.getClientId());
Converter converter = component.getConverter();
Object selectedItem = (converter != null) ? converter.getAsObject(context, component, submittedValue) : submittedValue;

boolean valid = false;

for (Object availableItem : bean.getAvailableItems()) {
    if (selectedItem.equals(availableItem)) {
        valid = true;
        break;
    }
}

if (!valid) {
    throw new ValidatorException("Validation Error: Value is not valid");
}

따라서 위의 논리를 기반으로이 문제는 논리적으로 다음과 같은 원인이있을 수 있습니다.

  1. 선택한 항목이 사용 가능한 항목 목록에 없습니다.
  2. equals()선택한 항목을 나타내는 클래스 의 메서드가 없거나 손상되었습니다.
  3. 사용자 지정 Converter이 포함 된 경우 getAsObject(). 아마도 null.

그것을 해결하려면 :

  1. 특히 여러 계단식 메뉴의 경우 후속 요청 중에 정확히 동일한 목록이 보존되었는지 확인합니다. @ViewScoped대신 콩을 만들면 @RequestScoped대부분의 경우 수정됩니다. 또한의 getter 메서드에서 비즈니스 논리를 수행하지 않고 <f:selectItem(s)>대신 @PostConstruct또는 작업 이벤트 (수신기) 메서드에서 수행해야합니다. 특정 요청 매개 변수에 의존하는 경우 @ViewScoped빈 에 명시 적으로 저장 하거나 예를 들어 후속 요청에서 다시 전달해야합니다 <f:param>. 올바른 Bean 범위를 선택하는 방법 도 참조하십시오 .
  2. equals()방법이 올바르게 구현 되었는지 확인하십시오 . 이것은 java.lang.String, 등과 같은 표준 Java 유형에서 이미 올바르게 수행 java.lang.Number되었지만 사용자 정의 객체 / 빈 / 엔티티에서는 반드시 수행되는 것은 아닙니다. 동등한 계약을 구현하는 올바른 방법을 참조하십시오 . 이미을 사용중인 경우 String요청 문자 인코딩이 올바르게 구성되었는지 확인하십시오. 특수 문자를 포함하고 JSF가 출력을 UTF-8로 렌더링하도록 구성되었지만 입력을 ISO-8859-1과 같이 해석하면 실패합니다. PrimeFaces 입력 구성 요소를 통해 검색된 유니 코드 입력이 손상됨을 참조하십시오 .
  3. 사용자 지정 작업을 디버그 / 로그하고 Converter적절하게 수정합니다. 지침 은 'null 변환기'에 대한 변환 오류 설정 값 도 참조하십시오. java.util.Date와 함께 사용 가능한 항목으로 사용 <f:convertDateTime>하는 경우 패턴의 전체 시간 부분을 잊지 마십시오. f : datetimeConverter의 "유효성 검사 오류 : 값이 유효하지 않음"오류를 참조하십시오 .

또한보십시오:


누군가가 이런 종류의 문제에 대한 문제 해결 / 디버깅 팁을 던질 수 있다면 대단히 감사하겠습니다.

여기서 명확하고 구체적인 질문을하십시오. 너무 광범위한 질문을하지 마십시오.)


@BalusC : 모자라 코드에서 정확히 어디에서이 equals검사가 발생하는지. 제 상황은 조금 복잡합니다. 사용자가 복잡한 라디오 레이아웃을 가질 수 있도록 고유 한 사용자 지정 구성 요소를 만듭니다. 하나의 라디오 그룹 (사용자 정의 구성 요소 바로 아래에 f : selectItems) 만 있으면 제대로 작동합니다. 그러나 레이아웃이 더 복잡 해짐에 따라 (여러 라디오 그룹, 각각 고유 한 f : selectItems가 있지만 모두 동일한 선택을 공유 함) ui : repeat 내에 f : selectItems가 있어야하고 ui : repeat가 내 사용자 지정 구성 요소 아래에 있습니다. 그런 다음이 문제가 발생했습니다. 나는 이것을 처리하는 mojarra 코드를보고 싶다
Thang Pham

또한 내 f : selectItems는 문자열 유형이므로 이것이 변환 문제가 아니라고 확신합니다. 검증 단계에서 f : selectItems 목록이 없기 때문에 이것이 원인이라고 생각합니다.
Thang Pham 2012

f : param을 사용하여 "초기 상태"를 다시 생성 할 수 있도록 관리 빈에 상태를 보내는 방법에 대해 자세히 설명해 주시겠습니까 ??? 감사.
Agustí Sánchez

1
비슷한 오류가 있습니다. SelectItemsConverter를 사용하고 있으며이 구성 요소는 비활성화 된 필드 세트 내에 있으므로 비활성화되어 있습니다. 알려진 동작입니까?
Gilberto 2014 년

표시 할 항목에 대해 열거 형을 사용하고 있고 백업 Bean이 Bean의 값을 설정하기위한 문자열 유형을 가지고 있고 변환기를 사용하지 않는 경우 동일한 오류가 발생합니다. 그것이 내가 여기까지 온 방법입니다.
Philip Puthenvila 2015 년

2

제 경우에는 올바른 get / set 메서드를 구현하는 것을 잊었습니다. 개발 과정에서 많은 속성을 변경했기 때문에 발생했습니다.

적절한 get 메서드가 없으면 JSF는 선택한 항목을 복구 할 수 없으며 BalusC가 대답의 항목 1에서 말한대로 발생합니다.

1 . 선택한 항목이 사용 가능한 항목 목록에 없습니다. 이는 사용 가능한 항목 목록이 후속 요청에서 제대로 다시 초기화되지 않은 요청 범위 Bean에 의해 제공되거나 getter 메소드 내에서 비즈니스 작업을 잘못 수행하여 어떤 방식 으로든 다른 목록을 리턴하는 경우 발생할 수 있습니다.


1

이것은 변환기 문제이거나 DTO 문제 일 수 있습니다. 개체 DTO에 hashCode () 및 equals () 메서드를 추가하여이 문제를 해결하십시오. 위의 시나리오에서는 여기에서 'DTO'로 표시되는 Location 개체 클래스 내에서 이러한 메서드를 생성 할 수 있습니다.

예:

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + (int) (id ^ (id >>> 32));
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Location other = (Location) obj;
    if (id != other.id)
        return false;
    return true;
}
  • 위의 예는 'long'유형의 'id'에 대한 것입니다.

등이 허용 높은 upvoted 대답 # 2에 명시된
Kukeltje
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.