Basic Web Application Setup

These are my personal notes to myself on how I setup my particular web applications. It is not meant as a tutorial or as documentation on how to use Velocity or Log4J or Tomcat. It does not attempt to cover all aspects of setting up a web application, or even try to explain everything I did. It was meant as a reminder to myself and a help to my collegues in case they need to take over or write their own applications. If others find it helpful, that is also good. Note that I do not write very complicated applications, nor applications that would get thousands of hits a day. I also don't use a framework or VelocityViewServlet. These web applications are very simple.

For those who are not affiliated with UTD, the UTD-specific classes referred to in this document would not be readily available. I believe we can freely share with other educational institutions, but that comes under legal-stuff-I-know-nothing-about-and-that's-good.

Author: Barbara Baughman, Systems Analyst, University of Texas at Dallas, [email protected]

What releases were used?

References

What permissions should be used for the files?

Tomcat Setup

The server.xml file - Configuring tomcat

The tomcat log files

Set up the tomcat lib subdirectory

Create application subdirectories

The web.xml file - Configuring the application

Velocity Setup

The velocity.properties file - Configuring Velocity

Servlets that use Velocity templates

Templates

General Comments

Templates for every application

Setting Up Log4j Logging

The Log4jServlet

Configuring Log4j loggers in the properties file.

Other Tips

Provide resources through servlets and the web.xml file

Setup application workflow through several servlets

Setup application workflow through function classes.

Troubleshooting

Can't find the URL

Internal Server Error

A blank screen is returned instead of the results of a Velocity template.

Velocity doesn't execute one of my methods or find a reference


What releases were used for these instructions?

References

The home directory for tomcat is referred to as ${tomcat_home}.

The name of the directory that stores the application files is referred to as app_name.

The home directory for the application files is reffered to as ${app_home}, which is the same as ${tomcat_home}/webapps/app_name.

What permissions should be used for the files?
All of the files for the ${tomcat_home} subdirectory and everything underneath it should be owned by the same userid as apache (http). The group permission should have userids that can read and/or write. There is no need to make anything world-readable/writeable/executable.

Tomcat Setup

Configuring tomcat

The server.xml file in $tomcat_home/conf contains instructions about setting up the tomcat-managed web applications. It is a good idea to add a <Context> element to the file for every web application, just to make sure the application will be setup as you like. Put them after the line for <Context path="/examples" ...</Context>

        <Context path="/jams" docBase="jams" debug="0"
                 reloadable="true" crossContext="false">
          <Logger className="org.apache.catalina.logger.FileLogger"
                     prefix="localhost_jams." suffix=".txt"
                  timestamp="true"/>
        </Context> 

The path refers to the path from $tomcat_home/webapps that holds the files related to this application. The docBase under my usual setup is the same as the path without the leading '/'.

Reloadable is true if you want the application to be reloaded when a java class file changes. This is very convenient for a test environment. However, in production it will invalidate all of your current sessions when it reloads. For production environments, this should be false.

The crossContext indicates if the ServletContext for this application will be shared with other tomcat web applications. I make this false, since it is unnecessary for my applications.

The Logger is an optional statement that puts tomcat log messages for startup/shutdown for this application into a separate file. In this case, you can look for it under $tomcat_home/logs/localhost_jams.yyyy-mm-dd.txt.

Tomcat log files
If tomcat doesn't seem to startup correctly, or you application doesn't seem to startup, you can go to the tomcat logs to view error messages. See above for an example of setting up a separate log file for a given web application. Otherwise, the messages are in localhost_log.yyyy-mm-dd.txt. These log files should be purged periodically, since they do nothing but get more and more numerous.

Setup the tomcat shared/lib subdirectory
Under ${tomcat_home}/shared/lib, put the jar files for programs that will be needed for all applications. In particular, tomcat expects to find all oracle drivers and ldap-related jars in this directory. For any given web application, tomcat will include in its CLASSPATH the jars in this directory. The files should be owned by the same userid that will startup tomcat.

If you add new jars to this library, you must restart tomcat to have them included in the CLASSPATH.

Create application subdirectories
Make the directories/subdirectories for the application. First, create the subdirectory app_name under ${tomcat_home}/webapps, where app_name will be the name of your choice. All application files should go under ${tomcat_home}/webapps/app_name. Be sure that apache allows the ${app_home} subdirectory to be readable by a browser.

Under ${app_home}, create the subdirectories images, html, and WEB-INF. The images subdirectory contains image files that may be used in the application. The html subdirectory contains any HTML files that may be used in the application. The WEB-INF subdirectory contains everything else. Of course, you can have other subdirectories depending on how you wish to organize the application. Keep in mind that everything under the WEB-INF subdirectory will not be viewable from a web browser, and everything not under WEB-INF can be viewed from a web browser. Under WEB-INF, create the subdirectories lib, logs, templates, and classes.

The URL http://server.utdallas.edu/app_name/html/htmlfile.html will look for the file ${app_home}/html/htmlfile.html.

The lib subdirectory contains all jars that are needed for this particular application. Include the velocity jar here, log4j jars, and UTD-specific jars. All files in this subdirectory are in the tomcat CLASSPATH for this application only. If you add new jars to this library, you must reload this web application or restart tomcat to have them included in the CLASSPATH. If you put a new version of the jar in this subdirectory, you must reload the application or restart tomcat to have them in the CLASSPATH for this web application.

The logs subdirectory contains application logs.

The classes subdirectory contains java classes that are known in the tomcat CLASSPATH for this web application. It will contain any classes that are specific to this application.

The templates subdirectory will hold the Velocity templates for this application.

The web.xml file - Configuring the application
At application startup, Tomcat expects to find a file called web.xml in each application under ${app_home}/WEB-INF (although it does have a default in ${tomcat_home}/conf). Put an entry for every servlet that will be accessed under this application as follows:

    <servlet>
        <servlet-name>
            MAIN
        </servlet-name>
        <servlet-class>MainController</servlet-class>
        <init-param>
            <param-name>properties</param-name>
            <param-value>/WEB-INF/velocity.properties</param-value>
        </init-param>
        <load-on-startup>5</logad-on-startup>
    </servlet>

This tells the web browser information about a particular servlet. It gives the name and then the class in the CLASSPATH that will run. In this case, it is probably the file $app_home/WEB-INF/classes/MainController.class. The load-on-startup tells tomcat to run the init() method when tomcat starts up. The number is a simple sequence number to have multiple servlets in the application start in a particular order.

The example above includes an init-param for the servlet. Optionally, initializing parameters can also be defined as a context parameter, which makes it available to all servlets within the application. Parameters defined under the <servlet> are obtained through the ServletConfig object. Context parameters are available through the ServletContext object. During the servlet's init() method call:
getServletConfig().getInitParameter("properties");
to get an init-param under the servlet definition, or
getServletConfig().getServletContext().getInitParameter("properties");
to get a context parameter. Here properties is the param-name.

To set a context parameter, have the following code before the first <servlet>.

    <context-param>
        <param-name>properties</param-name>
        <param-value>/WEB-INF/app.properties<param-value>
        <description>Property values for this application
        </descrption>
    </context-param>

For every servlet that should be accessible to the user, you must also give the <servlet-mapping>, telling which URL's will be mapped to a particular servlet. A servlet that does not interract with the web application user does not need and should not have a <servlet-mapping>

    <servlet-mapping>
        <servlet-name>MAIN</servlet-name>
        <url-pattern>/servlet/MAIN</url-pattern>
    </servlet-mapping>

The URL pattern refers to the characters that will follow the base URL that gets you to the application itself. For example, if the base application URL is https://netid.utdallas.edu/guam, the the mapping above will take all URL requests to https://netid.utdallas.edu/guam/servlet/MAIN to be processed by the class MainController. The servlets must all be defined in the web.xml file before the first servlet-mapping.

The web.xml file is where you can impose the maximum length of a user session to be idle before the session information goes away. The following example sets the session limit to 60 minutes.

    <session-config>
        <session-timeout>60</session-timeout>
    <session-config>

In addition, it is a good idea to put a welcome file in the application home directory for troubleshooting purposes. If it does nothing but provide a link to the welcome or login screen, that's enough.

    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>

Velocity Setup

The velocity.properties file - Configuring Velocity
The application's properties file for any servlet that will have use Velocity must contain configuration parameters for the engine. In general, the only line needed is:
file.resource.loader.path=/WEB-INF/templates

This gives the location of template files. If more than one directory is used, separate the list of directories with a comma. Note that the path is relative to the app_home directory because of the way the method startVelocity() below initializes the VelocityEngine.

To use log4j to output the Velocity log file, also add something like the following line to the application properties file.
runtime.log.logsystem.log4j.category=VELOCITY

Then in the log4j properties file, define the log4j parameters for this category. Currently, Velocity's log4j link uses the deprecated Category class instead of the preferred Logger class.

The easiest way to create a servlet that has a builtin VelocityEngine is to create a class that extends edu.utdallas.ir.servlet.UTDServlet. The following method is used to create a VelocityEngine based on a Properties object created from the properties file. Call edu.utdallas.ir.util.WebAppProperties.getProperties(ServletConfig) to get this Properties object. This method is included in UTDServlet during init().

If you are not affiliated with UTD, then you'll want to create your own web application servlet that has some basic methods and does standard initialization.

    private VelocityEngine startVelocity(Properties p) {
        String m="";  
        VelocityEngine ve=new VelocityEngine();
        //Setup the file resource loader
        String
            path=p.getProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH,
                    "/templates");
        path = getServletContext().getRealPath(  path );
        if ( path != null) {
            p.setProperty(
                    RuntimeConstants.FILE_RESOURCE_LOADER_PATH,path);
        }
        m=new StringBuffer(64)
         .append("Velocity templates in ").append(path).toString();
        msg.add(m);
        //Setup the velocity log
        String vellog=p.getProperty("RuntimeConstants.RUNTIME_LOG",
                      "/WEB-INF/logs/velocity.log");
        String log=getServletContext().getRealPath(vellog);
        if (log!=null) {
            p.setProperty(RuntimeConstants.RUNTIME_LOG,log);
        }
        try {
            ve.init(p);
        } catch (Exception e) {   
            m=new StringBuffer(64)
             .append("Unable to init the VelocityEngine.\n")
             .append(e).toString();
            msg.add(m);
            working= false;   
        }
        return ve; 
    }

Here msg is a Vector of startup messages and working is a boolean value that tells whether the servlet was properly initialized. These are private values defined for the class.

Following is a basic method for rendering a template.

    protected void renderTemplate(HttpServletResponse res,
            VelocityContext context, String template) {
        res.setContentType("text/html"); 
        try {
            ve.mergeTemplate(template, context, res.getWriter());   
        } catch (ResourceNotFoundException rnfe) {
        } catch (ParseErrorException pee) {
        } catch (MethodInvocationException mie) {
        } catch (Exception e) {
        } 
    }
Add your own handling of any exceptions. The exception is very seldom thrown (famous last words). If there is a problem, look to velocity.log for the error message. The ve object is the VelocityEngine object owned by the servlet.

Other standard methods that I find helpful are:

protected Vector setServletParameters(Properties p);
This method is called during init(), right after the properties are obtained from the web application's properties file as designated in web.xml. The properties file, then, contains all the changeable parameters that would define the servlet workings. The Vector is a set of String messages about the value of the parameters as they are picked up.

protected VelocityContext setInitialContext(Properties p);
This method is called during init(), after the properties are obtained from the web application's properties file. It loads a VelocityContext object with objects that you want to make available to all templates, and which never change. You would do this by creating the template's context using a statement like:
//Create a VelocityContext for this template rendering from initial context
VelocityContext ctx=new VelocityContext(initialContext);

Servlets that use Velocity templates.
There are several servlets already in edu.utdallas.ir.servlet which will make development of Velocity-based applications much easier. The class edu.utdallas.ir.servlet.UTDServlet is already mentioned. However, the servlet you will most often extend, is edu.utdallas.ir.servlet.UTDAppServlet or edu.utdallas.ir.servlet.UTDAppServletLogged. See the documentation for these classes for information about what the class does and decide which methods you would want to override. The DownloadServlet and DownloadServletLogged servlets will provide a web application where a user can download files in a protected directory after authenticating.

Templates

General Comments
Template files are in the ${app_home}/WEB-INF/templates directory. The file extension is always .vm, although Velocity doesn't force any naming conventions for template files. The files may or may not contain Velocity directives, although files that are complete HTML files not referenced in a Velocity #parse or #include directive would generally be in the ${app_home}/html directory.

When creating classes that will be used as references for the Velocity template, make it easy on the designer. Use lots of get methods and is methods to return data or boolean values respectively. This will make getting references more intuitive. The reference $user.lastname will refer to the method getLastname(). The reference #if ($user.isStudent) will refer to the method isStudent(). Avoid mixing upper case more than once after the get unless you have a clear understanding with the designer. The method getLastName will have to be referenced in the template as $user.lastName or $user.LastName. Velocity is only forgiving about the first capital letter.

All of the classes referenced in a template must be public, and all methods referenced must be public. Only public methods within the class are accessible to Velocity.

Public classes defined within another public class are difficult for Velocity to find. Avoid these.

Avoid making the template designer use methods that are complex. The get methods and is methods are good. Other methods that do not take parameters are also okay but the addition of the required () at the end can be confusing, because now some references need it and some don't. Methods that call for parameters are even more dicey, because the designer may need to know about using the correct java types, etc. This should really be avoided. Whenever possible, run this method in the java servlet and pass the results to the template. Another option is to place a tool in the VelocityContext that simplifies the use of the method. Even for standard methods that you think are simple (size()), it is better to make a simple method for the designer like getsize() to make a reference like $list.size, or to send a VelocityContext string $listsize. Be kind to your designer.

Also, be sure that methods used by the designer cannot throw any kind of exception whatsoever, even NullPointerException or IndexOutOfBoundsException. You don't want the designer to be able to inadvertantly send a javac exception stack to the web user.

Templates for every application
Some templates show up in virtually all of my applications. Thus, templates with the same function always have the same name to help me with troubleshooting.

The error.vm template is called when the application fails in some crucial part of initialization.

The noserver.vm template gives a standard message to the user when a request cannot be processed because of a system error. The idea is to avoid sending stack traces to the poor user. Instead, send this screen to the user, and log the stack trace to a log file.

The login.vm template presents a standard login screen.

The welcome.vm template presents the "home page" screen for this application.

The head.vm template presents the standard top of a screen. You can use the Velocity directive #parse("head.vm") at the top of a template file to have this at the top of the screen. Changing the header then only involves changing this file. This is also a good place to setup a standard

statement, since all templates in the application will be directed to basically the same URL.

The tail.vm template presents a standard footer for a screen. You can use the Velocity directive #include("tail.vm") at the bottom of a template file to have this at the bottom of the screen. Changing the footer then only involves changing this file.

The end.vm template includes a standard footer with links to the UTD homepage and the IR homepage. These are mandated on all UTD web pages. However, for pages that are confidential in nature and should require a logout, these links should not be presented.

Setting Up Log4j Logging

The Log4jServlet
The servlet edu.utdallas.ir.servlet.Log4jServlet provides log4j logging. It will look for an init-param of "log4j" as the name of the Log4j properties file. Log4j logging will be setup according to this properties file. See the javadoc for edu.utdallas.ir.servlet.Log4jServlet for more information.

There does not need to be a <servlet-mapping> in web.xml for this servlet. The following should be placed in the list of <servlet> in web.xml. Note that <load-on-startup> is 1, so log4j logging is setup before any other servlets are called.

    <servlet>
        <servlet-name>Log4j</servlet-name>
        <servlet-class>edu.utdallas.ir.servlet.Log4jServlet
        </servlet-class>
        <init-param>log4j</init-param>
        <init-value>/WEB-INF/log4j.properties</init-value>
        <load-on-startup>1<load-on-startup>
    </servlet>
Configuring Log4j loggers in the properties file
See the documentation on setting up Log4j logging at http://jakarta for full details. Some common configurations are given below.

To setup the Velocity log file as a rolling appender file named velocity.log under WEB-INF/ use:

log4j.category.VELOCITY=DEBUG, VEL
log4j.appender.VEL=org.apache.log4j.RollingFileAppender
log4j.appender.VEL.File=${catalina.home}/webapps/appname/WEB-INF/logs/velocity.log
log4j.appender.VEL.MaxFileSize=10KB
log4j.appender.VEL.MaxBackupIndex=1
log4j.appender.VEL.layout=org.apache.log4j.PatternLayout
log4j.appender.VEL.layout.ConversionPattern=%d - %m%n

Here VELOCITY refers to the runtime.log.logsystem.log4j.category property in the properties file. When velocity.log fills to its maximum size of 10KB, the velocity.log will be written to velocity.log.1 and new messages will be written to velocity.log. In the ConversionPattern, %d is the date, %m is the message, %n is a newline. Be sure the log4j.appender File property points to the filename you want to use. Here the first line refers to log4j.category, which it must for Velocity. However, the application should be using the more recent Logger class, which means the first line would refer to log4j.logger.

To write to a system log:

log4j.logger.Login=DEBUG, Login
log4j.appender.Login=org.apache.log4j.net.SyslogAppender
log4j.appender.Login.SyslogHost=localhost
log4j.appender.Login.Facility=LOCAL0
log4j.appender.Login.layout=org.apache.log4j.PatternLayout
log4j.appender.Login.layout.ConversionPattern=%-5r %-5p [%t] %c{2} %x - %m\n

Here the SyslogHost will be the server name of the syslog or localhost for this server. LOCAL0 would be setup by the system administrator in configuring the syslog. Note that this uses the log4j.logger instead of log4j.category used for Velocity.

To setup a logger in the application, include the line
import org.apache.log4j.Logger;
among the import statements, and name the Logger when you name other class fields:
static Logger LOG=Logger.getLogger("Login");

Note that the Logger must be static. LOG is the name that will be used to program log statements (LOG.info("message");). "Login" is the reference that will be used in log4j.properties to define the Logger's properties, as in the example for Login above.

Because the Logger is static, it can be referred to in more than one class. So you could have the above logger definition in several different classes, and it would write to the same Log4J managed log.

In addition, you could define a static Logger in a class with a different Log4J reference name, and then map it to the same logger in the log4j.properties file.
log4j.logger.Alogger=DEBUG, Login

Other Tips

Provide resources to the web application through servlets and the web.xml file
By writing specialized servlets for web application resources, it is easy to customize the resources that will be available to a particular web application. For each resource, initialize all necessary objects and put them in the ServletContext. These objects then become available to all servlets that are loaded later. See the web.xml discussion for defining servlets and the order in which they will be loaded. With this strategy, you can customize the resources available to a web application with the web.xml file alone. In addition, you can provide other standard servlets, like the Login servlet to handle authentication.

The following sets up Log4j, an Oracle connection pool, an LDAP connection pool, a standard LDAP authentication servlet, and then a servlet that is specific to this application. The application servlet pulls the connection pools into private fields. The last servlet removes the connection pools from ServletContext, so they are no longer available with a public java method.

    <context-param>
        <param-name>properties</param-name>
        <param-value>/WEB-INF/guam.properties</param-value>
        <description>
            Contains the property values for this application.
            To be used all servlets except Log4j.
        </description>
    </context-param>
    
    <servlet>
        <servlet-name>Log4j</servlet-name>
        <servlet-class>edu.utdallas.ir.servlet.Log4jServlet
        </servlet-class>
        <init-param>
            <param-name>log4j</param-name>
            <param-value>/WEB-INF/log4j.properties</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
        
    <servlet>
        <servlet-name>Oracle</servlet-name>
        <servlet-class>edu.utdallas.ir.servlet.OraclePoolServlet
        </servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>
    
    <servlet>
        <servlet-name>Login</servlet-name>
        <servlet-class>edu.utdallas.ir.servlet.LoginServlet
        </servlet-class>
        <load-on-startup>5</load-on-startup>
    </servlet>
        
    <servlet>
        <servlet-name>LDAP</servlet-name>
        <servlet-class>edu.utdallas.ir.servlet.LDAPPoolServlet
        </servlet-class>
        <load-on-startup>3</load-on-startup>
    </servlet>
        
    <servlet>
        <servlet-name>
            MAIN
        </servlet-name>
        <servlet-class>guam.Main</servlet-class>
        <load-on-startup>6</load-on-startup>
    </servlet>

    <servlet> 
        <servlet-name>ClearServletContext</servlet-name>
        <servlet-class>
                edu.utdallas.ir.servlet.ClearServletContext
        </servlet-class>
        <load-on-startup>8</load-on-startup>
    </servlet>
Setup application flow through several servlets
This is a good approach if the various functions of your web application will need to access the ServletContext, and you have an application that provides clearly delineated subapplications. Define each servlet and its servlet-mapping in the web.xml file. Designate a value for $app in the initialVelocityContext. Then the <FORM HREF="${url}/${app}"...> in the template will always take the user to the proper subapplication.

Setup application workflow through function classes
For more complex applications, I like the function approach. In the HTML form, define a hidden field with the name of the function to reference as <INPUT TYPE="hidden" NAME="function" VALUE="DoSomething">. The function is a relatively small task to be performed by the web application. It can handle more that more than one template in handling its mini-workflow. It extends an interface I call WebFunction, which has an execute method that receives the Http request and session, the VelocityContext, etc. It processes the request parameters, updates the session and context as needed, and returns the Velocity template name for rendering. It also throws Exception, so the calling program is always in change of handling exceptions. The function class must also have a default constructor, taking no parameters. This avoids having ten million 'if' statements in the servlet while trying to decide where to go next.

So in the doGet method of the servlet:

    VelocityContext ctx=new VelocityContext(initialVelocityContext);
    String name=(String) req.getParameter("function");
    // Create the class name from the function parameter
    String function="functions."+name+"Function";
    WebFunction task;
    String template;
    try {
        task=(WebFunction) Class.forName(name).newInstance();
    } catch (Exception e) {
        handleException(e);
    }
    try {
        template=task.execute(req, session, ctx);
    } catch (Exception e) {
        handleException(e);
    }

If the functions need resources available only to the servlet, then have standard methods in the WebFunction that will get these resources.

   public boolean needsConnection();
   public void setConnection(Connection con);
The function class then implements these methods, depending on whether it needs the particular resource.
    public boolean needsConnection() {
        return true;
    }
    public void setConnection(Connection con) {
        this.con=con;
    }
The servlet can use these methods to provide the resources, and then performs any necessary closing when the function is done.
    if (task.needsConnection()) {
        task.setConnection(pool.getConnection());
    }
    ...
    pool.close(con);

Troubleshooting

Can't find the URL
Check that the URL you gave is valid to Apache. Are you using the correct protocol (http: or https). Does Apache know about your application path? If you have an index.html file defined in web.xml, try a URL that has a path to just the application, not to the servlet. (i.e., http://myserver.xxx/app_name). If you can't bring up index.html, then Apache doesn't know about the application path.

If you are able to look at index.html, check that web.xml has setup the path with a servlet-mapping entry for the servlet. Unless the default invoker is setup for the application (and I don't recommend it), then this is the only way Tomcat can find the URL.

Check the Tomcat logs for the web application and tomcat itself to make sure they started normally. See the section on Tomcat logs for more information.

A blank screen is returned instead of the results of the Velocity template
This is Velocity's graceful way of telling you that there is a problem with the template. The user will not get a screen with confusing messages, but the Velocity log will be happy to supply the details. If following the Velocity configuration given here, your velocity log will be the file $app_home/WEB-INF/logs/velocity.log.

The problem could be that Velocity is unable to find the template filename given, or that a template file referred to in a #parse or #include cannot be found. Check the initialization messages in the velocity.log file to see the exact path being used by the file loader to find files. The template name should be given relative to that path. So if, as in my setup, the templates are in $app_home/WEB-INF/templates, the template "welcome.vm" would be $app_home/WEB-INF/templates/welcome.vm. Also, check that the permissions for the template file allow the web owner to access it.

If the problem is a parse error, the velocity log will happily give you the line number and column number where the parse error occurred. Common errors are missing #end or too many #end lines.

Velocity doesn't execute one of my methods or find a reference
The symptom is that you put a reference to a field or a method in the template, and it is rendered without change to the screen instead of being replaced by the reference value or the method results. For example, $user.lastname comes out on the web screen as $user.lastname instead of 'Baughman'.

Check that the referenced object is public and in Tomcat's CLASSPATH. Velocity has a hard time working with public classes that are defined within public classes.

Check that the method is public.

Check that an object with this name has been placed in the VelocityContext by the servlet. If the reference is $user.lastname, then the servlet should have a line like context.put("user",user); before rendering the template.

Be sure the reference refers to an actual method name in the class. If you are using a 'get' or 'is' method to find a value, be sure your capitalization is correct. If you have $user.lastname, then the method must be getLastname or getlastname (or isLastname or islastname), not getLastName. In the latter case, you would use $user.LastName or $user.lastName as valid references.

If you are using public methods that have arguments, make sure the java types of the arguments you pass are the java types expected by the method.


Email comments or suggestions to me.