Showing posts with label app engine. Show all posts
Showing posts with label app engine. Show all posts

Monday, June 15, 2009

Executing A FreeMarker Template

In our front page servlet, we need to execute the FreeMarker template we created.

We start by creating a Configuration instance. This only needs to be done once per application, so we can use a singleton pattern (remember the PMF class?) Only this time we don't have a utility class provided to us, so you'll have to write your own. Follow the PMF pattern and create a singleton for getting Configuration instances.

You'll end up with something like this (I've left off the package and import statements to save space):


public class ConfigFactory
{
  private static Configuration configInstance = null;
  private ConfigFactory() {}
  public static Configuration get(ServletContext context)
  {
   if (configInstance == null)
   {
    configInstance = new Configuration();
    configInstance.setServletContextForTemplateLoading(context, "WEB-INF/templates");
    configInstance.setObjectWrapper(new DefaultObjectWrapper());
   }

   return configInstance;
  }
}


Note that I have it looking for templates in WEB-INF/templates. That gets templates out of the way, which is generally a good idea to keep things tidy. Now would be a good time to right click on WEB-INF and create a new folder named templates, and to drag Front.ftl into that new directory.

In our front page servlet, we can now use the singleton class to get a Configuration instance.


Configuration config = ConfigFactory.get(getServletContext ());


Now we need to create the data model for the template. In the case of our simplified front page, the data model just has a boolean named loggedIn. Before we can do that we need to know if they're logged in or not.

If they are logged in, we'll have their user id in the session. So let's get the session and check.


HttpSession session = req.getSession(false);


I pass false into getSession this time because if there isn't already a session, I don't want to create one. If no session already existed, getSession(false) returns null.


boolean loggedIn = false;

if (session != null)
  loggedIn = true;


We could very well have used getAttribute to get the actual user id and looked up the User record in the datastore, but this will do for the moment. Now that we have our loggedIn variable, let's create the data model:


Map root = new HashMap();
root.put("loggedIn", loggedIn);


That's it. A data model is nothing more than a map of values. You can nest maps inside the map to create objects with fields for the template to use.

Now we need to get the template:


Template temp = config.getTemplate("Front.ftl");


If you named your template something other than Front, you'll want to modify that. Now that we have the template, let's execute it:


PrintWriter out = resp.getWriter();

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


Note that printing the stack trace to the user's web browser isn't the best way to handle errors. We'll want to do something better than that later, but for now it'll serve.

We have one last piece before this will ever show "Sign Out". That's to cause the RPXResults servlet to redirect the user's browser back to the front page after the session has been set.

At the bottom of doPost in RPXResults, this should do it:


resp.sendRedirect("/front");


Assuming that /front is what you put in for the url mapping for your front page servlet.

You should now be able to run the application, click Sign In, go through the RPX process and end up back at the front page with the Sign Out link showing. This shows a very simple example of using templates to display pages with dynamic content. If our content is going to be updated according to user action, we'll use GWT widgets, but for simple content that stays the same once it's generated on the page, templates are a great option.

Installing FreeMarker

There are two pieces to install with FreeMarker. One is the server side code needed to allow the servlets to run template files. The other is the Eclipse plugin that provides support for writing template files.

Let's start with the plugin (you remember installing all those plugins earlier, right?). Go to this page and copy the link for the version of Eclipse you have (use the Stable Updates links). Install just the FreeMarker IDE from that site.

Restart Eclipse at the end, and we'll move on to the FreeMarker server libraries. Download the latest stable version at the FreeMarker download page. Unzip the file onto your desktop, and look for lib/freemarker.jar (the rest of the zip file is documentation that you may want to keep).

Copy freemarker.jar into the war/WEB-INF/lib directory of your project in Eclipse. Right click on the file, choose Build Path->Add to Build Path.

That's it, we can now both create template files and execute them from servlets. We'll see how in the next few posts.

UPDATE: If you're using more recent versions of GAE and Freemarker than are installed in the labs (very likely if you've installed the latest versions at home), there might be a conflict between them. If you get an error message when compiling code that uses Freemarker templates about TreeNode being a restricted class, then you have the versions that are not compatible.

There's a workaround here. The workaround is to to create a TextBlock.java file in the freemarker.core package (the thread linked to gives the code you put into that file). If you got it right, you should see, under your src directory in Eclipse, a freemarker.core package (at the same level as your project.server and project.client packages).

Note that to successfully copy the code from the thread, you need to click the Read More link at the bottom of that message (since not all the code shows in the thread view). Then, after you paste the code into Eclipse, you'll get some errors because of line wrapping in the thread. Just back the offending lines onto the end of the previous line to remove the wrapping, and it'll compile.

Eventually, this will be fixed in one way or another (probably with a Freemarker update), and your version of TextBlock.java can be removed.

A One Page Web Site

We'll now create a one-page web site that properly reflects the user's logged in status. Where our current first page has the "Sign In" link, that will be "Sign In" if the user is not logged in, or "Sign Out" if the user is logged in.

Our RPXResults servlet will do its thing silently, and then redirect back to the first page. We'll have to change the first page to be a servlet rather than a static HTML page, so that we can dynamically change it based on the user's logged in status.

Note that we could do the same thing with a static HTML page that included GWT components. We could in a GWT pane display the "Sign In" or "Sign Out" links, and use GWT calls to the server to see if the user is logged in or not. Eventually we'll get around to that sort of thing, but for now I'd like to keep it as simple as possible.

First step, change the main page of the site to be a servlet. Right click on war/WEB-INF/web.xml and choose Open With->Text Editor.

Enter the info for a new servlet (you remember how, right?) to be used as the main page. You don't need to have a servlet mapping for this servlet, but it might come in handy later to have it map to something like /front. Then copy the welcome-file-list section down to just before /web-app, and change the welcome file to be the name you gave to the servlet.

Now create the servlet (which you also remember, right?). Go ahead and put in the code to create the PrintWriter.

Let me describe the easy way (at least in the short term) to do this, which makes the code very ugly and the HTML almost impossible to maintain. Then we'll look at the hard way to do it, which makes the code nicer and the HTML easier to maintain.

The easy way is to output the HTML using our PrintWriter:


writer.println ("<html>");
writer.println ("<head>");
writer.println ("<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">");


Etc, printing the entire HTML file using the PrintWriter. Notice the need to escape the double quotes inside the output using a backslash. This method is easy, because we don't have to work with anything but the servlet, but it makes it nearly impossible to easily change the HTML later.

The harder way (in the short run at least) is to use a templating engine. A templating engine is server side code that allows us to write the HTML in a file of its own, with a mini-programming language for making decisions. The servlet will execute that template file and provide any information it needs to make decisions. The result is the HTML that should be sent to the client.

There are lots of templating engines out there. I'm going to use FreeMarker, which integrates well with Java servlets and Eclipse.

So before we can use FreeMarker, we have to install it and the Eclipse plugin for it.

Session Handling

Normal web pages are "stateless". This means that every time they're loaded is like the first. They don't keep any information around about the user loading them.

This doesn't work for web applications, where we do want to keep information about the user around from page to page. To carry information over from page load to page load, we need to create something called a "session".

A session is basically an id that gets sent to the browser and stored in a cookie. Future page loads on the same domain will send that session id along with the page request. The server then uses that session id as the primary key in a datastore lookup to load in any information you wanted to carry over from page load to page load.

By default, session support in the Java version of App Engine is not enabled. Right click on war/WEB-INF/appengine-web.xml and choose Open With->Text Editor. Just before the ending /appengine-web-app tag, put this line:


<sessions-enabled>true</sessions-enabled>


This makes the class HttpSession available to your servlets. The HttpSession class is how you'll set data on one page and get it on another page. Inside RPXResults.java, after we have the User instance, we can get the HttpSession instance like this:


HttpSession session = req.getSession ();


The HttpSession class then has methods for getting to data you've previously set, and for setting data. Think of it like a map between a property name and a property value. Use the setAttribute method to set property values, and the getAttribute method to get property values.

Another useful method on HttpSession is setMaxInactiveInterval, where you specify the number of seconds the session will live without activity (e.g. the timeout). Pass in a negative value to make the session live forever (or at least until the user clears their cookies).

What do we need to store in the session? Not much, really. The datastore already will have our User records (and other entity records we'll add later), so in the session we just need enough to get to the User in the datastore.

So let's store the user's primary key in the session. From there we can look up the rest of their fields.


HttpSession session = req.getSession();
session.setAttribute("userid", user.getId());


And that's it. In other code we can use getAttribute to fetch the user's id, and then use the datastore to fetch the full User instance for that id.

So the user is officially logged in at this point, although we don't have much of a web site yet to demonstrate that fact. So that's next, to develop a very simple web site that will reflect the logged in status of the user.

User Datastore Interaction

Okay, here's the complete code (in RPXResults.java) for creating users only if they don't already exist:


PersistenceManager pm = PMF.get().getPersistenceManager();

Query query = pm.newQuery("select from omega.server.User where identifier == identifierParam");
query.declareParameters("String identifierParam");

try
{
 List results = (List) query.execute(identifier);

 if (results.size() == 0)
 {
  User user = new User ();
  user.setIdentifier(identifier);
  pm.makePersistent(user);
 }
 else
 {
  User user = results.get(0);
 }
}
finally
{
 query.closeAll();
 pm.close();
}


We could do more about populating User fields from the RPX profile, but this is reasonably complete otherwise. Does this mean the user is logged in?

Unfortunately, no.

By the end of the code, we have loaded the User instance from the datastore (or created it). To get the other pages in the application, and the GWT widgets, to know about the user we have to start a session.

Next post, sessions.

Searching For A User

Searching for a user in the datastore uses the Query interface. We get a Query by aking for one from a PerstistenceManager. There are several ways to populate a Query...I'll use the SQL like form:


Query query = pm.newQuery("select from project.server.User where identifier == " + identifier);


Note the use of the project.server.User notation to say which class you want to load. Change the project to be the name of your project.

If your first thought on seeing that wasn't, "What about SQL injection attacks?", then you should read this tutorial.

In this particular instance, the likelihood of suffering an SQL injection attack is low, since the data is coming from a request to RPX. Nobody can just load up the RPXResults servlet in a browser and inject an arbitrary identifier.

But, it never hurts to be safe, so let's use a parameter to lessen the risk:


Query query = pm.newQuery("select from project.server.User where identifier == identifierParam");
query.declareParameters("String identifierParam");


Note that parameters may lessen your risk of an SQL injection attack, but it depends on the implementation of JDO. I'd like to think Google is on top of its game with App Engine security, but we should be wary of relying on that for pages that are susceptible to SQL injection. When we get to a page that's more vulnerable, we'll look at ways to protect the page.

Now that we have a Query, we need to execute it and provide the value for the parameter:


try
{
  List results = (List) query.execute(identifier);
}
finally
{
  query.closeAll();
}


We can then use normal List methods for iterating over elements of the list of Users that has been returned. Note that since our identifier field is not a unique field, the List could theoretically have more than one element. But we'll write the code so that we only have one User per identifier, so the List will either have zero elements (for a new user) or one element.

We'll put the pieces together in the next post.

Creating A New User

Back in RPXResults.java, we've gotten our identifier and need to create a User. With JDO, that's a two-step process. First we create the User instance and populate it. Second we store that data to the datastore.

Creating the User is nothing new:


String identifier = info.getElementsByTagName("identifier").item(0).getTextContent();
User user = new User ();
user.setIdentifier(identifier);


We could search through the profile data to see if any of the various name fields were provided and use those to pass to user.setName, but I'll opt for the simple route of asking them for their name later. For now we'll leave it null.

Now for storing the User to the datastore. We need to get an instance of a PerstistenceManager from the factory:


PersistenceManager pm = PMF.get().getPersistenceManager();


Then we call makePersistent:


try
{
  pm.makePersistent(user);
}
finally
{
  pm.close();
}


The odd try/finally usage is worth a comment. There's no catch block needed, because there are no checked exceptions thrown by makePersistent. So why a try block in the first place? I'd guess it's because makePersistent can throw some runtime exceptions, and the finally block is a way to ensure the manager gets closed even if a runtime exception is thrown.

That saves the User to the datastore. In the next post we'll add in querying the datastore to see if the user already exists, so we only create the user if this is their first time using our application.

Storing Data In App Engine

My students will have had a database course by now, so they'll be familiar with (or at least exposed to) SQL and relational database design.

The bad news is that App Engine doesn't support SQL and it isn't a relational database. Instead it supports an object oriented database and you use Java Data Objects to interact with it.

The good news is that this means you don't have to fool with a database design, you just write Java classes in a certain way, and App Engine takes care of the rest.

The bad news is that Java Data Objects use annotations, a Java feature you won't have seen yet. Annotations allow you to add features to a Java class without using inheritance.

The good news is that JDO does allow an SQL like syntax for querying, so that database course will come in handy (or maybe that's more bad news).

Enough of the good news/bad news bit. Let's dive into JDO.

An object that is stored into the database is called an entity. Entities have properties and a unique key (which can be autogenerated by App Engine, if you like). Oh, and we'll start to use the JDO terminology for database, which is datastore.

To specify a class as an entity, use the annotation @PersistenceCapable on the line before the class definition. For example, we'll need an entity to store information about a user (create this class in Eclipse in your project.server package):


@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class User
{
}


That marks User as an entity that can be stored in the datastore. We also have to mark each field in User that we want stored in the datastore as @Persistent, and one of them as a @PrimaryKey.

I know that I'll need an autogenerated user id as a primary key (because the identifier returned by RPX is too long to be suitable as a primary key), and I'll need some other basic info. Here's what I came up with as a first pass:


@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class User
{
  @PrimaryKey
  @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
  private Long id;
  
  @Persistent
  private String identifier;
  
  @Persistent
  private String name;
}


The valueStrategy argument on the id means it'll be automatically generated for me when I create new Users. Since the fields are private, I'll need public get methods for them, and set methods for the name and identifier. I won't show those here, but go ahead and add them to your version (this is a good time to figure out how to use Eclipse's Refactor->Encapsulate Field option to save yourself the typing).

To work with the datastore itself, we need an instance of PersistenceManagerFactory. The Google docs suggest using a singleton pattern for this, since the class is expensive to instantiate. Go ahead and use their PMF class as is in your project.server package.

In our RPXResults servlet, we'll need to use the identifier RPX provides to see if we already have the user in the datastore. If so, we'll load the existing data. Otherwise, we need to create the User instance and store it to the datastore.

We'll start in the next post with creating a new User and storing it to the datastore.

Thursday, May 21, 2009

User Authentication

Since we know our application will need to have registered users, I figured I'd start by implementing the user authentication framework.

There are several options, some of which can be used together.

Use OpenID

OpenID is a pretty cool mechanism that allows you to register on one web site, and use that id and password on another web site. So instead of registering with each web site, you only register the once. It's a lot like Google Accounts, but there's no centralized control over where you register. You can register on any OpenID enabled site, and that site then becomes your home site.

The problem with OpenID is that it's still very much a geeky sort of thing to use. I don't want to force non-technical community members to figure out OpenID in order to use my application. It'd be cool to allow OpenID for those who already have those IDs, but I don't want to require it.

On the other hand, the geeks at places like Google and Yahoo allow their ids to be used as OpenID ids, so people might already have an OpenID and not know it.

Use Google's Authentication

App Engine makes it nearly trivial to hitch on to the authentication Google uses for Gmail and other Google services. No code needs written to force someone to log in before seeing a specific page, and only a little code is needed to get the email of the currently logged in user. That email can then be used as a key into an application specific data store.

One problem is that people have to register for a Google Account if they don't have one...that isn't all that serious, since people would have to register on the web application anyway.

Another issue is that this doesn't support any OpenID account, just Google Accounts (which can also be used as OpenID accounts). So an OpenID user who used a different OpenID provider than Google would still have to register for a Google Account.

Maintain My Own Database

The traditional way of handling a web application is for that web application to maintain a list of registered users. A new user must register with the web application, and their user id and password is specific to that web application.

The advantage here is that I can write this so it plays well with OpenID, and have both. Since a Google Account also works as an OpenID account, I'd be automatically supporting those, too.

The disadvantage is that there's quite a bit of code to write, compared to the nearly zero effort of just supporting Google Accounts via App Engine.

What To Do?

Having talked about three options, I think I'll use a fourth.

RPX is a website that allows a site to piggy back on logins people already have, such as OpenID, Google, Yahoo, Facebook, etc. So someone could sign onto my site with their Facebook ID. The basic service is free, so no worries there.

The disadvantage to this is that I'm now dependent on a third party site for processing my user authentication. No doubt this opens up all sorts of security problems, but for the purposes of this course I can accept that. I'll talk at some point during the course about security concerns with web applications, and how to reduce security issues.

For a company, or a site that expected to have a huge user base, RPX might not be the best option (at least not the free version...but then a company could afford the paid version). But to get something up and running easily that allows access to a fairly large number of people, I'll go with RPX.

We'll start to work through the details of this in the next post.

Wednesday, May 20, 2009

Examining The Sample App

When we created our project in Eclipse, we got a sample GWT/App Engine application for free. It doesn't do much, but it's a good way of seeing the sorts of things we'll have to deal with in our own application.

App Engine works by means of Java Servlets. These are Java classes that are associated on the server with a specific URL. When a web browser asks the server for that URL, the Java class is run and it returns data back to the browser. That data may be a complete web page, or it may be smaller amounts of data.

GWT will call servlets in the server by asking for specific URLs. GWT can then parse the data sent back to figure out what to change on the current page.

In the Eclipse project, look under war/WEB-INF and open web.xml. Expand web-app and then servlet, and you'll see that the servlet named greetServlet maps to the Java class omega.server.GreetingServiceImpl. Expand servlet-mapping and you'll see that the servlet named greetServlet also maps to the URL /omega/greet (yours will have project names different from omega).

For servlet based projects, the web.xml file manages the mapping between URLs and Java classes.

You should also see an HTML file at the same level as WEB-INF. That's the HTML file that provides the container for the GWT app. If you look at it, you'll see that there are a couple of empty divs for the name field and the send button. The GWT code in Omega.java fills those in wtih an edit field and a button, and calls the server when the button is pressed.

Now look at Omega.java (again, the name of yours will depend on your project name). In the onModuleLoad method, you'll see what looks like Java Swing initialization. Note though the RootPanel.get lines. Those are actually adding user interface elements to the HTML page itself, in the divs with those specific ids.

Scroll farther down to the MyHandler nested class. This handles the click on the button, or the pressing of the Enter key. Both call sendNameToServer, which is just below them in the file. The line that starts greetingService.greet makes a call to the server. The onFailure method is run if that call fails for some reason. The onSuccess method is run if the call succeeds. On success a dialog box is shown that contains the HTML sent back by the server.

Now look at GreetingServiceImpl.java in the server folder. This is the class that gets called by the client. You can see it just returns some HTML with info about what browser they're running.

That's a quick tour through the sample app. Studying this will give you a better handle on what we'll be doing as we add our own functionality.

Teaching & Development Philosophy

Okay, one more post before I start writing some code.

My general teaching philosophy with this course is that we are learning how to develop web applications. We are not just learning GWT (which is the client side), and we are not just learning App Engine (which is the server side).

We're learning how those two tools (and a host of others) hook together to form a complete web application.

In these posts, I'm not going to cover the basics. If you're not in the course, and you're reading this, and you haven't done any Java Swing work before, head for a tutorial. That'll be important for understanding how to create a user interface in GWT.

There will probably be other things that I won't cover as well. I'll try to post tutorial links when I remember to do so.

Another important aspect of my development philosophy is that I favor having a working application at all times. I'm not going to write tons of code in GWT for the screens, and then move on to the server work. At every stage we will have a working application and full client/server interaction for the features we've implemented so far.

It may take a few blogs posts to get through a particular feature, but I believe strongly that having a working application is the best way to know if you're heading in the wrong direction early.

The first step of this project is going to be user authentication. At the end of that step I'll have a web server that can accept logins and registrations, even if it doesn't do anything else.

Okay, enough talking, the next post will start the technical bits. Promise.

Tuesday, May 19, 2009

Why GWT & App Engine?

I said last post that we didn't have any code written yet, and that's technically true.

We haven't written any code yet, but by creating a Web Application Project using GWT and App Engine, we do have a skeleton project that shows communication between a GWT client and an App Engine server. And it'll all run right on our machine from within Eclipse.

Start Eclipse and click on the project name for your project in the upper left pane. Then click on the toolbar icon that looks like a red suitcase with a G on it. On the next screen click Compile. That will take the GWT code and compile it down into Javascript.

Now if you right click on the project name and choose Run As->Web Application, a local web server will start with Java App Engine running, and the web page defined by our GWT application will open. Type in your name and click Send to see a full round trip to the server and back.

It's important to understand that all this is running on your local machine. We haven't signed up for App Engine space yet (and won't until we figure out what the project is!), and we haven't had to transfer anything to a web server. It's all local, and we can keep it local until we're ready for it to go online.

Okay, so on to the question, Why GWT? There are many reasons, but here are the important ones for this course.

1) My students already know Java, so they don't need to learn Javascript.

2) GWT takes care of browser compatibility

3) GWT limits the security concerns of web apps (to at least a manageable level)

4) It all works in Eclipse, which my students are already used to using

Why App Engine? We could write GWT apps that communicate with any server language, including PHP, Python, etc, hosted on any shared hosting account. We're using App Engine because:

1) With Java App Engine and Eclipse, it all integrates beautifully for testing locally

2) There's no cost for App Engine hosting at the basic level

3) If a student's project takes off, App Engine can scale with their success

Sure, I could have used a Javascript library on the client and PHP on the server, but I'd have lost at least some of the advantages of GWT and App Engine in doing so. This way, I'll know that students who complete the course will have a leg up on their colleagues who don't have this sort of experience.

Installing Eclipse

The IDE I'll be using for this project is Eclipse.

For the course, the computer labs will already have Eclipse installed and configured. Most of the students will also already have Eclipse installed on their home machines and/or laptops. But, they probably have the Eclipse IDE for Java Developers, not the one for Java EE Developers. We're moving into web programming now, so let's move to the version of Eclipse that has tools specifically for web programming (at this point, I have no idea if we'll need the extra tools or not...that's how software development goes when you're trying something new, you seem wise only after you've made your mistakes).

Head over to the Eclipse downloads page, and download the latest Eclipse IDE for Java EE Developers. Have some coffee, or take a walk in the sun, while you wait for the download to complete.

What the download gets you is a zip file. If you've never installed Eclipse before, just unzip this file somewhere (the root of your C: drive is traditional, but if you have another version of Eclipse there and don't want to overwrite it, anywhere will do). You'll end up with an Eclipse directory with a whole bunch of files and directories under it. One of those files immediately under it will be Eclipse.exe. Make a shortcut to that somewhere handy, like on your Desktop.

Start Eclipse, and wait for a bit more. When it asks you about the workspace, you can accept the default or change it. You should know where your workspace is if you aren't going to be using a hosted version control system, so you can regularly back up your code.

Now, for the plugins. Note that everything but the Google Plugin was part of the Pro Web 2.0 toolset, so credit goes to Jeff Dwyer for choosing them for his project. I'm just following his lead.

Google Plugin

This is an important one, since it takes what used to be a bunch of command line typing for managing GWT and App Engine projects and instead gives us Eclipse menus. See the Google page about installing this plugin. To find out what version of Eclipse you have (if you've forgotten what you downloaded), in Eclipse look at Help->About Eclipse Platform.

Once you figure out which of the URLs you need, copy that and then go into Eclipse's Help->Software Updates menu. Click on the Available Software tab, and then on the Add Site button. Paste in the URL from you copied from Google's page and click OK.

You should see now the option to download not only the plugin, but also the latest versions of GWT and Java App Engine. Go ahead and check all three and click the Install button. It'll take a few seconds to calculate dependencies, and then will display an Install wizard. Go ahead and click Next, and then accept the terms of the license agreements. Click the Finish button, and it'll actually do the install. Click Yes when it asks if you want to restart Eclipse.

We now have the Google Eclipse plugin, plus the GWT and App Engine files we need to develop those sorts of applications.

Subclipse Plugin

This plugin allows Eclipse to work with a Subversion repository (a particular type of online version control). That's the sort used by Google Code, so if you're making your project Open Source then you'll be able to use Google Code to host it. If you aren't making it Open Source, then you'll have to find another Subversion server to use (do a Google Search on free subversion hosting and you'll find some that are suitable for single person projects).

To install Subclipse, go to the Subclipse web site and click the Download and Install link on the left. Scroll down a bit to where it lists the links for the most recent version. Copy the link that's labeled Eclipse Update Site URL.

In Eclipse, go back to Help->Software Updates, and back to the Available Software tab to Add Site with the URL for Subclipse. Click the box next to that URL when it shows up in the list to install everything from that site. Click Install, Next, agree to the license agreements, and Finish.

Restart Eclipse again.

Find Bugs Plugin

Install the Find Bugs plugin. This plugin will look for some common causes of errors in Java programs. These sorts of errors will pass the compiler, but cause you problems. There's a huge variety of bugs that are looked for as part of this. Most you won't ever see, but if it saves you the time tracking down even one obscure bug, it'll have been worth installing.

That's it for Eclipse.

Monday, May 18, 2009

Hello World

This blog exists for one purpose only, to document my sample GWT & Google App Engine project. This will be used as a guide for students in a Web Applications class to be held Spring 2010. I'll start by assuming you know what GWT and App Engine are, because otherwise the other posts are going to be either boring or mystifying, or both.

I haven't decided what the project will be yet; I'm leaning toward something more complicated than a typical to-do list sample, because that'll give my students a better guide (along with giving them the odd laugh or two as they see my mistakes along the way).

I'll be using GWT for the client side because my students already know Java. Not all of them will have had Swing programming yet, but I'm confident they'll come up to speed on that quickly enough. Which wouldn't be the case if I decided to go with Java Script for the client side.

For the server side I'd really like to use Python, and would if it were just my own project. But again, my students will already know Java so it's hard to justify switching languages on the server. Especially since App Engine is available in a Java version that plays well with GWT Serialization.

So, GWT on the client, and Java App Engine on the server. The next few posts will be about getting the environment set up. We'll be using Eclipse with some relevant plugins for both client and server code.

I'm going to be using SVN for managing my project. My students are welcome to follow along and do that, too. That isn't required, but if you've ever deleted a big Java file from your hard drive accidentally, you know the motivation for having every version saved somewhere safe.

That's it for the first post. Hopefully by the time I've done all the setup posts, I'll have figured out what this project is!

Important Note: I'll be posting Java code in many of the posts. Code does not format well on the blog posts, so don't expect to be able to simply copy and paste the code into your files. Treat the code as a text book example...type it in yourself to get a feel for what it's doing, rather than copying and pasting.