Tuesday, April 14, 2009

App Engine Tutorial : Creating the Beer Radar Server component

App Engine App #1.0 - Server Component for Android Application Beer Radar.

I created the Beer Radar Android Application last February 2009, and I was looking for a suitable Java server application. I don't know when it was announced, but I just heard about the Google App Engine support for Java last week (April 10, 2009).

Here's the basic App Engine Application which I'll connect the Beer Radar app soon. :) http://beer.androidph.com/

I quickly signed up to see what is it all about. So, here's what I learned so far.

Here are the steps to create a web app using Google App Engine with Java Lanuage Support.

1. Sign-up for an App Engine Account http://appengine.google.com/ you should click link for Java then click the sign-up button (I waited for 2 days for the confirmation). I don't have a screenshot for it, but its easy to spot.

2. Download the Google App Engine SDK http://code.google.com/appengine/downloads.html

3. Install the App Engine Eclipse Plugin
From the Eclipse Menu, go to HELP > Software Update...
Click the Available Software Tab
Click Add Site, type http://dl.google.com/eclipse/plugin/3.4
Then Install
See http://code.google.com/appengine/docs/java/tools/eclipse.html for more details.
Restart Eclipse


4. Click the New Web Application Icon as shown below


5. Type in the Project name and package. I unchecked the GWT option since I'm not going to use it.


6. Then click Finish. Everything is created for you, even the libraries that you need for your application.


7. Run the server by right-clicking on the project, select Debug As > Web Application


8. If you have tomcat running by default, you'd probably get this error message
WARNING: failed SelectChannelConnector@127.0.0.1:8080
java.net.BindException: Address already in use: bind


9. Fix this by going to the Debug Configurations, then on the Main Tab, set a new port or click "Automatically select an unused port".





10. Click Debug.

11. Now open your browser to http://localhost:8989.

12. Now you can test your application.


13. Once you're done with you application and you already got the Google confirmation message, you can now create an application.


14. Type in a unique Application Identifier and the Application Title. This will be used in deploying your application.


15. Once everything is done, you can now deploy by clicking the Deploy App Engine Project icon.


16. You will need to click the App Engine project settings to enter your Application Identifier.


17. Enter you Application ID then type in a version then click OK.


18. Enter your Google App Engine Account Email and Password and that is done.


20. Here's the app http://beerradar.appspot.com/ I deployed, to be used as the server component of the Beer Radar project.

21. AND YES, I had to put in the ads. ;)

What I really like about the app engine is the JDO support.

Here's the code for my Persistent Object
Beer.java

package com.androidph.beerserver;

import java.text.SimpleDateFormat;
import java.util.Date;

import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Beer {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Long id;

@Persistent
private String name;

@Persistent
private Double price;

@Persistent
private Date lastCallTime;

@Persistent
private String promotions;

@Persistent
private String address;

@Persistent
private Double longitude;

@Persistent
private Double latitude;

public Long getId() {
return id;
}

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

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Double getPrice() {
return price;
}

public void setPrice(Double price) {
this.price = price;
}

public Date getLastCallTime() {
return lastCallTime;
}

public void setLastCallTime(Date lastCallTime) {
this.lastCallTime = lastCallTime;
}

private SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");

public String getLastCallTimeString() {
if(lastCallTime != null) {
return sdf.format(lastCallTime);
} else {
return "-";
}
}

public String getPromotions() {
return promotions;
}

public void setPromotions(String promotions) {
this.promotions = promotions;
}

public String getAddress() {
return address;
}

public void setAddress(String address) {
this.address = address;
}

public Double getLongitude() {
return longitude;
}

public void setLongitude(Double longitude) {
this.longitude = longitude;
}

public Double getLatitude() {
return latitude;
}

public void setLatitude(Double latitude) {
this.latitude = latitude;
}

public String toString() {
return id + " | " + name + " | " + price + " | " + lastCallTime + " | " + promotions + " | " + address + " | " + longitude + " | " + latitude;
}

public byte[] convertToStream() {
return null;
}

public void fromStream(byte[] data) {

}
}

Here's the code to get a Persistence Manager. I got this from the GuestBook demo included in the AppEngine SDK

PMF.java

package com.androidph.beerserver;

import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManagerFactory;

public final class PMF {
private static final PersistenceManagerFactory pmfInstance =
JDOHelper.getPersistenceManagerFactory("transactions-optional");

private PMF() {}

public static PersistenceManagerFactory get() {
return pmfInstance;
}
}


Here are code snippets on how to use the Persistence Manager.

Persisting an Object

PersistenceManager persistenceManager = PMF.get()
.getPersistenceManager();
Beer beer = beerValidator.getBeer(name, address, price,
lastCallTime, promotions, longitude, latitude);
persistenceManager.makePersistent(beer);

Retrieving Data

String query = "select from " + Beer.class.getName()
+ " order by name asc";
List beerLocations = (List) persistenceManager
.newQuery(query).execute();
for (Beer beer : beerLocations) {
beerServletData.addLog("beer.toString() : " + beer.toString());
}

16 comments:

Unknown said...

Hi there,

Do you have any idea on how to move on?

I have a similar project in my mind. Done the same with App Engine for Java, but having problem in finding a suitable but yet secure way of attaching Android as client to the App Engine application as a server.

I come from the world of WS and it is hard to imagine how to move on without it. :)

Best Regards,
Tamas

java.padawan said...

Hi Tamas,

I'm thinking of including a key in the HTTP header that identifies the request is coming from an android phone.

I'll just post my solution when I'll have time.

Thanks a lot.
-Ice

Anonymous said...

I had the same problem with 8080... Changed to 8989 and it is working... Thanks for the tip...

Also good app!!

Winai said...

I can't solve my problem in google
app engine anyone help me please.
My error told me that it can't compile class in jsp. Especially,
it's class of datastore and error also told that me maybe I should change my file version but I try to do it.As a result, it still doesn't work. Help me!

java.padawan said...

Hi Winai,

Can you give me more details of your problem?

Are you using the eclipse plug-in? Can you post some exceptions / error messages you are getting?

Winai said...

Yes, This my error message
Unable to compile class for JSP

Generated servlet error:
[javac] C:\Users\ADMINI~1\AppData\Local\Temp\Jetty_127_0_0_1_8080_war____-7ieg8g\jsp\org\apache\jsp\addressbook_jsp.java:6: cannot access com.google.appengine.demos.jdoexamples.AddressBookEntry


Generated servlet error:
[javac] bad class file: D:\Project\JDO\war\WEB-INF\classes\com\google\appengine\demos\jdoexamples\AddressBookEntry.class
[javac] class file has wrong version 50.0, should be 49.0
[javac] Please remove or make sure it appears in the correct subdirectory of the classpath.
[javac] import com.google.appengine.demos.jdoexamples.AddressBookEntry;
[javac] ^
[javac] 1 error
Have you ever seen it yet?
Can you help me?

java.padawan said...

Hi Winai,

"class file has wrong version 50.0, should be 49.0"

You may have the wrong JDK version. Kindly check if your are using Java 1.5 or use 1.6 if it still does not work.

Type "java -version" on the command line

If that does not work, maybe the AppEngine version you are using is an older version. Upgrade to a newer one.

I cannot remember getting this problem before, but I also encountered a compile/build problem when I upgraded to AppEngine SDK 1.2.2, I just right click on the project, then properties, then expanded the Google tree menu, then selected the App Engine entry. Then chose App Engine SDK 1.2.2.

Winai said...

I still have problem when I install
google app 1.2.2.
HTTP ERROR: 503
SERVICE_UNAVAILABLE
RequestURI=/
Can you help me?

java.padawan said...

Hi Winai,

There's something wrong with your code. It's not an app engine problem anymore.

If you are using eclipse, try just creating a simple project without GWT.

You should have a hello world servlet working. Then work from there.

PhamThai said...

Hi you!!
please give me a full source code of beer radar application!
Thanks you very much

Unknown said...

hey really liked ur work...i am currently working on my final year project(movie finder in android)...i would be really grateful if u could plzzz mail(dexterlab11@gmail.com) me the full source code of beer radar application.
thank you

Anonymous said...

hey really liked ur work...i am currently working on my final year project(movie finder in android)..could u plzz mail me the entire source code of ur beer radar application..
thank you

Unknown said...

hey really liked ur work...i am currently working on my final year project(movie finder in android)..could u plzz mail me the entire source code of ur beer radar application..
thank you

Anonymous said...

hey really liked ur work...i am currently working on my final year project(movie finder in android)..could u plzz mail me the entire source code of ur beer radar application..
thank you

ASTX813 said...

I notice in your Beer class, you don't have a constructor. How are you creating & setting the id field? Is that being handled by the persistence manager since it is tagged as the primary key?

Great writeup, I'm following your tutorial project, and so far it has been the most helpful information I've found since I've started learning Android!

java.padawan said...

@ASTX813

The JDO persistence manager handles setting and getting via the getter and setter methods.

As for creating the Object from the fields, you need to set the files one by one.

Thanks for appreciating my site, I was not able to update it anymore, although I'm still trying to experiment on some android app when I get some spare time.

Thanks

Email

java.padawan@androidph.com