Petclinic Jakarta EE - a Jakarta EE 10 Version of Spring Petclinic demo application using PrimeFaces JSF.
- JSF and Jakarta EE 10 Version of Spring Petclinic
- This is an Update of Java EE 7 Petclinic
- Github: https://github.com/Jakarta-EE-Petclinic/petclinic-jakartaee
- Demo on OpenShift: http://jakartaee8petclinic.rhcloud.com/
- Blog: https://thomas-woehlke.blogspot.com/2014/02/java-ee-7-petclinic.html
- Some experimental Work with JSF, Jakarta EE 10 and Java EE
- This Demo Application is planned to be the first in a series of “Rosetta Stone” to compare OOP Web Application Frameworks
- The Domain Classes show all relationships like one-to-many (1:n), many-to-one (n:1) and many-to-many (n:m)
- It is simple enough but yet it shows more than just the CRUD Use Cases (Create, Read, Update, Delete) of most Demos and Training Examples.
- You can think of it as smallest complete Web App with the usual things to solve.
- github.com/Jakarta-EE-Petclinic/petclinic-javaee7
- Thomas Woehlke: Java EE 7 Petclinic
- Stefan Hildebrandt: Was eine QS-Abetilung immer wollte. Mit automatisierten Tests zum Ziel
- Reza Rahman: Migrating the Spring Pet Clinic to Java EE 7
git clone [email protected]:Jakarta-EE-Petclinic/petclinic-jakartaee.git
cd petclinic-jakartaee
./mvnw
maven profile | Runtime | Version | Status |
---|---|---|---|
./mvnw -Pliberty | OpenLiberty | 23.0.0.6 | Jakarta EE 10 |
./mvnw -Pwildfly | Wildfly | 28.0.1.Final | Jakarta EE 10 |
./mvnw -Ppayara | Payara | 6.2023.6 | Jakarta EE 10 |
./mvnw -Pglassfish | GlassFish | 7.0.5 | Jakarta EE 10 |
./mvnw -Ptomee | Apache TomEE | 9.1.0 | Jakarta EE 9.1 |
Arquillian End2End Tests for REST Endpoints and for JSF Frontend Browser Tests with Graphene and Selenium.
maven profile | Runtime | Version | Status |
---|---|---|---|
./mvnw -Parq-liberty-managed | OpenLiberty | 23.0.0.1 | waiting for OpenLiberty |
./mvnw -Parq-wildfly-managed | Wildfly | 27.0.1.Final | work in progress |
./mvnw -Parq-payara-managed | Payara | 6.2023.2 | work in progress |
./mvnw -Parq-glassfish-managed | GlassFish | 7.0.2 | work in progress |
Object Oriented Design
Specialty Use Cases | Specialty States | Frontend |
---|---|---|
Specialty.list | SPECIALTY_LIST_EMPTY | Disable Search-Button and Paging-Widget |
Specialty.list | SPECIALTY_LIST | |
Specialty.search | SPECIALTY_LIST_SEARCH_RESULT | |
Specialty.addNew | SPECIALTY_NEW | |
Specialty.details | SPECIALTY_DETAILS | |
Specialty.edit | SPECIALTY_EDIT | |
Specialty.delete | SPECIALTY_DELETE |
PetType Use Cases | Actions | Frontend to View | View to Backend (DB) | outcome | precondition | postcondition |
---|---|---|---|---|---|---|
Specialty.list | SpecialtyView.button_list_dialog() | x, calls: SpecialtyView.loadList() | change state | length(list(Specialty)) > 0 | SPECIALTY_LIST | |
Specialty.list | SpecialtyView.loadList() | x | list(Specialty) | length(list(Specialty)) == 0 | SPECIALTY_LIST_EMPTY | |
Specialty.list | SpecialtyView.loadList() | x | list(Specialty) | length(list(Specialty)) > 0 | SPECIALTY_LIST | |
Specialty.addNew | SpecialtyView.button_addNew_dialog() | x | change state | SPECIALTY_LIST | SPECIALTY_NEW | |
Specialty.addNew | SpecialtyView.cancelNew() | x | change state | SPECIALTY_NEW | SPECIALTY_LIST | |
Specialty.addNew | SpecialtyView.saveNew() | x, calls: SpecialtyView.saveNewEntity() | if OK: change state | SPECIALTY_NEW | SPECIALTY_DETAILS | |
Specialty.addNew | SpecialtyView.saveNewEntity() | x | OK | length(list(Specialty)) = n | length(list(Specialty)) = n+1 | |
Specialty.addNew | SpecialtyView.saveNewEntity() | x | not OK, invalid | length(list(Specialty)) = n | display cause as flash message | |
Specialty.details | SpecialtyView.showDetailsForm(Specialty) | x | change state | SPECIALTY_LIST | SPECIALTY_DETAILS | |
Specialty.edit | SpecialtyView.showEditForm() | x | change state | SPECIALTY_DETAILS | SPECIALTY_EDIT | |
Specialty.edit | SpecialtyView.cancelEdited() | x | change state | SPECIALTY_EDIT | SPECIALTY_LIST | |
Specialty.edit | SpecialtyView.saveEdited() | x, calls: SpecialtyView.saveEditedEntity() | if OK: change state | SPECIALTY_EDIT | SPECIALTY_DETAILS | |
Specialty.edit | SpecialtyView.saveEditedEntity() | x | OK | length(list(Specialty)) = n > 0 | length(list(Specialty)) = n; 1 element changed | |
Specialty.edit | SpecialtyView.saveEditedEntity() | x | not OK, invalid | length(list(Specialty)) = n >= 0 | display cause as flash message | |
Specialty.delete | SpecialtyView.showDeleteForm() | x | change state | SPECIALTY_DETAILS | SPECIALTY_DELETE | |
Specialty.delete | SpecialtyView.cancelDelete() | x | change state | SPECIALTY_DELETE | SPECIALTY_LIST | |
Specialty.delete | SpecialtyView.performDelete() | x, calls: SpecialtyView.deleteSelectedEntity() | if OK: change state | SPECIALTY_DELETE | SPECIALTY_DETAILS | |
Specialty.delete | SpecialtyView.deleteSelectedEntity() | x | OK | length(list(Specialty)) = n > 0 | length(list(Specialty)) = n-1 | |
Specialty.delete | SpecialtyView.deleteSelectedEntity() | x | not OK, invalid | length(list(Specialty)) = n >= 0 | display cause as flash message |
Use Case | Vetinarian States | Frontend |
---|---|---|
Vet.list | VET_LIST_EMPTY | Disable Search-Button and Paging-Widget |
Vet.list | VET_LIST | |
Vet.search | VET_LIST_SEARCH_RESULT | |
Vet.addNew | VET_NEW | |
Vet.details | vet_DETAILS | |
Vet.details | VET_DETAILS | |
Vet.edit | VET_EDIT | |
Vet.delete | VET_DELETE |
*) TODO
PetType Use Cases | Actions | Frontend to View | View to Backend (DB) | outcome | precondition | postcondition |
---|---|---|---|---|---|---|
Vet.list | VetView.button_list_dialog() | x, calls: Vet View.loadList() | change state | length(list(Vet)) > 0 | VET_LIST | |
Vet.list | VetView.loadList() | x | list(Vet) | length(list(Vet)) == 0 | VET_LIST_EMPTY | |
Vet.list | VetView.loadList() | x | list(Vet) | length(list(Vet)) > 0 | VET_LIST | |
Vet.addNew | VetView.showNewForm() | x, calls: VetView.newEntity() | change state | VET_LIST | VET_NEW | |
Vet.addNew | VetView.cancelNew() | x | change state | VET_NEW | VET_LIST | |
Vet.addNew | VetView.saveNew() | x, calls: VetView.saveNewEntity() | if OK: change state | VET_NEW | VET_DETAILS | |
Vet.addNew | VetView.saveNewEntity() | x | OK | length(list(Vet)) = n | length(list(Vet)) = n+1 | |
Vet.addNew | VetView.saveNewEntity() | x | not OK, invalid | length(list(Vet)) = n | display cause as flash message | |
Vet.details | VetView.showDetailsForm(Vet) | x | change state | VET_LIST | VET_DETAILS | |
Vet.details | VetView.cancelDetails() | x | change state | VET_DETAILS | VET_LIST | |
Vet.edit | VetView.showEditForm() | x | change state | VET_DETAILS | VET_EDIT | |
Vet.edit | VetView.cancelEdited() | x | change state | VET_EDIT | VET_LIST | |
Vet.edit | VetView.saveEdited() | x, calls: VetView.saveEditedEntity() | if OK: change state | VET_EDIT | VET_DETAILS | |
Vet.edit | VetView.saveEditedEntity() | x | OK | length(list(Vet)) = n > 0 | length(list(Vet)) = n; 1 element changed | |
Vet.edit | VetView.saveEditedEntity() | x | not OK, invalid | length(list(Vet)) = n >= 0 | display cause as flash message | |
Vet.delete | VetView.showDeleteForm() | x | change state | VET_DETAILS | VET_DELETE | |
Vet.delete | VetView.cancelDelete() | x | change state | VET_DELETE | VET_LIST | |
Vet.delete | VetView.performDelete() | x, calls: VetView.deleteSelectedEntity() | if OK: change state | VET_DELETE | VET_DETAILS | |
Vet.delete | VetView.deleteSelectedEntity() | x | OK | length(list(Vet)) = n > 0 | length(list(Vet)) = n-1 | |
Vet.delete | VetView.deleteSelectedEntity() | x | not OK, invalid | length(list(Vet)) = n >= 0 | display cause as flash message |
PetType States | PetType Use Cases | Frontend |
---|---|---|
PetType.list | PETTYPE_LIST_EMPTY | Disable Search-Button and Paging-Widget |
PetType.list | PETTYPE_LIST | |
PetType.search | PETTYPE_LIST_SEARCH_RESULT | |
PetType.addNew | PETTYPE_NEW | |
PetType.details | PETTYPE_DETAILS | |
PetType.edit | PETTYPE_EDIT | |
PetType.delete | PETTYPE_DELETE |
*) TODO
PetType Use Cases | Actions | Frontend to View | View to Backend (DB) | outcome | precondition | postcondition |
---|---|---|---|---|---|---|
PetType.list | PetTypeView.button_list_dialog() | x, calls: PetType.loadList() | change state | length(list(PetType)) == 0 | PETTYPE_LIST_EMPTY | |
PetType.list | PetTypeView.button_list_dialog() | x, calls: PetType.loadList() | change state | length(list(PetType)) > 0 | PETTYPE_LIST | |
PetType.list | PetTypeView.loadList() | x | list(PetType) | length(list(PetType)) == 0 | PETTYPE_LIST_EMPTY | |
PetType.list | PetTypeView.loadList() | x | list(PetType) | length(list(PetType)) > 0 | PETTYPE_LIST | |
PetType.addNew | PetTypeView.showNewForm() | x | change state | PETTYPE_LIST | PETTYPE_NEW | |
PetType.addNew | PetTypeView.cancelNew() | x | change state | PETTYPE_NEW | PETTYPE_LIST | |
PetType.addNew | PetTypeView.saveNew() | x, calls: PetType.saveNewEntity() | if OK: change state | PETTYPE_NEW | PETTYPE_DETAILS | |
PetType.addNew | PetTypeView.saveNewEntity() | x | OK | length(list(PetType)) = n | length(list(PetType)) = n+1 | |
PetType.addNew | PetTypeView.saveNewEntity() | x | not OK, invalid | length(list(PetType)) = n | display cause as flash message | |
PetType.details | PetTypeView.showDetailsForm(PetType) | x | change state | PETTYPE_LIST | PETTYPE_DETAILS | |
PetType.details | PetTypeView.cancelDetails() | x | change state | PETTYPE_LIST_EMPTY | PETTYPE_DETAILS | |
PetType.edit | PetTypeView.showEditForm() | x | change state | PETTYPE_DETAILS | PETTYPE_EDIT | |
PetType.edit | PetTypeView.cancelEdited() | x | change state | PETTYPE_EDIT | PETTYPE_LIST | |
PetType.edit | PetTypeView.saveEdited() | x, calls: PetType.saveEditedEntity() | if OK: change state | PETTYPE_EDIT | PETTYPE_DETAILS | |
PetType.edit | PetTypeView.saveEditedEntity() | x | OK | length(list(PetType)) = n > 0 | length(list(PetType)) = n; 1 element changed | |
PetType.edit | PetTypeView.saveEditedEntity() | x | not OK, invalid | length(list(PetType)) = n >= 0 | display cause as flash message | |
PetType.delete | PetTypeView.showDeleteForm() | x | change state | PETTYPE_DETAILS | PETTYPE_DELETE | |
PetType.delete | PetTypeView.cancelDelete() | x | change state | PETTYPE_DELETE | PETTYPE_LIST | |
PetType.delete | PetTypeView.cancelDelete() | x, calls: PetType.performDelete() | if OK: change state | PETTYPE_DELETE | PETTYPE_DETAILS | |
PetType.delete | PetTypeView.performDelete() | x | OK | length(list(PetType)) = n > 0 | length(list(PetType)) = n-1 | |
PetType.delete | PetTypeView.performDelete() | x | not OK, invalid | length(list(PetType)) = n >= 0 | display cause as flash message |
Use Case | Owner States | Frontend |
---|---|---|
Owner.list | OWNER_LIST | |
Owner.list | OWNER_LIST_SEARCH_RESULT | |
Owner.addNew | OWNER_NEW | |
Owner.details | OWNER_DETAILS | |
Owner.edit | OWNER_EDIT | |
Owner.delete | OWNER_DELETE | |
Owner.Pet.addNew | OWNER_PET_NEW | |
Owner.Pet.edit | OWNER_PET_EDIT | |
Owner.Pet.delete | OWNER_PET_DELETE | |
Owner.Pet.Visit.addNew | OWNER_PET_VISIT_NEW | |
Owner.Pet.Visit.edit | OWNER_PET_VISIT_EDIT | |
Owner.Pet.Visit.delete | OWNER_PET_VISIT_DELETE |
Use Case | Actions | Frontend to View | View to Backend (DB) | outcome | precondition | postcondition |
---|---|---|---|---|---|---|
Owner.list | OwnerView.button_list_dialog() | x, calls: Vet View.loadList() | change state | length(list(Owner)) == 0 | OWNER_LIST_EMPTY | |
Owner.list | OwnerView.button_list_dialog() | x, calls: Vet View.loadList() | change state | length(list(Owner)) > 0 | OWNER_LIST | |
Owner.list | OwnerView.loadList() | x | list(Owner) | length(list(Owner)) == 0 | OWNER_LIST_EMPTY | |
Owner.list | OwnerView.loadList() | x | list(Owner) | length(list(Owner)) > 0 | OWNER_LIST | |
Owner.addNew | OwnerView.showNewForm() | x | change state | OWNER_LIST | OWNER_NEW | |
Owner.addNew | OwnerView.cancelNew() | x | change state | OWNER_NEW | OWNER_LIST | |
Owner.addNew | OwnerView.cancelNew() | x | change state | OWNER_NEW | OWNER_LIST | |
Owner.addNew | OwnerView.saveNew() | x, calls: Owner.saveNewEntity() | if OK: change state | OWNER_NEW | OWNER_LIST | |
Owner.addNew | OwnerView.saveNewEntity() | x | OK | length(list(Owner)) = n | length(list(Owner)) = n+1 | |
Owner.addNew | OwnerView.saveNewEntity() | x | not OK, invalid | length(list(Owner)) = n | display cause as flash message | |
Owner.details | OwnerView.showDetailsForm(Owner) | x | change state | OWNER_LIST | OWNER_DETAILS | |
Owner.details | OwnerView.cancelDetails() | x | change state | OWNER_DETAILS | OWNER_LIST | |
Owner.edit | OwnerView.showNewForm() | x | change state | OWNER_DETAILS | OWNER_EDIT | |
Owner.edit | OwnerView.cancelNew() | x | change state | OWNER_EDIT | OWNER_DETAILS | |
Owner.edit | OwnerView.cancelNew() | x, calls: Owner.db_owner_update() | if OK: change state | OWNER_EDIT | OWNER_DETAILS | |
Owner.edit | OwnerView.saveEditedEntity() | x | OK | length(list(Owner)) = n > 0 | length(list(Owner)) = n; 1 element changed | |
Owner.edit | OwnerView.saveEditedEntity() | x | not OK, invalid | length(list(Owner)) = n >= 0 | display cause as flash message | |
Owner.delete | OwnerView.showDeleteForm() | x | change state | OWNER_DETAILS | OWNER_DELETE | |
Owner.delete | OwnerView.cancelDelete() | x | change state | OWNER_DELETE | OWNER_DETAILS | |
Owner.delete | OwnerView.performDelete() | x, calls: Owner.db_owner_delete() | if OK: change state | OWNER_DELETE | OWNER_DETAILS | |
Owner.delete | OwnerView.deleteSelectedEntity() | x | OK | length(list(Owner)) = n > 0 | length(list(Owner)) = n-1 | |
Owner.delete | OwnerView.deleteSelectedEntity() | x | not OK, invalid | length(list(Owner)) = n >= 0 | display cause as flash message | |
Owner.Pet.addNew | OwnerView.showOwnerPetNewForm() | x | change state | OWNER_DETAILS | OWNER_PET_NEW | |
Owner.Pet.addNew | OwnerView.saveOwnerPetNew() | x | change state | OWNER_PET_NEW | OWNER_DETAILS | |
Owner.Pet.edit | OwnerView.showOwnerPetEditForm(Pet pet) | x | change state | OWNER_DETAILS | OWNER_PET_EDIT | |
Owner.Pet.edit | OwnerView.saveOwnerPetEdit() | x | change state | OWNER_PET_EDIT | OWNER_DETAILS | |
Owner.Pet.Visit.addNew | OwnerView.showOwnerPetVisitNewForm() | x | change state | OWNER_DETAILS | OWNER_PET_VISIT_NEW | |
Owner.Pet.Visit.addNew | OwnerView.saveOwnerPetVisitNew() | x | change state | OWNER_PET_VISIT_NEW | OWNER_DETAILS |
- add some PetTypes like dog,cat,mouse,lion,frog,elephant,spider,...
- add some Specialties for Vetinarians like dentist, anesthetist, surgeon, neurosurgeon, oncologist, radiologist,...
- add a Vetinarian and choose his/her Specialties
- add an Owner, add her a Pet and book a visit for her Pet