├── .travis.yml ├── scoring ├── adapters-input │ └── src │ │ └── main │ │ ├── resources │ │ ├── application.properties │ │ └── static │ │ │ ├── index.html │ │ │ └── app.js │ │ └── java │ │ └── com │ │ └── mploed │ │ └── dddwithspring │ │ └── scoring │ │ ├── web │ │ ├── WebSocketMessage.java │ │ └── WebSocketController.java │ │ ├── incoming │ │ ├── realEstate │ │ │ ├── Interior.java │ │ │ ├── ParkingSpace.java │ │ │ ├── Construction.java │ │ │ ├── TypeOfUse.java │ │ │ ├── Attic.java │ │ │ ├── Basement.java │ │ │ ├── UsageOfLoan.java │ │ │ ├── ObjectType.java │ │ │ ├── ApartmentLocation.java │ │ │ ├── Feature.java │ │ │ └── ApartmentInformation.java │ │ ├── AgencyMessage.java │ │ ├── applicant │ │ │ ├── MaritalStatus.java │ │ │ ├── Employment.java │ │ │ ├── Business.java │ │ │ ├── Address.java │ │ │ └── Applicant.java │ │ ├── financing │ │ │ ├── OwnResources.java │ │ │ ├── PurchaseCosts.java │ │ │ ├── Loan.java │ │ │ └── Financing.java │ │ ├── creditAgency │ │ │ └── AgencyRating.java │ │ ├── AgencyResultArrivedEvent.java │ │ ├── household │ │ │ ├── MonthlyExpenses.java │ │ │ ├── EarningCapacity.java │ │ │ └── Household.java │ │ └── ApplicationSubmittedEvent.java │ │ ├── messaging │ │ ├── ApplicationProcessChannels.java │ │ ├── SpringEventListener.java │ │ └── IncomingMessageListener.java │ │ ├── WebSocketConfig.java │ │ ├── InputAdaptersConfiguration.java │ │ └── feeds │ │ └── CreditAgencyPoller.java ├── aggregates │ ├── src │ │ ├── main │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── mploed │ │ │ │ └── dddwithspring │ │ │ │ └── scoring │ │ │ │ ├── scoringResult │ │ │ │ ├── ScoringColor.java │ │ │ │ ├── OverallScoringResult.java │ │ │ │ ├── ScoringResultRootEntity.java │ │ │ │ ├── ScoringCalculationResults.java │ │ │ │ └── ScoringResultAggregate.java │ │ │ │ ├── financialSituation │ │ │ │ ├── Outgoings.java │ │ │ │ ├── Incomings.java │ │ │ │ ├── FinancialSituationRootEntity.java │ │ │ │ └── FinancialSituationAggregate.java │ │ │ │ ├── agencyResult │ │ │ │ ├── KoCriteria.java │ │ │ │ ├── WarningMessage.java │ │ │ │ ├── AgencyResultRootEntity.java │ │ │ │ └── AgencyResultAggregate.java │ │ │ │ └── applicant │ │ │ │ ├── AccountBalance.java │ │ │ │ ├── Address.java │ │ │ │ └── ApplicantAggregate.java │ │ └── test │ │ │ ├── resources │ │ │ └── com │ │ │ │ └── mploed │ │ │ │ └── dddwithspring │ │ │ │ └── scoring │ │ │ │ └── archunit │ │ │ │ └── scoring.puml │ │ │ └── java │ │ │ └── com │ │ │ └── mploed │ │ │ └── dddwithspring │ │ │ └── scoring │ │ │ ├── agencyResult │ │ │ └── AgencyResultTest.java │ │ │ └── archunit │ │ │ └── AggregateArchitectureTest.java │ ├── jqassistant │ │ └── my-rules.xml │ └── pom.xml ├── microarchitecture │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── com │ │ │ └── mploed │ │ │ └── dddwithspring │ │ │ └── scoring │ │ │ └── microarchitecture │ │ │ ├── Aggregate.java │ │ │ └── AggregateBuilder.java │ └── pom.xml ├── adapters-output │ └── src │ │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── mploed │ │ │ └── dddwithspring │ │ │ └── scoring │ │ │ ├── SpringBootTestApplication.java │ │ │ └── AgencyResultRepositoryTest.java │ │ └── main │ │ └── java │ │ └── com │ │ └── mploed │ │ └── dddwithspring │ │ └── scoring │ │ ├── agencyResult │ │ ├── AgencyResultDAO.java │ │ ├── AgencyMessage.java │ │ ├── AgencyResultProjection.java │ │ └── AgencyResultJPARepository.java │ │ ├── scoringResult │ │ ├── ScoringResultDAO.java │ │ ├── DetailedScoringResults.java │ │ ├── ScoringResultEntity.java │ │ └── ScoringResultJPARepository.java │ │ ├── financialSituation │ │ ├── FinancialSituationResultDAO.java │ │ ├── FinancialSituationResultProjection.java │ │ └── FinancialSituationResultJPARepository.java │ │ └── applicant │ │ ├── ApplicantResultDAO.java │ │ ├── ApplicantResultProjection.java │ │ └── ApplicantResultJPARepository.java ├── sharedmodel │ ├── src │ │ ├── main │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── mploed │ │ │ │ └── dddwithspring │ │ │ │ └── scoring │ │ │ │ ├── ApplicationNumber.java │ │ │ │ ├── Money.java │ │ │ │ └── PersonId.java │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── mploed │ │ │ └── dddwithspring │ │ │ └── scoring │ │ │ └── MoneyTest.java │ └── pom.xml ├── scoring-application │ └── src │ │ └── main │ │ ├── resources │ │ └── application.properties │ │ └── java │ │ └── com │ │ └── mploed │ │ └── dddwithspring │ │ └── scoring │ │ └── ScoringApplication.java ├── Dockerfile ├── application-services │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── com │ │ │ └── mploed │ │ │ └── dddwithspring │ │ │ └── scoring │ │ │ └── appservices │ │ │ ├── repositories │ │ │ ├── AgencyResultRepository.java │ │ │ ├── ScoringResultRepository.java │ │ │ ├── FinancialSituationResultRepository.java │ │ │ └── ApplicantResultRepository.java │ │ │ ├── internalevents │ │ │ ├── CreditAgencyResultArrived.java │ │ │ ├── CreditApplicationArrived.java │ │ │ ├── PartOfScoringPerformed.java │ │ │ └── ScoringPerformed.java │ │ │ └── dto │ │ │ ├── FinancialSituation.java │ │ │ ├── Applicant.java │ │ │ └── CreditApplication.java │ └── pom.xml └── pom.xml ├── assets ├── src │ ├── main │ │ ├── resources │ │ │ ├── application.properties │ │ │ └── static │ │ │ │ ├── cssAssets.html │ │ │ │ └── jsAssets.html │ │ └── java │ │ │ └── com │ │ │ └── mploed │ │ │ └── dddwithspring │ │ │ └── assets │ │ │ └── AssetsApplication.java │ └── test │ │ └── java │ │ └── com │ │ └── mploed │ │ └── dddwithspring │ │ └── assets │ │ └── AssetsApplicationTests.java ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── .gitignore └── pom.xml ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── infrastructure_varnish ├── start ├── default.vcl └── Dockerfile ├── credit-sales-funnel ├── src │ └── main │ │ ├── resources │ │ ├── static │ │ │ └── BigPugLoans.jpg │ │ ├── application.properties │ │ └── templates │ │ │ ├── index.html │ │ │ └── layout │ │ │ ├── baseIndex.html │ │ │ └── baseLayout.html │ │ └── java │ │ └── com │ │ └── mploed │ │ └── dddwithspring │ │ └── creditsalesfunnel │ │ ├── model │ │ ├── validation │ │ │ └── ApplicationSubmissionGroup.java │ │ ├── realEstate │ │ │ ├── Interior.java │ │ │ ├── ParkingSpace.java │ │ │ ├── Construction.java │ │ │ ├── TypeOfUse.java │ │ │ ├── Attic.java │ │ │ ├── Basement.java │ │ │ ├── UsageOfLoan.java │ │ │ ├── ObjectType.java │ │ │ ├── ApartmentLocation.java │ │ │ ├── Feature.java │ │ │ └── ApartmentInformation.java │ │ ├── applicant │ │ │ ├── MaritalStatus.java │ │ │ ├── Employment.java │ │ │ ├── Business.java │ │ │ └── Address.java │ │ ├── financing │ │ │ ├── OwnResources.java │ │ │ ├── PurchaseCosts.java │ │ │ ├── Loan.java │ │ │ └── Financing.java │ │ ├── CreditApplicationForm.java │ │ └── household │ │ │ ├── EarningCapacity.java │ │ │ ├── MonthlyExpenses.java │ │ │ └── Household.java │ │ ├── event │ │ ├── CreditSalesFunnelChannels.java │ │ └── CreditApplicationSubmittedEvent.java │ │ ├── repository │ │ ├── FinancingRepository.java │ │ ├── HouseholdRepository.java │ │ ├── RealEstatePropertyRepository.java │ │ └── ApplicantRepository.java │ │ └── CreditSalesFunnelApplication.java └── Dockerfile ├── credit-agency ├── src │ └── main │ │ ├── resources │ │ └── application.properties │ │ └── java │ │ └── com │ │ └── mploed │ │ └── dddwithspring │ │ └── creditagency │ │ ├── messaging │ │ ├── CreditAgencyChannels.java │ │ └── IncomingMessageListener.java │ │ ├── events │ │ └── incoming │ │ │ ├── applicant │ │ │ ├── MaritalStatus.java │ │ │ ├── Employment.java │ │ │ ├── Business.java │ │ │ ├── Address.java │ │ │ └── Applicant.java │ │ │ └── ApplicationSubmittedEvent.java │ │ ├── repository │ │ └── PersonRatingRepository.java │ │ ├── CreditAgencyApplication.java │ │ ├── web │ │ ├── PersonRatingRestController.java │ │ ├── PersonRatingController.java │ │ └── PersonRatingAtomFeedView.java │ │ ├── model │ │ ├── RatingModel.java │ │ └── PersonRating.java │ │ └── service │ │ └── PersonRatingQueryService.java └── Dockerfile ├── pom.xml ├── .gitignore ├── README.md └── docker-compose.yml /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: openjdk8 -------------------------------------------------------------------------------- /scoring/adapters-input/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.servlet.context-path=/scoring/* -------------------------------------------------------------------------------- /assets/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=9003 2 | server.servlet.context-path=/assets 3 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mploed/ddd-with-spring/HEAD/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /assets/src/main/resources/static/cssAssets.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /infrastructure_varnish/start: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | varnishd -f /etc/varnish/default.vcl -s malloc,200M -a 0.0.0.0:8080 3 | varnishlog -------------------------------------------------------------------------------- /assets/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mploed/ddd-with-spring/HEAD/assets/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.3/apache-maven-3.5.3-bin.zip 2 | -------------------------------------------------------------------------------- /assets/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip 2 | -------------------------------------------------------------------------------- /credit-sales-funnel/src/main/resources/static/BigPugLoans.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mploed/ddd-with-spring/HEAD/credit-sales-funnel/src/main/resources/static/BigPugLoans.jpg -------------------------------------------------------------------------------- /scoring/aggregates/src/main/java/com/mploed/dddwithspring/scoring/scoringResult/ScoringColor.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.scoringResult; 2 | 3 | enum ScoringColor { 4 | GREEN, YELLOW, RED 5 | } 6 | -------------------------------------------------------------------------------- /assets/src/main/resources/static/jsAssets.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /credit-sales-funnel/src/main/java/com/mploed/dddwithspring/creditsalesfunnel/model/validation/ApplicationSubmissionGroup.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditsalesfunnel.model.validation; 2 | 3 | public interface ApplicationSubmissionGroup { 4 | } 5 | -------------------------------------------------------------------------------- /scoring/microarchitecture/src/main/java/com/mploed/dddwithspring/scoring/microarchitecture/Aggregate.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.microarchitecture; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Target(ElementType.TYPE) 6 | @Documented 7 | public @interface Aggregate { 8 | } 9 | -------------------------------------------------------------------------------- /credit-agency/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=9002 2 | management.security.enabled=false 3 | spring.jpa.show-sql=true 4 | 5 | spring.cloud.stream.bindings.applicationSubmittedIn.destination=CreditApplicationSubmittedTopic 6 | spring.cloud.stream.bindings.applicationSubmittedIn.contentType=application/json 7 | -------------------------------------------------------------------------------- /credit-sales-funnel/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=9000 2 | management.security.enabled=false 3 | spring.jpa.show-sql=true 4 | 5 | spring.cloud.stream.bindings.creditApplicationSubmittedOut.destination=CreditApplicationSubmittedTopic 6 | spring.cloud.stream.bindings.creditApplicationSubmittedOut.contentType=application/json 7 | -------------------------------------------------------------------------------- /scoring/adapters-output/src/test/java/com/mploed/dddwithspring/scoring/SpringBootTestApplication.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring; 2 | 3 | import org.springframework.boot.autoconfigure.SpringBootApplication; 4 | 5 | @SpringBootApplication(scanBasePackages = "com.mploed.dddwithspring") 6 | public class SpringBootTestApplication { 7 | } 8 | -------------------------------------------------------------------------------- /scoring/adapters-output/src/main/java/com/mploed/dddwithspring/scoring/agencyResult/AgencyResultDAO.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.agencyResult; 2 | 3 | 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | interface AgencyResultDAO extends JpaRepository { 7 | AgencyResultProjection findByPersonId(String personId); 8 | } 9 | -------------------------------------------------------------------------------- /scoring/adapters-output/src/main/java/com/mploed/dddwithspring/scoring/scoringResult/ScoringResultDAO.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.scoringResult; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | interface ScoringResultDAO extends JpaRepository { 6 | ScoringResultEntity findByApplicationNumber(String applicationNumber); 7 | } 8 | -------------------------------------------------------------------------------- /credit-agency/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jdk-alpine 2 | LABEL maintainer="michael.ploed@innoq.com" 3 | VOLUME /tmp 4 | ENV JAVA_OPTS="" 5 | ENV SPRING_APPLICATION_JSON='{"spring": {"rabbitmq": {"host": "localrabbit", "addresses": "rabbit-mq"}}}' 6 | ENTRYPOINT exec java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar 7 | EXPOSE 9002 8 | ADD target/credit-agency-0.0.1-SNAPSHOT.jar app.jar 9 | -------------------------------------------------------------------------------- /scoring/aggregates/src/main/java/com/mploed/dddwithspring/scoring/scoringResult/OverallScoringResult.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.scoringResult; 2 | 3 | class OverallScoringResult { 4 | final int points; 5 | final ScoringColor color; 6 | 7 | public OverallScoringResult(int points, ScoringColor color) { 8 | this.points = points; 9 | this.color = color; 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /credit-sales-funnel/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jdk-alpine 2 | LABEL maintainer="michael.ploed@innoq.com" 3 | VOLUME /tmp 4 | ENV SPRING_APPLICATION_JSON='{"spring": {"rabbitmq": {"host": "localrabbit", "addresses": "rabbit-mq"}}}' 5 | ENV JAVA_OPTS="" 6 | ENTRYPOINT exec java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar 7 | EXPOSE 9001 8 | ADD target/credit-sales-funnel-0.0.1-SNAPSHOT.jar app.jar 9 | -------------------------------------------------------------------------------- /scoring/microarchitecture/src/main/java/com/mploed/dddwithspring/scoring/microarchitecture/AggregateBuilder.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.microarchitecture; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Target; 6 | 7 | @Target(ElementType.TYPE) 8 | @Documented 9 | public @interface AggregateBuilder { 10 | } 11 | -------------------------------------------------------------------------------- /credit-sales-funnel/src/main/java/com/mploed/dddwithspring/creditsalesfunnel/event/CreditSalesFunnelChannels.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditsalesfunnel.event; 2 | 3 | import org.springframework.cloud.stream.annotation.Output; 4 | import org.springframework.messaging.MessageChannel; 5 | 6 | public interface CreditSalesFunnelChannels { 7 | 8 | @Output 9 | MessageChannel creditApplicationSubmittedOut(); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /scoring/adapters-input/src/main/java/com/mploed/dddwithspring/scoring/web/WebSocketMessage.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.web; 2 | 3 | public class WebSocketMessage { 4 | private String content; 5 | 6 | public WebSocketMessage(String content) { 7 | this.content = content; 8 | } 9 | 10 | public WebSocketMessage() { 11 | } 12 | 13 | public String getContent() { 14 | return content; 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /scoring/sharedmodel/src/main/java/com/mploed/dddwithspring/scoring/ApplicationNumber.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring; 2 | 3 | public class ApplicationNumber { 4 | private String applicationNumber; 5 | 6 | public ApplicationNumber(String applicationNumber) { 7 | this.applicationNumber = applicationNumber; 8 | } 9 | 10 | @Override 11 | public String toString() { 12 | return applicationNumber; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /scoring/scoring-application/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=9001 2 | server.servlet.context-path=/scoring 3 | management.security.enabled=false 4 | spring.jpa.show-sql=true 5 | 6 | spring.cloud.stream.bindings.applicationSubmittedIn.destination=CreditApplicationSubmittedTopic 7 | spring.cloud.stream.bindings.applicationSubmittedIn.contentType=application/json 8 | 9 | creditAgencyFeed=http://localhost:9002/person-rating/feed -------------------------------------------------------------------------------- /assets/src/main/java/com/mploed/dddwithspring/assets/AssetsApplication.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.assets; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class AssetsApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(AssetsApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /scoring/adapters-output/src/main/java/com/mploed/dddwithspring/scoring/financialSituation/FinancialSituationResultDAO.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.financialSituation; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | public interface FinancialSituationResultDAO extends JpaRepository { 6 | FinancialSituationResultProjection findByApplicationNumber(String applicationNumber); 7 | } 8 | -------------------------------------------------------------------------------- /credit-agency/src/main/java/com/mploed/dddwithspring/creditagency/messaging/CreditAgencyChannels.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditagency.messaging; 2 | 3 | import org.springframework.cloud.stream.annotation.Input; 4 | import org.springframework.messaging.SubscribableChannel; 5 | 6 | public interface CreditAgencyChannels { 7 | String APPLICATION_SUBMITTED = "applicationSubmittedIn"; 8 | 9 | @Input 10 | SubscribableChannel applicationSubmittedIn(); 11 | } 12 | -------------------------------------------------------------------------------- /scoring/scoring-application/src/main/java/com/mploed/dddwithspring/scoring/ScoringApplication.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class ScoringApplication { 8 | public static void main(String[] args) { 9 | SpringApplication.run(ScoringApplication.class, args); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /credit-sales-funnel/src/main/java/com/mploed/dddwithspring/creditsalesfunnel/repository/FinancingRepository.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditsalesfunnel.repository; 2 | 3 | import com.mploed.dddwithspring.creditsalesfunnel.model.financing.Financing; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface FinancingRepository extends JpaRepository { 7 | Financing findByApplicationNumber(String applicationNumber); 8 | } 9 | -------------------------------------------------------------------------------- /credit-sales-funnel/src/main/java/com/mploed/dddwithspring/creditsalesfunnel/repository/HouseholdRepository.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditsalesfunnel.repository; 2 | 3 | import com.mploed.dddwithspring.creditsalesfunnel.model.household.Household; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface HouseholdRepository extends JpaRepository { 7 | Household findByApplicationNumber(String applicationNumber); 8 | } 9 | -------------------------------------------------------------------------------- /scoring/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jdk-alpine 2 | LABEL maintainer="michael.ploed@innoq.com" 3 | VOLUME /tmp 4 | ENV JAVA_OPTS="" 5 | ENV SPRING_APPLICATION_JSON='{"creditAgencyFeed": "http://credit-agency:9002/person-rating/feed", "spring": {"rabbitmq": {"host": "localrabbit", "addresses": "rabbit-mq"}}}' 6 | ENTRYPOINT exec java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar 7 | EXPOSE 9001 8 | ADD scoring-application/target/scoring-application-0.0.1-SNAPSHOT.jar app.jar 9 | -------------------------------------------------------------------------------- /assets/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | 30 | ### VS Code ### 31 | .vscode/ 32 | -------------------------------------------------------------------------------- /scoring/adapters-input/src/main/java/com/mploed/dddwithspring/scoring/incoming/realEstate/Interior.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.incoming.realEstate; 2 | 3 | public enum Interior { 4 | STANDARD("Standard"), 5 | LUXURY("Luxury"), 6 | SIMPLE("Simple"); 7 | 8 | private final String displayName; 9 | 10 | Interior(String displayName) { 11 | this.displayName = displayName; 12 | } 13 | 14 | public String getDisplayName() { 15 | return displayName; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /scoring/aggregates/src/main/java/com/mploed/dddwithspring/scoring/financialSituation/Outgoings.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.financialSituation; 2 | 3 | import com.mploed.dddwithspring.scoring.Money; 4 | 5 | class Outgoings { 6 | Money rent; 7 | Money costOfLiving; 8 | 9 | Outgoings(Money rent, Money costOfLiving) { 10 | this.rent = rent; 11 | this.costOfLiving = costOfLiving; 12 | } 13 | 14 | Money sum() { 15 | return rent.add(costOfLiving); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /assets/src/test/java/com/mploed/dddwithspring/assets/AssetsApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.assets; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class AssetsApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /scoring/aggregates/src/main/java/com/mploed/dddwithspring/scoring/agencyResult/KoCriteria.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.agencyResult; 2 | 3 | class KoCriteria { 4 | private String key; 5 | private String messageText; 6 | 7 | KoCriteria(String key, String messageText) { 8 | this.key = key; 9 | this.messageText = messageText; 10 | } 11 | 12 | String getKey() { 13 | return key; 14 | } 15 | 16 | String getMessageText() { 17 | return messageText; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /scoring/aggregates/src/main/java/com/mploed/dddwithspring/scoring/financialSituation/Incomings.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.financialSituation; 2 | 3 | import com.mploed.dddwithspring.scoring.Money; 4 | 5 | class Incomings { 6 | Money salary; 7 | Money otherIncome; 8 | 9 | Incomings(Money salary, Money otherIncome) { 10 | this.salary = salary; 11 | this.otherIncome = otherIncome; 12 | } 13 | 14 | Money sum() { 15 | return salary.add(otherIncome); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /credit-sales-funnel/src/main/java/com/mploed/dddwithspring/creditsalesfunnel/model/realEstate/Interior.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditsalesfunnel.model.realEstate; 2 | 3 | public enum Interior { 4 | STANDARD("Standard"), 5 | LUXURY("Luxury"), 6 | SIMPLE("Simple"); 7 | 8 | private final String displayName; 9 | 10 | Interior(String displayName) { 11 | this.displayName = displayName; 12 | } 13 | 14 | public String getDisplayName() { 15 | return displayName; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /scoring/aggregates/src/main/java/com/mploed/dddwithspring/scoring/agencyResult/WarningMessage.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.agencyResult; 2 | 3 | class WarningMessage { 4 | private String key; 5 | private String messageText; 6 | 7 | WarningMessage(String key, String messageText) { 8 | this.key = key; 9 | this.messageText = messageText; 10 | } 11 | 12 | String getKey() { 13 | return key; 14 | } 15 | 16 | String getMessageText() { 17 | return messageText; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /scoring/adapters-input/src/main/java/com/mploed/dddwithspring/scoring/incoming/realEstate/ParkingSpace.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.incoming.realEstate; 2 | 3 | public enum ParkingSpace { 4 | NOT_PRESENT("Not present"), 5 | CARPORT("Carport"), 6 | GARAGE("Garage"); 7 | 8 | private final String displayName; 9 | 10 | ParkingSpace(String displayName) { 11 | this.displayName = displayName; 12 | } 13 | 14 | public String getDisplayName() { 15 | return displayName; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /scoring/adapters-input/src/main/java/com/mploed/dddwithspring/scoring/incoming/realEstate/Construction.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.incoming.realEstate; 2 | 3 | public enum Construction { 4 | PREFABRICATED_HOUSE("Prefabricated house"), 5 | WOOD("Wood"), 6 | STONE("Stone"); 7 | 8 | private final String displayName; 9 | 10 | Construction(String displayName) { 11 | this.displayName = displayName; 12 | } 13 | 14 | public String getDisplayName() { 15 | return displayName; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /scoring/adapters-input/src/main/java/com/mploed/dddwithspring/scoring/incoming/realEstate/TypeOfUse.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.incoming.realEstate; 2 | 3 | public enum TypeOfUse { 4 | FOR_LEASE("For lease"), 5 | SELF_OCCUPIED("Self occupied"), 6 | COMMERCIAL("Commercial"); 7 | 8 | private final String displayName; 9 | 10 | TypeOfUse(String displayName) { 11 | this.displayName = displayName; 12 | } 13 | 14 | public String getDisplayName() { 15 | return displayName; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /credit-sales-funnel/src/main/java/com/mploed/dddwithspring/creditsalesfunnel/model/realEstate/ParkingSpace.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditsalesfunnel.model.realEstate; 2 | 3 | public enum ParkingSpace { 4 | NOT_PRESENT("Not present"), 5 | CARPORT("Carport"), 6 | GARAGE("Garage"); 7 | 8 | private final String displayName; 9 | 10 | ParkingSpace(String displayName) { 11 | this.displayName = displayName; 12 | } 13 | 14 | public String getDisplayName() { 15 | return displayName; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /credit-sales-funnel/src/main/java/com/mploed/dddwithspring/creditsalesfunnel/repository/RealEstatePropertyRepository.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditsalesfunnel.repository; 2 | 3 | import com.mploed.dddwithspring.creditsalesfunnel.model.realEstate.RealEstateProperty; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface RealEstatePropertyRepository extends JpaRepository { 7 | RealEstateProperty findByApplicationNumber(String applicationNumber); 8 | } 9 | -------------------------------------------------------------------------------- /scoring/adapters-input/src/main/java/com/mploed/dddwithspring/scoring/incoming/AgencyMessage.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.incoming; 2 | 3 | public class AgencyMessage { 4 | private String key; 5 | private String messageText; 6 | 7 | AgencyMessage(String key, String messageText) { 8 | this.key = key; 9 | this.messageText = messageText; 10 | } 11 | 12 | public String getKey() { 13 | return key; 14 | } 15 | 16 | public String getMessageText() { 17 | return messageText; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /scoring/application-services/src/main/java/com/mploed/dddwithspring/scoring/appservices/repositories/AgencyResultRepository.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.appservices.repositories; 2 | 3 | 4 | import com.mploed.dddwithspring.scoring.PersonId; 5 | import com.mploed.dddwithspring.scoring.agencyResult.AgencyResultAggregate; 6 | 7 | public interface AgencyResultRepository { 8 | void save(AgencyResultAggregate agencyResultAggregate); 9 | 10 | AgencyResultAggregate retrieve(PersonId personId); 11 | } 12 | -------------------------------------------------------------------------------- /credit-sales-funnel/src/main/java/com/mploed/dddwithspring/creditsalesfunnel/model/realEstate/Construction.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditsalesfunnel.model.realEstate; 2 | 3 | public enum Construction { 4 | PREFABRICATED_HOUSE("Prefabricated house"), 5 | WOOD("Wood"), 6 | STONE("Stone"); 7 | 8 | private final String displayName; 9 | 10 | Construction(String displayName) { 11 | this.displayName = displayName; 12 | } 13 | 14 | public String getDisplayName() { 15 | return displayName; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /credit-sales-funnel/src/main/java/com/mploed/dddwithspring/creditsalesfunnel/model/realEstate/TypeOfUse.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditsalesfunnel.model.realEstate; 2 | 3 | public enum TypeOfUse { 4 | FOR_LEASE("For lease"), 5 | SELF_OCCUPIED("Self occupied"), 6 | COMMERCIAL("Commercial"); 7 | 8 | private final String displayName; 9 | 10 | TypeOfUse(String displayName) { 11 | this.displayName = displayName; 12 | } 13 | 14 | public String getDisplayName() { 15 | return displayName; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /scoring/adapters-input/src/main/java/com/mploed/dddwithspring/scoring/incoming/realEstate/Attic.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.incoming.realEstate; 2 | 3 | public enum Attic { 4 | NOT_PRESENT("Not present"), 5 | PARTLY_DEVELOPED("Partly developed"), 6 | FULLY_DEVELOPED("Fully developed"); 7 | 8 | private final String displayName; 9 | 10 | Attic(String displayName) { 11 | this.displayName = displayName; 12 | } 13 | 14 | public String getDisplayName() { 15 | return displayName; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /scoring/adapters-input/src/main/java/com/mploed/dddwithspring/scoring/incoming/applicant/MaritalStatus.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.incoming.applicant; 2 | 3 | public enum MaritalStatus { 4 | SINGLE("Single"), 5 | MARRIED("Married"), 6 | DIVORCED("Divorced"), 7 | WIDOWED("Widowed"); 8 | 9 | private final String displayName; 10 | 11 | MaritalStatus(String displayName) { 12 | this.displayName = displayName; 13 | } 14 | 15 | public String getDisplayName() { 16 | return displayName; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /scoring/adapters-input/src/main/java/com/mploed/dddwithspring/scoring/incoming/realEstate/Basement.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.incoming.realEstate; 2 | 3 | public enum Basement { 4 | NOT_PRESENT("Not present"), 5 | PARTLY_DEVELOPED("Partly developed"), 6 | FULLY_DEVELOPED("Fully developed"); 7 | 8 | private final String displayName; 9 | 10 | Basement(String displayName) { 11 | this.displayName = displayName; 12 | } 13 | 14 | public String getDisplayName() { 15 | return displayName; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /credit-sales-funnel/src/main/java/com/mploed/dddwithspring/creditsalesfunnel/model/realEstate/Attic.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditsalesfunnel.model.realEstate; 2 | 3 | public enum Attic { 4 | NOT_PRESENT("Not present"), 5 | PARTLY_DEVELOPED("Partly developed"), 6 | FULLY_DEVELOPED("Fully developed"); 7 | 8 | private final String displayName; 9 | 10 | Attic(String displayName) { 11 | this.displayName = displayName; 12 | } 13 | 14 | public String getDisplayName() { 15 | return displayName; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /credit-sales-funnel/src/main/java/com/mploed/dddwithspring/creditsalesfunnel/model/applicant/MaritalStatus.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditsalesfunnel.model.applicant; 2 | 3 | public enum MaritalStatus { 4 | SINGLE("Single"), 5 | MARRIED("Married"), 6 | DIVORCED("Divorced"), 7 | WIDOWED("Widowed"); 8 | 9 | private final String displayName; 10 | 11 | MaritalStatus(String displayName) { 12 | this.displayName = displayName; 13 | } 14 | 15 | public String getDisplayName() { 16 | return displayName; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /credit-agency/src/main/java/com/mploed/dddwithspring/creditagency/events/incoming/applicant/MaritalStatus.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditagency.events.incoming.applicant; 2 | 3 | public enum MaritalStatus { 4 | SINGLE("Single"), 5 | MARRIED("Married"), 6 | DIVORCED("Divorced"), 7 | WIDOWED("Widowed"); 8 | 9 | private final String displayName; 10 | 11 | MaritalStatus(String displayName) { 12 | this.displayName = displayName; 13 | } 14 | 15 | public String getDisplayName() { 16 | return displayName; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /credit-sales-funnel/src/main/java/com/mploed/dddwithspring/creditsalesfunnel/model/realEstate/Basement.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditsalesfunnel.model.realEstate; 2 | 3 | public enum Basement { 4 | NOT_PRESENT("Not present"), 5 | PARTLY_DEVELOPED("Partly developed"), 6 | FULLY_DEVELOPED("Fully developed"); 7 | 8 | private final String displayName; 9 | 10 | Basement(String displayName) { 11 | this.displayName = displayName; 12 | } 13 | 14 | public String getDisplayName() { 15 | return displayName; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /scoring/adapters-input/src/main/java/com/mploed/dddwithspring/scoring/incoming/realEstate/UsageOfLoan.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.incoming.realEstate; 2 | 3 | public enum UsageOfLoan { 4 | PURCHASE("Purchase"), 5 | CONSTRUCTION("Construction"), 6 | MODERNIZATION("Modernization"), 7 | OTHER("Other"); 8 | 9 | private final String displayName; 10 | 11 | UsageOfLoan(String displayName) { 12 | this.displayName = displayName; 13 | } 14 | 15 | public String getDisplayName() { 16 | return displayName; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /credit-sales-funnel/src/main/java/com/mploed/dddwithspring/creditsalesfunnel/model/realEstate/UsageOfLoan.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditsalesfunnel.model.realEstate; 2 | 3 | public enum UsageOfLoan { 4 | PURCHASE("Purchase"), 5 | CONSTRUCTION("Construction"), 6 | MODERNIZATION("Modernization"), 7 | OTHER("Other"); 8 | 9 | private final String displayName; 10 | 11 | UsageOfLoan(String displayName) { 12 | this.displayName = displayName; 13 | } 14 | 15 | public String getDisplayName() { 16 | return displayName; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /scoring/application-services/src/main/java/com/mploed/dddwithspring/scoring/appservices/repositories/ScoringResultRepository.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.appservices.repositories; 2 | 3 | import com.mploed.dddwithspring.scoring.ApplicationNumber; 4 | import com.mploed.dddwithspring.scoring.scoringResult.ScoringResultAggregate; 5 | 6 | public interface ScoringResultRepository { 7 | void save(ScoringResultAggregate scoringResultAggregate); 8 | 9 | ScoringResultAggregate findByApplicationNumber(ApplicationNumber applicationNumber); 10 | } 11 | -------------------------------------------------------------------------------- /scoring/adapters-input/src/main/java/com/mploed/dddwithspring/scoring/incoming/realEstate/ObjectType.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.incoming.realEstate; 2 | 3 | public enum ObjectType { 4 | SEMI_DETACHED_HOUSE("Semi detached house"), 5 | ROW_HOUSE("Row house"), 6 | DETACHED_HOUSE("Detached house"), 7 | APARTMENT("Apartment"); 8 | 9 | private final String displayName; 10 | 11 | ObjectType(String displayName) { 12 | this.displayName = displayName; 13 | } 14 | 15 | public String getDisplayName() { 16 | return displayName; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /scoring/adapters-output/src/main/java/com/mploed/dddwithspring/scoring/applicant/ApplicantResultDAO.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.applicant; 2 | 3 | import com.mploed.dddwithspring.scoring.agencyResult.AgencyResultProjection; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface ApplicantResultDAO extends JpaRepository { 7 | ApplicantResultProjection findByApplicationNumber(String applicationNumber); 8 | 9 | ApplicantResultProjection findByPersonId(String personId); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /credit-sales-funnel/src/main/java/com/mploed/dddwithspring/creditsalesfunnel/model/realEstate/ObjectType.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditsalesfunnel.model.realEstate; 2 | 3 | public enum ObjectType { 4 | SEMI_DETACHED_HOUSE("Semi detached house"), 5 | ROW_HOUSE("Row house"), 6 | DETACHED_HOUSE("Detached house"), 7 | APARTMENT("Apartment"); 8 | 9 | private final String displayName; 10 | 11 | ObjectType(String displayName) { 12 | this.displayName = displayName; 13 | } 14 | 15 | public String getDisplayName() { 16 | return displayName; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /scoring/adapters-input/src/main/java/com/mploed/dddwithspring/scoring/incoming/realEstate/ApartmentLocation.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.incoming.realEstate; 2 | 3 | public enum ApartmentLocation { 4 | BASEMENT_FLOOR("Basement floor"), 5 | GROUND_FLOOR("Ground floor"), 6 | UPPER_FLOOR("Upper floor"), 7 | PENTHOUSE("Penthouse"); 8 | 9 | private final String displayName; 10 | 11 | ApartmentLocation(String displayName) { 12 | this.displayName = displayName; 13 | } 14 | 15 | public String getDisplayName() { 16 | return displayName; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /credit-sales-funnel/src/main/java/com/mploed/dddwithspring/creditsalesfunnel/model/realEstate/ApartmentLocation.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditsalesfunnel.model.realEstate; 2 | 3 | public enum ApartmentLocation { 4 | BASEMENT_FLOOR("Basement floor"), 5 | GROUND_FLOOR("Ground floor"), 6 | UPPER_FLOOR("Upper floor"), 7 | PENTHOUSE("Penthouse"); 8 | 9 | private final String displayName; 10 | 11 | ApartmentLocation(String displayName) { 12 | this.displayName = displayName; 13 | } 14 | 15 | public String getDisplayName() { 16 | return displayName; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /scoring/application-services/src/main/java/com/mploed/dddwithspring/scoring/appservices/repositories/FinancialSituationResultRepository.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.appservices.repositories; 2 | 3 | 4 | import com.mploed.dddwithspring.scoring.ApplicationNumber; 5 | import com.mploed.dddwithspring.scoring.financialSituation.FinancialSituationAggregate; 6 | 7 | public interface FinancialSituationResultRepository { 8 | void save(FinancialSituationAggregate financialSituationAggregate); 9 | 10 | FinancialSituationAggregate retrieve(ApplicationNumber applicationNumber); 11 | } 12 | -------------------------------------------------------------------------------- /scoring/adapters-input/src/main/java/com/mploed/dddwithspring/scoring/messaging/ApplicationProcessChannels.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.messaging; 2 | 3 | import org.springframework.cloud.stream.annotation.Input; 4 | import org.springframework.cloud.stream.annotation.Output; 5 | import org.springframework.messaging.MessageChannel; 6 | import org.springframework.messaging.SubscribableChannel; 7 | 8 | public interface ApplicationProcessChannels { 9 | String APPLICATION_SUBMITTED = "applicationSubmittedIn"; 10 | 11 | @Input 12 | SubscribableChannel applicationSubmittedIn(); 13 | } 14 | -------------------------------------------------------------------------------- /infrastructure_varnish/default.vcl: -------------------------------------------------------------------------------- 1 | vcl 4.0; 2 | 3 | 4 | backend default { 5 | .host = "credit-sales-funnel"; 6 | .port = "9000"; 7 | } 8 | 9 | backend scoring { 10 | .host = "scoring"; 11 | .port = "9001"; 12 | } 13 | 14 | sub vcl_recv { 15 | if (req.url ~ "^/scoring") { 16 | set req.backend_hint = scoring; 17 | } else if (req.url ~ "^/application") { 18 | set req.backend_hint = default; 19 | return(pass); 20 | } else { 21 | set req.backend_hint = default; 22 | } 23 | } 24 | 25 | sub vcl_backend_response { 26 | set beresp.do_esi = true; 27 | } -------------------------------------------------------------------------------- /scoring/adapters-input/src/main/java/com/mploed/dddwithspring/scoring/incoming/applicant/Employment.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.incoming.applicant; 2 | 3 | public enum Employment { 4 | EMPLOYEE("Employee"), OFFICIAL("Official"), 5 | PENSIONER("Pensioner"), 6 | STUDENT("Student"), 7 | TRAINEE("Trainee"), 8 | FREELANCER("Freelancer"), 9 | UNEMPLOYED("Unemployed"), 10 | OTHER("Other"); 11 | 12 | private final String displayName; 13 | 14 | Employment(String displayName) { 15 | this.displayName = displayName; 16 | } 17 | 18 | public String getDisplayName() { 19 | return displayName; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /credit-agency/src/main/java/com/mploed/dddwithspring/creditagency/repository/PersonRatingRepository.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditagency.repository; 2 | 3 | import com.mploed.dddwithspring.creditagency.model.PersonRating; 4 | import org.springframework.data.domain.Example; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.data.jpa.repository.Query; 7 | 8 | import java.util.Date; 9 | 10 | 11 | public interface PersonRatingRepository extends JpaRepository { 12 | @Query("SELECT max(pr.lastUpdated) FROM PersonRating pr") 13 | Date lastUpdate(); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /credit-sales-funnel/src/main/java/com/mploed/dddwithspring/creditsalesfunnel/model/applicant/Employment.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditsalesfunnel.model.applicant; 2 | 3 | public enum Employment { 4 | EMPLOYEE("Employee"), OFFICIAL("Official"), 5 | PENSIONER("Pensioner"), 6 | STUDENT("Student"), 7 | TRAINEE("Trainee"), 8 | FREELANCER("Freelancer"), 9 | UNEMPLOYED("Unemployed"), 10 | OTHER("Other"); 11 | 12 | private final String displayName; 13 | 14 | Employment(String displayName) { 15 | this.displayName = displayName; 16 | } 17 | 18 | public String getDisplayName() { 19 | return displayName; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /scoring/aggregates/src/test/resources/com/mploed/dddwithspring/scoring/archunit/scoring.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | skinparam componentStyle uml2 4 | skinparam component { 5 | BorderColor #grey 6 | BackgroundColor #white 7 | } 8 | 9 | [AgencyResult] <<..scoring.agencyResult..>> 10 | [Applicant] <<..scoring.applicant..>> 11 | [FinancialSituation] <<..scoring.financialSituation..>> 12 | [ScoringResult] <<..scoring.scoringResult..>> 13 | [SharedKernel] <<..scoring>> 14 | 15 | [AgencyResult] --> [SharedKernel] 16 | [Applicant] --> [SharedKernel] 17 | [FinancialSituation] --> [SharedKernel] 18 | [ScoringResult] --> [SharedKernel] 19 | 20 | @enduml -------------------------------------------------------------------------------- /credit-agency/src/main/java/com/mploed/dddwithspring/creditagency/events/incoming/applicant/Employment.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditagency.events.incoming.applicant; 2 | 3 | public enum Employment { 4 | EMPLOYEE("Employee"), OFFICIAL("Official"), 5 | PENSIONER("Pensioner"), 6 | STUDENT("Student"), 7 | TRAINEE("Trainee"), 8 | FREELANCER("Freelancer"), 9 | UNEMPLOYED("Unemployed"), 10 | OTHER("Other"); 11 | 12 | private final String displayName; 13 | 14 | Employment(String displayName) { 15 | this.displayName = displayName; 16 | } 17 | 18 | public String getDisplayName() { 19 | return displayName; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /scoring/application-services/src/main/java/com/mploed/dddwithspring/scoring/appservices/repositories/ApplicantResultRepository.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.appservices.repositories; 2 | 3 | 4 | import com.mploed.dddwithspring.scoring.ApplicationNumber; 5 | import com.mploed.dddwithspring.scoring.PersonId; 6 | import com.mploed.dddwithspring.scoring.applicant.ApplicantAggregate; 7 | 8 | public interface ApplicantResultRepository { 9 | void save(ApplicantAggregate applicantAggregate); 10 | 11 | ApplicantAggregate retrieve(ApplicationNumber applicationNumber); 12 | 13 | ApplicantAggregate retrieve(PersonId personId); 14 | } 15 | -------------------------------------------------------------------------------- /scoring/adapters-input/src/main/java/com/mploed/dddwithspring/scoring/incoming/applicant/Business.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.incoming.applicant; 2 | 3 | public enum Business { 4 | BANKING("Banking"), 5 | ENERGY("Energy"), 6 | INSURANCE("Insurance"), 7 | CONSTRUCTION("Construction"), 8 | AGRICULTURE("Agriculture"), 9 | INDUSTRY("Industry"), 10 | PUBLIC_SERVICE("Public service"), 11 | OTHER("Other"); 12 | 13 | private final String displayName; 14 | 15 | Business(String displayName) { 16 | this.displayName = displayName; 17 | } 18 | 19 | public String getDisplayName() { 20 | return displayName; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /credit-sales-funnel/src/main/java/com/mploed/dddwithspring/creditsalesfunnel/model/applicant/Business.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditsalesfunnel.model.applicant; 2 | 3 | public enum Business { 4 | BANKING("Banking"), 5 | ENERGY("Energy"), 6 | INSURANCE("Insurance"), 7 | CONSTRUCTION("Construction"), 8 | AGRICULTURE("Agriculture"), 9 | INDUSTRY("Industry"), 10 | PUBLIC_SERVICE("Public service"), 11 | OTHER("Other"); 12 | 13 | private final String displayName; 14 | 15 | Business(String displayName) { 16 | this.displayName = displayName; 17 | } 18 | 19 | public String getDisplayName() { 20 | return displayName; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /credit-agency/src/main/java/com/mploed/dddwithspring/creditagency/CreditAgencyApplication.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditagency; 2 | 3 | import com.mploed.dddwithspring.creditagency.messaging.CreditAgencyChannels; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.cloud.stream.annotation.EnableBinding; 7 | 8 | @SpringBootApplication 9 | @EnableBinding(CreditAgencyChannels.class) 10 | public class CreditAgencyApplication { 11 | public static void main(String[] args) { 12 | SpringApplication.run(CreditAgencyApplication.class); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /credit-agency/src/main/java/com/mploed/dddwithspring/creditagency/events/incoming/applicant/Business.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditagency.events.incoming.applicant; 2 | 3 | public enum Business { 4 | BANKING("Banking"), 5 | ENERGY("Energy"), 6 | INSURANCE("Insurance"), 7 | CONSTRUCTION("Construction"), 8 | AGRICULTURE("Agriculture"), 9 | INDUSTRY("Industry"), 10 | PUBLIC_SERVICE("Public service"), 11 | OTHER("Other"); 12 | 13 | private final String displayName; 14 | 15 | Business(String displayName) { 16 | this.displayName = displayName; 17 | } 18 | 19 | public String getDisplayName() { 20 | return displayName; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /credit-sales-funnel/src/main/java/com/mploed/dddwithspring/creditsalesfunnel/repository/ApplicantRepository.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditsalesfunnel.repository; 2 | 3 | import com.mploed.dddwithspring.creditsalesfunnel.model.applicant.Applicant; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | import java.util.List; 7 | 8 | public interface ApplicantRepository extends JpaRepository { 9 | public Applicant findByApplicationNumberAndApplicantNumber(String applicationNumber, String applicantNumber); 10 | 11 | public List findByApplicationNumberOrderByApplicantNumber(String applicationNumber); 12 | } 13 | -------------------------------------------------------------------------------- /scoring/adapters-input/src/main/java/com/mploed/dddwithspring/scoring/incoming/realEstate/Feature.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.incoming.realEstate; 2 | 3 | public enum Feature { 4 | SOLAR_COLLECTORS("Solar collectors"), 5 | PHOTOVOLTAICS("Photovoltaics"), 6 | SPA("Spa"), 7 | TWO_OR_MORE_BATHS("Two or more baths"), 8 | EV_CHARGER("Charger for electric vehicle"), 9 | POOL("Pool"), 10 | SUMMERHOUSE_IN_GARDEN("Summerhouse in the garden"), 11 | SAT_TV("Satellite TV"); 12 | 13 | private final String displayName; 14 | 15 | Feature(String displayName) { 16 | this.displayName = displayName; 17 | } 18 | 19 | public String getDisplayName() { 20 | return displayName; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /scoring/aggregates/src/main/java/com/mploed/dddwithspring/scoring/applicant/AccountBalance.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.applicant; 2 | 3 | import com.mploed.dddwithspring.scoring.Money; 4 | 5 | import java.math.BigDecimal; 6 | 7 | class AccountBalance { 8 | private Money balance; 9 | 10 | AccountBalance(BigDecimal balance) { 11 | this(new Money(balance)); 12 | } 13 | AccountBalance(Money balance) { 14 | this.balance = balance; 15 | } 16 | 17 | int calculateScoringPoints() { 18 | if(balance.isGreaterThan(new Money(3000))) { 19 | return 10; 20 | } else { 21 | return 0; 22 | } 23 | } 24 | 25 | BigDecimal toBigDecimal() { 26 | return balance.getAmount(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /scoring/application-services/src/main/java/com/mploed/dddwithspring/scoring/appservices/internalevents/CreditAgencyResultArrived.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.appservices.internalevents; 2 | 3 | import com.mploed.dddwithspring.scoring.ApplicationNumber; 4 | import com.mploed.dddwithspring.scoring.PersonId; 5 | import org.springframework.context.ApplicationEvent; 6 | 7 | public class CreditAgencyResultArrived extends ApplicationEvent { 8 | private PersonId personId; 9 | 10 | public CreditAgencyResultArrived(Object source, String personId) { 11 | super(source); 12 | this.personId = new PersonId(personId); 13 | } 14 | 15 | public PersonId getPersonId() { 16 | return personId; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /credit-sales-funnel/src/main/java/com/mploed/dddwithspring/creditsalesfunnel/model/realEstate/Feature.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditsalesfunnel.model.realEstate; 2 | 3 | public enum Feature { 4 | SOLAR_COLLECTORS("Solar collectors"), 5 | PHOTOVOLTAICS("Photovoltaics"), 6 | SPA("Spa"), 7 | TWO_OR_MORE_BATHS("Two or more baths"), 8 | EV_CHARGER("Charger for electric vehicle"), 9 | POOL("Pool"), 10 | SUMMERHOUSE_IN_GARDEN("Summerhouse in the garden"), 11 | SAT_TV("Satellite TV"); 12 | 13 | private final String displayName; 14 | 15 | Feature(String displayName) { 16 | this.displayName = displayName; 17 | } 18 | 19 | public String getDisplayName() { 20 | return displayName; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /credit-sales-funnel/src/main/java/com/mploed/dddwithspring/creditsalesfunnel/CreditSalesFunnelApplication.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditsalesfunnel; 2 | 3 | import com.mploed.dddwithspring.creditsalesfunnel.event.CreditSalesFunnelChannels; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.cloud.stream.annotation.EnableBinding; 7 | 8 | @SpringBootApplication 9 | @EnableBinding(CreditSalesFunnelChannels.class) 10 | public class CreditSalesFunnelApplication { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(CreditSalesFunnelApplication.class, args); 14 | } 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /infrastructure_varnish/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:14.04 2 | RUN apt-get update && apt-get dist-upgrade -y -qq 3 | RUN apt-get install -y -qq apt-transport-https 4 | RUN apt-get install -y -qq curl && \ 5 | curl -L https://packagecloud.io/varnishcache/varnish41/gpgkey | sudo apt-key add - && \ 6 | echo "deb https://packagecloud.io/varnishcache/varnish41/ubuntu/ trusty main" \ 7 | >> /etc/apt/sources.list.d/varnishcache_varnish41.list && \ 8 | echo "deb-src https://packagecloud.io/varnishcache/varnish41/ubuntu/ trusty main" \ 9 | >> /etc/apt/sources.list.d/varnishcache_varnish41.list 10 | RUN apt-get update 11 | RUN apt-get install -y -qq varnish 12 | COPY default.vcl /etc/varnish/default.vcl 13 | COPY start /start 14 | RUN chmod 0755 /start 15 | CMD ["/start"] -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.mploed.dddwithspring 6 | parent 7 | 0.0.1-SNAPSHOT 8 | 9 | assets 10 | credit-sales-funnel 11 | scoring 12 | credit-agency 13 | 14 | pom 15 | 16 | ddd-with-spring 17 | Domain-driven Design with Spring 18 | 19 | 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.ear 17 | *.zip 18 | *.tar.gz 19 | *.rar 20 | 21 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 22 | hs_err_pid* 23 | 24 | target/ 25 | !.mvn/wrapper/maven-wrapper.jar 26 | 27 | ### STS ### 28 | .apt_generated 29 | .classpath 30 | .factorypath 31 | .project 32 | .settings 33 | .springBeans 34 | .sts4-cache 35 | 36 | ### IntelliJ IDEA ### 37 | .idea 38 | *.iws 39 | *.iml 40 | *.ipr 41 | 42 | ### NetBeans ### 43 | nbproject/private/ 44 | build/ 45 | nbbuild/ 46 | dist/ 47 | nbdist/ 48 | .nb-gradle/ -------------------------------------------------------------------------------- /scoring/adapters-output/src/main/java/com/mploed/dddwithspring/scoring/agencyResult/AgencyMessage.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.agencyResult; 2 | 3 | import javax.persistence.Embeddable; 4 | 5 | @Embeddable 6 | public class AgencyMessage { 7 | private String key; 8 | private String message; 9 | 10 | public AgencyMessage() { 11 | } 12 | 13 | AgencyMessage(String key, String message) { 14 | this.key = key; 15 | this.message = message; 16 | } 17 | 18 | public String getKey() { 19 | return key; 20 | } 21 | 22 | public void setKey(String key) { 23 | this.key = key; 24 | } 25 | 26 | public String getMessage() { 27 | return message; 28 | } 29 | 30 | public void setMessage(String message) { 31 | this.message = message; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /scoring/microarchitecture/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.mploed.dddwithspring.scoring 8 | microarchitecture 9 | 0.0.1-SNAPSHOT 10 | 11 | 12 | UTF-8 13 | 1.8 14 | 1.8 15 | 16 | 17 | -------------------------------------------------------------------------------- /scoring/aggregates/src/main/java/com/mploed/dddwithspring/scoring/financialSituation/FinancialSituationRootEntity.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.financialSituation; 2 | 3 | 4 | import com.mploed.dddwithspring.scoring.ApplicationNumber; 5 | import com.mploed.dddwithspring.scoring.Money; 6 | 7 | class FinancialSituationRootEntity { 8 | final ApplicationNumber applicationNumber; 9 | 10 | final Incomings incomings; 11 | final Outgoings outgoings; 12 | 13 | FinancialSituationRootEntity(ApplicationNumber applicationNumber, Incomings incomings, Outgoings outgoings) { 14 | this.applicationNumber = applicationNumber; 15 | this.incomings = incomings; 16 | this.outgoings = outgoings; 17 | } 18 | 19 | Money sum() { 20 | return incomings.sum().add(outgoings.sum()); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /scoring/application-services/src/main/java/com/mploed/dddwithspring/scoring/appservices/internalevents/CreditApplicationArrived.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.appservices.internalevents; 2 | 3 | import com.mploed.dddwithspring.scoring.ApplicationNumber; 4 | import com.mploed.dddwithspring.scoring.PersonId; 5 | import org.springframework.context.ApplicationEvent; 6 | 7 | public class CreditApplicationArrived extends ApplicationEvent { 8 | private ApplicationNumber applicationNumber; 9 | 10 | public CreditApplicationArrived(Object source, String applicationNumber) { 11 | super(source); 12 | this.applicationNumber = new ApplicationNumber(applicationNumber); 13 | } 14 | 15 | 16 | public ApplicationNumber getApplicationNumber() { 17 | return applicationNumber; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /scoring/sharedmodel/src/test/java/com/mploed/dddwithspring/scoring/MoneyTest.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring; 2 | 3 | 4 | import org.junit.Test; 5 | 6 | import java.math.BigDecimal; 7 | 8 | import static org.junit.Assert.assertEquals; 9 | import static org.junit.Assert.assertFalse; 10 | import static org.junit.Assert.assertTrue; 11 | 12 | public class MoneyTest { 13 | 14 | @Test 15 | public void testIsGreaterThan() { 16 | Money base = new Money(8000); 17 | assertTrue(base.isGreaterThan(new Money(7000))); 18 | assertFalse(base.isGreaterThan(new Money(8000))); 19 | } 20 | 21 | @Test 22 | public void testAdd() { 23 | Money base = new Money(); 24 | assertEquals(BigDecimal.ZERO, base.getAmount()); 25 | Money moneyToAdd = new Money(100); 26 | assertEquals(new Money(100), base.add(moneyToAdd)); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /scoring/aggregates/src/main/java/com/mploed/dddwithspring/scoring/applicant/Address.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.applicant; 2 | 3 | class Address { 4 | private String city; 5 | private String postCode; 6 | private String street; 7 | 8 | Address(String street, String postCode, String city) { 9 | this.city = city; 10 | this.postCode = postCode; 11 | this.street = street; 12 | } 13 | 14 | int calculateScoringPoints() { 15 | if("Munich".equals(city)) { 16 | return 5; 17 | } else if ("Dortmund".equals(city)) { 18 | return -2; 19 | } else if ("Nürnberg".equals(city)) { 20 | return 8; 21 | }else { 22 | return 0; 23 | } 24 | } 25 | 26 | String getCity() { 27 | return city; 28 | } 29 | 30 | String getPostCode() { 31 | return postCode; 32 | } 33 | 34 | String getStreet() { 35 | return street; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /credit-sales-funnel/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Get your big fat pug loan here 11 | 12 | 13 | Yes, I want to apply -> 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | Launch Scoring Activity Monitor 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /credit-agency/src/main/java/com/mploed/dddwithspring/creditagency/events/incoming/ApplicationSubmittedEvent.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditagency.events.incoming; 2 | 3 | import com.mploed.dddwithspring.creditagency.events.incoming.applicant.Applicant; 4 | 5 | import java.util.Date; 6 | 7 | public class ApplicationSubmittedEvent { 8 | private String applicationNumber; 9 | private Applicant firstApplicant; 10 | 11 | public ApplicationSubmittedEvent() { 12 | } 13 | 14 | public String getApplicationNumber() { 15 | return applicationNumber; 16 | } 17 | 18 | public void setApplicationNumber(String applicationNumber) { 19 | this.applicationNumber = applicationNumber; 20 | } 21 | 22 | public Applicant getFirstApplicant() { 23 | return firstApplicant; 24 | } 25 | 26 | public void setFirstApplicant(Applicant firstApplicant) { 27 | this.firstApplicant = firstApplicant; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /scoring/application-services/src/main/java/com/mploed/dddwithspring/scoring/appservices/dto/FinancialSituation.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.appservices.dto; 2 | 3 | import com.mploed.dddwithspring.scoring.Money; 4 | 5 | public class FinancialSituation { 6 | private Money costOfLiving; 7 | private Money furtherIncome; 8 | private Money rent; 9 | private Money salary; 10 | 11 | public FinancialSituation(Money costOfLiving, Money furtherIncome, Money rent, Money salary) { 12 | this.costOfLiving = costOfLiving; 13 | this.furtherIncome = furtherIncome; 14 | this.rent = rent; 15 | this.salary = salary; 16 | } 17 | 18 | public Money getCostOfLiving() { 19 | return costOfLiving; 20 | } 21 | 22 | public Money getFurtherIncome() { 23 | return furtherIncome; 24 | } 25 | 26 | public Money getRent() { 27 | return rent; 28 | } 29 | 30 | public Money getSalary() { 31 | return salary; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /scoring/aggregates/src/main/java/com/mploed/dddwithspring/scoring/scoringResult/ScoringResultRootEntity.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.scoringResult; 2 | 3 | 4 | import com.mploed.dddwithspring.scoring.ApplicationNumber; 5 | 6 | class ScoringResultRootEntity { 7 | final ApplicationNumber applicationNumber; 8 | final OverallScoringResult overallScoringResult; 9 | final ScoringCalculationResults scoringCalculationResults; 10 | ScoringResultRootEntity(ApplicationNumber applicationNumber, int applicantScoringResult, int financialSituationScoringResult, int agencyScoringResult, boolean noGoCriteriaPresent) { 11 | this.applicationNumber = applicationNumber; 12 | this.scoringCalculationResults = new ScoringCalculationResults(applicantScoringResult, financialSituationScoringResult, agencyScoringResult, noGoCriteriaPresent); 13 | this.overallScoringResult = this.scoringCalculationResults.calculateOverallResult(); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /scoring/application-services/src/main/java/com/mploed/dddwithspring/scoring/appservices/dto/Applicant.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.appservices.dto; 2 | 3 | public class Applicant { 4 | private String firstName; 5 | private String lastName; 6 | private String street; 7 | private String postCode; 8 | private String city; 9 | 10 | public Applicant(String firstName, String lastName, String street, String postCode, String city) { 11 | this.firstName = firstName; 12 | this.lastName = lastName; 13 | this.street = street; 14 | this.postCode = postCode; 15 | this.city = city; 16 | } 17 | 18 | public String getFirstName() { 19 | return firstName; 20 | } 21 | 22 | public String getLastName() { 23 | return lastName; 24 | } 25 | 26 | public String getStreet() { 27 | return street; 28 | } 29 | 30 | public String getPostCode() { 31 | return postCode; 32 | } 33 | 34 | public String getCity() { 35 | return city; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /scoring/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | parent 7 | com.mploed.dddwithspring 8 | 0.0.1-SNAPSHOT 9 | 10 | pom 11 | 4.0.0 12 | 13 | scoring 14 | 0.0.1-SNAPSHOT 15 | 16 | 17 | microarchitecture 18 | sharedmodel 19 | aggregates 20 | 21 | adapters-input 22 | adapters-output 23 | scoring-application 24 | application-services 25 | 26 | 27 | -------------------------------------------------------------------------------- /scoring/sharedmodel/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.mploed.dddwithspring.scoring 8 | 0.0.1-SNAPSHOT 9 | sharedmodel 10 | jar 11 | 12 | 13 | 14 | UTF-8 15 | 1.8 16 | 1.8 17 | 18 | 19 | 20 | 21 | junit 22 | junit 23 | 4.13.1 24 | 25 | 26 | -------------------------------------------------------------------------------- /scoring/adapters-input/src/main/java/com/mploed/dddwithspring/scoring/incoming/applicant/Address.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.incoming.applicant; 2 | 3 | import java.io.Serializable; 4 | 5 | public class Address implements Serializable { 6 | private String street; 7 | 8 | private String postCode; 9 | 10 | private String city; 11 | 12 | public String getStreet() { 13 | return street; 14 | } 15 | 16 | public String getPostCode() { 17 | return postCode; 18 | } 19 | 20 | public String getCity() { 21 | return city; 22 | } 23 | 24 | public void setStreet(String street) { 25 | this.street = street; 26 | } 27 | 28 | public void setPostCode(String postCode) { 29 | this.postCode = postCode; 30 | } 31 | 32 | public void setCity(String city) { 33 | this.city = city; 34 | } 35 | 36 | @Override 37 | public String toString() { 38 | return "Address{" + 39 | "street='" + street + '\'' + 40 | ", postCode='" + postCode + '\'' + 41 | ", city='" + city + '\'' + 42 | '}'; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /credit-agency/src/main/java/com/mploed/dddwithspring/creditagency/events/incoming/applicant/Address.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditagency.events.incoming.applicant; 2 | 3 | import java.io.Serializable; 4 | 5 | public class Address implements Serializable { 6 | private String street; 7 | 8 | private String postCode; 9 | 10 | private String city; 11 | 12 | public String getStreet() { 13 | return street; 14 | } 15 | 16 | public String getPostCode() { 17 | return postCode; 18 | } 19 | 20 | public String getCity() { 21 | return city; 22 | } 23 | 24 | public void setStreet(String street) { 25 | this.street = street; 26 | } 27 | 28 | public void setPostCode(String postCode) { 29 | this.postCode = postCode; 30 | } 31 | 32 | public void setCity(String city) { 33 | this.city = city; 34 | } 35 | 36 | @Override 37 | public String toString() { 38 | return "Address{" + 39 | "street='" + street + '\'' + 40 | ", postCode='" + postCode + '\'' + 41 | ", city='" + city + '\'' + 42 | '}'; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /scoring/adapters-input/src/main/java/com/mploed/dddwithspring/scoring/WebSocketConfig.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.messaging.simp.config.MessageBrokerRegistry; 5 | import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; 6 | import org.springframework.web.socket.config.annotation.StompEndpointRegistry; 7 | import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; 8 | 9 | @Configuration 10 | @EnableWebSocketMessageBroker 11 | public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { 12 | 13 | @Override 14 | public void configureMessageBroker(MessageBrokerRegistry config) { 15 | config.enableSimpleBroker("/topic"); 16 | config.setApplicationDestinationPrefixes("/app"); 17 | } 18 | 19 | @Override 20 | public void registerStompEndpoints(StompEndpointRegistry registry) { 21 | registry.addEndpoint("/gs-guide-websocket").withSockJS(); 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /scoring/adapters-input/src/main/java/com/mploed/dddwithspring/scoring/messaging/SpringEventListener.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.messaging; 2 | 3 | import com.mploed.dddwithspring.scoring.ApplicationNumber; 4 | import com.mploed.dddwithspring.scoring.appservices.ScoringApplicationService; 5 | import com.mploed.dddwithspring.scoring.appservices.internalevents.PartOfScoringPerformed; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.context.ApplicationListener; 8 | import org.springframework.stereotype.Component; 9 | 10 | @Component 11 | public class SpringEventListener implements ApplicationListener { 12 | 13 | private ScoringApplicationService scoringApplicationService; 14 | 15 | @Autowired 16 | public SpringEventListener(ScoringApplicationService scoringApplicationService) { 17 | this.scoringApplicationService = scoringApplicationService; 18 | } 19 | 20 | @Override 21 | public void onApplicationEvent(PartOfScoringPerformed event) { 22 | scoringApplicationService.performFinalScoring(event.getApplicationNumber()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /scoring/adapters-input/src/main/java/com/mploed/dddwithspring/scoring/incoming/realEstate/ApartmentInformation.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.incoming.realEstate; 2 | 3 | import java.io.Serializable; 4 | 5 | public class ApartmentInformation implements Serializable { 6 | private int numberOfApartmentsInHouse; 7 | 8 | private String nameOfApartment; 9 | 10 | private ApartmentLocation apartmentLocation; 11 | 12 | public int getNumberOfApartmentsInHouse() { 13 | return numberOfApartmentsInHouse; 14 | } 15 | 16 | public void setNumberOfApartmentsInHouse(int numberOfApartmentsInHouse) { 17 | this.numberOfApartmentsInHouse = numberOfApartmentsInHouse; 18 | } 19 | 20 | public String getNameOfApartment() { 21 | return nameOfApartment; 22 | } 23 | 24 | public void setNameOfApartment(String nameOfApartment) { 25 | this.nameOfApartment = nameOfApartment; 26 | } 27 | 28 | public ApartmentLocation getApartmentLocation() { 29 | return apartmentLocation; 30 | } 31 | 32 | public void setApartmentLocation(ApartmentLocation apartmentLocation) { 33 | this.apartmentLocation = apartmentLocation; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /scoring/adapters-input/src/main/java/com/mploed/dddwithspring/scoring/incoming/financing/OwnResources.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.incoming.financing; 2 | 3 | import javax.persistence.Embeddable; 4 | import java.io.Serializable; 5 | 6 | public class OwnResources implements Serializable { 7 | private int liquidAssets; 8 | private int balanceFromBuildingSociety; 9 | private int ownManpower; 10 | 11 | public int sum() { 12 | return liquidAssets + balanceFromBuildingSociety + ownManpower; 13 | } 14 | 15 | public int getLiquidAssets() { 16 | return liquidAssets; 17 | } 18 | 19 | public void setLiquidAssets(int liquidAssets) { 20 | this.liquidAssets = liquidAssets; 21 | } 22 | 23 | public int getBalanceFromBuildingSociety() { 24 | return balanceFromBuildingSociety; 25 | } 26 | 27 | public void setBalanceFromBuildingSociety(int balanceFromBuildingSociety) { 28 | this.balanceFromBuildingSociety = balanceFromBuildingSociety; 29 | } 30 | 31 | public int getOwnManpower() { 32 | return ownManpower; 33 | } 34 | 35 | public void setOwnManpower(int ownManpower) { 36 | this.ownManpower = ownManpower; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /credit-sales-funnel/src/main/java/com/mploed/dddwithspring/creditsalesfunnel/model/financing/OwnResources.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditsalesfunnel.model.financing; 2 | 3 | import javax.persistence.Embeddable; 4 | import java.io.Serializable; 5 | 6 | @Embeddable 7 | public class OwnResources implements Serializable { 8 | private int liquidAssets; 9 | private int balanceFromBuildingSociety; 10 | private int ownManpower; 11 | 12 | public int sum() { 13 | return liquidAssets + balanceFromBuildingSociety + ownManpower; 14 | } 15 | 16 | public int getLiquidAssets() { 17 | return liquidAssets; 18 | } 19 | 20 | public void setLiquidAssets(int liquidAssets) { 21 | this.liquidAssets = liquidAssets; 22 | } 23 | 24 | public int getBalanceFromBuildingSociety() { 25 | return balanceFromBuildingSociety; 26 | } 27 | 28 | public void setBalanceFromBuildingSociety(int balanceFromBuildingSociety) { 29 | this.balanceFromBuildingSociety = balanceFromBuildingSociety; 30 | } 31 | 32 | public int getOwnManpower() { 33 | return ownManpower; 34 | } 35 | 36 | public void setOwnManpower(int ownManpower) { 37 | this.ownManpower = ownManpower; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /credit-agency/src/main/java/com/mploed/dddwithspring/creditagency/web/PersonRatingRestController.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditagency.web; 2 | 3 | import com.mploed.dddwithspring.creditagency.model.PersonRating; 4 | import com.mploed.dddwithspring.creditagency.repository.PersonRatingRepository; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.ui.Model; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.PathVariable; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.RestController; 11 | 12 | @RestController 13 | @RequestMapping("rating/rest") 14 | public class PersonRatingRestController { 15 | private PersonRatingRepository personRatingRepository; 16 | 17 | @Autowired 18 | public PersonRatingRestController(PersonRatingRepository personRatingRepository) { 19 | this.personRatingRepository = personRatingRepository; 20 | } 21 | 22 | @GetMapping("/{ratingId}") 23 | public PersonRating index(Model model, @PathVariable Long ratingId) { 24 | return personRatingRepository.findById(ratingId).get(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /scoring/adapters-input/src/main/resources/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Big Pug Loans - Scoring monitor 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | Seems your browser doesn't support Javascript! Websocket relies on Javascript being 18 | enabled. Please enable 19 | Javascript and reload this page! 20 | 21 | Scoring activity 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /scoring/adapters-output/src/main/java/com/mploed/dddwithspring/scoring/scoringResult/DetailedScoringResults.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.scoringResult; 2 | 3 | import javax.persistence.Embeddable; 4 | 5 | @Embeddable 6 | public class DetailedScoringResults { 7 | private int applicantScoringResult; 8 | private int financialSituationScoringResult; 9 | private int agencyScoringResult; 10 | private boolean noGoCriteriaPresent; 11 | 12 | public DetailedScoringResults(ScoringCalculationResults scoringCalculationResults) { 13 | this.applicantScoringResult = scoringCalculationResults.applicantScoringResult; 14 | this.financialSituationScoringResult = scoringCalculationResults.financialSituationScoringResult; 15 | this.agencyScoringResult = scoringCalculationResults.agencyScoringResult; 16 | this.noGoCriteriaPresent = scoringCalculationResults.noGoCriteriaPresent; 17 | } 18 | 19 | private DetailedScoringResults() { 20 | } 21 | 22 | public int getApplicantScoringResult() { 23 | return applicantScoringResult; 24 | } 25 | 26 | public int getFinancialSituationScoringResult() { 27 | return financialSituationScoringResult; 28 | } 29 | 30 | public int getAgencyScoringResult() { 31 | return agencyScoringResult; 32 | } 33 | 34 | public boolean isNoGoCriteriaPresent() { 35 | return noGoCriteriaPresent; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /scoring/adapters-output/src/main/java/com/mploed/dddwithspring/scoring/scoringResult/ScoringResultEntity.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.scoringResult; 2 | 3 | import javax.persistence.*; 4 | 5 | @Entity 6 | @Table(name = "SCORING_RESULT") 7 | public class ScoringResultEntity { 8 | @Id 9 | @GeneratedValue 10 | private Long id; 11 | 12 | private String applicationNumber; 13 | 14 | private int scorePoints; 15 | 16 | private String scoreColor; 17 | 18 | @Embedded 19 | private DetailedScoringResults detailedScoringResults; 20 | 21 | public ScoringResultEntity(String applicationNumber, int scorePoints, String scoreColor, DetailedScoringResults detailedScoringResults) { 22 | this.applicationNumber = applicationNumber; 23 | this.scorePoints = scorePoints; 24 | this.scoreColor = scoreColor; 25 | this.detailedScoringResults = detailedScoringResults; 26 | } 27 | 28 | private ScoringResultEntity() { 29 | } 30 | 31 | public Long getId() { 32 | return id; 33 | } 34 | 35 | public int getScorePoints() { 36 | return scorePoints; 37 | } 38 | 39 | public String getScoreColor() { 40 | return scoreColor; 41 | } 42 | 43 | public String getApplicationNumber() { 44 | return applicationNumber; 45 | } 46 | 47 | public DetailedScoringResults getDetailedScoringResults() { 48 | return detailedScoringResults; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /scoring/adapters-input/src/main/java/com/mploed/dddwithspring/scoring/InputAdaptersConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring; 2 | 3 | import com.mploed.dddwithspring.scoring.messaging.ApplicationProcessChannels; 4 | import org.springframework.cloud.stream.annotation.EnableBinding; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.context.event.ApplicationEventMulticaster; 8 | import org.springframework.context.event.SimpleApplicationEventMulticaster; 9 | import org.springframework.core.task.SimpleAsyncTaskExecutor; 10 | import org.springframework.scheduling.annotation.EnableScheduling; 11 | import org.springframework.web.client.RestTemplate; 12 | 13 | @Configuration 14 | @EnableBinding(ApplicationProcessChannels.class) 15 | @EnableScheduling 16 | public class InputAdaptersConfiguration { 17 | @Bean 18 | public RestTemplate restTemplate() { 19 | return new RestTemplate(); 20 | } 21 | 22 | @Bean(name = "applicationEventMulticaster") 23 | public ApplicationEventMulticaster simpleApplicationEventMulticaster() { 24 | SimpleApplicationEventMulticaster eventMulticaster 25 | = new SimpleApplicationEventMulticaster(); 26 | 27 | eventMulticaster.setTaskExecutor(new SimpleAsyncTaskExecutor()); 28 | return eventMulticaster; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /scoring/adapters-input/src/main/java/com/mploed/dddwithspring/scoring/incoming/financing/PurchaseCosts.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.incoming.financing; 2 | 3 | import javax.persistence.Embeddable; 4 | import java.io.Serializable; 5 | 6 | public class PurchaseCosts implements Serializable { 7 | private int priceOfLand; 8 | private int purchasePrice; 9 | private int reconstructionCosts; 10 | private int additionalPurchaseCharges; 11 | 12 | public int sum() { 13 | return priceOfLand + purchasePrice + reconstructionCosts + additionalPurchaseCharges; 14 | } 15 | public int getPriceOfLand() { 16 | return priceOfLand; 17 | } 18 | 19 | public void setPriceOfLand(int priceOfLand) { 20 | this.priceOfLand = priceOfLand; 21 | } 22 | 23 | public int getPurchasePrice() { 24 | return purchasePrice; 25 | } 26 | 27 | public void setPurchasePrice(int purchasePrice) { 28 | this.purchasePrice = purchasePrice; 29 | } 30 | 31 | public int getReconstructionCosts() { 32 | return reconstructionCosts; 33 | } 34 | 35 | public void setReconstructionCosts(int reconstructionCosts) { 36 | this.reconstructionCosts = reconstructionCosts; 37 | } 38 | 39 | public int getAdditionalPurchaseCharges() { 40 | return additionalPurchaseCharges; 41 | } 42 | 43 | public void setAdditionalPurchaseCharges(int additionalPurchaseCharges) { 44 | this.additionalPurchaseCharges = additionalPurchaseCharges; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /scoring/application-services/src/main/java/com/mploed/dddwithspring/scoring/appservices/internalevents/PartOfScoringPerformed.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.appservices.internalevents; 2 | 3 | import com.mploed.dddwithspring.scoring.ApplicationNumber; 4 | import com.mploed.dddwithspring.scoring.PersonId; 5 | import org.springframework.context.ApplicationEvent; 6 | 7 | public class PartOfScoringPerformed extends ApplicationEvent { 8 | private ApplicationNumber applicationNumber; 9 | private PersonId personId; 10 | private String cluster; 11 | 12 | public PartOfScoringPerformed(Object source, String cluster, String applicationNumber, PersonId personId) { 13 | super(source); 14 | this.applicationNumber = new ApplicationNumber(applicationNumber); 15 | this.personId = personId; 16 | } 17 | 18 | 19 | public PartOfScoringPerformed(Object source, String cluster, PersonId personId) { 20 | super(source); 21 | this.personId = personId; 22 | } 23 | 24 | 25 | 26 | public PartOfScoringPerformed(Object source, String cluster, ApplicationNumber applicationNumber) { 27 | super(source); 28 | this.applicationNumber = applicationNumber; 29 | this.cluster = cluster; 30 | } 31 | 32 | public ApplicationNumber getApplicationNumber() { 33 | return applicationNumber; 34 | } 35 | 36 | public PersonId getPersonId() { 37 | return personId; 38 | } 39 | 40 | public String getCluster() { 41 | return cluster; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /credit-sales-funnel/src/main/java/com/mploed/dddwithspring/creditsalesfunnel/model/financing/PurchaseCosts.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditsalesfunnel.model.financing; 2 | 3 | import javax.persistence.Embeddable; 4 | import java.io.Serializable; 5 | 6 | @Embeddable 7 | public class PurchaseCosts implements Serializable { 8 | private int priceOfLand; 9 | private int purchasePrice; 10 | private int reconstructionCosts; 11 | private int additionalPurchaseCharges; 12 | 13 | public int sum() { 14 | return priceOfLand + purchasePrice + reconstructionCosts + additionalPurchaseCharges; 15 | } 16 | public int getPriceOfLand() { 17 | return priceOfLand; 18 | } 19 | 20 | public void setPriceOfLand(int priceOfLand) { 21 | this.priceOfLand = priceOfLand; 22 | } 23 | 24 | public int getPurchasePrice() { 25 | return purchasePrice; 26 | } 27 | 28 | public void setPurchasePrice(int purchasePrice) { 29 | this.purchasePrice = purchasePrice; 30 | } 31 | 32 | public int getReconstructionCosts() { 33 | return reconstructionCosts; 34 | } 35 | 36 | public void setReconstructionCosts(int reconstructionCosts) { 37 | this.reconstructionCosts = reconstructionCosts; 38 | } 39 | 40 | public int getAdditionalPurchaseCharges() { 41 | return additionalPurchaseCharges; 42 | } 43 | 44 | public void setAdditionalPurchaseCharges(int additionalPurchaseCharges) { 45 | this.additionalPurchaseCharges = additionalPurchaseCharges; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /scoring/adapters-input/src/main/java/com/mploed/dddwithspring/scoring/incoming/creditAgency/AgencyRating.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.incoming.creditAgency; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | 5 | @JsonIgnoreProperties(ignoreUnknown = true) 6 | 7 | public class AgencyRating { 8 | private int points; 9 | private String firstName; 10 | private String lastName; 11 | private String street; 12 | private String postCode; 13 | private String city; 14 | 15 | public int getPoints() { 16 | return points; 17 | } 18 | 19 | public void setPoints(int points) { 20 | this.points = points; 21 | } 22 | 23 | public String getFirstName() { 24 | return firstName; 25 | } 26 | 27 | public void setFirstName(String firstName) { 28 | this.firstName = firstName; 29 | } 30 | 31 | public String getLastName() { 32 | return lastName; 33 | } 34 | 35 | public void setLastName(String lastName) { 36 | this.lastName = lastName; 37 | } 38 | 39 | public String getStreet() { 40 | return street; 41 | } 42 | 43 | public void setStreet(String street) { 44 | this.street = street; 45 | } 46 | 47 | public String getPostCode() { 48 | return postCode; 49 | } 50 | 51 | public void setPostCode(String postCode) { 52 | this.postCode = postCode; 53 | } 54 | 55 | public String getCity() { 56 | return city; 57 | } 58 | 59 | public void setCity(String city) { 60 | this.city = city; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /credit-agency/src/main/java/com/mploed/dddwithspring/creditagency/model/RatingModel.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditagency.model; 2 | 3 | import javax.persistence.Entity; 4 | import javax.persistence.GeneratedValue; 5 | import javax.persistence.GenerationType; 6 | import javax.persistence.Id; 7 | 8 | @Entity 9 | public class RatingModel { 10 | @Id @GeneratedValue(strategy = GenerationType.TABLE) 11 | private Long id; 12 | 13 | private String category; 14 | 15 | private int points; 16 | 17 | private String inputValue; 18 | 19 | private int start; 20 | 21 | private int end; 22 | 23 | public Long getId() { 24 | return id; 25 | } 26 | 27 | public void setId(Long id) { 28 | this.id = id; 29 | } 30 | 31 | public String getCategory() { 32 | return category; 33 | } 34 | 35 | public void setCategory(String category) { 36 | this.category = category; 37 | } 38 | 39 | public int getPoints() { 40 | return points; 41 | } 42 | 43 | public void setPoints(int points) { 44 | this.points = points; 45 | } 46 | 47 | public String getInputValue() { 48 | return inputValue; 49 | } 50 | 51 | public void setInputValue(String inputValue) { 52 | this.inputValue = inputValue; 53 | } 54 | 55 | public int getStart() { 56 | return start; 57 | } 58 | 59 | public void setStart(int start) { 60 | this.start = start; 61 | } 62 | 63 | public int getEnd() { 64 | return end; 65 | } 66 | 67 | public void setEnd(int end) { 68 | this.end = end; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /scoring/aggregates/src/main/java/com/mploed/dddwithspring/scoring/scoringResult/ScoringCalculationResults.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.scoringResult; 2 | 3 | class ScoringCalculationResults { 4 | final int applicantScoringResult; 5 | final int financialSituationScoringResult; 6 | final int agencyScoringResult; 7 | final boolean noGoCriteriaPresent; 8 | 9 | ScoringCalculationResults(int applicantScoringResult, int financialSituationScoringResult, int agencyScoringResult, boolean noGoCriteriaPresent) { 10 | this.applicantScoringResult = applicantScoringResult; 11 | this.financialSituationScoringResult = financialSituationScoringResult; 12 | this.agencyScoringResult = agencyScoringResult; 13 | this.noGoCriteriaPresent = noGoCriteriaPresent; 14 | } 15 | 16 | OverallScoringResult calculateOverallResult() { 17 | System.out.println("Applicant Result: " + applicantScoringResult); 18 | System.out.println("FinancialSituation Result: " + financialSituationScoringResult); 19 | System.out.println("CreditAgency Result: " + agencyScoringResult); 20 | int overallPoints = applicantScoringResult + financialSituationScoringResult + agencyScoringResult; 21 | ScoringColor color; 22 | 23 | if(noGoCriteriaPresent) { 24 | color = ScoringColor.RED; 25 | } else { 26 | if (overallPoints > 40) { 27 | color = ScoringColor.GREEN; 28 | } else { 29 | color = ScoringColor.RED; 30 | } 31 | } 32 | return new OverallScoringResult(overallPoints, color); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /scoring/sharedmodel/src/main/java/com/mploed/dddwithspring/scoring/Money.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring; 2 | 3 | import java.math.BigDecimal; 4 | import java.util.Objects; 5 | 6 | public final class Money { 7 | private final static int DEFAULT_SCALE = 2; 8 | private BigDecimal amount; 9 | private int scale; 10 | 11 | public Money() { 12 | this(BigDecimal.ZERO); 13 | } 14 | 15 | public Money(BigDecimal amount) { 16 | this.amount = amount; 17 | this.scale = DEFAULT_SCALE; 18 | } 19 | 20 | public Money(int amount) { 21 | this(new BigDecimal(amount)); 22 | } 23 | 24 | public Money add(Money money) { 25 | BigDecimal total = this.getAmount().add(money.getAmount()); 26 | 27 | return new Money(total); 28 | } 29 | 30 | public boolean isGreaterThan(Money comparison) { 31 | return this.getAmount().compareTo(comparison.getAmount()) > 0; 32 | } 33 | 34 | public BigDecimal getAmount() { 35 | return amount; 36 | } 37 | 38 | @Override 39 | public String toString() { 40 | return "Money{" + 41 | "amount=" + amount + 42 | ", scale=" + scale + 43 | '}'; 44 | } 45 | 46 | @Override 47 | public boolean equals(Object o) { 48 | if (this == o) return true; 49 | if (o == null || getClass() != o.getClass()) return false; 50 | Money money = (Money) o; 51 | return scale == money.scale && 52 | Objects.equals(amount, money.amount); 53 | } 54 | 55 | @Override 56 | public int hashCode() { 57 | 58 | return Objects.hash(amount, scale); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /scoring/adapters-input/src/main/resources/static/app.js: -------------------------------------------------------------------------------- 1 | var stompClient = null; 2 | 3 | function setConnected(connected) { 4 | $("#connect").prop("disabled", connected); 5 | $("#disconnect").prop("disabled", !connected); 6 | if (connected) { 7 | $("#conversation").show(); 8 | } 9 | else { 10 | $("#conversation").hide(); 11 | } 12 | $("#greetings").html(""); 13 | } 14 | 15 | function connect() { 16 | var socket = new SockJS('/scoring/gs-guide-websocket'); 17 | stompClient = Stomp.over(socket); 18 | stompClient.connect({}, function (frame) { 19 | setConnected(true); 20 | console.log('Connected: ' + frame); 21 | stompClient.subscribe('/topic/greetings', function (greeting) { 22 | console.log('received: ' + greeting) 23 | showGreeting(JSON.parse(greeting.body).content); 24 | }); 25 | }); 26 | } 27 | 28 | function disconnect() { 29 | if (stompClient !== null) { 30 | stompClient.disconnect(); 31 | } 32 | setConnected(false); 33 | console.log("Disconnected"); 34 | } 35 | 36 | function showGreeting(message) { 37 | $("#greetings").append("" + message + ""); 38 | } 39 | 40 | $(function () { 41 | $("form").on('submit', function (e) { 42 | e.preventDefault(); 43 | }); 44 | $( "#connect" ).click(function() { connect(); }); 45 | $( "#disconnect" ).click(function() { disconnect(); }); 46 | $( "#send" ).click(function() { sendName(); }); 47 | }); -------------------------------------------------------------------------------- /credit-agency/src/main/java/com/mploed/dddwithspring/creditagency/service/PersonRatingQueryService.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditagency.service; 2 | 3 | import com.mploed.dddwithspring.creditagency.model.PersonRating; 4 | import com.mploed.dddwithspring.creditagency.repository.PersonRatingRepository; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Service; 7 | 8 | import java.util.Calendar; 9 | import java.util.Date; 10 | import java.util.GregorianCalendar; 11 | 12 | @Service 13 | public class PersonRatingQueryService { 14 | private PersonRatingRepository personRatingRepository; 15 | 16 | @Autowired 17 | public PersonRatingQueryService(PersonRatingRepository personRatingRepository) { 18 | this.personRatingRepository = personRatingRepository; 19 | } 20 | 21 | public void ratePerson(String firstName, String lastName, String street, String postCode, String city) { 22 | PersonRating rating = new PersonRating(); 23 | rating.setCity(city); 24 | rating.setFirstName(firstName); 25 | rating.setLastName(lastName); 26 | rating.setPostCode(postCode); 27 | rating.setStreet(street); 28 | rating.setPoints(100); 29 | rating.setLastUpdated(new Date()); 30 | GregorianCalendar gregorianCalendar = new GregorianCalendar(); 31 | gregorianCalendar.add(Calendar.MONTH, 1); 32 | System.out.println(gregorianCalendar.getTime()); 33 | rating.setValidTo(gregorianCalendar.getTime()); 34 | personRatingRepository.save(rating); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /scoring/adapters-output/src/test/java/com/mploed/dddwithspring/scoring/AgencyResultRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring; 2 | 3 | import com.mploed.dddwithspring.scoring.agencyResult.AgencyResultAggregate; 4 | import com.mploed.dddwithspring.scoring.agencyResult.AgencyResultJPARepository; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; 9 | import org.springframework.boot.test.context.SpringBootTest; 10 | import org.springframework.test.context.junit4.SpringRunner; 11 | 12 | import static org.assertj.core.api.AssertionsForClassTypes.assertThat; 13 | 14 | @RunWith(SpringRunner.class) 15 | @SpringBootTest 16 | public class AgencyResultRepositoryTest { 17 | @Autowired 18 | private AgencyResultJPARepository repository; 19 | 20 | @Test 21 | public void testSave() { 22 | AgencyResultAggregate aggregate = new AgencyResultAggregate.AgencyResultBuilder() 23 | .forPerson("Michael", "Plöd", "teststr", "40789", "Testcity") 24 | .withPoints(100) 25 | .withWarning("234", "test") 26 | .withKoCriteria("123", "test test") 27 | .withKoCriteria("342", "testing") 28 | .build(); 29 | 30 | repository.save(aggregate); 31 | 32 | AgencyResultAggregate resultAggregate = repository.retrieve(aggregate.getPersonId()); 33 | 34 | assertThat(resultAggregate.getPersonId().toString()).isEqualTo(aggregate.getPersonId().toString()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /scoring/application-services/src/main/java/com/mploed/dddwithspring/scoring/appservices/internalevents/ScoringPerformed.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.appservices.internalevents; 2 | 3 | import com.mploed.dddwithspring.scoring.ApplicationNumber; 4 | import com.mploed.dddwithspring.scoring.PersonId; 5 | import org.springframework.context.ApplicationEvent; 6 | 7 | public class ScoringPerformed extends ApplicationEvent { 8 | private ApplicationNumber applicationNumber; 9 | private PersonId personId; 10 | private String scoreColor; 11 | private int points; 12 | 13 | public ScoringPerformed(Object source, String applicationNumber, PersonId personId, String scoreColor, int points) { 14 | super(source); 15 | this.applicationNumber = new ApplicationNumber(applicationNumber); 16 | this.personId = personId; 17 | this.scoreColor = scoreColor; 18 | this.points = points; 19 | } 20 | 21 | 22 | public ScoringPerformed(Object source, PersonId personId) { 23 | super(source); 24 | this.personId = personId; 25 | } 26 | 27 | 28 | 29 | public ScoringPerformed(Object source, ApplicationNumber applicationNumber) { 30 | super(source); 31 | this.applicationNumber = applicationNumber; 32 | } 33 | 34 | public ApplicationNumber getApplicationNumber() { 35 | return applicationNumber; 36 | } 37 | 38 | public PersonId getPersonId() { 39 | return personId; 40 | } 41 | 42 | public String getScoreColor() { 43 | return scoreColor; 44 | } 45 | 46 | public int getPoints() { 47 | return points; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ddd-with-spring 2 | 3 | 4 | 5 | [](https://travis-ci.org/mploed/ddd-with-spring) 6 | 7 | 8 | 9 | This repository aims at showcasing a way how you could implement various aspects from Domain-driven Design with the 10 | Spring ecosystem. It is also the demo project for my conference talk "Implementing Domain-driven Design with the Spring 11 | ecosystem". 12 | 13 | ## Which DDD aspects are covered? 14 | The focus of the demo project are Aggregates, event-based communication and bounded contexts. The complete list is: 15 | 16 | - Aggregates 17 | - Event-based communication with 18 | - a message broker (RabbitMQ) 19 | - HTTP Feeds 20 | - Spring Application Events 21 | - Architectural styles 22 | - Hexagonal Architecture 23 | - CRUD 24 | - Query-driven (not yet implemented properly) 25 | 26 | ## Which Spring Technologies are being used? 27 | 28 | The project uses the following Spring technologies: 29 | 30 | - Spring Framework Core 31 | - Spring MVC 32 | - Spring Boot 33 | - Spring Cloud Stream 34 | - Spring Data JPA 35 | 36 | ## Prerequisites and getting started 37 | 38 | In order to run the application you need to have Docker and docker-compose installed on your machine. 39 | 40 | When you have docker up and running you need to perform the following steps on the command line: 41 | 42 | 1. ./mvnw clean package 43 | 2. docker-compose up --build 44 | 3. After everything has started you can open http://localhost:8080 in a browser of your choice 45 | -------------------------------------------------------------------------------- /credit-agency/src/main/java/com/mploed/dddwithspring/creditagency/messaging/IncomingMessageListener.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditagency.messaging; 2 | 3 | import com.mploed.dddwithspring.creditagency.events.incoming.ApplicationSubmittedEvent; 4 | import com.mploed.dddwithspring.creditagency.events.incoming.applicant.Applicant; 5 | import com.mploed.dddwithspring.creditagency.service.PersonRatingQueryService; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.cloud.stream.annotation.StreamListener; 8 | import org.springframework.messaging.handler.annotation.Payload; 9 | import org.springframework.stereotype.Component; 10 | 11 | @Component 12 | public class IncomingMessageListener { 13 | 14 | private PersonRatingQueryService personRatingQueryService; 15 | 16 | @Autowired 17 | public IncomingMessageListener(PersonRatingQueryService personRatingQueryService) { 18 | this.personRatingQueryService = personRatingQueryService; 19 | } 20 | 21 | @StreamListener(CreditAgencyChannels.APPLICATION_SUBMITTED) 22 | public void receiveApplicationSubmission(@Payload ApplicationSubmittedEvent applicationSubmittedEvent) { 23 | 24 | System.out.println("received " + applicationSubmittedEvent.getFirstApplicant().toString()); 25 | Applicant applicant = applicationSubmittedEvent.getFirstApplicant(); 26 | personRatingQueryService.ratePerson(applicant.getFirstName(), 27 | applicant.getLastName(), 28 | applicant.getAddress().getStreet(), 29 | applicant.getAddress().getPostCode(), 30 | applicant.getAddress().getCity()); 31 | } 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /credit-sales-funnel/src/main/java/com/mploed/dddwithspring/creditsalesfunnel/model/applicant/Address.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditsalesfunnel.model.applicant; 2 | 3 | import com.mploed.dddwithspring.creditsalesfunnel.model.validation.ApplicationSubmissionGroup; 4 | 5 | import javax.persistence.Embeddable; 6 | import javax.validation.constraints.NotEmpty; 7 | import javax.validation.constraints.NotNull; 8 | import java.io.Serializable; 9 | 10 | @Embeddable 11 | public class Address implements Serializable { 12 | @NotNull(groups = ApplicationSubmissionGroup.class) 13 | @NotEmpty(groups = ApplicationSubmissionGroup.class) 14 | private String street; 15 | 16 | @NotNull(groups = ApplicationSubmissionGroup.class) 17 | @NotEmpty(groups = ApplicationSubmissionGroup.class) 18 | private String postCode; 19 | 20 | @NotNull(groups = ApplicationSubmissionGroup.class) 21 | @NotEmpty(groups = ApplicationSubmissionGroup.class) 22 | private String city; 23 | 24 | public String getStreet() { 25 | return street; 26 | } 27 | 28 | public String getPostCode() { 29 | return postCode; 30 | } 31 | 32 | public String getCity() { 33 | return city; 34 | } 35 | 36 | public void setStreet(String street) { 37 | this.street = street; 38 | } 39 | 40 | public void setPostCode(String postCode) { 41 | this.postCode = postCode; 42 | } 43 | 44 | public void setCity(String city) { 45 | this.city = city; 46 | } 47 | 48 | @Override 49 | public String toString() { 50 | return "Address{" + 51 | "street='" + street + '\'' + 52 | ", postCode='" + postCode + '\'' + 53 | ", city='" + city + '\'' + 54 | '}'; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /scoring/adapters-input/src/main/java/com/mploed/dddwithspring/scoring/incoming/financing/Loan.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.scoring.incoming.financing; 2 | 3 | import javax.persistence.Entity; 4 | import javax.persistence.GeneratedValue; 5 | import javax.persistence.GenerationType; 6 | import javax.persistence.Id; 7 | import java.io.Serializable; 8 | 9 | public class Loan implements Serializable { 10 | private Long databaseId; 11 | private int loanAmount; 12 | private int interestRate; 13 | private int repaymentInPercent; 14 | private int fixedInterestRateInYears; 15 | 16 | public Loan() { 17 | this.interestRate = 2; 18 | } 19 | 20 | public Long getDatabaseId() { 21 | return databaseId; 22 | } 23 | 24 | public void setDatabaseId(Long databaseId) { 25 | this.databaseId = databaseId; 26 | } 27 | 28 | public int getLoanAmount() { 29 | return loanAmount; 30 | } 31 | 32 | public void setLoanAmount(int loanAmount) { 33 | this.loanAmount = loanAmount; 34 | } 35 | 36 | public int getInterestRate() { 37 | return interestRate; 38 | } 39 | 40 | public void setInterestRate(int interestRate) { 41 | this.interestRate = interestRate; 42 | } 43 | 44 | public int getRepaymentInPercent() { 45 | return repaymentInPercent; 46 | } 47 | 48 | public void setRepaymentInPercent(int repaymentInPercent) { 49 | this.repaymentInPercent = repaymentInPercent; 50 | } 51 | 52 | public int getFixedInterestRateInYears() { 53 | return fixedInterestRateInYears; 54 | } 55 | 56 | public void setFixedInterestRateInYears(int fixedInterestRateInYears) { 57 | this.fixedInterestRateInYears = fixedInterestRateInYears; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /credit-agency/src/main/java/com/mploed/dddwithspring/creditagency/web/PersonRatingController.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditagency.web; 2 | 3 | import com.mploed.dddwithspring.creditagency.repository.PersonRatingRepository; 4 | import org.springframework.data.domain.Sort; 5 | import org.springframework.stereotype.Controller; 6 | import org.springframework.ui.Model; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.context.request.WebRequest; 10 | import org.springframework.web.servlet.ModelAndView; 11 | 12 | import javax.servlet.http.HttpServletResponse; 13 | import java.util.Date; 14 | 15 | @Controller 16 | @RequestMapping("person-rating") 17 | public class PersonRatingController { 18 | private PersonRatingRepository personRatingRepository; 19 | 20 | public PersonRatingController(PersonRatingRepository personRatingRepository) { 21 | this.personRatingRepository = personRatingRepository; 22 | } 23 | 24 | @RequestMapping(value = "/feed", produces = "application/atom+xml") 25 | public ModelAndView orderFeed(WebRequest webRequest, HttpServletResponse response) { 26 | 27 | Date lastUpdate = personRatingRepository.lastUpdate(); 28 | // null handling for a new start of the application with no current ratings in it 29 | if(lastUpdate != null) { 30 | response.setDateHeader("Last-Modified", lastUpdate.getTime()); 31 | } 32 | 33 | Sort sort = new Sort(Sort.Direction.ASC, "lastUpdated"); 34 | return new ModelAndView(new PersonRatingAtomFeedView(personRatingRepository), "personRatings", personRatingRepository.findAll(sort)); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /credit-sales-funnel/src/main/java/com/mploed/dddwithspring/creditsalesfunnel/model/realEstate/ApartmentInformation.java: -------------------------------------------------------------------------------- 1 | package com.mploed.dddwithspring.creditsalesfunnel.model.realEstate; 2 | 3 | import com.mploed.dddwithspring.creditsalesfunnel.model.validation.ApplicationSubmissionGroup; 4 | 5 | import javax.persistence.Embeddable; 6 | import javax.validation.constraints.Min; 7 | import javax.validation.constraints.NotEmpty; 8 | import javax.validation.constraints.NotNull; 9 | import java.io.Serializable; 10 | 11 | @Embeddable 12 | public class ApartmentInformation implements Serializable { 13 | @Min(value = 1, groups = ApplicationSubmissionGroup.class) 14 | private int numberOfApartmentsInHouse; 15 | 16 | @NotNull(groups = ApplicationSubmissionGroup.class) 17 | @NotEmpty(groups = ApplicationSubmissionGroup.class) 18 | private String nameOfApartment; 19 | 20 | @NotNull(groups = ApplicationSubmissionGroup.class) 21 | private ApartmentLocation apartmentLocation; 22 | 23 | public int getNumberOfApartmentsInHouse() { 24 | return numberOfApartmentsInHouse; 25 | } 26 | 27 | public void setNumberOfApartmentsInHouse(int numberOfApartmentsInHouse) { 28 | this.numberOfApartmentsInHouse = numberOfApartmentsInHouse; 29 | } 30 | 31 | public String getNameOfApartment() { 32 | return nameOfApartment; 33 | } 34 | 35 | public void setNameOfApartment(String nameOfApartment) { 36 | this.nameOfApartment = nameOfApartment; 37 | } 38 | 39 | public ApartmentLocation getApartmentLocation() { 40 | return apartmentLocation; 41 | } 42 | 43 | public void setApartmentLocation(ApartmentLocation apartmentLocation) { 44 | this.apartmentLocation = apartmentLocation; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /credit-sales-funnel/src/main/resources/templates/layout/baseIndex.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 13 | 14 | 15 | Big Pug Loans 16 | 17 | 18 | 19 | 20 | 21 | Whatever content there is 22 | 23 | 24 | 25 | 26 | 27 | 30 | 33 | 36 | 37 |
21 | Launch Scoring Activity Monitor 22 |