Google App Engine + Spring MVC, CRUD example with datastore low level api

GAE datastore
Refer to this official “ Using datstore guide” to understand what is GAE datastore.

See following code snippets to perform CRUD for Google App Engine datastore, Java, using low-level API.

Add

Store a customer into datastore, with “name” as the key.

    Key customerKey = KeyFactory.createKey("Customer", "your name");
Entity customer = new Entity("Customer", customerKey);
customer.setProperty("name", "your name");
customer.setProperty("email", "your email");
 
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
datastore.put(customer); //save it

Search

Return 10 customers as a List.

	DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Query query = new Query("Customer").addSort("date", Query.SortDirection.DESCENDING);
List<Entity> customers = datastore.prepare(query).asList(FetchOptions.Builder.withLimit(10));

Find and returned a customer with matched filter.

	Query query = new Query("Customer");
query.addFilter("name", FilterOperator.EQUAL, "your name");
PreparedQuery pq = datastore.prepare(query);
Entity customer = pq.asSingleEntity();

FilterOperator.EQUAL
Play this filters, it has few condition options, like less than, great than and etc.

Update

To update, just modify the existing Entity and save it again.

	Query query = new Query("Customer");
query.addFilter("name", FilterOperator.EQUAL, "your name");
PreparedQuery pq = datastore.prepare(query);
Entity customer = pq.asSingleEntity();  customer.setProperty("name", name); customer.setProperty("email", email);  DatastoreService datastore = DatastoreServiceFactory.getDatastoreService(); datastore.put(customer); //GAE will know save or update

Delete

To delete, need the entity key.

    Query query = new Query("Customer");
query.addFilter("name", FilterOperator.EQUAL, name);
PreparedQuery pq = datastore.prepare(query);
Entity customer = pq.asSingleEntity();
 
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
datastore.delete(customer.getKey()); //delete it

GAE + Spring MVC + CRUD example

Ok, now we will show you a simple web application developed using Spring MVC in REST style, manipulate data in Google App Engine datastore, using low-level APIs above.

  1. Google App Engine Java SDK 1.6.3.1
  2. Spring 3.1.1
  3. JDK 1.6
  4. Eclipse 3.7 + Google Plugin for Eclipse
Note
This example is keep into as simple as possible, to show you how to perform CRUD only, no layers like DAO or BO, no validation or message notification of the success or failed action.

1. Spring Controller

Spring controller, REST style, to display the web page and perform the CRUD. The code should be self-explanatory.

File : CustomerController.java

package com.mkyong.controller;
 
import java.util.Date;
import java.util.List;
 
import javax.servlet.http.HttpServletRequest;
 
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
 
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.FilterOperator;
 
@Controller
@RequestMapping("/customer")
public class CustomerController {
 
@RequestMapping(value="/addCustomerPage", method = RequestMethod.GET)
public String getAddCustomerPage(ModelMap model) {
 
return "add";
 
}
 
@RequestMapping(value="/add", method = RequestMethod.POST)
public ModelAndView add(HttpServletRequest request, ModelMap model) {
 
String name = request.getParameter("name");
String email = request.getParameter("email");
 
Key customerKey = KeyFactory.createKey("Customer", name);
 
Date date = new Date();
Entity customer = new Entity("Customer", customerKey);
customer.setProperty("name", name);
customer.setProperty("email", email);
customer.setProperty("date", date);
 
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
datastore.put(customer);
 
return new ModelAndView("redirect:list");
 
}
 
@RequestMapping(value="/update/{name}", method = RequestMethod.GET)
public String getUpdateCustomerPage(@PathVariable String name,
HttpServletRequest request, ModelMap model) {
 
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Query query = new Query("Customer");
query.addFilter("name", FilterOperator.EQUAL, name);
PreparedQuery pq = datastore.prepare(query);
 
Entity e = pq.asSingleEntity();
model.addAttribute("customer", e);
 
return "update";
 
}
 
@RequestMapping(value="/update", method = RequestMethod.POST)
public ModelAndView update(HttpServletRequest request, ModelMap model) {
 
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
 
String name = request.getParameter("name");
String email = request.getParameter("email");
String originalName = request.getParameter("originalName");
 
Query query = new Query("Customer");
query.addFilter("name", FilterOperator.EQUAL, originalName);
PreparedQuery pq = datastore.prepare(query);
Entity customer = pq.asSingleEntity();
 
customer.setProperty("name", name);
customer.setProperty("email", email);
customer.setProperty("date", new Date());
 
datastore.put(customer);
 
//return to list
return new ModelAndView("redirect:list");
 
}
 
@RequestMapping(value="/delete/{name}", method = RequestMethod.GET)
public ModelAndView delete(@PathVariable String name,
HttpServletRequest request, ModelMap model) {
 
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
 
Query query = new Query("Customer");
query.addFilter("name", FilterOperator.EQUAL, name);
PreparedQuery pq = datastore.prepare(query);
Entity customer = pq.asSingleEntity();
 
datastore.delete(customer.getKey());
 
//return to list
return new ModelAndView("redirect:../list");
 
}
 
//get all customers
@RequestMapping(value="/list", method = RequestMethod.GET)
public String listCustomer(ModelMap model) {
 
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Query query =
new Query("Customer").addSort("date", Query.SortDirection.DESCENDING);
List<Entity> customers =
datastore.prepare(query).asList(FetchOptions.Builder.withLimit(10));
 
model.addAttribute("customerList", customers);
 
return "list";
 
}
 
}

2. JSP Pages

3 JSP pages to display customer and perform add and update.

File : list.jsp

<%@ page import="java.util.List" %>
<%@ page import="com.google.appengine.api.datastore.Entity" %>
<html>
<body>
<h1>GAE + Spring 3 MVC REST + CRUD Example</h1>
 
Function : <a href="addCustomerPage">Add Customer</a>
<hr />
 
<h2>All Customers</h2>
<table border="1">
<thead>
<tr>
<td>Name</td>
<td>Email</td>
<td>Created Date</td>
<td>Action</td>
</tr>
</thead>
<%
 
List<Entity> customers = (List<Entity>)request.getAttribute("customerList");
for(Entity e : customers){
 
%>
<tr>
<td><%=e.getProperty("name") %></td>
<td><%=e.getProperty("email") %></td>
<td><%=e.getProperty("date") %></td>
<td><a href="update/<%=e.getProperty("name")%>">Update</a>
| <a href="delete/<%=e.getProperty("name")%>">Delete</a></td>
</tr>
<%
}
%>
</table>
 
</body>
</html>

File : add.jsp

<html>
<body>
<h1>Add Customer</h1>
 
<form method="post" action="add" >
<table>
<tr>
<td>
UserName :
</td>
<td>
<input type="text" style="width: 185px;"
maxlength="30" name="name" id="name" />
</td>
</tr>
<tr>
<td>
Email :
</td>
<td>
<input type="text" style="width: 185px;"
maxlength="30" name="email" id="email" />
</td>
</tr>
</table>
<input type="submit" class="save" title="Save" value="Save" />
</form>
 
</body>
</html>

File : update.jsp

<%@ page import="com.google.appengine.api.datastore.Entity" %>
<html>
<body>
<h1>Update Customer</h1>
 
<%
Entity customer = (Entity)request.getAttribute("customer");
%>
 
<form method="post" action="../update" >
<input type="hidden" name="originalName" id="originalName"
value="<%=customer.getProperty("name") %>" />
 
<table>
<tr>
<td>
UserName :
</td>
<td>
<input type="text" style="width: 185px;"
maxlength="30" name="name" id="name"
value="<%=customer.getProperty("name") %>" />
</td>
</tr>
<tr>
<td>
Email :
</td>
<td>
<input type="text" style="width: 185px;"
maxlength="30" name="email" id="email"
value="<%=customer.getProperty("email") %>" />
</td>
</tr>
</table>
<input type="submit" class="update" title="Update" value="Update" />
</form>
 
</body>
</html>

3. Spring Configuration

Scan the Spring controller and configure the view resolver, so that it can redirect the view to jsp pages.

File : mvc-dispatcher-servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"
>
 
<context:component-scan base-package="com.mkyong.controller" />
<mvc:annotation-driven />
 
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
 
</beans>

4. Integrate Spring

Integrate Spring into the web application.

File : web.xml

<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">

 
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
 
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
 
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
</context-param>
 
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
 
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>

5. Demo

Done, see demo and show you the workflow of the web application.

1. A listing page, to display list of existing customers.

URL : http://localhost:8888/customer/list

gae spring mvc crud example - list gae spring mvc crud example - list

2. In listing page, click on the “Add Customer” link to display the add customer page, fill in a new customer, and click on the “Add” button.

URL : http://localhost:8888/customer/addCustomerPage

gae spring mvc crud example - add gae spring mvc crud example - add

3. After saved the customer, it will return back to the listing page.

URL : http://localhost:8888/customer/list

gae spring mvc crud example - list gae spring mvc crud example - list

4. Try update link, it will display the selected customer’s data, update email address and click on the update button.

URL : http://localhost:8888/customer/update/mkyong

gae spring mvc crud example - update gae spring mvc crud example - update

5. The email is updated, and redirect back to listing page.

URL : http://localhost:8888/customer/list

gae spring mvc crud example - list gae spring mvc crud example - list

6. To delete the customer, just click on the “delete” link.

Download Source Code

Due to large file size, all Spring MVC and GAE jars are excluded.

Download – GoogleAppEngine-SpringMVC-datastore.zip (17 KB)
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s