From 0291bab4934552c9a4e7955c78a20718b0b49c6d Mon Sep 17 00:00:00 2001 From: Gustavo Martin Morcuende Date: Wed, 20 Jul 2016 20:02:55 +0200 Subject: [PATCH] Spring JPA: new structure --- SpringJava/JPA/pom.xml | 390 +--- SpringJava/JPA/spring-jpa-bom/pom.xml | 405 ++++ SpringJava/JPA/spring-jpa-persistence/pom.xml | 131 ++ .../example/context/UsernameThreadContext.java | 26 + .../OffsetDateTimeAttributeConverter.java | 39 + .../de/spring/example/persistence/domain/Ad.java | 150 ++ .../example/persistence/domain/AdDescription.java | 112 ++ .../persistence/domain/audit/MyCustomRevision.java | 35 + .../domain/audit/MyCustomRevisionListener.java | 33 + .../domain/specifications/AdSpectifications.java | 62 + .../repository/AdDescriptionRepository.java | 22 + .../persistence/repository/AdRepository.java | 28 + .../src/main/resources/jpa.properties | 2 + .../spring-configuration/configuration.xml | 15 + .../datasource-configuration.xml | 31 + .../spring-configuration/jpa-configuration.xml | 52 + .../spring-configuration/liquibase/changeLogs.xml | 19 + .../liquibase/ddlChangelog.xml | 52 + .../liquibase/dmlChangelog.xml | 1960 ++++++++++++++++++++ .../spring-configuration/liquibase/liquibase.xml | 18 + .../spring/persistence/example/domain/AdTest.java | 5 + .../resources/datasource-test-configuration.xml | 27 + SpringJava/JPA/spring-jpa-resources/pom.xml | 74 + .../example/rest/controllers/AdController.java | 27 + .../rest/controllers/AdDescriptionController.java | 23 + .../example/rest/handler/UsernameHandler.java | 32 + .../common/exception/NotFoundException.java | 24 + .../controller/RepositoryBasedRestController.java | 156 ++ .../org/resthub/web/controller/RestController.java | 119 ++ .../web/controller/ServiceBasedRestController.java | 146 ++ .../src/main/resources/log4j2.xml | 58 + .../spring-configuration/configuration.xml | 11 + .../spring-configuration/mvc/rest/rest-config.xml | 102 + .../src/main/webapp/WEB-INF/web.xml | 61 + SpringJava/JPA/spring-jpa-services/pom.xml | 36 + .../example/services/AdDescriptionService.java | 12 + .../java/de/spring/example/services/AdService.java | 12 + .../services/impl/AdDescriptionServiceImpl.java | 51 + .../example/services/impl/AdServiceImpl.java | 41 + .../org/resthub/common/service/CrudService.java | 94 + .../resthub/common/service/CrudServiceImpl.java | 138 ++ .../spring-configuration/configuration.xml | 13 + .../example/context/UsernameThreadContext.java | 26 - .../OffsetDateTimeAttributeConverter.java | 39 - .../de/spring/example/persistence/domain/Ad.java | 150 -- .../example/persistence/domain/AdDescription.java | 112 -- .../persistence/domain/audit/MyCustomRevision.java | 35 - .../domain/audit/MyCustomRevisionListener.java | 33 - .../domain/specifications/AdSpectifications.java | 62 - .../repository/AdDescriptionRepository.java | 22 - .../persistence/repository/AdRepository.java | 28 - .../example/rest/controllers/AdController.java | 27 - .../rest/controllers/AdDescriptionController.java | 23 - .../example/rest/handler/UsernameHandler.java | 32 - .../example/services/AdDescriptionService.java | 12 - .../java/de/spring/example/services/AdService.java | 12 - .../services/impl/AdDescriptionServiceImpl.java | 51 - .../example/services/impl/AdServiceImpl.java | 41 - .../common/exception/NotFoundException.java | 24 - .../org/resthub/common/service/CrudService.java | 94 - .../resthub/common/service/CrudServiceImpl.java | 138 -- .../controller/RepositoryBasedRestController.java | 156 -- .../org/resthub/web/controller/RestController.java | 119 -- .../web/controller/ServiceBasedRestController.java | 146 -- SpringJava/JPA/src/main/resources/jpa.properties | 2 - SpringJava/JPA/src/main/resources/log4j2.xml | 58 - .../datasource-configuration.xml | 31 - .../spring-configuration/jpa-configuration.xml | 52 - .../spring-configuration/liquibase/changeLogs.xml | 19 - .../liquibase/ddlChangelog.xml | 52 - .../liquibase/dmlChangelog.xml | 1960 -------------------- .../spring-configuration/liquibase/liquibase.xml | 18 - .../spring-configuration/mvc/rest/rest-config.xml | 102 - .../spring-configuration/spring-configuration.xml | 15 - SpringJava/JPA/src/main/webapp/WEB-INF/web.xml | 61 - .../spring/persistence/example/domain/AdTest.java | 5 - .../resources/datasource-test-configuration.xml | 27 - 77 files changed, 4462 insertions(+), 4166 deletions(-) create mode 100644 SpringJava/JPA/spring-jpa-bom/pom.xml create mode 100644 SpringJava/JPA/spring-jpa-persistence/pom.xml create mode 100644 SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/context/UsernameThreadContext.java create mode 100644 SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/converters/OffsetDateTimeAttributeConverter.java create mode 100644 SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/domain/Ad.java create mode 100644 SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/domain/AdDescription.java create mode 100644 SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/domain/audit/MyCustomRevision.java create mode 100644 SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/domain/audit/MyCustomRevisionListener.java create mode 100644 SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/domain/specifications/AdSpectifications.java create mode 100644 SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/repository/AdDescriptionRepository.java create mode 100644 SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/repository/AdRepository.java create mode 100644 SpringJava/JPA/spring-jpa-persistence/src/main/resources/jpa.properties create mode 100644 SpringJava/JPA/spring-jpa-persistence/src/main/resources/spring-configuration/configuration.xml create mode 100644 SpringJava/JPA/spring-jpa-persistence/src/main/resources/spring-configuration/datasource-configuration.xml create mode 100644 SpringJava/JPA/spring-jpa-persistence/src/main/resources/spring-configuration/jpa-configuration.xml create mode 100644 SpringJava/JPA/spring-jpa-persistence/src/main/resources/spring-configuration/liquibase/changeLogs.xml create mode 100644 SpringJava/JPA/spring-jpa-persistence/src/main/resources/spring-configuration/liquibase/ddlChangelog.xml create mode 100644 SpringJava/JPA/spring-jpa-persistence/src/main/resources/spring-configuration/liquibase/dmlChangelog.xml create mode 100644 SpringJava/JPA/spring-jpa-persistence/src/main/resources/spring-configuration/liquibase/liquibase.xml create mode 100644 SpringJava/JPA/spring-jpa-persistence/src/test/java/de/spring/persistence/example/domain/AdTest.java create mode 100644 SpringJava/JPA/spring-jpa-persistence/src/test/resources/datasource-test-configuration.xml create mode 100644 SpringJava/JPA/spring-jpa-resources/pom.xml create mode 100644 SpringJava/JPA/spring-jpa-resources/src/main/java/de/spring/example/rest/controllers/AdController.java create mode 100644 SpringJava/JPA/spring-jpa-resources/src/main/java/de/spring/example/rest/controllers/AdDescriptionController.java create mode 100644 SpringJava/JPA/spring-jpa-resources/src/main/java/de/spring/example/rest/handler/UsernameHandler.java create mode 100644 SpringJava/JPA/spring-jpa-resources/src/main/java/org/resthub/common/exception/NotFoundException.java create mode 100644 SpringJava/JPA/spring-jpa-resources/src/main/java/org/resthub/web/controller/RepositoryBasedRestController.java create mode 100644 SpringJava/JPA/spring-jpa-resources/src/main/java/org/resthub/web/controller/RestController.java create mode 100644 SpringJava/JPA/spring-jpa-resources/src/main/java/org/resthub/web/controller/ServiceBasedRestController.java create mode 100644 SpringJava/JPA/spring-jpa-resources/src/main/resources/log4j2.xml create mode 100644 SpringJava/JPA/spring-jpa-resources/src/main/resources/spring-configuration/configuration.xml create mode 100644 SpringJava/JPA/spring-jpa-resources/src/main/resources/spring-configuration/mvc/rest/rest-config.xml create mode 100644 SpringJava/JPA/spring-jpa-resources/src/main/webapp/WEB-INF/web.xml create mode 100644 SpringJava/JPA/spring-jpa-services/pom.xml create mode 100644 SpringJava/JPA/spring-jpa-services/src/main/java/de/spring/example/services/AdDescriptionService.java create mode 100644 SpringJava/JPA/spring-jpa-services/src/main/java/de/spring/example/services/AdService.java create mode 100644 SpringJava/JPA/spring-jpa-services/src/main/java/de/spring/example/services/impl/AdDescriptionServiceImpl.java create mode 100644 SpringJava/JPA/spring-jpa-services/src/main/java/de/spring/example/services/impl/AdServiceImpl.java create mode 100644 SpringJava/JPA/spring-jpa-services/src/main/java/org/resthub/common/service/CrudService.java create mode 100644 SpringJava/JPA/spring-jpa-services/src/main/java/org/resthub/common/service/CrudServiceImpl.java create mode 100644 SpringJava/JPA/spring-jpa-services/src/main/resources/spring-configuration/configuration.xml delete mode 100644 SpringJava/JPA/src/main/java/de/spring/example/context/UsernameThreadContext.java delete mode 100644 SpringJava/JPA/src/main/java/de/spring/example/persistence/converters/OffsetDateTimeAttributeConverter.java delete mode 100644 SpringJava/JPA/src/main/java/de/spring/example/persistence/domain/Ad.java delete mode 100644 SpringJava/JPA/src/main/java/de/spring/example/persistence/domain/AdDescription.java delete mode 100644 SpringJava/JPA/src/main/java/de/spring/example/persistence/domain/audit/MyCustomRevision.java delete mode 100644 SpringJava/JPA/src/main/java/de/spring/example/persistence/domain/audit/MyCustomRevisionListener.java delete mode 100644 SpringJava/JPA/src/main/java/de/spring/example/persistence/domain/specifications/AdSpectifications.java delete mode 100644 SpringJava/JPA/src/main/java/de/spring/example/persistence/repository/AdDescriptionRepository.java delete mode 100644 SpringJava/JPA/src/main/java/de/spring/example/persistence/repository/AdRepository.java delete mode 100644 SpringJava/JPA/src/main/java/de/spring/example/rest/controllers/AdController.java delete mode 100644 SpringJava/JPA/src/main/java/de/spring/example/rest/controllers/AdDescriptionController.java delete mode 100644 SpringJava/JPA/src/main/java/de/spring/example/rest/handler/UsernameHandler.java delete mode 100644 SpringJava/JPA/src/main/java/de/spring/example/services/AdDescriptionService.java delete mode 100644 SpringJava/JPA/src/main/java/de/spring/example/services/AdService.java delete mode 100644 SpringJava/JPA/src/main/java/de/spring/example/services/impl/AdDescriptionServiceImpl.java delete mode 100644 SpringJava/JPA/src/main/java/de/spring/example/services/impl/AdServiceImpl.java delete mode 100644 SpringJava/JPA/src/main/java/org/resthub/common/exception/NotFoundException.java delete mode 100644 SpringJava/JPA/src/main/java/org/resthub/common/service/CrudService.java delete mode 100644 SpringJava/JPA/src/main/java/org/resthub/common/service/CrudServiceImpl.java delete mode 100644 SpringJava/JPA/src/main/java/org/resthub/web/controller/RepositoryBasedRestController.java delete mode 100644 SpringJava/JPA/src/main/java/org/resthub/web/controller/RestController.java delete mode 100644 SpringJava/JPA/src/main/java/org/resthub/web/controller/ServiceBasedRestController.java delete mode 100644 SpringJava/JPA/src/main/resources/jpa.properties delete mode 100644 SpringJava/JPA/src/main/resources/log4j2.xml delete mode 100644 SpringJava/JPA/src/main/resources/spring-configuration/datasource-configuration.xml delete mode 100644 SpringJava/JPA/src/main/resources/spring-configuration/jpa-configuration.xml delete mode 100644 SpringJava/JPA/src/main/resources/spring-configuration/liquibase/changeLogs.xml delete mode 100644 SpringJava/JPA/src/main/resources/spring-configuration/liquibase/ddlChangelog.xml delete mode 100644 SpringJava/JPA/src/main/resources/spring-configuration/liquibase/dmlChangelog.xml delete mode 100644 SpringJava/JPA/src/main/resources/spring-configuration/liquibase/liquibase.xml delete mode 100644 SpringJava/JPA/src/main/resources/spring-configuration/mvc/rest/rest-config.xml delete mode 100644 SpringJava/JPA/src/main/resources/spring-configuration/spring-configuration.xml delete mode 100644 SpringJava/JPA/src/main/webapp/WEB-INF/web.xml delete mode 100644 SpringJava/JPA/src/test/java/de/spring/persistence/example/domain/AdTest.java delete mode 100644 SpringJava/JPA/src/test/resources/datasource-test-configuration.xml diff --git a/SpringJava/JPA/pom.xml b/SpringJava/JPA/pom.xml index 0faca72..98fd27f 100644 --- a/SpringJava/JPA/pom.xml +++ b/SpringJava/JPA/pom.xml @@ -3,9 +3,9 @@ 4.0.0 de.spring.jpa spring-jpa - war 1.0-SNAPSHOT - spring-jpa + pom + SPRING JPA https://gumartinm.name/ JPA Spring Framework @@ -17,385 +17,11 @@ https://git.gumartinm.name/Spring/JPA - - UTF-8 - UTF-8 - 4.3.0.RELEASE - 4.1.3 - + + spring-jpa-bom + spring-jpa-persistence + spring-jpa-services + spring-jpa-resources + - - - release - - release - - - true - - - - - - - - org.apache.logging.log4j - log4j-slf4j-impl - 2.6.1 - - - - org.apache.logging.log4j - log4j-core - 2.6.1 - - - - org.slf4j - jcl-over-slf4j - 1.7.21 - - - - org.springframework - spring-context - ${spring.version} - - - - commons-logging - commons-logging - - - - - org.springframework - spring-webmvc - ${spring.version} - - - commons-logging - commons-logging - - - - - org.springframework - spring-oxm - ${spring.version} - - - commons-logging - commons-logging - - - - - javax.inject - javax.inject - 1 - - - - cglib - cglib - 2.2.2 - - - - - - org.springframework - spring-orm - ${spring.version} - - - commons-logging - commons-logging - - - - - - org.springframework.data - spring-data-jpa - 1.10.2.RELEASE - - - org.springframework - spring-beans - - - org.springframework - spring-jdbc - - - org.springframework - spring-orm - - - org.springframework - spring-core - - - org.springframework - spring-aop - - - org.springframework - spring-context - - - commons-logging - commons-logging - - - - - - org.hibernate - hibernate-entitymanager - 5.2.1.Final - - - - - org.hibernate - hibernate-envers - 5.2.1.Final - - - - - javax.servlet - javax.servlet-api - 4.0.0-b01 - provided - - - - - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - 2.8.0.rc2 - - - - - - javax.validation - validation-api - 1.1.0.Final - - - org.hibernate - hibernate-validator - 5.2.4.Final - - - - - com.querydsl - querydsl-apt - ${querydsl.version} - - - com.querydsl - querydsl-jpa - ${querydsl.version} - - - - - org.liquibase - liquibase-core - 3.5.1 - - - - - junit - junit - 4.12 - test - - - org.springframework - spring-test - ${spring.version} - test - - - commons-logging - commons-logging - - - - - org.mockito - mockito-core - 2.0.11-beta - test - - - com.h2database - h2 - 1.4.192 - test - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.3 - - 1.8 - 1.8 - ${project.build.sourceEncoding} - - - - org.apache.maven.plugins - maven-resources-plugin - 2.7 - - ${project.build.sourceEncoding} - - - - org.apache.maven.plugins - maven-jar-plugin - 2.4 - - - - ${project.description} - ${project.version} - ${project.organization.name} - ${project.description} - ${project.version} - ${project.organization.name} - - - - - - - - com.mysema.maven - apt-maven-plugin - 1.0.4 - - - - process - - - ${project.build.directory}/generated-sources/querydsl - com.querydsl.apt.jpa.JPAAnnotationProcessor - - - - - - - org.codehaus.mojo - build-helper-maven-plugin - 1.11 - - - add-source - generate-sources - - add-source - - - - ${project.build.directory}/generated-sources/querydsl - - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.18.1 - - - **/*IntegrationTest.java - - - - - org.apache.maven.plugins - maven-failsafe-plugin - 2.18.1 - - - - integration-test - verify - - - - - - **/*IntegrationTest.java - - - - - org.apache.maven.plugins - maven-war-plugin - 2.6 - - - - true - src/main/webapp - - WEB-INF/web.xml - - - - - - - diff --git a/SpringJava/JPA/spring-jpa-bom/pom.xml b/SpringJava/JPA/spring-jpa-bom/pom.xml new file mode 100644 index 0000000..5745d50 --- /dev/null +++ b/SpringJava/JPA/spring-jpa-bom/pom.xml @@ -0,0 +1,405 @@ + + + 4.0.0 + + + de.spring.jpa + spring-jpa + 1.0-SNAPSHOT + + + spring-jpa-bom + pom + SPRING JPA BOM + http://gumartinm.name + + Spring JPA BOM example. + + + Gustavo Martin Morcuende + http://www.gumartinm.name + + + scm:git:http://git.gumartinm.name/JavaForFun + http://git.gumartinm.name/JavaForFun + + + + UTF-8 + UTF-8 + 4.3.0.RELEASE + 4.1.3 + + + + + release + + release + + + true + + + + + + + + org.apache.logging.log4j + log4j-slf4j-impl + 2.6.1 + + + + org.apache.logging.log4j + log4j-core + 2.6.1 + + + + org.slf4j + jcl-over-slf4j + 1.7.21 + + + + javax.inject + javax.inject + 1 + + + + cglib + cglib + 2.2.2 + + + + + junit + junit + 4.12 + test + + + org.mockito + mockito-core + 2.0.43-beta + test + + + + + + org.springframework + spring-context + ${spring.version} + + + + commons-logging + commons-logging + + + + + + + org.springframework + spring-webmvc + ${spring.version} + + + commons-logging + commons-logging + + + + + org.springframework + spring-oxm + ${spring.version} + + + commons-logging + commons-logging + + + + + + + + javax.servlet + javax.servlet-api + 4.0.0-b01 + provided + + + + + com.fasterxml.jackson.core + jackson-databind + 2.6.4 + + + + + + org.springframework + spring-orm + ${spring.version} + + + commons-logging + commons-logging + + + + + + org.springframework.data + spring-data-jpa + 1.10.2.RELEASE + + + org.springframework + spring-beans + + + org.springframework + spring-jdbc + + + org.springframework + spring-orm + + + org.springframework + spring-core + + + org.springframework + spring-aop + + + org.springframework + spring-context + + + commons-logging + commons-logging + + + + + + org.hibernate + hibernate-entitymanager + 5.2.1.Final + + + + + org.hibernate + hibernate-envers + 5.2.1.Final + + + + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + 2.8.0.rc2 + + + + + + javax.validation + validation-api + 1.1.0.Final + + + org.hibernate + hibernate-validator + 5.2.4.Final + + + + + + com.querydsl + querydsl-apt + ${querydsl.version} + + + com.querydsl + querydsl-jpa + ${querydsl.version} + + + + + org.liquibase + liquibase-core + 3.5.1 + + + + + org.springframework + spring-test + ${spring.version} + test + + + + commons-logging + commons-logging + + + + + com.h2database + h2 + 1.4.192 + test + + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.19.1 + + + org.apache.maven.plugins + maven-failsafe-plugin + 2.19.1 + + + + + com.mysema.maven + apt-maven-plugin + 1.0.4 + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.11 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + 1.8 + 1.8 + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-resources-plugin + 2.7 + + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-jar-plugin + 2.6 + + + + ${project.description} + ${project.version} + ${project.organization.name} + ${project.description} + ${project.version} + ${project.organization.name} + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + **/*IntegrationTest.java + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + + integration-test + verify + + + + + + **/*IntegrationTest.java + + + + + + diff --git a/SpringJava/JPA/spring-jpa-persistence/pom.xml b/SpringJava/JPA/spring-jpa-persistence/pom.xml new file mode 100644 index 0000000..ac9eeda --- /dev/null +++ b/SpringJava/JPA/spring-jpa-persistence/pom.xml @@ -0,0 +1,131 @@ + + 4.0.0 + + + de.spring.jpa + spring-jpa-bom + 1.0-SNAPSHOT + + + spring-jpa-persistence + SPRING JPA PERSISTENCE + https://gumartinm.name/ + JPA Spring Framework. Persistence. + + + + + + + + org.springframework + spring-orm + + + org.springframework.data + spring-data-jpa + + + org.hibernate + hibernate-entitymanager + + + + + org.hibernate + hibernate-envers + + + + + javax.validation + validation-api + + + org.hibernate + hibernate-validator + + + + + + com.fasterxml.jackson.core + jackson-databind + + + + + com.querydsl + querydsl-apt + + + com.querydsl + querydsl-jpa + + + + + org.liquibase + liquibase-core + + + + + org.springframework + spring-test + test + + + com.h2database + h2 + test + + + + + + + + com.mysema.maven + apt-maven-plugin + + + + process + + + ${project.build.directory}/generated-sources/querydsl + com.querydsl.apt.jpa.JPAAnnotationProcessor + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add-source + generate-sources + + add-source + + + + ${project.build.directory}/generated-sources/querydsl + + + + + + + + diff --git a/SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/context/UsernameThreadContext.java b/SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/context/UsernameThreadContext.java new file mode 100644 index 0000000..4d698ee --- /dev/null +++ b/SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/context/UsernameThreadContext.java @@ -0,0 +1,26 @@ +package de.spring.example.context; + +import javax.inject.Named; + +import org.springframework.util.Assert; + +@Named("userNameThreadContext") +public class UsernameThreadContext { + public static final String USERNAME_HEADER = "USERNAME"; + + private final ThreadLocal contextHolder = new ThreadLocal<>(); + + public void setUsername(String username) { + Assert.notNull(username); + + contextHolder.set(username); + } + + public String getUsername() { + return contextHolder.get(); + } + + public void clearUsername() { + contextHolder.remove(); + } +} diff --git a/SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/converters/OffsetDateTimeAttributeConverter.java b/SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/converters/OffsetDateTimeAttributeConverter.java new file mode 100644 index 0000000..30ab6bb --- /dev/null +++ b/SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/converters/OffsetDateTimeAttributeConverter.java @@ -0,0 +1,39 @@ +package de.spring.example.persistence.converters; + +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; + +import javax.persistence.AttributeConverter; +import javax.persistence.Converter; + +@Converter(autoApply = true) +public class OffsetDateTimeAttributeConverter implements AttributeConverter { + + @Override + public Timestamp convertToDatabaseColumn(OffsetDateTime offsetDateTime) { + Timestamp timestamp = null; + + if (offsetDateTime != null) { + timestamp = Timestamp.valueOf(offsetDateTime.toLocalDateTime()); + } + + return timestamp; + } + + @Override + public OffsetDateTime convertToEntityAttribute(Timestamp sqlTimestamp) { + OffsetDateTime offsetDateTime = null; + + if (sqlTimestamp != null) { + final LocalDateTime localDateTime = sqlTimestamp.toLocalDateTime(); + final ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.systemDefault()); + offsetDateTime = zonedDateTime.toOffsetDateTime(); + } + + return offsetDateTime; + } + +} diff --git a/SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/domain/Ad.java b/SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/domain/Ad.java new file mode 100644 index 0000000..0f91253 --- /dev/null +++ b/SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/domain/Ad.java @@ -0,0 +1,150 @@ +package de.spring.example.persistence.domain; + +import java.io.Serializable; +import java.time.OffsetDateTime; +import java.util.Set; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Convert; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +//import javax.persistence.NamedNativeQueries; +//import javax.persistence.NamedNativeQuery; +//import javax.persistence.NamedQueries; +//import javax.persistence.NamedQuery; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import javax.validation.constraints.Max; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +import org.hibernate.envers.Audited; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.fasterxml.jackson.annotation.ObjectIdGenerators; + +import de.spring.example.persistence.converters.OffsetDateTimeAttributeConverter; + +@Entity +@Audited(withModifiedFlag=true) +@Table(name="ad", schema="mybatis_example") +@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="jsonId") +// 1. Named query is JPL. It is portable. +// 2. Instead of annotating the domain class we should be using @Query annotation at the query method +// because it should be cleaner :) +// So you'd better use @Query. +//http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.at-query +//See: de.spring.persistence.example.repository.AdRepository +//@NamedQueries( +// { +// @NamedQuery( +// name="Ad.findByIdQuery", +// query="select a from Ad a where a.id = :id) +// } +// +//) +// 1. Native query IS NOT JPL. It is not portable and it is written directly in the native language +// of the store. We can use special features at the cost of portability. +// 2. Instead of annotating the domain class we should be using @Query annotation at the query method +// because it should be cleaner :) +// So you'd better use @Query. +// http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.at-query +// See: de.spring.persistence.example.repository.AdRepository +//@NamedNativeQueries( +// { +// @NamedNativeQuery( +// name="Ad.findByIdNativeQuery", +// query="SELECT * FROM ad WHERE ad.id = :id", +// resultClass=Ad.class) +// } +//) +public class Ad implements Serializable { + + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name="id", updatable=false, nullable=false) + private Long id; + + @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL) + @JoinColumn(name = "ad_id", nullable = false) + private Set adDescriptions; + + @Max(60) + @Column(name="company_id") + private Long companyId; + + @Max(40) + @Column(name="company_categ_id") + private Long companyCategId; + + @Size(min=2, max=255) + @Column(name="ad_mobile_image") + private String adMobileImage; + + @NotNull + @Convert(converter=OffsetDateTimeAttributeConverter.class) + @Column(name="created_at", nullable=false) + @JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ssZ") + private OffsetDateTime createdAt; + + @NotNull + @Convert(converter=OffsetDateTimeAttributeConverter.class) + @Column(name="updated_at", nullable = false) + @JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ssZ") + private OffsetDateTime updatedAt; + + // It will be used by JPA when filling the property fields with data coming from data base. + protected Ad() { + + } + + // It will be used by my code (for example by Unit Tests) + public Ad(Long id, Set adDescriptions, Long companyId, Long companyCategId, String adMobileImage, + OffsetDateTime createdAt, OffsetDateTime updatedAt) { + this.id = id; + this.adDescriptions = adDescriptions; + this.companyId = companyId; + this.companyCategId = companyCategId; + this.adMobileImage = adMobileImage; + this.createdAt = createdAt; + this.updatedAt = updatedAt; + } + + /** + * WARNING: JPA REQUIRES GETTERS!!! + */ + + public Long getId() { + return id; + } + + public Set getAdDescriptions() { + return adDescriptions; + } + + public Long getCompanyId() { + return companyId; + } + + public Long getCompanyCategId() { + return companyCategId; + } + + public String getAdMobileImage() { + return adMobileImage; + } + + public OffsetDateTime getCreatedAt() { + return createdAt; + } + + public OffsetDateTime getUpdatedAt() { + return updatedAt; + } +} diff --git a/SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/domain/AdDescription.java b/SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/domain/AdDescription.java new file mode 100644 index 0000000..2142b39 --- /dev/null +++ b/SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/domain/AdDescription.java @@ -0,0 +1,112 @@ +package de.spring.example.persistence.domain; + +import java.io.Serializable; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import javax.validation.constraints.Max; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +import org.hibernate.envers.Audited; + +import com.fasterxml.jackson.annotation.JsonIdentityInfo; +import com.fasterxml.jackson.annotation.ObjectIdGenerators; + +@Entity +@Audited +@Table(name="ad_description", schema="mybatis_example") +@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="jsonId") +public class AdDescription implements Serializable { + + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name="id", updatable=false, nullable=false) + private Long id; + + @ManyToOne(fetch=FetchType.LAZY, cascade = CascadeType.ALL, optional=true) + @JoinColumn(name="ad_id", nullable=false, updatable = false, insertable = false, referencedColumnName="id") + private Ad ad; + + @NotNull + @Max(60) + @Column(name="laguage_id") + private Long languageId; + + @NotNull + @Size(min=2, max=255) + @Column(name="ad_name") + private String adName; + + @NotNull + @Size(min=2, max=255) + @Column(name="ad_description") + private String adDescription; + + @NotNull + @Size(min=2, max=500) + @Column(name="ad_mobile_text") + private String adMobileText; + + @NotNull + @Size(min=2, max=3000) + @Column(name="ad_link") + private String adLink; + + // It will be used by JPA when filling the property fields with data coming from data base. + protected AdDescription() { + + } + + // It will be used by my code (for example by Unit Tests) + public AdDescription(Long id, Ad ad, Long languageId, String adName, String adDescription, + String adMobileText, String adLink) { + this.id = id; + this.ad = ad; + this.languageId = languageId; + this.adName = adName; + this.adDescription = adDescription; + this.adMobileText = adMobileText; + this.adLink = adLink; + } + + /** + * WARNING: JPA REQUIRES GETTERS!!! + */ + + public Long getId() { + return id; + } + + public Ad getAd() { + return ad; + } + + public Long getLanguageId() { + return languageId; + } + + public String getAdName() { + return adName; + } + + public String getAdDescription() { + return adDescription; + } + + public String getAdMobileText() { + return adMobileText; + } + + public String getAdLink() { + return adLink; + } +} diff --git a/SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/domain/audit/MyCustomRevision.java b/SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/domain/audit/MyCustomRevision.java new file mode 100644 index 0000000..f8ebfe9 --- /dev/null +++ b/SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/domain/audit/MyCustomRevision.java @@ -0,0 +1,35 @@ +package de.spring.example.persistence.domain.audit; + +import javax.persistence.Entity; +import javax.persistence.Table; + +import org.hibernate.envers.RevisionEntity; + +@Entity +@RevisionEntity(MyCustomRevisionListener.class) +@Table(name="CUSTOM_REVISION", schema="mybatis_example") +public class MyCustomRevision { + private String username; + + // It will be used by JPA when filling the property fields with data coming from data base. + protected MyCustomRevision() { + + } + + // It will be used by my code (for example by Unit Tests) + public MyCustomRevision(String username) { + this.username = username; + } + + /** + * WARNING: JPA REQUIRES GETTERS!!! + */ + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } +} diff --git a/SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/domain/audit/MyCustomRevisionListener.java b/SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/domain/audit/MyCustomRevisionListener.java new file mode 100644 index 0000000..79e3bf2 --- /dev/null +++ b/SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/domain/audit/MyCustomRevisionListener.java @@ -0,0 +1,33 @@ +package de.spring.example.persistence.domain.audit; + +import org.hibernate.envers.RevisionListener; + +import de.spring.example.context.UsernameThreadContext; + +public class MyCustomRevisionListener implements RevisionListener { + private final UsernameThreadContext userNameThreadContext; + + public MyCustomRevisionListener(UsernameThreadContext userNameThreadContext) { + this.userNameThreadContext = userNameThreadContext; + } + + @Override + public void newRevision(Object revisionEntity) { + MyCustomRevision myCustomRevision = (MyCustomRevision) revisionEntity; + + final String username = getSafeUsername(); + myCustomRevision.setUsername(username); + + } + + private String getSafeUsername() { + String userName = userNameThreadContext.getUsername(); + + if (userName == null) { + userName = "NO_USER"; + } + + return userName; + } + +} diff --git a/SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/domain/specifications/AdSpectifications.java b/SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/domain/specifications/AdSpectifications.java new file mode 100644 index 0000000..2cadb54 --- /dev/null +++ b/SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/domain/specifications/AdSpectifications.java @@ -0,0 +1,62 @@ +package de.spring.example.persistence.domain.specifications; + +import java.time.LocalDate; + +//import javax.persistence.criteria.CriteriaBuilder; +//import javax.persistence.criteria.CriteriaQuery; +//import javax.persistence.criteria.Predicate; +//import javax.persistence.criteria.Root; + +import org.springframework.data.jpa.domain.Specification; + +import de.spring.example.persistence.domain.Ad; + +public class AdSpectifications { + +// public static Specification createdToday() { +// return new Specification() { +// +// @Override +// public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { +// final LocalDate date = LocalDate.now(); +// +// return cb.equal(root.get("createdAt"), date); +// } +// +// }; +// +// } + + /** + * The same using lambda expressions + */ + public static Specification createdToday() { + return (root, query, cb) -> { + final LocalDate date = LocalDate.now(); + + return cb.equal(root.get("createdAt"), date); + }; + } + +// public static Specification mobileImage(String image) { +// return new Specification() { +// +// @Override +// public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { +// +// return cb.equal(root.get("adMobileImage"), image); +// } +// +// }; +// +// } + + /** + * The same using lambda expressions + */ + public static Specification mobileImage(String image) { + return (root, query, cb) -> { + return cb.equal(root.get("adMobileImage"), image); + }; + } +} diff --git a/SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/repository/AdDescriptionRepository.java b/SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/repository/AdDescriptionRepository.java new file mode 100644 index 0000000..4b4e6fc --- /dev/null +++ b/SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/repository/AdDescriptionRepository.java @@ -0,0 +1,22 @@ +package de.spring.example.persistence.repository; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.querydsl.QueryDslPredicateExecutor; +import org.springframework.data.repository.PagingAndSortingRepository; + +import de.spring.example.persistence.domain.Ad; +import de.spring.example.persistence.domain.AdDescription; + +/** + * By default org.springframework.data.jpa.repository.support.SimpleJpaRepository + * will be the implementation for this interface. + * + * Be careful with @Transactional. SimpleJpaRepository has annotated methods. + * + */ +public interface AdDescriptionRepository extends PagingAndSortingRepository, QueryDslPredicateExecutor { + + // Custom Query method (useful when the offered methods by PagingAndSortingRepository are not enough) + Page findByAd(Ad ad, Pageable pageable); +} diff --git a/SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/repository/AdRepository.java b/SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/repository/AdRepository.java new file mode 100644 index 0000000..bc73359 --- /dev/null +++ b/SpringJava/JPA/spring-jpa-persistence/src/main/java/de/spring/example/persistence/repository/AdRepository.java @@ -0,0 +1,28 @@ +package de.spring.example.persistence.repository; + +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.data.repository.query.Param; + +import de.spring.example.persistence.domain.Ad; + +/** + * By default org.springframework.data.jpa.repository.support.SimpleJpaRepository + * will be the implementation for this interface. + * + * Be careful with @Transactional. SimpleJpaRepository has annotated methods. + * + */ +public interface AdRepository extends PagingAndSortingRepository, JpaSpecificationExecutor { + + // Named Native Query (using the native language of the store) It is not portable. + // See de.spring.persistence.example.domain.Ad + @Query(value="SELECT * FROM ad WHERE ad.id = :id", nativeQuery=true) + Ad findByIdNativeQuery(@Param("id") Long id); + + // Named Query (using JPL) It is portable. + // See de.spring.persistence.example.domain.Ad + @Query("select a from Ad a where a.id = :id") + Ad findByIdQuery(@Param("id") Long id); +} diff --git a/SpringJava/JPA/spring-jpa-persistence/src/main/resources/jpa.properties b/SpringJava/JPA/spring-jpa-persistence/src/main/resources/jpa.properties new file mode 100644 index 0000000..9f628d3 --- /dev/null +++ b/SpringJava/JPA/spring-jpa-persistence/src/main/resources/jpa.properties @@ -0,0 +1,2 @@ +jpa.dialect=org.hibernate.dialect.MySQL5Dialect +jpa.show_sql=false \ No newline at end of file diff --git a/SpringJava/JPA/spring-jpa-persistence/src/main/resources/spring-configuration/configuration.xml b/SpringJava/JPA/spring-jpa-persistence/src/main/resources/spring-configuration/configuration.xml new file mode 100644 index 0000000..5609f29 --- /dev/null +++ b/SpringJava/JPA/spring-jpa-persistence/src/main/resources/spring-configuration/configuration.xml @@ -0,0 +1,15 @@ + + + + + + + + \ No newline at end of file diff --git a/SpringJava/JPA/spring-jpa-persistence/src/main/resources/spring-configuration/datasource-configuration.xml b/SpringJava/JPA/spring-jpa-persistence/src/main/resources/spring-configuration/datasource-configuration.xml new file mode 100644 index 0000000..6b5500c --- /dev/null +++ b/SpringJava/JPA/spring-jpa-persistence/src/main/resources/spring-configuration/datasource-configuration.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + diff --git a/SpringJava/JPA/spring-jpa-persistence/src/main/resources/spring-configuration/jpa-configuration.xml b/SpringJava/JPA/spring-jpa-persistence/src/main/resources/spring-configuration/jpa-configuration.xml new file mode 100644 index 0000000..b460a27 --- /dev/null +++ b/SpringJava/JPA/spring-jpa-persistence/src/main/resources/spring-configuration/jpa-configuration.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + _AUDITED + REVISION + REVISION_TYPE + true + org.hibernate.envers.strategy.ValidityAuditStrategy + REVISION_END + true + REVISION_END_TIMESTAMP + _MODIFIED + + + + + + + diff --git a/SpringJava/JPA/spring-jpa-persistence/src/main/resources/spring-configuration/liquibase/changeLogs.xml b/SpringJava/JPA/spring-jpa-persistence/src/main/resources/spring-configuration/liquibase/changeLogs.xml new file mode 100644 index 0000000..4d558c2 --- /dev/null +++ b/SpringJava/JPA/spring-jpa-persistence/src/main/resources/spring-configuration/liquibase/changeLogs.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + diff --git a/SpringJava/JPA/spring-jpa-persistence/src/main/resources/spring-configuration/liquibase/ddlChangelog.xml b/SpringJava/JPA/spring-jpa-persistence/src/main/resources/spring-configuration/liquibase/ddlChangelog.xml new file mode 100644 index 0000000..e8fbd91 --- /dev/null +++ b/SpringJava/JPA/spring-jpa-persistence/src/main/resources/spring-configuration/liquibase/ddlChangelog.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SpringJava/JPA/spring-jpa-persistence/src/main/resources/spring-configuration/liquibase/dmlChangelog.xml b/SpringJava/JPA/spring-jpa-persistence/src/main/resources/spring-configuration/liquibase/dmlChangelog.xml new file mode 100644 index 0000000..0f07094 --- /dev/null +++ b/SpringJava/JPA/spring-jpa-persistence/src/main/resources/spring-configuration/liquibase/dmlChangelog.xml @@ -0,0 +1,1960 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SpringJava/JPA/spring-jpa-persistence/src/main/resources/spring-configuration/liquibase/liquibase.xml b/SpringJava/JPA/spring-jpa-persistence/src/main/resources/spring-configuration/liquibase/liquibase.xml new file mode 100644 index 0000000..705fc46 --- /dev/null +++ b/SpringJava/JPA/spring-jpa-persistence/src/main/resources/spring-configuration/liquibase/liquibase.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/SpringJava/JPA/spring-jpa-persistence/src/test/java/de/spring/persistence/example/domain/AdTest.java b/SpringJava/JPA/spring-jpa-persistence/src/test/java/de/spring/persistence/example/domain/AdTest.java new file mode 100644 index 0000000..7fb4c57 --- /dev/null +++ b/SpringJava/JPA/spring-jpa-persistence/src/test/java/de/spring/persistence/example/domain/AdTest.java @@ -0,0 +1,5 @@ +package de.spring.persistence.example.domain; + +public class AdTest { + +} diff --git a/SpringJava/JPA/spring-jpa-persistence/src/test/resources/datasource-test-configuration.xml b/SpringJava/JPA/spring-jpa-persistence/src/test/resources/datasource-test-configuration.xml new file mode 100644 index 0000000..05ca000 --- /dev/null +++ b/SpringJava/JPA/spring-jpa-persistence/src/test/resources/datasource-test-configuration.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + diff --git a/SpringJava/JPA/spring-jpa-resources/pom.xml b/SpringJava/JPA/spring-jpa-resources/pom.xml new file mode 100644 index 0000000..0c3f84f --- /dev/null +++ b/SpringJava/JPA/spring-jpa-resources/pom.xml @@ -0,0 +1,74 @@ + + 4.0.0 + + + + de.spring.jpa + spring-jpa-bom + 1.0-SNAPSHOT + + + spring-jpa-resources + war + SPRING JPA RESOURCES + https://gumartinm.name/ + JPA Spring Framework. Resources. + + + + + de.spring.jpa + spring-jpa-services + 1.0-SNAPSHOT + + + + + org.springframework + spring-webmvc + + + org.springframework + spring-oxm + + + + + javax.servlet + javax.servlet-api + provided + + + + + + + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + + + org.springframework + spring-test + test + + + + diff --git a/SpringJava/JPA/spring-jpa-resources/src/main/java/de/spring/example/rest/controllers/AdController.java b/SpringJava/JPA/spring-jpa-resources/src/main/java/de/spring/example/rest/controllers/AdController.java new file mode 100644 index 0000000..edbf37d --- /dev/null +++ b/SpringJava/JPA/spring-jpa-resources/src/main/java/de/spring/example/rest/controllers/AdController.java @@ -0,0 +1,27 @@ +package de.spring.example.rest.controllers; + +import javax.inject.Inject; + +import org.resthub.web.controller.RepositoryBasedRestController; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import de.spring.example.persistence.domain.Ad; +import de.spring.example.persistence.repository.AdRepository; + +@RestController +@RequestMapping("/ads/") +public class AdController extends RepositoryBasedRestController { + + @Override + @Inject + public void setRepository(AdRepository repository) { + this.repository = repository; + } + + // I do not have to do anything here because all I need is implemented by RepositoryBasedRestController :) + + // @Transactional is implemented by org.springframework.data.jpa.repository.support.SimpleJpaRepository + // By default, SimpleJpaRepository will be automatically implemented by my + // Spring JPA repositories: AdRepository and AdDescriptionRepository. +} diff --git a/SpringJava/JPA/spring-jpa-resources/src/main/java/de/spring/example/rest/controllers/AdDescriptionController.java b/SpringJava/JPA/spring-jpa-resources/src/main/java/de/spring/example/rest/controllers/AdDescriptionController.java new file mode 100644 index 0000000..d3c1849 --- /dev/null +++ b/SpringJava/JPA/spring-jpa-resources/src/main/java/de/spring/example/rest/controllers/AdDescriptionController.java @@ -0,0 +1,23 @@ +package de.spring.example.rest.controllers; + +import javax.inject.Inject; + +import org.resthub.web.controller.ServiceBasedRestController; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import de.spring.example.persistence.domain.AdDescription; +import de.spring.example.services.AdDescriptionService; + +@RestController +@RequestMapping("/ad-descriptions/") +public class AdDescriptionController extends ServiceBasedRestController { + + @Override + @Inject + public void setService(AdDescriptionService adDescriptionService) { + this.service = adDescriptionService; + } + + // I do not have to do anything here because all I need is implemented by ServiceBasedRestController :) +} diff --git a/SpringJava/JPA/spring-jpa-resources/src/main/java/de/spring/example/rest/handler/UsernameHandler.java b/SpringJava/JPA/spring-jpa-resources/src/main/java/de/spring/example/rest/handler/UsernameHandler.java new file mode 100644 index 0000000..9878f3d --- /dev/null +++ b/SpringJava/JPA/spring-jpa-resources/src/main/java/de/spring/example/rest/handler/UsernameHandler.java @@ -0,0 +1,32 @@ +package de.spring.example.rest.handler; + +import javax.inject.Inject; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +import de.spring.example.context.UsernameThreadContext; + +public class UsernameHandler extends HandlerInterceptorAdapter { + private final UsernameThreadContext usernameThreadContext; + + @Inject + public UsernameHandler(UsernameThreadContext userNameThreadContext) { + this.usernameThreadContext = userNameThreadContext; + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) + throws Exception { + final String userName = request.getHeader(UsernameThreadContext.USERNAME_HEADER); + + if (userName != null) { + usernameThreadContext.setUsername(userName); + } else { + usernameThreadContext.clearUsername(); + } + + return super.preHandle(request, response, handler); + } +} diff --git a/SpringJava/JPA/spring-jpa-resources/src/main/java/org/resthub/common/exception/NotFoundException.java b/SpringJava/JPA/spring-jpa-resources/src/main/java/org/resthub/common/exception/NotFoundException.java new file mode 100644 index 0000000..7135761 --- /dev/null +++ b/SpringJava/JPA/spring-jpa-resources/src/main/java/org/resthub/common/exception/NotFoundException.java @@ -0,0 +1,24 @@ +package org.resthub.common.exception; + +/** + * Exception thrown when not result was found (for example findById with null return value) + */ +public class NotFoundException extends RuntimeException { + + public NotFoundException() { + super(); + } + + public NotFoundException(final String message, final Throwable cause) { + super(message, cause); + } + + public NotFoundException(final String message) { + super(message); + } + + public NotFoundException(final Throwable cause) { + super(cause); + } + +} diff --git a/SpringJava/JPA/spring-jpa-resources/src/main/java/org/resthub/web/controller/RepositoryBasedRestController.java b/SpringJava/JPA/spring-jpa-resources/src/main/java/org/resthub/web/controller/RepositoryBasedRestController.java new file mode 100644 index 0000000..2fd4c10 --- /dev/null +++ b/SpringJava/JPA/spring-jpa-resources/src/main/java/org/resthub/web/controller/RepositoryBasedRestController.java @@ -0,0 +1,156 @@ +package org.resthub.web.controller; + +import org.resthub.common.exception.NotFoundException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.util.Assert; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; + +import java.io.Serializable; +import java.util.Set; + +/** + * Abstract REST controller using a repository implementation + *

+ *

+ * You should extend this class when you want to use a 2 layers pattern : Repository and Controller. This is the default + * controller implementation to use if you have no service (also called business) layer. You will be able to transform + * it to a ServiceBasedRestController later easily if needed. + *

+ * + *

Default implementation uses "id" field (usually a Long) in order to identify resources in web request. + * If your want to identity resources by a slug (human readable identifier), your should override findById() method with for example : + * + *

+ * 
+   {@literal @}Override
+   public Sample findById({@literal @}PathVariable String id) {
+        Sample sample = this.repository.findByName(id);
+        if (sample == null) {
+            throw new NotFoundException();
+        }
+        return sample;
+   }
+   
+ * 
+ * + * + * @param Your resource class to manage, maybe an entity or DTO class + * @param Resource id type, usually Long or String + * @param The repository class + * @see ServiceBasedRestController + */ +public abstract class RepositoryBasedRestController + implements RestController { + + protected R repository; + + protected Logger logger = LoggerFactory.getLogger(RepositoryBasedRestController.class); + + /** + * You should override this setter in order to inject your repository with @Inject annotation + * + * @param repository The repository to be injected + */ + public void setRepository(R repository) { + this.repository = repository; + } + + /** + * {@inheritDoc} + */ + @Override + public T create(@RequestBody T resource) { + return (T)this.repository.save(resource); + } + + /** + * {@inheritDoc} + */ + @Override + public T update(@PathVariable ID id, @RequestBody T resource) { + Assert.notNull(id, "id cannot be null"); + + T retrievedResource = this.findById(id); + if (retrievedResource == null) { + throw new NotFoundException(); + } + + return (T)this.repository.save(resource); + } + + /** + * {@inheritDoc} + */ + @Override + public Iterable findAll() { + return repository.findAll(); + } + + /** + * {@inheritDoc} + */ + @Override + public Page findPaginated(@RequestParam(value = "page", required = false, defaultValue = "1") Integer page, + @RequestParam(value = "size", required = false, defaultValue = "10") Integer size, + @RequestParam(value = "direction", required = false, defaultValue = "") String direction, + @RequestParam(value = "properties", required = false) String properties) { + Assert.isTrue(page > 0, "Page index must be greater than 0"); + Assert.isTrue(direction.isEmpty() || direction.equalsIgnoreCase(Sort.Direction.ASC.toString()) || direction.equalsIgnoreCase(Sort.Direction.DESC.toString()), "Direction should be ASC or DESC"); + if(direction.isEmpty()) { + return this.repository.findAll(new PageRequest(page - 1, size)); + } else { + Assert.notNull(properties); + return this.repository.findAll(new PageRequest(page - 1, size, new Sort(Sort.Direction.fromString(direction.toUpperCase()), properties.split(",")))); + } + } + + /** + * {@inheritDoc} + */ + @Override + public T findById(@PathVariable ID id) { + T entity = (T)this.repository.findOne(id); + if (entity == null) { + throw new NotFoundException(); + } + + return entity; + } + + /** + * {@inheritDoc} + */ + @Override + public Iterable findByIds(@RequestParam(value="ids[]") Set ids){ + Assert.notNull(ids, "ids list cannot be null"); + return this.repository.findAll(ids); + } + + /** + * {@inheritDoc} + */ + @Override + public void delete() { + Iterable list = repository.findAll(); + for (T entity : list) { + repository.delete(entity); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void delete(@PathVariable ID id) { + T resource = this.findById(id); + this.repository.delete(resource); + } + +} diff --git a/SpringJava/JPA/spring-jpa-resources/src/main/java/org/resthub/web/controller/RestController.java b/SpringJava/JPA/spring-jpa-resources/src/main/java/org/resthub/web/controller/RestController.java new file mode 100644 index 0000000..9aa9a26 --- /dev/null +++ b/SpringJava/JPA/spring-jpa-resources/src/main/java/org/resthub/web/controller/RestController.java @@ -0,0 +1,119 @@ +package org.resthub.web.controller; + +import org.resthub.common.exception.NotFoundException; +import org.springframework.data.domain.Page; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.*; + +import java.io.Serializable; +import java.util.Set; + +/** + * REST controller interface + * + * @param Your resource POJO to manage, maybe an entity or DTO class + * @param Primary resource identifier at webservice level, usually Long or String + */ +public interface RestController { + + /** + * Create a new resource
+ * REST webservice published : POST / + * + * @param resource The resource to create + * @return CREATED http status code if the request has been correctly processed, with updated resource enclosed in the body, usually with and additional identifier automatically created by the database + */ + @RequestMapping(method = RequestMethod.POST) + @ResponseStatus(HttpStatus.CREATED) + @ResponseBody + T create(@RequestBody T resource); + + /** + * Update an existing resource
+ * REST webservice published : PUT /{id} + * + * @param id The identifier of the resource to update, usually a Long or String identifier. It is explicitely provided in order to handle cases where the identifier could be changed. + * @param resource The resource to update + * @return OK http status code if the request has been correctly processed, with the updated resource enclosed in the body + * @throws NotFoundException + */ + @RequestMapping(value = "{id}", method = RequestMethod.PUT) + @ResponseBody + T update(@PathVariable ID id, @RequestBody T resource); + + /** + * Find all resources, and return the full collection (plain list not paginated)
+ * REST webservice published : GET /?page=no + * + * @return OK http status code if the request has been correctly processed, with the list of all resource enclosed in the body. + * Be careful, this list should be big since it will return ALL resources. In this case, consider using paginated findAll method instead. + */ + @RequestMapping(method = RequestMethod.GET, params = "page=no") + @ResponseBody + Iterable findAll(); + + /** + * Find all resources, and return a paginated and optionaly sorted collection
+ * REST webservice published : GET /search?page=0&size=20 or GET /search?page=0&size=20&direction=desc&properties=name + * + * @param page Page number starting from 0. default to 0 + * @param size Number of resources by pages. default to 10 + * @param direction Optional sort direction, could be "asc" or "desc" + * @param properties Ordered list of comma separeted properies used for sorting resulats. At least one property should be provided if direction is specified + * @return OK http status code if the request has been correctly processed, with the a paginated collection of all resource enclosed in the body. + */ + @RequestMapping(method = RequestMethod.GET) + @ResponseBody + Page findPaginated(@RequestParam(value = "page", required = false, defaultValue = "1") Integer page, + @RequestParam(value = "size", required = false, defaultValue = "10") Integer size, + @RequestParam(value = "direction", required = false, defaultValue = "ASC") String direction, + @RequestParam(value = "properties", required = false) String properties); + + /** + * Find a resource by its identifier
+ * REST webservice published : GET /{id} + * + * @param id The identifier of the resouce to find + * @return OK http status code if the request has been correctly processed, with resource found enclosed in the body + * @throws NotFoundException + */ + @RequestMapping(value = "{id}", method = RequestMethod.GET) + @ResponseBody + T findById(@PathVariable ID id); + + /** + * Find multiple resources by their identifiers
+ * REST webservice published : GET /?ids[]= + *

+ * example : /?ids[]=1&ids[]=2&ids[]=3 + * + * @param ids List of ids to retrieve + * @return OK http status code with list of retrieved resources. Not found resources are ignored: + * no Exception thrown. List is empty if no resource found with any of the given ids. + */ + @RequestMapping(method = RequestMethod.GET, params = "ids[]") + @ResponseBody + Iterable findByIds(@RequestParam(value = "ids[]") Set ids); + + /** + * Delete all resources
+ * REST webservice published : DELETE /
+ * Return No Content http status code if the request has been correctly processed + */ + @RequestMapping(method = RequestMethod.DELETE) + @ResponseStatus(HttpStatus.NO_CONTENT) + void delete(); + + /** + * Delete a resource by its identifier
+ * REST webservice published : DELETE /{id}
+ * Return No Content http status code if the request has been correctly processed + * + * @param id The identifier of the resource to delete + * @throws NotFoundException + */ + @RequestMapping(value = "{id}", method = RequestMethod.DELETE) + @ResponseStatus(HttpStatus.NO_CONTENT) + void delete(@PathVariable ID id); + +} diff --git a/SpringJava/JPA/spring-jpa-resources/src/main/java/org/resthub/web/controller/ServiceBasedRestController.java b/SpringJava/JPA/spring-jpa-resources/src/main/java/org/resthub/web/controller/ServiceBasedRestController.java new file mode 100644 index 0000000..cd93416 --- /dev/null +++ b/SpringJava/JPA/spring-jpa-resources/src/main/java/org/resthub/web/controller/ServiceBasedRestController.java @@ -0,0 +1,146 @@ +package org.resthub.web.controller; + +import java.io.Serializable; +import java.util.Set; + +import org.resthub.common.exception.NotFoundException; +import org.resthub.common.service.CrudService; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.util.Assert; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; + +/** + * Abstract REST controller using a service implementation + *

+ *

You should extend this class when you want to use a 3 layers pattern : Repository, Service and Controller + * If you don't have a real service (also called business layer), consider using RepositoryBasedRestController

+ *

+ *

Default implementation uses "id" field (usually a Long) in order to identify resources in web request. + * If your want to identity resources by a slug (human readable identifier), your should override findById() method with for example : + *

+ *

+ * 
+ * {@literal @}Override
+ * public Sample findById({@literal @}PathVariable String id) {
+ * Sample sample = this.service.findByName(id);
+ * if (sample == null) {
+ * throw new NotFoundException();
+ * }
+ * return sample;
+ * }
+ * 
+ * 
+ * + * @param Your resource class to manage, maybe an entity or DTO class + * @param Resource id type, usually Long or String + * @param The service class + * @see RepositoryBasedRestController + */ +public abstract class ServiceBasedRestController implements + RestController { + + protected S service; + + /** + * You should override this setter in order to inject your service with @Inject annotation + * + * @param service The service to be injected + */ + public void setService(S service) { + this.service = service; + } + + /** + * {@inheritDoc} + */ + @Override + public T create(@RequestBody T resource) { + return (T) this.service.create(resource); + } + + /** + * {@inheritDoc} + */ + @Override + public T update(@PathVariable ID id, @RequestBody T resource) { + Assert.notNull(id, "id cannot be null"); + + T retreivedResource = this.findById(id); + if (retreivedResource == null) { + throw new NotFoundException(); + } + + return (T) this.service.update(resource); + } + + /** + * {@inheritDoc} + */ + @Override + public Iterable findAll() { + return service.findAll(); + } + + /** + * {@inheritDoc} + */ + @Override + public Page findPaginated(@RequestParam(value = "page", required = false, defaultValue = "1") Integer page, + @RequestParam(value = "size", required = false, defaultValue = "10") Integer size, + @RequestParam(value = "direction", required = false, defaultValue = "") String direction, + @RequestParam(value = "properties", required = false) String properties) { + Assert.isTrue(page > 0, "Page index must be greater than 0"); + Assert.isTrue(direction.isEmpty() || direction.equalsIgnoreCase(Sort.Direction.ASC.toString()) || direction.equalsIgnoreCase(Sort.Direction.DESC.toString()), "Direction should be ASC or DESC"); + if (direction.isEmpty()) { + return this.service.findAll(new PageRequest(page - 1, size)); + } else { + Assert.notNull(properties); + return this.service.findAll(new PageRequest(page - 1, size, new Sort(Sort.Direction.fromString(direction.toUpperCase()), properties.split(",")))); + } + } + + /** + * {@inheritDoc} + */ + @Override + public T findById(@PathVariable ID id) { + T resource = (T) this.service.findById(id); + if (resource == null) { + throw new NotFoundException(); + } + + return resource; + } + + /** + * {@inheritDoc} + */ + @Override + public Iterable findByIds(@RequestParam(value = "ids[]") Set ids) { + Assert.notNull(ids, "ids list cannot be null"); + return this.service.findByIds(ids); + } + + + /** + * {@inheritDoc} + */ + @Override + public void delete() { + this.service.deleteAllWithCascade(); + } + + /** + * {@inheritDoc} + */ + @Override + public void delete(@PathVariable ID id) { + T resource = this.findById(id); + this.service.delete(resource); + } +} + diff --git a/SpringJava/JPA/spring-jpa-resources/src/main/resources/log4j2.xml b/SpringJava/JPA/spring-jpa-resources/src/main/resources/log4j2.xml new file mode 100644 index 0000000..eec10be --- /dev/null +++ b/SpringJava/JPA/spring-jpa-resources/src/main/resources/log4j2.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SpringJava/JPA/spring-jpa-resources/src/main/resources/spring-configuration/configuration.xml b/SpringJava/JPA/spring-jpa-resources/src/main/resources/spring-configuration/configuration.xml new file mode 100644 index 0000000..fbd171f --- /dev/null +++ b/SpringJava/JPA/spring-jpa-resources/src/main/resources/spring-configuration/configuration.xml @@ -0,0 +1,11 @@ + + + + \ No newline at end of file diff --git a/SpringJava/JPA/spring-jpa-resources/src/main/resources/spring-configuration/mvc/rest/rest-config.xml b/SpringJava/JPA/spring-jpa-resources/src/main/resources/spring-configuration/mvc/rest/rest-config.xml new file mode 100644 index 0000000..e8cc1a8 --- /dev/null +++ b/SpringJava/JPA/spring-jpa-resources/src/main/resources/spring-configuration/mvc/rest/rest-config.xml @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SpringJava/JPA/spring-jpa-resources/src/main/webapp/WEB-INF/web.xml b/SpringJava/JPA/spring-jpa-resources/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..31173b6 --- /dev/null +++ b/SpringJava/JPA/spring-jpa-resources/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,61 @@ + + + + Spring JPA: example JPA + + + + org.springframework.web.context.ContextLoaderListener + + + + + spring.profiles.default + ${environment.profile} + contextConfigLocation + + classpath*:spring-configuration/*.xml + + + + + + spring-rest + org.springframework.web.servlet.DispatcherServlet + 1 + true + + contextConfigLocation + classpath*:spring-configuration/mvc/rest/*.xml + + + + + spring-rest + + /* + + + + + + OpenEntityManagerInViewFilter + org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter + + + OpenEntityManagerInViewFilter + /* + + + + diff --git a/SpringJava/JPA/spring-jpa-services/pom.xml b/SpringJava/JPA/spring-jpa-services/pom.xml new file mode 100644 index 0000000..18570a6 --- /dev/null +++ b/SpringJava/JPA/spring-jpa-services/pom.xml @@ -0,0 +1,36 @@ + + 4.0.0 + + + de.spring.jpa + spring-jpa-bom + 1.0-SNAPSHOT + + + spring-jpa-services + SPRING JPA SERVICES + https://gumartinm.name/ + JPA Spring Framework. Services. + + + + + de.spring.jpa + spring-jpa-persistence + 1.0-SNAPSHOT + + + + org.springframework + spring-context + + + + + org.springframework + spring-test + test + + + diff --git a/SpringJava/JPA/spring-jpa-services/src/main/java/de/spring/example/services/AdDescriptionService.java b/SpringJava/JPA/spring-jpa-services/src/main/java/de/spring/example/services/AdDescriptionService.java new file mode 100644 index 0000000..bbcf1fa --- /dev/null +++ b/SpringJava/JPA/spring-jpa-services/src/main/java/de/spring/example/services/AdDescriptionService.java @@ -0,0 +1,12 @@ +package de.spring.example.services; + +import org.resthub.common.service.CrudService; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import de.spring.example.persistence.domain.AdDescription; + +public interface AdDescriptionService extends CrudService { + + public Page queryDslExample(Pageable pageRequest); +} diff --git a/SpringJava/JPA/spring-jpa-services/src/main/java/de/spring/example/services/AdService.java b/SpringJava/JPA/spring-jpa-services/src/main/java/de/spring/example/services/AdService.java new file mode 100644 index 0000000..c491be8 --- /dev/null +++ b/SpringJava/JPA/spring-jpa-services/src/main/java/de/spring/example/services/AdService.java @@ -0,0 +1,12 @@ +package de.spring.example.services; + +import org.resthub.common.service.CrudService; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import de.spring.example.persistence.domain.Ad; + +public interface AdService extends CrudService { + + public Page queryCriteriaExample(Pageable pageRequest); +} diff --git a/SpringJava/JPA/spring-jpa-services/src/main/java/de/spring/example/services/impl/AdDescriptionServiceImpl.java b/SpringJava/JPA/spring-jpa-services/src/main/java/de/spring/example/services/impl/AdDescriptionServiceImpl.java new file mode 100644 index 0000000..7f5a681 --- /dev/null +++ b/SpringJava/JPA/spring-jpa-services/src/main/java/de/spring/example/services/impl/AdDescriptionServiceImpl.java @@ -0,0 +1,51 @@ +package de.spring.example.services.impl; + +import javax.inject.Inject; +import javax.inject.Named; + +import org.resthub.common.service.CrudServiceImpl; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import com.querydsl.core.types.dsl.BooleanExpression; + +import de.spring.example.persistence.domain.AdDescription; +import de.spring.example.persistence.domain.QAdDescription; +import de.spring.example.persistence.repository.AdDescriptionRepository; +import de.spring.example.services.AdDescriptionService; + +@Named("adDescriptionService") +public class AdDescriptionServiceImpl + extends CrudServiceImpl + implements AdDescriptionService { + + @Override + @Inject + public void setRepository(AdDescriptionRepository repository) { + this.repository = repository; + } + + // Extending CrudServiceImpl when we need some business logic. Otherwise we would be using + // the JPA repositories and nothing else :) + + // In this case there is any business logic, but this is just an example. + + + /** + * Using Querydsl. Giving some business logic to this service :) + * + * Querydsl: fluent interface done easy. There is no effort because it is already implemented. + * + * Criteria using Specifications requires some effort. + * + * See: de.spring.example.services.impl.AdServiceImpl + */ + @Override + public Page queryDslExample(Pageable pageRequest) { + final QAdDescription adDescription = QAdDescription.adDescription1; + final BooleanExpression adDescriptionHasAdLink = adDescription.adLink.contains("gumartinm"); + final BooleanExpression adDescriptionHasDescription = adDescription.adDescription.contains("babucha"); + + return repository.findAll(adDescriptionHasAdLink.and(adDescriptionHasDescription), pageRequest); + } +} diff --git a/SpringJava/JPA/spring-jpa-services/src/main/java/de/spring/example/services/impl/AdServiceImpl.java b/SpringJava/JPA/spring-jpa-services/src/main/java/de/spring/example/services/impl/AdServiceImpl.java new file mode 100644 index 0000000..db3140f --- /dev/null +++ b/SpringJava/JPA/spring-jpa-services/src/main/java/de/spring/example/services/impl/AdServiceImpl.java @@ -0,0 +1,41 @@ +package de.spring.example.services.impl; + +import static org.springframework.data.jpa.domain.Specifications.where; + +import javax.inject.Inject; + +import org.resthub.common.service.CrudServiceImpl; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import de.spring.example.persistence.domain.Ad; +import de.spring.example.persistence.domain.specifications.AdSpectifications; +import de.spring.example.persistence.repository.AdRepository; +import de.spring.example.services.AdService; + +public class AdServiceImpl + extends CrudServiceImpl + implements AdService { + + @Override + @Inject + public void setRepository(AdRepository repository) { + this.repository = repository; + } + + /** + * Criteria using Specifications. + * + * It is more complicated than when using Querydsl because I have to implement the + * Specifications. Querydsl is doing everything for me. + * + * See: de.spring.example.services.impl.AdDescriptionServiceImpl + */ + @Override + public Page queryCriteriaExample(Pageable pageRequest) { + return repository.findAll( + where(AdSpectifications.createdToday()).and(AdSpectifications.mobileImage("picasso")), + pageRequest); + } + +} diff --git a/SpringJava/JPA/spring-jpa-services/src/main/java/org/resthub/common/service/CrudService.java b/SpringJava/JPA/spring-jpa-services/src/main/java/org/resthub/common/service/CrudService.java new file mode 100644 index 0000000..a9f4332 --- /dev/null +++ b/SpringJava/JPA/spring-jpa-services/src/main/java/org/resthub/common/service/CrudService.java @@ -0,0 +1,94 @@ +package org.resthub.common.service; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import java.io.Serializable; +import java.util.Set; + +/** + * CRUD Service interface. + * + * @param Your resource POJO to manage, maybe an entity or DTO class + * @param Resource id type, usually Long or String + */ +public interface CrudService { + + /** + * Create new resource. + * + * @param resource Resource to create + * @return new resource + */ + T create(T resource); + + /** + * Update existing resource. + * + * @param resource Resource to update + * @return resource updated + */ + T update(T resource); + + /** + * Delete existing resource. + * + * @param resource Resource to delete + */ + void delete(T resource); + + /** + * Delete existing resource. + * + * @param id Resource id + */ + void delete(ID id); + + /** + * Delete all existing resource. Do not use cascade remove (not a choice -> JPA specs) + */ + void deleteAll(); + + /** + * Delete all existing resource, including linked entities with cascade delete + */ + void deleteAllWithCascade(); + + /** + * Find resource by id. + * + * @param id Resource id + * @return resource + */ + T findById(ID id); + + /** + * Find resources by their ids. + * + * @param ids Resource ids + * @return a list of retrieved resources, empty if no resource found + */ + Iterable findByIds(Set ids); + + /** + * Find all resources. + * + * @return a list of all resources. + */ + Iterable findAll(); + + /** + * Find all resources (pageable). + * + * @param pageRequest page request + * @return resources + */ + Page findAll(Pageable pageRequest); + + /** + * Count all resources. + * + * @return number of resources + */ + Long count(); +} diff --git a/SpringJava/JPA/spring-jpa-services/src/main/java/org/resthub/common/service/CrudServiceImpl.java b/SpringJava/JPA/spring-jpa-services/src/main/java/org/resthub/common/service/CrudServiceImpl.java new file mode 100644 index 0000000..b623bf3 --- /dev/null +++ b/SpringJava/JPA/spring-jpa-services/src/main/java/org/resthub/common/service/CrudServiceImpl.java @@ -0,0 +1,138 @@ +package org.resthub.common.service; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.Assert; + +import java.io.Serializable; +import java.util.Set; + +/** + * CRUD service that uses a {@link org.springframework.data.repository.PagingAndSortingRepository} Spring Data repository implementation + * + * You should extend it and inject your Repository bean by overriding {@link #setRepository(org.springframework.data.repository.PagingAndSortingRepository)} + * + * @param Your resource class to manage, usually an entity class + * @param Resource id type, usually Long or String + * @param The repository class + */ +@Transactional(readOnly = true) +public class CrudServiceImpl> implements + CrudService { + + protected R repository; + + /** + * @param repository the repository to set + */ + public void setRepository(R repository) { + this.repository = repository; + } + + /** + * {@inheritDoc} + */ + @Override + @Transactional + public T create(T resource) { + Assert.notNull(resource, "Resource can't be null"); + return repository.save(resource); + } + + /** + * {@inheritDoc} + */ + @Override + @Transactional + public T update(T resource) { + Assert.notNull(resource, "Resource can't be null"); + return repository.save(resource); + } + + /** + * {@inheritDoc} + */ + @Override + @Transactional + public void delete(T resource) { + Assert.notNull(resource, "Resource can't be null"); + repository.delete(resource); + } + + /** + * {@inheritDoc} + */ + @Override + @Transactional + public void delete(ID id) { + Assert.notNull(id, "Resource ID can't be null"); + repository.delete(id); + } + + /** + * {@inheritDoc} + */ + @Override + @Transactional + public void deleteAll() { + repository.deleteAll(); + } + + /** + * {@inheritDoc} + */ + @Override + @Transactional + public void deleteAllWithCascade() { + Iterable list = repository.findAll(); + for (T entity : list) { + repository.delete(entity); + } + } + + /** + * {@inheritDoc} + */ + @Override + public T findById(ID id) { + Assert.notNull(id, "Resource ID can't be null"); + return repository.findOne(id); + } + + /** + * {@inheritDoc} + */ + @Override + public Iterable findByIds(Set ids) { + Assert.notNull(ids, "Resource ids can't be null"); + return repository.findAll(ids); + } + + /** + * {@inheritDoc} + */ + @Override + public Iterable findAll() { + return repository.findAll(); + } + + /** + * {@inheritDoc} + */ + @Override + @Transactional + public Page findAll(Pageable pageRequest) { + Assert.notNull(pageRequest, "page request can't be null"); + return repository.findAll(pageRequest); + } + + /** + * {@inheritDoc} + */ + @Override + public Long count() { + return repository.count(); + } +} diff --git a/SpringJava/JPA/spring-jpa-services/src/main/resources/spring-configuration/configuration.xml b/SpringJava/JPA/spring-jpa-services/src/main/resources/spring-configuration/configuration.xml new file mode 100644 index 0000000..05346ba --- /dev/null +++ b/SpringJava/JPA/spring-jpa-services/src/main/resources/spring-configuration/configuration.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/SpringJava/JPA/src/main/java/de/spring/example/context/UsernameThreadContext.java b/SpringJava/JPA/src/main/java/de/spring/example/context/UsernameThreadContext.java deleted file mode 100644 index 4d698ee..0000000 --- a/SpringJava/JPA/src/main/java/de/spring/example/context/UsernameThreadContext.java +++ /dev/null @@ -1,26 +0,0 @@ -package de.spring.example.context; - -import javax.inject.Named; - -import org.springframework.util.Assert; - -@Named("userNameThreadContext") -public class UsernameThreadContext { - public static final String USERNAME_HEADER = "USERNAME"; - - private final ThreadLocal contextHolder = new ThreadLocal<>(); - - public void setUsername(String username) { - Assert.notNull(username); - - contextHolder.set(username); - } - - public String getUsername() { - return contextHolder.get(); - } - - public void clearUsername() { - contextHolder.remove(); - } -} diff --git a/SpringJava/JPA/src/main/java/de/spring/example/persistence/converters/OffsetDateTimeAttributeConverter.java b/SpringJava/JPA/src/main/java/de/spring/example/persistence/converters/OffsetDateTimeAttributeConverter.java deleted file mode 100644 index 30ab6bb..0000000 --- a/SpringJava/JPA/src/main/java/de/spring/example/persistence/converters/OffsetDateTimeAttributeConverter.java +++ /dev/null @@ -1,39 +0,0 @@ -package de.spring.example.persistence.converters; - -import java.sql.Timestamp; -import java.time.LocalDateTime; -import java.time.OffsetDateTime; -import java.time.ZoneId; -import java.time.ZonedDateTime; - -import javax.persistence.AttributeConverter; -import javax.persistence.Converter; - -@Converter(autoApply = true) -public class OffsetDateTimeAttributeConverter implements AttributeConverter { - - @Override - public Timestamp convertToDatabaseColumn(OffsetDateTime offsetDateTime) { - Timestamp timestamp = null; - - if (offsetDateTime != null) { - timestamp = Timestamp.valueOf(offsetDateTime.toLocalDateTime()); - } - - return timestamp; - } - - @Override - public OffsetDateTime convertToEntityAttribute(Timestamp sqlTimestamp) { - OffsetDateTime offsetDateTime = null; - - if (sqlTimestamp != null) { - final LocalDateTime localDateTime = sqlTimestamp.toLocalDateTime(); - final ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.systemDefault()); - offsetDateTime = zonedDateTime.toOffsetDateTime(); - } - - return offsetDateTime; - } - -} diff --git a/SpringJava/JPA/src/main/java/de/spring/example/persistence/domain/Ad.java b/SpringJava/JPA/src/main/java/de/spring/example/persistence/domain/Ad.java deleted file mode 100644 index 0f91253..0000000 --- a/SpringJava/JPA/src/main/java/de/spring/example/persistence/domain/Ad.java +++ /dev/null @@ -1,150 +0,0 @@ -package de.spring.example.persistence.domain; - -import java.io.Serializable; -import java.time.OffsetDateTime; -import java.util.Set; - -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Convert; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -//import javax.persistence.NamedNativeQueries; -//import javax.persistence.NamedNativeQuery; -//import javax.persistence.NamedQueries; -//import javax.persistence.NamedQuery; -import javax.persistence.OneToMany; -import javax.persistence.Table; -import javax.validation.constraints.Max; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; - -import org.hibernate.envers.Audited; - -import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.annotation.JsonIdentityInfo; -import com.fasterxml.jackson.annotation.ObjectIdGenerators; - -import de.spring.example.persistence.converters.OffsetDateTimeAttributeConverter; - -@Entity -@Audited(withModifiedFlag=true) -@Table(name="ad", schema="mybatis_example") -@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="jsonId") -// 1. Named query is JPL. It is portable. -// 2. Instead of annotating the domain class we should be using @Query annotation at the query method -// because it should be cleaner :) -// So you'd better use @Query. -//http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.at-query -//See: de.spring.persistence.example.repository.AdRepository -//@NamedQueries( -// { -// @NamedQuery( -// name="Ad.findByIdQuery", -// query="select a from Ad a where a.id = :id) -// } -// -//) -// 1. Native query IS NOT JPL. It is not portable and it is written directly in the native language -// of the store. We can use special features at the cost of portability. -// 2. Instead of annotating the domain class we should be using @Query annotation at the query method -// because it should be cleaner :) -// So you'd better use @Query. -// http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.at-query -// See: de.spring.persistence.example.repository.AdRepository -//@NamedNativeQueries( -// { -// @NamedNativeQuery( -// name="Ad.findByIdNativeQuery", -// query="SELECT * FROM ad WHERE ad.id = :id", -// resultClass=Ad.class) -// } -//) -public class Ad implements Serializable { - - @Id - @GeneratedValue(strategy=GenerationType.IDENTITY) - @Column(name="id", updatable=false, nullable=false) - private Long id; - - @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL) - @JoinColumn(name = "ad_id", nullable = false) - private Set adDescriptions; - - @Max(60) - @Column(name="company_id") - private Long companyId; - - @Max(40) - @Column(name="company_categ_id") - private Long companyCategId; - - @Size(min=2, max=255) - @Column(name="ad_mobile_image") - private String adMobileImage; - - @NotNull - @Convert(converter=OffsetDateTimeAttributeConverter.class) - @Column(name="created_at", nullable=false) - @JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ssZ") - private OffsetDateTime createdAt; - - @NotNull - @Convert(converter=OffsetDateTimeAttributeConverter.class) - @Column(name="updated_at", nullable = false) - @JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ssZ") - private OffsetDateTime updatedAt; - - // It will be used by JPA when filling the property fields with data coming from data base. - protected Ad() { - - } - - // It will be used by my code (for example by Unit Tests) - public Ad(Long id, Set adDescriptions, Long companyId, Long companyCategId, String adMobileImage, - OffsetDateTime createdAt, OffsetDateTime updatedAt) { - this.id = id; - this.adDescriptions = adDescriptions; - this.companyId = companyId; - this.companyCategId = companyCategId; - this.adMobileImage = adMobileImage; - this.createdAt = createdAt; - this.updatedAt = updatedAt; - } - - /** - * WARNING: JPA REQUIRES GETTERS!!! - */ - - public Long getId() { - return id; - } - - public Set getAdDescriptions() { - return adDescriptions; - } - - public Long getCompanyId() { - return companyId; - } - - public Long getCompanyCategId() { - return companyCategId; - } - - public String getAdMobileImage() { - return adMobileImage; - } - - public OffsetDateTime getCreatedAt() { - return createdAt; - } - - public OffsetDateTime getUpdatedAt() { - return updatedAt; - } -} diff --git a/SpringJava/JPA/src/main/java/de/spring/example/persistence/domain/AdDescription.java b/SpringJava/JPA/src/main/java/de/spring/example/persistence/domain/AdDescription.java deleted file mode 100644 index 2142b39..0000000 --- a/SpringJava/JPA/src/main/java/de/spring/example/persistence/domain/AdDescription.java +++ /dev/null @@ -1,112 +0,0 @@ -package de.spring.example.persistence.domain; - -import java.io.Serializable; - -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.Table; -import javax.validation.constraints.Max; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; - -import org.hibernate.envers.Audited; - -import com.fasterxml.jackson.annotation.JsonIdentityInfo; -import com.fasterxml.jackson.annotation.ObjectIdGenerators; - -@Entity -@Audited -@Table(name="ad_description", schema="mybatis_example") -@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="jsonId") -public class AdDescription implements Serializable { - - @Id - @GeneratedValue(strategy=GenerationType.IDENTITY) - @Column(name="id", updatable=false, nullable=false) - private Long id; - - @ManyToOne(fetch=FetchType.LAZY, cascade = CascadeType.ALL, optional=true) - @JoinColumn(name="ad_id", nullable=false, updatable = false, insertable = false, referencedColumnName="id") - private Ad ad; - - @NotNull - @Max(60) - @Column(name="laguage_id") - private Long languageId; - - @NotNull - @Size(min=2, max=255) - @Column(name="ad_name") - private String adName; - - @NotNull - @Size(min=2, max=255) - @Column(name="ad_description") - private String adDescription; - - @NotNull - @Size(min=2, max=500) - @Column(name="ad_mobile_text") - private String adMobileText; - - @NotNull - @Size(min=2, max=3000) - @Column(name="ad_link") - private String adLink; - - // It will be used by JPA when filling the property fields with data coming from data base. - protected AdDescription() { - - } - - // It will be used by my code (for example by Unit Tests) - public AdDescription(Long id, Ad ad, Long languageId, String adName, String adDescription, - String adMobileText, String adLink) { - this.id = id; - this.ad = ad; - this.languageId = languageId; - this.adName = adName; - this.adDescription = adDescription; - this.adMobileText = adMobileText; - this.adLink = adLink; - } - - /** - * WARNING: JPA REQUIRES GETTERS!!! - */ - - public Long getId() { - return id; - } - - public Ad getAd() { - return ad; - } - - public Long getLanguageId() { - return languageId; - } - - public String getAdName() { - return adName; - } - - public String getAdDescription() { - return adDescription; - } - - public String getAdMobileText() { - return adMobileText; - } - - public String getAdLink() { - return adLink; - } -} diff --git a/SpringJava/JPA/src/main/java/de/spring/example/persistence/domain/audit/MyCustomRevision.java b/SpringJava/JPA/src/main/java/de/spring/example/persistence/domain/audit/MyCustomRevision.java deleted file mode 100644 index f8ebfe9..0000000 --- a/SpringJava/JPA/src/main/java/de/spring/example/persistence/domain/audit/MyCustomRevision.java +++ /dev/null @@ -1,35 +0,0 @@ -package de.spring.example.persistence.domain.audit; - -import javax.persistence.Entity; -import javax.persistence.Table; - -import org.hibernate.envers.RevisionEntity; - -@Entity -@RevisionEntity(MyCustomRevisionListener.class) -@Table(name="CUSTOM_REVISION", schema="mybatis_example") -public class MyCustomRevision { - private String username; - - // It will be used by JPA when filling the property fields with data coming from data base. - protected MyCustomRevision() { - - } - - // It will be used by my code (for example by Unit Tests) - public MyCustomRevision(String username) { - this.username = username; - } - - /** - * WARNING: JPA REQUIRES GETTERS!!! - */ - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } -} diff --git a/SpringJava/JPA/src/main/java/de/spring/example/persistence/domain/audit/MyCustomRevisionListener.java b/SpringJava/JPA/src/main/java/de/spring/example/persistence/domain/audit/MyCustomRevisionListener.java deleted file mode 100644 index f4c63c7..0000000 --- a/SpringJava/JPA/src/main/java/de/spring/example/persistence/domain/audit/MyCustomRevisionListener.java +++ /dev/null @@ -1,33 +0,0 @@ -package de.spring.example.persistence.domain.audit; - -import org.hibernate.envers.RevisionListener; - -import de.spring.example.context.UsernameThreadContext; - -public class MyCustomRevisionListener implements RevisionListener { - private final UsernameThreadContext userNameThreadContext; - - public MyCustomRevisionListener(UsernameThreadContext userNameThreadContext) { - this.userNameThreadContext = userNameThreadContext; - } - - @Override - public void newRevision(Object revisionEntity) { - MyCustomRevision myCustomRevision = (MyCustomRevision) revisionEntity; - - final String username = getSafeUsername(); - myCustomRevision.setUsername(username); - - } - - private String getSafeUsername() { - String userName = userNameThreadContext.getUserName(); - - if (userName == null) { - userName = "NO_USER"; - } - - return userName; - } - -} diff --git a/SpringJava/JPA/src/main/java/de/spring/example/persistence/domain/specifications/AdSpectifications.java b/SpringJava/JPA/src/main/java/de/spring/example/persistence/domain/specifications/AdSpectifications.java deleted file mode 100644 index 2cadb54..0000000 --- a/SpringJava/JPA/src/main/java/de/spring/example/persistence/domain/specifications/AdSpectifications.java +++ /dev/null @@ -1,62 +0,0 @@ -package de.spring.example.persistence.domain.specifications; - -import java.time.LocalDate; - -//import javax.persistence.criteria.CriteriaBuilder; -//import javax.persistence.criteria.CriteriaQuery; -//import javax.persistence.criteria.Predicate; -//import javax.persistence.criteria.Root; - -import org.springframework.data.jpa.domain.Specification; - -import de.spring.example.persistence.domain.Ad; - -public class AdSpectifications { - -// public static Specification createdToday() { -// return new Specification() { -// -// @Override -// public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { -// final LocalDate date = LocalDate.now(); -// -// return cb.equal(root.get("createdAt"), date); -// } -// -// }; -// -// } - - /** - * The same using lambda expressions - */ - public static Specification createdToday() { - return (root, query, cb) -> { - final LocalDate date = LocalDate.now(); - - return cb.equal(root.get("createdAt"), date); - }; - } - -// public static Specification mobileImage(String image) { -// return new Specification() { -// -// @Override -// public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { -// -// return cb.equal(root.get("adMobileImage"), image); -// } -// -// }; -// -// } - - /** - * The same using lambda expressions - */ - public static Specification mobileImage(String image) { - return (root, query, cb) -> { - return cb.equal(root.get("adMobileImage"), image); - }; - } -} diff --git a/SpringJava/JPA/src/main/java/de/spring/example/persistence/repository/AdDescriptionRepository.java b/SpringJava/JPA/src/main/java/de/spring/example/persistence/repository/AdDescriptionRepository.java deleted file mode 100644 index 4b4e6fc..0000000 --- a/SpringJava/JPA/src/main/java/de/spring/example/persistence/repository/AdDescriptionRepository.java +++ /dev/null @@ -1,22 +0,0 @@ -package de.spring.example.persistence.repository; - -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.querydsl.QueryDslPredicateExecutor; -import org.springframework.data.repository.PagingAndSortingRepository; - -import de.spring.example.persistence.domain.Ad; -import de.spring.example.persistence.domain.AdDescription; - -/** - * By default org.springframework.data.jpa.repository.support.SimpleJpaRepository - * will be the implementation for this interface. - * - * Be careful with @Transactional. SimpleJpaRepository has annotated methods. - * - */ -public interface AdDescriptionRepository extends PagingAndSortingRepository, QueryDslPredicateExecutor { - - // Custom Query method (useful when the offered methods by PagingAndSortingRepository are not enough) - Page findByAd(Ad ad, Pageable pageable); -} diff --git a/SpringJava/JPA/src/main/java/de/spring/example/persistence/repository/AdRepository.java b/SpringJava/JPA/src/main/java/de/spring/example/persistence/repository/AdRepository.java deleted file mode 100644 index bc73359..0000000 --- a/SpringJava/JPA/src/main/java/de/spring/example/persistence/repository/AdRepository.java +++ /dev/null @@ -1,28 +0,0 @@ -package de.spring.example.persistence.repository; - -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.PagingAndSortingRepository; -import org.springframework.data.repository.query.Param; - -import de.spring.example.persistence.domain.Ad; - -/** - * By default org.springframework.data.jpa.repository.support.SimpleJpaRepository - * will be the implementation for this interface. - * - * Be careful with @Transactional. SimpleJpaRepository has annotated methods. - * - */ -public interface AdRepository extends PagingAndSortingRepository, JpaSpecificationExecutor { - - // Named Native Query (using the native language of the store) It is not portable. - // See de.spring.persistence.example.domain.Ad - @Query(value="SELECT * FROM ad WHERE ad.id = :id", nativeQuery=true) - Ad findByIdNativeQuery(@Param("id") Long id); - - // Named Query (using JPL) It is portable. - // See de.spring.persistence.example.domain.Ad - @Query("select a from Ad a where a.id = :id") - Ad findByIdQuery(@Param("id") Long id); -} diff --git a/SpringJava/JPA/src/main/java/de/spring/example/rest/controllers/AdController.java b/SpringJava/JPA/src/main/java/de/spring/example/rest/controllers/AdController.java deleted file mode 100644 index edbf37d..0000000 --- a/SpringJava/JPA/src/main/java/de/spring/example/rest/controllers/AdController.java +++ /dev/null @@ -1,27 +0,0 @@ -package de.spring.example.rest.controllers; - -import javax.inject.Inject; - -import org.resthub.web.controller.RepositoryBasedRestController; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import de.spring.example.persistence.domain.Ad; -import de.spring.example.persistence.repository.AdRepository; - -@RestController -@RequestMapping("/ads/") -public class AdController extends RepositoryBasedRestController { - - @Override - @Inject - public void setRepository(AdRepository repository) { - this.repository = repository; - } - - // I do not have to do anything here because all I need is implemented by RepositoryBasedRestController :) - - // @Transactional is implemented by org.springframework.data.jpa.repository.support.SimpleJpaRepository - // By default, SimpleJpaRepository will be automatically implemented by my - // Spring JPA repositories: AdRepository and AdDescriptionRepository. -} diff --git a/SpringJava/JPA/src/main/java/de/spring/example/rest/controllers/AdDescriptionController.java b/SpringJava/JPA/src/main/java/de/spring/example/rest/controllers/AdDescriptionController.java deleted file mode 100644 index d3c1849..0000000 --- a/SpringJava/JPA/src/main/java/de/spring/example/rest/controllers/AdDescriptionController.java +++ /dev/null @@ -1,23 +0,0 @@ -package de.spring.example.rest.controllers; - -import javax.inject.Inject; - -import org.resthub.web.controller.ServiceBasedRestController; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import de.spring.example.persistence.domain.AdDescription; -import de.spring.example.services.AdDescriptionService; - -@RestController -@RequestMapping("/ad-descriptions/") -public class AdDescriptionController extends ServiceBasedRestController { - - @Override - @Inject - public void setService(AdDescriptionService adDescriptionService) { - this.service = adDescriptionService; - } - - // I do not have to do anything here because all I need is implemented by ServiceBasedRestController :) -} diff --git a/SpringJava/JPA/src/main/java/de/spring/example/rest/handler/UsernameHandler.java b/SpringJava/JPA/src/main/java/de/spring/example/rest/handler/UsernameHandler.java deleted file mode 100644 index 9878f3d..0000000 --- a/SpringJava/JPA/src/main/java/de/spring/example/rest/handler/UsernameHandler.java +++ /dev/null @@ -1,32 +0,0 @@ -package de.spring.example.rest.handler; - -import javax.inject.Inject; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; - -import de.spring.example.context.UsernameThreadContext; - -public class UsernameHandler extends HandlerInterceptorAdapter { - private final UsernameThreadContext usernameThreadContext; - - @Inject - public UsernameHandler(UsernameThreadContext userNameThreadContext) { - this.usernameThreadContext = userNameThreadContext; - } - - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) - throws Exception { - final String userName = request.getHeader(UsernameThreadContext.USERNAME_HEADER); - - if (userName != null) { - usernameThreadContext.setUsername(userName); - } else { - usernameThreadContext.clearUsername(); - } - - return super.preHandle(request, response, handler); - } -} diff --git a/SpringJava/JPA/src/main/java/de/spring/example/services/AdDescriptionService.java b/SpringJava/JPA/src/main/java/de/spring/example/services/AdDescriptionService.java deleted file mode 100644 index bbcf1fa..0000000 --- a/SpringJava/JPA/src/main/java/de/spring/example/services/AdDescriptionService.java +++ /dev/null @@ -1,12 +0,0 @@ -package de.spring.example.services; - -import org.resthub.common.service.CrudService; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; - -import de.spring.example.persistence.domain.AdDescription; - -public interface AdDescriptionService extends CrudService { - - public Page queryDslExample(Pageable pageRequest); -} diff --git a/SpringJava/JPA/src/main/java/de/spring/example/services/AdService.java b/SpringJava/JPA/src/main/java/de/spring/example/services/AdService.java deleted file mode 100644 index c491be8..0000000 --- a/SpringJava/JPA/src/main/java/de/spring/example/services/AdService.java +++ /dev/null @@ -1,12 +0,0 @@ -package de.spring.example.services; - -import org.resthub.common.service.CrudService; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; - -import de.spring.example.persistence.domain.Ad; - -public interface AdService extends CrudService { - - public Page queryCriteriaExample(Pageable pageRequest); -} diff --git a/SpringJava/JPA/src/main/java/de/spring/example/services/impl/AdDescriptionServiceImpl.java b/SpringJava/JPA/src/main/java/de/spring/example/services/impl/AdDescriptionServiceImpl.java deleted file mode 100644 index 7f5a681..0000000 --- a/SpringJava/JPA/src/main/java/de/spring/example/services/impl/AdDescriptionServiceImpl.java +++ /dev/null @@ -1,51 +0,0 @@ -package de.spring.example.services.impl; - -import javax.inject.Inject; -import javax.inject.Named; - -import org.resthub.common.service.CrudServiceImpl; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; - -import com.querydsl.core.types.dsl.BooleanExpression; - -import de.spring.example.persistence.domain.AdDescription; -import de.spring.example.persistence.domain.QAdDescription; -import de.spring.example.persistence.repository.AdDescriptionRepository; -import de.spring.example.services.AdDescriptionService; - -@Named("adDescriptionService") -public class AdDescriptionServiceImpl - extends CrudServiceImpl - implements AdDescriptionService { - - @Override - @Inject - public void setRepository(AdDescriptionRepository repository) { - this.repository = repository; - } - - // Extending CrudServiceImpl when we need some business logic. Otherwise we would be using - // the JPA repositories and nothing else :) - - // In this case there is any business logic, but this is just an example. - - - /** - * Using Querydsl. Giving some business logic to this service :) - * - * Querydsl: fluent interface done easy. There is no effort because it is already implemented. - * - * Criteria using Specifications requires some effort. - * - * See: de.spring.example.services.impl.AdServiceImpl - */ - @Override - public Page queryDslExample(Pageable pageRequest) { - final QAdDescription adDescription = QAdDescription.adDescription1; - final BooleanExpression adDescriptionHasAdLink = adDescription.adLink.contains("gumartinm"); - final BooleanExpression adDescriptionHasDescription = adDescription.adDescription.contains("babucha"); - - return repository.findAll(adDescriptionHasAdLink.and(adDescriptionHasDescription), pageRequest); - } -} diff --git a/SpringJava/JPA/src/main/java/de/spring/example/services/impl/AdServiceImpl.java b/SpringJava/JPA/src/main/java/de/spring/example/services/impl/AdServiceImpl.java deleted file mode 100644 index db3140f..0000000 --- a/SpringJava/JPA/src/main/java/de/spring/example/services/impl/AdServiceImpl.java +++ /dev/null @@ -1,41 +0,0 @@ -package de.spring.example.services.impl; - -import static org.springframework.data.jpa.domain.Specifications.where; - -import javax.inject.Inject; - -import org.resthub.common.service.CrudServiceImpl; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; - -import de.spring.example.persistence.domain.Ad; -import de.spring.example.persistence.domain.specifications.AdSpectifications; -import de.spring.example.persistence.repository.AdRepository; -import de.spring.example.services.AdService; - -public class AdServiceImpl - extends CrudServiceImpl - implements AdService { - - @Override - @Inject - public void setRepository(AdRepository repository) { - this.repository = repository; - } - - /** - * Criteria using Specifications. - * - * It is more complicated than when using Querydsl because I have to implement the - * Specifications. Querydsl is doing everything for me. - * - * See: de.spring.example.services.impl.AdDescriptionServiceImpl - */ - @Override - public Page queryCriteriaExample(Pageable pageRequest) { - return repository.findAll( - where(AdSpectifications.createdToday()).and(AdSpectifications.mobileImage("picasso")), - pageRequest); - } - -} diff --git a/SpringJava/JPA/src/main/java/org/resthub/common/exception/NotFoundException.java b/SpringJava/JPA/src/main/java/org/resthub/common/exception/NotFoundException.java deleted file mode 100644 index 7135761..0000000 --- a/SpringJava/JPA/src/main/java/org/resthub/common/exception/NotFoundException.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.resthub.common.exception; - -/** - * Exception thrown when not result was found (for example findById with null return value) - */ -public class NotFoundException extends RuntimeException { - - public NotFoundException() { - super(); - } - - public NotFoundException(final String message, final Throwable cause) { - super(message, cause); - } - - public NotFoundException(final String message) { - super(message); - } - - public NotFoundException(final Throwable cause) { - super(cause); - } - -} diff --git a/SpringJava/JPA/src/main/java/org/resthub/common/service/CrudService.java b/SpringJava/JPA/src/main/java/org/resthub/common/service/CrudService.java deleted file mode 100644 index a9f4332..0000000 --- a/SpringJava/JPA/src/main/java/org/resthub/common/service/CrudService.java +++ /dev/null @@ -1,94 +0,0 @@ -package org.resthub.common.service; - -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; - -import java.io.Serializable; -import java.util.Set; - -/** - * CRUD Service interface. - * - * @param Your resource POJO to manage, maybe an entity or DTO class - * @param Resource id type, usually Long or String - */ -public interface CrudService { - - /** - * Create new resource. - * - * @param resource Resource to create - * @return new resource - */ - T create(T resource); - - /** - * Update existing resource. - * - * @param resource Resource to update - * @return resource updated - */ - T update(T resource); - - /** - * Delete existing resource. - * - * @param resource Resource to delete - */ - void delete(T resource); - - /** - * Delete existing resource. - * - * @param id Resource id - */ - void delete(ID id); - - /** - * Delete all existing resource. Do not use cascade remove (not a choice -> JPA specs) - */ - void deleteAll(); - - /** - * Delete all existing resource, including linked entities with cascade delete - */ - void deleteAllWithCascade(); - - /** - * Find resource by id. - * - * @param id Resource id - * @return resource - */ - T findById(ID id); - - /** - * Find resources by their ids. - * - * @param ids Resource ids - * @return a list of retrieved resources, empty if no resource found - */ - Iterable findByIds(Set ids); - - /** - * Find all resources. - * - * @return a list of all resources. - */ - Iterable findAll(); - - /** - * Find all resources (pageable). - * - * @param pageRequest page request - * @return resources - */ - Page findAll(Pageable pageRequest); - - /** - * Count all resources. - * - * @return number of resources - */ - Long count(); -} diff --git a/SpringJava/JPA/src/main/java/org/resthub/common/service/CrudServiceImpl.java b/SpringJava/JPA/src/main/java/org/resthub/common/service/CrudServiceImpl.java deleted file mode 100644 index b623bf3..0000000 --- a/SpringJava/JPA/src/main/java/org/resthub/common/service/CrudServiceImpl.java +++ /dev/null @@ -1,138 +0,0 @@ -package org.resthub.common.service; - -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.repository.PagingAndSortingRepository; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.Assert; - -import java.io.Serializable; -import java.util.Set; - -/** - * CRUD service that uses a {@link org.springframework.data.repository.PagingAndSortingRepository} Spring Data repository implementation - * - * You should extend it and inject your Repository bean by overriding {@link #setRepository(org.springframework.data.repository.PagingAndSortingRepository)} - * - * @param Your resource class to manage, usually an entity class - * @param Resource id type, usually Long or String - * @param The repository class - */ -@Transactional(readOnly = true) -public class CrudServiceImpl> implements - CrudService { - - protected R repository; - - /** - * @param repository the repository to set - */ - public void setRepository(R repository) { - this.repository = repository; - } - - /** - * {@inheritDoc} - */ - @Override - @Transactional - public T create(T resource) { - Assert.notNull(resource, "Resource can't be null"); - return repository.save(resource); - } - - /** - * {@inheritDoc} - */ - @Override - @Transactional - public T update(T resource) { - Assert.notNull(resource, "Resource can't be null"); - return repository.save(resource); - } - - /** - * {@inheritDoc} - */ - @Override - @Transactional - public void delete(T resource) { - Assert.notNull(resource, "Resource can't be null"); - repository.delete(resource); - } - - /** - * {@inheritDoc} - */ - @Override - @Transactional - public void delete(ID id) { - Assert.notNull(id, "Resource ID can't be null"); - repository.delete(id); - } - - /** - * {@inheritDoc} - */ - @Override - @Transactional - public void deleteAll() { - repository.deleteAll(); - } - - /** - * {@inheritDoc} - */ - @Override - @Transactional - public void deleteAllWithCascade() { - Iterable list = repository.findAll(); - for (T entity : list) { - repository.delete(entity); - } - } - - /** - * {@inheritDoc} - */ - @Override - public T findById(ID id) { - Assert.notNull(id, "Resource ID can't be null"); - return repository.findOne(id); - } - - /** - * {@inheritDoc} - */ - @Override - public Iterable findByIds(Set ids) { - Assert.notNull(ids, "Resource ids can't be null"); - return repository.findAll(ids); - } - - /** - * {@inheritDoc} - */ - @Override - public Iterable findAll() { - return repository.findAll(); - } - - /** - * {@inheritDoc} - */ - @Override - @Transactional - public Page findAll(Pageable pageRequest) { - Assert.notNull(pageRequest, "page request can't be null"); - return repository.findAll(pageRequest); - } - - /** - * {@inheritDoc} - */ - @Override - public Long count() { - return repository.count(); - } -} diff --git a/SpringJava/JPA/src/main/java/org/resthub/web/controller/RepositoryBasedRestController.java b/SpringJava/JPA/src/main/java/org/resthub/web/controller/RepositoryBasedRestController.java deleted file mode 100644 index 2fd4c10..0000000 --- a/SpringJava/JPA/src/main/java/org/resthub/web/controller/RepositoryBasedRestController.java +++ /dev/null @@ -1,156 +0,0 @@ -package org.resthub.web.controller; - -import org.resthub.common.exception.NotFoundException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Sort; -import org.springframework.data.repository.PagingAndSortingRepository; -import org.springframework.util.Assert; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestParam; - -import java.io.Serializable; -import java.util.Set; - -/** - * Abstract REST controller using a repository implementation - *

- *

- * You should extend this class when you want to use a 2 layers pattern : Repository and Controller. This is the default - * controller implementation to use if you have no service (also called business) layer. You will be able to transform - * it to a ServiceBasedRestController later easily if needed. - *

- * - *

Default implementation uses "id" field (usually a Long) in order to identify resources in web request. - * If your want to identity resources by a slug (human readable identifier), your should override findById() method with for example : - * - *

- * 
-   {@literal @}Override
-   public Sample findById({@literal @}PathVariable String id) {
-        Sample sample = this.repository.findByName(id);
-        if (sample == null) {
-            throw new NotFoundException();
-        }
-        return sample;
-   }
-   
- * 
- * - * - * @param Your resource class to manage, maybe an entity or DTO class - * @param Resource id type, usually Long or String - * @param The repository class - * @see ServiceBasedRestController - */ -public abstract class RepositoryBasedRestController - implements RestController { - - protected R repository; - - protected Logger logger = LoggerFactory.getLogger(RepositoryBasedRestController.class); - - /** - * You should override this setter in order to inject your repository with @Inject annotation - * - * @param repository The repository to be injected - */ - public void setRepository(R repository) { - this.repository = repository; - } - - /** - * {@inheritDoc} - */ - @Override - public T create(@RequestBody T resource) { - return (T)this.repository.save(resource); - } - - /** - * {@inheritDoc} - */ - @Override - public T update(@PathVariable ID id, @RequestBody T resource) { - Assert.notNull(id, "id cannot be null"); - - T retrievedResource = this.findById(id); - if (retrievedResource == null) { - throw new NotFoundException(); - } - - return (T)this.repository.save(resource); - } - - /** - * {@inheritDoc} - */ - @Override - public Iterable findAll() { - return repository.findAll(); - } - - /** - * {@inheritDoc} - */ - @Override - public Page findPaginated(@RequestParam(value = "page", required = false, defaultValue = "1") Integer page, - @RequestParam(value = "size", required = false, defaultValue = "10") Integer size, - @RequestParam(value = "direction", required = false, defaultValue = "") String direction, - @RequestParam(value = "properties", required = false) String properties) { - Assert.isTrue(page > 0, "Page index must be greater than 0"); - Assert.isTrue(direction.isEmpty() || direction.equalsIgnoreCase(Sort.Direction.ASC.toString()) || direction.equalsIgnoreCase(Sort.Direction.DESC.toString()), "Direction should be ASC or DESC"); - if(direction.isEmpty()) { - return this.repository.findAll(new PageRequest(page - 1, size)); - } else { - Assert.notNull(properties); - return this.repository.findAll(new PageRequest(page - 1, size, new Sort(Sort.Direction.fromString(direction.toUpperCase()), properties.split(",")))); - } - } - - /** - * {@inheritDoc} - */ - @Override - public T findById(@PathVariable ID id) { - T entity = (T)this.repository.findOne(id); - if (entity == null) { - throw new NotFoundException(); - } - - return entity; - } - - /** - * {@inheritDoc} - */ - @Override - public Iterable findByIds(@RequestParam(value="ids[]") Set ids){ - Assert.notNull(ids, "ids list cannot be null"); - return this.repository.findAll(ids); - } - - /** - * {@inheritDoc} - */ - @Override - public void delete() { - Iterable list = repository.findAll(); - for (T entity : list) { - repository.delete(entity); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void delete(@PathVariable ID id) { - T resource = this.findById(id); - this.repository.delete(resource); - } - -} diff --git a/SpringJava/JPA/src/main/java/org/resthub/web/controller/RestController.java b/SpringJava/JPA/src/main/java/org/resthub/web/controller/RestController.java deleted file mode 100644 index 9aa9a26..0000000 --- a/SpringJava/JPA/src/main/java/org/resthub/web/controller/RestController.java +++ /dev/null @@ -1,119 +0,0 @@ -package org.resthub.web.controller; - -import org.resthub.common.exception.NotFoundException; -import org.springframework.data.domain.Page; -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.*; - -import java.io.Serializable; -import java.util.Set; - -/** - * REST controller interface - * - * @param Your resource POJO to manage, maybe an entity or DTO class - * @param Primary resource identifier at webservice level, usually Long or String - */ -public interface RestController { - - /** - * Create a new resource
- * REST webservice published : POST / - * - * @param resource The resource to create - * @return CREATED http status code if the request has been correctly processed, with updated resource enclosed in the body, usually with and additional identifier automatically created by the database - */ - @RequestMapping(method = RequestMethod.POST) - @ResponseStatus(HttpStatus.CREATED) - @ResponseBody - T create(@RequestBody T resource); - - /** - * Update an existing resource
- * REST webservice published : PUT /{id} - * - * @param id The identifier of the resource to update, usually a Long or String identifier. It is explicitely provided in order to handle cases where the identifier could be changed. - * @param resource The resource to update - * @return OK http status code if the request has been correctly processed, with the updated resource enclosed in the body - * @throws NotFoundException - */ - @RequestMapping(value = "{id}", method = RequestMethod.PUT) - @ResponseBody - T update(@PathVariable ID id, @RequestBody T resource); - - /** - * Find all resources, and return the full collection (plain list not paginated)
- * REST webservice published : GET /?page=no - * - * @return OK http status code if the request has been correctly processed, with the list of all resource enclosed in the body. - * Be careful, this list should be big since it will return ALL resources. In this case, consider using paginated findAll method instead. - */ - @RequestMapping(method = RequestMethod.GET, params = "page=no") - @ResponseBody - Iterable findAll(); - - /** - * Find all resources, and return a paginated and optionaly sorted collection
- * REST webservice published : GET /search?page=0&size=20 or GET /search?page=0&size=20&direction=desc&properties=name - * - * @param page Page number starting from 0. default to 0 - * @param size Number of resources by pages. default to 10 - * @param direction Optional sort direction, could be "asc" or "desc" - * @param properties Ordered list of comma separeted properies used for sorting resulats. At least one property should be provided if direction is specified - * @return OK http status code if the request has been correctly processed, with the a paginated collection of all resource enclosed in the body. - */ - @RequestMapping(method = RequestMethod.GET) - @ResponseBody - Page findPaginated(@RequestParam(value = "page", required = false, defaultValue = "1") Integer page, - @RequestParam(value = "size", required = false, defaultValue = "10") Integer size, - @RequestParam(value = "direction", required = false, defaultValue = "ASC") String direction, - @RequestParam(value = "properties", required = false) String properties); - - /** - * Find a resource by its identifier
- * REST webservice published : GET /{id} - * - * @param id The identifier of the resouce to find - * @return OK http status code if the request has been correctly processed, with resource found enclosed in the body - * @throws NotFoundException - */ - @RequestMapping(value = "{id}", method = RequestMethod.GET) - @ResponseBody - T findById(@PathVariable ID id); - - /** - * Find multiple resources by their identifiers
- * REST webservice published : GET /?ids[]= - *

- * example : /?ids[]=1&ids[]=2&ids[]=3 - * - * @param ids List of ids to retrieve - * @return OK http status code with list of retrieved resources. Not found resources are ignored: - * no Exception thrown. List is empty if no resource found with any of the given ids. - */ - @RequestMapping(method = RequestMethod.GET, params = "ids[]") - @ResponseBody - Iterable findByIds(@RequestParam(value = "ids[]") Set ids); - - /** - * Delete all resources
- * REST webservice published : DELETE /
- * Return No Content http status code if the request has been correctly processed - */ - @RequestMapping(method = RequestMethod.DELETE) - @ResponseStatus(HttpStatus.NO_CONTENT) - void delete(); - - /** - * Delete a resource by its identifier
- * REST webservice published : DELETE /{id}
- * Return No Content http status code if the request has been correctly processed - * - * @param id The identifier of the resource to delete - * @throws NotFoundException - */ - @RequestMapping(value = "{id}", method = RequestMethod.DELETE) - @ResponseStatus(HttpStatus.NO_CONTENT) - void delete(@PathVariable ID id); - -} diff --git a/SpringJava/JPA/src/main/java/org/resthub/web/controller/ServiceBasedRestController.java b/SpringJava/JPA/src/main/java/org/resthub/web/controller/ServiceBasedRestController.java deleted file mode 100644 index cd93416..0000000 --- a/SpringJava/JPA/src/main/java/org/resthub/web/controller/ServiceBasedRestController.java +++ /dev/null @@ -1,146 +0,0 @@ -package org.resthub.web.controller; - -import java.io.Serializable; -import java.util.Set; - -import org.resthub.common.exception.NotFoundException; -import org.resthub.common.service.CrudService; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Sort; -import org.springframework.util.Assert; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestParam; - -/** - * Abstract REST controller using a service implementation - *

- *

You should extend this class when you want to use a 3 layers pattern : Repository, Service and Controller - * If you don't have a real service (also called business layer), consider using RepositoryBasedRestController

- *

- *

Default implementation uses "id" field (usually a Long) in order to identify resources in web request. - * If your want to identity resources by a slug (human readable identifier), your should override findById() method with for example : - *

- *

- * 
- * {@literal @}Override
- * public Sample findById({@literal @}PathVariable String id) {
- * Sample sample = this.service.findByName(id);
- * if (sample == null) {
- * throw new NotFoundException();
- * }
- * return sample;
- * }
- * 
- * 
- * - * @param Your resource class to manage, maybe an entity or DTO class - * @param Resource id type, usually Long or String - * @param The service class - * @see RepositoryBasedRestController - */ -public abstract class ServiceBasedRestController implements - RestController { - - protected S service; - - /** - * You should override this setter in order to inject your service with @Inject annotation - * - * @param service The service to be injected - */ - public void setService(S service) { - this.service = service; - } - - /** - * {@inheritDoc} - */ - @Override - public T create(@RequestBody T resource) { - return (T) this.service.create(resource); - } - - /** - * {@inheritDoc} - */ - @Override - public T update(@PathVariable ID id, @RequestBody T resource) { - Assert.notNull(id, "id cannot be null"); - - T retreivedResource = this.findById(id); - if (retreivedResource == null) { - throw new NotFoundException(); - } - - return (T) this.service.update(resource); - } - - /** - * {@inheritDoc} - */ - @Override - public Iterable findAll() { - return service.findAll(); - } - - /** - * {@inheritDoc} - */ - @Override - public Page findPaginated(@RequestParam(value = "page", required = false, defaultValue = "1") Integer page, - @RequestParam(value = "size", required = false, defaultValue = "10") Integer size, - @RequestParam(value = "direction", required = false, defaultValue = "") String direction, - @RequestParam(value = "properties", required = false) String properties) { - Assert.isTrue(page > 0, "Page index must be greater than 0"); - Assert.isTrue(direction.isEmpty() || direction.equalsIgnoreCase(Sort.Direction.ASC.toString()) || direction.equalsIgnoreCase(Sort.Direction.DESC.toString()), "Direction should be ASC or DESC"); - if (direction.isEmpty()) { - return this.service.findAll(new PageRequest(page - 1, size)); - } else { - Assert.notNull(properties); - return this.service.findAll(new PageRequest(page - 1, size, new Sort(Sort.Direction.fromString(direction.toUpperCase()), properties.split(",")))); - } - } - - /** - * {@inheritDoc} - */ - @Override - public T findById(@PathVariable ID id) { - T resource = (T) this.service.findById(id); - if (resource == null) { - throw new NotFoundException(); - } - - return resource; - } - - /** - * {@inheritDoc} - */ - @Override - public Iterable findByIds(@RequestParam(value = "ids[]") Set ids) { - Assert.notNull(ids, "ids list cannot be null"); - return this.service.findByIds(ids); - } - - - /** - * {@inheritDoc} - */ - @Override - public void delete() { - this.service.deleteAllWithCascade(); - } - - /** - * {@inheritDoc} - */ - @Override - public void delete(@PathVariable ID id) { - T resource = this.findById(id); - this.service.delete(resource); - } -} - diff --git a/SpringJava/JPA/src/main/resources/jpa.properties b/SpringJava/JPA/src/main/resources/jpa.properties deleted file mode 100644 index 9f628d3..0000000 --- a/SpringJava/JPA/src/main/resources/jpa.properties +++ /dev/null @@ -1,2 +0,0 @@ -jpa.dialect=org.hibernate.dialect.MySQL5Dialect -jpa.show_sql=false \ No newline at end of file diff --git a/SpringJava/JPA/src/main/resources/log4j2.xml b/SpringJava/JPA/src/main/resources/log4j2.xml deleted file mode 100644 index eec10be..0000000 --- a/SpringJava/JPA/src/main/resources/log4j2.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/SpringJava/JPA/src/main/resources/spring-configuration/datasource-configuration.xml b/SpringJava/JPA/src/main/resources/spring-configuration/datasource-configuration.xml deleted file mode 100644 index 6b5500c..0000000 --- a/SpringJava/JPA/src/main/resources/spring-configuration/datasource-configuration.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/SpringJava/JPA/src/main/resources/spring-configuration/jpa-configuration.xml b/SpringJava/JPA/src/main/resources/spring-configuration/jpa-configuration.xml deleted file mode 100644 index b460a27..0000000 --- a/SpringJava/JPA/src/main/resources/spring-configuration/jpa-configuration.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - _AUDITED - REVISION - REVISION_TYPE - true - org.hibernate.envers.strategy.ValidityAuditStrategy - REVISION_END - true - REVISION_END_TIMESTAMP - _MODIFIED - - - - - - - diff --git a/SpringJava/JPA/src/main/resources/spring-configuration/liquibase/changeLogs.xml b/SpringJava/JPA/src/main/resources/spring-configuration/liquibase/changeLogs.xml deleted file mode 100644 index 4d558c2..0000000 --- a/SpringJava/JPA/src/main/resources/spring-configuration/liquibase/changeLogs.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - diff --git a/SpringJava/JPA/src/main/resources/spring-configuration/liquibase/ddlChangelog.xml b/SpringJava/JPA/src/main/resources/spring-configuration/liquibase/ddlChangelog.xml deleted file mode 100644 index e8fbd91..0000000 --- a/SpringJava/JPA/src/main/resources/spring-configuration/liquibase/ddlChangelog.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/SpringJava/JPA/src/main/resources/spring-configuration/liquibase/dmlChangelog.xml b/SpringJava/JPA/src/main/resources/spring-configuration/liquibase/dmlChangelog.xml deleted file mode 100644 index 0f07094..0000000 --- a/SpringJava/JPA/src/main/resources/spring-configuration/liquibase/dmlChangelog.xml +++ /dev/null @@ -1,1960 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/SpringJava/JPA/src/main/resources/spring-configuration/liquibase/liquibase.xml b/SpringJava/JPA/src/main/resources/spring-configuration/liquibase/liquibase.xml deleted file mode 100644 index 705fc46..0000000 --- a/SpringJava/JPA/src/main/resources/spring-configuration/liquibase/liquibase.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/SpringJava/JPA/src/main/resources/spring-configuration/mvc/rest/rest-config.xml b/SpringJava/JPA/src/main/resources/spring-configuration/mvc/rest/rest-config.xml deleted file mode 100644 index e8cc1a8..0000000 --- a/SpringJava/JPA/src/main/resources/spring-configuration/mvc/rest/rest-config.xml +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/SpringJava/JPA/src/main/resources/spring-configuration/spring-configuration.xml b/SpringJava/JPA/src/main/resources/spring-configuration/spring-configuration.xml deleted file mode 100644 index 505576c..0000000 --- a/SpringJava/JPA/src/main/resources/spring-configuration/spring-configuration.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/SpringJava/JPA/src/main/webapp/WEB-INF/web.xml b/SpringJava/JPA/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 31173b6..0000000 --- a/SpringJava/JPA/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - Spring JPA: example JPA - - - - org.springframework.web.context.ContextLoaderListener - - - - - spring.profiles.default - ${environment.profile} - contextConfigLocation - - classpath*:spring-configuration/*.xml - - - - - - spring-rest - org.springframework.web.servlet.DispatcherServlet - 1 - true - - contextConfigLocation - classpath*:spring-configuration/mvc/rest/*.xml - - - - - spring-rest - - /* - - - - - - OpenEntityManagerInViewFilter - org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter - - - OpenEntityManagerInViewFilter - /* - - - - diff --git a/SpringJava/JPA/src/test/java/de/spring/persistence/example/domain/AdTest.java b/SpringJava/JPA/src/test/java/de/spring/persistence/example/domain/AdTest.java deleted file mode 100644 index 7fb4c57..0000000 --- a/SpringJava/JPA/src/test/java/de/spring/persistence/example/domain/AdTest.java +++ /dev/null @@ -1,5 +0,0 @@ -package de.spring.persistence.example.domain; - -public class AdTest { - -} diff --git a/SpringJava/JPA/src/test/resources/datasource-test-configuration.xml b/SpringJava/JPA/src/test/resources/datasource-test-configuration.xml deleted file mode 100644 index 05ca000..0000000 --- a/SpringJava/JPA/src/test/resources/datasource-test-configuration.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - -- 2.1.4