JavaServer Faces portlet does not do command action

Olaf Kock, modified 1 Year ago. New Member Posts: 3 Join Date: 7/8/20 Recent Posts

I put together a simple java serverfaces application using the Maven archetype to build it. It is based upon a texbook example from Cay Horstmann's _Core Java Server Faces_ book. The issue that when you answer question 1 on the first page, it navigates to "/success.xhtml" based upon the rule in faces-config.xml. It does correctly, so I believe. The issue comes when I am on /success.xhtml and it asks me the next question. I hit the commandButton that calls the action quizBean.answerAction. When I look at the debug output, I don't see any evidence of this action being called! It's as if bridge lost track of itsself and bounces back to /view.xhtml. I am not sure why this happens. Any tips?
​​​​​​​

<?xml version="1.0"?>

<faces-config version="2.2"
	xmlns="http://xmlns.jcp.org/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
>
	<lifecycle>
		<phase-listener>com.liferay.faces.util.lifecycle.DebugPhaseListener</phase-listener>
		<phase-listener>com.liferay.faces.util.lifecycle.ViewScopePhaseListener</phase-listener>
	</lifecycle>
	
	<navigation-rule>
	 <from-view-id>/done.xhtml</from-view-id>
      <navigation-case>
         <from-outcome>startOver</from-outcome>
         <to-view-id>/view.xhtml</to-view-id>
      </navigation-case>
   </navigation-rule>
   
   <navigation-rule>
      <from-view-id>/again.xhtml</from-view-id>
      <navigation-case>
         <from-outcome>failure</from-outcome>
         <to-view-id>/failure.xhtml</to-view-id>
      </navigation-case>
       <navigation-case>
         <from-outcome>success</from-outcome>
         <to-view-id>/success.xhtml</to-view-id>
      </navigation-case>
   </navigation-rule>
   
   <navigation-rule>
      <from-view-id>/success.xhtml</from-view-id>
      <navigation-case>
         <from-outcome>failure</from-outcome>
         <to-view-id>/again.xhtml</to-view-id>
      </navigation-case>
       <navigation-case>
         <from-outcome>success</from-outcome>
         <to-view-id>/success.xhtml</to-view-id>
      </navigation-case>
   </navigation-rule>
   
   <navigation-rule>
   		<from-view-id>/view.xhtml</from-view-id>
      <navigation-case>
         <from-outcome>failure</from-outcome>
         <to-view-id>/again.xhtml</to-view-id>
      </navigation-case>
      <navigation-case>
         <from-outcome>success</from-outcome>
         <to-view-id>/success.xhtml</to-view-id>
      </navigation-case>
   </navigation-rule>
   


   <application>
      <resource-bundle>
         <base-name>com.corejsf.messages</base-name>
         <var>msgs</var>
      </resource-bundle>
   </application>
   
</faces-config>

/success.xhtml
 

<?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">
<f:view
	xmlns="http://www.w3.org/1999/xhtml"
	xmlns:f="http://xmlns.jcp.org/jsf/core"
	xmlns:h="http://xmlns.jcp.org/jsf/html"
>
   <h:head>
     <h:outputStylesheet library="css" name="main.css" />
   </h:head>
   <h:body>
  	 <h:panelGroup id="panelId" layout="block">
      <h:form>
         <p>
            #{msgs.correct}
            <h:outputFormat value="#{msgs.score}">
               <f:param value="#{quizBean.score}"/>
            </h:outputFormat>
         </p>
         <p>#{msgs.nextProblem}</p>
         <p>#{quizBean.question}</p>
         <p><h:inputText value="#{quizBean.response}"/></p>
         <p>
            <h:commandButton value="#{msgs.checkAnswer}" action="#{quizBean.answerAction}">
            	
            </h:commandButton>
         </p>
      </h:form>
      </h:panelGroup>
   </h:body>
</f:view>

Quiz bean
​​​​​​​

package com.corejsf;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;
import javax.portlet.PortletRequest;
import javax.portlet.annotations.PortletSessionScoped;

import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.User;
import com.liferay.portal.kernel.theme.ThemeDisplay;
import com.liferay.portal.kernel.util.WebKeys;



@Named // or @ManagedBean
@PortletSessionScoped
public class QuizBean implements Serializable {
	   private static final long serialVersionUID = -4712268339879239065L;
	   private int currentProblem;
	   private int tries;
	   private int score;
	   private String response = "";
	   private String correctAnswer;
	   
	   	private Greeting greeting = new Greeting();

	public Greeting getGreeting() {
		_log.debug("REturning greeting for bean");
		return greeting;
	}
	
	@PostConstruct
	public void postConstruct() {
		_log.info("post construct");
	}

	   // Here, we hardwire the problems. In a real application,
	   // they would come from a database
	   
	   private ArrayList<Problem> problems = new ArrayList<Problem>(Arrays.asList(
	      new Problem(
	         "What trademarked slogan describes Java development? Write once, ...",
	         "run anywhere"),
	      new Problem(
	         "What are the first 4 bytes of every class file (in hexadecimal)?",
	         "CAFEBABE"),
	      new Problem(
	         "What does this statement print? System.out.println(1+\"2\");",
	         "12"),
	      new Problem(
	         "Which Java keyword is used to define a subclass?",
	         "extends"),
	      new Problem(
	         "What was the original name of the Java programming language?",
	         "Oak"),
	      new Problem(
	         "Which java.util class describes a point in time?",
	         "Date")));

	   public String getQuestion() { 
		   _log.info("Question number is " + currentProblem);
		   _log.info("Calling get question " + problems.get(currentProblem).getQuestion());
		   return problems.get(currentProblem).getQuestion(); 
	   }

	   public String getAnswer() { 
		   _log.info("get correct answer is " + correctAnswer);
		   return correctAnswer; 
	   }

	   public int getScore() { 
		return score; 
		}

	   public String getResponse() { 
		return response; 
		}
	   public void setResponse(String newValue) { 
		response = newValue; 
		}

	   public String answerAction() {
		   _log.info("answer Action called");
	      tries++;
	      _log.info("answerAction. tries is " + tries);
	      if (problems.get(currentProblem).isCorrect(response)) {
	         score++;
	         nextProblem();
	         if (currentProblem == problems.size()) 
	        	 return "done";
	         else 
	        	 return "success";
	      }
	      else if (tries == 1) 
	    	  return "again";
	      else {
	         nextProblem();
	         if (currentProblem == problems.size()) 
	        	 return "done";
	         else 
	        	 return "failure";
	      }
	   }

	   public String startOverAction() {
	      Collections.shuffle(problems);
	      currentProblem = 0;
	      score = 0;
	      tries = 0;
	      response = "";
	      return "startOver";
	   }

	   private void nextProblem() {
		   _log.info("CAlling next problem");
	      correctAnswer = problems.get(currentProblem).getAnswer();
	      currentProblem++;
	      tries = 0;
	      response = "";
	   }
	   
	   
		@Inject
		private PortletRequest portletRequest;

		public String getName() {

			ThemeDisplay themeDisplay = (ThemeDisplay) portletRequest.getAttribute(WebKeys.THEME_DISPLAY);
			User user = themeDisplay.getUser();

			return user.getFirstName() + " " + user.getLastName();
		}
	   
		// Logger
		private static final Log _log = LogFactoryUtil.getLog(QuizBean.class);
	}

 

jsf