Tutorial: JPA on Google App Engine

   

This project will create and delete an entity record. I have chosen JPA for datastore in app engine. You can also look JDO for this purpose. But my choice to go for JPA is due to Sun standardization on it.

I am using App Engine SDK version 1.2.18

Project name: engineplay
URL: http://engineplay.appspot.com
[ad#co-2]

Project structure:

jpa_gae_project_structureUserPrefs.java: The entity class

package com.engineplay.datastore.pojos;
import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.Id;
import com.engineplay.datastore.EMFService;
import com.google.appengine.api.users.User;

@Entity(name = "UserPrefs")
public class UserPrefs {
 @Id
 private String userId;
 private int donuts;
 @Basic
 private User user;

 public UserPrefs(String userId) {
 this.userId = userId;
 }

 /* TODO create getter and setters for above properties yourself */

 public static UserPrefs getPrefsForUser(User user) {
 UserPrefs userPrefs = null;
 EntityManager em = EMFService.get().createEntityManager();
 try {
 if (em.find(UserPrefs.class, user.getEmail()) == null) {

 userPrefs = new UserPrefs(user.getEmail());
 userPrefs.setUser(user);

 } else {
 userPrefs = em.find(UserPrefs.class, user.getEmail());
 }
 } finally {
 em.close();
 }
 return userPrefs;
 }

 public void save() {
 EntityManager em = EMFService.get().createEntityManager();
 try {
 em.persist(this);
 } finally {
 em.close();
 }
 }

 public void remove() {
 EntityManager em = EMFService.get().createEntityManager();
 try {
 UserPrefs userPrefs = em.find(UserPrefs.class, user.getEmail());
 em.remove(userPrefs);
 } finally {
 em.close();
 }
 }
}

EMFService.java: The class to create EntityManagerFactory instance.

package com.engineplay.datastore;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class EMFService {
 private static final EntityManagerFactory emfInstance = Persistence
 .createEntityManagerFactory("transactions-optional");

 private EMFService() {
 }

 public static EntityManagerFactory get() {
 return emfInstance;
 }
}

LoginServlet.java

package com.engineplay.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.engineplay.datastore.pojos.UserPrefs;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;

public class LoginServlet extends HttpServlet {

 public void doGet(HttpServletRequest req, HttpServletResponse resp)
 throws IOException {

 UserService userService = UserServiceFactory.getUserService();
 User user = userService.getCurrentUser();
 String navBar, form = null;
 int donuts = 0;
 if (user == null) {
 navBar = "<p>Welcome! <a href=\"" + userService.createLoginURL("/") +
 "\">Sign in or register</a> to customize.</p>";
 form = "";
 } else {
 UserPrefs userPrefs = UserPrefs.getPrefsForUser(user);

 if (userPrefs != null) {
 donuts = userPrefs.getDonuts();
 }
 navBar = "<p>Welcome, " + user.getEmail() + "! You can <a href=\"" +
 userService.createLogoutURL("/") +
 "\">sign out</a>.</p>";
 form = "<form action=\"/donuts\" method=\"post\">" +
 "<label for=\"donuts\">" +
 "Need more donuts?:" +
 "</label>" +
 "<input name=\"donuts\" id=\"donuts\" type=\"text\" size=\"4\" />" +
 " <input name=\"olddonuts\"  type=\"hidden\" value=\"" + donuts + "\" /> " +
 " <input name=\"userId\"  type=\"hidden\" value=\"" +user.getEmail()+ "\" /> " +
 "   <input type=\"submit\" value=\"  ADD  \" /><br><input type=\"submit\"  name =\"deleteBtn\" value=\"  DELETE ME!  \" />" +
 "</form>";

 }
 resp.setContentType("text/html");
 PrintWriter out = resp.getWriter();
 out.print("<html><head><title>Engine Play - Donuts</title</head><body>");
 out.println(navBar);
 if (donuts != 0)
 out.println("<p>Donuts you have: " + donuts + "</p>");
 else
 out.println("<p> No donuts you have :(  </p>");
 out.println(form);
 out.print("</body></html>");
 }
}

DonutsServlet.java

package com.engineplay.servlet;

import java.io.IOException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.engineplay.datastore.pojos.UserPrefs;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;

public class DonutsServlet extends HttpServlet {

 public void doPost(HttpServletRequest req, HttpServletResponse resp)
 throws IOException {
 UserService userService = UserServiceFactory.getUserService();
 User user = userService.getCurrentUser();
 UserPrefs userPrefs = UserPrefs.getPrefsForUser(user);
 try {

 String deleteOpt = req.getParameter("deleteBtn");
 if (deleteOpt == null){
 int donuts = new Integer(req.getParameter("donuts")).intValue();
 int oldDonuts = new Integer(req.getParameter("olddonuts")).intValue();

 userPrefs.setDonuts(donuts + oldDonuts);
 userPrefs.save();
 }else{
 String userId = req.getParameter("userId");
 userPrefs.setUserId(userId);
 userPrefs.remove();
 }
 } catch (Exception e) {
 e.printStackTrace();
 }
 resp.sendRedirect("/Login");
 }
}

persistence.xml: Configuration file required for JPA

<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence

http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"

 version="1.0">
 <persistence-unit name="transactions-optional">
 <provider>
 org.datanucleus.store.appengine.jpa.DatastorePersistenceProvider
 </provider>
 <properties>
 <property name="datanucleus.NontransactionalRead"
 value="true" />
 <property name="datanucleus.NontransactionalWrite"
 value="true" />
 <property name="datanucleus.ConnectionURL"
 value="appengine" />
 </properties>
 </persistence-unit>
</persistence>

web.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">

 <servlet>
 <servlet-name>LoginServlet</servlet-name>
 <servlet-class>com.engineplay.servlet.LoginServlet</servlet-class>
 </servlet>
 <servlet>
 <servlet-name>DonutsServlet</servlet-name>
 <servlet-class>com.engineplay.servlet.DonutsServlet</servlet-class>
 </servlet>

 <servlet-mapping>
 <servlet-name>LoginServlet</servlet-name>
 <url-pattern>/Login</url-pattern>
 </servlet-mapping>
 <servlet-mapping>
 <servlet-name>DonutsServlet</servlet-name>
 <url-pattern>/donuts</url-pattern>
 </servlet-mapping>

 <welcome-file-list>
 <welcome-file>Login</welcome-file>
 </welcome-file-list>
</web-app>

Access the project here: http://engineplay.appspot.com

run_gae_project

Related Posts Plugin for WordPress, Blogger...

Related Posts

Tags: , ,

  • http://skillstm.com Robert Lancer

    Tahir,

    Nice tutorial. I started out with app engine using the JPA/JDO but then found the low level API to be just as easy. I then disabled the JDO/JPA which allows the project to deploy faster. Have you found a significant advantage of using the JDO/JPA over the low level API?

  • http://www.pakzilla.com Tahir Akram

    Thanks Robert.

    Its my first program to learn datastore in app engine. I will read about working with low level API and will discuss with you.

  • http://icoloma.blogspot.com Ignacio Coloma

    I may be tweeting my own horn here, but if you are using the low-level API for real you should give a look to this:

    http://code.google.com/p/simpleds/

  • http://softwarebyasif.blogspot.com/ Asif Shazad

    Great article. I was thinking to explore the app engine. Found a good place to start … Thanks.

  • http://www.pakzilla.com Tahir Akram

    Coloma;

    I just take a look on the page. Sounds interesting if its easy to use over JPA and JDO. As JPA and SimpleDS both are new for me so learning core JPA will be better investment for me.

    Thanks for your comments.

  • Marek Dominiak

    @Robert Lancer:

    There is a significat adventage of using JPA over the low level api – you can move your application from Google and deploy it somewhere else, and to do that you only have mappings (probably) – you don’t have to change the code. Using low level api you depends on google – to move your application somewhere else you have to change a bunch of code.

    Best regards
    Marek

  • http://veerasundar.com/blog Veera

    good article, Tahir. :)

  • http://www.pakzilla.com Tahir Akram

    Thanks Veera.

  • http://yahoo.co.in Ramya

    Thanks for your pgm
    This is my 1st pgm to run with JPA.
    but i didnot know how the html file should be can any one help me.

  • http://superdeporter.wordpress.com Cesare Veritas

    Nice tutorial!

    Visit here if you want to see example usage of Blobstore API on Google App Engine. It shows file uploading via JSP.

    http://superdeporter.wordpress.com

    Thanks.

  • Jitendra

    Thanks Its nice content on app engine. I am also using google app engine.

    Thanks
    Jitendra
    http://www.javaprogrammings.info

  • Bdar

    How Did you package and deploy the project ?

Switch to our mobile site