diff --git a/.classpath b/.classpath
new file mode 100644
index 0000000..d1baf75
--- /dev/null
+++ b/.classpath
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.project b/.project
new file mode 100644
index 0000000..607f702
--- /dev/null
+++ b/.project
@@ -0,0 +1,42 @@
+
+
+ person-service
+
+
+
+
+
+ org.eclipse.wst.jsdt.core.javascriptValidator
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.wst.common.project.facet.core.builder
+
+
+
+
+ org.eclipse.wst.validation.validationbuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.eclipse.jem.workbench.JavaEMFNature
+ org.eclipse.wst.common.modulecore.ModuleCoreNature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+ org.eclipse.wst.common.project.facet.core.nature
+ org.eclipse.wst.jsdt.core.jsNature
+
+
diff --git a/README.md b/README.md
index f57af54..0682468 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,84 @@
Person Service
==============
-A simple JPA backend service that loads data from a CSV file and make it
-accessible through `Person` entity.
+**You can clone this project and import it directly into Eclipse**
-It can be easily upgraded to read/write from a real database instead of the CSV
-file.
+A simple JPA backend service that loads data from a CSV file and make it accessible through `Person` entity.
-You can modify the provided demo data from `Persons.csv` located under
-`src/resources`.
+It can be easily upgraded to read/write from a real database instead of the CSV file.
+
+You can modify the provided demo data from `Persons.csv` located under `src/resources`.
+
+Watch step by step on how to use this backend in a Vaadin project
+-
+
+[](https://www.youtube.com/watch?v=Lwhg3NrOLVA)
+
+Referencing This Project Into Another Maven Project
+-
+
+After installing this project locally, you can reference it by including it as a dependency into the front-end project. Most probably you will need to include JavaEE dependencies as well:
+
+```xml
+
+ ...
+
+
+ javax
+ javaee-api
+ 7.0
+ provided
+
+
+
+ org.vaadin.stepbystep
+ person-service
+ 2.0
+
+
+ ...
+
+```
+
+Usage
+-
+
+- Inject `PersonService`.
+- Call `getEntries()` to return a list of `Person`.
+- Call `delete()` or `save()` to update a given entity.
+- Call `getFirst()` to retrieve the first entity.
+- Call `getById()` to retrieve an entity by its id.
+
+Example
+-
+
+```java
+ @Inject
+ PersonService service;
+
+ void load() {
+ component.bind(service.getEntries());
+ }
+```
+
+Obtain Maven dependency
+-
+
+You can obtain the maven dependency from [Vaadin Directory](https://vaadin.com/directory/#!addon/demo-person-service) without any downloads or installs.
+
+Import & Install Using CLI
+-
+
+Platform and IDE independent, you can install this project locally using the following three commands:
+```bash
+ $ git clone git@github.com:amahdy/person-service.git
+ $ cd person-service
+ $ mvn install
+```
+Or alternatively:
Import Into Eclipse
-===================
+-
This project is easy to import into Eclipse from the [eclipse-project branch](https://github.com/amahdy/person-service/tree/eclipse-project). Here are the direct steps to get started:
@@ -58,51 +125,3 @@ This project is easy to import into Eclipse from the [eclipse-project branch](ht
**Step 11) You should get a BUILD SUCCESS in the Console, now the project is ready to be used locally**

-
-Referencing this project into another Maven project
-===================================================
-After installing this project locally, you can easily reference it by including it as a dependecy into the front-end project. Most porbably you will need to include JavaEE dependencies as well:
-
-```xml
-
- ...
-
-
- javax
- javaee-api
- 7.0
- provided
-
-
-
- org.vaadin.stepbystep
- person-service
- 1.0
-
-
- ...
-
-```
-
-Usage
-=====
-
-- Inject `PersonService`.
-- Call `loadData()` to load the data from the CSV file.
-- Call `getEntries()` to return a list of `Person`.
-- Call `delete()` or `save()` to update a given entity.
-
-Example
-=======
-
-```java
- @Inject
- PersonService service;
-
- @PostConstruct
- void load() {
- service.loadData();
-
- container.bind(service.getEntries());
- }
-```
diff --git a/pom.xml b/pom.xml
index 9789052..d761ada 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,8 +6,11 @@
org.vaadin.stepbystep
person-service
jar
- 1.0
- Person Service: Step by step backend demo for a Vaadin app
+ 2.0
+ Demo Person Service
+
+ AMahdy
+
3
@@ -18,6 +21,12 @@
1.8
1.8
1.4.1
+ ${project.version}
+
+ ${project.name}
+ ${project.organization.name}
+ Apache License 2.0
+ ${project.artifactId}-${project.version}.jar
@@ -62,5 +71,26 @@
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.0.2
+
+
+ true
+
+ true
+ true
+
+
+
+ 1
+ ${Vaadin-License-Title}
+
+
+
+
+
diff --git a/src/main/java/org/vaadin/stepbystep/person/backend/LocalDateAttributeConverter.java b/src/main/java/org/vaadin/stepbystep/person/backend/LocalDateAttributeConverter.java
new file mode 100644
index 0000000..9a6bc4e
--- /dev/null
+++ b/src/main/java/org/vaadin/stepbystep/person/backend/LocalDateAttributeConverter.java
@@ -0,0 +1,20 @@
+package org.vaadin.stepbystep.person.backend;
+
+import javax.persistence.AttributeConverter;
+import javax.persistence.Converter;
+import java.sql.Date;
+import java.time.LocalDate;
+
+@Converter(autoApply = true)
+public class LocalDateAttributeConverter implements AttributeConverter {
+
+ @Override
+ public Date convertToDatabaseColumn(LocalDate locDate) {
+ return (locDate == null ? null : Date.valueOf(locDate));
+ }
+
+ @Override
+ public LocalDate convertToEntityAttribute(Date sqlDate) {
+ return (sqlDate == null ? null : sqlDate.toLocalDate());
+ }
+}
diff --git a/src/main/java/org/vaadin/stepbystep/person/backend/Person.java b/src/main/java/org/vaadin/stepbystep/person/backend/Person.java
index a7ba60f..7cfcb47 100644
--- a/src/main/java/org/vaadin/stepbystep/person/backend/Person.java
+++ b/src/main/java/org/vaadin/stepbystep/person/backend/Person.java
@@ -1,14 +1,12 @@
package org.vaadin.stepbystep.person.backend;
-import java.util.Date;
-
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Lob;
-import javax.persistence.Temporal;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
+import java.time.LocalDate;
/**
* A domain object example. In a real application this would probably be a JPA
@@ -18,20 +16,19 @@
@Entity
public class Person extends AbstractEntity {
- @NotNull(message = "Firstname is required")
- @Size(min = 3, max = 40, message = "Firstname must be longer than 3 and less than 40 characters")
- private String firstname;
+ @NotNull(message = "First Name is required")
+ @Size(min = 3, max = 40, message = "First Name must be longer than 3 and less than 40 characters")
+ private String firstName;
- @NotNull(message = "Lastname is required")
- @Size(min = 3, max = 40, message = "Lastname must be longer than 3 and less than 40 characters")
- private String lastname;
+ @NotNull(message = "Last Name is required")
+ @Size(min = 3, max = 40, message = "Last Name must be longer than 3 and less than 40 characters")
+ private String lastName;
@NotNull(message = "Email is required")
@Pattern(regexp = ".+@.+\\.[a-z]+", message = "Must be valid email")
private String email;
- @Temporal(javax.persistence.TemporalType.DATE)
- private Date birthDate;
+ private LocalDate dateOfBirth;
private boolean remind = false;
@@ -44,20 +41,20 @@ public class Person extends AbstractEntity {
public Person() {
}
- public String getFirstname() {
- return firstname;
+ public String getFirstName() {
+ return firstName;
}
- public void setFirstname(String firstname) {
- this.firstname = firstname;
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
}
- public String getLastname() {
- return lastname;
+ public String getLastName() {
+ return lastName;
}
- public void setLastname(String lastname) {
- this.lastname = lastname;
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
}
public boolean isRemind() {
@@ -76,12 +73,12 @@ public void setEmail(String email) {
this.email = email;
}
- public Date getBirthDate() {
- return birthDate;
+ public LocalDate getDateOfBirth() {
+ return dateOfBirth;
}
-
- public void setBirthDate(Date birthDate) {
- this.birthDate = birthDate;
+
+ public void setDateOfBirth(LocalDate dateOfBirth) {
+ this.dateOfBirth = dateOfBirth;
}
public String getPicture() {
diff --git a/src/main/java/org/vaadin/stepbystep/person/backend/PersonService.java b/src/main/java/org/vaadin/stepbystep/person/backend/PersonService.java
index 59ac4ef..79fe6c2 100644
--- a/src/main/java/org/vaadin/stepbystep/person/backend/PersonService.java
+++ b/src/main/java/org/vaadin/stepbystep/person/backend/PersonService.java
@@ -1,18 +1,19 @@
package org.vaadin.stepbystep.person.backend;
+import javax.annotation.PostConstruct;
+import javax.ejb.Stateless;
+import javax.inject.Inject;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
import java.util.List;
-
-import javax.ejb.Stateless;
-import javax.inject.Inject;
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
+import java.util.Locale;
/**
* EJB to hide JPA related stuff from the UI layer.
@@ -33,17 +34,32 @@ public List getEntries() {
return entryRepo.findAll();
}
- public void save(Person entity) {
- entryRepo.save(entity);
+ public Person getFirst() {
+ return entryRepo.findAll(0, 1).get(0);
+ }
+
+ public Person getById(Long id) {
+ return entryRepo.findById(id).getSingleResult();
+ }
+
+ public Person save(Person entity) {
+ return entryRepo.saveAndFlush(entity);
}
public void delete(Person entity) {
// Hibernate cannot remove detached, reattach...
- entryRepo.remove(entryRepo.findBy(entity.getId()));
+ entryRepo.removeAndFlush(entryRepo.findBy(entity.getId()));
}
+ @PostConstruct
public void loadData() {
+ if(entryRepo.count() != 0) {
+ return;
+ }
+
+ // Fill in demo data
+
String csvFile = "Persons.csv";
BufferedReader br = null;
String line = "";
@@ -54,21 +70,18 @@ public void loadData() {
InputStream inputStream = getClass().getClassLoader().getResourceAsStream(csvFile);
br = new BufferedReader(new InputStreamReader(inputStream));
- SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yy");
+ DateTimeFormatter dtf = DateTimeFormatter.ofPattern("d-MMM-yy")
+ .withLocale(Locale.US);
while ((line = br.readLine()) != null) {
String[] person = line.split(cvsSplitBy);
Person entry = new Person();
// entry.setId(Long.parseLong(person[0]));
- entry.setFirstname(person[1]);
- entry.setLastname(person[2]);
+ entry.setFirstName(person[1]);
+ entry.setLastName(person[2]);
entry.setEmail(person[3]);
- try {
- entry.setBirthDate(sdf.parse(person[4]));
- } catch (ParseException e) {
- e.printStackTrace();
- }
+ entry.setDateOfBirth(LocalDate.parse(person[4], dtf));
entry.setRemind(Math.random() > 0.5);
entry.setPicture(person[5]);
entry.setNotes(person[6]);
diff --git a/src/resources/META-INF/persistence.xml b/src/resources/META-INF/persistence.xml
index 2c44b2b..7c08e06 100644
--- a/src/resources/META-INF/persistence.xml
+++ b/src/resources/META-INF/persistence.xml
@@ -5,9 +5,9 @@
server will generate a test database automatically for you.
For production deployment you'll want to configure data source in your
app server and poin it to your database. -->
-
+
-
+