2013-06-26 1 views
1

여기에서 설명 할 것보다 더 큰 문제가 있습니다. 그러나 설명하고 디버깅하기가 어려울 수 있으므로 더 작은 및 벙어리) 문제가 발생합니다.전용 Java 클래스가있는 사용자 정의 컴포넌트에서 Ajax 뷰 업데이트가 제대로 작동하지 않습니다.

내 목록에서 문자열 목록을 인쇄하려고하는데이 목록은 오프셋을 기반으로 계산됩니다. 내 자바 클래스에서 나는 거대한 정적 배열의 문자열 있습니다. 내 문자열 목록 (페이지에 인쇄 될)을 계산하려면 정적 배열의 값을 "offset"값부터 시작하여 내 목록에 복사합니다.

내 페이지에는 아약스 요청을 통해 "오프셋"값을 증가시키고 결과를 업데이트하는 "오프셋 증가"버튼이 있습니다 (목록은 새 오프셋을 기준으로 다시 계산됩니다).

내 문제는 : "Increment offset"버튼을 클릭하면 서버 측 코드가 실행되고 오프셋은 증가하지만 업데이트시 문제가 발생합니다 : 현재 오프셋을 보여주는 텍스트가 새 값으로 업데이트 됨 "offset"은 같지만 문자열 목록에는 동일하지 않으며 이전 값으로 업데이트되며 두 번째 요청을 수행하는 경우 새 값이 고려됩니다. 두 번째 요청에서 계산 된 값은 세 번째 업데이트에서는 뷰의 문자열 목록을 항상 한 요청 만 늦게 만듭니다.

이 이미지보기 (그래서 더 큰하는 새 탭에서 엽니) : enter image description here

가의 몇 가지 코드를 보자 ...

버튼 : 문자열의

<h:form> 
    <h:commandButton value="Increment offsets"> 
    <f:ajax listener="#{test.incrementOffset()}" render=":stringList" /> 
    </h:commandButton> 
</h:form> 

목록 :

<h:panelGroup id="stringList"> 
    <h1>Offsets increment = #{test.offset}</h1> 
    <comp:stringPrinter offset="#{test.offset}" /> 
</h:panelGroup> 

내가 제목에 대해 이야기 한 구성 요소가 있습니다. 문자열 목록은 페이지에 의해 계산되거나 인쇄되지 않습니다. 복합 요소로 계산되고 인쇄됩니다.

@ManagedBean(name="test") 
@ViewScoped 
public class Test implements Serializable { 
    private int offset; 

    public int getOffset() { 
    return offset; 
    } 

    public void incrementOffset(){ 
    offset++; 
    } 
} 

복합 구성 요소 :

복합 구성 요소의 코드에 가기 전에, 여기에 뷰에 사용 된 관리 빈 "테스트"의 간단한 말했듯이, 그것은 단지로 "오프셋"수신 매개 변수를 지정하고 문자열 목록을 인쇄하십시오. 아래 뷰 코드를 참조하십시오 :

<h:body> 
    <composite:interface componentType="stringPrinter"> 
    <composite:attribute name="offset" type="java.lang.Integer" required="true" /> 
    </composite:interface> 
    <composite:implementation> 
    <ul> 
     <ui:repeat value="#{cc.list}" var="string"> 
     <li>#{string}</li> 
     </ui:repeat> 
    </ul> 
    </composite:implementation> 
</h:body> 

을 그리고 이것은 문자열의 목록을 계산하는 방법이다 : 나는 구성 요소를 사용하지 않는 경우

@FacesComponent(value="stringPrinter") 
public class StringPrinter extends UINamingContainer implements Serializable { 
    private ArrayList<String> list; 

    private static String[] LIPSUM = "...".split(" "); // "..." is not the actual string, the string is irrelevant (it has more than 400 words separated by spaces). 
    private static int ARRAY_SIZE = 12; 

    private void generateList(){ 
    int offset = (Integer) getAttributes().get("offset"); 
    int position = offset; 
    list = new ArrayList<String>(); 
    for (int i = 0; i < ARRAY_SIZE; i++){ 
     list.add(LIPSUM[position++ % LIPSUM.length]); 
    } 
    } 

    public ArrayList<String> getList() { 
    if (null == list) generateList(); 
     return list; 
    } 
    } 
} 

문제가 발생하지 않습니다. 상위 뷰에서 목록이 계산되고 구성 요소에 연결된 Java 클래스가없는 경우 문제가 발생하지 않습니다. 그러나 실제 문제는 문자열을 출력 할 필요가 없기 때문에 복합 컴포넌트로 처리해야 할 필요가 있으므로 전용 클래스가 필요합니다.


일부 디버깅 :

는 UI : 반복 태그가 문제가 될 수 있습니다. 목록에서 첫 번째 문자열을 인쇄해야하는 목록을 인쇄하는 대신 (ui : repeat가 필요할 것입니다.) 모든 항목이 올바른 시간에 올바르게 업데이트됩니다.반복 : 정말 UI를 사용해야

<h:body> 
    <composite:interface componentType="stringPrinter"> 
    <composite:attribute name="offset" type="java.lang.Integer" required="true" /> 
    </composite:interface> 
    <composite:implementation> 
    <h:outputText value="#{cc.list.get(0)}" /> 
    </composite:implementation> 
</h:body> 

작품 위의 코드를하지만, 내가해야 할 일이 아니다 : 반복 : UI를 사용하지 않고 복합 구성 요소의 코드를 참조하십시오. 나는 또한 c : forEach, 같은 결과를 시도했다.

추가 디버깅을 위해 나는 페이지에서 incrementOffset() 메소드가 실행 된 후 구성 요소의 getList() 메소드가 호출되는지를 스스로에게 묻습니다. " 이 로그는 다음과 같습니다.

*** GET LIST CALLED! 
*** GET LIST CALLED! 
*** OFFSET INCREMENTED! 
*** GET LIST CALLED! 
*** GET LIST CALLED! 

메시지가 버퍼되지 않도록 System.out.flush()를 사용했습니다. 메소드가 실행 된 후에 getList()가 호출 된 것처럼 보입니다. 뷰가 이전 값으로 업데이트되는 이유가 표시되지 않습니다. 어쨌든 incrementOffset()이 실행되기 직전에 두 번 호출되고 두 번 후에는 조금 이상하다는 사실이 사실입니다.

이 문제는 Mojarra 2.1.7, 2.1.22, 2.1.23 및 2.2.0에 영향을줍니다. 나는 다른 버전을 테스트하지 않았다.

추가 디버그로이 게시물을 업데이트 할 예정입니다.

은 Maven 프로젝트를 다운로드하고 자신을 위해 테스트하려면 다음 zip file

감사합니다 사전에 어떤 대답을.

답변

2

문제가있는 곳을 발견했습니다. 구성 요소가 업데이트되면 완전히 재 처리되지만 일부 경우에는 발생하지 않는다고 생각했습니다. 어떤 이유로 인해 ui : repeat가 사용되면 JSF는 컴포넌트 재설정을 지연 시키려고합니다. getList()가 호출 될 때

해결책은 명시 적으로 목록을 다시 계산하는 것입니다 : 내가 널 (null)에 대한 검증을 제거하면

가 작동 :

그것은 전에이 같았다.

필자의 의견으로는 구성 요소가 업데이트되었을 때 목록에 이전에 계산 된 값이 있었지만 null이 아니며 다시 계산하지 않았습니다. 한 요청과 다른 요청 사이의 시간에 구성 요소가 재구성되고있었습니다. 컴퍼넌트가 리 셋트되고있는 경우, list는 null와 동일 해, 재 계산이 getList()로 행해져 뷰가 항상 1 개의 요구를 늦게합니다.


편집 : 모든 get에서 목록을 다시 계산하는 대신 구성 요소의보기에서 f : event를 사용하는 것이 훨씬 더 좋은 해결책입니다.

<f:metadata> 
    <f:event type="preRenderComponent" listener="#{cc.generateList}" /> 
</f:metadata> 
+0

기꺼이 해결했습니다. – Andy

+0

''은 ''안에있을 필요가 없습니다. – BalusC

관련 문제