4

次のように、Primefaces データ テーブルとその中にコマンド ボタンを含む JSF ビューがあります。

<p:messages id="statusMessages" showDetail="true" />
    <h:form id="listForm">
        <p:panel header="Wellsite List">
            <br />
            <h:outputLabel value="Welcome, #{wellsiteController.loggedUser.login}" />
            <br />
            <br />
            
            <p:dataTable id="dataTable" var="wellsite" value="#{wellsiteController.wellsiteDataTableModel}"
                         paginator="true" rows="10" selection="#{wellsiteController.wellsite}">

                <p:column selectionMode="single" style="width:18px" id="radioSelect" />

                <p:column sortBy="#{wellsite.reference}" headerText="Wellsite ID">
                    <h:outputText value="#{wellsite.reference}" />
                </p:column>

                <p:column headerText="Allowed Groups">
                    <h:outputText value="#{wellsite.allowedGroups.toString()}" />
                </p:column>

                <f:facet name="footer">
                    <h:panelGrid columns="3">
                        <p:commandButton id="addWellsite" value="Add New Wellsite" icon="ui-icon-flag" ajax="false" action="#{wellsiteController.showAddWellsite}"/>
                        <p:commandButton id="editWellsite" value="Edit Selected Wellsite" icon="ui-icon-wrench" ajax="false" action="#{wellsiteController.showEditWellsite}"/>

                        <p:commandButton id="deleteWellsiteButton" value="Remove Selected Wellsite" icon="ui-icon-trash" onclick="confirmation.show()" type="button"/>
                         
                    </h:panelGrid>
                </f:facet>
            </p:dataTable>
            <p:spacer height="20" />
        </p:panel>
        <p:confirmDialog id="confirmDialog" message="Are you sure you want to remove the selected Wellsite along with all it's data?" header="Confirmation" severity="alert" widgetVar="confirmation">  
            <p:commandButton id="confirm" value="Yes" ajax="false" oncomplete="confirmation.hide()" action="#{wellsiteController.deleteWellsite}" />
            <p:commandButton id="decline" value="Cancel" onclick="confirmation.hide()" type="button" />   

        </p:confirmDialog>
    </h:form>

そして、ここにコントローラーがあります:

@ManagedBean(name = "wellsiteController")
@RequestScoped
public class WellsiteController implements Serializable {
private static final long serialVersionUID = 1L;

@ManagedProperty("#{wellsiteDao}")
private WellsiteDao wellsiteDao;

@ManagedProperty("#{userDao}")
private UserDao userDao;

@ManagedProperty("#{groupDao}")
private GroupDao groupDao;

@ManagedProperty("#{userController.loggedUser}")
private UserEnt loggedUser;

private WellsiteEnt wellsite;
private List<WellsiteEnt> wellsiteList;
DualListModel<GroupEnt> pickGroupsModel;

public WellsiteController(){
}

@PostConstruct
public void build(){
    wellsite = new WellsiteEnt();
    wellsite.setAllowedGroups(new ArrayList<GroupEnt>());
}

/*some getters & setters*/

public WellsiteDataTableModel getWellsiteDataTableModel(){
    return new WellsiteDataTableModel(getWellsiteList());
}

public void setPickGroupsModel(DualListModel<GroupEnt> model){
    pickGroupsModel = model;
}

public DualListModel<GroupEnt> getPickGroupsModel() {
    if(pickGroupsModel == null){
        List<GroupEnt> allGroups = groupDao.getAll();
        List<GroupEnt> currentGroups = wellsite.getAllowedGroups();
        for(GroupEnt g : currentGroups){
            allGroups.remove(g);
        }
        pickGroupsModel = new DualListModel<GroupEnt>(allGroups, currentGroups);
    }
    return pickGroupsModel;
}

public String listWellsites(){
    getWellsiteList();
    return "listWellsites";
}

public String showAddWellsite(){
    FacesContext context = FacesContext.getCurrentInstance();
    setWellsite(new WellsiteEnt());
    wellsite.setAllowedGroups(new ArrayList<GroupEnt>());
    pickGroupsModel = null;
    context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,
                                            "Fields annotated with a ' * ' are mandatory",""));
    return "addWellsite";
}

public String addWellsite(){
    FacesContext context = FacesContext.getCurrentInstance();
    
    wellsite.setDate(new Date());
    wellsite.setLastUpdate(wellsite.getDate());
    try {
        wellsiteDao.addWell(wellsite);
        
        for(GroupEnt g : pickGroupsModel.getTarget()){
            GroupEnt group = groupDao.getOne(g.getGroupId());
            group.getGroupWellsites().add(wellsite);
            groupDao.update(group);
        }
        return listWellsites();
        
    } catch (Exception ex) {
        Logger.getLogger(WellsiteController.class.getName()).log(Level.SEVERE, null, ex);
        context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
                                            ex.getMessage(),""));
        return null;
    }
}
}

このビューは正しくレンダリングされます。データテーブルとボタンは問題ないようです。問題は、最初に「addWellsite」コマンド ボタンをクリックしても何も起こらないことです。ページが更新されたようです。もう一度クリックすると、例外が発生します。

java.lang.NumberFormatException: For input string: "null"

デバッガーを使用して、「addWellsite」のアクションが初めて呼び出されないことがわかったため、結果が生成されません (したがって、ページの更新)。

例外は、現在のビューまたはターゲット ビューで初期化が行われていないことが原因である可能性があります (両方のビューが、ページの更新で呼び出されなかったアクション メソッドから表示されるため)。

問題は、アクションメソッドが最初に呼び出されないのはなぜですか?

この回答からのように:

UICommandコンポーネントが関連付けられたアクションの呼び出しに失敗するたびに、次のことを確認してください。

  1. UICommandコンポーネントは、コンポーネント内に配置する必要がありUIFormます (例: h:form)。

私は ah:form を持っています

  1. 複数のコンポーネントを互いに入れ子にすることはできません(インクルード ファイルに注意してください!)。UIForm

ひとつだけ。

  1. 検証/変換エラーは発生していないはずです (h:messagesそれらをすべて取得するために使用します)。

エラーを表示しない ah:messages があります。

  1. UICommandコンポーネントがコンポーネント内に配置されている場合はUIData、まったく同じ( 's属性のDataModel背後にあるオブジェクト) が保持されていることを確認してください。UIDatavalue

commandButton は dataTable 内にありますが、ターゲット ビューには dataModel は必要ありません。コントローラーのコードが示すように、ビューがオブジェクトを取得しようとすると、オブジェクトが構築されます。次のリクエストはこのdataTableを使用していないため、もう処理しません。

  1. コンポーネントとすべての親コンポーネントの属性と属性は、リクエスト値の適用フェーズ中に評価されるべきではありませrenderedん。disabledfalse

renderedまたはdisbled属性はありません。

  1. 要求と応答のチェーン内で JSF ライフサイクルが変更されていないこと、PhaseListenerまたはいずれかが呼び出しアクション フェーズをスキップしていることを確認してください。EventListener

phaseListener は定義されていません。

  1. なんらかの理由でリクエストをブロックしていないFilterServlet、同じリクエスト - レスポンス チェーン内にあることを確認してくださいFacesServlet

他のサーブレットは定義されていません。私はフィルターが何であるかさえ知りません。

アクションメソッドが初めて呼び出されないのはなぜですか?

4

1 に答える 1

5

これは、この親が事前に別の<h:form>リクエストによって開始された ajax リクエストによってレンダリングされた場合に発生する可能性があります。レンダリング/更新されたものは、そのビュー ステートを失います。これは、 JSF issue 790で説明されているように、JavaScript API のバグが原因で発生します。このバグは、まもなくリリースされる JSF 2.2 ですでに修正されています。 <h:form><h:form>

<h:form>一方、JSF 2.0/2.1 では、アクションのrender(または PrimeFaces の場合はupdate) 属性のクライアント ID を別の形式で明示的に指定する必要があります。

例えば

<h:commandButton ...>
   <f:ajax ... render=":listForm" />
</h:commandButton>

また

<p:commandButton ... update=":listForm" />

または、代わりに通常の (非 ajax) リクエストにします。

以下も参照してください。

于 2012-05-14T16:29:43.887 に答える