Posted on 05 March 2009 by Sri Nivas

Amazon SimpleDB Web Service with Simple JPA API, Typica API and Java

In this article I will explain how to use Amazon SimpleDB web service using Java Persistence API (SimpleJPA) + Typica API

Read the previous blog, In which we were using Typica API only. Compare the StudentDAOImpl in this project and the previous project where we were using Typica API only.

Using SimpleJPA + Typica API simplified the code and it is easy to develop complex applications.

Read my previous blog post about using Amazon SImpleDB using Typica API Only.

What are we going to do in this tutorial

I am going to create a student object. After creating the student object, we will use Amazon SimpleDB web service to create a student in Amazon SimpleDB database, update the student, list all students in the datbase, print count of students in the database, delete a student from the database.

All we are doing is CRUD operations [Create, Read, Update, Delete] with student object.

Prerequisites:

To run this you will need a Amazon SimpleDB account with Amazon Web Services.

Step 0: let us create a Entity Manager

public class SimpleDBEntityManagerFactory
{

public static EntityManager getEntityManager()
{
final EntityManagerFactoryImpl factory = new EntityManagerFactoryImpl(“studentdb”,null);
EntityManager em = factory.createEntityManager();

return em;
}

}

Create a file called simplejpa.properties and add it to your classpath.

Contents of simplejpa.properties are as below:

accessKey = sdfgsdfhsryerhsdfhsdfh
secretKey = dfsdfhsdfhsdfhsdjfsdjf
printQueries = true
sessionless = false
threads = 10
groovyBeans = false

The accessKey and secretKey above are provided by Amazon web service, when you register with them.

Step 1: Now let us create our Student Domain

EntityManager em = SimpleDBEntityManagerFactory.getEntityManager();
student.setId(String.valueOf(id));
em.persist(student);

A domain called student will be created on running the above snippet of code.

Domain is same as a table in relational database with columns.

Each row in a domain is called item.

Each item will have attributes.

Each attribute will have a name and value.

Step 2: Create Student object (Student.java) with annotations

package com.vulab.domain;

import java.util.Date;

@Entity

public class Student {
private String id;
private String salutation;
private String jobTitle;
private String department;
private String company;
private String firstName;
private String lastName;
private String addressLineOne;
private String addressLineTwo;
private String city;
private String state;
private String zip;
private String country;
private String workPhone;
private String workPhoneExtension;
private String fax;
private String homePhone;
private String cellPhone;
private String email;
private String userId;
private String password;
private String dateOfBirth;

@Id

public String getId() {
return id;
}

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

public String getSalutation() {
return salutation;
}

public void setSalutation(String salutation) {
this.salutation = salutation;
}

public String getJobTitle() {
return jobTitle;
}

public void setJobTitle(String jobTitle) {
this.jobTitle = jobTitle;
}

public String getDepartment() {
return department;
}

public void setDepartment(String department) {
this.department = department;
}

public String getCompany() {
return company;
}

public void setCompany(String company) {
this.company = company;
}

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public String getAddressLineOne() {
return addressLineOne;
}

public void setAddressLineOne(String addressLineOne) {
this.addressLineOne = addressLineOne;
}

public String getAddressLineTwo() {
return addressLineTwo;
}

public void setAddressLineTwo(String addressLineTwo) {
this.addressLineTwo = addressLineTwo;
}

public String getCity() {
return city;
}

public void setCity(String city) {
this.city = city;
}

public String getState() {
return state;
}

public void setState(String state) {
this.state = state;
}

public String getZip() {
return zip;
}

public void setZip(String zip) {
this.zip = zip;
}

public String getCountry() {
return country;
}

public void setCountry(String country) {
this.country = country;
}

public String getWorkPhone() {
return workPhone;
}

public void setWorkPhone(String workPhone) {
this.workPhone = workPhone;
}

public String getWorkPhoneExtension() {
return workPhoneExtension;
}

public void setWorkPhoneExtension(String workPhoneExtension) {
this.workPhoneExtension = workPhoneExtension;
}

public String getFax() {
return fax;
}

public void setFax(String fax) {
this.fax = fax;
}

public String getHomePhone() {
return homePhone;
}

public void setHomePhone(String homePhone) {
this.homePhone = homePhone;
}

public String getCellPhone() {
return cellPhone;
}

public void setCellPhone(String cellPhone) {
this.cellPhone = cellPhone;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public String getUserId() {
return userId;
}

public void setUserId(String userId) {
this.userId = userId;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public String getDateOfBirth() {
return dateOfBirth;
}

public void setDateOfBirth(String dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
}

Step 3: Let us code the Student Data Access Object (StudentDAO.java) Create Read Update Delete Functionality

package com.vulab.dao;
import java.util.List;
import com.vulab.domain.Student;

public interface StudentDAO {
	public Student createStudent(Student student)throws Exception;

	public void updateStudent(Student student)throws Exception;

	public Student getStudentById(int studentId)throws Exception;	

	public void deleteStudentById(int studentId)throws Exception;

	public void deleteStudent(Student student)throws Exception;

	public List<Student> getAllStudents()throws Exception;

	public int getTotalCountOfStudents()throws Exception;
}

Step 4: Let us code the StudentDAO implementation (StudentDAOImpl.java)

package com.vulab.dao;

import java.util.List;
import java.util.Random;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import com.vulab.domain.Student;
import com.vulab.utils.SimpleDBEntityManagerFactory;

public class StudentDAOImpl implements StudentDAO {

	public static final String domain = "student";

public Student createStudent(Student student) throws Exception {


		Random randomGenerator = new Random();
		int id = randomGenerator.nextInt(100000);

		EntityManager em = SimpleDBEntityManagerFactory.getEntityManager();
		student.setId(String.valueOf(id));
		em.persist(student);
		em.close();

		return student;
	}

public void updateStudent(Student student) throws Exception {


		EntityManager em = SimpleDBEntityManagerFactory.getEntityManager();
		em.persist(student);
		em.close();

	}

public Student getStudentById(int studentId) throws Exception {

		EntityManager em = SimpleDBEntityManagerFactory.getEntityManager();
		Query q = em.createQuery("select o from Student o where o.id= :studentid");
		q.setParameter("studentid", studentId);
		List<Student> obs = q.getResultList();
		Student student = (Student) obs.get(0);
		em.close();
		return student;
	}

public void deleteStudentById(int studentId) throws Exception {

		EntityManager em = SimpleDBEntityManagerFactory.getEntityManager();
		Query q = em.createQuery("select o from Student o where o.id= :studentid");
		q.setParameter("studentid", studentId);
		List<Student> obs = q.getResultList();
		Student student = (Student) obs.get(0);
		em.remove(student);
		em.close();
	}

public void deleteStudent(Student student) throws Exception {

		EntityManager em = SimpleDBEntityManagerFactory.getEntityManager();
		em.remove(student);
		em.close();
	}

public List<Student> getAllStudents() throws Exception {

		EntityManager em = SimpleDBEntityManagerFactory.getEntityManager();
		Query q = em.createQuery("select o from Student o");
		List<Student> obs = q.getResultList();
		em.close();
		return obs;
	}

public int getTotalCountOfStudents() throws Exception {

		EntityManager em = SimpleDBEntityManagerFactory.getEntityManager();
		Query q = em.createQuery("select o from Student o");
		List<Student> obs = q.getResultList();
		em.close();
		return obs.size();
	}

}


Step 5:let us create a Student Service (StudentService.java)

This service can be used by our web front end actions.

package com.vulab.service;

import java.util.List;

import com.vulab.domain.Student;

public interface StudentService
{
	public Student createStudent(Student student)throws Exception;

	public void updateStudent(Student student)throws Exception;

	public Student getStudentById(int studentId)throws Exception;	

	public void deleteStudentById(int studentId)throws Exception;

	public void deleteStudent(Student student)throws Exception;

	public List<Student> getAllStudents()throws Exception;

	public int getTotalCountOfStudents()throws Exception;	

}

Step 6:let us implement the Student Service Interface (StudentServiceImpl.java)

package com.vulab.service;

import java.util.List;

import com.vulab.dao.StudentDAO;
import com.vulab.dao.StudentDAOImpl;
import com.vulab.domain.Student;
public class StudentServiceImpl implements StudentService {

	StudentDAO studentDAO = new StudentDAOImpl();

	public Student createStudent(Student student) throws Exception {
		return studentDAO.createStudent(student);
	}

	public void updateStudent(Student student) throws Exception {
		studentDAO.updateStudent(student);
	}

	public Student getStudentById(int studentId) throws Exception {
		return studentDAO.getStudentById(studentId);
	}

	public void deleteStudentById(int studentId) throws Exception {
		studentDAO.deleteStudentById(studentId);
	}

	public void deleteStudent(Student student) throws Exception {
		studentDAO.deleteStudent(student);
	}

	public List<Student> getAllStudents() throws Exception {
		return studentDAO.getAllStudents();
	}

	public int getTotalCountOfStudents() throws Exception {
		return studentDAO.getTotalCountOfStudents();
	}

}

Step 7:Let us write a JUnit test case to test our Student Service

package com.vulab.test.service;

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

import junit.framework.TestCase;

import com.vulab.domain.Student;
import com.vulab.service.StudentService;
import com.vulab.service.StudentServiceImpl;

/* What are we doing in this test case
* we are creating a student in the domain student
* we are updating the created students first name and last name
* we are retrieving the updated object from database again and checking if the first name is updated
* we are listing all the students in the database
* we are printing the count of students in the database
* we are deleting a student from the database
* we are listing the students in the database after delete
* we are printing the number of students in the database after delete.
*/
public class TestStudentService extends TestCase
{

	public void testCreate() throws Exception
	{
		Student student = new Student();
		student.setAddressLineOne("116 Franklin Lane");
		student.setAddressLineTwo("none");
		student.setCellPhone("5454666");
		student.setCity("Nainza");
		student.setCompany("alpha");
		student.setCountry("beta");
		student.setDateOfBirth("june 6th 4532");
		student.setDepartment("learn");
		student.setEmail("beta@alpha.com");
		student.setFax("2342342");
		student.setFirstName("John");
		student.setHomePhone("2342342342");
		student.setJobTitle("learner");
		student.setLastName("keller");
		student.setPassword("secret");
		student.setSalutation("Mr.");
		student.setState("NJ");
		student.setUserId("user32423");
		student.setWorkPhone("534534534");
		student.setZip("34345");

		StudentService studentService = new StudentServiceImpl();
		Student st = studentService.createStudent(student);

		System.out.println("Created students first name: "+student.getFirstName());
		System.out.println("Student with the following id is created "+st.getId());

		student.setFirstName("karen");
		student.setLastName("parker");
		studentService.updateStudent(student);
		System.out.println("Student is updated");

		Student studentFromDB = studentService.getStudentById(Integer.parseInt(st.getId()));
		System.out.println("Student first name is "+studentFromDB.getFirstName());

		List<Student> studentList = new ArrayList<Student>();
		studentList = studentService.getAllStudents();
		System.out.println("listing all students");
		for(Student std: studentList)
		{
			System.out.println("*************************");
			System.out.println("Student Id: "+std.getId());
			System.out.println("First Name: "+std.getFirstName());
		}

		System.out.println("Number of students in domain: "+studentService.getTotalCountOfStudents());

		System.out.println("Now I am going to delete a student with id "+studentFromDB.getId());
		studentService.deleteStudentById(Integer.parseInt(studentFromDB.getId()));

		System.out.println("Now showing all students again");
		List<Student> studentAgainList = new ArrayList<Student>();
		studentAgainList = studentService.getAllStudents();
		System.out.println("listing all students");
		for(Student std: studentAgainList)
		{
			System.out.println("*************************");
			System.out.println("Student Id: "+std.getId());
			System.out.println("First Name: "+std.getFirstName());
		}

		System.out.println("Number of students in domain: "+studentService.getTotalCountOfStudents());

	}

}

Step 8: Let us review the result from our JUnit testcase

Scanning for entity classes…
entity=com.vulab.domain.Student
Finished scanning for entity classes.
Initing second level cache: null
getting all domains
itemAttr=workPhoneExtension: null
Created students first name: John
Student with the following id is created 97641
Scanning for entity classes…
entity=com.vulab.domain.Student
Finished scanning for entity classes.
Initing second level cache: null
getting all domains
itemAttr=workPhoneExtension: null
Student is updated
Scanning for entity classes…
entity=com.vulab.domain.Student
Finished scanning for entity classes.
Initing second level cache: null
getting all domains
amazonQuery: Domain=studentdb-Student, query=['id' = '97641']
Student first name is karen
Scanning for entity classes…
entity=com.vulab.domain.Student
Finished scanning for entity classes.
Initing second level cache: null
getting all domains
amazonQuery: Domain=studentdb-Student, query=
listing all students
*************************
Student Id: 36666
First Name: karen
*************************
Student Id: 97641
First Name: karen
Scanning for entity classes…
entity=com.vulab.domain.Student
Finished scanning for entity classes.
Initing second level cache: null
getting all domains
amazonQuery: Domain=studentdb-Student, query=
Number of students in domain: 2
Now I am going to delete a student with id 97641
Scanning for entity classes…
entity=com.vulab.domain.Student
Finished scanning for entity classes.
Initing second level cache: null
getting all domains
amazonQuery: Domain=studentdb-Student, query=['id' = '97641']
Now showing all students again
Scanning for entity classes…
entity=com.vulab.domain.Student
Finished scanning for entity classes.
Initing second level cache: null
getting all domains
amazonQuery: Domain=studentdb-Student, query=
listing all students
*************************
Student Id: 36666
First Name: karen
Scanning for entity classes…
entity=com.vulab.domain.Student
Finished scanning for entity classes.
Initing second level cache: null
getting all domains
amazonQuery: Domain=studentdb-Student, query=
Number of students in domain: 1

Step 9: Recap what we have done!

We created a SimpleDB instance using Amazon SimpleDB web service.

Tested CRUD (Create, Read, Update, Delete) functionality with a student object using Amazon Simple DB Web Service with JPA API and typica API

Step 10: Conclusion:

Typica API is a great API to use when working with Amazon SimpleDB using java programming language.

But using Typica API along with SimpleJPA is a much better solution as this will cut down your DAO code complexity and much easier to maintain and extend.

Amazon SimpleDB webservice + Typica API + SimpleJPA API looks very promising.

Read more about SimpleJPA on google code, It has a caching feature which will reduce your cost associated with using Amazon SimpleDB.

You can also use SimpleJPA with Groovy beans also.

Step 11: What next?

This work is left for you. Create a domain called Course (learning course).

Enroll a student to a course using Amazon Simple DB and update the above Student Service to add the new functionality.

API Used:

Typica from Google Code.

Typica is a java client library for a variety of Amazon Web Services. The name (TIP-ik-uh) was chosen because this is a coffee grown in Brazil, through which the Amazon flows. (has the Java and Amazon references)

SimpleJPA from google code.

SimpleJPA is a Java Persistence API (JPA) implementation for Amazon’s SimpleDB. In other words, an object-relational mapping (ORM) framework for Amazon’s database in the cloud.

list of jars being used:

apache-mime4j-0.5.jar
backport-util-concurrent.jar
cglib-nodep-2.2.jar
cockpit-0.7.0.jar
cockpitlite-0.7.0.jar
commons-attributes-api-2.2.jar
commons-attributes-compiler-2.2.jar
commons-attributes-plugin-2.2.jar
commons-beanutils-1.8.0.jar
commons-beanutils-bean-collections-1.8.0.jar
commons-beanutils-core-1.8.0.jar
commons-codec-1.3.jar
commons-collections-3.2.1.jar
commons-httpclient-3.1.jar
commons-lang-2.4.jar
commons-logging-1.1.1.jar
commons-logging-adapters-1.1.1.jar
commons-logging-api-1.1.1.jar
ehcache-1.3.0.jar
ehcache-1.3.0-remote-debugger.jar
ehcache-jcache-1.1.jar
ejb3-persistence-1.0.2.GA.jar
httpclient-4.0-beta2.jar
httpcore-4.0.jar
httpcore-4.0-beta3.jar
httpcore-nio-4.0.jar
httpmime-4.0-beta2.jar
javassist.jar
JAXB2_20070122.jar
jets3t-0.7.0.jar
jets3t-gui-0.7.0.jar
jsr107cache-1.0.jar
junit-4.5.jar
scannotation-1.0.2.jar
simplejpa-alpha-0.7.jar
synchronize-0.7.0.jar
typica.jar
uploader-0.7.0.jar

Download Source Code for this tutorial from Google Code

Please leave a comment, if you found this blog useful.

0 Comments

Leave a Reply

You must be logged in to post a comment.