Monday, December 19, 2011

A Javascript script with query string parameters?

TopUp is one of the more popular so-called "lightbox" libraries that allows you to create Web 2.0 popups for tasks such as viewing full resolution images and playing videos. It works like this: Instead of opening a new browser window, like traditional popups do, TopUp uses Javascript to modify the webpage's DOM and display a popup window inside the webpage. This creates a more fluent user experience because it doesn't push the user away from the webpage they're currently viewing, like traditional popups tend to do.

Lightboxes are popups that are part of the webpage itself.

I was reading the library's documentation and noticed that you can pass configuration settings via query string parameters in the URL to the Javascript file. For example, to enable "fast mode" (a setting that improves support for IE 6 and 7), you would import the TopUp script into your page like so:

<script
  type="text/javascript"
  src="path/to/top_up-min.js?fast_mode=1">
</script>

The question I asked myself was, "How are they passing query string parameters into a Javascript file?" If top_up-min.js was really a server-side script that returned Javascript code, then I could understand. But it's an ordinary, plain-text .js file! The file can't be aware of its own URL, so it can't see the parameters!

I opened up the source code to have a look. The author queries the DOM to get a reference to the <script> element that imported the file, and then parses the element's src attribute to get the query string parameters. Pretty clever!

But how does he get a reference to the <script> element? There's nothing unique about this element that you can use to pull it out from the DOM. No unique ID. No specially-named class attribute. How does he do it? What he does is he adds a dummy element to the DOM as soon as the script loads. This guarantees that the dummy element will be added immediately after the <script> element, so he can just get the dummy element's previous sibling and wham...you've got your <script> node.

var scriptElement = (function deriveScriptElement() {
  var id = "tu_dummy_script";
  document.write('<script id="' + id + '"></script>');

  var dummyScript = document.getElementById(id);
  var element = dummyScript.previousSibling;

  dummyScript.parentNode.removeChild(dummyScript);
  return element;
}());

Some people say that programming is not a skill that requires creativity. I would ask these people to look at this code sample and tell me that it's not creative!

Thursday, December 15, 2011

GWT History Mechanism

GWT provides a way to let you interact with the history of the client's browser. This helps to better integrate your GWT application with the browser and provide a more streamlined experience to the user. It allows the application to respond to the user clicking the "back" and "forward" buttons.

In this tutorial, I'm going to add history support to my TwitterSearch application that I created in some previous blog posts. This is a simple app that allows the user to perform tweet searches, as well as view the Twitter privacy policy. By adding history support, the user will be able to navigate back to searches that she made previously. Feel free to download the complete source code so that you can better follow along with this blog post.

What the TwitterSearch application looks like

Because GWT apps never navigate away from the main, HTML page, the way GWT implements history is by adding a fragment identifier to the URL. The fragment identifier starts with a hash (#) and comes at the end of the URL. You often see fragment identifiers being used on large webpages. It allows you to jump around to different parts of the same page by clicking links that have fragment identifiers in their URLs. GWT, however, uses them to identify the "state" that the application was in at a specific point in history.

Enable history support

The first thing to do is make sure your GWT application has history support enabled. This is done by adding an <iframe> element to the HTML page (if you've created your GWT application using Eclipse, then it will be enabled by default):

<html>
  [...]
  <body>
    <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
    [...]
  </body>
</html>

Adding history tokens

Next, we must figure out when to add entries to the browser's history. In our case, we want to add an entry when the user performs a search and when the user views the privacy policy.

searchButton = new Button("Search");
searchButton.addClickHandler(new ClickHandler() {
  @Override
  public void onClick(ClickEvent event) {
    String query = searchQueryTextBox.getText();
    History.newItem(query);
    doSearch(query);
  }
});

privacyPolicyButton = new Button("Privacy Policy");
privacyPolicyButton.addClickHandler(new ClickHandler() {
  @Override
  public void onClick(ClickEvent event) {
    History.newItem("_privacyPolicy");
    doGetPrivacyPolicy();
  }
});

Here, we're adding a new history token when the "Search" and "Privacy Policy" buttons are clicked by calling the static History.newItem() method (new instances of the History class are never created--only its static methods are used). This method simply takes a String as an argument, which is the text that will appear in the fragment identifier. We use the search query as this string for tweet searches, and we use the hard-coded string _privacyPolicy for when the privacy policy is viewed. The doSearch() and doGetPrivacyPolicy() methods call the Twitter API and then update the UI with the results (download the complete TwitterSearch project to see how this is done, or read my previous blog posts).

Try performing a search now--you'll see the search query appear in the fragment identifier of the URL. But if you click "back", nothing will happen! We must explicitly tell our application how to respond to these events.

The history token is added to the fragment identifier in the URL

Handling history change events

Now, let's handle what happens when the user clicks the "back" or "forward" buttons. We'll do this in our onModuleLoad() method, so that the handler we define is registered as soon as our app loads.

@Override
public void onModuleLoad() {
  History.addValueChangeHandler(new ValueChangeHandler<String>() {
    @Override
    public void onValueChange(ValueChangeEvent<String> event) {
      String token = event.getValue();
      if ("_privacyPolicy".equals(token)){
        doGetPrivacyPolicy();
      } else {
        searchQueryTextBox.setText(token);
        doSearch(token);
      }
    }
  });

  [...]
}

As you can see, we call the History.addValueChangeHandler() method and pass in an implementation of the ValueChangeHandler interface. This handler will be invoked every time the user goes back or forward in their browser history. In the handler's only method, onValueChange(), we get the history token (which is the fragment identifier in the URL), and then use it to update our UI accordingly.

Handling history tokens on app startup

Besides giving the user the ability to use "back" and "forward", another good thing about using history is that the user can save bookmarks of our app. For example, a user might want to frequently check Twitter for news on her favorite celebrity, Brad Pitt. She might want to bookmark her search, so that she can reopen the bookmark at a later time and immediately see the latest search results.

To do this, we need to check for an existing history token on startup. We must check for it manually because the presence of a history token on startup will not fire a ValueChangeEvent (this event is only fired when the user clicks "back" or "forward").

@Override
public void onModuleLoad() {
  [...]

  String token = History.getToken();
  if (!token.isEmpty()){
    if ("_privacyPolicy".equals(token)){
      doGetPrivacyPolicy();
    } else {
      searchQueryTextBox.setText(token);
      doSearch(token);
    }
  }
}

The History.getToken() is called to get the current history token. The method returns an empty string if there is no token, so we first check to see if the string empty. If it's not, then we update the UI according to the token. Note that this should happen at the very end of the onModuleLoad() method because the UI widgets must be created first in order for the UI to be updated.

Does this code look familiar? It should because much of it is identical to the code we wrote for the History.addValueChangeHandler() method, so let's refactor it out into its own method:

@Override
public void onModuleLoad() {
  History.addValueChangeHandler(new ValueChangeHandler<String>() {
    @Override
    public void onValueChange(ValueChangeEvent<String> event) {
      String token = event.getValue();
      handleHistoryToken(token);
    }
  });

  [...]

  String token = History.getToken();
  if (!token.isEmpty()){
    handleHistoryToken(token);
  }
}

private void handleHistoryToken(String token){
  if ("_privacyPolicy".equals(token)){
    doGetPrivacyPolicy();
  } else {
    searchQueryTextBox.setText(token);
    doSearch(token);
  }
}

Changing the window title

It's also helpful to change the window title of the web page to reflect the history token. That way, when the user views their entire history, they can have a better idea of what Twitter searches they performed at a glance. To do this, we'll modify two sections of code. First, we'll modify the place where we add new history tokens.

searchButton = new Button("Search");
searchButton.addClickHandler(new ClickHandler() {
  @Override
  public void onClick(ClickEvent event) {
    String query = searchQueryTextBox.getText();
    History.newItem(query);
    Window.setTitle("Twitter Search - " + query);
    doSearch(query);
  }
});

privacyPolicyButton = new Button("Privacy Policy");
privacyPolicyButton.addClickHandler(new ClickHandler() {
  @Override
  public void onClick(ClickEvent event) {
    History.newItem("_privacyPolicy");
    Window.setTitle("Twitter Search - Privacy Policy");
    doGetPrivacyPolicy();
  }
});

Here, we've added calls to Window.setTitle() to set the title of the browser window. It's very important that you call this method after adding the history entry. Otherwise, the titles will not be synced properly with the history entries.

Second, we'll modify our handleHistoryToken() method to set the proper Window title when a history token is loaded.

private void handleHistoryToken(String token){
  if ("_privacyPolicy".equals(token)){
    Window.setTitle("Twitter Search - Privacy Policy");
    doGetPrivacyPolicy();
  } else {
    searchQueryTextBox.setText(token);
    Window.setTitle("Twitter Search - " + token);
    doSearch(token);
  }
}

Now, when you view your history, you'll get a good glimpse of all your past searches.

What the browser history looks like before and after setting window titles.

I hope you've enjoyed my GWT History tutorial. For more information, please see the GWT History page in the GWT Developer's Guide.

Sunday, December 11, 2011

GWT RPC (Part 3 of 3) - Take a ride on the client-side

GWT is all about creating web applications. And a web application wouldn't be a web application without client/server communication. A mechanism called GWT RPC (remote procedure call) is used for this communication in GWT. In this series of tutorials, I'm going to show you how GWT RPC works by building a simple GWT application that uses the Twitter API to perform tweet searches and retrieve the Twitter privacy policy.

The process involves three steps. I'll be covering step 3 in this blog post.

  1. Create the synchronous and asynchronous interfaces that define each RPC method
  2. Create the server-side implementation of each RPC method
  3. Create the UI (user interface) that the client will use perform the searches

You can download the entire sample project used in this tutorial here.


In this blog post, I'll show you how to design a basic UI that will call the RPC methods we created in the previous post. This UI will give us the ability to search for tweets and to view the Twitter privacy policy. Along with explaining how to call the GWT RPC methods from client code, I'll also give you a brief introduction into UI programming.

EntryPoint

package com.acme.twittersearch.client;

[imports...]

public class TwitterSearch implements EntryPoint {
[...]
  @Override
  public void onModuleLoad() {
    createWidgets();
    layoutWidgets();
  }
[...]
}

The first thing to notice is that the class implements the EntryPoint interface. Every GWT application must have one class that implements this. It tells GWT where to start when a user loads the application in her web browser. The interface consists of only one method, onModuleLoad(), which can be thought of as the GWT-equivalent of the public static void main(String args[]) method you see in command-line Java programs.

In our class, onModuleLoad() calls two private methods (that I've created), createWidgets() and layoutWidgets(). The createWidgets() method initializes our buttons, text boxes, etc. The second method, layoutWidgets(), adds those widgets to the page, positioning them in just the way that we want. You are not required by GWT to organize your code in this way, but I find it helpful to do so because UI code is very verbose and can quickly grow in size as your application becomes more complex.

Also, the fully-qualified class name of our entry point class must be added to the GWT module definition file (TwitterSearch.gwt.xml), as shown below:

<module rename-to='twittersearch'>
  [...]
  <entry-point class='com.acme.twittersearch.client.TwitterSearch'/>
  [...]
</module>

Widgets

I've defined my widget objects as class-level fields at the top of the class:

public class TwitterSearch implements EntryPoint {
  private Button privacyPolicyButton;
  private Button searchButton;
  private TextBox searchQueryTextBox;
  private Panel resultsPanel;
  private Label errorLabel;
  private Image loadingImage;
  [...]
}
  • privacyPolicyButton: This button will call the getPrivacyPolicy() RPC method and display the returned privacy policy on the page.
  • searchButton: This button will call the searchTweets() RPC method and display the search results on the page.
  • searchQueryTextBox: This is where the user will enter her Twitter search query.
  • resultsPanel: We'll display the results from each RPC call here.
  • errorLabel: If an error occurs while calling one of the RPC methods, we'll put the error message in here.
  • loadingImage: We'll display an animated loading icon when the client sends an RPC request to let the user know that their request is being processed. It's a good idea to always display some sort of loading image or message while an RPC request is being sent. Even the simplest requests can take several seconds to complete, especially if the user is on a slow network or the server is experiencing heavy load. In our case, we actually end up having to make two network calls per request, (1) the call to the GWT server and (2) the call to the Twitter server. So for us, having a loading image is essential (by the way, I got mine from loaderinfo.net).

The HTML page

Every GWT application has an HTML file that is loaded when the user navigates to the application in her browser. Here, I'm creating the "Twitter Search App" header and adding an image of the Twitter bird. I also have a CSS file which adds some extra formatting. The Javascript file that is being included is what the browser will use when the GWT application is compiled and run in production. The widgets that we load from our Java code will be added to the page dynamically at run time and be placed below the <h1> header (at the end of the <body> tag).

<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <link type="text/css" rel="stylesheet" href="TwitterSearch.css">
    <title>Twitter Search App</title>
    <script type="text/javascript" language="javascript" src="twittersearch/twittersearch.nocache.js"></script>
  </head>

  <body>
    <img src="twitter-bird.png" align="right"/>
    <h1>Twitter Search App</h1>
  </body>
</html>
What the app will look like.

Calling the RPC methods

Calling the RPC methods involves us using the asynchronous interface we created back in step 1 of this blog series. You might be thinking, "But TwitterSearchServiceAsync is an interface and we never created an implementation class for it." You are correct. But this is actually not a problem--GWT uses a technique called "deferred binding", which means that GWT will create a implementation for us during runtime. This is done by calling the GWT.create() method:

public class TwitterSearch implements EntryPoint {
  private final TwitterSearchServiceAsync service = GWT.create(TwitterSearchService.class);
  [...]
}

Even though we want an instance of the asynchronous interface, we pass it the class object of the synchronous interface, TwitterSearchService. The method then returns an instance of the asynchronous interface, TwitterSearchServiceAsync.

Remember how each method in the asynchronous interface took an extra AsyncCallback parameter? We will be using this now. Let's write the code that will do the Twitter search:

searchButton = new Button("Search");
searchButton.addClickHandler(new ClickHandler() {
  @Override
  public void onClick(ClickEvent event) {
    setLoading(true);
    String query = searchQueryTextBox.getText();
    service.searchTweets(query, new AsyncCallback<List<Tweet>>() {
      @Override
      public void onFailure(Throwable caught) {
        errorLabel.setText(caught.getMessage());
        errorLabel.setVisible(true);
        setLoading(false);
      }

      @Override
      public void onSuccess(List<Tweet> result) {
        resultsPanel.clear();
        for (Tweet tweet : result) {
          SafeHtmlBuilder builder = new SafeHtmlBuilder();
          builder.appendHtmlConstant("<b>User: </b>");
          builder.appendEscaped(tweet.getFrom_user());
          builder.appendHtmlConstant("<br /><b>Created: </b>");
          builder.appendEscaped(tweet.getCreated_at());
          builder.appendHtmlConstant("<br /><b>Tweet: </b>");
          builder.appendEscaped(tweet.getText());
          builder.appendHtmlConstant("<br /><br />");
          resultsPanel.add(new HTML(builder.toSafeHtml()));
        }
        setLoading(false);
      }
    });
  }
});

As you can see, we add a ClickHandler to the search button to define what happens when the search button is clicked. When the button is clicked, we first set the page to a "loading" state by calling setLoading(true). This method disables the buttons so the user can't click them and displays the loading image. We then grab the search query from the search text box and make a call to the searchTweets RPC method using the asynchronous interface.

A loading animation appears when a RPC request is made.

The onFailure() method of the AsyncCallback class is called when the RPC method throws an exception. The thrown exception is passed in as an argument to the method. If this happens, we put the exception message in our error label so the user can get an idea of what went wrong. We then set the page back to its normal, "non-loading" state by calling setLoading(false), which will re-enable the buttons and hide the loading image.

An error is thrown when no search query is specified.

The onSuccess() method of the AsyncCallback class is called when the RPC method completes without error. Here, we clear the results panel of past searches, and then loop through the list of returned tweets, adding each one of them to the page. After all tweets are displayed, we call setLoading(false) to re-enable the buttons and hide the loading image.

Search results for "#christmas".

I'm using the SafeHtmlBuilder class here to generate the HTML that is used to display each tweet. This class is like the StringBuilder and StringBuffer classes in that it allows you to efficiently create a large string in a peace-meal fashion. However, SafeHtmlBuilder specializes in making strings of HTML code. The appendEscaped() method escapes all HTML special characters in the string before appending it (for example, converting all < characters to &lt;). The appendHtmlConstant() method does not escape HTML special characters, so you can use this to add HTML tags to the string.

The RPC method call for the getPrivacyPolicy() method follows the same pattern:

privacyPolicyButton = new Button("Privacy Policy");
privacyPolicyButton.addClickHandler(new ClickHandler() {
 @Override
 public void onClick(ClickEvent event) {
    setLoading(true);
    service.getPrivacyPolicy(new AsyncCallback<String>() {
      @Override
      public void onFailure(Throwable caught) {
        errorLabel.setText(caught.getMessage());
        errorLabel.setVisible(true);
        setLoading(false);
      }

      @Override
      public void onSuccess(String result) {
        resultsPanel.clear();

        // convert newlines to  <br / >
        SafeHtmlBuilder builder = new SafeHtmlBuilder();
        builder.appendEscapedLines(result);

        resultsPanel.add(new HTML(builder.toSafeHtml()));

        setLoading(false);
      }
    });
  }
});

I hoped you've enjoyed my three part series on GWT RPC. Creating and calling GWT RPC methods is very easy to do once you become familiarized with these three steps. Simply create the synchronous/asynchronous interfaces, create your server-side RPC implementation, and then call the RPC methods from the client using the asynchronous interface.

For more information on GWT, check out the GWT Developer's Guide.

Friday, December 9, 2011

GWT RPC (Part 2 of 3) - The server-side RPC implementation

GWT is all about creating web applications. And a web application wouldn't be a web application without client/server communication. A mechanism called GWT RPC (remote procedure call) is used for this communication in GWT. In this series of tutorials, I'm going to show you how GWT RPC works by building a simple GWT application that uses the Twitter API to perform tweet searches and retrieve the Twitter privacy policy.

The process involves three steps. I'll be covering step 2 in this blog post.

  1. Create the synchronous and asynchronous interfaces that define each RPC method
  2. Create the server-side implementation of each RPC method
  3. Create the UI (user interface) that the client will use perform the searches

You can download the entire sample project used in this tutorial here.


Since we've already defined our RPC methods in the TwitterSearchService synchronous interface, we're now ready to write the implementations of those RPC methods. We'll create a new class named TwitterSearchServiceImpl (the naming convention is to use the synchronous interface's name with "Impl" appended to the end). It will be located in the "server" package because it's meant to only run on the server. It will extend the RemoteServiceServlet class and implement our TwitterSearchService synchronous interface (it should not implement the asynchronous interface).

package com.acme.twittersearch.server;

[imports...]

public class TwitterSearchServiceImpl extends RemoteServiceServlet implements TwitterSearchService {
  [...]
}

We do a little bit of error checking in the searchTweets method. If the search query is empty, then an IllegalArgumentException is thrown. With GWT RPC, exceptions are sent over the wire to the client. So the exact same exceptions can actually be handled in the client code (as you'll see in my next blog post). Exceptions can be used to return validation errors, as well as return unexpected server-side errors to the client.

@Override
public List<Tweet> searchTweets(String query) throws IllegalArgumentException, IOException {
  query = query.trim();
  if (query.isEmpty()) {
    throw new IllegalArgumentException("No search query specified.");
  }

  // see: https://dev.twitter.com/docs/api/1/get/search
  String q = URLEncoder.encode(query, "UTF-8");
  URL url = new URL("http://search.twitter.com/search.json?q=" + q);
  HttpURLConnection connection = (HttpURLConnection) url.openConnection();
  InputStream response = null;
  try {
    response = connection.getInputStream();
    return parseSearchResponse(response);
  } finally {
    if (response != null) {
      response.close();
    }
  }
}

Also in the searchTweets method, notice how the search query is passed into the URLEncoder.encode() method. This URLEncoder.encode() method encodes the search query so that it can be safely included in the query string of the Twitter API URL. You should always encode query string parameters in this way (just like you should always encode data before passing it into a SQL query string to avoid SQL injection). If a value happens to contain a character that has a special meaning in a URL (like an equals sign or ampersand), then you're likely to run into trouble.

We use the HttpURLConnection class to make the calls to the Twitter API. This class is not on the JRE Emulation list, but that's OK because we're only using it on the server. If we were to use it on the client, we'd get an error because GWT does not know how to convert this class to Javascript.

We also use the google-gson library to parse the JSON-encoded responses that are returned from the Twitter API. The way google-gson works is that you create a class that mirrors the JSON data you are unmarshalling. Each field in the class is named after a field in the JSON data. Google-gson looks at these field names to determine how to unmarshall the JSON message. So, we've created a SearchResponse class for our tweet search API call and a PrivacyPolicyResponse class for our privacy policy API call to do just that. However, for this demonstration, we don't need to unmarshal all the data in each response, so I've only included fields for the data that we need. You can see examples of the full JSON responses for the search and legal/privacy methods on the Twitter API documentation page.

private List<Tweet> parseSearchResponse(InputStream response) throws IOException {
  Reader reader = new InputStreamReader(response);
  SearchResponse searchResponse = new Gson().fromJson(reader, SearchResponse.class);
  return searchResponse.results;
}

private class SearchResponse {
  public List<Tweet> results;
}

Under the covers, TwitterSearchServiceImpl is a plain old Java servlet, which means that only one instance of this class is created to handle all requests. Therefore, be sure to keep thread-safety in mind.

web.xml

Our TwitterSearchServiceImpl class must also be added to the web application's deployment descriptor (web.xml).

<web-app ...>
  [...]

  <servlet>
    <servlet-name>twitterSearchServlet</servlet-name>
    <servlet-class>com.acme.twittersearch.server.TwitterSearchServiceImpl</servlet-class>
  </servlet>  

  <servlet-mapping>
    <servlet-name>twitterSearchServlet</servlet-name>
    <url-pattern>/twittersearch/search</url-pattern>
  </servlet-mapping></span>

  [...]
</web-app>

As you can see, the url-pattern for the servlet is /twittersearch/search. The first part, twittersearch, is the name of our GWT module, which is defined in the module definition file (TwitterSearch.gwt.xml). The second part, search, is the value of the @RemoteServiceRelativePath annotation in the TwitterSearchService interface that we created in the previous blog post.

Tweet class

Let's finish by creating the Tweet class. Because we're unmarshalling JSON data into this class using google-gson, the field names in this class must be named after the fields in the JSON message. Also, GWT requires that all objects that are sent over the wire implement Serializable, so let's do that too. The class must also be put in the "client" package, because it will be used in client code.

package com.acme.twittersearch.client;

import java.io.Serializable;

public class Tweet implements Serializable {
  private String id;
  private String from_user;
  private String created_at;
  private String text;

  [getter/setter methods...]
}

In the next and final blog post of my GWT RPC series, you'll learn how to create a basic UI and how to call these RPC methods from the client.

Thursday, December 8, 2011

GWT RPC (Part 1 of 3) - Synchronous and asynchronous interfaces

GWT is all about creating web applications. And a web application wouldn't be a web application without client/server communication. A mechanism called GWT RPC (remote procedure call) is used for this communication in GWT. In this series of tutorials, I'm going to show you how GWT RPC works by building a simple GWT application that uses the Twitter API to perform tweet searches and retrieve the Twitter privacy policy.

The process involves three steps. I'll be covering step 1 in this blog post.

  1. Create the synchronous and asynchronous interfaces that define each RPC method
  2. Create the server-side implementation of each RPC method
  3. Create the UI (user interface) that the client will use perform the searches

You can download the entire sample project used in this tutorial here.


Synchronous interface

The first thing to do is figure out what kind of communication you need to do with the server. What actions do you need to perform? What data do you need to retrieve? In this case, we need to do two things: perform tweet searches and get the Twitter privacy policy.

These actions are defined in the what's called the synchronous interface. I'll create two RPC methods in my synchronous interface (there's no limit to how many you can define). The interface must extend RemoteService and have a @RemoteServiceRelativePath annotation (which we'll revisit later). It must also be in the client package.

package com.acme.twittersearch.client;

[imports...]

@RemoteServiceRelativePath("search")
public interface TwitterSearchService extends RemoteService {
  List<Tweet> searchTweets(String query) throws IOException, IllegalArgumentException;
  String getPrivacyPolicy() throws IOException;
}

The first method, searchTweets, will take a search query as input and then return a list of tweets in the response. Tweets contain a lot of information (such as an ID, author, and creation date, not to mention the actual tweet message), so I'm going to create a Tweet class that encapsulates all of this information. I'm not going to worry about creating this class right now, though. For now, just assume that the Tweet class holds all the information about a tweet that we need it to.

Also notice how searchTweets throws two exceptions. An IOException will be thrown if there's a problem querying the Twitter API. We'll also have it throw an IllegalArgumentException if the search query is empty. Even though IllegalArgumentException is a runtime exception and doesn't have to be defined in the method's throws clause in order for the Java compilation to pass, GWT requires it to be declared here. Otherwise, it will send a generic "500 error" exception to the client instead of the real exception if that exception is thrown.

The second method, getPrivacyPolicy, doesn't need any parameters. It will return the Twitter privacy policy, which is a block of text that we will hold in a String object. As with searchTweets, it too will throw an IOException if there's a problem calling the Twitter API.

Asynchronous interface

Now that we've defined our RPC methods in the synchronous interface, we're ready to create the asynchronous interface. This interface will contain the exact same methods that are in the synchronous interface, but in a slightly different form:

package com.acme.twittersearch.client;

[imports...]

public interface TwitterSearchServiceAsync {
  void searchTweets(String query, AsyncCallback<List<Tweet>> callback);
  void getPrivacyPolicy(AsyncCallback<String> callback);
}

The interface can be named anything, but I've named it TwitterSearchServiceAsync because the convention is to use the synchronous interface's name with "Async" appended to the end.

As you may have noticed, unlike their counterparts in the synchronous interface, the methods don't return anything. They also take an extra parameter--an AsyncCallback object. This object will be used by the client to handle the response when the response is returned from the server. Since this interface will be used by the client, it must be located in the client package. Also, note that, while the methods in the synchronous interface throw exceptions, the methods in the asynchronous interface do not.

Both of these interfaces must remain in-sync. By that I mean, if one interface changes, the other must also change. For example, if I change the return value of a method in the synchronous interfaces, I must make the same, corresponding change to the asynchronous interface (by changing the generics parameter of the AsyncCallback parameter). The Eclipse GWT plugin is helpful in this regard. If it notices that the two interfaces are not in-sync, it will throw a Java compilation error.


In my next blog post, I'll talk about creating the server-side implementation of the RPC methods.

Saturday, December 3, 2011

GWT Introduction

The Google Web Toolkit allows you to write Javascript-based web applications without having to write any Javascript yourself. It translates Java code that you write into Javascript automatically. In this informational overview, I'm going to walk you through creating a GWT application and then describe the basic components that make up a GWT application.

Install the Eclipse plugin

Google provides an Eclipse plugin you can use for developing GWT applications. This is what I'll be using here, but the raw GWT SDK is available as well for command-line junkies.

The Eclipse update URL for the plugin is:

http://dl.google.com/eclipse/plugin/<version>

where <version> is your Eclipse version (3.7, 3.6, etc).

You'll need to install these modules:

  • Google Plugin for Eclipse
  • SDKs > Google Web Toolkit SDK 2.4.0

Create a new project

Once the Eclipse plugin is installed, create a new "Web Application Project".

Enter "SimpleApp" for the project name and "com.acme.simpleapp" for the package. The package name will be the "base" package for all of the packages in your project as you'll see in a minute. If you haven't installed the Google App Engine plugin, then uncheck the "Use Google App Engine" checkbox (I was on my netbook when I wrote this, so it's hard to see in the screenshot). The Google App Engine is a cloud-based service that lets you upload your application to the web, but that's out of the scope for this article.

Running the project

When you create a new GWT project in Eclipse, it creates a sample application, so let's run it. Right click on the project folder and select "Run As > Web Application". A "Development Mode" view will appear, showing a URL.

Let's quickly take a look at the URL:

http://127.0.0.1:8888/SimpleApp.html?gwt.codesvr=127.0.0.1:9997

The web server (GWT uses jetty, a light-weight web container) runs on port 8888 (remember that "127.0.0.1" is the same as "localhost"). The "gwt.codesvr" query string parameter is how GWT is able to run the application without compiling the project into Javascript. This is called running it in "hosted mode" (which is what you'll always want to do while developing and debugging a project). If this parameter is removed, it will instead use the Javascript code that was generated the last time the project was compiled (more on compilation later). This is called running it in "web mode". We haven't compiled the project yet, so running it in web mode will throw an error because there's no Javascript code to use.

Now, load the URL in your browser. In order to run the application in hosted mode, you have to install a browser plugin, so install the plugin and then refresh the page.

After a few seconds the web page will appear, asking you to enter your name. Enter your name and click send.

A popup message will appear with some information. What it's doing here is sending a message to the server using GWT RPC, which is the main mechanism GWT uses to communicate between the client (a Javascript-powered web page) and the server (a Java web application).

Debugging the application

You can set breakpoints and debug the GWT application just like any other Java application. Just be sure to select "Debug As > Web Application" instead of "Run As > Web Application" when running the application.

Translatable vs non-translatable code

One thing to keep in mind when developing a GWT application is the idea of distinguishing between Java code that should be converted to Javascript, from the Java code that shouldn't be converted to Javascript. This is defined in the "SimpleApp.gwt.xml" file, which is a configuration file for the application.

<?xml version="1.0" encoding="UTF-8"?>
<module rename-to='simpleapp'>
  <!-- Inherit the core Web Toolkit stuff.                        -->
  <inherits name='com.google.gwt.user.User'/>

  <!-- Inherit the default GWT style sheet.  You can change       -->
  <!-- the theme of your GWT application by uncommenting          -->
  <!-- any one of the following lines.                            -->
  <inherits name='com.google.gwt.user.theme.clean.Clean'/>
  <!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> -->
  <!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
  <!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/>     -->

  <!-- Other module inherits                                      -->

  <!-- Specify the app entry point class.                         -->
  <entry-point class='com.acme.simpleapp.client.SimpleApp'/>

  <!-- Specify the paths for translatable code                    -->
  <source path='client'/>
  <source path='shared'/>
</module>

As you can see, the <source> tags mark the "client" and "shared" packages as Javascript-compatible, which means they will be converted to Javascript code when the application is complied.

Keep in mind that, GWT can only convert certain Java classes to Javascript (for a complete list, see the JRE Emulation Reference). So, for example, even though creating a FileOutputStream in the Java code won't throw any errors when the Java class is complied, an error will be thrown when the project is compiled to Javascript or run in hosted mode. To help you remember which Java classes are translatable, just remember that you're writing code for Javascript and there's certain things you can't do in this environment (like save files to disk, for example). As long as you keep this in mind, you won't need to refer to the JRE Emulation Reference very often.

Packages that are not defined as translatable code will run on the server as real Java code, so you can do whatever you want with them.

Source code

Let's just drill down each of the files in the "src" directory and describe what they do:

  • SimpleApp.gwt.xml: This file is called the "module definition". It contains the project's configuration settings including which Java classes are translatable to Javascript, the "entry point" class (like the "main" method for the client), and the application's look and feel.
  • GreetingService.java: An interface which defines the GWT RPC methods that are used by the client to communicate with the server.
  • GreetingServiceAsync.java: An alternate version of the GreetingService interface that the client uses to perform asynchronous communication with the server. Note that these two interfaces must remain in-sync, so any time the GreetingService interface is changed, the GreetingServiceAsync interface must also be changed.
  • SimpleApp.java: Contains all of the client-side GUI code. It is also the entry point class.
  • GreetingsServiceImpl.java: The server-side code that is called when the client sends requests to the server via GWT RPC. It provides the implementation of all of GWT RPC methods defined in GreetingService.
  • FieldVerifier.java: Contains validation code that is used on both the client and server. This is one of the advantages to using GWT--because the same code can be used for both the client and server, only one version needs to be maintained.

Client-side code

Let's quickly take a look at the client-side code. In this sample application most of the code is in one class, SimpleApp.

public class SimpleApp implements EntryPoint {

  private final GreetingServiceAsync greetingService = GWT.create(GreetingService.class);

  public void onModuleLoad() {
    [...]
  }
  [...]
}

The SimpleApp class implements the EntryPoint interface and thus must implement the onModuleLoad() method. This method is where the application "starts" when the client loads it in her browser (like a "main" method). To communicate with the server over GWT RPC, an instance of the GreetingServiceAsync class is created.

Server-side code

When the client communicates with the server via GWT RPC using the GreetingServiceAsync class, the code in GreetingServiceImpl class is executed.

public class GreetingServiceImpl extends RemoteServiceServlet implements GreetingService {

  public String greetServer(String input) throws IllegalArgumentException {
    [...]
  }
  [...]
}

Under the covers, this class is just a plain Java servlet, but with some GWT additions. Notably, it does the work of converting all requests and responses to JSON when sent over the wire.

The only GWT RPC method here is greetServer. It accepts a String as the request and returns a String in the response.

Compiling

When you're ready to deploy your GWT application to production, you'll want to compile it. This will translate all the client-side Java code into Javascript code, making it a fully-functional web application that you can run from a web container like Tomcat.

To do this, right click on the project folder and select "Google > GWT Compile". When it's done, just copy the "war" directory into the web container.

Friday, December 2, 2011

Apache Commons IO Introduction

The Apache Commons project is a collection of over 40 individual Java libraries that provide convenience methods to eleviate the developer from having to write tedious, boiler-plate code. The libraries try to stay as close to the core Java API as possible, so they have few or no dependencies on other libraries.

One of the libraries that I use a lot is the IO library. It contains features that build upon the core Java IO API and also make it easier to interact with the filesystem. I'm going to list three of the methods that I use a lot (and that you should use too). Looking at the API though, there's a ton more stuff this library can do, so don't let my tiny blog post keep you from exploring it.

IOUtils.copy()

The IOUtils.copy() method is great for copying data from an InputStream (or Reader) to an OutputStream (or Writer). No more creating arbitrarily-sized buffers and parenthesis-laden while loops! What it does here isn't rocket-science--any programmer worth their salt could code this up themselves. The point of using it is to make your code easier to read, less error-prone, and more consistent with the broader Java programming community.

These two code samples show just how much less code you have to write if you use this method:

Plain Java:

InputStream in = ...
OutputStream out = ...
byte buffer[] = new byte[4096];
int read;
while ((read = in.read(buffer)) != -1){
  out.write(buffer, 0, read);
}
in.close();
out.close();

Commons IO:

InputStream in = ...
OutputStream out = ...
IOUtils.copy(in, out);
in.close();
out.close();

IOUtils.closeQuietly()

The IOUtils.closeQuietly() method eliminates the boiler-plate required to close a stream in Java. It (1) checks to make sure the stream isn't null, (2) closes the stream, and (3) catches the IOException that is thrown when the stream's close() method is called. Again, what it does here isn't rocket-science. Its purpose is to reduce the amount of fluff in your code:

Plain Java:

InputStream in = null;
try{
  in = ...
  ...
} catch (IOException e){
  ...
} finally{
  try{
    if (in != null){
      in.close();
    }
  } catch (IOException e){}
}

Commons IO:

InputStream in = null;
try{
  in = ...
  ...
} catch (IOException e){
  ...
} finally{
  IOUtils.closeQuietly(in);
}

FileUtils.writeStringToFile()

Whenever I switch from coding in PHP to coding in Java, my heart sinks a little bit when I have to write some text to a file. In PHP, you can do this with a single function call. But in Java, you need to write a dozen or so lines of code. The FileUtils.writeStringToFile() method, however, allows you to write text to a file in one fell swoop.

Plain Java:

String text = "some text";
File file = new File("myfile.txt");
Writer writer = null;
try{
  writer = new PrintWriter(file);
  writer.write(text);
} catch (IOException e){
  ...
} finally {
  if (writer != null){
    try{
      writer.close();
    } catch (IOException e){}
  }
}

Commons IO:

String text = "some text";
File file = new File("myfile.txt");
try{
  FileUtils.writeStringToFile(file, text);
} catch (IOException e){
  ...
}

I hope you've enjoyed my little introduction to Commons IO. Using this library can greatly increase the readability and reliability of your code.

Wednesday, November 23, 2011

Book review: Tomcat 6 Developer's Guide

The book is very wholistic in its approach to educating the reader. It provides a well-written overview of JavaEE and HTTP in Chapter 2. And whenever it mentions a technology that Tomcat uses in some way, it immediately gives a brief overview of that technology. I found this helpful because it gave me the knowledge I needed to continue reading without having to switch to a search engine. For example, in Chapter 5, when discussing the JNDI functionality that Tomcat comes packaged with, the book pauses for a moment to explain the basic concepts of JNDI itself. The book will also often describe the historical origins of the technology, like in Chapter 1, where it discusses the origins of Ant (spoiler alert: it was created as a custom build system for Tomcat).

The instructions for downloading the Tomcat source code and building it are very clear. It provides a specific branch you can checkout from the Tomcat Subversion server, which is the exact version of Tomcat that was used when writing the book. This allows you to follow along without worrying about dealing with differences between what you see in the code and what you see in the book. And it also includes instructions for getting the project properly configured with Eclipse.

The later chapters of the book go into a lot of detail about the various classes that make up the Tomcat source code, so be prepared for some serious code spelunking. Anyone who is interested in doing serious coding in the Tomcat codebase will gain a lot from these chapters.

I'd recommend this book to people who want to work on the Tomcat source code and need something to guide them through it. I'd also recommend the book to JavaEE developers who use Tomcat on a regular basis and who want to expand their knowledge.

Saturday, October 15, 2011

Microsoft Word: Disabling spellcheck for a block of text

Often times, when I'm putting together a piece of documentation for work, it helps to include code samples and console commands in the document. I like to use Word to write documentation because it allows you to stylize the text (such as increasing the font size of headers, making things bold, etc) which I think makes it easier to read (when used in moderation). It's also nice for code samples because when you copy and paste code from Eclipse, it includes the syntax-highlighting of the code. Creating plain text files is simpler, but you loose that readability aspect I think is important.

Anyway, one annoying thing is that Word spell checks and grammar checks these code samples and console commands, so you get all these red and green squiggly lines under the text.

However, it is possible to disable spell and grammar check for selected blocks of text! First, select the text that you want to exclude from being checked. Then, select the "Review" tab from the ribbon at the top of the screen and click on "Set Language".

In the dialog window that appears, click the "Do not check spelling and grammar" checkbox and click "OK". If your document happens to have multiple written languages in it, you can also use this dialog to tell Word which blocks of text are written in which language.

Now, those squiggly lines should disappear!

Saturday, October 8, 2011

Book Review: Play Framework Cookbook

Play Framework Cookbook is divided into seven chapters, each of which contains a dozen or so recipes. The recipes range in skill level from beginner to advanced and are pretty much organized in this order, with the more basic recipes at the start of the book and the more advanced ones at the end. Some examples of the more basic recipes include "Defining your own controllers" and "Basics of caching". Advanced topics include "Understanding bytecode enhancement" and "Implementing your own persistence layer". Nearly all of the recipes are self-contained so you don't have to read the book from start to finish--you can jump around at your leasure and read whatever looks interesting to you.

Each recipe is usually divided into four sections. "Getting Ready" describes how to prepare your development environment for the recipe. "How to do it..." covers the steps you have to take to complete the recipe, like what code you have to write. A detailed explaination of those steps can be found in the next section, "How it works...". The last section, "There's more..." (what's with all the ellipses?), contains supplemental information on how to improve upon the recipe and broaden its scope. I like the way the author divided each recipe this way because it makes it easier to find what you're looking for. For example, if I'm in the midst of coding something and need to refresh my memory about a particular method call or class name, I can jump right to the "How to do it..." section and not have to wade through a lot of text to find what I'm looking for.

I would say that the only prerequisite of the book is that you know how to program in Java, though having basic knowledge of Play beforehand will help. The Forward contains an informative overview that describes where Play fits into wider the Java web application world and how it differentiates itself from other web frameworks. And the recipes in the first chapter contain a lot of the basics of the framework, like how to define routes and create controllers.

But all the information in the first chapter can be found in the official Play documentation online. Where the book really shines is in the subsequent chapters. They describe how to perform specific tasks such as creating an RSS feed, creating PDFs, and generating JSON data. They also describe how to integrate Play with a variety of systems like Apache, MongoDB, Spring, Google Charts, and Jenkins. Getting an application to "play nice" with the other parts of a system, no matter what technology you are using, can be a hairy ordeal, so I think these recipes are especially helpful.

All of the code samples can be downloaded from the book's website. Each sample corresponds to a single recipe and is a complete Play application, which is great because it means the samples are self-contained and can be run right off the bat. However, I had a little trouble getting some of them to run. I had to manually enable the in-memory database (the "db=mem" config property) because I was getting JPA errors on application startup. But otherwise, the samples seemed to work fine.

All in all, I would recommend this book to anyone interested in learning more about Play. It covers a wide variety of topics, so you're bound to find something useful no matter what kind of Play application you're developing (or want to develop) or what your skill level is.

Monday, September 19, 2011

Upcoming book review: "Play Framework Cookbook"

I got an interesting email last Friday. A publisher, Packt Publishing, noticed my recent blog posts about the Play Framework and asked if I would review the book, Play Framework Cookbook by Alexander Reelsen. I've never been asked to write a book review before, so I'm really excited about it! I'll be posting a review of the book within the next 2-3 weeks.

In the mean time, feel free to check out a sample chapter from the book entitled "Using Controllers" where the author covers topics such as how to generate PDFs and implement HTTP digest authentication.

Saturday, September 17, 2011

The Play Framework - Part 6

The Play Framework is a MVC web application framework for Java that focuses on being light-weight and easy to use--two qualities that you don't see very often in the Java web application world.


Here are a couple miscellaneous features of the Play Framework:

In the "conf/routes" file, a regular expression can be used to match a URL to a controller action. The regular expression is enclosed within < > characters and comes before the variable name. For example, the following route definition only matches if the last part of the URL is a number:

GET  /posts/{<[0-9]+>id}  Application.show

In a template, when looping through a list of elements, it is often helpful to know if the current element is the first or last element in the list. To do this, append _isFirst or _isLast to the end of the variable name. For example, the code below will output the contents of a list with each element separated by a comma. A comma should always be printed after each element--except for the last element, which shouldn't print a comma:

#{list items:tags, as:tag}
  ${tag}${tag_isLast ? '' : ', '}
#{/list}

Thursday, September 15, 2011

The Play Framework - Part 5 - CAPTCHAs

The Play Framework is a MVC web application framework for Java that focuses on being light-weight and easy to use--two qualities that you don't see very often in the Java web application world.


Play comes packaged with a CAPTCHA generator, which is good for ensuring that form submissions are sent by a human being and not by an automated bot.

A CAPTCHA is an image that contains random letters and numbers that the user has to type in order to submit a form. The letters and numbers are rendered in a non-uniform way in order to make it as difficult as possible for an automated image recognition algorithm to read (but still clear enough for a human to read). For example, the characters may each be a different size and font. It stands for (take a deep breath) "Completely Automated Public Turing test to tell Computers and Humans Apart".

To generate a CAPTCHA in Play, use the Images.Captcha class:

public class Application extends Controller{
  public static void captcha(){
    Images.Captcha captcha = Images.captcha();
    String code = captcha.getText("#990000");
    captcha.addNoise("#CCCCCC");
    captcha.setBackground("#996633", "#FF9900");
    renderBinary(captcha);
  }
}

In this code, I'm generating a CAPTCHA image and returning it in the response. Calling the getText() method sets the color of the text and returns the random string that the CAPTCHA is rendering. As you can see, the notation used to define the color is conveniently the same notation that is used in HTML and CSS (however, you cannot use the three-character abbreviated form used by CSS).

I'm also adding noise to the image to make it even harder for an image recognition algorithm to read (it will add a gray squiggly line through the image). And then, I'm setting a background gradient to have it fade from a dark to a light orange.

Because the Captcha class implements InputStream, it can be passed into the renderBinary() method to send the image to the response. It generates a PNG image.

Tuesday, September 13, 2011

The Play Framework - Part 4

The Play Framework is a MVC web application framework for Java that focuses on being light-weight and easy to use--two qualities that you don't see very often in the Java web application world.


A special template syntax is used to link to other pages in the application (the actual URL of the page is not used). This makes things more flexible, because you can change the page's URL in the "conf/routes" file without having to go through each template file and edit all the links that point to that page. Take this example:

Template file:

<a href="@{Application.index()}">Home</a>

"conf/routes" file:

GET  /home   Application.index

Generated HTML:

<a href="/home">Home</a>

Play sees that the Application.index method is assigned to the URL "/home" and generates the appropriate HTML when a user requests the page.

To access a static resource (like images, Javascript files, and CSS files), put the path to that resource in single quotes. With Play, all static resources go in the "public" directory.

<script src="@{'/public/javascripts/jquery-1.4.2.min.js'}"></script>

As with seemingly every type of file in a Play application, any changes made to the "conf/routes" file while the application is running are applied immediately. No restart is needed.

The "form" template tag can be used to create HTML forms:

#{form @Application.postComment(post.id)}
  Name: <input type="text" name="author" value="${params.author}" />
  <input type="submit" value="Post" />
#{/form}

This ends up adding two more attributes to the generated <form> tag ("accept-charset" and "enctype") and also adds a hidden parameter called "authenticityToken" (probably used for security purposes). You can also add attributes of your own, by supplying them as tag parameters after the action URL:

#{form @Application.postComment(post.id), onsubmit:'return validateForm()'}

Saturday, September 10, 2011

The Play Framework - Part 3

The Play Framework is a MVC web application framework for Java that focuses on being light-weight and easy to use--two qualities that you don't see very often in the Java web application world.


If you want to execute some code when the application first starts up, you can create a class that has the @OnApplicationStart annotation and that extends the Job class. Put the code that you want to run on startup in a method called doJob(). This class can just go in the default package for simplicity, but it doesn't matter what package the class is in.

@OnApplicationStart
public class Bootstrap extends Job {
  @Override
  public void doJob(){
    if (User.count() == 0){
      Fixtures.loadModels("initial-data.yml");
    }
  }
}

In DEV mode, this will be run when the application gets its first request. That way, if an error occurrs, it will appear in the browser. But in PROD mode, the startup code will be run as soon as the play run command is executed and if there are any errors, the server will fail to start up.

To pass variables to a template, simply pass them as arguments to the render() method in the controller. The variable will have the same name inside the template as it does inside the controller.

If you want to run some code every time a controller handles a request, use the @Before annotation. For example, the addDefaults() method below will add two variables to the template every time a request comes in to the Application controller (the Play.configuration variable allows you to access values from the 'application.conf" file):


public class Application extends Controller {
  @Before
  public static void addDefaults(){
    //called before every request is handled
    renderArgs.put(
      "blogTitle",
      Play.configuration.getProperty("blog.title")
    );
    renderArgs.put(
      "blogBaseline",
      Play.configuration.getProperty("blog.baseline")
    );
  }

  //...
}

Play adds some helpful utility methods to various datatypes inside template code. Calling pluralize() on a number will return the string "s" if the number is not 1. Calling format('MM/dd/yyyy') on a Date object will format the date according to the given format string (you don't need to create a SimpleDateFormat object). Calling nl2br() on a string will replace all newlines with <br/> tags.

Tags are snippets of template code that you can insert into other templates by calling them like functions. The tag parameter names all begin with underscores in the tag file. Tag files go in the "views/tags" directory. The tag's name is the same as its file name (minus the file extension).

Calling a tag from a template:

#{hello person:'George', timeOfDay:'morning' /}

Tag file (views/tags/hello.html):

Good ${_timeOfDay}, <b>${_person}</b>!

Monday, September 5, 2011

The Play Framework - Part 2 - Database

The Play Framework is a MVC web application framework for Java that focuses on being light-weight and easy to use--two qualities that you don't see very often in the Java web application world.


To connect your application to a database, modify the "db.*" settings in the "conf/application.conf" file. To get up and running quickly, uncomment the "db=mem" line to create an in-memory database (all changes will be lost, of course, when the application ends).

To save data to the database, start by creating entity classes inside the "model" package. An entity class is a plain Java bean class that has JPA (Java Persistence Architecture) annotations. Each entity class represents a table in the database, each instance of the class represents a row in the table, and each field in the instance represents a column in the row (getter and setter methods aren't needed for the fields--Play generates them automatically). By default, the table name is the same as the class name. To change the table name, use the @Table annotation.

Each entity class can also optionally extend Play's Model class, which gives it access to utility methods for saving and retrieving data. For example, to insert a new row into the table, simply create a new instance of the class and call the save() method:

User user = new User("Bob", "bob@gmail.com");
user.save();

To retrieve data, call the static find() method:

List<User> users = User.find("byNameAndEmail", "Bob", "bob@gmail.com").fetch();

You don't need to write any SQL code to interact with the database. Play uses Hibernate for its persistence layer, so HQL (Hibernate Query Language) can be used for more complex queries.

The Model class also automatically generates an "id" primary key column for you (something that every table should have). So basically, you should always extend this class.

Here's an example of an entity class. It represents a blog post:

package models;
import java.util.*;
import javax.persistence.*;
import play.db.jpa.*;

@Entity
@Table(name="blog_posts")
public class Post extends Model {
  public String title;
  public Date postedAt;

  @Lob
  //large amount of text
  public String content;

  @ManyToOne
  //many Posts can belong to one User
  public User author;

  //a list of all comments that belong to this post
  //(the comments are in a separate table)
  //CascadeType.ALL = the post's comments will be automatically deleted when the post is deleted
  @OneToMany(mappedBy="post", cascade=CascadeType.ALL)
  public List<Comment> comments;

  public Post(User author, String title, String content) {
    comments = new ArrayList<Comment>();
    this.author = author;
    this.title = title;
    this.content = content;
    postedAt = new Date();
  }

  public Post addComment(String author, String content){
    Comment newComment = new Comment(this, author, content).save();
    comments.add(newComment);
    save();
    return this;
  }
}

The Fixtures class provides more utility methods for interacting with the database. For example, to delete the entire database, call the deleteDatabase() method. It can also execute SQL code contained in a file or persist the data in a specially-formatted YAML file (YAML is a new standard for representing structured data. Its aim is to provide a better alternative to XML).

Sunday, September 4, 2011

The Play Framework

The Play Framework is a MVC web application framework for Java that focuses on being light-weight and easy to use--two qualities that you don't see very often in the Java web application world. Writing a web application in Java has always been more complicated than, say, writing a web application in PHP.

The first thing you must do after downloading the Play framework is configure your path so that you can invoke the "play" executable:

PATH=$PATH:/home/user/play-1.2.2

Everything you do with Play is done through this play executable.

To create a new application, run this command:

play new appName

This creates a folder in the current directory with the same name as the application. The folder is populated with the basic scaffolding needed for a Play application.

You can immediately run this application too. To run the application, execute this command:

play run appName

This will start up a web server and run your application at "http://localhost:9000". You don't need any web servers of your own, everything is bundled within the framework (you don't even need a JavaEE web container like Tomcat). The only thing you need to run Play is a JRE.

Note that, if you get an error that says, "ERROR ~ Could not bind on port 9000", then something on your computer must be using port 9000. Port 9000 is the default port Play uses to run the application. This setting is defined in "conf/application.conf" under the "http.port" setting (be sure to uncomment the line too--remove the "#" at the beginning of the line to uncomment it). I changed the port to 9001 because 9000 didn't work for me.

Notice the line that says, "Listening for transport dt_socket at address: 8000", when the application is starting up. This means the web application has opened a port which allows you to debug the application as it is running using an IDE like Eclipse.

After it successfully starts up, open a web browser and navigate to "http://localhost:9001". When the web application gets its first request, it compiles all the Java code and template code in the application for you (it saves the .class files to the "tmp" directory). You don't have to manually compile any of the .java files yourself like in a normal JavaEE web application. If you change any Java code or template code while the application is running, the application will detect this and automatically recompile it for you. You don't have to restart the application. This is how the web application behaves in DEV (development) mode (the default). If started in PROD (production) mode, then this is not done in order to increase performance.

The application's unit tests (in the "test" folder) can be run from the web application itself. To do this, execute this command:

play test appName

This will start the web application and also enable the unit test functionality at "http://localhost:9001/@tests". The page displays all available tests and lets you select which tests to run.

Eclipse Integration

You can edit all of the files in a basic text editor of course, but for serious development work, this can be tedious. To configure the Play application for Eclipse, execute this command:

play eclipsify appName

This will create all the necessary configuration files (such as the ".project" file) needed to open the application as an Eclipse project. It also creates a directory named "eclipse", which contains launch configurations that can be run from Eclipse:

  • appName.launch - Running this has the same effect as running play run appName from the command line (it starts up the web application). To run it, right-click on it and select "Run As > appName".
  • Connect JPDA to appName.launch - This will connect Eclipse to the JPDA port (8000) while the application is running and allow you to debug the application in Eclipse. Note that the application must already be running for this to work. To run it, right-click on it and select "Debug As > Connect JPDA to appName". Go to the "Debug" perspective in Eclipse to see if it connected properly (you can see all the different web server threads in the upper-left hand corner).
  • Test appName.launch - Running this has the same effect as running play test appName from the command line. To run it, right-click on it and select "Run As > Test appName". Make sure that you first shut down the web application if you had already started it using "appName.launch".

Import the project into Eclipse by going to "File > Import..." and then selecting "Existing Projects into Workspace".

If you try to open some of the template files (the .html files in "app/views") in Eclipse, some files will display an error that says, "Character encoding "${_response_encoding}" is not supported by this platform." This is because Eclipse considers the file to be an HTML file and it looks at the <meta> tag to determine the character encoding of the file (even though the file has a ".html" extension and has HTML tags, it isn't really an HTML file--Play uses a special templating engine that has a special syntax). Well, the character encoding here is defined as a template variable, so Eclipse sees the variable name and gets confused. Click the "Set Encoding..." button and set the encoding to "UTF-8".