java - туториал - Область действия в JSF Validator




primefaces example (2)

Я хочу реализовать проверку входных данных. Это код управляемого компонента:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"    
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets">
    <h:head>
        <ui:insert name="header">           
            <ui:include src="header.xhtml"/>         
        </ui:insert>
    </h:head>
    <h:body>

        <h1><img src="resources/css/images/icon.png" alt="NVIDIA.com" /> History Center</h1>
        <!-- layer for black background of the buttons -->
        <div id="toolbar" style="margin: 0 auto; width:1180px; height:30px; position:relative;  background-color:black">
            <!-- Include page Navigation -->
            <ui:insert name="Navigation">           
                <ui:include src="Navigation.xhtml"/>         
            </ui:insert>

        </div>  

        <div id="logodiv" style="position:relative; top:35px; left:0px;"> 
            <h:graphicImage alt="Demo Insert Form"  style="position:relative; top:-20px; left:9px;"  value="resources/images/logo_databasez.png" />
        </div>
        <div id="main" style="margin: 0 auto; width:1190px; height:700px; position:absolute;  background-color:transparent; top:105px">

            <div id="mainpage" style="margin: 0 auto; width:1190px; height:500px; position:absolute;  background-color:transparent; top:80px">

                <div id="settingsHashMap" style="width:350px; height:400px; position:absolute;  background-color:r; top:20px; left:1px">
                    <h:form>
                        <div id="settingsdiv" style="width:750px; height:400px; position:absolute;  background-color:r; top:20px; left:1px">

                            <h:panelGrid columns="2">
                                <h:panelGroup>Session ID</h:panelGroup>
                                <h:panelGroup>
                                    <h:inputText id="sessionid" value="#{DatabaseController.formMap['sessionid']}" >
                                        <f:validateLength minimum="0" maximum="15"/>
                                        <f:validator binding="#{ValidatorController.validateMessage}" >
                                            <f:attribute name="type" value="sessionid" />
                                        </f:validator>
                                        <f:ajax event="blur" render="sessionidvalidate" />                                          
                                    </h:inputText>
                                    <h:message id="sessionidMessage" for="sessionid" />
                                </h:panelGroup>

                                <h:panelGroup>User ID</h:panelGroup>
                                <h:panelGroup>
                                    <h:inputText id="userid" value="#{DatabaseController.formMap['userid']}" >
                                        <f:validateLength minimum="0" maximum="15"/>
                                    </h:inputText>
                                </h:panelGroup>

                                <h:panelGroup>Login Time</h:panelGroup>
                                <h:panelGroup>
                                    <h:inputText id="logintime" value="#{DatabaseController.formMap['logintime']}" >
                                        <f:validateLength minimum="0" maximum="35"/>
                                    </h:inputText>
                                </h:panelGroup>

                                <h:panelGroup>Last Refresh Time</h:panelGroup>
                                <h:panelGroup>
                                    <h:inputText id="lastrefreshtime" value="#{DatabaseController.formMap['lastrefreshtime']}" >
                                        <f:validateLength minimum="0" maximum="35"/>
                                    </h:inputText>
                                </h:panelGroup>

                                <h:panelGroup>User IP</h:panelGroup>
                                <h:panelGroup>
                                    <h:inputText id="userip" value="#{DatabaseController.formMap['userip']}" >
                                        <f:validateLength minimum="0" maximum="15"/>
                                    </h:inputText>
                                </h:panelGroup>

                            </h:panelGrid>          

                        </div>   

                        <div id="settingstwodiv" style="width:150px; height:60px; position:absolute;  background-color:transparent; top:380px; left:800px">

                            <h:commandButton value="Create User" action="#{DatabaseController.saveData}"/>

                        </div> 
                    </h:form> 

                </div>   

            </div>  
        </div>

    </h:body>
</html>

Это код, который я добавил в faces-config.xml

<validator>
    <validator-id>ValidatorController</validator-id>
    <validator-class>com.DX_57.HM_57.FormValidator</validator-class>
</validator>

Это код проверки, который я пытался проверить:

import javax.enterprise.context.SessionScoped;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
import javax.inject.Named;

@Named("ValidatorController")
@SessionScoped
public class FormValidator implements Validator {

    public FormValidator() {
    }

    @Override
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void validateMessage(FacesContext context, UIComponent component, Object value) throws ValidatorException {

        if (value.equals("test")) {
            throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    "Session ID is already in use, please choose another.", null));
        }
    }
}

Проблема заключается в этой ошибке, которую я получаю, когда пытаюсь запустить пример:

[#|2012-05-05T22:39:00.096+0300|INFO|glassfish3.1.2|org.glassfish.osgiweb|_ThreadID=58;_ThreadName=Thread-2;|Removed bundle 710 against context path /test |#]

[#|2012-05-05T22:39:00.097+0300|WARNING|glassfish3.1.2|org.glassfish.osgijavaeebase|_ThreadID=58;_ThreadName=Thread-2;|Failed to deploy bundle com.DX_57.History-Module-57 [710]
org.glassfish.osgijavaeebase.DeploymentException: Deployment of com.DX_57.History-Module-57 [710] failed because of following reason: Failed while deploying bundle com.DX_57.History-Module-57 [710] : java.lang.RuntimeException: Failed to deploy bundle [ com.DX_57.History-Module-57 [710] ], root cause: Exception while loading the app
    at org.glassfish.osgijavaeebase.AbstractOSGiDeployer.deploy(AbstractOSGiDeployer.java:125)
    at org.glassfish.osgijavaeebase.OSGiContainer.deploy(OSGiContainer.java:154)
    at org.glassfish.osgijavaeebase.JavaEEExtender.deploy(JavaEEExtender.java:107)
    at org.glassfish.osgijavaeebase.JavaEEExtender.access$200(JavaEEExtender.java:61)
    at org.glassfish.osgijavaeebase.JavaEEExtender$HybridBundleTrackerCustomizer$1.call(JavaEEExtender.java:151)
    at org.glassfish.osgijavaeebase.JavaEEExtender$HybridBundleTrackerCustomizer$1.call(JavaEEExtender.java:148)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
    at java.util.concurrent.FutureTask.run(FutureTask.java:166)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:722)
Caused by: java.lang.RuntimeException: Failed to deploy bundle [ com.DX_57.History-Module-57 [710] ], root cause: Exception while loading the app
    at org.glassfish.osgijavaeebase.OSGiDeploymentRequest.deploy(OSGiDeploymentRequest.java:196)
    at org.glassfish.osgijavaeebase.OSGiDeploymentRequest.execute(OSGiDeploymentRequest.java:118)
    at org.glassfish.osgijavaeebase.AbstractOSGiDeployer.deploy(AbstractOSGiDeployer.java:121)
    ... 10 more
Caused by: org.glassfish.deployment.common.DeploymentException: WELD-000072 Managed bean declaring a passivating scope must be passivation capable.  Bean:  Managed Bean [class com.DX_57.HM_57.FormValidator] with qualifiers [@Any @Default @Named]
    at org.glassfish.weld.WeldDeployer.event(WeldDeployer.java:181)
    at org.glassfish.kernel.event.EventsImpl.send(EventsImpl.java:128)
    at org.glassfish.internal.data.ApplicationInfo.load(ApplicationInfo.java:277)
    at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:460)
    at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:240)
    at org.glassfish.osgijavaeebase.OSGiDeploymentRequest.deploy(OSGiDeploymentRequest.java:183)
    ... 12 more
Caused by: org.jboss.weld.exceptions.DefinitionException: WELD-000072 Managed bean declaring a passivating scope must be passivation capable.  Bean:  Managed Bean [class com.DX_57.HM_57.FormValidator] with qualifiers [@Any @Default @Named]
    at org.jboss.weld.bean.ManagedBean.checkType(ManagedBean.java:405)
    at org.jboss.weld.bean.AbstractBean.initializeAfterBeanDiscovery(AbstractBean.java:149)
    at org.jboss.weld.bean.AbstractClassBean.initializeAfterBeanDiscovery(AbstractClassBean.java:308)
    at org.jboss.weld.bean.ManagedBean.initializeAfterBeanDiscovery(ManagedBean.java:361)
    at org.jboss.weld.bootstrap.BeanDeployment.doAfterBeanDiscovery(BeanDeployment.java:216)
    at org.jboss.weld.bootstrap.BeanDeployment.afterBeanDiscovery(BeanDeployment.java:208)
    at org.jboss.weld.bootstrap.WeldBootstrap.deployBeans(WeldBootstrap.java:352)
    at org.glassfish.weld.WeldDeployer.event(WeldDeployer.java:179)
    ... 17 more
|#]

Кажется, что класс Validator не в правильной области. Какую область я должен использовать?

С наилучшими пожеланиями


Из документации WELD:

Управляемые компоненты с областью @SessionScoped или @ConversationScoped должны быть сериализованы, поскольку контейнер периодически анализирует сеанс HTTP.

Могут быть и другие причины, но ваш бонусный сеанс с сеансом CDI должен по крайней мере реализовать интерфейс Serializable :

@Named("ValidatorController")
@SessionScoped
public class FormValidator implements Validator, Serializable {
...
}

Проверьте этот код:

<h:panelGroup>Session ID</h:panelGroup>
<h:panelGroup>
    <h:inputText id="sessionid" value="#{DatabaseController.formMap['sessionid']}" 
                    validator="#{ValidatorController.validatebean}">                                        
        <f:ajax event="blur" render="sessionidMessage" />                                          
    </h:inputText>
    <h:message id="sessionidMessage" for="sessionid" />
</h:panelGroup>

Это компонент:

@Named("ValidatorController")
@ViewScoped
public class FormValidator implements Validator {

    public FormValidator() {
    }

    @Override
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        if (value.equals("test")) {
            throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    "  Session ID is already in use, please choose another.", null));
        }
    }

    public void validatebean(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        if (value.equals("test")) {
            throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    "  Session ID is already in use, please choose another.", null));
        }
    }

}




jsf-2