오랜 시간 사과 드리지만 정말 도움이 필요합니다. 프로젝트의 일환으로 현재 사용자가 처음 4 자 이상을 입력하고 결과를 입력하면 검색 결과 목록이 업데이트되는 검색 엔진을 만들고 있습니다. 검색 값은 텍스트 상자에 입력되지만 결과는 Richfaces 구성 요소 rich : extendedDataTable에 표시됩니다. 검색 값이 제거되면 결과 목록은 비어 있습니다. 그러나 몇 번 시도한 후에 컴포넌트 자체에 의해 throw 된 ConcurrentModificationException을 얻었습니다. 내가 찾고있는 초기 목록은 속성 파일에서옵니다 (사용자가 무언가를 입력 할 때마다 검색이 데이터베이스에 저장되는 것을 원하지 않기 때문에). 나는 몇 달 동안 머리를 두드렸다. 내가 뭘 놓치고 있니? 내가 한 일을 보여 드리겠습니다.Richfaces ExtendedDataTable을 사용하는 ConcurrentModificationException
검색 논리를 트리거해야하는 입력 텍스트입니다 (값이 4 자 미만이거나 사용자가 키를 누르면 테이블이 업데이트되지 않도록해야합니다.
<h:inputText id="firmname" value="#{ExtendedTableBean.searchValue}">
<a4j:support reRender="resultsTable" onsubmit="
if ((this.value.length<4 && this.value.length>0) || !returnunicode(event)) {
return false;
}" actionListener="#{ExtendedTableBean.searchForResults}" event="onkeyup" />
</h:inputText>
액션 리스너 목록을 갱신해야하는지이다 -, 화살표, 시프트 및 CTRL 같이이 함수는 "returnunicode (이벤트)")이다. 여기에 바로 InputText]를 아래 extendedDataTable은 다음과 같습니다
이제<rich:extendedDataTable tableState="#{ExtendedTableBean.tableState}" var="item"
id="resultsTable" value="#{ExtendedTableBean.dataModel}">
... <%-- I'm listing columns here --%>
</rich:extendedDataTable>
가 괜찮은지 어떤지, 내가 당신에게 백엔드 코드를 보여 드리고자합니다. 나는 내 문제에 중요한 논리 만 남겼다.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.beans;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.ConcurrentModificationException;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import org.richfaces.model.DataProvider;
import org.richfaces.model.ExtendedTableDataModel;
public class ExtendedTableBean {
private String sortMode="single";
private ExtendedTableDataModel<ResultObject> dataModel;
//ResultObject is a simple pojo and getResultsPerValue is a method that
//read the data from the properties file, assigns it to this pojo, and
//adds a pojo to the list
private Object tableState;
private List<ResultObject> results = new CopyOnWriteArrayList<ResultObject>();
private List<ResultObject> selectedResults =
new CopyOnWriteArrayList<ResultObject>();
private String searchValue;
/**
* This is the action listener that the user triggers, by typing the search value
*/
public void searchForResults(ActionEvent e) {
synchronized(results) {
results.clear();
}
//I don't think it's necessary to clear results list all the time, but here
//I also make sure that we start searching if the value is at least 4
//characters long
if (this.searchValue.length() > 3) {
results.clear();
updateTableList();
} else {
results.clear();
}
dataModel = null; // to force the dataModel to be updated.
}
public List<ResultObject> getResultsPerValue(String searchValue) {
List<ResultObject> resultsList = new CopyOnWriteArrayList<ResultObject>();
//Logic for reading data from the properties file, populating ResultObject
//and adding it to the list
return resultsList;
}
/**
* This method updates a firm list, based on a search value
*/
public void updateTableList() {
try {
List<ResultObject> searchedResults = getResultsPerValue(searchValue);
//Once the results have been retrieved from the properties, empty
//current firm list and replace it with what was found.
synchronized(firms) {
firms.clear();
firms.addAll(searchedFirms);
}
} catch(Throwable xcpt) {
//Exception handling
}
}
/**
* This is a recursive method, that's used to constantly keep updating the
* table list.
*/
public synchronized ExtendedTableDataModel<ResultObject> getDataModel() {
try {
if (dataModel == null) {
dataModel = new ExtendedTableDataModel<ResultObject>(
new DataProvider<ResultObject>() {
public ResultObject getItemByKey(Object key) {
try {
for(ResultObject c : results) {
if (key.equals(getKey(c))){
return c;
}
}
} catch (Exception ex) {
//Exception handling
}
return null;
}
public List<ResultObject> getItemsByRange(
int firstRow, int endRow) {
return Collections.unmodifiableList(results.subList(firstRow, endRow));
}
public Object getKey(ResultObject item) {
return item.getResultName();
}
public int getRowCount() {
return results.size();
}
});
}
} catch (Exception ex) {
//Exception handling
}
return dataModel;
}
//Getters and setters
}
그리고, 해, ConcurrentModificationException가 발생 내가 말했듯이, 그것을 잘 작동하지만, 빠른 삭제하면 사용자 유형 빠르거나 (그것이 어떻게 정확히 잡기 어렵다). 여기가 정확히 어떻게 생겼는지입니다 : 나는 그것을 제거 할 수있는 방법 자바 코드의
WARNING: executePhase(RENDER_RESPONSE 6,[email protected]) threw exception
java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at org.richfaces.model.ExtendedTableDataModel.walk(ExtendedTableDataModel.java:108)
at org.ajax4jsf.component.UIDataAdaptorBase.walk(UIDataAdaptorBase.java:1156)
at org.richfaces.renderkit.AbstractExtendedRowsRenderer.encodeRows(AbstractExtendedRowsRenderer.java:159)
at org.richfaces.renderkit.AbstractExtendedRowsRenderer.encodeRows(AbstractExtendedRowsRenderer.java:142)
at org.richfaces.renderkit.AbstractExtendedRowsRenderer.encodeChildren(AbstractExtendedRowsRenderer.java:191)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:812)
at org.ajax4jsf.renderkit.RendererBase.renderChild(RendererBase.java:277)
at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxComponent(AjaxChildrenRenderer.java:166)
at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxChildren(AjaxChildrenRenderer.java:83)
at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxComponent(AjaxChildrenRenderer.java:157)
...
동기화, 내 강한면, 나는 가장 중요한 오류의 원인이 될 것 모르는 적이있다. 리치 스 페이스 4.0은 richDataTable 구성 요소에 많은 변화를 가져 왔다는 것을 알고 있습니다.이 구성 요소는 이전에 문제 였고 지금은 해결되었다고 들었습니다. 그러나 전체 응용 프로그램을 Richfaces 4.0으로 업그레이드 할 시간이 없습니다 (2 단계에서 진행될 예정입니다.) 이것은 전체 프로젝트의 일부에 지나지 않습니다. 위에 설명 된 문제를 해결할 방법이 없다면 해결 방법이있을 수 있습니다. 아니면 비슷한 종류의 검색을 구현할 수있는 다른 방법이 있습니다. 일반 JSF를 사용하는 것입니다 (구현이 빠르면 빠름). 그 문제에 관해 어떤 종류의 도움이나 조언을 부탁드립니다. 코드가 충분히 이해할 수 있기를 바랍니다. 그러나 그렇지 않다면 알려주세요. 더 설명하겠습니다. 미리 감사드립니다. 정말 감사드립니다.
감사합니다. 정확하게 필요한 것입니다. 전에 ajaxSingle을 사용했는데 생각하지 않았습니다. 그러나 EventsQueue는 나에게 새로운 것이 었습니다. 그렇게 단순한 것으로 나타났습니다. 다시 한 번 감사드립니다. –