diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..45e762d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+/.metadata
+/target
+/.settings
+.project
+.classpath
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..596715c
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,101 @@
+
+ 4.0.0
+ eu.lestard
+ noteWebApp
+ 0.0.1-SNAPSHOT
+ war
+
+
+ UTF-8
+
+
+
+
+
+ maven-compiler-plugin
+ 2.3.2
+
+ 1.6
+ 1.6
+
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+
+ false
+
+
+
+ org.apache.tomcat.maven
+ tomcat7-maven-plugin
+
+
+
+
+
+
+ org.apache.myfaces.core
+ myfaces-api
+ 2.1.2
+
+
+ org.apache.myfaces.core
+ myfaces-impl
+ 2.1.2
+
+
+
+ org.jboss.weld
+ weld-core
+ 1.1.0-01-glassfish
+
+
+ org.jboss.weld
+ weld-api
+ 1.1.0-01-glassfish
+
+
+ org.jboss.weld.servlet
+ weld-servlet
+ 1.0.1-Final
+
+
+
+
+ junit
+ junit
+ 4.9
+ test
+
+
+ org.mockito
+ mockito-all
+ 1.9.0-rc1
+ test
+
+
+ org.mockito
+ mockito-core
+ 1.9.0-rc1
+
+
+
+ nl.jqno.equalsverifier
+ equalsverifier
+ 1.0.2
+ test
+
+
+
+
+
+
+ equalsverifier-repository
+ http://equalsverifier.googlecode.com/svn/maven/
+
+
+
+
+
diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..8a26695
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,13 @@
+# JSF-CDI Beispiel-Applikation
+Diese Applikation ist wurde für den Vortrag bei der [Java User Group Görlitz](http://juggr.github.io) zum
+Thema ["Einführung in JavaServer Faces 2 und Contexts and Dependency Injection"](http://juggr.github.io/2011/11/30/jsf-cdi.html) am 30. November 2011 von Manuel Maukys
+entwickelt.
+
+Die Anwendung benutzt Maven als Build-Tool. Mit `mvn clean install` wird die Anwendung compiliert und die Tests ausgeführt.
+
+Mit `mvn tomcat7:run` wird ein Embedded Tomcat gestartet und die Anwendung deployed. Sie kann anschließend
+unter `http://localhost:8080/noteWebApp/` ausprobiert werden.
+
+
+
+
diff --git a/src/main/java/eu/lestard/notes/entity/Note.java b/src/main/java/eu/lestard/notes/entity/Note.java
new file mode 100644
index 0000000..e0a383c
--- /dev/null
+++ b/src/main/java/eu/lestard/notes/entity/Note.java
@@ -0,0 +1,76 @@
+package eu.lestard.notes.entity;
+
+/**
+ * Entity class for notes.
+ *
+ * @author manuel
+ *
+ */
+public class Note {
+
+ private String name;
+ private String content;
+
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * Sets the name for this note instance. The name must not be empty or null.
+ * @param name the name of the note.
+ *
+ * @throws IllegalArgumentException if the name is null
or empty.
+ */
+ public void setName(String name) {
+ if(name == null){
+ throw new IllegalArgumentException("Argument name must not be null");
+ }
+
+ if(name.length() == 0){
+ throw new IllegalArgumentException("Argument name must not be empty");
+ }
+
+ this.name = name;
+ }
+ public String getContent() {
+ return this.content;
+ }
+ public void setContent(String content) {
+ this.content = content;
+ }
+
+ @Override
+ public boolean equals(Object other){
+ if(other == null){
+ return false;
+ }
+
+ if(this == other){
+ return true;
+ }
+
+ if(!(other instanceof Note)){
+ return false;
+ }
+
+ if(!this.getClass().equals(other.getClass())){
+ return false;
+ }
+
+ Note that = (Note)other;
+
+ if(this.getName() != that.getName()){
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode(){
+ if(this.getName() != null){
+ return this.getName().hashCode();
+ }
+ return 1;
+ }
+}
diff --git a/src/main/java/eu/lestard/notes/entity/NullNote.java b/src/main/java/eu/lestard/notes/entity/NullNote.java
new file mode 100644
index 0000000..8a1fa0f
--- /dev/null
+++ b/src/main/java/eu/lestard/notes/entity/NullNote.java
@@ -0,0 +1,47 @@
+package eu.lestard.notes.entity;
+
+/**
+ * Null-Object class for the note entity.
+ *
+ * @author manuel
+ *
+ */
+public class NullNote extends Note {
+
+ private static Note instance;
+
+ private NullNote() {
+ }
+
+ /**
+ * Singleton factory method.
+ *
+ * @return
+ */
+ public static Note getInstance() {
+ if (instance == null) {
+ instance = new NullNote();
+ }
+
+ return instance;
+ }
+
+ @Override
+ public String getName() {
+ return "";
+ }
+
+ @Override
+ public void setName(final String name) {
+ };
+
+ @Override
+ public String getContent() {
+ return "";
+ }
+
+ @Override
+ public void setContent(final String content) {
+ };
+
+}
diff --git a/src/main/java/eu/lestard/notes/service/NoteService.java b/src/main/java/eu/lestard/notes/service/NoteService.java
new file mode 100644
index 0000000..3473ca7
--- /dev/null
+++ b/src/main/java/eu/lestard/notes/service/NoteService.java
@@ -0,0 +1,50 @@
+package eu.lestard.notes.service;
+
+import java.util.List;
+
+import eu.lestard.notes.entity.Note;
+
+/**
+ * Service class for all actions on notes.
+ *
+ * @author manuel
+ *
+ */
+public interface NoteService {
+
+ /**
+ * Adds a note to the system. If the given note is an instance of NullNote,
+ * the note is not saved.
+ *
+ * If there is already a note with the given name (Note.name
)
+ * the note old note is replaced with the new one.
+ *
+ * @param note
+ * the instance that should be added.
+ *
+ * @throws IllegalArgumentException
+ * if the note is null
+ */
+ void addNote(final Note note);
+
+ /**
+ *
+ * @param name
+ * the name of the note that should be found.
+ * @return the note instance with the given name or an instance of
+ * NullNote
if there is no note saved with the given
+ * name.
+ *
+ * @throws IllegalArgumentException
+ * if the given name is null or empty (
+ * name.length() == 0
)
+ */
+ Note findByName(final String name);
+
+ /**
+ *
+ * @return an unmodifiable List of all saved notes.
+ */
+ List findAll();
+
+}
diff --git a/src/main/java/eu/lestard/notes/service/NoteServiceImpl.java b/src/main/java/eu/lestard/notes/service/NoteServiceImpl.java
new file mode 100644
index 0000000..ac216d0
--- /dev/null
+++ b/src/main/java/eu/lestard/notes/service/NoteServiceImpl.java
@@ -0,0 +1,62 @@
+package eu.lestard.notes.service;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.enterprise.context.SessionScoped;
+
+import eu.lestard.notes.entity.Note;
+import eu.lestard.notes.entity.NullNote;
+
+@SessionScoped
+public class NoteServiceImpl implements NoteService, Serializable {
+
+ private static final long serialVersionUID = 3122100380644982038L;
+
+ private final Map notes = new HashMap();
+
+ @Override
+ public void addNote(final Note note) {
+ if (note == null) {
+ throw new IllegalArgumentException("Argument note must not be null");
+ }
+
+ if (!(note instanceof NullNote)) {
+ notes.put(note.getName(), note);
+ }
+
+ }
+
+ @Override
+ public Note findByName(final String name) {
+ if (name == null) {
+ throw new IllegalArgumentException("Argument name must not be null");
+ }
+
+ if (name.length() == 0) {
+ throw new IllegalArgumentException(
+ "Argument name must not be empty");
+ }
+
+ Note note = notes.get(name);
+
+ if (note == null) {
+ note = NullNote.getInstance();
+ }
+
+ return note;
+ }
+
+ @Override
+ public List findAll() {
+
+ List noteList = new ArrayList(notes.values());
+
+ return Collections.unmodifiableList(noteList);
+ }
+
+}
diff --git a/src/main/java/eu/lestard/notes/view/NotesBackingBean.java b/src/main/java/eu/lestard/notes/view/NotesBackingBean.java
new file mode 100644
index 0000000..4b6919e
--- /dev/null
+++ b/src/main/java/eu/lestard/notes/view/NotesBackingBean.java
@@ -0,0 +1,57 @@
+package eu.lestard.notes.view;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.List;
+
+import javax.enterprise.context.SessionScoped;
+import javax.inject.Named;
+
+import eu.lestard.notes.entity.Note;
+
+/**
+ * Backing bean that holds the data needed by the view.
+ *
+ * @author manuel
+ *
+ */
+@Named
+@SessionScoped
+public class NotesBackingBean implements Serializable {
+
+ private static final long serialVersionUID = -7065449337339482947L;
+
+ private List notes;
+
+ private String name;
+ private String content;
+
+ public NotesBackingBean() {
+ notes = Collections.emptyList();
+ }
+
+ public List getNotes() {
+ return Collections.unmodifiableList(notes);
+ }
+
+ public void setNotes(final List notes) {
+ this.notes = notes;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+ public void setContent(final String content) {
+ this.content = content;
+ }
+
+}
diff --git a/src/main/java/eu/lestard/notes/view/NotesController.java b/src/main/java/eu/lestard/notes/view/NotesController.java
new file mode 100644
index 0000000..fd36c0f
--- /dev/null
+++ b/src/main/java/eu/lestard/notes/view/NotesController.java
@@ -0,0 +1,66 @@
+package eu.lestard.notes.view;
+
+import java.util.List;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import eu.lestard.notes.entity.Note;
+import eu.lestard.notes.service.NoteService;
+
+/**
+ * Controller class to save new notes and synchronize the view with the values
+ * of the NoteService
+ *
+ * @author manuel
+ *
+ */
+@Named
+public class NotesController {
+
+ private final NotesBackingBean backingBean;
+
+ private final NoteService noteService;
+
+ @Inject
+ public NotesController(final NotesBackingBean backingBean,
+ final NoteService noteService) {
+ if (backingBean == null) {
+ throw new IllegalArgumentException(
+ "Argument NotesBackingBean was null");
+ }
+
+ if (noteService == null) {
+ throw new IllegalArgumentException("Argument NoteService was null");
+ }
+ this.backingBean = backingBean;
+ this.noteService = noteService;
+ }
+
+ @PostConstruct
+ @SuppressWarnings("unused")
+ private void postConstruct() {
+ synchronizeNotes();
+ }
+
+ public void addNote() {
+ String name = backingBean.getName();
+ String content = backingBean.getContent();
+
+ Note note = new Note();
+ note.setName(name);
+ note.setContent(content);
+
+ noteService.addNote(note);
+
+ synchronizeNotes();
+ }
+
+ private void synchronizeNotes() {
+ List notes = noteService.findAll();
+
+ backingBean.setNotes(notes);
+ }
+
+}
diff --git a/src/main/webapp/WEB-INF/beans.xml b/src/main/webapp/WEB-INF/beans.xml
new file mode 100644
index 0000000..8ba38bb
--- /dev/null
+++ b/src/main/webapp/WEB-INF/beans.xml
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/src/main/webapp/WEB-INF/faces-config.xml b/src/main/webapp/WEB-INF/faces-config.xml
new file mode 100644
index 0000000..933b2ea
--- /dev/null
+++ b/src/main/webapp/WEB-INF/faces-config.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..d7bae37
--- /dev/null
+++ b/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,32 @@
+
+
+ noteWebApp
+
+ index.xhtml
+
+
+
+
+
+
+ javax.faces.PROJECT_STAGE
+ Development
+
+
+
+ Faces Servlet
+ javax.faces.webapp.FacesServlet
+ 1
+
+
+ Faces Servlet
+ *.xhtml
+
+
+ org.jboss.weld.environment.servlet.Listener
+
+
+
\ No newline at end of file
diff --git a/src/main/webapp/index.xhtml b/src/main/webapp/index.xhtml
new file mode 100644
index 0000000..148534b
--- /dev/null
+++ b/src/main/webapp/index.xhtml
@@ -0,0 +1,55 @@
+
+
+
+
+
+ Notes
+
+
+ Your Notes:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/webapp/resources/components/notes/note.xhtml b/src/main/webapp/resources/components/notes/note.xhtml
new file mode 100644
index 0000000..b6aedc2
--- /dev/null
+++ b/src/main/webapp/resources/components/notes/note.xhtml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/java/eu/lestard/notes/entity/NoteTest.java b/src/test/java/eu/lestard/notes/entity/NoteTest.java
new file mode 100644
index 0000000..0e30a9a
--- /dev/null
+++ b/src/test/java/eu/lestard/notes/entity/NoteTest.java
@@ -0,0 +1,32 @@
+package eu.lestard.notes.entity;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+import nl.jqno.equalsverifier.Warning;
+
+import org.junit.Test;
+
+public class NoteTest {
+
+
+ @Test(expected=IllegalArgumentException.class)
+ public void testSetNameFailEmpty(){
+ Note note = new Note();
+
+ note.setName("");
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void testSetNameFailNull(){
+ Note note = new Note();
+
+ note.setName(null);
+ }
+
+
+ @Test
+ public void testEqualsAndHashcode(){
+ EqualsVerifier.forClass(Note.class)
+ .suppress(Warning.NONFINAL_FIELDS).usingGetClass().verify();
+ }
+
+}
diff --git a/src/test/java/eu/lestard/notes/service/NotesServiceTest.java b/src/test/java/eu/lestard/notes/service/NotesServiceTest.java
new file mode 100644
index 0000000..559181e
--- /dev/null
+++ b/src/test/java/eu/lestard/notes/service/NotesServiceTest.java
@@ -0,0 +1,114 @@
+package eu.lestard.notes.service;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+
+import org.junit.Test;
+
+import eu.lestard.notes.entity.Note;
+import eu.lestard.notes.entity.NullNote;
+
+public class NotesServiceTest {
+
+ private static final String NOTE_NAME2 = "myNote2";
+ private static final String NOTE_CONTENT = "This is my Content";
+ private static final String NOTE_NAME = "myNote1";
+
+ @Test
+ public void testAddNoteAndFindByName() {
+ NoteService noteService = new NoteServiceImpl();
+
+ Note note = new Note();
+
+ note.setName(NOTE_NAME);
+ note.setContent(NOTE_CONTENT);
+ noteService.addNote(note);
+
+ Note note2 = noteService.findByName(NOTE_NAME);
+
+ assertEquals(NOTE_NAME, note2.getName());
+ assertEquals(NOTE_CONTENT, note2.getContent());
+ }
+
+ @Test
+ public void testFindByNameFailNoEntry(){
+ NoteService noteService = new NoteServiceImpl();
+
+ Note emptyNote = noteService.findByName(NOTE_NAME);
+
+ assertNotNull(emptyNote);
+
+ assertTrue(emptyNote instanceof NullNote);
+ }
+
+
+ @Test(expected=IllegalArgumentException.class)
+ public void testFindByNameFailNull(){
+ NoteService noteService = new NoteServiceImpl();
+
+ noteService.findByName(null);
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void testFindByNameFailEmpty(){
+ NoteService noteService = new NoteServiceImpl();
+
+ noteService.findByName("");
+ }
+
+
+ @Test(expected=IllegalArgumentException.class)
+ public void testAddNoteFailNull(){
+ NoteService noteService = new NoteServiceImpl();
+ noteService.addNote(null);
+ }
+
+ @Test
+ public void testAddNoteNullObject(){
+ NoteService noteService = new NoteServiceImpl();
+
+ Note note = NullNote.getInstance();
+ noteService.addNote(note);
+
+
+ List notes = noteService.findAll();
+
+ assertTrue(notes.isEmpty());
+ }
+
+
+ @Test
+ public void testGetAll(){
+ NoteService noteService = new NoteServiceImpl();
+
+ Note note = new Note();
+ note.setName(NOTE_NAME);
+ note.setContent(NOTE_CONTENT);
+ noteService.addNote(note);
+
+ Note note2 = new Note();
+ note2.setName(NOTE_NAME2);
+ note2.setContent(NOTE_CONTENT);
+ noteService.addNote(note2);
+
+ List notes = noteService.findAll();
+ assertEquals(2,notes.size());
+ assertTrue(notes.contains(note));
+ assertTrue(notes.contains(note2));
+ }
+
+ @Test
+ public void testGetAllWithNoNotesSaved(){
+ NoteService noteService = new NoteServiceImpl();
+
+ List notes = noteService.findAll();
+
+ assertNotNull(notes);
+
+ assertTrue(notes.isEmpty());
+
+ }
+}
diff --git a/src/test/java/eu/lestard/notes/view/NotesControllerTest.java b/src/test/java/eu/lestard/notes/view/NotesControllerTest.java
new file mode 100644
index 0000000..b48d0db
--- /dev/null
+++ b/src/test/java/eu/lestard/notes/view/NotesControllerTest.java
@@ -0,0 +1,64 @@
+package eu.lestard.notes.view;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import eu.lestard.notes.entity.Note;
+import eu.lestard.notes.service.NoteService;
+
+public class NotesControllerTest {
+
+
+ private static final String MY_NOTE_NAME = "My Note 1";
+
+ private static final String MY_NOTE_CONTENT = "My note content....";
+
+ private NoteService noteService;
+
+ private NotesBackingBean backingBean;
+
+
+ @Test
+ public void testAddNote(){
+
+ this.backingBean = new NotesBackingBean();
+
+
+ this.noteService = Mockito.mock(NoteService.class);
+ NotesController controller = new NotesController(this.backingBean,this.noteService);
+
+ this.backingBean.setName(MY_NOTE_NAME);
+ this.backingBean.setContent(MY_NOTE_CONTENT);
+
+ List notes = this.backingBean.getNotes();
+ assertTrue(notes.isEmpty());
+
+ // We need to setup the NoteService
+ List notesInService = new ArrayList();
+ Note tempNote = new Note();
+ tempNote.setName(MY_NOTE_NAME);
+ tempNote.setContent(MY_NOTE_CONTENT);
+ notesInService.add(tempNote);
+ Mockito.when(this.noteService.findAll()).thenReturn(notesInService);
+
+ controller.addNote();
+
+ Mockito.verify(this.noteService, Mockito.times(1)).addNote(Mockito.any(Note.class));
+
+ notes = this.backingBean.getNotes();
+ assertEquals(1, notes.size());
+
+ Note note = notes.get(0);
+ assertEquals(MY_NOTE_NAME,note.getName());
+ assertEquals(MY_NOTE_CONTENT, note.getContent());
+
+ }
+
+}