JSF newbie question - ServletException - Method not found

I just started learning JSF (and JSP) by following the tutorial:

JSF for nonbelievers: Clearing the FUD about JSF

http://www-128.ibm.com/developerworks/library/j-jsf1/

I'm getting a ServletException and I'm not sure why. Instead of starting the tutorial over, I'd like to learn what I'm doing wrong.

The exception is:

exception

javax.servlet.ServletException: Method not found: secondapp.controller.CalcBean@1ad81d2.add()

root cause

javax.el.MethodNotFoundException: Method not found: secondapp.controller.CalcBean@1ad81d2.add()

In the calculator.jsp page (a simple page with two form fields), I noticed that when I typeCalcBean., my IDE (NetBeans) only autocompletes the class variables and neither of the methods (add and multiply). I quickly searched and someone suggested restarting the server. This did not fix my problem. I must be doing something completely wrong or I missed something in the tutorial. If you don't mind, please read the simple files below and see if you can spot anything wrong. Please keep in mind this is my first time using JSF (and JSP for that matter). If you can suggest a better newbie tutorial, please do! Thanks

web.xml

-

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

<context-param>

<param-name>com.sun.faces.verifyObjects</param-name>

<param-value>false</param-value>

</context-param>

<context-param>

<param-name>com.sun.faces.validateXml</param-name>

<param-value>true</param-value>

</context-param>

<context-param>

<param-name>javax.faces.STATE_SAVING_METHOD</param-name>

<param-value>client</param-value>

</context-param>

<servlet>

<servlet-name>Faces Servlet</servlet-name>

<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>

<load-on-startup>1</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>Faces Servlet</servlet-name>

<url-pattern>/faces/*</url-pattern>

</servlet-mapping>

<session-config>

<session-timeout>

30

</session-timeout>

</session-config>

<welcome-file-list>

<welcome-file>

index.jsp

</welcome-file>

</welcome-file-list>

</web-app>

faces-config.xml

-

<?xml version="1.0" encoding="UTF-8"?>

<!-- =========== FULL CONFIGURATION FILE ================================== -->

<faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">

<managed-bean>

<description>

The"backing file" bean that backs up the calculator webapp

</description>

<managed-bean-name>CalcBean</managed-bean-name>

<managed-bean-class>secondapp.controller.CalcBean</managed-bean-class>

<managed-bean-scope>session</managed-bean-scope>

</managed-bean>

<navigation-rule>

<from-view-id>/calculator.jsp</from-view-id>

<navigation-case>

<from-outcome>success</from-outcome>

<to-view-id>/results.jsp</to-view-id>

</navigation-case>

</navigation-rule>

</faces-config>

secondapp.controller.CalcBean.java

-

package secondapp.controller;

import secondapp.model.Calculator;

/**

*

* @author Jonathan

*/

publicclass CalcBean{

privateint firstNumber;

privateint secondNumber;

privateint result;

private Calculator calculator;

/** Creates a new instance of CalcBean */

public CalcBean(){

setFirstNumber(0);

setSecondNumber(0);

result = 0;

setCalculator(new Calculator());

}

public String add(int a,int b){

result = calculator.add(a,b);

return"success";

}

public String multiply(int a,int b){

result = calculator.multiply(a,b);

return"success";

}

// <editor-fold desc=" Accessors/Mutators ">

publicint getFirstNumber(){

return firstNumber;

}

publicvoid setFirstNumber(int firstNumber){

this.firstNumber = firstNumber;

}

publicint getSecondNumber(){

return secondNumber;

}

publicvoid setSecondNumber(int secondNumber){

this.secondNumber = secondNumber;

}

publicint getResult(){

return result;

}

publicvoid setCalculator(Calculator calculator){

this.calculator = calculator;

}

// </editor-fold>

}

secondapp.model.Calculator

-

package secondapp.model;

/**

*

* @author Jonathan

*/

publicclass Calculator{

/** Creates a new instance of Calculator */

public Calculator(){

}

publicint add(int a,int b){

return a+b;

}

publicint multiply(int a,int b){

return a*b;

}

}

calculator.jsp

-

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>

<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>

<html>

<head><title>Calculator Test</title></head>

<body bgcolor="white">

<h2>My Calculator</h2>

<f:view>

<h:form id="calcForm">

<h:panelGrid columns="3">

<h:outputLabel value="First Number" for="firstNumber" />

<h:inputText id="firstNumber" value="#{CalcBean.firstNumber}" required="true" />

<h:message for="firstNumber" />

<h:outputLabel value="Second Number" for="secondNumber" />

<h:inputText id="secondNumber" value="#{CalcBean.secondNumber}" required="true" />

<h:message for="secondNumber" />

</h:panelGrid>

<h:panelGroup>

<h:commandButton id="submitAdd" action="#{CalcBean.add}" value="Add" />

<h:commandButton id="submitMultiply" action="#{CalcBean.multiply}" value="Multiply" />

</h:panelGroup>

</h:form>

</f:view>

</body>

</html>

[10638 byte] By [Techniquea] at [2007-11-26 20:10:25]
# 1

In the future, please add some line breaks so I don't have to scroll horizontally to read your post.

The problem is that the CalcBean.add/.multiply method is requiring two parameters. This method should be parameter-less. When talking about action methods, they should return String and not take any parameters.

So, remove the parameters. You collect a firstNumber and a secondNumber from the user. These are the numbers you want to add (or multiply). Use those values (instead of the parameters) to calculate the result.

The code changes aren't too complicated. I'd write them out for you, but you seem interested in learning (which is great by the way!). Let me know if you need more help on this.

CowKing

ps - I see more problems with the code, and I haven't given you all the answers. I know, I'm mean. You'll learn better if you try to fix things on your own first. I've just given you enough info to overcome the immediate issue. =)

IamCowKinga at 2007-7-9 23:13:53 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 2

whoops.. I guess I added those paramters out of habit. Thanks!

I believe the only other thing that differs between my code and the tutorial is that I initialize CalcBean's class variables in the constructor whereas the tutorial initalized them where they are declared.

Unfortunately I'm away for the weekend and can't test this out :) Thanks for the help.

Techniquea at 2007-7-9 23:13:53 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 3
Talking about passing parameters, this article might be interesting: http://balusc.xs4all.nl/srv/dev-jep-com.html
BalusCa at 2007-7-9 23:13:53 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 4

IamCowKing,

Thanks I removed the parameters from the method and now it's working fine.

>>ps - I see more problems with the code

Well.. I finished the tutorial and since everything appears to be working I'll probably try other tutorials. Care to mention what else you found that was incorrect?

BalusC, thanks I'll check out the link.

On a side note, there's this annoying bug in NetBeans autocomplete for JSP pages. The foreground color (dark blue) doesn't get changed when an item is selected, but the background changes to dark blue -- so basically it's impossible to see what the selected variable/method is.

http://i18.tinypic.com/2uzpeu9.gif

I'm using NetBeans 5.5 with Windows XP SP2 - classic look and feel. How has this not been noticed by anyone else ? :) Time to search for/submit a bug report..

Techniquea at 2007-7-9 23:13:53 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 5

Great! I'm glad it's working for you. I guess I was wrong about those "other" errors in the code. =)

What I saw, was that your accessors for first and second number were using primitive int. I thought that this would cause a problem, because typically JSF passes String objects around. I thought that when the user entered a number in the inputText, it would attempt to put a String object into the setter that only took an int. Usually you would need a converter on your inputText to tell JSF what object type you actually want that field to be.

But if it's working... I was wrong!

I know very very little about netbeans. I hope you find the solution to your issue with it.

CowKing

IamCowKinga at 2007-7-9 23:13:53 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...