2012-01-31 3 views
3

長い質問に対してお詫び申し上げますが、本当に助けが必要です。私たちのプロジェクトの一環として、私は現在検索エンジンに取り組んでいます。ユーザーは最初の4文字以上を入力し、タイプすると結果リストが変わります。検索値はテキストボックスに入力され、結果は下のRichfacesコンポーネントrich:extendedDataTableに表示されます。検索値が削除されると、結果リストは空になります。私はそれを得ることができました、しかし、いくつかの試行後、私はコンポーネント自体によってスローされる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ががスローされ、私が言ったように、それが正常に動作しますが、高速で削除するとき、ユーザーのタイプ速いか(それはそれが起こるを正確にキャッチするのは難しいです)。ここでは、それは正確に次のようになります。私はそれを取り除くことができますどのようにJavaコードの

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) 
    ... 

同期は、私の最強の側は、私が最も重要なのは、エラーの原因とされるだろうかわからないではありませんでした。私はRichfaces 4.0が豊富な変更を加えたことを認識しています:extendedDataTableコンポーネントですが、以前はこれが問題だったと聞いていましたが、今解決しています。ただし、アプリケーション全体をRichfaces 4.0にアップグレードする時間はありません(フェーズ2で実行されます)。これはプロジェクト全体のほんの一部です。上記の問題を解決する方法がない場合は、回避策がありますか?あるいは、おそらく、プレーンなJSFを使用して同様の種類の検索を実装する他の方法があります(実装が十分に速い場合)。私はそのようなことについて何か助けやアドバイスをいただければ幸いです。コードが十分理解できることを願っていますが、そうでなければ私に教えてください、私はさらに説明します。事前にありがとう、本当にありがとうございます。

答えて

2

問題は、サーバーへの同時のajax呼び出しです。 a4j:サポートでは「eventsQueue」属性を使用します。通常、すべての "eventsQueue"をすべての "eventsQueue"が同じキューを参照するすべてのAJAXコンポーネントで使用する必要があります。

また、別のajax属性「ajaxSingle」を調べることもできます。

+0

ありがとう、それは私が必要としたものです。以前はajaxSingleを使っていましたが、それについては考えていませんでした。しかし、EventsQueueは私には新しいものでした。それは簡単であることが判明しました。もう一度ありがとう、これは本当に助けた。 –

関連する問題