2012-05-10 2 views
3

된 invoke 내가 유효성 검사를 결합하고 userIdPlayer로 변환하려고이 f:viewParam이있을 때, 그리고 나는 예상치 못한 결과를 얻었다. 이F : viewParam 변환기 및 ViewScoped 예외 밖으로는 두 번째 아약스 요청

@FacesConverter(value="pConverter") 
public class PConverter implements Converter { 
private static final List<Player> playerList; 
static{ 
    playerList = new ArrayList<Player>();   
    playerList.add(new Player(1, "Harry")); 
    playerList.add(new Player(2, "Tom")); 
    playerList.add(new Player(3, "Peter")); 
} 

@Override 
public Object getAsObject(FacesContext fc, UIComponent uic, String value) { 
    if(value == null || !value.matches("\\d+")){ 
     return null; 
    } 
    long id = Long.parseLong(value); 
    for(Player p : playerList){ 
     if(p.getId() == id){ 
      return p; 
     } 
    } 
    throw new ConverterException(new FacesMessage("Unknown userId: " + value)); 

} 

@Override 
public String getAsString(FacesContext fc, UIComponent uic, Object value) { 
    if(!(value instanceof Player) || value == null){ 
     return null; 
    } 
    return String.valueOf(((Player)value).getId()); 
} 
} 

같은

<f:metadata> 
    <f:viewParam name="userId" value="#{myBean.selectedPlayer}" converter="pConverter" 
     converterMessage="Bad Request. Unknown User" required="true" 
     requiredMessage="Bad Request. Please use a link from within the system" /> 

</f:metadata> 
<h:body> 
    <p:messages id="msgs"/>   
    <h:form> 
     <ul> 
      <li><a href="index2.xhtml?userId=1">Harry</a></li> 
      <li><a href="index2.xhtml?userId=2">Tom</a></li> 
      <li><a href="index2.xhtml?userId=3">Peter</a></li> 
     </ul>    
    </h:form> 
    <h:form> 
     <h:panelGrid columns="2" rendered="#{not empty myBean.selectedPlayer}"> 

      <h:outputText value="Id: #{myBean.selectedPlayer.id}"/> 

      <h:outputText value="Name: #{myBean.selectedPlayer.name}"/> 

     </h:panelGrid> 
    </h:form> 
    <h:form id="testForm"> 
     <h:inputText value="#{myBean.text}"/> 
     <p:commandButton value="Switch" update=":msgs testForm"/> 
     <h:outputText value="#{myBean.text}" rendered="#{not empty myBean.text}"/> 
    </h:form>  
</h:body> 

내 개종 보면 나는 세 개의 링크 (해리, 톰, 피터), 큰 컨버터 작업을 클릭한다. 그것은 id를 변환하고 player을 다시 내 관리 Bean에 바인드합니다. 그런 다음 입력란에 무언가를 입력 한 다음 Switch을 처음 클릭하면 입력 한 내용이 버튼 옆에 나타나지만 입력 한 내용이 변경되고 Switch을 다시 클릭하면 오류 메시지가 나타납니다. Bad Request. Please use a link from within the systemf:viewParam에 대한 required의 오류 메시지 f : viewParam을 꺼내면 모든 것이 잘 작동합니다. 놀랍게도, 내가 f : viewParam에서 o : viewParam (OmniFaces)으로 전환한다면, 그것은 훌륭하게 작동합니다.

답변

4

<f:viewParam>은 모든 단일 HTTP 요청과 포스트 백에서 실행되기 때문입니다. 일반 GET 링크의 경우 제대로 작동합니다. 링크에서 해당 매개 변수를 정확하게 전달하기 때문입니다. 그것은 POST 양식에 대한 귀하의 경우 실패합니다, 왜냐하면 당신은 버튼에 그 매개 변수를 전달하지 않기 때문입니다. 따라서 요청 매개 변수 맵에 null이되고 required 유효성 검사기가 시작되어이 유효성 검사 오류가 발생합니다.

POST 양식에서도 <f:viewParam required="true">을 행복하게 유지하려면 기본적으로 명령 단추/링크에서 <f:param>의 초기 요청 매개 변수를 유지해야합니다.

@Override 
public boolean isRequired() { 
    // The request parameter get lost on postbacks, however it's already present in the view scoped bean. 
    // So we can safely skip the required validation on postbacks. 
    return !FacesContext.getCurrentInstance().isPostback() && super.isRequired(); 
} 

그래서, 이것은 required 검증을 생략 :

<p:commandButton value="Switch" update=":msgs testForm"> 
    <f:param name="userId" value="#{param.userId}" /> 
</p:commandButton> 

보기 콩 범위와 함께 사용할 수 있도록 설계되어 OmniFaces <o:viewParam>는 상기 isRequired() 게터의 추가 검사 (source code here)이 모든 포스트 백에서 (그리고 덧붙여, 그것은 또한 그것의 무국적 속성 때문에 모든 포스트 백에서 모델 값을 설정하는 것을 건너 뜁니다.) 따라서 유효성 검사 오류가 표시되지 않고 적절한 모델 값 (모든 다시 게시에서 다시 설정되지 않음)을 유지해야합니다.

+0

대단히 감사합니다. Omnifaces는 매우 훌륭합니다, BalusC. 귀하의 블로그에 'o : viewParam'에 관한 한 가지 질문이 있는데, Ajax 요청이 호출 될 때마다 omnifaces가'Converter '호출을 피할 것이라고 말했지만, 항상 getAsString() 메소드 내부에있는 것처럼 보입니다. 그래서이 행동이 올바른지 궁금합니다. 나는'getAsObject'가 모델 값을 설정한다는 것을 알고 있으므로'getAsObject'를 호출하지 않는 것이 큰 발전입니다. 그리고 고마워요. –

+1

객체를 문자열로 변환해야 할 때 (생성 된 HTML에 표시하기 위해)'getAsString()'이 호출됩니다. 그러나 이미 속성 중 하나의 문자열 값으로 간주되기 때문에 다소 싼 작업이어야합니다. 이 시점에서 이미 객체를 손에 쥐고 있기 때문에 값 비싼 DB 작업이 필요하지 않습니다. – BalusC

+0

고맙습니다. –