Frage an jsf, jsf-2, java – So erstellen Sie ein JSF-Formular mit AJAX-Datenüberprüfung

3

Ich arbeite an einem JSF-Formularprototyp zum Einfügen von Daten in eine Datenbanktabelle mithilfe der AJAX-Datenvalidierung. Dies ist die JSF-Seite:

<code><?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:ajax render="sessionidvalidate" event="blur"/>                                          
                                    </h:inputText>
                                    <h:outputText id="sessionidvalidate" rendered="#{DatabaseController.validateSessionid}" value="session is already registered" />
                                </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>
</code>

Dies ist die Managed Bean:

<code>import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
// or import javax.faces.bean.SessionScoped;
import javax.inject.Named;
/* include SQL Packages */
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import javax.annotation.Resource;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
// or import javax.faces.bean.ManagedBean;   

import org.glassfish.osgicdi.OSGiService;

// Demo Insert Form
@Named("DatabaseController")
@SessionScoped
public class Database implements Serializable {

    private HashMap<String, String> formMap = new HashMap<>();

    public Database() {
    }
    /* Call the Oracle JDBC Connection driver */
    @Resource(name = "jdbc/Oracle")
    private DataSource ds;

    public HashMap<String, String> getformMap() {
        return formMap;
    }

    /*

    CREATE TABLE ACTIVESESSIONS(
    SESSIONID VARCHAR2(30 ) NOT NULL,
    USERID VARCHAR2(30 ) NOT NULL,
    LOGINTIME TIMESTAMP(6),
    LASTREFRESHTIME TIMESTAMP(6),
    USERIP VARCHAR2(30 )
    )
    /
     */
    @PostConstruct
    public void hashMapGenerate() {
        /* Initialize the hashmap */
        formMap.put("sessionid", null);
        formMap.put("userid", null);
        formMap.put("logintime", null);
        formMap.put("lastrefreshtime", null);
        formMap.put("userip", null);
    }

    public int saveData() throws SQLException, java.text.ParseException {
//        formMap = new HashMap<String, String>();

        String SqlStatement = null;

        if (ds == null) {
            throw new SQLException();
        }

        Connection conn = ds.getConnection();
        if (conn == null) {
            throw new SQLException();
        }

        PreparedStatement ps = null;

        /*

        CREATE TABLE ACTIVESESSIONS(
        SESSIONID VARCHAR2(30 ) NOT NULL,
        USERID VARCHAR2(30 ) NOT NULL,
        LOGINTIME TIMESTAMP(6),
        LASTREFRESHTIME TIMESTAMP(6),
        USERIP VARCHAR2(30 )
        )
        /
         */

        try {
            conn.setAutoCommit(false);
            boolean committed = false;
            try {           /* insert into Oracle the default system(Linux) time */
                SqlStatement = "INSERT INTO ACTIVESESSIONS"
                        + " (SESSIONID, USERID, LOGINTIME, LASTREFRESHTIME, USERIP)"
                        + " VALUES (?, ?, ?, ?, ?)";

                ps = conn.prepareStatement(SqlStatement);

                ps.setString(1, formMap.get("sessionid"));
                ps.setString(2, formMap.get("userid"));
                ps.setTimestamp(3, toTimeStamp(formMap.get("logintime")));
                ps.setTimestamp(4, toTimeStamp(formMap.get("lastrefreshtime")));
                ps.setString(5, formMap.get("userip"));

                ps.executeUpdate();

                conn.commit();
                committed = true;
            }
            finally 
            {
                if (!committed) {
                    conn.rollback();
                }
            }
        } finally {
            /* Release the resources */
            ps.close();
            conn.close();
        }

        return 0;

    }
    private Timestamp toTimeStamp(String s) throws java.text.ParseException
    {
        Timestamp ts = null;
        java.util.Date date = null;
        if (s == null || s.trim().isEmpty()) return ts;

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.S");
        date = (java.util.Date) sdf.parse(s);
        ts = new Timestamp(date.getTime());

        return ts;

    }

    /* Validators section */
    public boolean getvalidateSessionid(){

        //do SQL query

        return true;
    }

}
</code>

Ich habe Probleme bei der Implementierung der Formularüberprüfung. Ich möchte den von dem verwendeten eingegebenen String übergeben und in die Datenbank einchecken, dieser Wert steht bereits in der Datenbanktabelle. Hier rufe ich die Java-Methode auf, um den Wert zu überprüfen:

<code>                            <h:panelGroup>
                                <h:inputText id="sessionid" value="#{DatabaseController.formMap['sessionid']}" >
                                    <f:validateLength minimum="0" maximum="15"/>
                                    <f:ajax render="sessionidvalidate" event="blur"/>                                          
                                </h:inputText>
                                <h:outputText id="sessionidvalidate" rendered="#{DatabaseController.validateSessionid}" value="session is already registered" />
                            </h:panelGroup>
</code>

Wie kann ich den eingefügten Wert an die Java-Methode senden?

Schöne Grüße

Deine Antwort

2   die antwort
1

Fügen Sie einfach einen Listener in Ihr Tag einh:inputText:

<code><h:inputText id="sessionid" value="#{DatabaseController.formMap['sessionid']}" 
         valueChangeListener="#{DatabaseController.validateSessionid}">
</code>

So können Sie den eingegebenen Wert auf der Serverseite überprüfen. Wenn ein Benutzer das Eingabefeld verlässt, ruft JSF den Server ajax auf und führt die Namenseingabekomponente über den Ausführungsabschnitt des Lebenszyklus aus. Dies bedeutet, dass JSF den im Attribut angegebenen Listener für Wertänderungen der Namenseingabe aufruftvalueChangeListener während der Validierungsprozessphase des Lebenszyklus.

Und ich würde vorschlagen, diese Methode zu implementieren:

<code>public void validateSessionid(ValueChangeEvent e) {
    UIInput nameInput = e.getComponent()
    String sessionid = nameInput.getValue()

    //do SQL query
}
</code>

Nachdem der Ajax-Aufruf zurückgegeben wurde, rendert JSF dash:outputText id="sessionidvalidate".

DasvalueChangeListener dient einem ganz anderen Zweck. Es ist beabsichtigt, Wertänderungsereignisse abzuhören und keine Werte zu validieren. BalusC
Aber ein einfaches dynamisches Rendern einer Fehlermeldung ist billiger als das Generieren der Ausnahme in dieser Situation, nicht wahr? kapand
In diesem Fall ist der Vorgang jedoch praktisch der gleiche wie bei Verwendung eines benutzerdefinierten Validators. Was ist der grundsätzliche Unterschied? kapand
Mit dem richtigen Werkzeug für den Job. Wenn Sie etwas validieren möchten, verwenden Sie aValidator. Es ist gut geeignet für den Job, es hat eine gut definiertevalidate() Methode, bei der Sie eine werfen könnenValidatorException Dadurch wird JSF ordnungsgemäß gezwungen, die Übermittlung als ungültig zu behandeln und die Nachricht zu verarbeiten. In demvalueChangeListener Sie müssten alles manuell machen. BalusC
9

Sie müssen eine erstellenValidator.

Kickoff-Beispiel:

<code>@FacesValidator("sessionIdValidator")
public class SessionIdValidator implements Validator {

    @Override
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        // ...

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

}
</code>

Verwenden Sie es wie folgt:

<code><h:inputText id="sessionid" value="#{DatabaseController.formMap['sessionid']}">
    <f:validateLength minimum="0" maximum="15" />
    <f:validator validatorId="sessionIdValidator" />
    <f:ajax event="blur" render="sessionidMessage" />                                          
</h:inputText>
<h:message id="sessionidMessage" for="sessionid" />
</code>

Beachten Sie, dass Sie a verwenden sollten<h:message> um Validierungsnachrichten anzuzeigen. Sie haben keine in Ihrer Sicht. Wenden Sie dasselbe für alle Ihre anderen Felder an:

<code><h:inputText id="userid" value="#{DatabaseController.formMap['userid']}">
    <f:validateLength minimum="0" maximum="15" />
    <f:ajax event="blur" render="useridMessage" />                                          
</h:inputText>
<h:message id="useridMessage" for="userid" />
</code>

Wenn Sie verwenden möchten@Resource oder@EJB oder@Inject im Validator, dann ersetzen Sie die@FacesValidator Anmerkung von@ManagedBean oder (weil Sie aus irgendeinem Grund CDI verwenden)@Named:

<code>@Named
public class SessionIdValidator implements Validator {

    @Resource
    private DataSource dataSource;

    @Inject
    private YourDataService yourDataService;

    // ...
}
</code>

und verwenden Sie es stattdessen wie folgt

<code>    <f:validator binding="#{sessionIdValidator}" />
</code>
Noch eine Frage: Kann ich einen FacesValidator ("sessionIdValidator") in einer separaten Java-Datei haben, aber in der Lage sein, mehr als ein Feld zu validieren? Soweit ich jetzt sehe, brauche ich für jedes Feld einen separaten Validator. Peter Penzov
Laut<f:ajax>, nur wenn das Eingabefeld unscharf ist. BalusC
Danke für das Beispiel! Wenn ich Ihr Validierungsbeispiel implementiere, wird die Fehlermeldung auf der Webseite angezeigt? Wenn ich die Taste drücke oder wenn ich etwas eingebe? Peter Penzov
ImplementierenValidator und werfenValidatorException mit einerFacesMessage wie in meiner Antwort gezeigt. BalusC

Verwandte Fragen