Бин ViewScoped вызывает NotSerializableException - PullRequest
9 голосов
/ 04 октября 2010

Здравствуйте, я использую компонент ViewScoped. Проблема в том, что при вызове я получаю NotSerializableException.

Это код моего управляемого компонента:

@ManagedBean(name="demandesBean")
@ViewScoped
public class DemandesBean implements Serializable {
    private static final long serialVersionUID = 1L;

    @ManagedProperty(value="#{demandeService}")
    private DemandeService demandeService; //A Spring Service

    @ManagedProperty(value="#{loginBean}")
    private LoginBean loginBean;

    private DemandeVO newDemande;

    @PostConstruct
    public void initData() {
        newDemande = new DemandeVO();
    }

    public void doAjouterDemande(ActionListener event) {
        demandeService.createDemande(newDemande, loginBean.getUsername());
        newDemande = new DemandeVO();
    }

    public List<DemandeVO> getListDemande() {
        return demandeService.getAllDemandesByUser(loginBean.getUsername());
    }

    public DemandeService getDemandeService() {
        return demandeService;
    }

    public void setDemandeService(DemandeService demandeService) {
        this.demandeService = demandeService;
    }

    public LoginBean getLoginBean() {
        return loginBean;
    }

    public void setLoginBean(LoginBean loginBean) {
        this.loginBean = loginBean;
    }

    public DemandeVO getNewDemande() {
        return newDemande;
    }

    public void setNewDemande(DemandeVO newDemande) {
        this.newDemande = newDemande;
    }
}

Я получаю следующее исключение:

GRAVE: Exiting serializeView - Could not serialize state: com.bull.congesJBPM.serviceImpl.DemandeServiceImpl
java.io.NotSerializableException: com.bull.congesJBPM.serviceImpl.DemandeServiceImpl

Любое решение этой проблемы? Пожалуйста помоги !

Ответы [ 3 ]

7 голосов
/ 28 апреля 2012

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

Плюсы этого подхода в том, что история - это действительно история. Когда вы возвращаетесь к предыдущей версии представления (используя кнопку «Назад»), вы фактически получаете точную версию компонента поддержки в то время.

Суть в том, что кажется, что это препятствует внедрению сервисов (и не связано с этой проблемой, является основным ударом по производительности). Точно такие же проблемы возникают при внедрении службы EJB.

Существует параметр контекста, который вы можете поместить в web.xml, чтобы отключить это поведение:

<context-param>
    <param-name>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</param-name>
    <param-value>false</param-value>
</context-param>

См. http://wiki.apache.org/myfaces/Performance

Кстати, Mojarra имеет аналогичную настройку, но там по умолчанию установлено значение false.

0 голосов
/ 30 января 2013

Все в компоненте ViewScoped хранится в ViewState. Вы можете отключить сериализацию ViewState в сеансе, но сами сеансы можно сериализовать, и тогда проблема возникнет в другом месте.

Решением для Spring является использование Сериализуемый прокси .

<aop:scoped-proxy proxy-target-class="true"/>

Spring bean-компоненты обернуты в прокси, который сериализуем, и свернутая ссылка является временной, поэтому после десериализации она перечитывается из контекста Spring.

Технически это похоже на ответ elias , только вам не нужно самостоятельно писать этот код для каждого компонента. Вы используете AOP .

Вы можете увидеть мой вопрос: Проблема с JSF-компонентами и сериализуемостью для получения дополнительной информации.

0 голосов
/ 17 июля 2012

Я разместил решение этой проблемы на моем собственном вопросе об этой же проблеме , который выглядит следующим образом: вместо внедрения bean-компонентов Spring через EL в аннотации @ManagedProperty (выполняется при инициализации ManagedBean), вы получаете bean-компоненты, оценивающие EL во время выполнения.

При таком подходе ваш JSF-компонент должен выглядеть следующим образом:

@ManagedBean(name="demandesBean")
@ViewScoped
public class DemandesBean implements Serializable {
    private static final long serialVersionUID = 1L;

    private static DemandeService demandeService() {
        return SpringJSFUtil.getBean("demandeService");
    }

    // ... 
    public void doAjouterDemande(ActionListener event) {
        demandeService().createDemande(newDemande, loginBean.getUsername());
        newDemande = new DemandeVO();
    }
    // ...

И здесь используется используемый класс утилит SpringJSFUtil.java :

import javax.faces.context.FacesContext;

public class SpringJSFUtil {

    public static <T> T getBean(String beanName) {
        if (beanName == null) {
            return null;
        }
        return getValue("#{" + beanName + "}");
    }

    @SuppressWarnings("unchecked")
    private static <T> T getValue(String expression) {
        FacesContext context = FacesContext.getCurrentInstance();
        return (T) context.getApplication().evaluateExpressionGet(context,
                expression, Object.class);
    }
}

Это устраняет свойство bean-компонента Spring (за счет выполнения нескольких дополнительных оценок EL), таким образом избегая проблем сериализации, связанных с наличием свойства на первом месте.

...