Dennis Madsens Blog

08 Mar, 2010

Google Web Toolkit Guestbook Example

Posted by: Dennis Madsen In: Development|GWT|Java

For some months ago I’ve created a small guestbook web application in Google Web Toolkit (GWT). It’s deployed to Googles Appspot:
http://awt-guestbook.appspot.com/

The web application is written in Java and HTML. On compilation the Java code is transformed into JavaScript. Here is some source code example from the application:

Guestbook.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <link type="text/css" rel="stylesheet" href="Guestbook.css">
    <title>GWT Guestbook</title>
	<script type="text/javascript" language="javascript" src="guestbook/guestbook.nocache.js"></script>
  </head>
<body>
	<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>

	<noscript>
	  <div style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">
	    Your web browser must have JavaScript enabled
	    in order for this application to display correctly.
	  </div>
	</noscript>

	<h1>GWT Guestbook</h1>

	<div id="errorBox"></div>

	<h3>Post a new guestbook entry:</h3>
	<div id="nameFieldContainer">Name: </div>
	<div id="messageFieldContainer"></div>
	<div id="sendButtonContainer"></div>

	<h3>Guestbook entries:</h3>
	<div id="entriesLoading"></div>
	<div id="entries"></div>
</body>
</html>

client/Guestbook.java

package awt.example.guestbook.client;

import java.util.*;

import com.google.gwt.user.client.Timer;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.*;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class Guestbook implements EntryPoint {
	private long newestEntryTime = 0;
	private Label labelError;
	private Label labelLoading;
	private VerticalPanel entryPanel = new VerticalPanel();

	/**
	 * Create a remote service proxy to talk to the server-side Guestbook
	 * service.
	 */
	private final GuestbookServiceAsync guestbookService = GWT
			.create(GuestbookService.class);

	/**
	 * This is the entry point method.
	 */
	public void onModuleLoad() {
		// creating a error message
		this.labelError = new Label(
				"An error occured while processing your request");
		this.labelError.addStyleName("error");
		this.labelError.setVisible(false);
		RootPanel.get("errorBox").add(this.labelError);

		// creating loading message
		this.labelLoading = new Label("Loading guestbook entries..");
		this.labelLoading.addStyleName("loading");
		RootPanel.get("entriesLoading").add(this.labelLoading);

		// adding entryPanel to HTML
		RootPanel.get("entries").add(this.entryPanel);

		// creating other buttons
		final Button buttonSend = new Button("Post");
		final TextBox fieldName = new TextBox();
		final TextArea fieldMessage = new TextArea();
		fieldMessage.setPixelSize(300, 100);

		fieldName.setStyleName("inputField");
		fieldMessage.setStyleName("inputField");
		buttonSend.addStyleName("submitButton");

		// Add the nameField and sendButton to the RootPanel
		// Use RootPanel.get() to get the entire body element
		RootPanel.get("nameFieldContainer").add(fieldName);
		RootPanel.get("messageFieldContainer").add(fieldMessage);
		RootPanel.get("sendButtonContainer").add(buttonSend);

		// Focus the cursor on the name field when the app loads
		fieldMessage.setFocus(true);
		fieldMessage.selectAll();

		// Create a handler for the sendButton and nameField
		class MyHandler implements ClickHandler, KeyUpHandler {
			/**
			 * Fired when the user clicks on the sendButton.
			 */
			public void onClick(ClickEvent event) {
				sendEntryToServer();
			}

			/**
			 * Fired when the user types in the nameField.
			 */
			public void onKeyUp(KeyUpEvent event) {
				if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
					sendEntryToServer();
				}
			}

			/**
			 * Send the guestbookEntry to the server and wait for a response.
			 */
			private void sendEntryToServer() {
				buttonSend.setEnabled(false);
				GuestbookEntryDTO entry = new GuestbookEntryDTO(fieldName
						.getText(), fieldMessage.getText());

				guestbookService.addEntry(entry, new AsyncCallback<String>() {
					public void onFailure(Throwable caught) {
						showError();
						buttonSend.setEnabled(true);
					}

					public void onSuccess(String result) {
						fieldName.setValue("");
						fieldMessage.setValue("");
						buttonSend.setEnabled(true);
						updateEntries();
					}
				});
			}
		}

		// Add a handler to send the name to the server
		MyHandler handler = new MyHandler();
		buttonSend.addClickHandler(handler);
		fieldName.addKeyUpHandler(handler);
		fieldMessage.addKeyUpHandler(handler);

		// creating timer to look for new guestbook entries
		Timer refreshTimer = new Timer() {
			@Override
			public void run() {
				updateEntries();
			}
		};
		refreshTimer.scheduleRepeating(5000);

		// getting all entries
		getEntries();
	}

	private void getEntries() {
		guestbookService
				.getEntries(new AsyncCallback<List<GuestbookEntryDTO>>() {
					public void onFailure(Throwable caught) {
						showError();
					}

					public void onSuccess(List<GuestbookEntryDTO> entries) {
						labelLoading.setVisible(false);
						for (GuestbookEntryDTO entry : entries) {
							displayEntry(entry);
						}
					}
				});
	}

	private void updateEntries() {
		guestbookService.getEntries(this.newestEntryTime,
				new AsyncCallback<List<GuestbookEntryDTO>>() {
					public void onFailure(Throwable caught) {
						showError();
					}

					public void onSuccess(List<GuestbookEntryDTO> entries) {
						for (GuestbookEntryDTO entry : entries) {
							displayEntry(entry);
						}
					}
				});
	}

	private void displayEntry(GuestbookEntryDTO entry) {
		String date = convertTimeToDate(entry.getTime());

		HTML widget = new HTML("<div class='entry'><strong>" + entry.getName()
				+ "</strong> - " + date + "<br> " + entry.getMessage()
				+ "</div>");
		this.entryPanel.insert(widget, 0);

		if (entry.getTime() > newestEntryTime) {
			newestEntryTime = entry.getTime();
		}
	}

	private void showError() {
		this.labelError.setVisible(true);
	}

	private String convertTimeToDate(long time) {
		Date tmpDate = new Date();
		tmpDate.setTime(time);
		return tmpDate.toString();
	}
}

server/GuestbookServiceImpl.java

package awt.example.guestbook.server;

import java.util.*;
import awt.example.guestbook.client.*;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

/**
 * The server side implementation of the RPC service.
 */
@SuppressWarnings("serial")
public class GuestbookServiceImpl extends RemoteServiceServlet implements
		GuestbookService {

	private List<GuestbookEntryDTO> messages = new ArrayList<GuestbookEntryDTO>();

	public String addEntry(GuestbookEntryDTO entry) {
		messages.add(entry);
		return null;
	}

	public List<GuestbookEntryDTO> getEntries() {
		return this.messages;
	}

	public List<GuestbookEntryDTO> getEntries(long timeAfter) {
		List<GuestbookEntryDTO> resMessages = new ArrayList<GuestbookEntryDTO>();
		for (GuestbookEntryDTO entry : this.messages) {
			if (entry.getTime() > timeAfter)
				resMessages.add(entry);
		}
		return resMessages;
	}
}

If you don’t know how to set up GWT in Eclipse follow this tutorial from Google:
http://code.google.com/webtoolkit/usingeclipse.html

Download

Download the complete GWT sample project (Eclipse)

Download Download GWT Guestbook Eclipse project

Please feel free to leave a comment below.

24 Feb, 2010

RunKeeper: Belts is not a good armband alternative

Posted by: Dennis Madsen In: Miscellaneous

SPIBelt I have an armband which I use to carry my iPhone on my running workouts. While doing my workout the RunKeeper App is running on my iPhone which use the GPS inside the phone to track my running progress. I was getting tired to workout with this thing around my arm. Therefore I was looking for alternatives.

I found the SPIBelt which was well recommended on the web. Since I would wrap the phone inside the SPIBelt and then put the belt under my jacket, I had my thoughts about the quality of the GPS signal when lying there. Nevertheless I bought the SPIBelt to try it out. Now I have done a workout with it. I’m sorry to say, but the GPS signal was very weak. My workout took about 30 minutes but only nine GPS positions was received.

07 Feb, 2010

Recommendation of RunKeeper

Posted by: Dennis Madsen In: Software

RunKeeper activity on iPhoneRunKeeper gives you the opportunity to track your activities e.g. running, cycling, skiing etc. This application uses the GPS inside the iPhone and when doing your activity, the app displays data such as your current distance, speed, pace etc. in real-time.

When you end your activity the app submits the data of your activity to their web-system and afterwards it’s also visible on your personal user account on RunKeeper.com. From your user profile, your can see maps displaying the route of your activity. It also gives you all sorts of graphs, statistics and more. It’s a very well designed system and the RunKeeper team continually releases new features.

This system is not unique. In the past I’ve been using other systems like this, e.g. Run.GPS on my Windows Mobile phone. It has some of the same features, but not as many as this app offers. Furthermore, the user experience of much better!

As if it wasn’t enough. It’s completely free!

I’ve been using the free-version of RunKeeper for some time now, but since it really satisfy me I decided to bought the Pro-version. The Pro-version provides me with a female voice e.g. on every 5 minutes informing me about my current distance, pace and time doing the workout. That’s great. Furthermore, it integrates with the iPod. It’s also gives some kind of interval workouts, but I have not used that feature yet. The free-version does really provide you with many great features – so just try this out before you consider buying the Pro-version.

I’ve been using the Nike+ too, but for me it cannot compete with RunKeeper. For me the biggest advantage of RunKeeper is the ability to track the geographical position which gives me the position, speed and elevation over time. Since the Nike+ function like a pedometer it’s not aware of position and therefore you only have the chance to see your speed over time. In this topic I do really like graphs and statistics. Therefore only RunKeeper can offer me this core functionality and Nike+ is for me a bad alternative.

RunKeeper webinterface

If your are already using RunKeeper, please feel free to join my Steet team. Visit my RunKeeper profile.

Click to see the App on iTunes StorePrice: Free or 9.99$ (pro-version)
App homepage: http://runkeeper.com/

runkeeper02 runkeeper03 runkeeper04

07 Jan, 2010

Best Apps for iPhone 2009

Posted by: Dennis Madsen In: Software

To express my satisfaction with my best purchase in 2009 – the purchase of my iPhone 3GS, I would like to tell about my favourite applications. At the moment I have about 45+ Apps installed but I’ll only comment on my top 5 of daily used applications.

Please comment this post and give us a list of your favourite iPhone Apps.

1. RunKeeper Pro

RunKeeper gives you the opportunity to track your activities e.g. running, cycling, skiing etc. using the GPS inside the iPhone. When doing your activity the app displays data such as your current distance, speed, pace etc. in real-time. When you end your activity the app submits your activity to their web-system and afterwards it’s also visible on your personal user account on RunKeeper.com.

I’ve done a quick review of RunKeeper.

Click to see the App on iTunes StorePrice: Free or 9.99$ (pro-version)
App homepage: http://runkeeper.com/


2. Tweetie 2

Without a doubt my favourite Twitter client for iPhone. It has a lot of features and a very well designed interface. A must have, if you like to tweet on-the-go.

Click to see the App on iTunes StorePrice 2.99$
App homepage: http://www.atebits.com/tweetie-iphone/
 

3. TjekFodbold

It’s a Danish developed application – which explains the foreign language for some of you. Translated to English it’s “Check soccer”. This application provides live updates of worldwide soccer results. You can turn on notification for your favourite matches, which gives you live push notifications when goals are scored, on bookings and at half- and full-time. Furthermore, it also gives you the starting line-up, league tables etc.

Click to see the App on iTunes StorePrice: Free


4. Reeder

With this App it’s possible to follow your favourite feed in a good looking way. I’ve added my favourite news feed on Google Reader and afterwards Reeder synchronizes with your Google Reader account. The navigation and usage of the Application is absolutely intuitive.

Click to see the App on iTunes StorePrice: 2.99$
App homepage: http://reeder.ch/

5. Facebook

Well, not much to say about this one. If you have an iPhone then you probably already have this App installed. It’s one of the must popular applications world-wide. And why is it that great? Because it lets you communicate with your friends on Facebook!

Click to see the App on iTunes StorePrice: Free
App homepage: http://www.facebook.com/apps/application.php?id=6628568379

Bonus App: MyPhone+ for Facebook

I’m using this application to synchronize the pictures of my iPhone contacts with their pictures on Facebook. I’ve tried a handful of other application to handle this, but in my situation, this application where the best of them.

Notice: While writing this one, a new version of the Facebook Apps is available on the App Store. This one should offer synchronization of contact pictures as well.

You may wonder why I’ve put this App as a bonus on my list. If you do, I can say that it’s because I’m not using this application daily, but just a few times a month. Anyways, this is a very helpful application.

Click to see the App on iTunes StorePrice: 2.99$
App homepage: http://www.ultimake.com/myphone/

04 Jan, 2010

Bit.ly API class for PHP

Posted by: Dennis Madsen In: PHP

I’ve created a Bit.ly class for PHP, which lets you easily cooperate with the Bit.ly API. Bit.ly offers you a service where everyone can generate a small, unique URL from a large and unhandy URL.

Requirements

Example

Before you download the source code I would like to start by showing you how to use the Bit.ly class. Here is a small example:

<?php
require("bitly.class.php");

// Creating an instance of the bitly-class
$bitly = new Bitly();

// Setting the authentication for your Bit.ly user account. http://bit.ly/account/your_api_key
$login = "yourLogin";
$apiKey = "yourApiKey";
$bitly->setAuthentication($login, $apiKey);

// Getting a short URL by Bit.ly
echo $bitly->getShortURL("http://www.dennismadsen.com")."";
// result: http://bit.ly/8rPmdz

// Expand a short Bit.ly URL to the original URL
echo $bitly->getLongURL("http://bit.ly/7px4Q2")."";
// result: http://www.google.com/

// Get number of total click on a short Bit.ly URL
echo $bitly->getClicks("http://bit.ly/7px4Q2")."";
// result: E.g. 47000

// Get number of click by current bit.ly user on a short Bit.ly URL
echo $bitly->getClicksByMe("http://bit.ly/7px4Q2");
// result: E.g. 2
?>

All you have to do is to insert your Bit.ly username and your api Key. See http://bit.ly/account/your_api_key.

Download

Download Download Bitly.class.php (v. 1.0.1)

Please feel free to leave a comment below.

Get Adobe Flash playerPlugin by wpburn.com wordpress themes

Categories

Twitter

    Tags

    Archives