لماذا PostConstruct Callback Fire في كل مرة على الرغم من أن Bean eviewscoped؟ JSF

StackOverflow https://stackoverflow.com/questions/2797231

سؤال

أنا أستخدم DataTable في الصفحة واستخدام سمة الربط لربطها بحبة الدعم الخاصة بي. هذا هو الكود الخاص بي:-

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.prime.com.tr/ui">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
            <h:form prependId="false">

                <h:dataTable var="item" value="#{testBean.stringCollection}" binding="#{testBean.dataTable}">
                    <h:column>
                        <h:outputText value="#{item}"/>
                    </h:column>
                    <h:column>
                        <h:commandButton value="Click" actionListener="#{testBean.action}"/>
                    </h:column>
                </h:dataTable>

            </h:form>

    </h:body>
</html>

هذا هو الفاصولي:-

package managedBeans;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.component.html.HtmlDataTable;

@ManagedBean(name="testBean")
@ViewScoped
public class testBean implements Serializable {

    private List<String> stringCollection;

    public List<String> getStringCollection() {
        return stringCollection;
    }

    public void setStringCollection(List<String> stringCollection) {
        this.stringCollection = stringCollection;
    }

    private HtmlDataTable dataTable;

    public HtmlDataTable getDataTable() {
        return dataTable;
    }

    public void setDataTable(HtmlDataTable dataTable) {
        this.dataTable = dataTable;
    }

    @PostConstruct
    public void init(){
        System.out.println("Post Construct fired!!");
        stringCollection = new ArrayList<String>();
        stringCollection.add("a");
        stringCollection.add("b");
        stringCollection.add("c");

    }

    public void action(){
        System.out.println("Clicked!!");

    }
}

من فضلك قل لي لماذا يتم إطلاق PostConstruct في كل مرة أقوم فيها بالنقر فوق الزر؟ يجب أن تطلق النار مرة واحدة فقط طالما أنا في نفس الصفحة ، فهي BeaSeaive @ViewScoped. علاوة على ذلك ، إذا قمت بإزالة سمة الربط ، فكل شيء يعمل بشكل جيد ويتحرك PostConstruct رد الاتصال مرة واحدة فقط. ثم لماذا في كل مرة أستخدم فيها سمة الربط؟ أحتاج إلى سمة ملزمة وأرغب في تنفيذ مهام التهيئة مثل جلب البيانات من WebService ، وما إلى ذلك مرة واحدة فقط. ماذا علي أن أفعل؟ أين يجب أن أكتب مهمة التهيئة الخاصة بي؟

هل كانت مفيدة؟

المحلول

من المثير للاهتمام ، عندما تستخدم الربط المكون على الفول المنتشر في العرض ، ينهار نطاق العرض.

لست متأكدًا مما إذا كان هذا خطأ في JSF2 ، فسيتعين علي قراءة مواصفات JSF2 بالكامل أولاً. بقدر ما هو أفضل رهان لك هو إسقاط الربط المكون في الوقت الحالي وتمرير العنصر المحدد عبر بناء جملة وسيطة طريقة EL 2.2 الجديدة:

<h:dataTable var="item" value="#{testBean.stringCollection}">
    <h:column>
        <h:outputText value="#{item}"/>
    </h:column>
    <h:column>
        <h:commandButton value="Click" action="#{testBean.action(item)}"/>
    </h:column>
</h:dataTable>

أنظر أيضا:


تحديث (ديسمبر 2012): هذا بالفعل خطأ في JSF2. إنها قضية دجاج بيغ. يتم تخزين الفاصوليا المنتشر في حالة عرض JSF. لذلك تتوفر حبوب العرض المنتشر فقط بعد استعادة مرحلة العرض. ومع ذلك ، فإن binding يتم تشغيل السمة أثناء مرحلة عرض الاستعادة ، في حين أن الفاصوليا المنتشر في العرض غير متوفرة بعد. يؤدي هذا إلى إنشاء مثيل جديد للفاصوليا ، والذي يتم استبداله لاحقًا بالفاصوليا التي تم تحديدها في طريقة عرض JSF المستعادة.

تم الإبلاغ عن هذا JSF العدد 1492 و JSF spec issue 787 والتي سيتم إصلاحها لـ JSF 2.2. حتى ذلك الحين ، أفضل رهان هو الاستخدام binding عند طلب الفاصوليا المنتشر على وجه الحصر ، أو للبحث عن طرق بديلة للمتطلبات الوظيفية المعينة.


تحديث (مارس 2015): تم ترميم إصلاح JSF 2.2 إلى Mojarra 2.1.18. لذلك إذا كنت لا تزال تستخدم JSF 2.0/2.1 ، فمن الأفضل أن ترقية إلى هذا الإصدار على الأقل. انظر أيضا AO ما هو الربط المكون في JSF؟ عندما يفضل استخدامه؟ و JSTL في الوجه JSF2 ... من المنطقي؟

نصائح أخرى

كما قال آخرون ، أود أن أقول إن أفضل ما يجب فعله هو إسقاط الربط المكون (لا تحتاجه هنا).

لكنني أضيف أنه يمكنك تحقيق نفس الشيء الذي تحاول القيام به بطريقة أكثر توجهاً نحو الكائن باستخدام معلمات الحركة ، مثل هذا:

<h:commandButton value="Click" action="#{testBean.action(item)}"/>

... وفي رمز Java الخاص بك:

  public void action(Item item){
    System.out.println("Clicked!!" + item);
}

إذا كان لديك فول من ViewScoped وإذا كنت ترغب في الاحتفاظ بالقيم التي تم إدخالها في النموذج أو لا تريد إطلاق Postconstruct ، فيجب عليك العودة من طريقة الإجراء الخاصة بك.

إذا قمت بإرجاع بعض النتائج (على سبيل المثال) ، ثم قم بتوجيه النتيجة غير الصالحة إلى نفس الصفحة باستخدام الوجوه- config.xml ، ثم يتم إعادة إنشاء الفول في ViewScoped وبالتالي تسبب إطلاق البناء postruct مرة أخرى.

حل آخر:

  • ربط htmldatatable في نطاق طلب.
  • حقن هذا الطرف نطاق الفول في نطاق العرض.

jboss seam استخدم هذا الحل لربط مكونات JSF بمكون نطاق المحادثة.

لقد ساعدتني إجابة Balusc كثيرًا ، أود أن أقول إنني حصلت على هذا الخطأ مع Mojarra الإصدار 2.1.7 ، وأنا أستخدم حاليًا 2.1.29-01 تم إصدار Tabview إلى الفول ViewScoped. مع هذا الإصدار ، ليس لدي هذا الخطأ والربط والبناء البري يعمل بشكل جيد. أستخدم JBOSS 5.2 وعلي استخدام Mojarra 2.1.x لذلك آمل أن تساعد هذه الإجابة الآخرين في نفس الموقف.

http://mvnrepository.com/artifact/com.sun.faces/jsf-api/2.1.29-01 http://mvnrepository.com/artifact/com.sun.faces/jsf-impl/2.1.29-01

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top