TheCoder4eu / BootsFaces-OSP

BootsFaces - Open Source Project
Apache License 2.0
246 stars 102 forks source link

@previous The subexpression @previous doesn't exist, or it can't be resolved #944

Closed MohaTikiTaka closed 6 years ago

MohaTikiTaka commented 6 years ago

Hi BootsFaces team !

I recently discovered the existence of BootsFaces. I used PrimeFaces alone before. I combine both now. Thanks again.

I have a small error when I try to pass values (I think it comes from there) since I use BootsFaces.

Here is the error I have:

"Invalid search expression: @previous The subexpression @previous doesn't exist, or it can't be resolved. net.bootsfaces.component.message.Message j_idt7:j_idt18:j_idt25 Additional information: Invalid search expression - there's no predecessor to the @previous"

Here is my code:

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:f="http://xmlns.jcp.org/jsf/core"
      xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
      xmlns:p="http://primefaces.org/ui"
      xmlns:b="http://bootsfaces.net/ui"
      template="WEB-INF/pageTemplate.xhtml">

    <ui:define name="title">
        <h:outputText value="Se connecter"/>
    </ui:define>

    <ui:define name="content">
        <h:form>
        <b:container fluid="true">
          <b:row>
            <b:column medium-screen="2">
              <h:outputText value="Username:"/>
            </b:column>
            <b:column medium-screen="4">
              <b:inputText id="email" required="true" value="#{loginManager.email}" />
            </b:column>
            <b:column medium-screen="6">
              <b:message/>
            </b:column>
          </b:row>
          <b:row>
            <b:column medium-screen="2">
              <h:outputText value="Password:" />
            </b:column>
            <b:column medium-screen="4">
              <b:inputSecret id="password" required="true" value="#{loginManager.password}" />
            </b:column>
            <b:column medium-screen="6">
              <b:message />
            </b:column>
          </b:row>
          <b:row>
            <b:column span="1" offset="2">
              <b:commandButton value="Connexion" update="login" action="#{loginManager.login()}" look="primary" style="width:100%" />
            </b:column>
          </b:row>
        </b:container>
        </h:form>
    </ui:define>
</ui:composition>

Thank you for your future help!

Regards.

chongma commented 6 years ago

try putting h:form inside the b:container

chongma commented 6 years ago

read the "basic usage" part at https://showcase.bootsfaces.net/layout/basic.jsf. also it might help if you can show contents of pageTemplate.xhtml and LoginManager bean

MohaTikiTaka commented 6 years ago

@chongma Hi Works fine now ! Thank you 💯

Here is my pageTemplate.xhtml :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
      xmlns:p="http://primefaces.org/ui"
      xmlns:b="http://bootsfaces.net/ui">
    <h:head>
        <title><ui:insert name="title" /></title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    </h:head>

    <h:body>
        <h:form>
            <b:navBar brand="SupFile" brandHref="#" fluid="true">
             <b:navbarLinks>
               <b:navLink outcome="/index" value="Accueil"></b:navLink>
             </b:navbarLinks>
             <!-- Following line is needed for TBS 3.0.1 (panel content overflow issue) -->
           <b:navbarLinks pull="right"><b:navLink value="    " href="#"></b:navLink></b:navbarLinks>
             <b:navbarLinks pull="right" styleClass="hidden-xs">            
               <c:if test="#{loginManager.isUserLoggedIn()}">
                   <b:dropMenu value="Dropdown">               
                   <b:navLink value="Mon stockage" outcome="/user_space/home_page.xhtml"></b:navLink>
                   <b:navLink value="Mon compte" outcome="/user_space/myAccount.xhtml"></b:navLink>
                   <b:navLink action="#{loginManager.logout()}" value="Se déconnecter"/>
                   </b:dropMenu>
               </c:if>

               <c:if test="#{!loginManager.isUserLoggedIn()}">
                   <b:navLink value="S'enregistrer" outcome="/register"></b:navLink>
                   <b:navLink value="Se connecter" outcome="/login"></b:navLink>
               </c:if>
             </b:navbarLinks>
           </b:navBar>
        <main>
            <ui:insert name="content" />
        </main>

        <footer>
            Pied de page
        </footer>
        </h:form>
    </h:body>
</html>

And here my LoginManager :

package Beans;

import CRUD.UtilisateurFacadeLocal;
import Entities.Utilisateur;
import Util.SessionManager;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean
@SessionScoped
public class LoginManager {

    @EJB
    UtilisateurFacadeLocal utilisateur;

    private Utilisateur loggedInUser;

    private String email;
    private String password;

/******************************************************************************/

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public boolean isUserLoggedIn() {
        return SessionManager.isUserLoggedIn();
    }

    public Utilisateur getLoggedInUser() {
        //System.out.println(loggedInUser.getUsername());
        //System.out.println(loggedInUser.getFolder());
        return loggedInUser;
    }

/******************************************************************************/

    public String login(){

        try{
            loggedInUser = utilisateur.findByEmailAndPW(email, password);            
            if(!loggedInUser.equals(null)){//remplacer par try catch
                System.out.println(">>>>>>>>>>>>> userExist");
                SessionManager.getSession().setAttribute(SessionManager.ATTRIBUTE_USER, loggedInUser);
                return "/user_space/home_page?faces-redirect=true"; //home page
            }
        }catch(NullPointerException e){
            System.out.println("couple username password inconnu");
        }

        return "/login?faces-redirect=true"; //register_login
    }

    public String logout(){
        SessionManager.getSession().invalidate();
        return "/index?faces-redirect=true";
    }

    public String updateUser(){

        System.out.println("[" + password.length() + "]");

        if(password.length() >= 4){
            loggedInUser.setPassword(password);
        }

        utilisateur.edit(loggedInUser);

        return "/user_space/myAccount?faces-redirect=true";
    }

}

Thank you for your help. Regards.

chongma commented 6 years ago

i am glad it is working now. thank you for the extra info. out of interest which container are you using? tomcat, wildfly etc? you should consider changing to CDI instead of EJB if it is available

MohaTikiTaka commented 6 years ago

Im using GlassFish. Why CDI instead of EJB ?

ggam commented 6 years ago

Im using GlassFish. Why CDI instead of EJB ?

I think he refers to the use of @Inject instead of @EJB. Both annotations do the same, with the difference that @Inject works on every bean while @EJB only works for EJBs. EJBs are being left behind now with most of their functionality being moved to CDI to provide a more unified component model. At some point in time I expect EJBs to be deprecated.

But aside of that, what you should try to avoid is @ManagedBean. That's from and old JSF specific component model (created way before CDI) and it's already deprecated on JSF 2.3. In your case, @ManagedBean should be replaced with @Named, and javax.faces.bean.SessionScoped with javax.enterprise.context.SessionScoped. They work the basically the same but again, with CDI you may inject any bean, while the JSF managed bean facility is limited to specific JSF artifacts.

stephanrauh commented 6 years ago

Also see #256.

stephanrauh commented 6 years ago

@MohaTikiTaka I've got no idea how and why the hints of @chongma helped you to solve the bug...

I've improved the confusing error message and implemented the behavior you (and I) are intuitively expecting. <b:message> now finds it's input field even if both hide in a <b:column>.

I've uploaded a developer snapshot of BootsFaces to Maven Central. See #369 how to get it. Please test it and report back.

Thanks in advance, Stephan