2011-05-05 2 views
9

내 응용 프로그램에서 Bean 유효성 검사가 제대로 작동합니다. 이제 새 사용자가 이미 선택한 사용자 이름을 선택하지 않았는지 확인하고 싶습니다.actionListener 또는 action 메소드에서 JSF 유효성 검사를 수행하는 방법은 무엇입니까?

actionListener에는 데이터베이스를 검사하는 코드가 있지만 사용자가 이미 존재하는 사용자 이름을 선택하면 해당 페이지로 되돌려 보내야합니다. 어떻게해야합니까?

+0

사용자 이름이 유효하지 않으면 처음부터 다른 페이지로 리디렉션하지 않아야한다고 생각합니다. – Benchik

답변

14

소개

당신 을 수행하지만, JSF 아약스/액션/리스너 방법은 의미 적으로 검증 할 수있는 잘못된 장소입니다. 양식에 잘못된 입력 값이있는 경우 실제로 JSF 수명주기에서이를 얻고 싶지는 않습니다. JSF 유효성 검사 단계가 끝나면 JSF 라이프 사이클이 중지되기를 원합니다.

당신은 JSR303 콩 검증 주석 (@NotNull 친구) 및/또는 제약 유효성 검사기를 사용하거나 그 대신위한 JSF Validator (required="true", <f:validateXxx> 등)를 사용하고 싶습니다. JSF 유효성 검사 단계에서 올바르게 호출됩니다. 이렇게하면 유효성 검사가 실패하면 모델 값이 업데이트되지 않고 비즈니스 액션이 호출되지 않고 동일한 페이지/뷰에 유지됩니다.

주어진 입력 값이 데이터베이스에 따라 고유한지 확인하기 위해 표준 Bean 유효성 검사 주석 또는 JSF 유효성 검사기가 없기 때문에 사용자 정의 유효성 검사기를 homegrow해야합니다.

나는 두 가지 방법 모두 사용자 이름의 고유성을 검사하는 사용자 정의 검사기를 만드는 방법을 보여줍니다.

@Constraint(validatedBy = UsernameValidator.class) 
@Documented 
@Retention(RetentionPolicy.RUNTIME) 
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE}) 
public @interface Username { 
    String message() default "Username already exists"; 
    Class<?>[] groups() default {}; 
    Class<? extends Payload>[] payload() default {}; 
} 

이 제약 검사기 (참고 :

사용자 정의 JSR303 콩 검증 주석

먼저 사용자 정의 @Username 제약 주석 작성에만 CDI 1.1 이후 ConstraintValidator 작품 내부 @EJB 또는 @Inject을, 그래서 경우 CDI 1에 아직도있다.0 당신은) 수동으로 JNDI에서 잡아해야 할 것 :

public class UsernameValidator implements ConstraintValidator<Username, String> { 

    @EJB 
    private UserService service; 

    @Override 
    public void initialize(Username constraintAnnotation) { 
     // If not on CDI 1.1 yet, then you need to manually grab EJB from JNDI here. 
    } 

    Override 
    public boolean isValid(String username, ConstraintValidatorContext context) { 
     return !service.exist(username); 
    } 

} 

마지막으로 사용 모델에서 다음과 같이

@Username 
private String username; 

사용자 정의 JSF 검사기

또 다른 사용자 정의를 사용하는 것입니다

JSF 유효성 검사기. 보기에서 다음과 같이

@ManagedBean 
@RequestScoped 
public class UsernameValidator implements Validator { 

    @EJB 
    private UserService userService; 

    @Override 
    public void validate(FacesContext context, UIComponent component, Object submittedAndConvertedValue) throws ValidatorException { 
     String username = (String) submittedAndConvertedValue; 

     if (username == null || username.isEmpty()) { 
      return; // Let required="true" or @NotNull handle it. 
     } 

     if (userService.exist(username)) { 
      throw new ValidatorException(new FacesMessage("Username already in use, choose another")); 
     } 
    } 

} 
마지막으로

사용 : : 그냥 JSF Validator 인터페이스를 구현하면 일반적으로 Validator 클래스에 @FacesValidator 주석을 사용하지만, 곧 JSF 2.3까지 줄

<h:inputText id="username" ... validator="#{usernameValidator}" /> 
<h:message for="username" /> 

@EJB 또는 @Inject을 지원하지 않습니다. How to inject in @FacesValidator with @EJB, @PersistenceContext, @Inject, @Autowired을 참조하십시오.

+1

감사합니다. BalusC. Bean 유효성 검사가 수행되기 전이나 후에이 유효성 검사기를 호출 할 것인지 아니면 순서가 지정되지 않았습니까? –

+2

JSF 유효성 검사는 Bean 유효성 검사 전에 실행됩니다. 그러나 값이 'null'이거나 비어 있으면 'required'이외의 JSF 유효성 검사는 실행되지 않습니다. 그래서'required = "true"'없이'@ NotNull'을했다면, 먼저 실행될 것입니다. 하지만 비어 있지 않고 예를 들어'@ Pattern'을 가지고 있으면 JSF 검사기가 먼저 호출됩니다. – BalusC

+0

당신은 최고입니다. 하지만 난 그냥 정상 jsf 유효성 검사기를 사용하지만 콩 검증을 사용하여 속성의 유효성을 검사 할 수 있습니까? 유효하면 데이터베이스를 확인할 수 있습니다. Validator 클래스의 validateProperty 메서드를 시도했지만 이해할 수 없었던 그룹 및 기타 의미를 묻는 질문이 있었기 때문에 제대로 작동하지 못했습니다. –

2

이 목적을 위해 actionListener 대신 action 메서드를 사용하는 것이 좋습니다. 그런 다음 사용자 이름이있는 경우 null (작업을 실행 한 페이지를 다시로드)을이 메소드에서 반환 할 수 있습니다. facelet에서

: 빈에서

<h:commandButton action="#{testBean.doAction}" value="and... Action"/> 

:

public String doAction() { 
    if (userExists) { 
    return null; 
    } else { 
    // go on processing ... 
    } 
} 
0

당신은 faces-config.xml 파일에서 네비게이션 케이스를 정의 할 수 있습니다 다음은 예입니다. 이렇게하면 빈의 리턴 값에 따라 사용자를 주어진 페이지로 재지 정할 수 있습니다.

아래 예제에서 "myMethod()"의 반환 값에 따라 suer가 두 페이지 중 하나로 리디렉션됩니다.

<navigation-rule> 
    <from-view-id>/index.xhtml</from-view-id> 
    <navigation-case> 
    <from-action>#{myBean.myMethod()}</from-action> 
    <from-outcome>true</from-outcome> 
    <to-view-id>/correct.xhtml</to-view-id> 
    </navigation-case> 
    <navigation-case> 
    <from-action>#{myBean.myMethod()}</from-action> 
    <from-outcome>false</from-outcome> 
    <to-view-id>/error.xhtml</to-view-id> 
    </navigation-case> 
</navigation-rule> 
3

가능합니다. 작업 수신기 메서드에서 유효성 검사를 수행하고 사용자 지정 유효성 검사가 실패한 경우 얼굴 메시지를 추가 한 다음 반환하기 바로 전에 FacesContext.validationFailed()을 호출 할 수 있습니다.

이 솔루션의 유일한 문제점은 JSF 유효성 검증 및 bean 유효성 검증 이후에 발생합니다. 즉, 검증 단계가 끝난 후입니다. listener1 및 listener2 : listener1의 사용자 정의 유효성 검사에 실패한 경우 listener2를 계속 실행합니다. 하지만 결국 AJAX 응답에 불만족 스러울 것입니다.

+0

actionListener에서 주석이 완료된 경우에는이를 작성해야합니다. 액션 메소드가'facesContext.isValidationFailed()'를 계속 확인하는지 확인하십시오. – Lucas

관련 문제