The building of a web application

The simple way, extracted from the hard methods

I want a main page in Apache Wicket

So, We’ve set up the database and domain, now it’s time for the GUI. With Wicket.

Of course we’ve to start the initialisation Class for our application:

package com.rivaso.exp.web;

import org.apache.wicket.Page;
import org.apache.wicket.authroles.authentication.AbstractAuthenticatedWebSession;
import org.apache.wicket.authroles.authentication.AuthenticatedWebApplication;
import org.apache.wicket.markup.html.WebPage;
import org.wicketstuff.javaee.injection.JavaEEComponentInjector;

import com.rivaso.exp.web.secure.SignInPage;
import com.rivaso.exp.web.secure.EXPAuthenticatedWebSession;
import com.rivaso.exp.web.tests.TestOverviewPage;

/**
 * @author RiVaSo
 * @version 1.0
 */
public class Main extends AuthenticatedWebApplication {

	public Main() {
	}

	@Override
	protected void init() {
		super.init();
		super.getComponentInstantiationListeners().add(new JavaEEComponentInjector(this));
		getDebugSettings().setDevelopmentUtilitiesEnabled(true);
	}

	@Override
	public Class<? extends Page> getHomePage() {
		return MainPage.class;
	}

	@Override
	protected Class<? extends AbstractAuthenticatedWebSession> getWebSessionClass() {
		return EXPAuthenticatedWebSession.class;
	}

	@Override
	protected Class<? extends WebPage> getSignInPageClass() {
		return SignInPage.class;
	}
}

Then we create the class for the SignInPage:

package com.rivaso.exp.web.secure;

import org.apache.wicket.request.mapper.parameter.PageParameters;

import com.rivaso.exp.web.BasePage;

/**
 * @author RiVaSo
 * @version 1.0
 */
public class SignInPage extends BasePage {

	private static final long serialVersionUID = 97;

	public SignInPage() {
		this(null);
	}

	/**
	 * Constructor:
	 * 
	 * @param parameters The page parameters
	 */
	public SignInPage(final PageParameters parameters) {
		add(new JEESignInPanel("signInPanel"));
	}
}

As you could see, we’ve to create the J2EE Sign In Panel:

package com.rivaso.exp.web.secure;

import org.apache.wicket.authroles.authentication.panel.SignInPanel;

/**
 * @author RiVaSo
 * @version 1.0
 */
public class JEESignInPanel extends SignInPanel {

	private static final long serialVersionUID = 96L;

	public JEESignInPanel(String id) {
		super(id);
	}
	
	public JEESignInPanel(String id, boolean rememberMe) {
		super(id, rememberMe);
	}
	
	@Override
	protected void onBeforeRender() {
		EXPAuthenticatedWebSession.getExpAuthenticatedWebSession().checkJEEAuthentication();
		super.onBeforeRender();
	}
}

And here we have the HTML-side of the SignInPage:

<!DOCTYPE html>
<html>
    <head>
        <title>Please Sign In</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body>
    <wicket:extend> 
        <span wicket:id="signInPanel"/>
    </wicket:extend> 
</body>
</html>

Of course, also a NotAuthenthicatedPage and SignOutPage should be created:

package com.rivaso.exp.web.secure;

import com.rivaso.exp.web.BasePage;

public class NotAuthenthicatedPage extends BasePage {

	private static final long serialVersionUID = 0L;
}
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Not Authenthicated or Authorized</title>
    </head>
    <body>
    <wicket:extend>
        <h2>Forbidden</h2>
        <p>You're not authorized or authenthicated for using this application.</p>
        <br />
        <p>Please contact the administrators for requesting access.</p>
    </wicket:extend>
</body>
</html>
package com.rivaso.exp.web.secure;

import com.rivaso.exp.web.BasePage;
import com.rivaso.exp.web.UserPage;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.request.mapper.parameter.PageParameters;

/**
 * @author RiVaSo
 * @version 1.0
 */
public class SignOutPage
        extends BasePage
{
    /**
     * Constructor:
     * @param parameters Page parameters
     */
    public SignOutPage( final PageParameters parameters )
    {
        getSession().invalidate();
        add( new BookmarkablePageLink( "linkContinue", UserPage.class ) );
    }
}
<!DOCTYPE html>
<html>
    <head>
        <title>You're logged out now</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body>
    <wicket:extend>
        <p>You're logged out now. Goodbye</p>
        <wicket:link><a href="#" wicket:id="linkContinue">Continue</a></wicket:link>
    </wicket:extend>
</body>
</html>

And now we’ve to Create a special class to initailze a session:

package com.rivaso.exp.web.secure;

import java.security.Principal;

import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;

import org.apache.wicket.RestartResponseException;
import org.apache.wicket.authroles.authentication.AuthenticatedWebSession;
import org.apache.wicket.authroles.authorization.strategies.role.Roles;
import org.apache.wicket.injection.Injector;
import org.apache.wicket.request.Request;
import org.apache.wicket.request.cycle.RequestCycle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.rivaso.exp.domain.Person;
import com.rivaso.exp.domain.Position;
import com.rivaso.exp.manager.PersonManager;
import com.rivaso.exp.web.Main;
import com.rivaso.exp.web.SetupPage;

/**
 * @author RiVaSo
 * @version 1.0
 */
public class ExpAuthenticatedWebSession
        extends AuthenticatedWebSession {

    private static final long serialVersionUID = 996L;

	@EJB (name = "PersonManager")
	private PersonManager personManager;

    private Person authenticated;

    private transient Logger log = LoggerFactory.getLogger(EXPAuthenticatedWebSession.class);

    public EXPAuthenticatedWebSession(Request request) {
        super(request);
        Injector.get().inject(this);
    }

    public static EXPAuthenticatedWebSession getEXPAuthenticatedWebSession() {
        return (EXPAuthenticatedWebSession) get();
    }

    @Override
    public boolean authenticate(String emailAddress, String password) {
        emailAddress = emailAddress.toLowerCase();
        // Login using JEE security
        HttpServletRequest servletRequest = (HttpServletRequest) RequestCycle.get().getRequest().
                getContainerRequest();
        try {
            servletRequest.login(emailAddress, password);
            signIn(true);
            matchGlobalWithLocalUser(emailAddress);
        } catch (ServletException e) {
            // If login fails we come here
            return false;
        }
        return true;
    }

    private void matchGlobalWithLocalUser(String emailAddress) {
        try {
            Person personFound = personManager.getPersonByEmail(emailAddress);
            if (personFound != null && (personFound.isInPostion(Position.USER) || personFound.
                    isInPostion(Position.ADMIN))) {
                authenticated = personFound;
            }
        } catch (Exception ex) {
            log.error("Error by getting person", ex);
        }
        if (this.authenticated == null) {
			if (personManager.count() == 0 ) {
                // Go to setup page. First time use.
                throw new RestartResponseException(SetupPage.class);
            } else {
                throw new RestartResponseException(NotAuthenthicatedPage.class);
            }
        } else {
            throw new RestartResponseException(NotAuthenthicatedPage.class);
        }
    }

    @Override
    public Roles getRoles() {
        if (isSignedIn()) {
            return new Roles(authenticated.getRoles());
        }
        return null;
    }

    public Person getAuthenticated() {
        return this.authenticated;
    }

    
    /**
     * Checks if user is already logged in with JEE security and signs the user in if so. 
     * Restart the response if no user is found.
     *
     * No visible modifier. Only class from this package may call this method.
     */
    void checkJEEAuthentication() {
        HttpServletRequest servletRequest = (HttpServletRequest) RequestCycle.get().getRequest().
                getContainerRequest();
        Principal userPrincipal = servletRequest.getUserPrincipal();
        if (userPrincipal != null && userPrincipal.getName() != null) {
            signIn(true);
            matchGlobalWithLocalUser(userPrincipal.getName());
        }
    }
}

And now we make the class for BasePage, which will be inherited by all our pages.

package com.rivaso.exp.web;

import org.apache.wicket.Component;
import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.list.AbstractItem;
import org.apache.wicket.model.PropertyModel;

import com.rivaso.exp.domain.Person;
import com.rivaso.exp.domain.Position;
import com.rivaso.exp.web.secure.SignOutPage;
import com.rivaso.exp.web.secure.EXPAuthenticatedWebSession;

/**
 * @author RiVaSo
 * @version 1.0
 */
public class BasePage extends WebPage {

	private static final long serialVersionUID = -166L;

	public BasePage() {
		super();
		final EXPAuthenticatedWebSession expAWS = EXPAuthenticatedWebSession.getExpAuthenticatedWebSession();
		add(createMenuLI(new AbstractItem("userLI")).add(new BookmarkablePageLink<Void>("user", UserPage.class)));
		add(createMenuLI(new AbstractItem("experienceLI")).add(new BookmarkablePageLink<Void>("experience", ExperiencePage.class)));
		add(createMenuLI(new AbstractItem("adminLI")).add(new BookmarkablePageLink<Void>("admin", AdminPage.class) {
			private static final long serialVersionUID = 1L;

			protected void onConfigure() {
				if (expAWS.isSignedIn() && expAWS.getAuthenticated() != null && expAWS.getAuthenticated().isInPostion(Position.ADMIN)) {
					setVisibilityAllowed(true);
				} else {
					setVisibilityAllowed(false);
				}
			};
		}));
		add(createMenuLI(new AbstractItem("logoutLI")).add(new BookmarkablePageLink<Void>("logout", SignOutPage.class) {
			private static final long serialVersionUID = 1L;

			protected void onConfigure() {
				if (expAWS.isSignedIn()) {
					setVisibilityAllowed(true);
				} else {
					setVisibilityAllowed(false);
				}
			};
		}));
		add(new Label("loggedin", new PropertyModel<Person>(this, "session.authenticated.emailAddress")));
	}
	
	private AbstractItem createMenuLI(AbstractItem li) {
		li.add(new LinkActiveModifier());
		return li;
	}

	class LinkActiveModifier extends AttributeAppender {
		public LinkActiveModifier() {
			super("class", "active");
			super.setSeparator(" ");
		}

		private static final long serialVersionUID = 1L;

		@SuppressWarnings("rawtypes")
		@Override
		public boolean isEnabled(Component component) {
			if (component instanceof AbstractItem) {
				AbstractItem li = (AbstractItem) component;
				Component component2 = li.get(0);
				if (component2 instanceof BookmarkablePageLink) {
					BookmarkablePageLink bpl = (BookmarkablePageLink) component2;
					if (bpl.linksTo(BasePage.this.getPage())) {
						return true;
					}
				}
			}
			return false;
		}
	}
}
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>The Experience System</title>
        <meta name="description" content=""/>
        <meta name="keywords" content=""/>
        <link rel="icon" type="image/png" href="">
        <link rel="stylesheet" href="css/style.css" type="text/css" media="screen" />
    </head>
    <body id="home">
        <div id="page">
            <div id="header">
                <a href="/en/">
                    <img src="css/img/logo.jpg" id="logo" alt="logo"/>
                </a>
                <ul id="main_nav">
                    <li wicket:id="userLI" class="first ">
                        <a href="#" wicket:id="user">User</a>
                    </li>
                    <li wicket:id="experienceLI"  class="">
                        <a href="#" wicket:id="experience">Experience</a>
                    </li>
                    <li wicket:id="adminLI"  class="">
                        <a href="#" wicket:id="admin">Admin</a>
                    </li>
                    <li wicket:id="logoutLI"  class="">
                        <a href="#" wicket:id="logout">Logout</a>
                    </li>
                </ul>
            </div>
            <div id="content_bg">
                <div class="seperator">
                </div>
            </div>
            <div id="content">
                <wicket:child />                
            </div>
            <div class="clear"></div>
            <div id="footer-push"></div>
        </div>	
        <div id="footer-wrap">
            <div id="footer">
            	<ul class="left">© RiVaSo 2012</ul>
                <ul>
                    <li><span wicket:id="loggedin"></span></li>
                </ul>
            </div>
        </div>
    </body>
</html>

Now it’s time to make a main page, I’ve chosen to use the profile page of the user for that:

package com.rivaso.exp.web;

import com.rivaso.exp.domain.Person;
import com.rivaso.exp.domain.Position;
import com.rivaso.exp.web.secure.NotAuthenthicatedPage;
import com.rivaso.exp.web.secure.EXPAuthenticatedWebSession;
import javax.naming.AuthenticationException;
import org.apache.wicket.authroles.authorization.strategies.role.annotations.AuthorizeInstantiation;
import org.apache.wicket.markup.html.basic.Label;

/**
 *
 * @author RiVaSo
 * @version 1.0
 */
@AuthorizeInstantiation ({Position.ADMIN_STRING, Position.USER_STRING})
public class MainPage
        extends BasePage {

    private static final long serialVersionUID = 2446731116379770530L;

    public MainPage() {
        super();

        try {
            EXPAuthenticatedWebSession aws = (EXPAuthenticatedWebSession) this.getSession();

            if (aws.isSignedIn()) {
                showMainPage();
            } else {
                throw new AuthenticationException("Not signed in.");
            }
        } catch (AuthenticationException ex) {
            // Not signed in.
            ex.printStackTrace();
            this.redirectToInterceptPage(new NotAuthenthicatedPage());
        }

    }

    private void showMainPage() {
        EXPAuthenticatedWebSession aws = (EXPAuthenticatedWebSession) this.getSession();
        Person person = aws.getAuthenticated();
       
        String skills = "";
        String skillsDone = "";
        if (person != null) {
            skills = person.getTotalAmountOfSkills() + "";
            skillsLeft = person.getAmountOfSkillsLeft() + "";
        }
        add(new Label("lblFirstName", person.getFirstName()));
        add(new Label("lblSurName", person.getSurName()));
        add(new Label("lblEmailAddress", person.getEmailAddress()));
        add(new Label("lblAmountOfSkillsLeft", skillsLeft));
        add(new Label("lblAmountOfSkills", skills));
    }
}
<!DOCTYPE html>
<html>
    <head>
        <title>UserPage - Experience System</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body>
    <wicket:extend> 
        <h2>Welcome <span wicket:id="lblFirstName">Pleased</span> <span wicket:id="lblSurName">User</span></h2>
        <p>Your email-address is: <span wicket:id="lblEmailAddress">person@riva.so</span></p>
        <wicket:enclosure child="">
            <p>You have <span wicket:id="lblAmountOfSkillsLeft">a few</span> of the <span wicket:id="lblAmountOfSkills">big amount</span> skills left.</p>
        </wicket:enclosure>
    </wicket:extend>
</body>
</html>

As you could see… the tag <wicket:id> is used to insert information from the ‘logical layer’ (the Class) into your html.

The <wicket:child>-tag in the BasePage is to clarify that Wicket should put the content in the <wicket:extend>-tags of the html-versions of the childs classes inherited from BasePage.

The <wicket:enclosure>-tags are used to specify that if the content is null of a <wicket:child>-tag placed within the <wicket:enclosure>-tags, the content won’t be shown.

The attribute “child” is used to target a specific wicket:id. If you want to deactivate a specific nested wicket:id, use the attribute like this way: <wicket:enclosure child=”[parent-wicket:id]:[target-wicket:id]”>

Now, the next step it’s more on you. I’ll only give some examples for creating GUI components.

Advertisement

Written by RiVaSo

22 February 2012 at 00:06

%d bloggers like this: