Friday, March 9, 2012

Create Semi Transparent Rounded Border Image in Android

Hey, I am back.

In the earlier post, if you do notice that I wrote that I'm about to enter new chapter of life. It's been months and you are still waiting to know what I've been up to. I promised, it's coming pretty soon. In about a month time. :) 

Lots of things happened these days, lots of things not sorted out, and I've to work it out one after another all in a short time span. Life is pretty busy. 

Anyway, this Android passion drives my adrenaline. Here comes another Android stuff.

The tutorial is derived from Eric Burke's talk: Taming Android UIs with Eric Burke of Square I won't focus on the entire talk.

The only stuff I will focus is creating the semi transparent rounded border image in Android. Actually half of the codes is available in the talk itself. I just tried to complete/translate what he is presenting into a set of runnable codes.



Create Rounded Image

Drawable imageDrawable = (image != null) ? new BitmapDrawable(image) : placeHolder; Bitmap output = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(output); RectF outerRect = new RectF(0, 0, size, size); float cornerRadius = size / 10f; Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setColor(Color.RED); canvas.drawRoundRect(outerRect, cornerRadius, cornerRadius, paint); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); imageDrawable.setBounds(0, 0, size, size); // Save the layer to apply the paint canvas.saveLayer(outerRect, paint, Canvas.ALL_SAVE_FLAG); imageDrawable.draw(canvas); canvas.restore();
The above code will produce the following image, nice rounded corner


Create Frame

There are several steps in creating frame. The same principle is used here in composing the image (creating frame).
  1. Create offscreen bitmap Go direct to YouTube screen 
  2. Draw an opaque rounded rectangle Go direct to YouTube screen  
  3. Set the Power Duff mode  Go direct to YouTube screen  
  4. Draw a translucent rounded rectangle Go direct to YouTube screen  


Step 1. Create offscreen bitmap

// 1. Create offscreen bitmap link: http://www.youtube.com/watch?feature=player_detailpage&v=jF6Ad4GYjRU#t=1035s Bitmap framedOutput = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); Canvas framedCanvas = new Canvas(framedOutput); // End of Step 1 // Start Dummy Step - TODO IMPORTANT - this section shouldn't be included in the final code // It's needed here to differentiate step 2 (red) with the background color of the activity // It's should be commented out after the codes includes step 3 onwards Paint squaredPaint = new Paint(Paint.ANTI_ALIAS_FLAG); squaredPaint.setColor(Color.BLUE); framedCanvas.drawRoundRect(outerRect, 0f, 0f, squaredPaint); // End
Step 2. Draw an opaque rounded rectangle

// 2. Draw an opaque rounded rectangle link: // http://www.youtube.com/watch?feature=player_detailpage&v=jF6Ad4GYjRU#t=1044s RectF innerRect = new RectF(border, border, size - border, size - border); Paint innerPaint = new Paint(Paint.ANTI_ALIAS_FLAG); innerPaint.setColor(Color.RED); framedCanvas.drawRoundRect(innerRect, cornerRadius, cornerRadius, innerPaint);
Step 3. Set the Power Duff mode
Step 4. Draw a translucent rounded rectangle
From step 3 onwards, I will comment out "Dummy Step" in step 1. The reason why we put the code in the first place is ti differentiate the background color of the activity with the color of the widget.

// 1. Create offscreen bitmap link: http://www.youtube.com/watch?feature=player_detailpage&v=jF6Ad4GYjRU#t=1035s Bitmap framedOutput = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); Canvas framedCanvas = new Canvas(framedOutput); // End of Step 1 // Start - TODO IMPORTANT - this section shouldn't be included in the final code // It's needed here to differentiate step 2 (red) with the background color of the activity // It's should be commented out after the codes includes step 3 onwards // Paint squaredPaint = new Paint(Paint.ANTI_ALIAS_FLAG); // squaredPaint.setColor(Color.BLUE); // framedCanvas.drawRoundRect(outerRect, 0f, 0f, squaredPaint); // End // 2. Draw an opaque rounded rectangle link: // http://www.youtube.com/watch?feature=player_detailpage&v=jF6Ad4GYjRU#t=1044s RectF innerRect = new RectF(border, border, size - border, size - border); Paint innerPaint = new Paint(Paint.ANTI_ALIAS_FLAG); innerPaint.setColor(Color.RED); framedCanvas.drawRoundRect(innerRect, cornerRadius, cornerRadius, innerPaint); // 3. Set the Power Duff mode // http://www.youtube.com/watch?feature=player_detailpage&v=jF6Ad4GYjRU#t=1056s Paint outerPaint = new Paint(Paint.ANTI_ALIAS_FLAG); outerPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT)); // 4. Draw a translucent rounded rectangle link: // http://www.youtube.com/watch?feature=player_detailpage&v=jF6Ad4GYjRU outerPaint.setColor(Color.argb(100, 0, 0, 0)); framedCanvas.drawRoundRect(outerRect, cornerRadius, cornerRadius, outerPaint);
Create Semi Transparent Rounded Border Image
Now that we have both semi transparent framed image and rounded image, we have to combine both images into one.
Last Step. Draw the frame on top of original bitmap


private void createFramedPhoto(int size) { Drawable imageDrawable = (image != null) ? new BitmapDrawable(image) : placeHolder; Bitmap output = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(output); RectF outerRect = new RectF(0, 0, size, size); float cornerRadius = size / 18f; Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setColor(Color.RED); canvas.drawRoundRect(outerRect, cornerRadius, cornerRadius, paint); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); imageDrawable.setBounds(0, 0, size, size); // Save the layer to apply the paint canvas.saveLayer(outerRect, paint, Canvas.ALL_SAVE_FLAG); imageDrawable.draw(canvas); canvas.restore(); // FRAMING THE PHOTO float border = size / 15f; // 1. Create offscreen bitmap link: // http://www.youtube.com/watch?feature=player_detailpage&v=jF6Ad4GYjRU#t=1035s Bitmap framedOutput = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); Canvas framedCanvas = new Canvas(framedOutput); // End of Step 1 // Start - TODO IMPORTANT - this section shouldn't be included in the final code // It's needed here to differentiate step 2 (red) with the background color of the activity // It's should be commented out after the codes includes step 3 onwards // Paint squaredPaint = new Paint(Paint.ANTI_ALIAS_FLAG); // squaredPaint.setColor(Color.BLUE); // framedCanvas.drawRoundRect(outerRect, 0f, 0f, squaredPaint); // End // 2. Draw an opaque rounded rectangle link: // http://www.youtube.com/watch?feature=player_detailpage&v=jF6Ad4GYjRU#t=1044s RectF innerRect = new RectF(border, border, size - border, size - border); Paint innerPaint = new Paint(Paint.ANTI_ALIAS_FLAG); innerPaint.setColor(Color.RED); framedCanvas.drawRoundRect(innerRect, cornerRadius, cornerRadius, innerPaint); // 3. Set the Power Duff mode // http://www.youtube.com/watch?feature=player_detailpage&v=jF6Ad4GYjRU#t=1056s Paint outerPaint = new Paint(Paint.ANTI_ALIAS_FLAG); outerPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT)); // 4. Draw a translucent rounded rectangle link: // http://www.youtube.com/watch?feature=player_detailpage&v=jF6Ad4GYjRU outerPaint.setColor(Color.argb(100, 0, 0, 0)); framedCanvas.drawRoundRect(outerRect, cornerRadius, cornerRadius, outerPaint); // Draw the frame on top of original bitmap canvas.drawBitmap(framedOutput, 0f, 0f, null); framedPhoto = output; }
Tada!

Things to note:
  • You may notice that it's slightly different from what Eric Burke presented. It doesn't support editable photo. You may add OnClickListener and adjust the bottom border on Step 2.
  • No code refactoring is done here, so it needs one.
  • You may grab the source code at github
Thanks to Eric Burke

Saturday, October 1, 2011

Android: AsyncTaskLoader Exception Handling

Been months that I dont drop by here, and here on the weekend spending time to code blog...

On a side note: I'm about to enter new chapter of life, things are going to be very exciting and unpredictable in equal measure in the next few months. I'm so much looking forward into that :)

Okay, back to the topic.

While doing the implementation of AsyncTaskLoader, I realized that it doesn't provide a straightforward mechanism to handle exception. I googled it up, and found this thread. Google engineer suggested the following:

As far as errors from loaders, the design is that there are no errors as such. Ultimately they need to deliver a result back to the activity/fragment.  If your result can include an error state, then this should be part of the result you deliver.  This should be as simple as wrapping your result data in a container class that has it and the error state, and making that the result. 

With that in mind, I coded the following wrapper class to wrap the result of the loader:


package com.test;

public class AsyncResult< D > {
	private Exception exception;
	private D data;

	public void setException(Exception exception) {
		this.exception = exception;
	}

	public Exception getException() {
		return exception;
	}

	public void setData(D data) {
		this.data = data;
	}

	public D getData() {
		return data;
	}

}



And the loader class will be implemented like the following:
package com.test;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.support.v4.content.AsyncTaskLoader;

public class MyAsyncTaskLoader extends AsyncTaskLoader< AsyncResult < List < String >>> {
	private AsyncResult< List < String >> data;

	public MyAsyncTaskLoader(Context context) {
		super(context);
	}

	@Override
	public void deliverResult(AsyncResult < List < String>> data) {
		if (isReset()) {
			// a query came in while the loader is stopped
			return;
		}

		this.data = data;

		super.deliverResult(data);
	}

	@Override
	public AsyncResult< List < String >> loadInBackground() {
		AsyncResult< List< String>> result = new AsyncResult< List< String >>();

		List< String> dataList = null;

		try {
			dataList = new ArrayList< String>();

			// load data in background
			// when exception occurs, it should be caught

		} catch (Exception ex) {
			result.setException(ex);
		}

		result.setData(dataList);

		return result;
	}

	@Override
	protected void onStartLoading() {
		if (data != null) {
			deliverResult(data);
		}

		if (takeContentChanged() || data == null) {
			forceLoad();
		}
	}

	@Override
	protected void onStopLoading() {
		cancelLoad();
	}

	@Override
	protected void onReset() {
		super.onReset();

		onStopLoading();

		data = null;
	}
}


And here I handled the exception in onLoadFinished by checking if the exception in the wrapper class is not null.
private final LoaderCallbacks< AsyncResult < List < String >>> loaderCallbacks = new LoaderCallbacks< AsyncResult< List < String >>>() {

		@Override
		public Loader< AsyncResult < List < String>>> onCreateLoader(int id, Bundle args) {
			MyAsyncTaskLoader loader = new MyAsyncTaskLoader(TestActivity.this);
			loader.setUpdateThrottle(1000);

			return loader;
		}

		@Override
		public void onLoadFinished(Loader < AsyncResult < List < String >>> loader, final AsyncResult< List < String >> result) {

			Exception exception = result.getException();
			if (exception != null) {
				Toast.makeText(TestActivity.this, exception.getMessage(), Toast.LENGTH_SHORT).show();
			} else {
				// process the result
			}
		}

		@Override
		public void onLoaderReset(Loader < AsyncResult < List < String >>> loader) {
			loader.reset();
		}
	};


And we are done with the implementation and exception handling!

If you have better implementation, please feel free to give feedback.

 The entire source code could be found in github

Sunday, May 29, 2011

Invalid Key error - Facebook Android SDK Integration

Command used to generate the key hash of android application:

keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore 
| openssl sha1 -binary
| openssl base64

The Invalid Key issue might occur if you execute the above command in Windows Console.

I fixed the issue by running the command in other console like cygwin or Git Bash.


PS: the key hash generated in Windows Console and Cygwin/Git Bash are different from each other.

Reference: Facebook Mobile Apps Guide

Wednesday, March 23, 2011

Execute command after finding files in Unix

Find the list of files and perform operation on those files.

e.g. Find a list of files under current directory and sub-directories and move it to /tmp/newfolder

> find . -type f -exec mv {} /tmp/newfolder \;

> 



Reference:
find exec

Monday, March 21, 2011

Extract numbers / digits from a string in Unix

sed utility comes in handy to search and replace the string.

> man sed
  
  ...

  s/regexp/replacement/
       Attempt to match regexp against the pattern space.  If  success-
       ful,   replace  that  portion  matched  with  replacement.   The
       replacement may contain the special character & to refer to that
       portion  of  the pattern  space which matched, and the special
       escapes \1 through \9 to refer  to  the  corresponding  matching
       sub-expressions in the regexp.

  ...


If we would like to extract numbers / digits from a string, we can do the following command:

> echo "abc123def" | sed 's/[a-z]//g';

> 123


voila!

Reference:
sed

Wednesday, September 22, 2010

Sending email with message body and multiple attachments in 1 line Unix command

> (echo "message body"; uuencode file1.txt file1.txt; uuencode file2.txt file2.txt) | mailx -s "message subject" test@test.com

>



Reference:
uuencode
mailx

Maven GAE Integration Step by Step Tutorial

I have been playing around with Google AppEngine for quite sometimes. However, I always wanted to create a project to make full use of Maven dependency management. And here it goes to the integration of Maven with Google AppEngine.


Software Requirements

1. Google AppEngine SDK 1.3.7
2. Maven v2.2.0
3. Maven-gae-plugin v0.7.1


Step 1. Create Maven GAE Project by typing the following command in the console

D:\workspace\sources>mvn archetype:create -DarchetypeGroupId=net.kindleit -DarchetypeArtifactId=gae-archetype-jsp -DarchetypeVersion=0.7.1 -DgroupId=com.gn.gae -DartifactId=maven-gae-template
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'archetype'.
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Default Project
[INFO]    task-segment: [archetype:create] (aggregator-style)
[INFO] ------------------------------------------------------------------------
[INFO] Setting property: classpath.resource.loader.class => 'org.codehaus.plexus.velocity.ContextClassLoaderResourceLoader'.
[INFO] Setting property: velocimacro.messages.on => 'false'.
[INFO] Setting property: resource.loader => 'classpath'.
[INFO] Setting property: resource.manager.logwhenfound => 'false'.
[INFO] [archetype:create {execution: default-cli}]
[WARNING] This goal is deprecated. Please use mvn archetype:generate instead
[INFO] Defaulting package to group ID: com.gn.gae
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating OldArchetype: gae-archetype-jsp:0.7.1
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.gn.gae
[INFO] Parameter: packageName, Value: com.gn.gae
[INFO] Parameter: package, Value: com.gn.gae
[INFO] Parameter: artifactId, Value: maven-gae-template
[INFO] Parameter: basedir, Value: D:\workspace\sources
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[WARNING] org.apache.velocity.runtime.exception.ReferenceException: reference : template = archetype-resources/pom.xml [line 12,column 9] : ${name} is not a valid reference.
[WARNING] org.apache.velocity.runtime.exception.ReferenceException: reference : template = archetype-resources/pom.xml [line 13,column 16] : ${description} is not a valid reference.
[WARNING] org.apache.velocity.runtime.exception.ReferenceException: reference : template = archetype-resources/pom.xml [line 184,column 42] : ${gaePluginVersion} is not a valid reference.
[WARNING] org.apache.velocity.runtime.exception.ReferenceException: reference : template = archetype-resources/pom.xml [line 229,column 47] : ${gae.home} is not a valid reference.
[WARNING] org.apache.velocity.runtime.exception.ReferenceException: reference : template = archetype-resources/pom.xml [line 232,column 30] : ${gaeVersion} is not a valid reference.
[INFO] ********************* End of debug info from resources from generated POM ***********************
[WARNING] org.apache.velocity.runtime.exception.ReferenceException: reference : template = archetype-resources/src/main/webapp/index.jsp [line 13,column 37] : ${messages} is not a valid reference.
[WARNING] org.apache.velocity.runtime.exception.ReferenceException: reference : template = archetype-resources/src/main/webapp/index.jsp [line 15,column 28] : ${message.text} is not a valid reference.
[WARNING] org.apache.velocity.runtime.exception.ReferenceException: reference : template = archetype-resources/src/main/webapp/index.jsp [line 16,column 46] : ${message.id} is not a valid reference.
[WARNING] org.apache.velocity.runtime.exception.ReferenceException: reference : template = archetype-resources/src/main/webapp/WEB-INF/appengine-web.xml [line 4,column 18] : $gaeApplicationName is not a valid reference.
[WARNING] org.apache.velocity.runtime.exception.ReferenceException: reference : template = archetype-resources/src/main/webapp/WEB-INF/appengine-web.xml [line 5,column 14] : $gaeApplicationVersion is not a valid reference.
[INFO] OldArchetype created in dir: D:\workspace\sources\maven-gae-template
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3 seconds
[INFO] Finished at: Sun Sep 05 19:04:10 GMT+08:00 2010
[INFO] Final Memory: 7M/14M
[INFO] ------------------------------------------------------------------------
D:\workspace\sources>


Step 2. Change the value of properties in pom.xml

As there is some warning found in the console, we have to provide the value of those properties in the pom.xml

${name} => maven-gae-template
${description} => Maven GAE Template
${gaePluginVersion} => 0.7.1
${gae.home}=> Google AppEngine SDK root folder
${gae.version} => 1.3.7

Snippet of pom.xml BEFORE the changes:

...
  {name}
  ${description}
...

...
${gae.version}
...


Snippet of pom.xml AFTER the changes:

...
  maven-gae-template
  Maven GAE Template
...

...
D:\appengine-java-sdk-1.3.7
0.7.1
1.3.7
...


Please refer to pom.xml


Step 3. Fix package name of the generated code.

The current goal of maven-gae-plugin will generate incorrect Java packages. Basically we have to change four files.

Go to <workspace>\maven-gae-template\src\main\java\com\gn\gae\model\Message.java

Please change it to the following snippet. The commented one is before the change, whereas the uncommented one is after the change.

//package com.gn.gae;
package com.gn.gae.model;

Go to <workspace>\maven-gae-template\src\main\java\com\gn\gae\server\MessageRepository.java

//package com.gn.gae;
package com.gn.gae.server;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.jdo.Extent;
import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;

//import net.kindleit.gae.example.model.Message;
import com.gn.gae.model.Message;

Go to <workspace>\maven-gae-template\src\main\java\com\gn\gae\web\IndexServlet.java

//package com.gn.gae;
package com.gn.gae.web;

import java.io.IOException;
import java.util.Collection;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

//import net.kindleit.gae.example.model.Message;
//import net.kindleit.gae.example.server.MessageRepository;
import com.gn.gae.model.Message;
import com.gn.gae.server.MessageRepository;

Go to <workspace>\maven-gae-template\src\main\webapp\WEB-INF\web.xml


        IndexServlet
        
            
     com.gn.gae.web.IndexServlet
        
    


Step 4. Try to compile after we have made the changes

D:\workspace\sources>cd maven-gae-template

D:\workspace\sources\maven-gae-template>mvn clean compile
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building maven-gae-template
[INFO]    task-segment: [clean, compile]
[INFO] ------------------------------------------------------------------------
[INFO] [clean:clean {execution: default-clean}]
[INFO] [resources:resources {execution: default-resources}]
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 4 resources
[INFO] [compiler:compile {execution: default-compile}]
Compiling 3 source files to D:\workspace\sources\maven-gae-template\target\classes
[INFO] ------------------------------------------------------------------------
[ERROR] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Compilation failure

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\model\Message.java:[6,28] package javax.jdo.annotations does not exist

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\model\Message.java:[7,28] package javax.jdo.annotations does not exist

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\model\Message.java:[8,28] package javax.jdo.annotations does not exist

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\model\Message.java:[9,28] package javax.jdo.annotations does not exist

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\model\Message.java:[10,28] package javax.jdo.annotations does not exist

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\model\Message.java:[12,1] cannot find symbol
symbol: class PersistenceCapable
@PersistenceCapable(identityType = IdentityType.APPLICATION)

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\server\MessageRepository.java:[9,16] package javax.jdo does not exist

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\server\MessageRepository.java:[10,16] package javax.jdo does not exist

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\server\MessageRepository.java:[11,16] package javax.jdo does not exist

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\server\MessageRepository.java:[12,16] package javax.jdo does not exist

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\server\MessageRepository.java:[15,23] cannot find symbol
symbol  : class Messsage
location: package com.gn.gae.model

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\server\MessageRepository.java:[19,1] cannot find symbol
symbol  : class PersistenceManagerFactory
location: class com.gn.gae.server.MessageRepository

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\server\MessageRepository.java:[21,19] cannot find symbol
symbol  : class Message
location: class com.gn.gae.server.MessageRepository

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\server\MessageRepository.java:[37,20] cannot find symbol
symbol  : class Message
location: class com.gn.gae.server.MessageRepository

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\web\IndexServlet.java:[16,23] cannot find symbol
symbol  : class Messsage
location: package com.gn.gae.model

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\web\IndexServlet.java:[17,24] cannot find symbol
symbol  : class MesssageRepository
location: package com.gn.gae.server

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\web\IndexServlet.java:[28,9] cannot find symbol
symbol  : class MessageRepository
location: class com.gn.gae.web.IndexServlet

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\model\Message.java:[17,5] cannot find symbol
symbol  : class PrimaryKey
location: class com.gn.gae.messsage.Message

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\model\Message.java:[18,5] cannot find symbol
symbol  : class Persistent
location: class com.gn.gae.messsage.Message

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\model\Message.java:[21,5] cannot find symbol
symbol  : class Persistent
location: class com.gn.gae.messsage.Message

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\server\MessageRepository.java:[19,41] cannot find symbol
symbol  : variable JDOHelper
location: class com.gn.gae.server.MessageRepository

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\server\MessageRepository.java:[22,2] cannot find symbol
symbol  : class PersistenceManager
location: class com.gn.gae.server.MessageRepository

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\server\MessageRepository.java:[24,8] cannot find symbol
symbol  : class Message
location: class com.gn.gae.server.MessageRepository

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\server\MessageRepository.java:[24,42] cannot find symbol
symbol  : class Message
location: class com.gn.gae.server.MessageRepository

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\server\MessageRepository.java:[25,6] cannot find symbol
symbol  : class Extent
location: class com.gn.gae.server.MessageRepository

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\server\MessageRepository.java:[25,13] cannot find symbol
symbol  : class Message
location: class com.gn.gae.server.MessageRepository

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\server\MessageRepository.java:[25,44] cannot find symbol
symbol  : class Message
location: class com.gn.gae.server.MessageRepository

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\server\MessageRepository.java:[26,11] cannot find symbol
symbol  : class Message
location: class com.gn.gae.server.MessageRepository

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\server\MessageRepository.java:[38,2] cannot find symbol
symbol  : class PersistenceManager
location: class com.gn.gae.server.MessageRepository

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\server\MessageRepository.java:[47,2] cannot find symbol
symbol  : class PersistenceManager
location: class com.gn.gae.server.MessageRepository

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\server\MessageRepository.java:[49,40] cannot find symbol
symbol  : class Message
location: class com.gn.gae.server.MessageRepository

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\web\IndexServlet.java:[28,51] cannot find symbol
symbol  : class MessageRepository
location: class com.gn.gae.web.IndexServlet

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\web\IndexServlet.java:[47,13] cannot find symbol
symbol  : class Message
location: class com.gn.gae.web.IndexServlet

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\web\IndexServlet.java:[76,2] cannot find symbol
symbol  : class Message
location: class com.gn.gae.web.IndexServlet

D:\workspace\sources\maven-gae-template\src\main\java\com\gn\gae\web\IndexServlet.java:[76,24] cannot find symbol
symbol  : class Message
location: class com.gn.gae.web.IndexServlet

[INFO] ------------------------------------------------------------------------
[INFO] For more information, run Maven with the -e switch
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4 seconds
[INFO] Finished at: Sun Sep 05 19:30:25 GMT+08:00 2010
[INFO] Final Memory: 12M/25M
[INFO] ------------------------------------------------------------------------
D:\workspace\sources\maven-gae-template>

From the output, we could see that it couldn't find JDO library. Thus we have to add JDO dependency to pom.xml. FYI, pom.xml, generated by maven-gae-plugin, contains few problems that we have to fix.


Step 5. Fix JDO Library Dependency

Open pom.xml, add the following snippet into XML tag.


            javax.jdo
            jdo2-api
            2.3-eb
            
                
                    javax.transaction
                    transaction-api
                
            
        

Run mvn clean compile again (Refer to Step 4)

D:\workspace\sources\maven-gae-template>mvn clean compile
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building maven-gae-template
[INFO]    task-segment: [clean, compile]
[INFO] ------------------------------------------------------------------------
[INFO] [clean:clean {execution: default-clean}]
[INFO] Deleting directory D:\workspace\sources\maven-gae-template\target
[INFO] [resources:resources {execution: default-resources}]
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 4 resources
[INFO] [compiler:compile {execution: default-compile}]
Compiling 3 source files to D:\workspace\sources\maven-gae-template\target\classes
[INFO] artifact asm:asm: checking for updates from maven-gae-plugin-repo
[INFO] artifact asm:asm: checking for updates from DN_M2_Repo
[INFO] artifact asm:asm: checking for updates from local.repository
[INFO] artifact javax.jdo:jdo2-api: checking for updates from maven-gae-plugin-repo
[INFO] artifact org.datanucleus:datanucleus-jpa: checking for updates from maven-gae-plugin-repo
[INFO] [datanucleus:enhance {execution: default}]
[INFO]
[ERROR] --------------------
[ERROR]  Standard error from the DataNucleus tool + org.datanucleus.enhancer.DataNucleusEnhancer :
[ERROR] --------------------
[ERROR] Sep 5, 2010 7:54:43 PM org.datanucleus.enhancer.DataNucleusEnhancer 
INFO: DataNucleus Enhancer : Using ClassEnhancer "ASM" for API "JDO"
Exception in thread "main" Plugin (Bundle) "org.datanucleus" is already registered. Ensure you dont have multiple JAR versions of the same plugin in t
he classpath. The URL "file:/D:/workspace/repository/com/google/appengine/orm/datanucleus-core/1.1.5/datanucleus-core-1.1.5.jar" is already registered
, and you are trying to register an identical plugin located at URL "file:/D:/workspace/repository/org/datanucleus/datanucleus-core/1.1.5/datanucleus-
core-1.1.5.jar."
org.datanucleus.exceptions.NucleusException: Plugin (Bundle) "org.datanucleus" is already registered. Ensure you dont have multiple JAR versions of th
e same plugin in the classpath. The URL "file:/D:/workspace/repository/com/google/appengine/orm/datanucleus-core/1.1.5/datanucleus-core-1.1.5.jar" is
already registered, and you are trying to register an identical plugin located at URL "file:/D:/workspace/repository/org/datanucleus/datanucleus-core/
1.1.5/datanucleus-core-1.1.5.jar."
        at org.datanucleus.plugin.NonManagedPluginRegistry.registerBundle(NonManagedPluginRegistry.java:434)
        at org.datanucleus.plugin.NonManagedPluginRegistry.registerBundle(NonManagedPluginRegistry.java:340)
        at org.datanucleus.plugin.NonManagedPluginRegistry.registerExtensions(NonManagedPluginRegistry.java:222)
        at org.datanucleus.plugin.NonManagedPluginRegistry.registerExtensionPoints(NonManagedPluginRegistry.java:153)
        at org.datanucleus.plugin.PluginManager.registerExtensionPoints(PluginManager.java:82)
        at org.datanucleus.OMFContext.(OMFContext.java:160)
        at org.datanucleus.enhancer.DataNucleusEnhancer.(DataNucleusEnhancer.java:172)
        at org.datanucleus.enhancer.DataNucleusEnhancer.(DataNucleusEnhancer.java:150)
        at org.datanucleus.enhancer.DataNucleusEnhancer.main(DataNucleusEnhancer.java:1157)

[ERROR] --------------------
[INFO] ------------------------------------------------------------------------
[ERROR] BUILD ERROR
[INFO] ------------------------------------------------------------------------
[INFO] The DataNucleus tool org.datanucleus.enhancer.DataNucleusEnhancer exited with a non-null exit code.
[INFO] ------------------------------------------------------------------------
[INFO] For more information, run Maven with the -e switch
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 12 seconds
[INFO] Finished at: Sun Sep 05 19:54:43 GMT+08:00 2010
[INFO] Final Memory: 12M/24M
[INFO] ------------------------------------------------------------------------
D:\workspace\sources\maven-gae-template>


From the error output, it looks like maven was trying to register two exact libraries, means that we have two sets of same library in the classpath.

Step 6. Fix DataNucleus Library Duplication

Comment out net.kindleit dependency under XML tag in pom.xml. Somehow gae-runtime in maven-gae-plugin contains JDO library

...
    

Run mvn clean compile again (Refer to Step 4)

D:\workspace\sources\maven-gae-template>mvn clean compile
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building maven-gae-template
[INFO]    task-segment: [clean, compile]
[INFO] ------------------------------------------------------------------------
[INFO] [clean:clean {execution: default-clean}]
[INFO] Deleting directory D:\workspace\sources\maven-gae-template\target
[INFO] [resources:resources {execution: default-resources}]
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 4 resources
[INFO] [compiler:compile {execution: default-compile}]
Compiling 3 source files to D:\workspace\sources\maven-gae-template\target\classes
[INFO] [datanucleus:enhance {execution: default}]
[INFO] DataNucleus Enhancer (version 1.1.4) : Enhancement of classes
DataNucleus Enhancer : Classpath
>>  D:\workspace\repository\org\datanucleus\datanucleus-core\1.1.5\datanucleus-core-1.1.5.jar
>>  D:\workspace\repository\org\datanucleus\datanucleus-rdbms\1.1.5\datanucleus-rdbms-1.1.5.jar
>>  D:\workspace\repository\javax\transaction\transaction-api\1.1\transaction-api-1.1.jar
>>  D:\workspace\repository\org\datanucleus\datanucleus-enhancer\1.1.4\datanucleus-enhancer-1.1.4.jar
>>  D:\workspace\repository\asm\asm\3.2\asm-3.2.jar
>>  D:\workspace\repository\javax\jdo\jdo2-api\2.3-ec\jdo2-api-2.3-ec.jar
>>  D:\workspace\repository\javax\transaction\jta\1.1\jta-1.1.jar
>>  D:\workspace\repository\org\datanucleus\datanucleus-jpa\1.1.5\datanucleus-jpa-1.1.5.jar
>>  D:\workspace\repository\org\apache\geronimo\specs\geronimo-jpa_3.0_spec\1.1.1\geronimo-jpa_3.0_spec-1.1.1.jar
>>  D:\workspace\repository\javax\persistence\persistence-api\1.0\persistence-api-1.0.jar
>>  D:\workspace\repository\org\codehaus\plexus\plexus-utils\1.2\plexus-utils-1.2.jar
>>  D:\workspace\tools\apache-maven-2.2.0\lib\maven-2.2.0-uber.jar
>>  D:\workspace\sources\maven-gae-template\target\classes
>>  D:\workspace\repository\org\slf4j\slf4j-api\1.6.1\slf4j-api-1.6.1.jar
>>  D:\workspace\repository\ch\qos\logback\logback-classic\0.9.24\logback-classic-0.9.24.jar
>>  D:\workspace\repository\ch\qos\logback\logback-core\0.9.24\logback-core-0.9.24.jar
>>  D:\workspace\repository\javax\jdo\jdo2-api\2.3-eb\jdo2-api-2.3-eb.jar
ENHANCED (PersistenceCapable) : com.gn.gae.model.Message
DataNucleus Enhancer completed with success for 1 classes. Timings : input=218 ms, enhance=110 ms, total=328 ms. Consult the log for full details

[ERROR] --------------------
[ERROR]  Standard error from the DataNucleus tool + org.datanucleus.enhancer.DataNucleusEnhancer :
[ERROR] --------------------
[ERROR] Sep 5, 2010 7:59:22 PM org.datanucleus.enhancer.DataNucleusEnhancer 
INFO: DataNucleus Enhancer : Using ClassEnhancer "ASM" for API "JDO"
Sep 5, 2010 7:59:23 PM org.datanucleus.plugin.NonManagedPluginRegistry resolveConstraints
INFO: Bundle "org.datanucleus" has an optional dependency to "org.eclipse.equinox.registry" but it cannot be resolved
Sep 5, 2010 7:59:23 PM org.datanucleus.plugin.NonManagedPluginRegistry resolveConstraints
INFO: Bundle "org.datanucleus" has an optional dependency to "org.eclipse.core.runtime" but it cannot be resolved
Sep 5, 2010 7:59:23 PM org.datanucleus.enhancer.DataNucleusEnhancer main
INFO: DataNucleus Enhancer (version 1.1.4) : Enhancement of classes
Sep 5, 2010 7:59:23 PM org.datanucleus.jdo.metadata.JDOAnnotationReader processClassAnnotations
INFO: Class "com.gn.gae.model.Message" has been specified with JDO annotations so using those.
Sep 5, 2010 7:59:23 PM org.datanucleus.enhancer.asm.ASMClassEnhancer save
INFO: Updating class file "file:/D:/workspace/sources/maven-gae-template/target/classes/com/gn/gae/model/Message.class" with enhanced definition
Sep 5, 2010 7:59:23 PM org.datanucleus.enhancer.DataNucleusEnhancer addMessage
INFO: ENHANCED (PersistenceCapable) : com.gn.gae.model.Message
Sep 5, 2010 7:59:23 PM org.datanucleus.enhancer.DataNucleusEnhancer addMessage
INFO: DataNucleus Enhancer completed with success for 1 classes. Timings : input=218 ms, enhance=110 ms, total=328 ms. Consult the log for full detail
s

[ERROR] --------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5 seconds
[INFO] Finished at: Sun Sep 05 19:59:23 GMT+08:00 2010
[INFO] Final Memory: 13M/24M
[INFO] ------------------------------------------------------------------------
D:\workspace\sources\maven-gae-template>


Voila! We have built it successfully. There is DataNucleus error found in the output, somehow, we could ignore it, because the only thing we care is the "BUILD SUCCESSFUL" keyword.


Step 7. Add repository into pom.xml

Add maven-gae-plugin repository so that maven knows where to download Google AppEngine dependencies


  
            maven-gae-plugin-repo
            http://maven-gae-plugin.googlecode.com/svn/repository
            maven-gae-plugin repository
        
   


Step 8. Add GAE Runtime library dependencies

Since we have disabled the GAE-runtime dependencies (Refer to Step 6), we have to include manually here in pom.xml. Please add the following snippet into XML tag in pom.xml For the complete contents of pom.xml, please refer to pom.xml


            com.google.appengine.orm
            datanucleus-appengine
            1.0.6.final
        
  
            org.datanucleus
            datanucleus-core
            1.1.5
            runtime
            
                
                    javax.transaction
                    transaction-api
                
            
        

     
     com.google.appengine
     appengine-api-1.0-sdk
     ${gae.version}
  

  
     com.google.appengine
     geronimo-jta_1.1_spec
     1.1.1
     runtime
  

  
     com.google.appengine
     geronimo-jpa_3.0_spec
     1.1.1
     runtime
  

  
     com.google.appengine.orm
     datanucleus-appengine
     1.0.7.final
     runtime
  

  
     com.google.appengine
     datanucleus-jpa
     1.1.5
     runtime
  

  
     com.google.appengine
     appengine-tools-api
     ${gae.version}
  


Step 9. Time to run the GAE web app in local

D:\workspace\sources\maven-gae-template>mvn gae:run
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building maven-gae-template
[INFO]    task-segment: [gae:run]
[INFO] ------------------------------------------------------------------------
[INFO] Preparing gae:run
[INFO] [resources:resources {execution: default-resources}]
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 4 resources
Downloading: http://maven-gae-plugin.googlecode.com/svn/repository/com/google/appengine/appengine-tools-api/1.3.7/appengine-tools-api-1.3.7.pom
412b downloaded  (appengine-tools-api-1.3.7.pom)
Downloading: http://maven-gae-plugin.googlecode.com/svn/repository/com/google/appengine/appengine-tools-api/1.3.7/appengine-tools-api-1.3.7.jar
8044K downloaded  (appengine-tools-api-1.3.7.jar)
[INFO] [compiler:compile {execution: default-compile}]
[INFO] Nothing to compile - all classes are up to date
[INFO] [datanucleus:enhance {execution: default}]
[INFO] DataNucleus Enhancer (version 1.1.4) : Enhancement of classes
DataNucleus Enhancer : Classpath
>>  D:\workspace\repository\org\datanucleus\datanucleus-core\1.1.5\datanucleus-core-1.1.5.jar
>>  D:\workspace\repository\org\datanucleus\datanucleus-rdbms\1.1.5\datanucleus-rdbms-1.1.5.jar
>>  D:\workspace\repository\javax\transaction\transaction-api\1.1\transaction-api-1.1.jar
>>  D:\workspace\repository\org\datanucleus\datanucleus-enhancer\1.1.4\datanucleus-enhancer-1.1.4.jar
>>  D:\workspace\repository\asm\asm\3.2\asm-3.2.jar
>>  D:\workspace\repository\javax\jdo\jdo2-api\2.3-ec\jdo2-api-2.3-ec.jar
>>  D:\workspace\repository\javax\transaction\jta\1.1\jta-1.1.jar
>>  D:\workspace\repository\org\datanucleus\datanucleus-jpa\1.1.5\datanucleus-jpa-1.1.5.jar
>>  D:\workspace\repository\org\apache\geronimo\specs\geronimo-jpa_3.0_spec\1.1.1\geronimo-jpa_3.0_spec-1.1.1.jar
>>  D:\workspace\repository\javax\persistence\persistence-api\1.0\persistence-api-1.0.jar
>>  D:\workspace\repository\org\codehaus\plexus\plexus-utils\1.2\plexus-utils-1.2.jar
>>  D:\workspace\tools\apache-maven-2.2.0\lib\maven-2.2.0-uber.jar
>>  D:\workspace\sources\maven-gae-template\target\classes
>>  D:\workspace\repository\org\slf4j\slf4j-api\1.6.1\slf4j-api-1.6.1.jar
>>  D:\workspace\repository\ch\qos\logback\logback-classic\0.9.24\logback-classic-0.9.24.jar
>>  D:\workspace\repository\ch\qos\logback\logback-core\0.9.24\logback-core-0.9.24.jar
>>  D:\workspace\repository\javax\jdo\jdo2-api\2.3-eb\jdo2-api-2.3-eb.jar
>>  D:\workspace\repository\com\google\appengine\appengine-api-1.0-sdk\1.3.7\appengine-api-1.0-sdk-1.3.7.jar
>>  D:\workspace\repository\com\google\appengine\appengine-tools-api\1.3.7\appengine-tools-api-1.3.7.jar
ENHANCED (PersistenceCapable) : com.gn.gae.model.Message
DataNucleus Enhancer completed with success for 1 classes. Timings : input=234 ms, enhance=47 ms, total=281 ms. Consult the log for full details

[ERROR] --------------------
[ERROR]  Standard error from the DataNucleus tool + org.datanucleus.enhancer.DataNucleusEnhancer :
[ERROR] --------------------
[ERROR] Sep 5, 2010 8:12:13 PM org.datanucleus.enhancer.DataNucleusEnhancer 
INFO: DataNucleus Enhancer : Using ClassEnhancer "ASM" for API "JDO"
Sep 5, 2010 8:12:13 PM org.datanucleus.plugin.NonManagedPluginRegistry resolveConstraints
INFO: Bundle "org.datanucleus" has an optional dependency to "org.eclipse.equinox.registry" but it cannot be resolved
Sep 5, 2010 8:12:13 PM org.datanucleus.plugin.NonManagedPluginRegistry resolveConstraints
INFO: Bundle "org.datanucleus" has an optional dependency to "org.eclipse.core.runtime" but it cannot be resolved
Sep 5, 2010 8:12:13 PM org.datanucleus.enhancer.DataNucleusEnhancer main
INFO: DataNucleus Enhancer (version 1.1.4) : Enhancement of classes
Sep 5, 2010 8:12:14 PM org.datanucleus.jdo.metadata.JDOAnnotationReader processClassAnnotations
INFO: Class "com.gn.gae.model.Message" has been specified with JDO annotations so using those.
Sep 5, 2010 8:12:14 PM org.datanucleus.enhancer.asm.ASMClassEnhancer enhance
INFO: Class "com.gn.gae.model.Message" is already enhanced.
Sep 5, 2010 8:12:14 PM org.datanucleus.enhancer.DataNucleusEnhancer addMessage
INFO: ENHANCED (PersistenceCapable) : com.gn.gae.model.Message
Sep 5, 2010 8:12:14 PM org.datanucleus.enhancer.DataNucleusEnhancer addMessage
INFO: DataNucleus Enhancer completed with success for 1 classes. Timings : input=234 ms, enhance=47 ms, total=281 ms. Consult the log for full details

[ERROR] --------------------
[INFO] [resources:testResources {execution: default-testResources}]
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory D:\workspace\sources\maven-gae-template\src\test\resources
[INFO] [compiler:testCompile {execution: default-testCompile}]
[INFO] No sources to compile
[INFO] [surefire:test {execution: default-test}]
[INFO] No tests to run.
[INFO] [war:war {execution: default-war}]
[INFO] Packaging webapp
[INFO] Assembling webapp[maven-gae-template] in [D:\workspace\sources\maven-gae-template\target\maven-gae-template-1.0-SNAPSHOT]
[INFO] Processing war project
[INFO] Copying webapp webResources[D:\workspace\sources\maven-gae-template\src/main/webapp] to[D:\workspace\sources\maven-gae-template\target\maven-ga
e-template-1.0-SNAPSHOT]
[INFO] Copying webapp resources[D:\workspace\sources\maven-gae-template\src\main\webapp]
[INFO] Webapp assembled in [937 msecs]
[INFO] Building war: D:\workspace\sources\maven-gae-template\target\maven-gae-template-1.0-SNAPSHOT.war
Downloading: http://maven-gae-plugin.googlecode.com/svn/repository//net/kindleit/gae-runtime/1.3.7/gae-runtime-1.3.7.pom
2K downloaded  (gae-runtime-1.3.7.pom)
[INFO] [gae:run {execution: default-cli}]
Sep 5, 2010 12:12:24 PM com.google.apphosting.utils.jetty.JettyLogger info
INFO: Logging to JettyLogger(null) via com.google.apphosting.utils.jetty.JettyLogger
Sep 5, 2010 12:12:24 PM com.google.apphosting.utils.config.AppEngineWebXmlReader readAppEngineWebXml
INFO: Successfully processed D:\workspace\sources\maven-gae-template\target\maven-gae-template-1.0-SNAPSHOT\WEB-INF/appengine-web.xml
Sep 5, 2010 12:12:24 PM com.google.apphosting.utils.config.AbstractConfigXmlReader readConfigXml
INFO: Successfully processed D:\workspace\sources\maven-gae-template\target\maven-gae-template-1.0-SNAPSHOT\WEB-INF/web.xml
Sep 5, 2010 8:12:26 PM com.google.appengine.tools.development.DevAppServerImpl start
INFO: The server is running at http://localhost:8080/



Step 10. Go to http://localhost:8080/


Step 11. Time to deploy to Google AppEngine server

Configure the application id and application version in \maven-gae-template-working\src\main\webapp\WEB-INF\appengine-web.xml Snippet before the change

...
    $gaeApplicationName
    $gaeApplicationVersion
...

Snippet after the change, you should use your own application id.

...
    maven-gae-template
    1
...

Type mvn gae:deploy

D:\workspace\sources\maven-gae-template>mvn gae:deploy
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building maven-gae-template
[INFO]    task-segment: [gae:deploy]
[INFO] ------------------------------------------------------------------------
[INFO] Preparing gae:deploy
[INFO] [resources:resources {execution: default-resources}]
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 4 resources
[INFO] [compiler:compile {execution: default-compile}]
[INFO] Nothing to compile - all classes are up to date
[INFO] [datanucleus:enhance {execution: default}]
[INFO] DataNucleus Enhancer (version 1.1.4) : Enhancement of classes
DataNucleus Enhancer : Classpath
>>  D:\workspace\repository\org\datanucleus\datanucleus-core\1.1.5\datanucleus-core-1.1.5.jar
>>  D:\workspace\repository\org\datanucleus\datanucleus-rdbms\1.1.5\datanucleus-rdbms-1.1.5.jar
>>  D:\workspace\repository\javax\transaction\transaction-api\1.1\transaction-api-1.1.jar
>>  D:\workspace\repository\org\datanucleus\datanucleus-enhancer\1.1.4\datanucleus-enhancer-1.1.4.jar
>>  D:\workspace\repository\asm\asm\3.2\asm-3.2.jar
>>  D:\workspace\repository\javax\jdo\jdo2-api\2.3-ec\jdo2-api-2.3-ec.jar
>>  D:\workspace\repository\javax\transaction\jta\1.1\jta-1.1.jar
>>  D:\workspace\repository\org\datanucleus\datanucleus-jpa\1.1.5\datanucleus-jpa-1.1.5.jar
>>  D:\workspace\repository\org\apache\geronimo\specs\geronimo-jpa_3.0_spec\1.1.1\geronimo-jpa_3.0_spec-1.1.1.jar
>>  D:\workspace\repository\javax\persistence\persistence-api\1.0\persistence-api-1.0.jar
>>  D:\workspace\repository\org\codehaus\plexus\plexus-utils\1.2\plexus-utils-1.2.jar
>>  D:\workspace\tools\apache-maven-2.2.0\lib\maven-2.2.0-uber.jar
>>  D:\workspace\sources\maven-gae-template\target\classes
>>  D:\workspace\repository\org\slf4j\slf4j-api\1.6.1\slf4j-api-1.6.1.jar
>>  D:\workspace\repository\ch\qos\logback\logback-classic\0.9.24\logback-classic-0.9.24.jar
>>  D:\workspace\repository\ch\qos\logback\logback-core\0.9.24\logback-core-0.9.24.jar
>>  D:\workspace\repository\javax\jdo\jdo2-api\2.3-eb\jdo2-api-2.3-eb.jar
>>  D:\workspace\repository\com\google\appengine\appengine-api-1.0-sdk\1.3.7\appengine-api-1.0-sdk-1.3.7.jar
>>  D:\workspace\repository\com\google\appengine\appengine-tools-api\1.3.7\appengine-tools-api-1.3.7.jar
ENHANCED (PersistenceCapable) : com.gn.gae.model.Message
DataNucleus Enhancer completed with success for 1 classes. Timings : input=203 ms, enhance=62 ms, total=265 ms. Consult the log for full details

[ERROR] --------------------
[ERROR]  Standard error from the DataNucleus tool + org.datanucleus.enhancer.DataNucleusEnhancer :
[ERROR] --------------------
[ERROR] Sep 5, 2010 8:28:49 PM org.datanucleus.enhancer.DataNucleusEnhancer 
INFO: DataNucleus Enhancer : Using ClassEnhancer "ASM" for API "JDO"
Sep 5, 2010 8:28:50 PM org.datanucleus.plugin.NonManagedPluginRegistry resolveConstraints
INFO: Bundle "org.datanucleus" has an optional dependency to "org.eclipse.equinox.registry" but it cannot be resolved
Sep 5, 2010 8:28:50 PM org.datanucleus.plugin.NonManagedPluginRegistry resolveConstraints
INFO: Bundle "org.datanucleus" has an optional dependency to "org.eclipse.core.runtime" but it cannot be resolved
Sep 5, 2010 8:28:50 PM org.datanucleus.enhancer.DataNucleusEnhancer main
INFO: DataNucleus Enhancer (version 1.1.4) : Enhancement of classes
Sep 5, 2010 8:28:50 PM org.datanucleus.jdo.metadata.JDOAnnotationReader processClassAnnotations
INFO: Class "com.gn.gae.model.Message" has been specified with JDO annotations so using those.
Sep 5, 2010 8:28:50 PM org.datanucleus.enhancer.asm.ASMClassEnhancer enhance
INFO: Class "com.gn.gae.model.Message" is already enhanced.
Sep 5, 2010 8:28:50 PM org.datanucleus.enhancer.DataNucleusEnhancer addMessage
INFO: ENHANCED (PersistenceCapable) : com.gn.gae.model.Message
Sep 5, 2010 8:28:50 PM org.datanucleus.enhancer.DataNucleusEnhancer addMessage
INFO: DataNucleus Enhancer completed with success for 1 classes. Timings : input=203 ms, enhance=62 ms, total=265 ms. Consult the log for full details

[ERROR] --------------------
[INFO] [resources:testResources {execution: default-testResources}]
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory D:\workspace\sources\maven-gae-template\src\test\resources
[INFO] [compiler:testCompile {execution: default-testCompile}]
[INFO] No sources to compile
[INFO] [surefire:test {execution: default-test}]
[INFO] No tests to run.
[INFO] [war:war {execution: default-war}]
[INFO] Packaging webapp
[INFO] Assembling webapp[maven-gae-template] in [D:\workspace\sources\maven-gae-template\target\maven-gae-template-1.0-SNAPSHOT]
[INFO] Dependency[Dependency {groupId=javax.jdo, artifactId=jdo2-api, version=2.3-eb, type=jar}] has changed (was Dependency {groupId=javax.jdo, artif
actId=jdo2-api, version=2.3-eb, type=jar}).
[INFO] Dependency[Dependency {groupId=org.datanucleus, artifactId=datanucleus-core, version=1.1.5, type=jar}] has changed (was Dependency {groupId=org
.datanucleus, artifactId=datanucleus-core, version=1.1.5, type=jar}).
[INFO] Processing war project
[INFO] Copying webapp webResources[D:\workspace\sources\maven-gae-template\src/main/webapp] to[D:\workspace\sources\maven-gae-template\target\maven-ga
e-template-1.0-SNAPSHOT]
[INFO] Copying webapp resources[D:\workspace\sources\maven-gae-template\src\main\webapp]
[INFO] Webapp assembled in [250 msecs]
[INFO] Building war: D:\workspace\sources\maven-gae-template\target\maven-gae-template-1.0-SNAPSHOT.war
[INFO] [gae:deploy {execution: default-cli}]
[INFO] Updating Google App Engine Server...
Reading application configuration data...
Sep 5, 2010 8:28:59 PM com.google.apphosting.utils.config.AppEngineWebXmlReader readAppEngineWebXml
INFO: Successfully processed D:/workspace/sources/maven-gae-template/target/maven-gae-template-1.0-SNAPSHOT\WEB-INF/appengine-web.xml
Sep 5, 2010 8:28:59 PM com.google.apphosting.utils.config.AbstractConfigXmlReader readConfigXml
INFO: Successfully processed D:/workspace/sources/maven-gae-template/target/maven-gae-template-1.0-SNAPSHOT\WEB-INF/web.xml
Sep 5, 2010 8:28:59 PM com.google.apphosting.utils.config.IndexesXmlReader readConfigXml
INFO: Successfully processed D:\workspace\sources\maven-gae-template\target\maven-gae-template-1.0-SNAPSHOT\WEB-INF\appengine-generated\datastore-inde
xes-auto.xml
Beginning server interaction for maven-gae-template...
0% Creating staging directory
5% Scanning for jsp files.
8% Compiling jsp files.
Sep 5, 2010 8:29:07 PM com.google.apphosting.utils.config.AbstractConfigXmlReader readConfigXml
INFO: Successfully processed C:\DOCUME~1\awan\LOCALS~1\Temp\appcfg17635.tmp\WEB-INF/web.xml
20% Scanning files on local disk.
25% Initiating update.
28% Cloning 1 static files.
31% Cloning 34 application files.
40% Uploading 4 files.
52% Uploaded 1 files.
61% Uploaded 2 files.
68% Uploaded 3 files.
73% Uploaded 4 files.
77% Initializing precompilation...
90% Deploying new version.
95% Will check again in 1 seconds.
98% Will check again in 2 seconds.
99% Will check again in 4 seconds.
99% Will check again in 8 seconds.
99% Will check again in 16 seconds.
99% Closing update: new version is ready to start serving.
99% Uploading index definitions.

Details:
Sep 5, 2010 8:29:06 PM org.apache.jasper.JspC processFile
INFO: Built File: \index.jsp

Update completed successfully.
Success.
Cleaning up temporary files...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1 minute 11 seconds
[INFO] Finished at: Sun Sep 05 20:29:57 GMT+08:00 2010
[INFO] Final Memory: 18M/32M
[INFO] ------------------------------------------------------------------------
D:\workspace\sources\maven-gae-template>


Now, we have uploaded successfully to Google AppEngine server. Now you could go to open your application in the browser.

Alternatively, you could go to http://maven-gae-template.appspot.com to try out. =)