12
返回列表 发新帖
楼主: jieforest

[参考文档] Java development 2.0: Hello Google App Engine

[复制链接]
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
11#
 楼主| 发表于 2009-8-21 16:44 | 只看该作者
Data persistence, regardless of the underlying mechanism (that is, relational or Google's Big Table) still requires the notion of a key : a way to guarantee uniqueness of various aspects of data to avoid data clashes. For example, in the case of a triathlon the key could be the name of the triathlon. If two triathlons have the same name, then the key could be a combination of the name and the date. Regardless of how you choose to represent a key with Google's App Engine and JDO, you must specify a key in your JDO object via the @PrimaryKey annotation. You can also choose strategies for how a key is generated — either by you or by the Google infrastructure. I'll defer to Google and make it simple: my triathlon object's key is represented as a normal Java Long object, and I'll let Google pick the actual value by specifying a value strategy. Listing 3 adds the primary key:

Listing 3. Adding a primary key to the triathlon JDO

import java.util.Date;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
import javax.jdo.annotations.IdentityType;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;

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

@Persistent
private Date date;

@Persistent
private String name;

@Persistent
private String description;

public Triathlon(Date date, String name, String description) {
  super();
  this.date = date;
  this.name = name;
  this.description = description;
}

//...setters and getters left out

public String toString() {
  return ReflectionToStringBuilder.toString(this);
}

public int hashCode() {
  return HashCodeBuilder.reflectionHashCode(this);
}

public boolean equals(Object obj) {
  return EqualsBuilder.reflectionEquals(this, obj);
}
}

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
12#
 楼主| 发表于 2009-8-21 16:44 | 只看该作者
As you can see in Listing 3, my triathlon JDO now has a key managed by the Google infrastructure, and I've added a few standard methods (toString, hashCode, and equals) that help tremendously for debugging, logging, and of course, proper functionality. Rather than write them myself, I'm using the Apache commons-lang library (see Resources). I also added a constructor that'll make creating fully initialized objects a lot easier as compared to calling a lot of setter methods.

I've kept my JDO simple on purpose, but as you can see, there isn't much to it (that is, I've left out any relationships and omitted getters and setters for brevity's sake). You simply model your domain and then decorate the model with a few annotations, and Google takes care of the rest.

With an object defined as persistence-capable, there's one last step. To interact with the underlying data-store, you need to work with a PersistenceManager, which is a JDO standard class that does what its name implies: saves, updates, retrieves, and removes objects from an underlying data store (much like Hibernate's Session object). This class is created via a factory (PersistenceManagerFactory), which is rather heavyweight; thus, Google recommends creating a singleton object that manages a single instance of the factory (which will then return a proper PersistenceManager when you need it). Accordingly, I can define a simple singleton object for returning an instance of a PersistenceManager, as shown in Listing 4:

Listing 4. A simple singleton for returning a PersistenceManager instance

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

public class PersistenceMgr {

private static final PersistenceManagerFactory instance =
   JDOHelper.getPersistenceManagerFactory("transactions-optional");

private PersistenceMgr() {}

public static PersistenceManager manufacture() {
  return instance.getPersistenceManager();
}
}


As you can see, my PersistenceMgr is quite simple. The one method, manufacture, returns a PersistenceManager instance from a single instance of a PersistenceManagerFactory. You'll also notice that there is no Google-specific code in Listing 4 or any other listing leveraging JDO — all references are to standard JDO classes and interfaces.

The two newly defined Java objects reside in my project's src directory, and I added the commons-lang library to the war/WEB-INF/lib directory.

With a simple triathlon JDO POJO defined and a PersistenceMgr object handy, I'm good to go. All I need now is a way to capture triathlon information.

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
13#
 楼主| 发表于 2009-8-21 16:45 | 只看该作者
Capturing data via a Web interface

Most Web applications follow the same pattern: capture information via HTML forms and submit them to a server-side resource for handling. Sure, a lot of spice is mixed in here and there, but the pattern remains the same regardless of the underlying technology or infrastructure. The Google App Engine is no different — I've already coded the server-side resource to handle saving triathlon data. All that's left is a way to capture the information — a form — and a way to tie the server side and the form together. In Model-View-Controller (MVC) parlance, I need a controller, which is often a servlet; I'll leverage a Groovlet instead because I'd rather write less code.

My HTML form is simple: all I've done is created an HTML page that leverages some simple Cascading Style Sheets (CSS) code to make the form, shown in Figure 1, look more like Web 2.0 than HTML pages circa 1998:

Figure 1. A simple HTML form

Figure1.jpg (15.93 KB, 下载次数: 9)

Figure1.jpg

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
14#
 楼主| 发表于 2009-8-21 16:46 | 只看该作者
As you can see in Figure 1, the form captures a name, description, and a date. The date, however, isn't that simple — it really is three attributes of a date.

Groovlet quickly

Groovlets make controller coding a snap: they require less code and provide needed objects automatically. In a Groovlet, you have implicit access to the HTML request and response via the request and response objects, respectively. In my Groovlet, I can grab all the attributes of the submitted HTML form via the request.getParameter("name") call, as shown in Listing 5:

Listing 5. Groovlets in action

def triname = request.getParameter("tri_name")
def tridesc = request.getParameter("tri_description")
def month = request.getParameter("tri_month")
def day = request.getParameter("tri_day")
def year = request.getParameter("tri_year")


The JDO I coded earlier leverages a Java Date object; however, in Listing 5, I'm dealing with three distinct attributes of Date. So I need a DateFormat object to convert the month, day, year combination into a normal Java Date, as shown in Listing 6:

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
15#
 楼主| 发表于 2009-8-21 16:46 | 只看该作者
Listing 6. Date formatting in action

def formatter = new SimpleDateFormat("MM/dd/yyyy")
def tridate = formatter.parse("${month}/${day}/${year}")


Lastly, with all the parameters obtained from a submitted HTML form, I can persist them in Listing 7 to Google's infrastructure via my JDO and the PersistenceMgr object from Listing 4:

Listing 7. JDO to persistence easily

def triathlon = new Triathlon(tridate, triname, tridesc)
def mgr = PersistenceMgr.manufacture()

try {
mgr.makePersistent(triathlon)
} finally {
mgr.close()
}

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
16#
 楼主| 发表于 2009-8-21 16:46 | 只看该作者
That's it! Of course, as more pages are added to my simple application (such as capturing the results of a particular triathlon), I'd then probably forward or redirect to another form, which would then capture additional information, much like a wizard. Nevertheless, in a few short code snippets, I quickly put together a simple Web application that persists data to Google's infrastructure via JDO (coded in normal Java) and a Groovlet (coded in Groovy, of course). Deploying the application is as easy as specifying a version in the appengine-web.xml file and clicking the Deploy button.

Although this one-form Web application for capturing triathlon events didn't boil the ocean, so to speak, I did just deploy to an amorphous, omnipresent environment. I didn't have to fire up a Web container or even specify where to deploy the application. (Is it residing in California, my hard drive, or the moon?) The beauty is that it doesn't matter — Google has taken care of it. All of it. What's more, it's a safe bet that Google has figured out how to scale globally so that someone viewing the application in India has the same experience as someone in say, Argentina.

With all that said, you do need to keep a few things in mind. Google's infrastructure supports Java technology, but not everything; if you remember when J2ME came out years ago, App Engine's limitations are somewhat similar in nature. That is, not all core Java libraries and related open source libraries are supported. As I mentioned, Hibernate can't be used (mainly because with the App Engine you don't have a relational database). I also had some challenges using some open source libraries that embedded base64 encoding (Google requires you use its URL Fetch service instead). The App Engine is a platform — you must develop to it and, for now, that can be a one-way street.

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
17#
 楼主| 发表于 2009-8-21 16:46 | 只看该作者
The future is already here

Alan Kay, one of the fathers of object-oriented programming, is quoted as having said, "The best way to predict the future is to invent it." I agree with Alan Kay. Regardless of what other people are suggesting the future holds for Java technology, I think the future is already here.

As you saw in this article, the Google App Engine is a platform for the future — provided you play in its sandbox. (Keep in mind that I covered only a few grains of sand in that sandbox; the App Engine has a lot of features). If you want more flexibility (that is, you want a relational database and can't live without Hibernate) but also like the idea of borrowing someone else's scalable infrastructure, alternatives are available. Amazon's EC2 is literally a virtual server on an amorphous infrastructure that you can also summon on-demand. You'll check it out in next month's Java development 2.0 installment.

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
18#
 楼主| 发表于 2009-8-21 16:47 | 只看该作者
Resources

Learn

    * The Google App Engine: Visit the home base for Google's App Engine.

    * Using the Google Plugin for Eclipse: Learn how to install the Google Plugin for Eclipse, create a new App Engine project, and debug it using the development server running within Eclipse.

    * "Google App Engine for Java" (Rick Hightower, developerWorks, August 2009): Explore the Google App Engine for Java in depth in this three-part series.

    * "Stop writing so much code!" (Andrew Glover, developerWorks, December 2008): Find out how Commons Lang extends the standard java.lang API.

    * "Fluently Groovy" (Andrew Glover, developerWorks, March 2008): This tutorial gives Java developers unfamiliar with Groovy a quick and easy introduction to the basics.

    * "Secrets of lightweight development success, Part 6: Persistence strategies" (Bruce Tate, developerWorks, September 2005): This article explores a cornucopia of persistence options available for the Java platform, including JDO.

    * "Hands-on Java Data Objects" (Paul Monday, developerWorks, July 2002): Using discussion, code samples, and hands-on exercises, this tutorial demonstrates the practical application of JDO.

    * Cloud Computing: Visit IBM® Cloud Computing Central for a wealth of cloud resources.

    * Browse the technology bookstore for books on these and other technical topics.

    * developerWorks Java technology zone: Find hundreds of articles about every aspect of Java programming.

Get products and technologies

    * Google Plugin for Eclipse: Download the Eclipse plug-in for Google's App Engine.

    * Gaelyk: A lightweight Groovy framework designed for the Google App Engine.

    * developerWorks Cloud Computing Resource Center: Access IBM software products in the Amazon Elastic Compute Cloud (EC2) virtual environment.

Discuss

    * Get involved in the My developerWorks community.

使用道具 举报

回复
论坛徽章:
277
马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有车
日期:2014-02-19 11:55:14马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11版主9段
日期:2012-11-25 02:21:03ITPUB年度最佳版主
日期:2014-02-19 10:05:27现任管理团队成员
日期:2011-05-07 01:45:08
19#
 楼主| 发表于 2009-8-21 16:48 | 只看该作者
About the author
Andrew Glover

Andrew Glover is a developer, author, speaker, and entrepreneur with a passion for behavior-driven development, Continuous Integration, and Agile software development. You can keep up with him at his blog.

http://www.thediscoblog.com/

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表