Вопрос по action, methods, jsf – Метод действия JSF не вызывается

4

У меня есть JSF-представление с таблицей данных Primefaces и командная кнопка, как показано ниже:

<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;
    }
}
}

Это представление отображается правильно. Datatable и кнопки выглядит хорошо. Проблема заключается в том, что когда я впервые нажимаю кнопку «addWellsite», commandButton, ничего не происходит. Страница просто обновляется. Если я щелкну по нему еще раз, произойдет исключение:

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

Используя отладчик, я обнаружил, что действие «addWellsite» НЕ вызывается в первый раз, и поэтому не генерируется результат (таким образом, обновление страницы).

Вероятно, исключение происходит из-за отсутствия инициализации в текущем или целевом представлениях (поскольку оба представления отображаются из методов действия, которые не были вызваны при обновлении страницы)

Вопрос в том:WHY the action method is not called the first time?

Как изэтот ответ:

Whenever an UICommand component fails to invoke the associated action, verify the following:

UICommand components must be placed inside an UIForm component (e.g. h:form).

У меня есть ч: форма

You cannot nest multiple UIForm components in each other (watch out with include files!).

Там только один.

No validation/conversion error should have been occurred (use h:messages to get them all).

У меня есть h: сообщения, которые не отображают никаких ошибок.

If UICommand components are placed inside an UIData component, ensure that exactly the same DataModel (the object behind the UIData's value attribute) is preserved.

CommandButton находится внутри dataTable, но целевое представление не нуждается в dataModel. Как показывает мой код контроллера, объект создается, когда представление пытается его получить. Следующий запрос не использует этот dataTable, чтобы я больше не обрабатывал его.

The rendered and disabled attributes of the component and all of the parent components should not evaluate to false during apply request values phase.

Там нетrendered или жеdisbled атрибутов.

Be sure that no PhaseListener or any EventListener in the request-response chain has changed the JSF lifecycle to skip the invoke action phase.

PhaseListener не определен.

Be sure that no Filter or Servlet in the same request-response chain has blocked the request fo the FacesServlet somehow.

Другие сервлеты не определены. Я даже не знаю, что такое фильтр.

WHY the action method is not called the first time?

Я рендерил его не-Ajax-методом действия. Pedro Peixoto
Это было. Черт! Вы компилятор или что-то? Pedro Peixoto
Запрос ajax должен явно включать идентификатор формы:listForm вrender атрибут (илиupdate в случае PrimeFaces). BalusC
Как ты открываешь / рендеришь эту форму с таблицей? Просто открыв страницу? Или это делается с помощью ajax-запроса из другой формы? BalusC
Уверены ли вы? Если бы это был запрос ajax, я мог бы объяснить проблему. BalusC

Ваш Ответ

1   ответ
5

<h:form> был предоставлен AJAX-запросом, инициированнымanother <h:form> заранее. Оказанный / обновленный<h:form> затем потерял бы свое состояние зрения. Это вызвано ошибкой в JavaScript API, как описано вВыпуск JSF 790 который уже исправлен в ближайшем будущем JSF 2.2.

В то же время в JSF 2.0 / 2.1 вам необходимо явно указать идентификатор клиента<h:form> вrender (или для PrimeFaces,update) атрибут действия в другой форме.

Например.

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

или же

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

Или просто сделайте нормальный (не AJAX) запрос.

See also: Communication in JSF 2 - Ajax rendering of content which contains another form
Можно также :) Добро пожаловать.
Благодарю. Исправлена ошибка, из-за которой ajax устанавливался в false Не должно быть ajax вообще. Pedro Peixoto

Похожие вопросы