Wednesday, December 16, 2009

Adding The Profile Page

I want the user to be able to edit their profile page, so they can change their name to something other than what RPX reported. And so they can add information not given in RPX (for example, in my contest site I might want their birthday so I can calculate their age, and so I can display a Happy Birthday message on their birthday).

In the FreeMarker template for the front page I put the link for the profile page as /profile. That will have to map to a Java servlet that displays the profile editing page for the currently logged in user, and saves changes to the data store.

This will also let us set up a pattern for pages that require the user to be logged in to view, as well as a pattern for pages that do form processing.

So let's add a handler for the profile page, and start out by requiring the user to be logged in to view it. If they aren't logged in, they'll get a message and a Sign In link.

If you don't remember how to add a new servlet, read my original post on Java Servlets. Add a new servlet mapped to /profile. I'll call mine ProfileServlet, so the code for it will be in ProfileServlet.java in my project.server package.

In ProfileServlet.java, I'll use code like this to show one page if they're logged in, and another if they're not:


Map root = new HashMap();
String template = "profileNotLoggedIn.ftl";

if (session != null)
{
// Get the User's name
Long userid = (Long) session.getAttribute ("userid");
PersistenceManager pm = PMF.get().getPersistenceManager();

Query query = pm.newQuery("select from omega.server.User where id == idParam");
query.declareParameters("Long idParam");

try
{
List<User> results = (List<User>) query.execute(userid);
User user = results.get(0);
String name = user.getName ();
Integer userLevel = user.getUserLevel ();
root.put("loggedIn", true);
root.put("name", name);
root.put("userLevel", userLevel);
template = "profileLoggedIn.ftl";
}
finally
{
query.closeAll();
pm.close();
}
}
else
{
root.put("loggedIn", false);
}

Template temp = config.getTemplate(template);

PrintWriter out = resp.getWriter();

try
{
temp.process(root, out);
out.flush();
} catch (TemplateException e)
{
e.printStackTrace(out);
}


Notice how the FreeMarker template we use depends on whether the user is logged in or not. This allows us to separate out those pages for web design purposes, rather than forcing the web designer to put logic into the pages.

I'll need to create both FreeMarker templates. profileNotLoggedIn.ftl will just be a simple error page with the standard links across the top. profileLoggedIn.ftl will display a form, populating the fields with the data from the data model.

I'll create those templates by copying over my Front.ftl file and adding the extra bits. Next post we'll see how to centralize some of the common navigation elements so we aren't duplicating them between templates.

Here's the form from profileLoggedIn.ftl:


<form action="/profile" method="POST">
<input type="text" name="name" value="${name}">
<input type="submit" name="submit" value="Save Changes">
</form>


This is the simplest form possible that will do the job. It really should be a bit fancier, providing at least a label for the edit field.

Right now clicking Save Changes just redisplays the form. After we remove the duplication among the templates, we'll add in handling of the form to actually update the data store.

No comments:

Post a Comment