├── .gitignore ├── Keycloak-Demo.postman_collection.json ├── README.md ├── demos ├── javaee7-petclinic │ ├── LICENSE │ ├── README.md │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── org │ │ │ │ └── woehlke │ │ │ │ └── javaee7 │ │ │ │ └── petclinic │ │ │ │ ├── dao │ │ │ │ ├── OwnerDao.java │ │ │ │ ├── OwnerDaoImpl.java │ │ │ │ ├── PetDao.java │ │ │ │ ├── PetDaoImpl.java │ │ │ │ ├── PetTypeDao.java │ │ │ │ ├── PetTypeDaoImpl.java │ │ │ │ ├── SpecialtyDao.java │ │ │ │ ├── SpecialtyDaoImpl.java │ │ │ │ ├── VetDao.java │ │ │ │ ├── VetDaoImpl.java │ │ │ │ ├── VisitDao.java │ │ │ │ └── VisitDaoImpl.java │ │ │ │ ├── entities │ │ │ │ ├── Owner.java │ │ │ │ ├── Pet.java │ │ │ │ ├── PetType.java │ │ │ │ ├── Specialty.java │ │ │ │ ├── Vet.java │ │ │ │ └── Visit.java │ │ │ │ ├── model │ │ │ │ └── Vets.java │ │ │ │ ├── services │ │ │ │ ├── JaxRsActivator.java │ │ │ │ ├── OwnerService.java │ │ │ │ ├── OwnerServiceImpl.java │ │ │ │ └── VetWebservice.java │ │ │ │ └── web │ │ │ │ ├── LanguageBean.java │ │ │ │ ├── OwnerController.java │ │ │ │ ├── OwnerSortingBean.java │ │ │ │ ├── PetTypeController.java │ │ │ │ ├── SpecialtyController.java │ │ │ │ ├── SpecialtyConverter.java │ │ │ │ ├── VetController.java │ │ │ │ ├── VetSortingBean.java │ │ │ │ └── keycloak │ │ │ │ ├── KeycloakBean.java │ │ │ │ ├── KeycloakContextProvider.java │ │ │ │ └── KeycloakSsoFilter.java │ │ ├── resources │ │ │ ├── META-INF │ │ │ │ └── persistence.xml │ │ │ ├── messages.properties │ │ │ ├── messages_de.properties │ │ │ └── messages_en.properties │ │ └── webapp │ │ │ ├── WEB-INF │ │ │ ├── faces-config.xml │ │ │ ├── jboss-deployment-structure.xml │ │ │ ├── jboss-web.xml │ │ │ └── keycloak.json │ │ │ ├── addNewPet.xhtml │ │ │ ├── addVisitToPet.xhtml │ │ │ ├── editOwner.xhtml │ │ │ ├── editPet.xhtml │ │ │ ├── editPetType.xhtml │ │ │ ├── editSpecialty.xhtml │ │ │ ├── editVet.xhtml │ │ │ ├── findOwners.xhtml │ │ │ ├── hello.xhtml │ │ │ ├── index.html │ │ │ ├── newOwner.xhtml │ │ │ ├── newPetType.xhtml │ │ │ ├── newSpecialty.xhtml │ │ │ ├── newVet.xhtml │ │ │ ├── owners.xhtml │ │ │ ├── petTypes.xhtml │ │ │ ├── showOwner.xhtml │ │ │ ├── specialties.xhtml │ │ │ ├── template.xhtml │ │ │ └── vets.xhtml │ │ ├── site │ │ ├── apt │ │ │ └── index.apt │ │ ├── resources │ │ │ └── images │ │ │ │ ├── DomainClassModell.jpg │ │ │ │ ├── Pageflow.jpg │ │ │ │ ├── UseCases.jpg │ │ │ │ ├── UseCasesOwner.jpg │ │ │ │ ├── phasenraum_logo.gif │ │ │ │ ├── screenAddVet.png │ │ │ │ ├── screenNewVisit.png │ │ │ │ └── screenOwner.png │ │ └── site.xml │ │ └── test │ │ ├── java │ │ └── org │ │ │ └── woehlke │ │ │ └── javaee7 │ │ │ └── petclinic │ │ │ └── web │ │ │ ├── Deployments.java │ │ │ ├── Test01Specialties.java │ │ │ ├── Test02Vet.java │ │ │ ├── Test03PetType.java │ │ │ ├── Test04Owner.java │ │ │ └── pages │ │ │ ├── EditOwnerPage.java │ │ │ ├── EditPetPage.java │ │ │ ├── EditPetTypePage.java │ │ │ ├── EditSpecialtiesPage.java │ │ │ ├── EditVetPage.java │ │ │ ├── FindOwnersPage.java │ │ │ ├── HelloPage.java │ │ │ ├── NewOwnerPage.java │ │ │ ├── NewPetPage.java │ │ │ ├── NewPetTypePage.java │ │ │ ├── NewSpecialtiesPage.java │ │ │ ├── NewVetPage.java │ │ │ ├── NewVisitPage.java │ │ │ ├── OwnersPage.java │ │ │ ├── PetTypesPage.java │ │ │ ├── ShowOwnerPage.java │ │ │ ├── SpecialtiesPage.java │ │ │ └── VetsPage.java │ │ └── resources │ │ ├── WEB-INF │ │ └── beans.xml │ │ ├── arquillian.xml │ │ └── log4j.xml ├── keycloak-admin-cli │ └── admin-cli.md ├── keycloak-javafx-client-demo │ ├── .gitignore │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── demo │ │ │ ├── KeycloakJavafxClientDemoApp.java │ │ │ └── app │ │ │ └── HelloworldView.java │ │ └── resources │ │ ├── application.properties │ │ └── fxml │ │ └── helloworld.fxml ├── keycloak-postman │ └── 3.x │ │ └── keycloak-postman-3.x.json ├── plain-js-frontend │ ├── start.sh │ ├── start3.sh │ └── webapp │ │ ├── app.js │ │ ├── index.html │ │ └── styles.css ├── spring-boot-2-backend │ ├── .gitignore │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── demo │ │ │ │ ├── Backend2Application.java │ │ │ │ ├── KeycloakEvaluationContextExtension.java │ │ │ │ └── todo │ │ │ │ ├── Todo.java │ │ │ │ └── TodoRepository.java │ │ └── resources │ │ │ ├── application.yml │ │ │ └── data.sql │ │ └── test │ │ └── java │ │ └── demo │ │ └── SpringBootBackendApplicationTests.java ├── spring-boot-2-frontend │ ├── .gitignore │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── demo │ │ │ │ ├── Frontend2Application.java │ │ │ │ ├── config │ │ │ │ ├── KeycloakConfig.java │ │ │ │ └── KeycloakLinkGenerator.java │ │ │ │ ├── todo │ │ │ │ ├── KeycloakTodoClient.java │ │ │ │ ├── Todo.java │ │ │ │ └── TodoClient.java │ │ │ │ └── web │ │ │ │ ├── PingController.java │ │ │ │ └── UiController.java │ │ └── resources │ │ │ ├── application.yml │ │ │ ├── static │ │ │ └── css │ │ │ │ └── style.css │ │ │ └── templates │ │ │ ├── error.html │ │ │ ├── fragments.html │ │ │ ├── index.html │ │ │ └── todos.html │ │ └── test │ │ └── java │ │ └── demo │ │ └── SpringBootFrontend2ApplicationTests.java ├── spring-boot-app-integration │ ├── .gitignore │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── demo │ │ │ │ ├── SecurityConfig.java │ │ │ │ ├── ThirdpartyApp.java │ │ │ │ ├── oauth2 │ │ │ │ ├── Oauth2Client.java │ │ │ │ ├── Oauth2Properties.java │ │ │ │ └── TokensStore.java │ │ │ │ └── web │ │ │ │ ├── ApiController.java │ │ │ │ └── ConnectController.java │ │ └── resources │ │ │ ├── application.yml │ │ │ └── templates │ │ │ ├── connected.html │ │ │ └── index.html │ │ └── test │ │ └── java │ │ └── demo │ │ └── SpringBootAppIntegrationApplicationTests.java ├── spring-boot-backend │ ├── .gitignore │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── demo │ │ │ │ ├── BackendApplication.java │ │ │ │ ├── KeycloakEvaluationContextExtension.java │ │ │ │ └── todo │ │ │ │ ├── Todo.java │ │ │ │ └── TodoRepository.java │ │ └── resources │ │ │ ├── application.yml │ │ │ └── data.sql │ │ └── test │ │ └── java │ │ └── demo │ │ └── SpringBootBackendApplicationTests.java ├── spring-boot-frontend-javafx │ ├── .gitignore │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── demo │ │ │ │ ├── JavaFxFrontendApplication.java │ │ │ │ └── todos │ │ │ │ ├── Todo.java │ │ │ │ ├── TodoClient.java │ │ │ │ ├── TodoClientConfig.java │ │ │ │ ├── TodoService.java │ │ │ │ ├── TodoServiceImpl.java │ │ │ │ └── ui │ │ │ │ ├── TodosController.java │ │ │ │ ├── TodosView.java │ │ │ │ ├── todos.css │ │ │ │ ├── todos.fxml │ │ │ │ ├── todos.properties │ │ │ │ └── todos_de_DE.properties │ │ └── resources │ │ │ ├── META-INF │ │ │ └── keycloak.json │ │ │ ├── application.yml │ │ │ └── spring-boot-icon.png │ │ └── test │ │ └── java │ │ └── demo │ │ └── SpringBootFrontendJavafxApplicationTests.java ├── spring-boot-frontend │ ├── .gitignore │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── demo │ │ │ │ ├── FrontendApplication.java │ │ │ │ ├── config │ │ │ │ ├── KeycloakConfig.java │ │ │ │ └── KeycloakLinkGenerator.java │ │ │ │ ├── todo │ │ │ │ ├── Todo.java │ │ │ │ ├── TodoClient.java │ │ │ │ └── TodoClientConfig.java │ │ │ │ └── web │ │ │ │ ├── PingController.java │ │ │ │ └── UiController.java │ │ └── resources │ │ │ ├── application.yml │ │ │ ├── static │ │ │ └── css │ │ │ │ └── style.css │ │ │ └── templates │ │ │ ├── error.html │ │ │ ├── fragments.html │ │ │ ├── index.html │ │ │ └── todos.html │ │ └── test │ │ └── java │ │ └── demo │ │ └── SpringBootFrontendApplicationTests.java ├── spring-cloud-oauth2-demo │ ├── .gitignore │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── mvnw │ ├── mvnw.cmd │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ ├── META-INF │ │ │ │ └── MANIFEST.MF │ │ │ └── demo │ │ │ │ └── Oauth2DemoApplication.java │ │ └── resources │ │ │ └── application.yml │ │ └── test │ │ └── java │ │ └── demo │ │ └── Oauth2DemoApplicationTests.java ├── spring-oauth-cli-demo │ ├── application.yml │ ├── hello-oauth-final.groovy │ └── hello.groovy └── spring-websocket-chat │ └── readme.md ├── idm-system ├── acme-realm.json ├── customizations │ └── graylog │ │ └── custom-extractors.json ├── docker-compose.yml ├── jq └── keycloak │ ├── Dockerfile │ ├── activemq-rar.rar │ ├── docker-build.sh │ ├── docker-entrypoint.sh │ ├── extensions │ ├── jms-event-forwarder │ │ ├── pom.xml │ │ └── src │ │ │ └── main │ │ │ ├── java │ │ │ └── de │ │ │ │ └── tdlabs │ │ │ │ └── keycloak │ │ │ │ └── ext │ │ │ │ └── events │ │ │ │ └── forwarder │ │ │ │ ├── AuditInfo.java │ │ │ │ ├── ForwardingEventListenerProvider.java │ │ │ │ ├── IdmEventMapper.java │ │ │ │ ├── IdmEventPublisher.java │ │ │ │ ├── InstanceNameHolder.java │ │ │ │ ├── JmsEventListenerProviderFactory.java │ │ │ │ ├── KeycloakIdmEvent.java │ │ │ │ ├── RoleInfo.java │ │ │ │ └── UserInfo.java │ │ │ └── resources │ │ │ └── META-INF │ │ │ └── services │ │ │ └── org.keycloak.events.EventListenerProviderFactory │ └── user-storage-provider-demo │ │ ├── .gitignore │ │ ├── LICENSE │ │ ├── ear-module │ │ └── pom.xml │ │ ├── jar-module │ │ ├── pom.xml │ │ └── src │ │ │ └── main │ │ │ ├── java │ │ │ └── de │ │ │ │ └── tdlabs │ │ │ │ └── keycoak │ │ │ │ └── ext │ │ │ │ └── storage │ │ │ │ └── demo │ │ │ │ ├── DemoUserStorageProvider.java │ │ │ │ ├── DemoUserStorageProviderFactory.java │ │ │ │ ├── User.java │ │ │ │ ├── UserAdapter.java │ │ │ │ └── UserRepository.java │ │ │ └── resources │ │ │ └── META-INF │ │ │ └── services │ │ │ └── org.keycloak.storage.UserStorageProviderFactory │ │ ├── pom.xml │ │ ├── readme.md │ │ └── setup.cli │ ├── keycloak-setup.cli │ ├── modules │ ├── biz │ │ └── paluch │ │ │ └── logging │ │ │ └── main │ │ │ ├── commons-pool2-2.4.3.jar │ │ │ ├── jedis-2.9.0.jar │ │ │ ├── logstash-gelf-1.12.0.jar │ │ │ └── module.xml │ ├── de │ │ └── tdlabs │ │ │ └── keycloak │ │ │ └── ext │ │ │ └── jms-event-forwarder │ │ │ └── main │ │ │ └── module.xml │ └── org │ │ └── postgres │ │ └── main │ │ ├── module.xml │ │ └── postgresql.jar │ └── themes │ ├── springio18 │ └── login │ │ ├── resources │ │ ├── css │ │ │ └── login-custom.css │ │ └── img │ │ │ ├── springio18-bg-1.png │ │ │ └── springio18-bg.png │ │ └── theme.properties │ └── wjax18 │ └── login │ ├── resources │ ├── css │ │ └── login-custom.css │ └── img │ │ ├── WJAX_18_Website_Header_45485_v2_web.jpg │ │ └── wjax_logo_big-1.png │ └── theme.properties ├── keycloak-tdlabs.local.postman_environment.json └── slides ├── .gitkeep └── springio18-thomas-darimont-spring-keycloak.pdf /.gitignore: -------------------------------------------------------------------------------- 1 | idm-system/data/ 2 | *.class 3 | *.iml 4 | *.project 5 | *.classpath 6 | *.settings/ 7 | target/ 8 | 9 | .idea/ 10 | *.iml 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Spring 2 | Code & Slides from my talk `How to secure your Spring apps with Keycloak` at Spring I/O 2018 in Barcelona 3 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/java/org/woehlke/javaee7/petclinic/dao/OwnerDao.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.dao; 2 | 3 | import org.woehlke.javaee7.petclinic.entities.Owner; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Created with IntelliJ IDEA. 9 | * User: tw 10 | * Date: 06.01.14 11 | * Time: 09:38 12 | * To change this template use File | Settings | File Templates. 13 | */ 14 | public interface OwnerDao { 15 | 16 | List getAll(); 17 | 18 | void delete(long id); 19 | 20 | void addNew(Owner owner); 21 | 22 | Owner findById(long id); 23 | 24 | void update(Owner owner); 25 | 26 | List search(String searchterm); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/java/org/woehlke/javaee7/petclinic/dao/PetDao.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.dao; 2 | 3 | import org.woehlke.javaee7.petclinic.entities.Pet; 4 | 5 | /** 6 | * Created with IntelliJ IDEA. 7 | * User: tw 8 | * Date: 06.01.14 9 | * Time: 20:34 10 | * To change this template use File | Settings | File Templates. 11 | */ 12 | public interface PetDao { 13 | 14 | void addNew(Pet pet); 15 | 16 | Pet findById(long petId); 17 | 18 | void update(Pet pet); 19 | } 20 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/java/org/woehlke/javaee7/petclinic/dao/PetDaoImpl.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.dao; 2 | 3 | import org.woehlke.javaee7.petclinic.entities.Pet; 4 | 5 | import javax.ejb.Stateless; 6 | import javax.persistence.EntityManager; 7 | import javax.persistence.PersistenceContext; 8 | import java.util.logging.Logger; 9 | 10 | /** 11 | * Created with IntelliJ IDEA. 12 | * User: tw 13 | * Date: 06.01.14 14 | * Time: 20:34 15 | * To change this template use File | Settings | File Templates. 16 | */ 17 | @Stateless 18 | public class PetDaoImpl implements PetDao { 19 | 20 | private static Logger log = Logger.getLogger(PetDaoImpl.class.getName()); 21 | 22 | @PersistenceContext(unitName="javaee7petclinic") 23 | private EntityManager entityManager; 24 | 25 | 26 | @Override 27 | public void addNew(Pet pet) { 28 | log.info("addNewPet: "+pet.toString()); 29 | entityManager.persist(pet); 30 | } 31 | 32 | @Override 33 | public Pet findById(long petId) { 34 | return entityManager.find(Pet.class, petId); 35 | } 36 | 37 | @Override 38 | public void update(Pet pet) { 39 | log.info("updatePet: "+pet.toString()); 40 | pet=entityManager.merge(pet); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/java/org/woehlke/javaee7/petclinic/dao/PetTypeDao.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.dao; 2 | 3 | import org.woehlke.javaee7.petclinic.entities.PetType; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Created with IntelliJ IDEA. 9 | * User: Fert 10 | * Date: 06.01.14 11 | * Time: 11:51 12 | * To change this template use File | Settings | File Templates. 13 | */ 14 | public interface PetTypeDao { 15 | 16 | List getAll(); 17 | 18 | void delete(long id); 19 | 20 | void addNew(PetType petType); 21 | 22 | PetType findById(long id); 23 | 24 | void update(PetType petType); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/java/org/woehlke/javaee7/petclinic/dao/PetTypeDaoImpl.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.dao; 2 | 3 | import org.woehlke.javaee7.petclinic.entities.PetType; 4 | 5 | import javax.ejb.Stateless; 6 | import javax.persistence.EntityManager; 7 | import javax.persistence.PersistenceContext; 8 | import javax.persistence.TypedQuery; 9 | import java.util.List; 10 | import java.util.logging.Logger; 11 | 12 | /** 13 | * Created with IntelliJ IDEA. 14 | * User: Fert 15 | * Date: 06.01.14 16 | * Time: 11:51 17 | * To change this template use File | Settings | File Templates. 18 | */ 19 | @Stateless 20 | public class PetTypeDaoImpl implements PetTypeDao { 21 | 22 | private static Logger log = Logger.getLogger(PetTypeDaoImpl.class.getName()); 23 | 24 | @PersistenceContext(unitName="javaee7petclinic") 25 | private EntityManager entityManager; 26 | 27 | 28 | @Override 29 | public List getAll() { 30 | TypedQuery q = entityManager.createQuery("select pt from PetType pt order by pt.name",PetType.class); 31 | List list = q.getResultList(); 32 | return list; 33 | } 34 | 35 | @Override 36 | public void delete(long id) { 37 | PetType petType = entityManager.find(PetType.class, id); 38 | entityManager.remove(petType); 39 | } 40 | 41 | @Override 42 | public void addNew(PetType petType) { 43 | log.info("addNewPetType: "+petType.toString()); 44 | entityManager.persist(petType); 45 | } 46 | 47 | @Override 48 | public PetType findById(long id) { 49 | PetType petType = entityManager.find(PetType.class, id); 50 | return petType; 51 | } 52 | 53 | @Override 54 | public void update(PetType petType) { 55 | entityManager.merge(petType); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/java/org/woehlke/javaee7/petclinic/dao/SpecialtyDao.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.dao; 2 | 3 | import org.woehlke.javaee7.petclinic.entities.Specialty; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Created with IntelliJ IDEA. 9 | * User: tw 10 | * Date: 04.01.14 11 | * Time: 12:02 12 | * To change this template use File | Settings | File Templates. 13 | */ 14 | public interface SpecialtyDao { 15 | 16 | List getAll(); 17 | 18 | void delete(long id); 19 | 20 | void addNew(Specialty vet); 21 | 22 | Specialty findById(long id); 23 | 24 | void update(Specialty vet); 25 | } 26 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/java/org/woehlke/javaee7/petclinic/dao/SpecialtyDaoImpl.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.dao; 2 | 3 | import org.woehlke.javaee7.petclinic.entities.Specialty; 4 | 5 | import javax.ejb.Stateless; 6 | import javax.persistence.EntityManager; 7 | import javax.persistence.PersistenceContext; 8 | import javax.persistence.TypedQuery; 9 | import java.util.List; 10 | import java.util.logging.Logger; 11 | 12 | /** 13 | * Created with IntelliJ IDEA. 14 | * User: tw 15 | * Date: 04.01.14 16 | * Time: 12:03 17 | * To change this template use File | Settings | File Templates. 18 | */ 19 | @Stateless 20 | public class SpecialtyDaoImpl implements SpecialtyDao { 21 | 22 | private static Logger log = Logger.getLogger(SpecialtyDaoImpl.class.getName()); 23 | 24 | @PersistenceContext(unitName="javaee7petclinic") 25 | private EntityManager entityManager; 26 | 27 | @Override 28 | public List getAll() { 29 | TypedQuery q = entityManager.createQuery("select s from Specialty s order by s.name",Specialty.class); 30 | List list = q.getResultList(); 31 | return list; 32 | } 33 | 34 | @Override 35 | public void delete(long id) { 36 | Specialty specialty = entityManager.find(Specialty.class, id); 37 | entityManager.remove(specialty); 38 | } 39 | 40 | @Override 41 | public void addNew(Specialty specialty) { 42 | log.info("addNewSpecialty: "+specialty.toString()); 43 | entityManager.persist(specialty); 44 | } 45 | 46 | @Override 47 | public Specialty findById(long id) { 48 | Specialty specialty = entityManager.find(Specialty.class, id); 49 | return specialty; 50 | } 51 | 52 | @Override 53 | public void update(Specialty specialty) { 54 | entityManager.merge(specialty); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/java/org/woehlke/javaee7/petclinic/dao/VetDao.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.dao; 2 | 3 | import org.woehlke.javaee7.petclinic.entities.Vet; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Created with IntelliJ IDEA. 9 | * User: tw 10 | * Date: 02.01.14 11 | * Time: 08:37 12 | * To change this template use File | Settings | File Templates. 13 | */ 14 | public interface VetDao { 15 | 16 | List getAll(); 17 | 18 | void delete(long id); 19 | 20 | void addNew(Vet vet); 21 | 22 | Vet findById(long id); 23 | 24 | void update(Vet vet); 25 | 26 | List search(String searchterm); 27 | } 28 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/java/org/woehlke/javaee7/petclinic/dao/VisitDao.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.dao; 2 | 3 | import org.woehlke.javaee7.petclinic.entities.Visit; 4 | 5 | /** 6 | * Created with IntelliJ IDEA. 7 | * User: tw 8 | * Date: 07.01.14 9 | * Time: 12:43 10 | * To change this template use File | Settings | File Templates. 11 | */ 12 | public interface VisitDao { 13 | 14 | void addNew(Visit visit); 15 | 16 | void update(Visit visit); 17 | } 18 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/java/org/woehlke/javaee7/petclinic/dao/VisitDaoImpl.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.dao; 2 | 3 | import org.woehlke.javaee7.petclinic.entities.Visit; 4 | 5 | import javax.ejb.Stateless; 6 | import javax.persistence.EntityManager; 7 | import javax.persistence.PersistenceContext; 8 | import java.util.logging.Logger; 9 | 10 | /** 11 | * Created with IntelliJ IDEA. 12 | * User: tw 13 | * Date: 07.01.14 14 | * Time: 12:43 15 | * To change this template use File | Settings | File Templates. 16 | */ 17 | @Stateless 18 | public class VisitDaoImpl implements VisitDao { 19 | 20 | private static Logger log = Logger.getLogger(VisitDaoImpl.class.getName()); 21 | 22 | @PersistenceContext(unitName="javaee7petclinic") 23 | private EntityManager entityManager; 24 | 25 | @Override 26 | public void addNew(Visit visit) { 27 | log.info("addNewVisit: "+visit.toString()); 28 | entityManager.persist(visit); 29 | } 30 | 31 | @Override 32 | public void update(Visit visit) { 33 | visit= entityManager.merge(visit); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/java/org/woehlke/javaee7/petclinic/entities/PetType.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.entities; 2 | 3 | import org.hibernate.validator.constraints.NotEmpty; 4 | 5 | import javax.persistence.*; 6 | 7 | /** 8 | * Created with IntelliJ IDEA. 9 | * User: tw 10 | * Date: 01.01.14 11 | * Time: 21:12 12 | * To change this template use File | Settings | File Templates. 13 | */ 14 | @Entity 15 | @Table(name = "types") 16 | public class PetType { 17 | 18 | @Id 19 | @GeneratedValue(strategy = GenerationType.AUTO) 20 | private Long id; 21 | 22 | @NotEmpty 23 | @Column(name = "name") 24 | private String name; 25 | 26 | public Long getId() { 27 | return id; 28 | } 29 | 30 | public void setId(Long id) { 31 | this.id = id; 32 | } 33 | 34 | public String getName() { 35 | return name; 36 | } 37 | 38 | public void setName(String name) { 39 | this.name = name; 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | return "PetType{" + 45 | "id=" + id + 46 | ", name='" + name + '\'' + 47 | '}'; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/java/org/woehlke/javaee7/petclinic/entities/Specialty.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.entities; 2 | 3 | import org.hibernate.validator.constraints.NotEmpty; 4 | 5 | import javax.persistence.*; 6 | 7 | /** 8 | * Created with IntelliJ IDEA. 9 | * User: tw 10 | * Date: 01.01.14 11 | * Time: 21:11 12 | * To change this template use File | Settings | File Templates. 13 | */ 14 | @Entity 15 | @Table(name = "specialties") 16 | public class Specialty implements Comparable { 17 | 18 | @Id 19 | @GeneratedValue(strategy = GenerationType.AUTO) 20 | private Long id; 21 | 22 | @NotEmpty 23 | @Column(name = "name") 24 | private String name; 25 | 26 | public Long getId() { 27 | return id; 28 | } 29 | 30 | public void setId(Long id) { 31 | this.id = id; 32 | } 33 | 34 | public String getName() { 35 | return name; 36 | } 37 | 38 | public void setName(String name) { 39 | this.name = name; 40 | } 41 | 42 | @Override 43 | public int compareTo(Specialty other) { 44 | return this.name.compareTo(other.getName()); 45 | } 46 | 47 | 48 | @Override 49 | public boolean equals(Object o) { 50 | if (this == o) return true; 51 | if (!(o instanceof Specialty)) return false; 52 | 53 | Specialty specialty = (Specialty) o; 54 | 55 | if (id != null ? !id.equals(specialty.id) : specialty.id != null) return false; 56 | if (name != null ? !name.equals(specialty.name) : specialty.name != null) return false; 57 | 58 | return true; 59 | } 60 | 61 | @Override 62 | public int hashCode() { 63 | int result = id != null ? id.hashCode() : 0; 64 | result = 31 * result + (name != null ? name.hashCode() : 0); 65 | return result; 66 | } 67 | 68 | @Override 69 | public String toString() { 70 | return "Specialty{" + 71 | "id=" + id + 72 | ", name='" + name + '\'' + 73 | '}'; 74 | } 75 | 76 | 77 | } 78 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/java/org/woehlke/javaee7/petclinic/model/Vets.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.model; 2 | 3 | import org.woehlke.javaee7.petclinic.entities.Vet; 4 | 5 | import javax.xml.bind.annotation.XmlElement; 6 | import javax.xml.bind.annotation.XmlRootElement; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | /** 11 | * Created with IntelliJ IDEA. 12 | * User: tw 13 | * Date: 01.01.14 14 | * Time: 21:37 15 | * To change this template use File | Settings | File Templates. 16 | */ 17 | @XmlRootElement 18 | public class Vets { 19 | 20 | private List vetList; 21 | 22 | @XmlElement 23 | public List getVetList() { 24 | if (vetList == null) { 25 | vetList = new ArrayList(); 26 | } 27 | return vetList; 28 | } 29 | 30 | public void setVetList(List vetList) { 31 | this.vetList = vetList; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/java/org/woehlke/javaee7/petclinic/services/JaxRsActivator.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.services; 2 | 3 | import javax.ws.rs.ApplicationPath; 4 | import javax.ws.rs.core.Application; 5 | 6 | /** 7 | * Created with IntelliJ IDEA. 8 | * User: tw 9 | * Date: 05.01.14 10 | * Time: 09:27 11 | * To change this template use File | Settings | File Templates. 12 | */ 13 | @ApplicationPath("/rest") 14 | public class JaxRsActivator extends Application { 15 | } 16 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/java/org/woehlke/javaee7/petclinic/services/OwnerService.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.services; 2 | 3 | import org.woehlke.javaee7.petclinic.entities.Visit; 4 | 5 | /** 6 | * Created by tw on 10.03.14. 7 | */ 8 | public interface OwnerService { 9 | 10 | void addNewVisit(Visit visit); 11 | } 12 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/java/org/woehlke/javaee7/petclinic/services/OwnerServiceImpl.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.services; 2 | 3 | import org.woehlke.javaee7.petclinic.dao.OwnerDao; 4 | import org.woehlke.javaee7.petclinic.dao.PetDao; 5 | import org.woehlke.javaee7.petclinic.dao.VisitDao; 6 | import org.woehlke.javaee7.petclinic.entities.Visit; 7 | 8 | import javax.ejb.EJB; 9 | import javax.ejb.Stateless; 10 | 11 | /** 12 | * Created by tw on 10.03.14. 13 | */ 14 | @Stateless 15 | public class OwnerServiceImpl implements OwnerService { 16 | 17 | @EJB 18 | private OwnerDao ownerDao; 19 | 20 | @EJB 21 | private PetDao petDao; 22 | 23 | @EJB 24 | private VisitDao visitDao; 25 | 26 | 27 | @Override 28 | public void addNewVisit(Visit visit) { 29 | visitDao.addNew(visit); 30 | petDao.update(visit.getPet()); 31 | ownerDao.update(visit.getPet().getOwner()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/java/org/woehlke/javaee7/petclinic/web/LanguageBean.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.web; 2 | 3 | 4 | import javax.faces.bean.ManagedBean; 5 | import javax.faces.bean.SessionScoped; 6 | import javax.faces.context.FacesContext; 7 | import javax.faces.event.ValueChangeEvent; 8 | import java.io.Serializable; 9 | import java.util.LinkedHashMap; 10 | import java.util.Locale; 11 | import java.util.Map; 12 | 13 | /** 14 | * Created with IntelliJ IDEA. 15 | * User: tw 16 | * Date: 14.01.14 17 | * Time: 21:14 18 | * To change this template use File | Settings | File Templates. 19 | */ 20 | @ManagedBean(name="language") 21 | @SessionScoped 22 | public class LanguageBean implements Serializable { 23 | 24 | private static final long serialVersionUID = 1L; 25 | 26 | private String localeCode = Locale.ENGLISH.toString(); 27 | 28 | private static Map countries; 29 | static{ 30 | countries = new LinkedHashMap(); 31 | countries.put("English", Locale.ENGLISH); 32 | countries.put("Deutsch", Locale.GERMAN); 33 | } 34 | 35 | public Map getCountriesInMap() { 36 | return countries; 37 | } 38 | 39 | 40 | public String getLocaleCode() { 41 | return localeCode; 42 | } 43 | 44 | 45 | public void setLocaleCode(String localeCode) { 46 | this.localeCode = localeCode; 47 | } 48 | 49 | //value change event listener 50 | public void countryLocaleCodeChanged(ValueChangeEvent e){ 51 | 52 | String newLocaleValue = e.getNewValue().toString(); 53 | 54 | //loop country map to compare the locale code 55 | for (Map.Entry entry : countries.entrySet()) { 56 | 57 | if(entry.getValue().toString().equals(newLocaleValue)){ 58 | 59 | FacesContext.getCurrentInstance() 60 | .getViewRoot().setLocale((Locale)entry.getValue()); 61 | 62 | } 63 | } 64 | } 65 | 66 | public String getMsgCantDeleteSpecialty() { 67 | String msg = ""; 68 | if(localeCode.equals(Locale.ENGLISH.toString())){ 69 | msg = "cannot delete, Specialty still in use"; 70 | } else if(localeCode.equals(Locale.GERMAN.toString())){ 71 | msg = "löschen nicht möglich, Fachrichtung wird noch ausgeübt"; 72 | } 73 | return msg; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/java/org/woehlke/javaee7/petclinic/web/SpecialtyConverter.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.web; 2 | 3 | import org.woehlke.javaee7.petclinic.entities.Specialty; 4 | 5 | import javax.el.ELContext; 6 | import javax.faces.component.UIComponent; 7 | import javax.faces.context.FacesContext; 8 | import javax.faces.convert.Converter; 9 | import javax.faces.convert.FacesConverter; 10 | 11 | /** 12 | * Created with IntelliJ IDEA. 13 | * User: tw 14 | * Date: 04.01.14 15 | * Time: 12:44 16 | * To change this template use File | Settings | File Templates. 17 | */ 18 | @FacesConverter("SpecialtyConverter") 19 | public class SpecialtyConverter implements Converter { 20 | 21 | private VetController vetController; 22 | 23 | public Object getAsObject(FacesContext facesContext, UIComponent component, String s) { 24 | for (Specialty specialty : getCapitalsParser(facesContext).getSpecialties()) { 25 | if (specialty.getName().equals(s)) { 26 | return specialty; 27 | } 28 | } 29 | return null; 30 | } 31 | 32 | public String getAsString(FacesContext facesContext, UIComponent component, Object o) { 33 | if (o == null) return null; 34 | return ((Specialty) o).getName(); 35 | } 36 | 37 | private VetController getCapitalsParser(FacesContext facesContext) { 38 | if (vetController == null) { 39 | ELContext elContext = facesContext.getELContext(); 40 | vetController = (VetController) elContext.getELResolver().getValue(elContext, null, "vetController"); 41 | } 42 | return vetController; 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/java/org/woehlke/javaee7/petclinic/web/VetSortingBean.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.web; 2 | 3 | 4 | 5 | import org.richfaces.component.SortOrder; 6 | 7 | import javax.faces.bean.ManagedBean; 8 | import javax.faces.bean.SessionScoped; 9 | import java.io.Serializable; 10 | 11 | /** 12 | * Created by tw on 13.03.14. 13 | */ 14 | @ManagedBean 15 | @SessionScoped 16 | public class VetSortingBean implements Serializable { 17 | 18 | private static final long serialVersionUID = 1L; 19 | 20 | private SortOrder sortOrderFirstName = SortOrder.unsorted; 21 | private SortOrder sortOrderLastName = SortOrder.unsorted; 22 | private SortOrder sortOrderSpecialties = SortOrder.unsorted; 23 | 24 | public void setSortOrderToFirstName() { 25 | if (SortOrder.ascending == sortOrderFirstName) { 26 | sortOrderFirstName = SortOrder.descending; 27 | } else { 28 | sortOrderFirstName = SortOrder.ascending; 29 | } 30 | sortOrderLastName = SortOrder.unsorted; 31 | sortOrderSpecialties = SortOrder.unsorted; 32 | } 33 | 34 | public void setSortOrderToLastName() { 35 | sortOrderFirstName = SortOrder.unsorted; 36 | if (SortOrder.ascending==sortOrderLastName) { 37 | sortOrderLastName = SortOrder.descending; 38 | } else { 39 | sortOrderLastName = SortOrder.ascending; 40 | } 41 | sortOrderSpecialties = SortOrder.unsorted; 42 | } 43 | 44 | public void setSortOrderToSpecialties() { 45 | sortOrderFirstName = SortOrder.unsorted; 46 | sortOrderLastName = SortOrder.unsorted; 47 | if (SortOrder.ascending==sortOrderSpecialties) { 48 | sortOrderSpecialties = SortOrder.descending; 49 | } else { 50 | sortOrderSpecialties = SortOrder.ascending; 51 | } 52 | } 53 | 54 | public SortOrder getSortOrderFirstName() { 55 | return sortOrderFirstName; 56 | } 57 | 58 | public void setSortOrderFirstName(SortOrder sortOrderFirstName) { 59 | this.sortOrderFirstName = sortOrderFirstName; 60 | } 61 | 62 | public SortOrder getSortOrderLastName() { 63 | return sortOrderLastName; 64 | } 65 | 66 | public void setSortOrderLastName(SortOrder sortOrderLastName) { 67 | this.sortOrderLastName = sortOrderLastName; 68 | } 69 | 70 | public SortOrder getSortOrderSpecialties() { 71 | return sortOrderSpecialties; 72 | } 73 | 74 | public void setSortOrderSpecialties(SortOrder sortOrderSpecialties) { 75 | this.sortOrderSpecialties = sortOrderSpecialties; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/java/org/woehlke/javaee7/petclinic/web/keycloak/KeycloakContextProvider.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.web.keycloak; 2 | 3 | import javax.enterprise.context.RequestScoped; 4 | import javax.enterprise.inject.Produces; 5 | import javax.faces.context.ExternalContext; 6 | import javax.faces.context.FacesContext; 7 | import javax.servlet.http.HttpServletRequest; 8 | 9 | import org.keycloak.KeycloakSecurityContext; 10 | import org.keycloak.adapters.RefreshableKeycloakSecurityContext; 11 | 12 | @RequestScoped 13 | public class KeycloakContextProvider { 14 | 15 | @Produces 16 | public RefreshableKeycloakSecurityContext getCurrentKeycloakSecurityContext() { 17 | return getKeycloakSecurityContext(getCurrentHttpRequest()); 18 | } 19 | 20 | private RefreshableKeycloakSecurityContext getKeycloakSecurityContext(HttpServletRequest httpRequest) { 21 | return (RefreshableKeycloakSecurityContext) httpRequest.getAttribute(KeycloakSecurityContext.class.getName()); 22 | } 23 | 24 | private HttpServletRequest getCurrentHttpRequest() { 25 | 26 | FacesContext context = FacesContext.getCurrentInstance(); 27 | ExternalContext externalContext = context.getExternalContext(); 28 | 29 | return (HttpServletRequest) externalContext.getRequest(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/java/org/woehlke/javaee7/petclinic/web/keycloak/KeycloakSsoFilter.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.web.keycloak; 2 | 3 | import org.jboss.logging.Logger; 4 | import org.keycloak.adapters.servlet.KeycloakOIDCFilter; 5 | 6 | import javax.servlet.FilterChain; 7 | import javax.servlet.ServletException; 8 | import javax.servlet.ServletRequest; 9 | import javax.servlet.ServletResponse; 10 | import javax.servlet.annotation.WebFilter; 11 | import javax.servlet.http.HttpServletRequest; 12 | import java.io.IOException; 13 | 14 | @WebFilter(value = "/*", asyncSupported = true) 15 | public class KeycloakSsoFilter extends KeycloakOIDCFilter { 16 | 17 | private static final Logger LOG = Logger.getLogger(KeycloakSsoFilter.class); 18 | 19 | @Override 20 | public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { 21 | 22 | LOG.infof("Filtering request: %s", ((HttpServletRequest) req).getRequestURI()); 23 | 24 | super.doFilter(req, res, chain); 25 | } 26 | } -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/resources/META-INF/persistence.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | org.woehlke.javaee7.petclinic.entities.Owner 10 | org.woehlke.javaee7.petclinic.entities.Pet 11 | org.woehlke.javaee7.petclinic.entities.PetType 12 | org.woehlke.javaee7.petclinic.entities.Specialty 13 | org.woehlke.javaee7.petclinic.entities.Vet 14 | org.woehlke.javaee7.petclinic.entities.Visit 15 | 16 | 17 | 18 | 19 | 21 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/resources/messages.properties: -------------------------------------------------------------------------------- 1 | name=Name 2 | edit=\u00E4ndern 3 | delete=L\u00F6schen 4 | addNewPetType=F\u00FCge neue Tierart hinzu 5 | petTypes=Tierart 6 | addNewSpecialty=F\u00FCge neue Fachrichtung hinzu 7 | specialties=Fachrichtungen 8 | veterinarians=Tier\u00E4rzte 9 | firstName=Vorname 10 | lastName=Nachname 11 | addNewVeterinarian=F\u00FCge neuen Tierarzt hinzu 12 | showXml=Zeige als XML 13 | showAtom=Abonniere Atom Feed 14 | findOwners=Finde Besitzer 15 | addNewOwner=F\u00FCge neuen Besitzer hinzu 16 | home=Start 17 | welcome=Willkommen 18 | welcome_a=Erste Schritte: 19 | welcome_a_a=f\u00FCge neue Tierarten hinzu wie Hund, Katze, Maus,... 20 | welcome_a_b=f\u00FCge neue Fachrichtung f\u00FCr Tier\u00E4rzte hinzu wie Zahnarzt, R\u00F6ntgen, Chirurgie,... 21 | welcome_a_c=f\u00FCge neue Tier\u00E4rzte hinzu 22 | welcome_a_d=f\u00FCge neue Besitzer hinzu, gib ihre Haustiere ein, und f\u00FCge den Haustieren ihre Besuche hinzu 23 | welcome_b=Quellcode: 24 | welcome_b_b=Projekt Seite: 25 | save=Speichern 26 | availableSpecialties=Verf\u00FCgbare Fachrichtungen 27 | selectedSpecialties=Gew\u00E4hlte Fachrichtungen 28 | editSpecialty=Fachrichtung \u00E4ndern 29 | editPetType=Tierart \u00E4ndern 30 | owners=Besitzer 31 | address=Adresse 32 | city=Stadt 33 | telephone=Telefon 34 | editOwner=Besitzer \u00E4ndern 35 | owner=Besitzer 36 | petsAndVisits=Tiere und Besuche 37 | birthdate=Geburtsdatum 38 | petType=Tierart 39 | date=Datum 40 | description=Beschreibung 41 | editPet=Tier \u00E4ndern 42 | addVisit=Besuch hinzuf\u00FCgen 43 | previousVisits=Fr\u00FChere Besuche 44 | pet=Tier 45 | addNewPet=Neues Tier hinzuf\u00FCgen 46 | search=Suche 47 | language=Sprache 48 | 49 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/resources/messages_de.properties: -------------------------------------------------------------------------------- 1 | name=Name 2 | edit=\u00E4ndern 3 | delete=L\u00F6schen 4 | addNewPetType=F\u00FCge neue Tierart hinzu 5 | petTypes=Tierart 6 | addNewSpecialty=F\u00FCge neue Fachrichtung hinzu 7 | specialties=Fachrichtungen 8 | veterinarians=Tier\u00E4rzte 9 | firstName=Vorname 10 | lastName=Nachname 11 | addNewVeterinarian=F\u00FCge neuen Tierarzt hinzu 12 | showXml=Zeige als XML 13 | showAtom=Abonniere Atom Feed 14 | findOwners=Finde Besitzer 15 | addNewOwner=F\u00FCge neuen Besitzer hinzu 16 | home=Start 17 | welcome=Willkommen 18 | welcome_a=Erste Schritte: 19 | welcome_a_a=f\u00FCge neue Tierarten hinzu wie Hund, Katze, Maus,... 20 | welcome_a_b=f\u00FCge neue Fachrichtung f\u00FCr Tier\u00E4rzte hinzu wie Zahnarzt, R\u00F6ntgen, Chirurgie,... 21 | welcome_a_c=f\u00FCge neue Tier\u00E4rzte hinzu 22 | welcome_a_d=f\u00FCge neue Besitzer hinzu, gib ihre Haustiere ein, und f\u00FCge den Haustieren ihre Besuche hinzu 23 | welcome_b=Quellcode: 24 | welcome_b_b=Projekt Seite: 25 | save=Speichern 26 | availableSpecialties=Verf\u00FCgbare Fachrichtungen 27 | selectedSpecialties=Gew\u00E4hlte Fachrichtungen 28 | editSpecialty=Fachrichtung \u00E4ndern 29 | editPetType=Tierart \u00E4ndern 30 | owners=Besitzer 31 | address=Adresse 32 | city=Stadt 33 | telephone=Telefon 34 | editOwner=Besitzer \u00E4ndern 35 | owner=Besitzer 36 | petsAndVisits=Tiere und Besuche 37 | birthdate=Geburtsdatum 38 | petType=Tierart 39 | date=Datum 40 | description=Beschreibung 41 | editPet=Tier \u00E4ndern 42 | addVisit=Besuch hinzuf\u00FCgen 43 | previousVisits=Fr\u00FChere Besuche 44 | pet=Tier 45 | addNewPet=Neues Tier hinzuf\u00FCgen 46 | search=Suche 47 | language=Sprache 48 | 49 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/resources/messages_en.properties: -------------------------------------------------------------------------------- 1 | name=Name 2 | edit=Edit 3 | delete=Delete 4 | addNewPetType=Add New Pet Type 5 | petTypes=Pet Types 6 | addNewSpecialty=Add New Specialty 7 | specialties=Specialties 8 | veterinarians=Veterinarians 9 | firstName=First Name 10 | lastName=Last Name 11 | addNewVeterinarian=Add New Veterinarian 12 | showXml=View as XML 13 | showAtom=Subscribe to Atom feed 14 | findOwners=Find Owners 15 | addNewOwner=Add New Owner 16 | home=Home 17 | welcome=Welcome 18 | welcome_a=First Steps: 19 | welcome_a_a=add some Pet Types like dog,cat,mouse,... 20 | welcome_a_b=add some Specialties for Vetinarians like dentist, anesthetist, radiology,... 21 | welcome_a_c=add a Vetinarian 22 | welcome_a_d=add an Owner, add him am a Pet and his Pet a visit. 23 | welcome_b=Source Code: 24 | welcome_b_b=Project Page: 25 | save=Save 26 | availableSpecialties=Available specialties 27 | selectedSpecialties=Selected specialties 28 | editSpecialty=Edit Specialty 29 | editPetType=Edit Pet Type 30 | owners=Owners 31 | address=Address 32 | city=City 33 | telephone=Telephone 34 | editOwner=Edit Owner 35 | owner=Owner 36 | petsAndVisits=Pets and Visits 37 | birthdate=Birthdate 38 | petType=Pet Type 39 | date=Date 40 | description=Description 41 | editPet=Edit Pet 42 | addVisit=Add Visit 43 | previousVisits=Previous Visits 44 | pet=Pet 45 | addNewPet=Add new Pet 46 | search=Search 47 | language=Language 48 | 49 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/webapp/WEB-INF/faces-config.xml: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/webapp/WEB-INF/jboss-deployment-structure.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/webapp/WEB-INF/jboss-web.xml: -------------------------------------------------------------------------------- 1 | 2 | / 3 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/webapp/WEB-INF/keycloak.json: -------------------------------------------------------------------------------- 1 | { 2 | "realm": "acme", 3 | "auth-server-url": "http://sso.tdlabs.local:8899/u/auth", 4 | "ssl-required": "external", 5 | "resource": "app-javaee-petclinic", 6 | "credentials": { 7 | "secret": "e08169c8-0dea-4a75-83a4-f9e9e9bfb961" 8 | }, 9 | "use-resource-role-mappings": true 10 | } -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/webapp/addNewPet.xhtml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 |

#{msg.addNewPet}

11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |   22 | 24 | 25 | 26 | 28 | 29 | 30 | 32 | 33 | 34 | 35 | 37 | 38 | 40 | 41 | 42 | 43 | 44 |
45 | 46 |
-------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/webapp/editOwner.xhtml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 |

#{msg.editOwner}

11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 20 | 21 | 23 | 24 | 26 | 27 | 29 | 30 | 32 | 33 | 34 | 36 | 37 |
38 | 39 |
-------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/webapp/editPet.xhtml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 |

#{msg.editPet}

11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |   22 | 24 | 25 | 26 | 28 | 29 | 30 | 32 | 33 | 34 | 35 | 37 | 38 | 40 | 41 | 42 | 43 | 44 |
45 | 46 |
-------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/webapp/editPetType.xhtml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 |

#{msg.editPetType}

11 | 12 | 13 | 14 | 15 | 16 | 17 | 19 | 20 | 22 | 23 |
24 | 25 |
-------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/webapp/editSpecialty.xhtml: -------------------------------------------------------------------------------- 1 | > 8 | 9 | 10 | 11 |

#{msg.editSpecialty}

12 | 13 | 14 | 15 | 16 | 17 | 18 | 20 | 21 | 23 | 24 |
25 | 26 |
-------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/webapp/editVet.xhtml: -------------------------------------------------------------------------------- 1 | > 8 | 9 | 10 |

Edit Veterinarian

11 | 12 | 13 | 14 | 15 | 16 | 17 | 19 | 20 | 22 | 23 | 25 | 26 | 30 | 32 | 33 | 34 | 35 | 36 |
37 | 38 |
-------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/webapp/findOwners.xhtml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 |

#{msg.findOwners}

11 | 12 | 13 | 14 | 15 | 16 | 17 | #{msg.addNewOwner} 18 | 19 | 20 |
21 | 22 |
-------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/webapp/hello.xhtml: -------------------------------------------------------------------------------- 1 | 2 | > 9 | 10 | 11 |

#{msg.welcome}

12 |

#{msg.welcome_a}

13 |
    14 |
  • #{msg.welcome_a_a}
  • 15 |
  • #{msg.welcome_a_b}
  • 16 |
  • #{msg.welcome_a_c}
  • 17 |
  • #{msg.welcome_a_d}
  • 18 |
19 |

#{msg.welcome_b}

20 | 25 |
26 | 27 |
-------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/webapp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/webapp/newOwner.xhtml: -------------------------------------------------------------------------------- 1 | > 8 | 9 | 10 |

#{msg.addNewOwner}

11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 20 | 21 | 23 | 24 | 26 | 27 | 29 | 30 | 32 | 33 | 34 | 36 | 37 |
38 | 39 |
-------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/webapp/newPetType.xhtml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 |

#{msg.addNewPetType}

11 | 12 | 13 | 14 | 15 | 16 | 17 | 19 | 20 | 22 | 23 |
24 | 25 |
-------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/webapp/newSpecialty.xhtml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 |

#{msg.addNewSpecialty}

11 | 12 | 13 | 14 | 15 | 16 | 17 | 19 | 20 | 22 | 23 | 24 |
25 | 26 |
-------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/webapp/newVet.xhtml: -------------------------------------------------------------------------------- 1 | > 8 | 9 | 10 |

#{msg.addNewVeterinarian}

11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 20 | 21 | 23 | 24 | 25 | 29 | 31 | 32 | 33 | 34 | 36 | 37 |
38 | 39 |
-------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/main/webapp/petTypes.xhtml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 |

#{msg.petTypes}

11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
35 |
36 | 37 |
38 |
39 | 40 |
-------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/site/resources/images/DomainClassModell.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdarimont/springio18-spring-keycloak/c0b78658e2c74e934615fa18058e10d9b6eee4ca/demos/javaee7-petclinic/src/site/resources/images/DomainClassModell.jpg -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/site/resources/images/Pageflow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdarimont/springio18-spring-keycloak/c0b78658e2c74e934615fa18058e10d9b6eee4ca/demos/javaee7-petclinic/src/site/resources/images/Pageflow.jpg -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/site/resources/images/UseCases.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdarimont/springio18-spring-keycloak/c0b78658e2c74e934615fa18058e10d9b6eee4ca/demos/javaee7-petclinic/src/site/resources/images/UseCases.jpg -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/site/resources/images/UseCasesOwner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdarimont/springio18-spring-keycloak/c0b78658e2c74e934615fa18058e10d9b6eee4ca/demos/javaee7-petclinic/src/site/resources/images/UseCasesOwner.jpg -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/site/resources/images/phasenraum_logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdarimont/springio18-spring-keycloak/c0b78658e2c74e934615fa18058e10d9b6eee4ca/demos/javaee7-petclinic/src/site/resources/images/phasenraum_logo.gif -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/site/resources/images/screenAddVet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdarimont/springio18-spring-keycloak/c0b78658e2c74e934615fa18058e10d9b6eee4ca/demos/javaee7-petclinic/src/site/resources/images/screenAddVet.png -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/site/resources/images/screenNewVisit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdarimont/springio18-spring-keycloak/c0b78658e2c74e934615fa18058e10d9b6eee4ca/demos/javaee7-petclinic/src/site/resources/images/screenNewVisit.png -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/site/resources/images/screenOwner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdarimont/springio18-spring-keycloak/c0b78658e2c74e934615fa18058e10d9b6eee4ca/demos/javaee7-petclinic/src/site/resources/images/screenOwner.png -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/test/java/org/woehlke/javaee7/petclinic/web/pages/EditOwnerPage.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.web.pages; 2 | 3 | import org.jboss.arquillian.graphene.Graphene; 4 | import org.junit.Assert; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | 8 | /** 9 | * Created with IntelliJ IDEA. 10 | * User: tw 11 | * Date: 27.01.14 12 | * Time: 09:27 13 | * To change this template use File | Settings | File Templates. 14 | */ 15 | public class EditOwnerPage { 16 | 17 | @FindBy(id="editOwnerForm") 18 | private WebElement editOwnerForm; 19 | 20 | @FindBy(id="editOwnerForm:firstName") 21 | private WebElement firstName; 22 | 23 | @FindBy(id="editOwnerForm:lastName") 24 | private WebElement lastName; 25 | 26 | @FindBy(id="editOwnerForm:address") 27 | private WebElement address; 28 | 29 | @FindBy(id="editOwnerForm:city") 30 | private WebElement city; 31 | 32 | @FindBy(id="editOwnerForm:telephone") 33 | private WebElement telephone; 34 | 35 | @FindBy(id="editOwnerForm:save") 36 | private WebElement save; 37 | 38 | public void assertPageIsLoaded() { 39 | Graphene.waitModel().until().element(editOwnerForm).is().visible(); 40 | Assert.assertTrue(editOwnerForm.isDisplayed()); 41 | } 42 | 43 | public void editContent(String firstName, 44 | String lastName, 45 | String address, 46 | String city, 47 | String telephone) { 48 | this.firstName.clear(); 49 | this.lastName.clear(); 50 | this.address.clear(); 51 | this.city.clear(); 52 | this.telephone.clear(); 53 | this.firstName.sendKeys(firstName); 54 | this.lastName.sendKeys(lastName); 55 | this.address.sendKeys(address); 56 | this.city.sendKeys(city); 57 | this.telephone.sendKeys(telephone); 58 | Graphene.guardHttp(this.save).click(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/test/java/org/woehlke/javaee7/petclinic/web/pages/EditPetPage.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.web.pages; 2 | 3 | import org.joda.time.DateTime; 4 | import org.junit.Assert; 5 | import org.openqa.selenium.By; 6 | import org.openqa.selenium.WebElement; 7 | import org.openqa.selenium.support.FindBy; 8 | import org.richfaces.fragment.calendar.RichFacesCalendar; 9 | 10 | import java.util.Date; 11 | import java.util.List; 12 | 13 | /** 14 | * Created with IntelliJ IDEA. 15 | * User: tw 16 | * Date: 27.01.14 17 | * Time: 19:58 18 | * To change this template use File | Settings | File Templates. 19 | */ 20 | public class EditPetPage { 21 | 22 | @FindBy(id="editPetForm") 23 | private WebElement editPetForm; 24 | 25 | @FindBy(id="editPetForm:petName") 26 | private WebElement petName; 27 | 28 | @FindBy(id="editPetForm:petBirthDate") 29 | private RichFacesCalendar petBirthDate; 30 | 31 | @FindBy(id="editPetForm:petType") 32 | private WebElement petType; 33 | 34 | @FindBy(id="editPetForm:save") 35 | private WebElement save; 36 | 37 | public void assertPageIsLoaded() { 38 | Assert.assertTrue(editPetForm.isDisplayed()); 39 | } 40 | 41 | public void setContent(String petName, Date petBirthDate, String petType) { 42 | this.petName.clear(); 43 | this.petName.sendKeys(petName); 44 | DateTime dateTime = new DateTime(petBirthDate.getTime()); 45 | this.petBirthDate.setDate(dateTime); 46 | List options = this.petType.findElements(By.tagName("option")); 47 | for(WebElement option: options){ 48 | if(option.getText().contentEquals(petType)){ 49 | option.click(); 50 | break; 51 | } 52 | } 53 | save.click(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/test/java/org/woehlke/javaee7/petclinic/web/pages/EditPetTypePage.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.web.pages; 2 | 3 | import org.junit.Assert; 4 | import org.openqa.selenium.WebElement; 5 | import org.openqa.selenium.support.FindBy; 6 | 7 | /** 8 | * Created with IntelliJ IDEA. 9 | * User: tw 10 | * Date: 26.01.14 11 | * Time: 18:56 12 | * To change this template use File | Settings | File Templates. 13 | */ 14 | public class EditPetTypePage { 15 | 16 | @FindBy(id="editPetType") 17 | private WebElement editPetType; 18 | 19 | @FindBy(id="editPetTypeForm:name") 20 | private WebElement name; 21 | 22 | @FindBy(id="editPetTypeForm:save") 23 | private WebElement save; 24 | 25 | 26 | public void assertPageIsLoaded() { 27 | Assert.assertTrue(editPetType.isDisplayed()); 28 | } 29 | 30 | public void editContent(String content) { 31 | name.clear(); 32 | name.sendKeys(content); 33 | save.click(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/test/java/org/woehlke/javaee7/petclinic/web/pages/EditSpecialtiesPage.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.web.pages; 2 | 3 | import org.junit.Assert; 4 | import org.openqa.selenium.WebElement; 5 | import org.openqa.selenium.support.FindBy; 6 | 7 | /** 8 | * Created with IntelliJ IDEA. 9 | * User: tw 10 | * Date: 26.01.14 11 | * Time: 18:14 12 | * To change this template use File | Settings | File Templates. 13 | */ 14 | public class EditSpecialtiesPage { 15 | 16 | @FindBy(id="editSpecialty") 17 | private WebElement editSpecialty; 18 | 19 | @FindBy(id="editSpecialtyForm:name") 20 | private WebElement name; 21 | 22 | @FindBy(id="editSpecialtyForm:save") 23 | private WebElement save; 24 | 25 | public void assertPageIsLoaded() { 26 | Assert.assertTrue(editSpecialty.isDisplayed()); 27 | } 28 | 29 | public void editContent(String content) { 30 | name.clear(); 31 | name.sendKeys(content); 32 | save.click(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/test/java/org/woehlke/javaee7/petclinic/web/pages/EditVetPage.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.web.pages; 2 | 3 | import org.junit.Assert; 4 | import org.openqa.selenium.WebElement; 5 | import org.openqa.selenium.support.FindBy; 6 | import org.richfaces.fragment.pickList.RichFacesPickList; 7 | 8 | /** 9 | * Created with IntelliJ IDEA. 10 | * User: tw 11 | * Date: 26.01.14 12 | * Time: 21:18 13 | * To change this template use File | Settings | File Templates. 14 | */ 15 | public class EditVetPage { 16 | 17 | @FindBy(id="editVeterinarian") 18 | private WebElement editVeterinarian; 19 | 20 | @FindBy(id="editVeterinarianForm:firstName") 21 | private WebElement firstName; 22 | 23 | @FindBy(id="editVeterinarianForm:lastName") 24 | private WebElement lastName; 25 | 26 | @FindBy(id="editVeterinarianForm:selectedSpecialtiesPickList") 27 | private RichFacesPickList pickList; 28 | 29 | @FindBy(id="editVeterinarianForm:save") 30 | private WebElement save; 31 | 32 | public void assertPageIsLoaded() { 33 | Assert.assertTrue(editVeterinarian.isDisplayed()); 34 | } 35 | 36 | public void editContent(String firstName,String lastName) { 37 | this.firstName.clear(); 38 | this.firstName.sendKeys(firstName); 39 | this.lastName.clear(); 40 | this.lastName.sendKeys(lastName); 41 | save.click(); 42 | } 43 | 44 | public void editContentWithNoneSpecialties(String firstName,String lastName) { 45 | this.firstName.clear(); 46 | this.firstName.sendKeys(firstName); 47 | this.lastName.clear(); 48 | this.lastName.sendKeys(lastName); 49 | this.pickList.removeAll(); 50 | save.click(); 51 | } 52 | 53 | public void editContentWithAllSpecialties(String firstName,String lastName) { 54 | this.firstName.clear(); 55 | this.firstName.sendKeys(firstName); 56 | this.lastName.clear(); 57 | this.lastName.sendKeys(lastName); 58 | this.pickList.addAll(); 59 | save.click(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/test/java/org/woehlke/javaee7/petclinic/web/pages/FindOwnersPage.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.web.pages; 2 | 3 | import org.jboss.arquillian.graphene.Graphene; 4 | import org.jboss.arquillian.graphene.page.Location; 5 | import org.junit.Assert; 6 | import org.openqa.selenium.WebElement; 7 | import org.openqa.selenium.support.FindBy; 8 | 9 | /** 10 | * Created with IntelliJ IDEA. 11 | * User: tw 12 | * Date: 26.01.14 13 | * Time: 22:12 14 | * To change this template use File | Settings | File Templates. 15 | */ 16 | @Location("findOwners.jsf") 17 | public class FindOwnersPage { 18 | 19 | @FindBy(id="findOwners") 20 | private WebElement findOwners; 21 | 22 | @FindBy(id="findOwnersForm:search") 23 | private WebElement search; 24 | 25 | @FindBy(id="findOwnersForm:getNewOwnerForm") 26 | private WebElement getNewOwnerForm; 27 | 28 | public void assertPageIsLoaded() { 29 | Graphene.waitModel().until().element(findOwners).is().visible(); 30 | Assert.assertTrue(findOwners.isDisplayed()); 31 | } 32 | 33 | public void clickSearch() { 34 | Graphene.guardHttp(search).click(); 35 | } 36 | 37 | public void clickNewOwner() { 38 | Graphene.guardHttp(getNewOwnerForm).click(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/test/java/org/woehlke/javaee7/petclinic/web/pages/HelloPage.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.web.pages; 2 | 3 | import org.jboss.arquillian.drone.api.annotation.Drone; 4 | import org.jboss.arquillian.graphene.page.Location; 5 | import org.junit.Assert; 6 | import org.openqa.selenium.WebDriver; 7 | 8 | /** 9 | * Created with IntelliJ IDEA. 10 | * User: tw 11 | * Date: 26.01.14 12 | * Time: 17:05 13 | * To change this template use File | Settings | File Templates. 14 | */ 15 | @Location("hello.jsf") 16 | public class HelloPage { 17 | 18 | @Drone 19 | private WebDriver driver; 20 | 21 | public void assertTitle(){ 22 | Assert.assertEquals("Java EE 7 Petclinic",driver.getTitle()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/test/java/org/woehlke/javaee7/petclinic/web/pages/NewOwnerPage.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.web.pages; 2 | 3 | import org.jboss.arquillian.graphene.Graphene; 4 | import org.junit.Assert; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | 8 | /** 9 | * Created with IntelliJ IDEA. 10 | * User: tw 11 | * Date: 26.01.14 12 | * Time: 22:48 13 | * To change this template use File | Settings | File Templates. 14 | */ 15 | public class NewOwnerPage { 16 | 17 | @FindBy(id="addNewOwner") 18 | private WebElement addNewOwner; 19 | 20 | @FindBy(id="addNewOwnerForm:firstName") 21 | private WebElement firstName; 22 | 23 | @FindBy(id="addNewOwnerForm:lastName") 24 | private WebElement lastName; 25 | 26 | @FindBy(id="addNewOwnerForm:address") 27 | private WebElement address; 28 | 29 | @FindBy(id="addNewOwnerForm:city") 30 | private WebElement city; 31 | 32 | @FindBy(id="addNewOwnerForm:telephone") 33 | private WebElement telephone; 34 | 35 | @FindBy(id="addNewOwnerForm:save") 36 | private WebElement save; 37 | 38 | public void assertPageIsLoaded() { 39 | Graphene.waitModel().until().element(addNewOwner).is().visible(); 40 | Assert.assertTrue(addNewOwner.isDisplayed()); 41 | } 42 | 43 | public void addNewContent(String firstName, 44 | String lastName, 45 | String address, 46 | String city, 47 | String telephone) { 48 | this.firstName.sendKeys(firstName); 49 | this.lastName.sendKeys(lastName); 50 | this.address.sendKeys(address); 51 | this.city.sendKeys(city); 52 | this.telephone.sendKeys(telephone); 53 | Graphene.guardHttp(this.save).click(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/test/java/org/woehlke/javaee7/petclinic/web/pages/NewPetPage.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.web.pages; 2 | 3 | import org.jboss.arquillian.graphene.Graphene; 4 | import org.joda.time.DateTime; 5 | import org.junit.Assert; 6 | import org.openqa.selenium.By; 7 | import org.openqa.selenium.WebElement; 8 | import org.openqa.selenium.support.FindBy; 9 | import org.richfaces.fragment.calendar.RichFacesCalendar; 10 | 11 | import java.util.Date; 12 | import java.util.List; 13 | 14 | /** 15 | * Created with IntelliJ IDEA. 16 | * User: tw 17 | * Date: 27.01.14 18 | * Time: 16:49 19 | * To change this template use File | Settings | File Templates. 20 | */ 21 | public class NewPetPage { 22 | 23 | @FindBy(id="addNewPetForm") 24 | private WebElement addNewPetForm; 25 | 26 | @FindBy(id="addNewPetForm:petName") 27 | private WebElement petName; 28 | 29 | @FindBy(id="addNewPetForm:petBirthDate") 30 | private RichFacesCalendar petBirthDate; 31 | 32 | @FindBy(id="addNewPetForm:petType") 33 | private WebElement petType; 34 | 35 | @FindBy(id="addNewPetForm:add") 36 | private WebElement add; 37 | 38 | public void assertPageIsLoaded() { 39 | Graphene.waitModel().until().element(addNewPetForm).is().visible(); 40 | Assert.assertTrue(addNewPetForm.isDisplayed()); 41 | } 42 | 43 | public void setContent(String petName, Date petBirthDate, String petType){ 44 | this.petName.sendKeys(petName); 45 | DateTime dateTime = new DateTime(petBirthDate.getTime()); 46 | this.petBirthDate.setDate(dateTime); 47 | List options = this.petType.findElements(By.tagName("option")); 48 | for(WebElement option: options){ 49 | if(option.getText().contentEquals(petType)){ 50 | option.click(); 51 | break; 52 | } 53 | } 54 | Graphene.guardHttp(add).click(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/test/java/org/woehlke/javaee7/petclinic/web/pages/NewPetTypePage.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.web.pages; 2 | 3 | import org.jboss.arquillian.graphene.Graphene; 4 | import org.junit.Assert; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | 8 | /** 9 | * Created with IntelliJ IDEA. 10 | * User: tw 11 | * Date: 26.01.14 12 | * Time: 18:56 13 | * To change this template use File | Settings | File Templates. 14 | */ 15 | public class NewPetTypePage { 16 | 17 | @FindBy(id="addNewPetType") 18 | private WebElement addNewPetType; 19 | 20 | @FindBy(id="addNewPetTypeForm:name") 21 | private WebElement name; 22 | 23 | @FindBy(id="addNewPetTypeForm:save") 24 | private WebElement save; 25 | 26 | public void assertPageIsLoaded() { 27 | Graphene.waitModel().until().element(addNewPetType).is().visible(); 28 | Assert.assertTrue(addNewPetType.isDisplayed()); 29 | } 30 | 31 | public void addNewContent(String content) { 32 | name.clear(); 33 | name.sendKeys(content); 34 | Graphene.guardHttp(save).click(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/test/java/org/woehlke/javaee7/petclinic/web/pages/NewSpecialtiesPage.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.web.pages; 2 | 3 | import org.junit.Assert; 4 | import org.openqa.selenium.WebElement; 5 | import org.openqa.selenium.support.FindBy; 6 | 7 | /** 8 | * Created with IntelliJ IDEA. 9 | * User: tw 10 | * Date: 26.01.14 11 | * Time: 17:46 12 | * To change this template use File | Settings | File Templates. 13 | */ 14 | public class NewSpecialtiesPage { 15 | 16 | @FindBy(id="addNewSpecialty") 17 | private WebElement addNewSpecialty; 18 | 19 | @FindBy(id="addNewSpecialtyForm:name") 20 | private WebElement name; 21 | 22 | @FindBy(id="addNewSpecialtyForm:save") 23 | private WebElement save; 24 | 25 | public void assertPageIsLoaded(){ 26 | Assert.assertTrue(addNewSpecialty.isDisplayed()); 27 | } 28 | 29 | public void addNewContent(String content) { 30 | name.clear(); 31 | name.sendKeys(content); 32 | save.click(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/test/java/org/woehlke/javaee7/petclinic/web/pages/NewVetPage.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.web.pages; 2 | 3 | import org.junit.Assert; 4 | import org.openqa.selenium.WebElement; 5 | import org.openqa.selenium.support.FindBy; 6 | import org.richfaces.fragment.pickList.RichFacesPickList; 7 | 8 | /** 9 | * Created with IntelliJ IDEA. 10 | * User: tw 11 | * Date: 26.01.14 12 | * Time: 20:51 13 | * To change this template use File | Settings | File Templates. 14 | */ 15 | public class NewVetPage { 16 | 17 | @FindBy(id="addNewVeterinarian") 18 | private WebElement addNewVeterinarian; 19 | 20 | @FindBy(id="addNewVeterinarianForm:firstName") 21 | private WebElement firstName; 22 | 23 | @FindBy(id="addNewVeterinarianForm:lastName") 24 | private WebElement lastName; 25 | 26 | @FindBy(id="addNewVeterinarianForm:save") 27 | private WebElement save; 28 | 29 | @FindBy(id="addNewVeterinarianForm:selectedSpecialtiesPickList") 30 | private RichFacesPickList pickList; 31 | 32 | public void assertPageIsLoaded() { 33 | Assert.assertTrue(addNewVeterinarian.isDisplayed()); 34 | } 35 | 36 | public void addNewContent(String firstName,String lastName) { 37 | this.firstName.clear(); 38 | this.firstName.sendKeys(firstName); 39 | this.lastName.clear(); 40 | this.lastName.sendKeys(lastName); 41 | save.click(); 42 | } 43 | 44 | public void addNewContentWithAllSpecialties(String firstName, String lastName) { 45 | this.firstName.clear(); 46 | this.firstName.sendKeys(firstName); 47 | this.lastName.clear(); 48 | this.lastName.sendKeys(lastName); 49 | this.pickList.addAll(); 50 | save.click(); 51 | } 52 | 53 | public void addNewContentWithOneSpecialty(String firstName, String lastName, String specialty) { 54 | this.firstName.clear(); 55 | this.firstName.sendKeys(firstName); 56 | this.lastName.clear(); 57 | this.lastName.sendKeys(lastName); 58 | this.pickList.add(specialty); 59 | save.click(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/test/java/org/woehlke/javaee7/petclinic/web/pages/NewVisitPage.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.web.pages; 2 | 3 | import org.jboss.arquillian.graphene.Graphene; 4 | import org.joda.time.DateTime; 5 | import org.junit.Assert; 6 | import org.openqa.selenium.WebElement; 7 | import org.openqa.selenium.support.FindBy; 8 | import org.richfaces.fragment.calendar.RichFacesCalendar; 9 | 10 | import java.text.DateFormat; 11 | import java.util.Date; 12 | import java.util.Locale; 13 | 14 | /** 15 | * Created with IntelliJ IDEA. 16 | * User: tw 17 | * Date: 28.01.14 18 | * Time: 13:40 19 | * To change this template use File | Settings | File Templates. 20 | */ 21 | public class NewVisitPage { 22 | 23 | @FindBy(id="addVisitForm") 24 | private WebElement addVisitForm; 25 | 26 | @FindBy(id="addVisitForm:petName") 27 | private WebElement petName; 28 | 29 | @FindBy(id="addVisitForm:petBirthDate") 30 | private WebElement petBirthDate; 31 | 32 | @FindBy(id="addVisitForm:petType") 33 | private WebElement petType; 34 | 35 | @FindBy(id="addVisitForm:ownerFirstName") 36 | private WebElement ownerFirstName; 37 | 38 | @FindBy(id="addVisitForm:ownerLastName") 39 | private WebElement ownerLastName; 40 | 41 | @FindBy(id="addVisitForm:visitDate") 42 | private RichFacesCalendar visitDate; 43 | 44 | @FindBy(id="addVisitForm:visitDescription") 45 | private WebElement visitDescription; 46 | 47 | @FindBy(id="addVisitForm:save") 48 | private WebElement save; 49 | 50 | public void assertPageIsLoaded() { 51 | Assert.assertTrue(addVisitForm.isDisplayed()); 52 | } 53 | 54 | public void assertOwnerContent(String firstName, String lastName) { 55 | Assert.assertEquals(firstName,ownerFirstName.getText()); 56 | Assert.assertEquals(lastName,ownerLastName.getText()); 57 | } 58 | 59 | public void assertPetContent(String petName, Date birthDate, String petType) { 60 | Assert.assertEquals(petName,this.petName.getText()); 61 | Assert.assertEquals(petType,this.petType.getText()); 62 | Date birthDateTmp = new DateTime(birthDate.getTime()).minusDays(1).toDate(); 63 | Assert.assertEquals(DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.ENGLISH).format(birthDateTmp),petBirthDate.getText()); 64 | } 65 | 66 | public void setNewContent(Date visitDate, String description) { 67 | DateTime dateTime = new DateTime(visitDate.getTime()); 68 | Graphene.waitModel().until().element(addVisitForm).is().visible(); 69 | this.visitDescription.sendKeys(description); 70 | this.visitDate.setDate(dateTime); 71 | Graphene.guardHttp(save).click(); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/test/java/org/woehlke/javaee7/petclinic/web/pages/OwnersPage.java: -------------------------------------------------------------------------------- 1 | package org.woehlke.javaee7.petclinic.web.pages; 2 | 3 | import org.jboss.arquillian.graphene.Graphene; 4 | import org.junit.Assert; 5 | import org.openqa.selenium.WebElement; 6 | import org.openqa.selenium.support.FindBy; 7 | 8 | /** 9 | * Created with IntelliJ IDEA. 10 | * User: tw 11 | * Date: 26.01.14 12 | * Time: 22:24 13 | * To change this template use File | Settings | File Templates. 14 | */ 15 | public class OwnersPage { 16 | 17 | @FindBy(id="owners") 18 | private WebElement owners; 19 | 20 | @FindBy(id="ownersForm:getNewOwnerForm") 21 | private WebElement getNewOwnerForm; 22 | 23 | @FindBy(id="ownersForm:ownersTable:0:firstName") 24 | private WebElement firstName; 25 | 26 | @FindBy(id="ownersForm:ownersTable:0:lastName") 27 | private WebElement lastName; 28 | 29 | @FindBy(id="ownersForm:ownersTable:0:address") 30 | private WebElement address; 31 | 32 | @FindBy(id="ownersForm:ownersTable:0:city") 33 | private WebElement city; 34 | 35 | @FindBy(id="ownersForm:ownersTable:0:telephone") 36 | private WebElement telephone; 37 | 38 | @FindBy(id="ownersForm:ownersTable:0:showOwner") 39 | private WebElement showOwner; 40 | 41 | public void assertPageIsLoaded() { 42 | Graphene.waitModel().until().element(owners).is().visible(); 43 | Assert.assertTrue(owners.isDisplayed()); 44 | } 45 | 46 | public void clickNewOwner() { 47 | Graphene.guardHttp(getNewOwnerForm).click(); 48 | } 49 | 50 | public void assertNewContentFound(String firstName, 51 | String lastName, 52 | String address, 53 | String city, 54 | String telephone) { 55 | Assert.assertEquals(firstName,this.firstName.getText()); 56 | Assert.assertEquals(lastName,this.lastName.getText()); 57 | Assert.assertEquals(address,this.address.getText()); 58 | Assert.assertEquals(city,this.city.getText()); 59 | Assert.assertEquals(telephone,this.telephone.getText()); 60 | Assert.assertTrue(showOwner.isDisplayed()); 61 | } 62 | 63 | public void clickShowOwner() { 64 | Graphene.guardHttp(showOwner).click(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/test/resources/WEB-INF/beans.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdarimont/springio18-spring-keycloak/c0b78658e2c74e934615fa18058e10d9b6eee4ca/demos/javaee7-petclinic/src/test/resources/WEB-INF/beans.xml -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/test/resources/arquillian.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | firefox 8 | 9 | 10 | 11 | 120 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /demos/javaee7-petclinic/src/test/resources/log4j.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /demos/keycloak-admin-cli/admin-cli.md: -------------------------------------------------------------------------------- 1 | # Keycloak Admin CLI 2 | 3 | See: http://blog.keycloak.org/2017/01/administer-keycloak-server-from-shell.html 4 | 5 | ## Enter Keycloak docker container 6 | ``` 7 | docker exec -it idmsystem_idm-keycloak_1 /bin/bash 8 | ``` 9 | 10 | ## cd into Keycloak Directory 11 | ``` 12 | cd keycloak 13 | ``` 14 | 15 | ## Configure Keycloak credentials 16 | ``` 17 | bin/kcadm.sh config credentials \ 18 | # --server http://localhost:8080/auth \ 19 | --server http://172.20.0.7:8080/u/auth \ 20 | --realm master \ 21 | --user admin 22 | ``` 23 | 24 | ## Create new user 25 | ``` 26 | KC_USER_ID=$(\ 27 | bin/kcadm.sh create users \ 28 | -r javaland \ 29 | -s username=cli \ 30 | -i) 31 | 32 | echo $KC_USER_ID 33 | ``` 34 | 35 | ## List last events 36 | ``` 37 | bin/kcadm.sh get events --offset 0 --limit 100 38 | ``` -------------------------------------------------------------------------------- /demos/keycloak-javafx-client-demo/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /demos/keycloak-javafx-client-demo/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdarimont/springio18-spring-keycloak/c0b78658e2c74e934615fa18058e10d9b6eee4ca/demos/keycloak-javafx-client-demo/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /demos/keycloak-javafx-client-demo/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.9/apache-maven-3.3.9-bin.zip 2 | -------------------------------------------------------------------------------- /demos/keycloak-javafx-client-demo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | de.tdlabs.demo 7 | keycloak-javafx-client-demo 8 | 0.0.1.BUILD-SNAPSHOT 9 | jar 10 | 11 | keycloak-javafx-client-demo 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 1.5.13.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | 1.8 24 | 1.3.0 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter 31 | 32 | 33 | 34 | org.keycloak 35 | keycloak-adapter-core 36 | 3.0.0.Final 37 | 38 | 39 | 40 | org.keycloak 41 | keycloak-core 42 | 3.0.0.Final 43 | 44 | 45 | 46 | org.jboss.logging 47 | jboss-logging 48 | 49 | 50 | 51 | org.apache.httpcomponents 52 | httpclient 53 | 54 | 55 | 56 | de.roskenet 57 | springboot-javafx-support 58 | ${springboot-javafx.version} 59 | 60 | 61 | org.springframework.boot 62 | spring-boot-starter-web 63 | 64 | 65 | 66 | 67 | 68 | 69 | org.springframework.boot 70 | spring-boot-maven-plugin 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /demos/keycloak-javafx-client-demo/src/main/java/demo/KeycloakJavafxClientDemoApp.java: -------------------------------------------------------------------------------- 1 | package demo; 2 | 3 | import org.springframework.boot.autoconfigure.SpringBootApplication; 4 | 5 | import de.felixroske.jfxsupport.AbstractJavaFxApplicationSupport; 6 | import demo.app.HelloworldView; 7 | 8 | @SpringBootApplication 9 | public class KeycloakJavafxClientDemoApp extends AbstractJavaFxApplicationSupport { 10 | 11 | public static void main(String[] args) { 12 | launchApp(KeycloakJavafxClientDemoApp.class, HelloworldView.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /demos/keycloak-javafx-client-demo/src/main/java/demo/app/HelloworldView.java: -------------------------------------------------------------------------------- 1 | package demo.app; 2 | 3 | import de.felixroske.jfxsupport.AbstractFxmlView; 4 | import de.felixroske.jfxsupport.FXMLView; 5 | 6 | @FXMLView 7 | public class HelloworldView extends AbstractFxmlView { 8 | 9 | } -------------------------------------------------------------------------------- /demos/keycloak-javafx-client-demo/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdarimont/springio18-spring-keycloak/c0b78658e2c74e934615fa18058e10d9b6eee4ca/demos/keycloak-javafx-client-demo/src/main/resources/application.properties -------------------------------------------------------------------------------- /demos/keycloak-postman/3.x/keycloak-postman-3.x.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "Keycloak-Demos", 5 | "_postman_id": "c1a30f08-4152-d4e8-5fba-c533beb8d82a", 6 | "description": "", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [] 10 | } -------------------------------------------------------------------------------- /demos/plain-js-frontend/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | python -m SimpleHTTPServer 20002 4 | -------------------------------------------------------------------------------- /demos/plain-js-frontend/start3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "starting plain js app" 4 | python -m http.server 20002 5 | -------------------------------------------------------------------------------- /demos/plain-js-frontend/webapp/app.js: -------------------------------------------------------------------------------- 1 | var keycloak = new Keycloak({ 2 | url: 'http://sso.tdlabs.local:8899/u/auth', 3 | realm: 'acme', 4 | clientId: 'app-frontend-plainjs' 5 | }); 6 | 7 | window.onload = function () { 8 | 9 | keycloak.init({onLoad: 'login-required', checkLoginIframe: true, checkLoginIframeInterval: 1}) 10 | .success(function () { 11 | 12 | if (keycloak.authenticated) { 13 | showProfile(); 14 | } else { 15 | welcome(); 16 | } 17 | 18 | document.body.style.display = 'block'; 19 | }); 20 | }; 21 | 22 | function welcome() { 23 | show('welcome'); 24 | } 25 | 26 | function showProfile() { 27 | 28 | if (keycloak.tokenParsed['given_name']) { 29 | document.getElementById('firstName').innerHTML = keycloak.tokenParsed['given_name']; 30 | } 31 | if (keycloak.tokenParsed['family_name']) { 32 | document.getElementById('lastName').innerHTML = keycloak.tokenParsed['family_name']; 33 | } 34 | if (keycloak.tokenParsed['preferred_username']) { 35 | document.getElementById('username').innerHTML = keycloak.tokenParsed['preferred_username']; 36 | } 37 | if (keycloak.tokenParsed['email']) { 38 | document.getElementById('email').innerHTML = keycloak.tokenParsed['email']; 39 | } 40 | 41 | show('profile'); 42 | } 43 | 44 | function showToken() { 45 | document.getElementById('token-content').innerHTML = JSON.stringify(keycloak.tokenParsed, null, ' '); 46 | show('token'); 47 | } 48 | 49 | function show(id) { 50 | document.getElementById('welcome').style.display = 'none'; 51 | document.getElementById('profile').style.display = 'none'; 52 | document.getElementById('token').style.display = 'none'; 53 | document.getElementById(id).style.display = 'block'; 54 | } 55 | 56 | keycloak.onAuthLogout = welcome; 57 | -------------------------------------------------------------------------------- /demos/plain-js-frontend/webapp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Plain JS Profile 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 24 | 25 | 56 | 57 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /demos/plain-js-frontend/webapp/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #eaeaea; 3 | font-family: sans-serif; 4 | font-size: 30px; 5 | } 6 | 7 | button { 8 | font-family: sans-serif; 9 | font-size: 30px; 10 | width: 200px; 11 | 12 | background-color: #0085cf; 13 | background-image: linear-gradient(to bottom, #00a8e1 0%, #0085cf 100%); 14 | background-repeat: repeat-x; 15 | 16 | border: 2px solid #ccc; 17 | color: #fff; 18 | 19 | text-transform: uppercase; 20 | 21 | -webkit-box-shadow: 2px 2px 10px 0px rgba(0,0,0,0.5); 22 | -moz-box-shadow: 2px 2px 10px 0px rgba(0,0,0,0.5); 23 | box-shadow: 2px 2px 10px 0px rgba(0,0,0,0.5); 24 | } 25 | 26 | button:hover { 27 | background-color: #006ba6; 28 | background-image: none; 29 | -webkit-box-shadow: none; 30 | -moz-box-shadow: none; 31 | box-shadow: none; 32 | } 33 | 34 | hr { 35 | border: none; 36 | background-color: #eee; 37 | height: 10px; 38 | } 39 | 40 | .menu { 41 | padding: 10px; 42 | margin-bottom: 10px; 43 | } 44 | 45 | .content { 46 | background-color: #eee; 47 | border: 1px solid #ccc; 48 | padding: 10px; 49 | 50 | -webkit-box-shadow: 2px 2px 10px 0px rgba(0,0,0,0.5); 51 | -moz-box-shadow: 2px 2px 10px 0px rgba(0,0,0,0.5); 52 | box-shadow: 2px 2px 10px 0px rgba(0,0,0,0.5); 53 | } 54 | 55 | .content .message { 56 | padding: 10px; 57 | background-color: #fff; 58 | border: 1px solid #ccc; 59 | font-size: 40px; 60 | } 61 | 62 | #token-content { 63 | font-size: 20px; 64 | padding: 5px; 65 | white-space: pre; 66 | text-transform: none; 67 | } 68 | 69 | .wrapper { 70 | position: absolute; 71 | left: 10px; 72 | top: 10px; 73 | bottom: 10px; 74 | right: 10px; 75 | } 76 | 77 | .error { 78 | color: #a21e22; 79 | } 80 | 81 | table { 82 | width: 100%; 83 | } 84 | 85 | tr.even { 86 | background-color: #eee; 87 | } 88 | 89 | td { 90 | padding: 5px; 91 | } 92 | 93 | td.label { 94 | font-weight: bold; 95 | width: 250px; 96 | } 97 | -------------------------------------------------------------------------------- /demos/spring-boot-2-backend/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /demos/spring-boot-2-backend/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdarimont/springio18-spring-keycloak/c0b78658e2c74e934615fa18058e10d9b6eee4ca/demos/spring-boot-2-backend/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /demos/spring-boot-2-backend/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.0/apache-maven-3.5.0-bin.zip 2 | -------------------------------------------------------------------------------- /demos/spring-boot-2-backend/src/main/java/demo/Backend2Application.java: -------------------------------------------------------------------------------- 1 | package demo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.autoconfigure.domain.EntityScan; 6 | import org.springframework.data.jpa.convert.threeten.Jsr310JpaConverters; 7 | 8 | @EntityScan( 9 | basePackageClasses = {Backend2Application.class, Jsr310JpaConverters.class} 10 | ) 11 | @SpringBootApplication 12 | public class Backend2Application { 13 | 14 | public static void main(String[] args) { 15 | SpringApplication.run(Backend2Application.class, args); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /demos/spring-boot-2-backend/src/main/java/demo/KeycloakEvaluationContextExtension.java: -------------------------------------------------------------------------------- 1 | package demo; 2 | 3 | import org.keycloak.KeycloakPrincipal; 4 | import org.keycloak.KeycloakSecurityContext; 5 | import org.springframework.data.repository.query.spi.EvaluationContextExtensionSupport; 6 | import org.springframework.stereotype.Component; 7 | import org.springframework.web.context.request.RequestContextHolder; 8 | import org.springframework.web.context.request.ServletRequestAttributes; 9 | 10 | import java.security.Principal; 11 | 12 | @Component 13 | class KeycloakEvaluationContextExtension extends EvaluationContextExtensionSupport { 14 | 15 | @Override 16 | public String getExtensionId() { 17 | return "keycloak"; 18 | } 19 | 20 | @Override 21 | public Object getRootObject() { 22 | return getKeycloakSecurityContext(); 23 | } 24 | 25 | protected KeycloakSecurityContext getKeycloakSecurityContext() { 26 | 27 | ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); 28 | Principal principal = attributes.getRequest().getUserPrincipal(); 29 | 30 | if (principal instanceof KeycloakPrincipal) { 31 | return KeycloakPrincipal.class.cast(principal).getKeycloakSecurityContext(); 32 | } 33 | 34 | return null; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /demos/spring-boot-2-backend/src/main/java/demo/todo/Todo.java: -------------------------------------------------------------------------------- 1 | package demo.todo; 2 | 3 | import lombok.Data; 4 | 5 | import javax.persistence.Entity; 6 | import javax.persistence.GeneratedValue; 7 | import javax.persistence.Id; 8 | import java.time.LocalDateTime; 9 | 10 | @Data 11 | @Entity 12 | class Todo { 13 | 14 | @Id 15 | @GeneratedValue 16 | private Long id; 17 | 18 | private String name; 19 | 20 | private String description; 21 | 22 | private boolean completed; 23 | 24 | private LocalDateTime createdAt; 25 | 26 | private LocalDateTime updatedAt; 27 | 28 | private String ownerId; 29 | } 30 | -------------------------------------------------------------------------------- /demos/spring-boot-2-backend/src/main/java/demo/todo/TodoRepository.java: -------------------------------------------------------------------------------- 1 | package demo.todo; 2 | 3 | import org.springframework.data.jpa.repository.Query; 4 | import org.springframework.data.repository.CrudRepository; 5 | import org.springframework.data.rest.core.annotation.RepositoryRestResource; 6 | import org.springframework.data.rest.core.annotation.RestResource; 7 | 8 | import java.util.List; 9 | 10 | @RepositoryRestResource(path = "todos") 11 | interface TodoRepository extends CrudRepository { 12 | 13 | @RestResource(path = "my-todos") 14 | @Query("select t from Todo t where t.ownerId = ?#{ #keycloak.token.subject }") 15 | List findMyTodos(); 16 | } 17 | -------------------------------------------------------------------------------- /demos/spring-boot-2-backend/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | keycloak: 2 | realm: acme 3 | auth-server-url: http://sso.tdlabs.local:8899/u/auth 4 | resource: app-backend-springboot 5 | bearer-only: true 6 | ssl-required: external 7 | principal-attribute: subject 8 | use-resource-role-mappings: true 9 | 10 | securityConstraints: 11 | - authRoles: [user, admin] 12 | securityCollections: 13 | - name: API Private Data 14 | patterns: ['/todos/search/my-todos/*'] 15 | - authRoles: [admin] 16 | securityCollections: 17 | - name: API 18 | patterns: ['/todos/*'] 19 | 20 | spring: 21 | jpa: 22 | show-sql: true 23 | hibernate: 24 | ddl-auto: create 25 | jackson: 26 | serialization: 27 | write-dates-as-timestamps: false 28 | 29 | server: 30 | port: 20000 -------------------------------------------------------------------------------- /demos/spring-boot-2-backend/src/main/resources/data.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO todo (id, name, description, completed, created_at, owner_id) 2 | VALUES (1, 'Buy milk', '...', TRUE, {ts '2017-09-17 18:47:52.69'}, 3 | 'af86fe6e-6558-4872-88ee-0e9448e5ae91'); 4 | 5 | INSERT INTO todo (id, name, description, completed, created_at, owner_id) 6 | VALUES (2, 'Cleanup desk', '...', FALSE, {ts '2017-09-19 18:47:52.69'}, 7 | 'af86fe6e-6558-4872-88ee-0e9448e5ae91'); 8 | 9 | INSERT INTO todo (id, name, description, completed, created_at, owner_id) 10 | VALUES (3, 'Send memo', '...', FALSE, {ts '2017-09-20 18:47:52.69'}, 11 | 'af86fe6e-6558-4872-88ee-0e9448e5ae91'); 12 | 13 | INSERT INTO todo (id, name, description, completed, created_at, owner_id) 14 | VALUES (4, 'Publish article', '...', FALSE, {ts '2017-09-21 18:47:52.69'}, 15 | 'af86fe6e-6558-4872-88ee-0e9448e5ae91'); 16 | 17 | INSERT INTO todo (id, name, description, completed, created_at, owner_id) 18 | VALUES (11, 'Write article about Spring 2.0.x', '...', FALSE, {ts '2017-09-22 18:47:52.69'}, 19 | 'af86fe6e-6558-4872-88ee-0e9448e5ae91'); 20 | 21 | -- 22 | 23 | INSERT INTO todo (id, name, description, completed, created_at, owner_id) 24 | VALUES (5, 'Organize Grandfathers birthday', '...', TRUE, {ts '2017-09-17 18:47:52.69'}, 25 | 'eb2ad785-222c-4586-8b7c-c7ef4b2760dd'); 26 | 27 | INSERT INTO todo (id, name, description, completed, created_at, owner_id) 28 | VALUES (6, 'Pickup kids from school', '...', FALSE, {ts '2017-09-19 18:47:52.69'}, 29 | 'eb2ad785-222c-4586-8b7c-c7ef4b2760dd'); 30 | 31 | INSERT INTO todo (id, name, description, completed, created_at, owner_id) 32 | VALUES (7, 'Plan hiking tour', '...', FALSE, {ts '2017-09-20 18:47:52.69'}, 33 | 'eb2ad785-222c-4586-8b7c-c7ef4b2760dd'); 34 | -------------------------------------------------------------------------------- /demos/spring-boot-2-backend/src/test/java/demo/SpringBootBackendApplicationTests.java: -------------------------------------------------------------------------------- 1 | package demo; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class SpringBootBackendApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /demos/spring-boot-2-frontend/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /demos/spring-boot-2-frontend/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdarimont/springio18-spring-keycloak/c0b78658e2c74e934615fa18058e10d9b6eee4ca/demos/spring-boot-2-frontend/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /demos/spring-boot-2-frontend/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.0/apache-maven-3.5.0-bin.zip 2 | -------------------------------------------------------------------------------- /demos/spring-boot-2-frontend/src/main/java/demo/Frontend2Application.java: -------------------------------------------------------------------------------- 1 | package demo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.hateoas.config.EnableHypermediaSupport; 6 | import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType; 7 | 8 | @SpringBootApplication 9 | @EnableHypermediaSupport(type = HypermediaType.HAL) 10 | public class Frontend2Application { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(Frontend2Application.class, args); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /demos/spring-boot-2-frontend/src/main/java/demo/config/KeycloakLinkGenerator.java: -------------------------------------------------------------------------------- 1 | package demo.config; 2 | 3 | import org.keycloak.KeycloakSecurityContext; 4 | import org.keycloak.adapters.springboot.KeycloakSpringBootProperties; 5 | import org.springframework.stereotype.Component; 6 | import org.springframework.web.context.annotation.RequestScope; 7 | import org.springframework.web.util.UriComponentsBuilder; 8 | 9 | import lombok.RequiredArgsConstructor; 10 | 11 | @Component 12 | @RequestScope 13 | @RequiredArgsConstructor 14 | public class KeycloakLinkGenerator { 15 | 16 | private static final String CLIENT_LINK_TEMPLATE = "%s/realms/%s/clients/%s/redirect"; 17 | 18 | private final KeycloakSpringBootProperties keycloakProperties; 19 | 20 | private final KeycloakSecurityContext keycloakSecurityContext; 21 | 22 | public String getClientLink(String clientId) { 23 | return String.format(CLIENT_LINK_TEMPLATE, // 24 | keycloakProperties.getAuthServerUrl(), // 25 | keycloakProperties.getRealm(), // 26 | clientId // 27 | ); 28 | } 29 | 30 | public String createAccountLinkWithBacklink(String backlinkUri) { 31 | 32 | UriComponentsBuilder accountUri = UriComponentsBuilder 33 | .fromHttpUrl(keycloakSecurityContext.getToken().getIssuer()).path("/account") 34 | .queryParam("referrer", keycloakProperties.getResource()).queryParam("referrer_uri", backlinkUri); 35 | 36 | return accountUri.toUriString(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /demos/spring-boot-2-frontend/src/main/java/demo/todo/KeycloakTodoClient.java: -------------------------------------------------------------------------------- 1 | package demo.todo; 2 | 3 | import java.util.Collections; 4 | 5 | import org.keycloak.adapters.springsecurity.client.KeycloakRestTemplate; 6 | import org.springframework.beans.factory.annotation.Value; 7 | import org.springframework.hateoas.Resource; 8 | import org.springframework.hateoas.Resources; 9 | import org.springframework.http.ResponseEntity; 10 | import org.springframework.stereotype.Component; 11 | 12 | @Component 13 | class KeycloakTodoClient implements TodoClient { 14 | 15 | private final KeycloakRestTemplate keycloakRestTemplate; 16 | 17 | private final String backendUri; 18 | 19 | public KeycloakTodoClient( // 20 | KeycloakRestTemplate keycloakRestTemplate, // 21 | @Value("${todo-backend.server}") String backendUri // 22 | ) { 23 | this.keycloakRestTemplate = keycloakRestTemplate; 24 | this.backendUri = backendUri; 25 | } 26 | 27 | @Override 28 | public Resources> fetchTodos() { 29 | 30 | ResponseEntity response = keycloakRestTemplate.getForEntity( // 31 | backendUri + "/todos/search/my-todos", // 32 | Resources.class, // 33 | Collections.emptyMap() // 34 | ); 35 | 36 | Resources todos = response.getBody(); 37 | return todos; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /demos/spring-boot-2-frontend/src/main/java/demo/todo/Todo.java: -------------------------------------------------------------------------------- 1 | package demo.todo; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @NoArgsConstructor(force=true) 9 | @JsonIgnoreProperties(ignoreUnknown = true) 10 | public class Todo { 11 | 12 | final Long id; 13 | 14 | final String name; 15 | 16 | final boolean completed; 17 | } 18 | -------------------------------------------------------------------------------- /demos/spring-boot-2-frontend/src/main/java/demo/todo/TodoClient.java: -------------------------------------------------------------------------------- 1 | package demo.todo; 2 | 3 | import org.springframework.hateoas.Resource; 4 | import org.springframework.hateoas.Resources; 5 | 6 | public interface TodoClient { 7 | 8 | Resources> fetchTodos(); 9 | } 10 | -------------------------------------------------------------------------------- /demos/spring-boot-2-frontend/src/main/java/demo/web/PingController.java: -------------------------------------------------------------------------------- 1 | package demo.web; 2 | 3 | import java.util.Collections; 4 | 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @RestController 9 | class PingController { 10 | 11 | @GetMapping("/ping") 12 | public Object ping() { 13 | return Collections.singletonMap("status", "ok"); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /demos/spring-boot-2-frontend/src/main/java/demo/web/UiController.java: -------------------------------------------------------------------------------- 1 | package demo.web; 2 | 3 | import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo; 4 | 5 | import java.security.Principal; 6 | 7 | import javax.servlet.http.HttpServletRequest; 8 | 9 | import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken; 10 | import org.springframework.hateoas.Resource; 11 | import org.springframework.hateoas.Resources; 12 | import org.springframework.security.core.annotation.AuthenticationPrincipal; 13 | import org.springframework.stereotype.Controller; 14 | import org.springframework.ui.Model; 15 | import org.springframework.web.bind.annotation.GetMapping; 16 | 17 | import demo.config.KeycloakLinkGenerator; 18 | import demo.todo.Todo; 19 | import demo.todo.TodoClient; 20 | import lombok.RequiredArgsConstructor; 21 | 22 | @Controller 23 | @RequiredArgsConstructor 24 | class UiController { 25 | 26 | private final TodoClient todoClient; 27 | 28 | private final KeycloakLinkGenerator keycloakLinkGenerator; 29 | 30 | @GetMapping("/") 31 | public String index() { 32 | return "index"; 33 | } 34 | 35 | @GetMapping("/logout") 36 | public String logout(HttpServletRequest request) throws Exception { 37 | request.logout(); 38 | return "redirect:/todos"; 39 | } 40 | 41 | @GetMapping("/account") 42 | public String account() { 43 | 44 | String todoUri = linkTo(getClass()).toUriComponentsBuilder().path("/todos").toUriString(); 45 | return "redirect:" + keycloakLinkGenerator.createAccountLinkWithBacklink(todoUri); 46 | } 47 | 48 | @GetMapping("/todos*") 49 | public String todos(Model model, @AuthenticationPrincipal Principal currentUser) { 50 | 51 | Resources> todos = todoClient.fetchTodos(); 52 | model.addAttribute("todos", todos.getContent()); 53 | 54 | KeycloakAuthenticationToken keycloakUser = (KeycloakAuthenticationToken) currentUser; 55 | System.out.printf("Current user roles: %s%n", keycloakUser.getAuthorities()); 56 | 57 | return "todos"; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /demos/spring-boot-2-frontend/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 20001 3 | 4 | keycloak: 5 | # turn off keycloak spring boot auto-configuration: 6 | # We only want to use Spring Security without servlet container specific infrastructure 7 | # This allows us to pull the Keycloak configuration from here instead of keycloak.json 8 | enabled: false 9 | 10 | realm: acme 11 | auth-server-url: http://sso.tdlabs.local:8899/u/auth 12 | resource: app-frontend-springboot 13 | credentials: 14 | secret: 4822a740-20b9-4ff7-bbed-e664f4a70eb6 15 | ssl-required: external 16 | principal-attribute: preferred_username 17 | use-resource-role-mappings: true 18 | token-minimum-time-to-live: 30 19 | 20 | 21 | todo-backend: 22 | server: http://apps.tdlabs.local:20000 -------------------------------------------------------------------------------- /demos/spring-boot-2-frontend/src/main/resources/static/css/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 50px; 3 | } 4 | 5 | .text-center h1 { 6 | font-size: 68px; 7 | } 8 | 9 | .text-center span.glyphicon { 10 | font-size: 20em; 11 | } 12 | 13 | .search-line { 14 | position: relative; 15 | } -------------------------------------------------------------------------------- /demos/spring-boot-2-frontend/src/main/resources/templates/error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 |
8 |

Something went wrong

9 |

404

10 |

Error java.lang.NullPointerException

11 | Back to Home Page 12 |
13 |
14 | 15 | 16 | -------------------------------------------------------------------------------- /demos/spring-boot-2-frontend/src/main/resources/templates/fragments.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Todoo Frontend (Spring Boot) 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 24 | 25 | 26 | 62 | 63 | -------------------------------------------------------------------------------- /demos/spring-boot-2-frontend/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 |
8 |

Todoo

9 | 10 | 11 | 12 |
13 |
14 | 15 | 16 | -------------------------------------------------------------------------------- /demos/spring-boot-2-frontend/src/main/resources/templates/todos.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 | 8 |
9 |

My Todos

10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
NameCompleted
24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /demos/spring-boot-2-frontend/src/test/java/demo/SpringBootFrontend2ApplicationTests.java: -------------------------------------------------------------------------------- 1 | package demo; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class SpringBootFrontend2ApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /demos/spring-boot-app-integration/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /demos/spring-boot-app-integration/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdarimont/springio18-spring-keycloak/c0b78658e2c74e934615fa18058e10d9b6eee4ca/demos/spring-boot-app-integration/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /demos/spring-boot-app-integration/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.2/apache-maven-3.5.2-bin.zip 2 | -------------------------------------------------------------------------------- /demos/spring-boot-app-integration/src/main/java/demo/SecurityConfig.java: -------------------------------------------------------------------------------- 1 | package demo; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 5 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 6 | 7 | @Configuration 8 | class SecurityConfig extends WebSecurityConfigurerAdapter { 9 | 10 | protected void configure(HttpSecurity http) throws Exception { 11 | 12 | http.authorizeRequests() // 13 | .anyRequest().authenticated() // 14 | .and().formLogin(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /demos/spring-boot-app-integration/src/main/java/demo/ThirdpartyApp.java: -------------------------------------------------------------------------------- 1 | package demo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 6 | 7 | import demo.oauth2.Oauth2Properties; 8 | 9 | @SpringBootApplication 10 | @EnableConfigurationProperties(Oauth2Properties.class) 11 | public class ThirdpartyApp { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(ThirdpartyApp.class, args); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /demos/spring-boot-app-integration/src/main/java/demo/oauth2/Oauth2Properties.java: -------------------------------------------------------------------------------- 1 | package demo.oauth2; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | import lombok.Data; 6 | 7 | @Data 8 | @ConfigurationProperties("demo.oauth2") 9 | public class Oauth2Properties { 10 | 11 | String clientId; 12 | 13 | String clientSecret; 14 | 15 | String tokenEndpoint; 16 | 17 | String authEndpoint; 18 | 19 | String jwksEndpoint; 20 | 21 | String redirectUri; 22 | } 23 | -------------------------------------------------------------------------------- /demos/spring-boot-app-integration/src/main/java/demo/oauth2/TokensStore.java: -------------------------------------------------------------------------------- 1 | package demo.oauth2; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import java.util.concurrent.ConcurrentHashMap; 6 | import java.util.concurrent.ConcurrentMap; 7 | 8 | import org.springframework.stereotype.Component; 9 | 10 | import com.fasterxml.jackson.annotation.JsonAnySetter; 11 | import com.fasterxml.jackson.annotation.JsonProperty; 12 | 13 | import lombok.Data; 14 | import lombok.extern.slf4j.Slf4j; 15 | 16 | @Component 17 | @Slf4j 18 | public class TokensStore { 19 | 20 | private final ConcurrentMap store = new ConcurrentHashMap<>(); 21 | 22 | public Tokens storeTokens(String key, Tokens tokens) { 23 | store.put(key, tokens); 24 | return tokens; 25 | } 26 | 27 | public Tokens getTokens(String key) { 28 | return store.get(key); 29 | } 30 | 31 | @Data 32 | public static class Tokens { 33 | 34 | private static final long MIN_SECONDS = 3; 35 | 36 | private final long createdAt = System.currentTimeMillis(); 37 | 38 | @JsonProperty(value = "access_token") 39 | private String accessToken; 40 | 41 | @JsonProperty(value = "refresh_token") 42 | private String refreshToken; 43 | 44 | @JsonProperty(value = "refresh_expires_in") 45 | private long refreshExpiresInSeconds; 46 | 47 | @JsonProperty(value = "expires_in") 48 | private long expiresInSeconds; 49 | 50 | Map additionalValues = new HashMap<>(); 51 | 52 | public Tokens() { 53 | } 54 | 55 | public Tokens(String accessToken, String refreshToken, long refreshExpiresInSeconds, long expiresInSeconds) { 56 | this.accessToken = accessToken; 57 | this.refreshToken = refreshToken; 58 | this.refreshExpiresInSeconds = refreshExpiresInSeconds; 59 | this.expiresInSeconds = expiresInSeconds; 60 | } 61 | 62 | @JsonAnySetter 63 | public void addAdditional(String key, Object value) { 64 | additionalValues.put(key, value); 65 | } 66 | 67 | public boolean isAccessTokenStillValid() { 68 | 69 | long ageInSeconds = (System.currentTimeMillis() - createdAt) / 1000; 70 | long maxAgeInSeconds = expiresInSeconds - MIN_SECONDS; 71 | 72 | boolean valid = ageInSeconds <= maxAgeInSeconds; 73 | 74 | if (valid) { 75 | TokensStore.log.info("token still valid for: {} seconds", maxAgeInSeconds - ageInSeconds); 76 | } 77 | 78 | return valid; 79 | } 80 | 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /demos/spring-boot-app-integration/src/main/java/demo/web/ApiController.java: -------------------------------------------------------------------------------- 1 | package demo.web; 2 | 3 | import java.security.Principal; 4 | import java.util.Map; 5 | 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.RestController; 9 | import org.springframework.web.client.RestTemplate; 10 | 11 | import demo.oauth2.Oauth2Client; 12 | import lombok.RequiredArgsConstructor; 13 | import lombok.extern.slf4j.Slf4j; 14 | 15 | @RestController 16 | @Slf4j 17 | @RequiredArgsConstructor 18 | class ApiController { 19 | 20 | private final Oauth2Client oauth2Client; 21 | 22 | @GetMapping("/api") 23 | Object callApi(Principal principal) { 24 | 25 | log.info("create oauth template..."); 26 | 27 | RestTemplate rt = oauth2Client.createOauth2RestTemplate(principal.getName()); 28 | 29 | log.info("make api call..."); 30 | 31 | ResponseEntity response = rt.getForEntity("http://apps.tdlabs.local:20000/todos/search/my-todos", Map.class); 32 | log.info("got api response."); 33 | 34 | return response.getBody(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /demos/spring-boot-app-integration/src/main/java/demo/web/ConnectController.java: -------------------------------------------------------------------------------- 1 | package demo.web; 2 | 3 | import java.security.Principal; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | import javax.validation.Valid; 8 | 9 | import org.hibernate.validator.constraints.NotEmpty; 10 | import org.springframework.stereotype.Controller; 11 | import org.springframework.ui.Model; 12 | import org.springframework.web.bind.annotation.GetMapping; 13 | 14 | import com.fasterxml.jackson.annotation.JsonAnySetter; 15 | 16 | import demo.oauth2.Oauth2Client; 17 | import demo.oauth2.Oauth2Properties; 18 | import demo.oauth2.TokensStore.Tokens; 19 | import lombok.Data; 20 | import lombok.RequiredArgsConstructor; 21 | import lombok.extern.slf4j.Slf4j; 22 | 23 | @Controller 24 | @Slf4j 25 | @RequiredArgsConstructor 26 | public class ConnectController { 27 | 28 | private final Oauth2Client oauth2Client; 29 | 30 | private final Oauth2Properties oauthProperties; 31 | 32 | @GetMapping("/") 33 | public String index(Model model) { 34 | model.addAttribute("oauth", oauthProperties); 35 | return "index"; 36 | } 37 | 38 | @GetMapping(path = "/connect", params = { "session_state", "code" }) 39 | public String connect(@Valid ConnectRequest connectRequest, Principal principal) { 40 | 41 | log.info("Obtain tokens..."); 42 | 43 | Tokens tokens = oauth2Client.requestNewTokensWithCode( // 44 | principal.getName(), connectRequest.getCode(), connectRequest.getSession_state()); 45 | 46 | log.info("Obtained tokens for user: {} with external_user_id: {}", principal.getName(), 47 | tokens.getAdditionalValues().get("subject")); 48 | return "redirect:/connected"; 49 | } 50 | 51 | @GetMapping(path = "/connected") 52 | public String connect(Model model) { 53 | return "connected"; 54 | } 55 | 56 | @Data 57 | static class ConnectRequest { 58 | 59 | @NotEmpty 60 | String session_state; 61 | 62 | @NotEmpty 63 | String code; 64 | 65 | Map additionalValues = new HashMap<>(); 66 | 67 | public ConnectRequest(){ 68 | } 69 | 70 | public ConnectRequest(String session_state, String code, Map additionalValues) { 71 | this.session_state = session_state; 72 | this.code = code; 73 | this.additionalValues = additionalValues; 74 | } 75 | 76 | @JsonAnySetter 77 | public void addAdditional(String key, Object value) { 78 | additionalValues.put(key, value); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /demos/spring-boot-app-integration/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 30000 3 | security: 4 | user: 5 | password: dev 6 | 7 | demo: 8 | authServerUrl: http://sso.tdlabs.local:8899/u/auth 9 | oauth2: 10 | clientId: app-thirdparty 11 | clientSecret: e6152257-d856-4f72-8530-bddd1179d112 12 | authEndpoint: ${demo.authServerUrl}/realms/acme/protocol/openid-connect/auth 13 | tokenEndpoint: ${demo.authServerUrl}/realms/acme/protocol/openid-connect/token 14 | jwksEndpoint: ${demo.authServerUrl}/realms/acme/protocol/openid-connect/certs 15 | redirectUri: http://thirdparty.local:30000/connect -------------------------------------------------------------------------------- /demos/spring-boot-app-integration/src/main/resources/templates/connected.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Thirdparty App: Connected 5 | 6 | 7 | 8 | 9 |

Connected

10 | Make API call 11 | 12 | -------------------------------------------------------------------------------- /demos/spring-boot-app-integration/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Thirdparty App 5 | 6 | 7 | 8 |

Connect

9 | 10 | 24 | 25 | -------------------------------------------------------------------------------- /demos/spring-boot-app-integration/src/test/java/demo/SpringBootAppIntegrationApplicationTests.java: -------------------------------------------------------------------------------- 1 | package demo; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class SpringBootAppIntegrationApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /demos/spring-boot-backend/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /demos/spring-boot-backend/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdarimont/springio18-spring-keycloak/c0b78658e2c74e934615fa18058e10d9b6eee4ca/demos/spring-boot-backend/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /demos/spring-boot-backend/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.0/apache-maven-3.5.0-bin.zip 2 | -------------------------------------------------------------------------------- /demos/spring-boot-backend/src/main/java/demo/BackendApplication.java: -------------------------------------------------------------------------------- 1 | package demo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.autoconfigure.domain.EntityScan; 6 | import org.springframework.data.jpa.convert.threeten.Jsr310JpaConverters; 7 | 8 | @EntityScan( 9 | basePackageClasses = {BackendApplication.class, Jsr310JpaConverters.class} 10 | ) 11 | @SpringBootApplication 12 | public class BackendApplication { 13 | 14 | public static void main(String[] args) { 15 | SpringApplication.run(BackendApplication.class, args); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /demos/spring-boot-backend/src/main/java/demo/KeycloakEvaluationContextExtension.java: -------------------------------------------------------------------------------- 1 | package demo; 2 | 3 | import org.keycloak.KeycloakPrincipal; 4 | import org.keycloak.KeycloakSecurityContext; 5 | import org.springframework.data.repository.query.spi.EvaluationContextExtensionSupport; 6 | import org.springframework.stereotype.Component; 7 | import org.springframework.web.context.request.RequestContextHolder; 8 | import org.springframework.web.context.request.ServletRequestAttributes; 9 | 10 | import java.security.Principal; 11 | 12 | @Component 13 | class KeycloakEvaluationContextExtension extends EvaluationContextExtensionSupport { 14 | 15 | @Override 16 | public String getExtensionId() { 17 | return "keycloak"; 18 | } 19 | 20 | @Override 21 | public Object getRootObject() { 22 | return getKeycloakSecurityContext(); 23 | } 24 | 25 | protected KeycloakSecurityContext getKeycloakSecurityContext() { 26 | 27 | ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); 28 | Principal principal = attributes.getRequest().getUserPrincipal(); 29 | 30 | if (principal instanceof KeycloakPrincipal) { 31 | return KeycloakPrincipal.class.cast(principal).getKeycloakSecurityContext(); 32 | } 33 | 34 | return null; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /demos/spring-boot-backend/src/main/java/demo/todo/Todo.java: -------------------------------------------------------------------------------- 1 | package demo.todo; 2 | 3 | import lombok.Data; 4 | 5 | import javax.persistence.Entity; 6 | import javax.persistence.GeneratedValue; 7 | import javax.persistence.Id; 8 | import java.time.LocalDateTime; 9 | 10 | @Data 11 | @Entity 12 | class Todo { 13 | 14 | @Id 15 | @GeneratedValue 16 | private Long id; 17 | 18 | private String name; 19 | 20 | private String description; 21 | 22 | private boolean completed; 23 | 24 | private LocalDateTime createdAt; 25 | 26 | private LocalDateTime updatedAt; 27 | 28 | private String ownerId; 29 | } 30 | -------------------------------------------------------------------------------- /demos/spring-boot-backend/src/main/java/demo/todo/TodoRepository.java: -------------------------------------------------------------------------------- 1 | package demo.todo; 2 | 3 | import org.springframework.data.jpa.repository.Query; 4 | import org.springframework.data.repository.CrudRepository; 5 | import org.springframework.data.rest.core.annotation.RepositoryRestResource; 6 | import org.springframework.data.rest.core.annotation.RestResource; 7 | 8 | import java.util.List; 9 | 10 | @RepositoryRestResource(path = "todos") 11 | interface TodoRepository extends CrudRepository { 12 | 13 | @RestResource(path = "my-todos") 14 | @Query("select t from Todo t where t.ownerId = ?#{ #keycloak.token.subject }") 15 | List findMyTodos(); 16 | } 17 | -------------------------------------------------------------------------------- /demos/spring-boot-backend/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | keycloak: 2 | realm: acme 3 | auth-server-url: http://sso.tdlabs.local:8899/u/auth 4 | resource: app-backend-springboot 5 | bearer-only: true 6 | ssl-required: external 7 | principal-attribute: subject 8 | use-resource-role-mappings: true 9 | 10 | securityConstraints: 11 | - authRoles: [user, admin] 12 | securityCollections: 13 | - name: API Private Data 14 | patterns: ['/todos/search/my-todos/*'] 15 | - authRoles: [admin] 16 | securityCollections: 17 | - name: API 18 | patterns: ['/todos/*'] 19 | 20 | spring: 21 | jpa: 22 | show-sql: true 23 | hibernate: 24 | ddl-auto: create 25 | jackson: 26 | serialization: 27 | write-dates-as-timestamps: false 28 | 29 | server: 30 | port: 20000 -------------------------------------------------------------------------------- /demos/spring-boot-backend/src/main/resources/data.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO todo (id, name, description, completed, created_at, owner_id) 2 | VALUES (1, 'Buy milk', '...', TRUE, {ts '2017-09-17 18:47:52.69'}, 3 | 'af86fe6e-6558-4872-88ee-0e9448e5ae91'); 4 | 5 | INSERT INTO todo (id, name, description, completed, created_at, owner_id) 6 | VALUES (2, 'Cleanup desk', '...', FALSE, {ts '2017-09-19 18:47:52.69'}, 7 | 'af86fe6e-6558-4872-88ee-0e9448e5ae91'); 8 | 9 | INSERT INTO todo (id, name, description, completed, created_at, owner_id) 10 | VALUES (3, 'Send memo', '...', FALSE, {ts '2017-09-20 18:47:52.69'}, 11 | 'af86fe6e-6558-4872-88ee-0e9448e5ae91'); 12 | 13 | INSERT INTO todo (id, name, description, completed, created_at, owner_id) 14 | VALUES (4, 'Publish article', '...', FALSE, {ts '2017-09-21 18:47:52.69'}, 15 | 'af86fe6e-6558-4872-88ee-0e9448e5ae91'); 16 | 17 | INSERT INTO todo (id, name, description, completed, created_at, owner_id) 18 | VALUES (11, 'Write article about Spring 1.5.x', '...', FALSE, {ts '2017-09-22 18:47:52.69'}, 19 | 'af86fe6e-6558-4872-88ee-0e9448e5ae91'); 20 | 21 | 22 | -- 23 | 24 | INSERT INTO todo (id, name, description, completed, created_at, owner_id) 25 | VALUES (5, 'Organize Grandfathers birthday', '...', TRUE, {ts '2017-09-17 18:47:52.69'}, 26 | 'eb2ad785-222c-4586-8b7c-c7ef4b2760dd'); 27 | 28 | INSERT INTO todo (id, name, description, completed, created_at, owner_id) 29 | VALUES (6, 'Pickup kids from school', '...', FALSE, {ts '2017-09-19 18:47:52.69'}, 30 | 'eb2ad785-222c-4586-8b7c-c7ef4b2760dd'); 31 | 32 | INSERT INTO todo (id, name, description, completed, created_at, owner_id) 33 | VALUES (7, 'Plan hiking tour', '...', FALSE, {ts '2017-09-20 18:47:52.69'}, 34 | 'eb2ad785-222c-4586-8b7c-c7ef4b2760dd'); 35 | -------------------------------------------------------------------------------- /demos/spring-boot-backend/src/test/java/demo/SpringBootBackendApplicationTests.java: -------------------------------------------------------------------------------- 1 | package demo; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class SpringBootBackendApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /demos/spring-boot-frontend-javafx/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /demos/spring-boot-frontend-javafx/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdarimont/springio18-spring-keycloak/c0b78658e2c74e934615fa18058e10d9b6eee4ca/demos/spring-boot-frontend-javafx/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /demos/spring-boot-frontend-javafx/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.0/apache-maven-3.5.0-bin.zip 2 | -------------------------------------------------------------------------------- /demos/spring-boot-frontend-javafx/src/main/java/demo/JavaFxFrontendApplication.java: -------------------------------------------------------------------------------- 1 | package demo; 2 | 3 | 4 | import de.felixroske.jfxsupport.AbstractJavaFxApplicationSupport; 5 | import demo.todos.ui.TodosView; 6 | import org.keycloak.adapters.installed.KeycloakInstalled; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | import org.springframework.cloud.netflix.feign.EnableFeignClients; 9 | import org.springframework.hateoas.config.EnableHypermediaSupport; 10 | 11 | import static org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType; 12 | 13 | @EnableFeignClients 14 | @SpringBootApplication 15 | @EnableHypermediaSupport(type = HypermediaType.HAL) 16 | public class JavaFxFrontendApplication extends AbstractJavaFxApplicationSupport { 17 | 18 | public static final KeycloakInstalled KEYCLOAK = new KeycloakInstalled(); 19 | 20 | public static void main(String[] args) { 21 | launchApp(JavaFxFrontendApplication.class, TodosView.class, args); 22 | } 23 | 24 | @Override 25 | public void init() throws Exception { 26 | 27 | KEYCLOAK.loginDesktop(); 28 | 29 | super.init(); 30 | } 31 | } -------------------------------------------------------------------------------- /demos/spring-boot-frontend-javafx/src/main/java/demo/todos/Todo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package demo.todos; 17 | 18 | import lombok.Data; 19 | import lombok.NoArgsConstructor; 20 | import lombok.ToString; 21 | 22 | /** 23 | * @author Thomas Darimont 24 | */ 25 | @Data 26 | @ToString 27 | @NoArgsConstructor 28 | public class Todo { 29 | 30 | private Long id; 31 | 32 | private String name; 33 | 34 | private boolean completed; 35 | } 36 | -------------------------------------------------------------------------------- /demos/spring-boot-frontend-javafx/src/main/java/demo/todos/TodoClient.java: -------------------------------------------------------------------------------- 1 | package demo.todos; 2 | 3 | import org.springframework.cloud.netflix.feign.FeignClient; 4 | import org.springframework.hateoas.Resource; 5 | import org.springframework.hateoas.Resources; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RequestMethod; 8 | 9 | @FeignClient(url = "${todo-backend.server}", configuration = TodoClientConfig.class, name = "localhost") 10 | public interface TodoClient { 11 | 12 | @RequestMapping(method = RequestMethod.GET, value = "/todos/search/my-todos", consumes = "application/json") 13 | Resources> fetchTodos(); 14 | } 15 | -------------------------------------------------------------------------------- /demos/spring-boot-frontend-javafx/src/main/java/demo/todos/TodoClientConfig.java: -------------------------------------------------------------------------------- 1 | package demo.todos; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.http.HttpHeaders; 7 | 8 | import demo.JavaFxFrontendApplication; 9 | import feign.RequestInterceptor; 10 | import feign.RequestTemplate; 11 | 12 | public class TodoClientConfig { 13 | 14 | @Bean 15 | protected RequestInterceptor keycloakSecurityContextRequestInterceptor() { 16 | return new KeycloakSecurityContextRequestInterceptor(); 17 | } 18 | 19 | static class KeycloakSecurityContextRequestInterceptor implements RequestInterceptor { 20 | 21 | @Override 22 | public void apply(RequestTemplate template) { 23 | 24 | try { 25 | String accessToken = JavaFxFrontendApplication.KEYCLOAK.getTokenString(5, TimeUnit.SECONDS); 26 | template.header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken); 27 | } catch (Exception e) { 28 | e.printStackTrace(); 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /demos/spring-boot-frontend-javafx/src/main/java/demo/todos/TodoService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package demo.todos; 17 | 18 | import java.util.List; 19 | 20 | /** 21 | * @author Thomas Darimont 22 | */ 23 | public interface TodoService { 24 | 25 | List findMyTodos(); 26 | } 27 | -------------------------------------------------------------------------------- /demos/spring-boot-frontend-javafx/src/main/java/demo/todos/TodoServiceImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package demo.todos; 17 | 18 | import static java.util.stream.Collectors.toList; 19 | 20 | import java.util.List; 21 | 22 | import org.springframework.hateoas.Resource; 23 | import org.springframework.stereotype.Service; 24 | 25 | import lombok.RequiredArgsConstructor; 26 | 27 | /** 28 | * @author Thomas Darimont 29 | */ 30 | @Service 31 | @RequiredArgsConstructor 32 | class TodoServiceImpl implements TodoService { 33 | 34 | private final TodoClient todoClient; 35 | 36 | @Override 37 | public List findMyTodos() { 38 | 39 | List todos = todoClient.fetchTodos().getContent() // 40 | .stream().map(Resource::getContent).collect(toList()); 41 | 42 | return todos; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /demos/spring-boot-frontend-javafx/src/main/java/demo/todos/ui/TodosView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package demo.todos.ui; 17 | 18 | import de.felixroske.jfxsupport.AbstractFxmlView; 19 | import de.felixroske.jfxsupport.FXMLView; 20 | 21 | /** 22 | * @author Thomas Darimont 23 | */ 24 | @FXMLView(bundle="demo.todos.ui.todos") 25 | public class TodosView extends AbstractFxmlView {} 26 | -------------------------------------------------------------------------------- /demos/spring-boot-frontend-javafx/src/main/java/demo/todos/ui/todos.css: -------------------------------------------------------------------------------- 1 | /* Add custom css rules here */ 2 | 3 | * { 4 | -fx-font-size: 20; 5 | } -------------------------------------------------------------------------------- /demos/spring-boot-frontend-javafx/src/main/java/demo/todos/ui/todos.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 |