Showing posts with label guice. Show all posts
Showing posts with label guice. Show all posts

Thursday, September 23, 2010

Dumbassing things up

In a previous entry, Some management servlets, in the section You do know that anyone in the world can delete your datastore, right?, I goofed.

In my defense, the first section of that entry WAS entitled I have no idea what I'm talking about. But it turns out my ignorance knows few bounds.

web.xml, access control, and Guice


I stated that in moving my BuildDB servlet under the control of Guice, I lost the ability to use a security-constraint in the web.xml file to stop the hoi polloi from accessing our servlet. Not so.

Simply have Guice respond to a URL pattern (such as "/*") that includes the security-constraint constrained URL below it, say /admin/*. All of your servlets now are Guicified, and the ones you want protected are protected.

Yeah, shoulda figured that out the first time.

war/WEB-INF/web.xml
<web-app>
 <!-- Servlets -->
 <security-constraint>
  <web-resource-collection>
   <url-pattern>/admin/*</url-pattern>
  </web-resource-collection>
  <auth-constraint>
   <role-name>admin</role-name>
  </auth-constraint>
 </security-constraint>

 <filter>
  <filter-name>guiceFilter</filter-name>
  <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
 </filter>

 <filter-mapping>
  <filter-name>guiceFilter</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>

 <listener>
  <listener-class>com.lisedex.voluntickler.server.guice.VolunticklerServletContextListener</listener-class>
 </listener>

 <!-- Default page to serve -->
 <welcome-file-list>
  <welcome-file>index.html</welcome-file>
 </welcome-file-list>
</web-app>

The observant among you will notice that our package is now com.lisedex.voluntickler instead of com.lisedex.volinfoman. It's a sexy name change, I know, and I realize that you're a bit jealous, but the domains are already registered. Sorry.

Saturday, September 4, 2010

Some management servlets

So I got StarCraft II, and let's just say I've spent a lot more time with that than I have with this project, what with playing, watching Day9 Daily archives, reading strategy...

And I'm still in the bronze league. You may now commence laughing.

But a couple of days ago, I picked this stuff back up. Leaving it for so long is a mistake, as it always takes me a while to remember what's what, where I was, and where I was going. I messed around with the interface, trying to get a very basic layout with a working login page.

I learned a few important lessons, like wrapping widgets with SimplePanels so they could be swapped out easily with just a setWidget() as the interface required, and my previous understanding, as explained in my last entry, of bind() from mvp4g was off. But I learned a much more important lesson.

I have no idea what I'm talking about


OK, that's maybe a bit harsh, but really, I think I was coming at this with a fundamental misconception about how it'll work. I was trying to build an application where you could login, or register for the site, or request a reset password, or actually use the site for its intended purpose basically without leaving the layout and original landing page. Lunacy. Trying to fit the project to the tool, while not understanding the tool all that well, either.

At first, I realized things should work more like Gmail, where your initial login and registration could be handled on some regular pages, and then you move in to the application itself. Flipping this switch in my brain alone allowed me to start making much faster progress (obviously helped along because I had moved back to a more familiar paradigm). Taking that lesson more generally, I shouldn't force this thing into a single page where widgets are swapped in and out. If it makes more sense, I should be willing to just move to another page, or sprinkle parts of GWT throughout pages, unless there's too much of a startup penalty.

In short, I don't need to write this as if it were some monolithic desktop application.

On that note, I'm going to focus in this post on the account registration, email confirmation, App Engine cron jobs. At this time, these all use GAE, but not GWT. You'll just have to ignore the GWT client code for now, as it's in a screwy state that compiles and renders a page, but doesn't do anything remotely useful.

As always, the code is available at github under the add-static-login tag.

Moving the starting line


The first step was moving the home page, and having it basically static with a login form and a link to the registration page.

war/WEB-INF/web.xml
<!-- Default page to serve -->
        <welcome-file-list>
               <welcome-file>index.html</welcome-file>
        </welcome-file-list>

I can keep the original Volinfoman.html for later, and this automatically solves one of the issues I had been thinking about, but had put off for later: auto-complete not working in GWT login pages, and using HTTPS to submit the user's password.

The link to the registration page leads to another simple, static form, register.html. This submits to a servlet which is written using App Engine, Register.

The making of a servlet


We need to register this servlet with Guice so that injection works.

src/com/lisedex/volinfoman/server/guice/VolinfomanGuiceModule.java
bind(Register.class).in(Singleton.class);

src/com/lisedex/volinfoman/server/guice/VolinfomanServletModule.java
serve("/volinfoman/register").with(Register.class);

In our Guice module, we configure Register as a Singleton, and in Guice's servlet configuration, we let it know that the URL /volinfoman/register should be sent to Register for handling. This is, of course, the action we use for the form in register.html.

src/com/lisedex/volinfoman/server/authenticate/Register.java
public class Register extends HttpServlet {
        @Inject
        private Dao dao;

        private static final Logger log = Logger.getLogger(Register.class.getName());

        @Override
        public void doGet(HttpServletRequest req, HttpServletResponse resp)
                        throws IOException {

                PrintWriter output = resp.getWriter();

                // build HTML response page
                resp.setContentType("text/html");
                resp.setCharacterEncoding("utf-8");
                output.println("<head><title>Add initial datastore information</title></head>");
                output.println("<body>");

                String username = req.getParameter("username");
                String firstName = req.getParameter("firstName");
                String lastName = req.getParameter("lastName");
                String password = req.getParameter("password");
                String email = req.getParameter("email");

                if (!StringSafety.isSafe(username)) {
                        output.println("<span style=\"color: #ff0000;\">Username bad, please go back and enter it again</span>");
                        output.println("</body>");
                        return;
                }

                if (!StringSafety.isSafe(firstName)) {
                        output.println("<span style=\"color: #ff0000;\">First name bad, please go back and enter it again</span>");
                        output.println("</body>");
                        return;
                }

                // ... etc, etc. for input safety ...

                if (dao.getUser(username) != null) {
                        output.println("<span style=\"color: #ff0000;\">Username already exists, please go back and enter it again</span>");
                        output.println("</body>");
                        return;
                }

This first pass at the servlet is pretty ugly, with plenty of string literals, but what we're doing is laying the groundwork for the registration by collecting the user's input.

We extend javax.servlet.http.HttpServlet and override its doGet() method, since at this point we have not declared a method for our HTML form to use and it defaults to GET. Later, we'll change this to doPost() since the user is entering their password in the form, and we don't really need that showing up in the address bar of their browser. Or our server logs.

We start setting up the page that gets sent back to the user when the servlet completes, by filling out the HttpServletResponse object passed in as resp. After setting what type of page we'll be returning, we print to the object line-by-line in the order we would want to build a standard HTML page.

We need to get the user's input, so we use the getParameter method of HttpServletRequest, which parses the form data for us, and hides the logic needed to handle both GET and POST forms. After we get the input, we want to protect ourselves from things like injection attacks, so we have to check each piece of input that comes from outside of the servlet. The static StringSafety.isSafe() method right now is terribly simple, just looking for ; and & characters. Later, we'd want to do better verification, like making sure the username and password meet whatever requirements we have and that the email address looks basically valid.

If any of the input doesn't meet our standards, we spit out an error message and abort the servlet. I check each separately, so I can inform the user of which field doesn't meet our standards. Ideally, instead of forcing the user to go back, we'd re-render the form, with the error message integrated into it, but right now we're doing it the simple way. I removed some of the repetitious statements for brevity; see the code for the full version.

Finally, we make sure that the username requested doesn't already exist. This seems like an expensive way to look this up, and is also open to another account with the same username getting created between that test and the next lines of code.

User user = new User(null, username, 
                    User.STATUS_UNCONFIRMED, firstName, lastName, 
                    email, password);
                dao.putUser(user);

We put the user in the datastore, with a status of User.STATUS_UNCONFIRMED. This status indicates that the account has been created, but the user has not yet clicked the link included in the email we're about to send them. This code has a bug, in that the password is not passed through BCrypt before storage. We'll fix this as we come back and fix this class up.

Properties props = new Properties();
                Session session = Session.getDefaultInstance(props, null);

                String msgBody = "Thank you for registering a VolunteerIM "
                   + "account!  Please follow the link below to confirm "
                   + "your account:\n\n";
                Random r = new Random();
                msgBody += "http://lisedexvolinfomantest/volinfoman/emailConfirm?code="
                    + Long.toString(Math.abs(r.nextLong()), 36)
                    + "\n\n";
                msgBody += "Note: Please do not reply to this address, as "
                    + "email is thrown away.  If you did not set up a "
                    + "VolunteerIM account, please ignore this email, as the "
                    + "account will be removed automatically in a week.\n";

                try {
                    Message msg = new MimeMessage(session);
                    msg.setFrom(new InternetAddress("admin@lisedex.com", 
                        "VolunteerIM Confirmation"));
                    msg.addRecipient(Message.RecipientType.TO,
                             new InternetAddress(email, firstName + 
                                 " " + lastName));
                    msg.setSubject("VolunteerIM account confirmation");
                    msg.setText(msgBody);
                    Transport.send(msg);
                } catch (AddressException e) {
                    output.println("Bad email address.  Please try again. " +
                        e.toString() + "</body>");
                    log.info("AddressException sending confirmation email: " +
                        e.toString());
                    return;
                } catch (MessagingException e) {
                    output.println("Error sending confirmation email.  Please try again. "
                        + e.toString() + "</body>");
                    log.info("MessagingException sending confirmation email: "
                        + e.toString());
                    return;
                }

        output.println("We have sent a confirmation email to " 
             + email + ".  It should arrive shortly.  As soon as you receive " 
             + "it, please <a href=\"/\">return to the front "
             + "page to log in.</a>");
        }
}

Google's App Engine has an API for sending emails which uses the JavaMail API, but we just use a tiny subset.

We need a reference to a mail Session, which we use to build a MIME compatible email. First, we build a quick message body, which contains a link with a random string that we'll use as a confirmation code.

When we set the address that the message will come from, it has to be set as an email address that is listed in the App Engine dashboard as a collaborator on the project. I found this the hard way, after a MessagingException kept getting thrown during testing. The code worked fine on the local development server, but when deployed it choked.

Then we specify the recipient and subject, and attach the message body we already generated.

We can still get an exception when sending the email, if we use a To address App Engine doesn't like, or, as I found out, a From address that's not registered. If one of these pop up, we generate an error for the user, and exit the servlet. At this stage of the code, this will leave an UNCONFIRMED account in the datastore, with no confirmation email sent. Whooops.

If everything's gone according to plan, we let the user know that they should keep an eye out for the confirmation email.

Of course, right now, if the user were to click on the link in the email, we'd have to return a 404, since there's no servlet registered at /volinfoman/emailConfirm.

OK, do you at least have an email account you can read?


Before that, let's change the registration form to use the POST method. The GET method puts all of the user's input into the URL, which include the user's password in plaintext. So not only does it show in their address bar, it will live on forever in the server logs. Fortunately, HttpServlet makes this easy: just add method="post" to the form declaration in register.html, and change the doGet() method in Register to doPost(). The class library handles the details.

Now, we want to make sure that the email address the user entered is linked to an account they can read, like every other website in existence with individual accounts. We're sending a link with a code embedded to the user after they register, so we'll need a servlet to manage confirming the accounts. We could put the confirmation code for each user into the User class, and have the datastore index it so we could run a query, but we also want to expire accounts that haven't been confirmed after some length of time. So then we'd need to add an indexed expiration date field to the User class, and it starts to look cleaner to create a datastore table just for this purpose.

src/com/lisedex/volinfoman/shared/ConfirmationCode.java
public class ConfirmationCode implements Serializable {
        @Id
        private Long id;

        @Indexed
        private String username;

        @Indexed
        private String code;

        @Indexed
        private long expires;

        public ConfirmationCode() {
        }

        /**
         * Constructor
         * @param id Datastore primary key
         * @param username username associated with code
         * @param code confirmation code associated with username
         * @param expires expiration date for code in milliseconds
         */
        public ConfirmationCode(Long id, String username, String code, long expires) {
                setId(id);
                setUsername(username);
                setCode(code);
                setExpires(expires);
        }

        public Long getId() {
                return id;
        }

        public void setId(Long id) {
                this.id = id;
        }

        public String getUsername() {
                return username;
        }

        // ... etc, etc ... it's getters and setters all the way down
}


It's a pretty bare bones data structure, though we should probably add some input verification later to the setters. We also index all of the elements of the table. At different times we'll need to search by the code, and we'll also need to query for expiration times that are older than a certain time. Currently, the username does not need to be indexed, but we'll leave it for now.

In the earlier blog entry about Guice, I talked some about a BuildDB class which could delete all Users in the datastore, and just leave one admin account. Well, we also want the option of wiping out our confirmation code table while developing, which requires a new method in our DAO. We declare it in the Dao interface, and implement it in DaoGaeDatastore.

src/com/lisedex/volinfoman/server/DaoGaeDatastore.java
@Override
        public void deleteUser(Long id) {
                ofy().delete(User.class, id.toString());
        }

        @Override
        public void putConfirmationCode(ConfirmationCode code) {
                ofy().put(code);
        }

        @Override
        public void deleteAllConfirmationCodes() {
                ofy().delete(ofy().query(ConfirmationCode.class).fetchKeys());
        }

While we're in there, we added a couple of other methods that we'll use to work with the confirmation codes right now. We'll need a way to delete the users that we put into the datastore, if we get an exception during sending them their confirmation email. When the exception is caught, we want to throw away the new User object we put in the datastore, so the user can reuse it when they resubmit their registration. When calling this, we'll already have the User object, which includes the Id field, so we won't need to run a query; we can just straight up delete using an Objectify convenience method that builds a datastore Key from the provided class and its Id.

We'll also need to store new ConfirmationCode objects, and the deleteAllConfirmationCodes() method is pretty much ripped from the deleteAllUsers() method verbatim (just changing the class).

We also need to register the ConfirmationCode class with Objectify, so it knows how to handle it. We do this in the same place we register User: a static constructor in our DAO implementation.

ObjectifyService.register(ConfirmationCode.class);

Now, in our BuildDB servlet, we can simply call dao.deleteAllConfirmationCodes when we want, and clean out the table. "Dangerous Database Deletions" are my middle names.

Now, in our Register servlet, we want to add the confirmation code to the datastore.

src/com/lisedex/volinfoman/server/authenticate/Register.java
public static final int EXPIRATION_FIELD = Calendar.DATE;
    public static final int EXPIRATION_INCREMENT = 7;

We'll use the Java Calendar class to calculate our expiration date. This gives us flexibility to easily change the delay without having to recalculate how many milliseconds it is. The EXPIRATION_FIELD says which field we'll be incrementing, where DATE is days, but we could also use MONTH or HOUR or even YEAR. Calendar will handle the rollover and carrying the ones and the leap years and leap seconds and all of that. The EXPIRATION_INCREMENT, surprisingly enough, is how much that field will be incremented by.

Random r = new Random();
                String code = Long.toString(Math.abs(r.nextLong()), 36);
                Calendar expirationTime = Calendar.getInstance();
                expirationTime.add(EXPIRATION_FIELD, EXPIRATION_INCREMENT);

                ConfirmationCode confCode = new ConfirmationCode(null, username, 
                    code, expirationTime.getTimeInMillis());
                dao.putConfirmationCode(confCode);

We generate the confirmation code before the message body so we can insert it into the ConfirmationCode table in the datastore. Calendar.getInstance() gets a Calendar object representing the current time, and we add however much time we'd like to make our expiration time in milliseconds.

In both of the exception handlers for email transmission errors, we add a line to delete the users we just added to the datastore.

dao.deleteUser(user.getId());

You do know that anyone in the world can delete your datastore, right?


In the Guice blog entry, we moved BuildDB under control of Guice so we could inject our DAO implementation. In doing so, we lost the ability to use the App Engine user authentication to control access to the servlet. As we get further along, this becomes unacceptable, but I'm still not ready to build my own authentication mechanism into the servlet. We'll also need the authentication for protecting our cron jobs, so fixing this is not a waste.

In BuildDB, we no longer inject the Dao, we directly instantiate a DaoGaeDatastore. In the VolinfomanGuiceModule and VolinfomanServletModule, we pull out our definitions for BuildDB (and CacheStats, another servlet that I don't believe works at the moment).

war/WEB-INF/web.xml
<filter-mapping>
            <filter-name>guiceFilter</filter-name>
            <url-pattern>/volinfoman/*</url-pattern>
    </filter-mapping>


    <security-constraint>
        <web-resource-collection>
            <url-pattern>/admin/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>admin</role-name>
        </auth-constraint>
    </security-constraint>

    <servlet>
        <servlet-name>BuildDB</servlet-name>
        <servlet-class>com.lisedex.volinfoman.server.admin.BuildDB</servlet-class>
    </servlet>

        <servlet-mapping>
                <servlet-name>BuildDB</servlet-name>
                <url-pattern>/admin/builddb</url-pattern>
        </servlet-mapping>

In web.xml, we will change the Guice url-pattern from /* to /volinfoman/*, to allow us some granularity in defining which servlets get processed through Guice. To get BuildDB out of Guice's control, we'll need to change its URL from /volinfoman/admin/builddb to /admin/builddb.

We also set a security-constraint on the url-pattern /admin/* which requires the user have an administrator role for the application. If the user is not logged in, they will be presented with a login form from Google that allows them to log in with whatever account they've used as a collaborator for the project. If their Google account is not registered as a collaborator on the project, they will get an error and the servlet will not run. This is also used to protect cron jobs, as they will run as if run by an authenticated admin user.

Finally, we set the url-pattern that configures what URLs BuildDB processes. Since /admin/builddb matches the /admin/* security-constraint definition, it's protected by Google's authentication.

Get rid of expired confirmation codes


We want to run a cron job that will find any expired confirmation codes, and remove them. It will also need to look at the User associated with the code, and if it's still in the User.UNCONFIRMED state, the User needs to be deleted as well. The reason we double check this, is that I can imagine a time when someone emails support, and support confirms their account, but forgets to remove the associated confirmation code. If we didn't check the User's status, we could delete a confirmed account.

@Override
        public void expireCodesBefore(long now) {
                Query<ConfirmationCode> oldCodes = 
                    ofy().query(ConfirmationCode.class).
                        filter("expires <", now);
                for (ConfirmationCode code: oldCodes) {
                        User user = getUser(code.getUsername());
                        if (user != null) {
                                // make sure user is still in unconfirmed state
                                if (user.getStatus() == User.STATUS_UNCONFIRMED) {
                                        deleteUser(user.getId());
                                }
                        }

                        deleteConfirmationCode(code);
                }
        }

        @Override
        public ConfirmationCode getConfirmationCode(String code) {
                ConfirmationCode fetched = 
                    ofy().query(ConfirmationCode.class).
                        filter("code", code).get();
                return fetched;
        }

        @Override
        public void deleteConfirmationCode(ConfirmationCode code) {
                if (code != null) {
                        ofy().delete(code);
                }
        }


The expireCodesBefore() method takes a time, in milliseconds, and deletes all confirmation codes with an expiration time that comes before that time. This can be tested with a relational operator: if the expiration time is less than the time provided, it's expired.

The query does just that, and the query itself is Iterable, so we walk through it. For each expired code, we get the username associated with it, and pull in the User by that name. If the user exists, and the user's status is still unconfirmed, we delete the user. The expired confirmation code is deleted regardless of the user's state.

getConfirmationCode() will retrieve a confirmation code by the code field, instead of by Id. To do this, we need to run a query. Since it should only return one hit, we only return the first one found. If there were multiple entries with the same username, we'd only work with the first one.

Lastly, we add a method to delete confirmation codes.

In the Register servlet, we move most of the string literals scatted throughout the code into static Strings at the top of the class. This includes parameter names that are submitted by the registration form, as well as information used to build the email.

src/com/lisedex/volinfoman/server/authenticate/Register.java
User user = new User(null, username, User.STATUS_UNCONFIRMED, 
                firstName, lastName, email, null);
            dao.changeUserPassword(user, password);

We now build the User with a null password, and insert the User into the datastore using the password change method. This allows us to hash the password before storing it, fixing the bug we introduced in the early version of the code.

src/com/lisedex/volinfoman/server/cron/ExpireConfirmationCodes.java
public class ExpireConfirmationCodes extends HttpServlet {
        private Dao dao = new DaoGaeDatastore();

    private static final Logger log = Logger.getLogger(ExpireConfirmationCodes.class.getName());

        @Override
        public void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws IOException {

                Calendar now = Calendar.getInstance();
                log.info("Expiring expiration codes at " + Long.toString(now.getTimeInMillis()));

                dao.expireCodesBefore(now.getTimeInMillis());
        }
}

The ExpireConfirmationCodes cron job is just a stripped down servlet based on BuildDB. Since it accepts no parameters, we simply get the current time, and pass its value in milliseconds to the DAO method we wrote above for this purpose. Note that we're directly instantiating the DaoGaeDatastore again, as we need to bypass Guice since we need to put our cron jobs behind a security-constraint.

war/WEB-INF/web.xml
<!-- Cron jobs -->
        <security-constraint>
        <web-resource-collection>
            <url-pattern>/cron/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>admin</role-name>
        </auth-constraint>
        </security-constraint>
  
        <servlet>
                <servlet-name>expireConfirmationCodes</servlet-name>
                <servlet-class>com.lisedex.volinfoman.server.cron.ExpireConfirmationCodes</servlet-class>
        </servlet>

        <servlet-mapping>
                <servlet-name>expireConfirmationCodes</servlet-name>
                <url-pattern>/cron/expireConfirmationCodes</url-pattern>
        </servlet-mapping>

We add /cron/* URLs to what we hide behind Google's authentication, and define the URL /cron/expireConfirmationCodes as the one which invokes our expiration servlet.

war/WEB-INF/cron.xml
<cronentries>
        <cron>
                <url>/cron/expireConfirmationCodes</url>
                <description>Expire confirmation codes every day</description>
                <schedule>every day 02:00</schedule>
        </cron>
</cronentries>

The cron job definition specifies what URL gets called at what frequency. If you use a frequency like "every 5 minutes", the job is started 5 minutes after the last job completed. For example, if the job took 1 minute to run, the first job would start at 01:00, the next run at 01:06, the next at 01:12, and so on. If you wanted the jobs to start at 01:00, 01:05, and 01:10, you would need to add the keyword synchronized to the schedule.

Lastly (aka FINALLY), we can process the confirmation link and login form


This has stretched a bit longer than I expected, but it's almost over.

src/com/lisedex/volinfoman/server/authenticate/ConfirmationCodeChecker.java
public class ConfirmationCodeChecker extends HttpServlet {
        private static final String ACCOUNT_NEW = "Sorry, the account you're trying" +
           " to confirmed has not reached the point where it can be confirmed.  " +
           "Unfortunately, the only way to resolve this is to contact our support" +
           " department, or <a href=\"/register.html\">apply for a new account</a>." +
           "  We apologize for the inconvenience.";

        private static final String ACCOUNT_INVALID = ""; // another message
        private static final String ALREADY_CONFIRMED = ""; // another message
        private static final String ACCOUNT_CLOSED = ""; // another message
        private static final String BAD_CONFIRMATION_CODE = "";
        private static final String CONFIRMATION_SUCCESS = "";

        @Inject
        private Dao dao;

        private static final Logger log = Logger
                        .getLogger(ConfirmationCodeChecker.class.getName());

        private static final String UNSAFE_ERROR = "<span style=\"color: #ff0000;\">" +
            "There is a problem with the link used to confirm your user account." +
            "  Please try clicking the link again, and if the problem continues, " +
            "return to the home page and request that the email is sent again.  " +
            "Or you can contact support.  Sorry for the inconvenience!</span>";

        @Override
        public void doGet(HttpServletRequest req, HttpServletResponse resp)
                        throws IOException {
                // standard stuff
                output.println("<head><title>VolunteerIM account confirmation</title></head>");
                output.println("<body>");

                output.println("<h2>VolunteerIM account confirmation</h2><p>");

                String username = req.getParameter("username");
                String code = req.getParameter("code");

                log.info("Confirmation request with username " + username
                                + " and code " + code);

                if (!StringSafety.isSafe(username)) {
                        output.println(UNSAFE_ERROR + "</body>");
                        return;
                }

                if (!StringSafety.isSafe(code)) {
                        output.println(UNSAFE_ERROR + "</body>");
                        return;
                }

                ConfirmationCode testCode = dao.getConfirmationCode(code);
                if ((testCode == null) || (testCode.getUsername() == null)
                                || (testCode.getCode() == null)) {
                        output.println(BAD_CONFIRMATION_CODE + "</body>");
                        return;
                }

                User fetched = dao.getUser(testCode.getUsername());

                if (fetched.getStatus() == User.STATUS_UNCONFIRMED) {
                        fetched.setStatus(User.STATUS_CONFIRMED);
                        dao.putUser(fetched);

                        // eliminate confirmation code from datastore, as we're
                        // done with it
                        dao.deleteConfirmationCode(testCode);

                        output.println(CONFIRMATION_SUCCESS + "</body>");
                        log.info("Confirmed username " + fetched.getUsername());
                        return;
                }

                if (fetched.getStatus() == User.STATUS_CLOSED) {
                        output.println(ACCOUNT_CLOSED + "</body>");
                        return;
                }

                if (fetched.getStatus() == User.STATUS_CONFIRMED) {
                        output.println(ALREADY_CONFIRMED + "</body>");
                        return;
                }

                if (fetched.getStatus() == User.STATUS_INVALID) {
                        output.println(ACCOUNT_INVALID + "</body>");
                        return;
                }

                if (fetched.getStatus() == User.STATUS_NEW) {
                        output.println(ACCOUNT_NEW + "</body>");
                        return;
                }
        }
}

This servlet is under Guice's control, so its URL is defined in VolinfomanGuiceModule and VolinfomanServletModule. In this case it's /volinfoman/emailConfirm, as specified in the email sent to the user.

We define a bunch of messages that may get sent to the user, for different states of the User status, or malformed URL parameters. We get both a username and code from the URL, which we check for bad data, and also use to cross check whether the code matches the specified username. If it does, we pull up the User, and based on its status, we return different messages.

If the User was previously unconfirmed, we tell them it's now confirmed, we mark it as such in the datastore, and they can now log in from the home page. If it was closed, we let them know they can register for a new account, or contact support to find out why it was closed. Already confirmed Users get told they can go ahead and log in, and invalid and new users are told to contact support or register new accounts. In the code above, I've stripped the messages since they're pretty long, but they're available in the code in the repository at github.

src/com/lisedex/volinfoman/server/authenticate/Login.java
public class Login extends HttpServlet {
        @Inject
        Dao dao;

        private static final Logger log = Logger.getLogger(Login.class.getName());

        @Override
        public void doPost(HttpServletRequest req, HttpServletResponse resp)
                        throws IOException {

                // standard stuff

                String username = req.getParameter("username");
                String password = req.getParameter("password");

                if ((username == null) || (password == null)) {
                        output.println("<head><title>VolunteerIM login</title></head>");
                        output.println("<body>Please fill out both username and " +
                            "password fields.</body>");
                        return;
                }

                if (!StringSafety.isSafe(username)) {
                        output.println("<head><title>VolunteerIM login</title></head>");
                        output.println("<body>Username invalid, please go back and " +
                            "try again.</body>");
                        return;
                }

                if (!StringSafety.isSafe(password)) {
                        output.println("<head><title>VolunteerIM login</title></head>");
                        output.println("<body>Password invalid, please go back and try" +
                            " again.</body>");
                        return;
                }

                if (dao.checkUserPassword(username, password)) {
                        if (dao.getUser(username).getStatus() == User.STATUS_CONFIRMED) {
                                HttpSession session = req.getSession();
                                resp.sendRedirect(resp.encodeRedirectURL("/Volinfoman.html"));
                                session.setAttribute(Session.AUTHENTICATEDUSER, username);
                                return;
                        } else {
                                output.println("<head><title>VolunteerIM login</title></head>");
                                output.println("<body>INSERT CONFIRMATION MESSAGE HERE</body>");
                                return;
                        }
                } else {
                        output.println("<head><title>VolunteerIM login</title></head>");
                        output.println("<body>Username and password do not match." +
                            "  Please try again.</body>");
                        return;
                }
        }
}

For the login form, we have a Login servlet. I've stripped out some messages and some of the boilerplate code I've been using in all of these servlets. We check the submitted username and password for safety, and then pass them to our previously (way back in the day) developed password checking code in the DAO. If it's a match, we also check the User's status to make sure it's been confirmed. If it has, we set a cookie with the HTTP session identifier, mark it in App Engine's session table as an authorized user, and redirect them to /Volinfoman.html, which is the entry point to our GWT application. Currently, there is no testing whether the browser visiting /Volinfoman.html is authenticated, so anyone can visit it directly, but this will be rectified in the next bit of code.

Whew


I realize this is way too long, and maybe showing the revisions as I was figuring this stuff out is not helpful, but I wanted to give a decent introduction to some of the code that will run the site behind the scenes. I've been focusing almost exclusively on GWT code, and as I described above, I'm realizing something that I should have realized a long time ago (except I was blinded by GWT's novelty). I should have realized that GWT's not everything.

Tuesday, July 20, 2010

Guice

NOTE: There is an intermediate stage for the project between the last posting and this one. In it, I add a servlet that will populate the datastore with sample data, optionally deleting the datastore first. It is protected by web.xml directives that no longer work after moving the servlet to Guice, but it's available as tag "add-objectify" on github.

Using Guice to inject an appropriate Dao is kind of a no-brainer goal. Use it to inject one that uses the App Engine datastore for production, and one that's got a dummy at the back end for testing.

Prepare to be Guiced


We need to make a Data Access Object interface that the methods needing it can use. The way that makes most sense to me is to rename our current DAO class to DaoGaeDatastore (correcting the capitalization to match the Java naming conventions), and extract from that a new Dao interface.

Eclipse makes this really easy to accomplish. The Refactor->Rename... menu item handles renaming the class, as well as updating all references to it in the code to the new name. The Refactor->Extract Interface... applied to DaoGaeDatastore pulls out the interface Dao, also with no real trouble. While I was at it, I removed the extra Objectify object I had added to the DAO, and used the ofy() method implemented by its parent DAOBase.

To the interface and implementation class, I added a method named deleteAllUsers(), which does exactly what you'd expect based on the name.

com/lisedex/volinfoman/server/DaoGaeDatastore.java
@Override
        public void deleteAllUsers() {
                ofy().delete(ofy().query(User.class).fetchKeys());
        }

One of the Objectify.delete() methods accepts an iterable collection of objects that can be a mix of Keys and POJOs (Plain Old Java Object). Executing a query() on User.class will return all Users, and the Query.fetchKeys() method will return an iterable collection of their Keys. We can just pass this collection to Objectify.delete(), and all of our Users in the datastore disappear.

We can now convert our BuildDB class, which was built between the last blog entry and this one, to use Dao.deleteAllUsers(), and remove its dependency on an Objectify object.

Let the Guicing commence


We need the guice-servlet jar.

I used the Guice integration documentation to see how to get Guice set up for the App Engine environment. All servlets where we want to use Guice need to be moved from their web.xml declarations into Guice module configurations. Also, all servlets must be have the Singleton scope, so we can either use the @Singleton notation in the class definitions themselves, or follow the design philosophy we used for Gin and declare them all in a Guice module. I chose the latter for consistency.

First we build an AbstractModule called VolinfomanGuiceModule. Its sole function is to override the configure() method to declare our Guice object bindings.

com/lisedex/volinfoman/server/guice/VolinfomanGuiceModule.java
public class VolinfomanGuiceModule extends AbstractModule {
        @Override
        protected void configure() {
                // Servlets
                bind(UserServiceImpl.class).in(Singleton.class);
                bind(BuildDB.class).in(Singleton.class);
        }
}

Since all servlets need to have Singleton scope, and we're not injecting them with replacement objects, this is all the binding we need.

If you've looked at the code before now, you'll notice we're using a library called gwt-log with a remote logging servlet that's been declared in web.xml. We're not moving this to the Guice configuration because it doesn't need Guice injection right now, and it also produces a warning when it's not declared in web.xml. This warning problem is corrected in r504 of gwt-log, but I'm only using the release version.

Next, we need a ServletModule that sets up what URLs each servlet handles, so we build VolinfomanServletModule and override configureServlets().

com/lisedex/volinfoman/server/guice/VolinfomanServletModule.java
public class VolinfomanServletModule extends ServletModule {
        @Override protected void configureServlets() {
                serve("/volinfoman/user").with(UserServiceImpl.class);
                serve("/volinfoman/admin/builddb").with(BuildDB.class);
        }
}

Each serve() call tells Guice which URL to map to which servlet class. Each servlet can handle multiple URLs through multiple calls to serve().

Finally, we need a GuiceServletContextListener that provides a Guice Injector that knows about the modules so it can configure the injection properly.

com/lisedex/volinfoman/server/guice/VolinfomanGuiceServletContextListener.java
public class VolinfomanGuiceServletContextListener extends
                GuiceServletContextListener {
        @Override
        protected Injector getInjector() {
                return Guice.createInjector(
                                new VolinfomanServletModule(),
                                new VolinfomanGuiceModule());
        }
}

In web.xml we need to remove references to the servlets we're configuring through Guice, and add the configuration for Guice in their place. After taking out the BuildDB and UserServiceImpl declarations, but leaving the RemoteLoggerServiceImpl for gwt-log, we put in the Guice code.

war/WEB-INF/web.xml
<!-- Configure Guice servlet, other servlets configured in
                 VolinfomanServletModule -->
        <filter>
                <filter-name>guiceFilter</filter-name>
                <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
        </filter>

        <filter-mapping>
                <filter-name>guiceFilter</filter-name>
                <url-pattern>/*</url-pattern>
        </filter-mapping>

        <listener>
                <listener-class>com.lisedex.volinfoman.server.guice.VolinfomanGuiceServletContextListener</listener-class>
        </listener>

We set up a GuiceFilter with a URL pattern that describes which URL will be processed by Guice. We also plug our GuiceServletContextListener as a listener so Guice gets configured when the application is deployed.

Moving the BuildDB servlet to Guice configuration stops the authentication we had set up through a <security-constraint> in the servlet container. We'll have to add security in the code itself later, but for now the BuildDB servlet is open to the world.

Guiced!


All that set up for what will appear to be a pretty small payoff, but we're ready to use Guice anywhere we want in our servlets, as well as Gin in our GWT client.

We want to inject an instance of DaoGaeDatastore in place of fields declared as Dao in our servlets. First we need to configure this in VolinfomanGuiceModule.

com/lisedex/volinfoman/server/guice/VolinfomanGuiceModule.java
// Data providers
            bind(Dao.class).to(DaoGaeDatastore.class).in(Singleton.class);

After adding this to the configure() method, a DaoGaeDatastore singleton will be provided to any servlet that has a class field of type Dao that we also annotate with @Inject. So we need to inject it in UserServiceImpl.

com/lisedex/volinfoman/server/UserServiceImpl.java
@Inject
    private Dao dao;

This replaces the previous declaration for dao, and tells Guice to do the injection for that field. The rest of the class stays the same, since we were already using the Dao interface to define our interaction with the datastore.

In BuildDB we remove the local variable dao in doGet(), and use the same code as above to declare it as a class variable that needs injection.

That's it. The project is now Guicified.

Using Objectify to access the datastore

There are several options to choose from when deciding how you want to access the App Engine datastore. Two options are Java Data Objects (JDO) and Java Persistence API (JPA); both are from Sun and are in the Java SDK. From searching around the web, the consensus seems to be that both are too heavyweight for most App Engine projects. They are, however, both standards, and JDO is datastore agnostic, which would make moving your application off of the App Engine platform somewhat easier. However, you still are stuck with the limitations of the GAE datastore, so it's not quite so easy bringing JDO code into your GAE project.

Open source alternatives for Google App Engine


Two GAE specific open source projects are Objectify and Twig. Out of the two, Objectify seems simpler and more aligned with what's actually happening in the datastore. As I learn GAE, I feel it's somewhat imperative to not have the details of the datastore hidden from me. It's also modeled after the GAE Python library, which seems pretty clean. And, last but not least, your data classes can be passed through GWT RPC without modification. Perhaps in the future I'll come to a different conclusion if I get tired of having to write too much in the way of nuts and bolts that Twig handles automatically. Twig also supports parallel queries and merging OR queries, both of which could be pretty nice.

Hearing about the different design philosophies straight from the horses' mouths gave me some good information I needed to make this decision, too.

The Objectify concepts documentation is a good starting point for understanding both Objectify, and the GAE datastore.

Adding Objectify to VolInfoMan


Adding Objectify to the project leads us to the first time that we need a servlet running on App Engine. The servlet will simply provide a front end to Objectify and the datastore by responding to GWT RPC calls.

The code for this state of the project is available as tag "add-object-step1" on github.

He's not any kind of program, Sark. He's a User.


The first step is to define the object we want to pass back and forth between our GWT code and the GAE servlet. To continue the login page we've been working on, we'll need a User so we can authenticate the session. Since the User will be shared between GWT and GAE, we'll put it in the shared package.

(I'm leaving out the package and import statements to conserve space)

com/lisedex/volinfoman/shared/User.java
public class User implements Serializable {
        @Id
        private Long id;
        @Indexed
        private String username;
        @Indexed
        private long status;
        @Unindexed
        private String firstName;
        @Unindexed
        private String lastName;
        @Unindexed
        private String email;
        @Unindexed
        private String password;

Objects that will go through RPC need be Serializable. Later on, I'll probably add the @Cached annotation to the class so that it will automatically be cached by GAE's memcache.

You can only run queries on the GAE datastore against fields that are indexed. More specifically, you need an index for every query you intend to run, so by default all class fields are indexed to make it easier to query on any specific field. However, according to the Objectify best practices documentation, each property that is indexed requires a separate write to the index, which won't add to latency (writes are done in parallel), but will add to the CPU time used by the application. So instead, I explicitly declare which fields are to be indexed, and which are not. The same could be achieved by declaring the whole class @Indexed and only specifying the @Unindexed, or vice versa, but I like to explicitly declare each for easier reading. The field to be used to create the Key for the object is annotated with @Id.

I put in a couple of getter/setters, and a toString() method for easy logging. It will need to be fleshed out more later.

GAE, we need to have a serious talk. - Love, GWT


Next, we need to define the interface our client uses to access the servlet. I put GWT code for handling data into com.lisedex.volinfoman.client.data, so I define a UserService interface in that package.

com/lisedex/volinfoman/client/data/UserService.java
@RemoteServiceRelativePath("user")
public interface UserService extends RemoteService {
        User getUser(Long id);
        User getUser(String username);

        void putUser(User user);
}

The important part is that we declare what URL we'll be using to access the RPC servlet using the @RemoteServiceRelativePath annotation. The interface itself extends RemoteService, which all GWT RPC client interfaces should extend, and then we add the RPC functions we want to support. I want to support grabbing a User by name or id number, or putting a User object back into the datastore.

If you're using Eclipse, it will complain about the lack of a UserServiceAsync interface, and will build it for you automatically if you let it. It's basically the same as above, but doesn't need to extend RemoteService or declare a @RemoteServiceRelativePath. You can grab the complete code from github, as shown above.

In the server package, we need a servlet class that implements the UserService interface we just defined.

com/lisedex/volinfoman/server/UserServiceImpl.java
public class UserServiceImpl extends RemoteServiceServlet implements
                UserService {

    private DAO dao = new DAO();

    public User getUser(String username) {
            return dao.getUser(username);
    }
}

The real code has stub implementations for getUser(Long id) and putUser(User user) since we're not using them for now. We want to abstract away how we'll be accessing the datastore in case we need to change it, so we put actual interaction in a Data Access Object called...DAO.

com/lisedex/volinfoman/server/DAO.java
public class DAO extends DAOBase {
        static {
                ObjectifyService.register(User.class);
        }

        private Objectify ofy;

        public DAO() {
                ofy = ObjectifyService.begin();
        }

We don't have to extend the DAOBase class, but it gives us a couple of functions that we can use without coding, such as a lazily instantiated Objectify object. Of course, I didn't know that at the time I wrote the code, so I created my own. Oops.

You need to register the classes you'll be using with Objectify, and calling ObjectifyService.begin() returns an Objectify object we'll use to interact with the datastore.

public User getUser(String username) {
                User fetched = ofy.query(User.class)
                    .filter("username", username).get();
                return fetched;
        }

        public User getOrCreateUser(String username) {
                User fetched = ofy.query(User.class)
                    .filter("username", username).get();
                if (fetched == null) {
                        fetched = new User(null, username, 
                            User.STATUS_INVALID, null, null, null, 
                            null);
                        ofy.put(fetched);
                }
                return fetched;
        }

        public void putUser(User user) {
                ofy.put(user);
        }
}

To get a User by username, we need to execute a query on the datastore for all User objects, and filter the results by the username field. If no such object is in the datastore, the get() method will return a null.

Writing the object is easier, since we already know the Key for the object, as it's encoded in the class (User.class, and Long id). Just pass the object to Objectify's put() method. If the id field in the object is of type Long, and its value when passed to put() is null, Objectify will automatically generate an id for the object. If the id is of type long or String, the developer is responsible for that themselves.

The getOrCreateUser() function should be modified to use the get() and put() methods in DAO. Another oops. And I need to add more data checking, such as if the User sent to put() is null.

Make the Login button do something


Now we need to wire this stuff into the user interface, so that when we hit the Login button, we actually go out to the datastore and try to retrieve the appropriate User.

com/lisedex/volinfoman/client/DefaultHomepage.java
class MyHandler implements ClickHandler {

    @Override
    public void onClick(ClickEvent event) {
        sendStatus.setText("Sending..." + username.getText() +
                           "/" + password.getText());
        sendButton.setEnabled(false);
        userService.getUser(username.getText(),
            new AsyncCallback<User>() {
                  public void onFailure(Throwable caught) {
                      sendStatus.setText(sendStatus.getText()
                                 + "   FAILED");
                      sendButton.setEnabled(true);
                  }

                  @Override
                  public void onSuccess(User result) {
                      if (result == null) {
                             sendStatus.setText(sendStatus.getText() 
                                 + "    NO SUCH USER");
                             sendButton.setEnabled(true);
                             return;
                      }
                      sendStatus.setText(sendStatus.getText()
                          + "    SUCCESS: " + result.toString());
                      sendButton.setEnabled(true);
                  }
              });
    }
}

sendButton.addClickHandler(new MyHandler());

We obviously have not implemented the MVP model, as all of this stuff is in our view. In the ClickHandler inner class, we call the UserService.getUser() asynchronous method with an AsyncCallback inner class that will handle what happens when the RPC call returns.

If the RPC call fails, onFailure gets called with an exception. This doesn't happen if the username doesn't exist in the User indexes; it only happens with the client is not able to access the servlet for some reason. onSuccess is called with a User object when the RPC call works. The result is null if no such User was found, otherwise it's populated with all stored fields for the object.

Next up: Guice, security


Guice is the basis for Gin, except Guice provides dependency injection for Java generally, where Gin is for GWT. DAO's are a perfect place to apply dependency injection, since we may want to use the real datastore back end, or a dummy used for testing. We'll cover that in the next installment.

Also, there's no security or authorization needed to call any of the RPC functions. Anyone that wants can read or write any User object to my datastore, even if they're not using my client application. We'll, uh, get to that sometime.

Sunday, July 18, 2010

Dependency injection and Gin

I was coming across the phrase "dependency injection" quite a bit while reading articles about GWT and MVP, and references to the Guice and Gin libraries coming out of Google. I figured it was some new programming paradigm and that I was hopelessly out of date not knowing what it was. The wikipedia entry didn't really help clear it up, nor did other articles I read. I kept getting the feeling that I was missing something, and that the concept wasn't really something new.

Turns out I was missing something, all right


I was missing that DI is giving a name to something that I and every other object oriented developer have been doing for years.

The short summary in this great article is what finally made me realize that I could stop trying to make it more complicated than it was: "Dependency injection means giving an object its instance variables. Really. That's it." If you're having trouble with the concept, James Shore's article is invaluable.

A conceptual example would be something like: you have an object that relies on a reference to some sort of data provider. In production, the provider will be a database back end, but during testing you want to mock up a provider that is always up and you can precisely control what errors it has.

You might solve this by constructing a factory that spits out the correct type of provider, and your object can ask that factory to give it a reference to the proper kind of provider. This works, but your testing has to construct, tear down, and reset the factory to the previous state between each test. You also have to write a lot of boilerplate code for each of these factories.

DI refers to giving the object a reference to the proper provider, which, during testing, allows you to build a new provider instance which you pass to the object during each test. As you exit the test, the object and provider are dereferenced automatically, saving you the cleanup. But in the code itself, you're now either passing provider references possibly through layer after layer of constructors, or you're building factories for the initial object which get the proper provider and pass it to the object, and then return the completed object.

Guice and Gin save you from all this repetitive factory building and wiring, and what provider each object needs can be declared in one place, or inline where the instantiated providers will be injected in the object.

I'm certainly not qualified at this time to discuss all of the nuances and capabilities of these libraries, since there are many different ways this concept could be used.

Instead, I'll talk about using Gin in this project


com/lisedex/volinfoman/Volinfoman.gwt.xml
<!-- Include Gin -->
<inherits name="com.google.gwt.inject.Inject" />
Adding those lines to your module's gwt.xml file, and adding the Gin and Guice jar files to your classpath, is all that it takes to enable the Gin annotations and compile time code generation.

If you go to the VolInfoMan project page on github, you can go to the basic-gin tag and download the source. The project is very, very basic at this point, and it's easy to find the one instance of using Gin.

As practice, I wanted to set up the home page you land on when loading the site to be capable of being changed by dependency injection. This will allow, later, changing the implementation of the page by making a new class that extends the skeleton Homepage class, and just changing the Gin binding in one place, and all references to that Homepage will be using my new implementation. Look ma, no factory!

com/lisedex/volinfoman/client/Homepage.java
package com.lisedex.volinfoman.client;

import com.google.gwt.user.client.ui.Composite;

public class Homepage extends Composite {
}

First we define our skeleton Homepage class, which will be added to our RootPanel later in onModuleLoad() (actually onModuleLoad2() due to our use of the gwt-log library).

com/lisedex/volinfoman/client/gin/VolinfomanGinjector.java
package com.lisedex.volinfoman.client.gin;

import com.google.gwt.inject.client.GinModules;
import com.google.gwt.inject.client.Ginjector;
import com.lisedex.volinfoman.client.Homepage;

@GinModules(VolinfomanModule.class)
public interface VolinfomanGinjector extends Ginjector {
 Homepage getHomepage();
}

We extend the com.google.gwt.inject.client.Ginjector class and use the @GinModules annotation to specify what class contains the binding configuration. We also define the getHomepage() injector method, which we need when using Gin in our application initialization code, because Gin is working at compile time to generate JavaScript, unlike Guice. Other dependencies that operate below our initialization code will be injected automatically, and won't require this type of method.

com/lisedex/volinfoman/client/gin/VolinfomanModule.java
package com.lisedex.volinfoman.client.gin;

import com.google.gwt.inject.client.AbstractGinModule;
import com.lisedex.volinfoman.client.DefaultHomepage;
import com.lisedex.volinfoman.client.Homepage;

public class VolinfomanModule extends AbstractGinModule {
        @Override
        protected void configure() {
                bind(Homepage.class).to(DefaultHomepage.class);
        }
}

We extend AbstractGinModule to declare our bindings for injection. Using AbstractGinModule instead of GinModule allows us to drop the binder.bind() syntax in favor of bind(). In the above code, we're declaring that when our code asks for a Homepage object, it will get a DefaultHomepage instead.

com.lisedex.volinfoman.client.DefaultHomepage actually contains no references to Gin. It extends Homepage but doesn't need to know anything about injection.

com/lisedex/volinfoman/client/Volinfoman.java
package com.lisedex.volinfoman.client;

import com.lisedex.volinfoman.client.gin.VolinfomanGinjector;
// import GWT objects here...

public class Volinfoman implements EntryPoint {
        public void onModuleLoad() {
                // we set up gwt-log here and
                // use a DeferredCommand to execute
                // onModuleLoad2() */
                // ...
        }

        private void onModuleLoad2() {
                // Create a ginjector
                VolinfomanGinjector ginjector = 
                    GWT.create(VolinfomanGinjector.class);
                // Add the homepage to the rootpanel
                RootPanel.get().add(ginjector.getHomepage());
        }
}

And our GWT entry point creates the Ginjector, and we use the injector method getHomepage() to inject an instance of DefaultHomepage, thanks to the binding we set up in VolinfomanModule. As mentioned above, we have to use an injector method due to current limitations in Gin.

That's it. Remember to grab the basic-gin tag of the source code from github for a compile-ready Eclipse project where you can immediately play with Gin.

Other Gin information


Gin supports some of the same annotations as Guice, such as @Inject, @ProvidedBy, @Singleton, @ImplementedBy, all of which allow you to move much of the binding information out to the source where the bindings occur. Much of this is to provide an alternative to using a GinModule to declare all of the bindings in one place; the latter is the option I prefer, but it's personal preference for the most part.

Some of the other bind() syntaxes are:
bind(Something.class).toProvider(SomethingProvider.class);
bind(Something.class).to(SomethingImplementation.class)
    .in(Elsewhere.class);
bind(Something.class).annotatedWith(SomethingAnnotation.class);
    .to(SomethingImplementation.class);
bind(Something.class).to(SomethingImplementation.class)
    .in(Singleton.class);

Line 1: When Gin injects an instance of a class normally, it uses the class's default constructor. If you need to give extra information to a constructor, you can use the toProvider() syntax. Gin will inject an instance of Something from the SomethingProvider wherever you need a Something class.

Line 2: If you only want a binding to apply in Elsewhere, instead of globally, you can use this syntax to specify that scope.

Line 4: You can also set up custom annotations. When you want multiple bindings for one type, you can specify which binding to use by setting up an annotation for each. The annotation and the type will uniquely identify which binding is appropriate. See the Guice wiki for more information.

Line 6: Gin's injector normally creates a new instance of each SomethingImplementation when it gets injected. However, sometimes you'll want to use the Singleton pattern, and only have one instance of SomethingImplementation running around. Remember that this is a Singleton per Ginjector, so if you have multiple Ginjectors (which, if you do, you probably need to double check your code) there will be one instance of the SomethingImplementation for each.

There's a bunch more that can be done with Gin; this is obviously only scratching the surface. Remember that Gin does the injection at compile-time, so there should be almost no overhead for using it, and it can save you a lot of repetitive coding. To understand all of the capabilities, it would behoove you to read the Guice User's Guide, the Gin tutorial, and the compatibility information between Gin and Guice. The documentation for Guice is much more thorough, but you have to know which ideas can be used in your GWT code. Guice will be used later for our server side code which runs under GAE.