├── confsvr ├── src │ └── main │ │ ├── resources │ │ ├── bootstrap.yml │ │ └── application.yml │ │ ├── docker │ │ ├── Dockerfile │ │ └── run.sh │ │ └── java │ │ └── com │ │ └── thoughtmechanix │ │ └── confsvr │ │ └── ConfigServerApplication.java └── pom.xml ├── orgservice-new ├── src │ └── main │ │ ├── resources │ │ ├── bootstrap.yml │ │ ├── application.yml │ │ └── schema.sql │ │ ├── docker │ │ ├── Dockerfile │ │ └── run.sh │ │ └── java │ │ └── com │ │ └── thoughtmechanix │ │ └── organization │ │ ├── repository │ │ └── OrganizationRepository.java │ │ ├── utils │ │ ├── UserContextHolder.java │ │ ├── UserContextInterceptor.java │ │ ├── UserContext.java │ │ └── UserContextFilter.java │ │ ├── Application.java │ │ ├── services │ │ └── OrganizationService.java │ │ ├── model │ │ └── Organization.java │ │ ├── hystrix │ │ ├── DelegatingUserContextCallable.java │ │ ├── ThreadLocalConfiguration.java │ │ └── ThreadLocalAwareStrategy.java │ │ └── controllers │ │ └── OrganizationServiceController.java └── pom.xml ├── zuulsvr ├── src │ └── main │ │ ├── resources │ │ ├── bootstrap.yml │ │ └── application.yml │ │ ├── docker │ │ ├── Dockerfile │ │ └── run.sh │ │ └── java │ │ └── com │ │ └── thoughtmechanix │ │ └── zuulsvr │ │ ├── model │ │ ├── UserInfo.java │ │ └── AbTestingRoute.java │ │ ├── utils │ │ ├── UserContextHolder.java │ │ ├── UserContextInterceptor.java │ │ ├── UserContext.java │ │ └── UserContextFilter.java │ │ ├── ZuulServerApplication.java │ │ └── filters │ │ ├── ResponseFilter.java │ │ ├── TrackingFilter.java │ │ ├── FilterUtils.java │ │ └── SpecialRoutesFilter.java └── pom.xml ├── organization-service ├── src │ └── main │ │ ├── resources │ │ ├── bootstrap.yml │ │ ├── application.yml │ │ └── schema.sql │ │ ├── docker │ │ ├── Dockerfile │ │ └── run.sh │ │ └── java │ │ └── com │ │ └── thoughtmechanix │ │ └── organization │ │ ├── repository │ │ └── OrganizationRepository.java │ │ ├── utils │ │ ├── UserContextHolder.java │ │ ├── UserContextInterceptor.java │ │ ├── UserContext.java │ │ └── UserContextFilter.java │ │ ├── Application.java │ │ ├── services │ │ └── OrganizationService.java │ │ ├── model │ │ └── Organization.java │ │ ├── hystrix │ │ ├── DelegatingUserContextCallable.java │ │ ├── ThreadLocalConfiguration.java │ │ └── ThreadLocalAwareStrategy.java │ │ └── controllers │ │ └── OrganizationServiceController.java └── pom.xml ├── specialroutes-service ├── src │ └── main │ │ ├── resources │ │ ├── bootstrap.yml │ │ ├── schema.sql │ │ └── application.yml │ │ ├── docker │ │ ├── Dockerfile │ │ └── run.sh │ │ └── java │ │ └── com │ │ └── thoughtmechanix │ │ └── specialroutes │ │ ├── exception │ │ └── NoRouteFound.java │ │ ├── repository │ │ └── AbTestingRouteRepository.java │ │ ├── utils │ │ ├── UserContextHolder.java │ │ ├── UserContextInterceptor.java │ │ ├── UserContext.java │ │ └── UserContextFilter.java │ │ ├── Application.java │ │ ├── controllers │ │ └── SpecialRoutesServiceController.java │ │ ├── services │ │ └── AbTestingRouteService.java │ │ ├── model │ │ └── AbTestingRoute.java │ │ └── hystrix │ │ ├── DelegatingUserContextCallable.java │ │ ├── ThreadLocalConfiguration.java │ │ └── ThreadLocalAwareStrategy.java └── pom.xml ├── eurekasvr ├── src │ └── main │ │ ├── docker │ │ ├── Dockerfile │ │ └── run.sh │ │ ├── resources │ │ └── application.yml │ │ └── java │ │ └── com │ │ └── thoughtmechanix │ │ └── eurekasvr │ │ └── EurekaServerApplication.java └── pom.xml ├── licensing-service ├── src │ └── main │ │ ├── docker │ │ ├── Dockerfile │ │ └── run.sh │ │ ├── resources │ │ ├── bootstrap.yml │ │ ├── application.yml │ │ └── schema.sql │ │ └── java │ │ └── com │ │ └── thoughtmechanix │ │ └── licenses │ │ ├── config │ │ └── ServiceConfig.java │ │ ├── repository │ │ └── LicenseRepository.java │ │ ├── controllers │ │ ├── ToolsController.java │ │ └── LicenseServiceController.java │ │ ├── utils │ │ ├── UserContextHolder.java │ │ ├── UserContextInterceptor.java │ │ ├── UserContext.java │ │ └── UserContextFilter.java │ │ ├── model │ │ ├── Organization.java │ │ └── License.java │ │ ├── services │ │ ├── DiscoveryService.java │ │ └── LicenseService.java │ │ ├── Application.java │ │ ├── clients │ │ └── OrganizationRestTemplateClient.java │ │ └── hystrix │ │ ├── DelegatingUserContextCallable.java │ │ ├── ThreadLocalConfiguration.java │ │ └── ThreadLocalAwareStrategy.java └── pom.xml ├── .gitignore ├── pom.xml ├── .travis.yml ├── docker └── common │ └── docker-compose.yml └── README.md /confsvr/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: configserver 4 | 5 | -------------------------------------------------------------------------------- /orgservice-new/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: organizationservice 4 | profiles: 5 | active: 6 | default 7 | cloud: 8 | config: 9 | enabled: true -------------------------------------------------------------------------------- /zuulsvr/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: zuulservice 4 | profiles: 5 | active: 6 | default 7 | cloud: 8 | config: 9 | enabled: true 10 | -------------------------------------------------------------------------------- /organization-service/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: organizationservice 4 | profiles: 5 | active: 6 | default 7 | cloud: 8 | config: 9 | enabled: true -------------------------------------------------------------------------------- /specialroutes-service/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: specialroutesservice 4 | profiles: 5 | active: 6 | default 7 | cloud: 8 | config: 9 | enabled: true 10 | -------------------------------------------------------------------------------- /zuulsvr/src/main/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jdk-alpine 2 | RUN apk update && apk upgrade && apk add netcat-openbsd 3 | RUN mkdir -p /usr/local/zuulservice 4 | ADD @project.build.finalName@.jar /usr/local/zuulservice/ 5 | ADD run.sh run.sh 6 | RUN chmod +x run.sh 7 | CMD ./run.sh 8 | -------------------------------------------------------------------------------- /eurekasvr/src/main/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jdk-alpine 2 | RUN apk update && apk upgrade && apk add netcat-openbsd 3 | RUN mkdir -p /usr/local/eurekaserver 4 | ADD @project.build.finalName@.jar /usr/local/eurekaserver/ 5 | ADD run.sh run.sh 6 | RUN chmod +x run.sh 7 | CMD ./run.sh 8 | -------------------------------------------------------------------------------- /licensing-service/src/main/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jdk-alpine 2 | RUN apk update && apk upgrade && apk add netcat-openbsd 3 | RUN mkdir -p /usr/local/licensingservice 4 | ADD @project.build.finalName@.jar /usr/local/licensingservice/ 5 | ADD run.sh run.sh 6 | RUN chmod +x run.sh 7 | CMD ./run.sh 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Java class files 2 | *.class 3 | 4 | # Eclipse project files 5 | .classpath 6 | .project 7 | .settings/ 8 | 9 | # Intellij project files 10 | *.iml 11 | *.ipr 12 | *.iws 13 | .idea/ 14 | 15 | .DS_Store/ 16 | /target 17 | 18 | /target 19 | /target/ 20 | **/target/ 21 | 22 | .DS_Store 23 | -------------------------------------------------------------------------------- /licensing-service/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: licensingservice 4 | profiles: 5 | active: 6 | default 7 | cloud: 8 | config: 9 | enabled: true 10 | # discovery: 11 | # enabled: true 12 | # serviceId: configserver 13 | -------------------------------------------------------------------------------- /orgservice-new/src/main/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jdk-alpine 2 | RUN apk update && apk upgrade && apk add netcat-openbsd 3 | RUN mkdir -p /usr/local/organizationservice-new 4 | ADD @project.build.finalName@.jar /usr/local/organizationservice-new/ 5 | ADD run.sh run.sh 6 | RUN chmod +x run.sh 7 | CMD ./run.sh 8 | -------------------------------------------------------------------------------- /eurekasvr/src/main/docker/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | echo "********************************************************" 3 | echo "Starting the Eureka Server" 4 | echo "********************************************************" 5 | java -Djava.security.egd=file:/dev/./urandom -jar /usr/local/eurekaserver/@project.build.finalName@.jar 6 | -------------------------------------------------------------------------------- /specialroutes-service/src/main/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jdk-alpine 2 | RUN apk update && apk upgrade && apk add netcat-openbsd 3 | RUN mkdir -p /usr/local/specialroutes-services 4 | ADD @project.build.finalName@.jar /usr/local/specialroutes-service/ 5 | ADD run.sh run.sh 6 | RUN chmod +x run.sh 7 | CMD ./run.sh 8 | -------------------------------------------------------------------------------- /organization-service/src/main/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jdk-alpine 2 | RUN apk update && apk upgrade && apk add netcat-openbsd 3 | RUN mkdir -p /usr/local/organizationservice 4 | 5 | ADD organization-service-0.0.1-SNAPSHOT.jar /usr/local/organizationservice/ 6 | ADD run.sh run.sh 7 | RUN chmod +x run.sh 8 | CMD ./run.sh 9 | -------------------------------------------------------------------------------- /specialroutes-service/src/main/java/com/thoughtmechanix/specialroutes/exception/NoRouteFound.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.specialroutes.exception; 2 | 3 | 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.web.bind.annotation.ResponseStatus; 6 | 7 | @ResponseStatus(HttpStatus.NOT_FOUND) 8 | public class NoRouteFound extends RuntimeException{ 9 | } 10 | -------------------------------------------------------------------------------- /licensing-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | eureka: 2 | instance: 3 | preferIpAddress: true 4 | client: 5 | registerWithEureka: true 6 | fetchRegistry: true 7 | serviceUrl: 8 | defaultZone: http://localhost:8761/eureka/ 9 | 10 | #Setting logging levels 11 | logging: 12 | level: 13 | com.netflix: WARN 14 | org.springframework.web: WARN 15 | com.thoughtmechanix: DEBUG 16 | -------------------------------------------------------------------------------- /specialroutes-service/src/main/resources/schema.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS abtesting; 2 | 3 | CREATE TABLE abtesting ( 4 | service_name VARCHAR(100) PRIMARY KEY NOT NULL, 5 | active VARCHAR(1) NOT NULL, 6 | endpoint VARCHAR(100) NOT NULL, 7 | weight INT); 8 | 9 | 10 | INSERT INTO abtesting (service_name, active, endpoint, weight) VALUES ('organizationservice', 'Y','http://orgservice-new:8087',5); 11 | -------------------------------------------------------------------------------- /specialroutes-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | 2 | #Setting the logging levels for the service 3 | logging: 4 | level: 5 | com.netflix: WARN 6 | org.springframework.web: WARN 7 | com.thoughtmechanix: DEBUG 8 | 9 | eureka: 10 | instance: 11 | preferIpAddress: true 12 | client: 13 | registerWithEureka: true 14 | fetchRegistry: true 15 | serviceUrl: 16 | defaultZone: http://localhost:8761/eureka/ 17 | -------------------------------------------------------------------------------- /orgservice-new/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | 2 | #Setting the logging levels for the service 3 | logging: 4 | level: 5 | com.netflix: WARN 6 | org.springframework.web: WARN 7 | com.thoughtmechanix: DEBUG 8 | 9 | 10 | eureka: 11 | instance: 12 | preferIpAddress: true 13 | client: 14 | registerWithEureka: true 15 | fetchRegistry: true 16 | serviceUrl: 17 | defaultZone: http://localhost:8761/eureka/ 18 | 19 | -------------------------------------------------------------------------------- /organization-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | 2 | #Setting the logging levels for the service 3 | logging: 4 | level: 5 | com.netflix: WARN 6 | org.springframework.web: WARN 7 | com.thoughtmechanix: DEBUG 8 | 9 | 10 | eureka: 11 | instance: 12 | preferIpAddress: true 13 | client: 14 | registerWithEureka: true 15 | fetchRegistry: true 16 | serviceUrl: 17 | defaultZone: http://localhost:8761/eureka/ 18 | 19 | -------------------------------------------------------------------------------- /eurekasvr/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | #Default port is 8761 2 | server: 3 | port: 8761 4 | 5 | eureka: 6 | client: 7 | registerWithEureka: false 8 | fetchRegistry: false 9 | server: 10 | waitTimeInMsWhenSyncEmpty: 30 11 | serviceUrl: 12 | defaultZone: http://localhost:8761 13 | 14 | #Setting logging levels 15 | logging: 16 | level: 17 | com.netflix: WARN 18 | org.springframework.web: WARN 19 | com.thoughtmechanix: DEBUG 20 | -------------------------------------------------------------------------------- /licensing-service/src/main/java/com/thoughtmechanix/licenses/config/ServiceConfig.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.licenses.config; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.stereotype.Component; 5 | 6 | @Component 7 | public class ServiceConfig{ 8 | 9 | @Value("${example.property}") 10 | private String exampleProperty=""; 11 | 12 | public String getExampleProperty(){ 13 | return exampleProperty; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /specialroutes-service/src/main/java/com/thoughtmechanix/specialroutes/repository/AbTestingRouteRepository.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.specialroutes.repository; 2 | 3 | import com.thoughtmechanix.specialroutes.model.AbTestingRoute; 4 | import org.springframework.data.repository.CrudRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | @Repository 8 | public interface AbTestingRouteRepository extends CrudRepository { 9 | public AbTestingRoute findByServiceName(String serviceName); 10 | } 11 | -------------------------------------------------------------------------------- /orgservice-new/src/main/java/com/thoughtmechanix/organization/repository/OrganizationRepository.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.organization.repository; 2 | 3 | import com.thoughtmechanix.organization.model.Organization; 4 | import org.springframework.data.repository.CrudRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import java.util.List; 8 | 9 | @Repository 10 | public interface OrganizationRepository extends CrudRepository { 11 | public Organization findById(String organizationId); 12 | } 13 | -------------------------------------------------------------------------------- /organization-service/src/main/java/com/thoughtmechanix/organization/repository/OrganizationRepository.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.organization.repository; 2 | 3 | import com.thoughtmechanix.organization.model.Organization; 4 | import org.springframework.data.repository.CrudRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import java.util.List; 8 | 9 | @Repository 10 | public interface OrganizationRepository extends CrudRepository { 11 | public Organization findById(String organizationId); 12 | } 13 | -------------------------------------------------------------------------------- /zuulsvr/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 5555 3 | 4 | #Setting logging levels 5 | logging: 6 | level: 7 | com.netflix: WARN 8 | org.springframework.web: WARN 9 | com.thoughtmechanix: DEBUG 10 | 11 | eureka: 12 | instance: 13 | preferIpAddress: true 14 | client: 15 | registerWithEureka: true 16 | fetchRegistry: true 17 | serviceUrl: 18 | defaultZone: http://localhost:8761/eureka/ 19 | 20 | zuul: 21 | prefix: /api 22 | routes: 23 | organizationservice: /organization/** 24 | -------------------------------------------------------------------------------- /eurekasvr/src/main/java/com/thoughtmechanix/eurekasvr/EurekaServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.eurekasvr; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; 6 | 7 | @SpringBootApplication 8 | @EnableEurekaServer 9 | public class EurekaServerApplication { 10 | public static void main(String[] args) { 11 | SpringApplication.run(EurekaServerApplication.class, args); 12 | } 13 | } -------------------------------------------------------------------------------- /zuulsvr/src/main/java/com/thoughtmechanix/zuulsvr/model/UserInfo.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.zuulsvr.model; 2 | 3 | public class UserInfo { 4 | String organizationId; 5 | String userId; 6 | 7 | public String getOrganizationId() { 8 | return this.organizationId; 9 | } 10 | 11 | 12 | public void setOrganizationId(String organizationId) { 13 | this.organizationId = organizationId; 14 | } 15 | 16 | public String getUserId() { 17 | return userId; 18 | } 19 | 20 | public void setUserId(String userId) { 21 | this.userId = userId; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /licensing-service/src/main/java/com/thoughtmechanix/licenses/repository/LicenseRepository.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.licenses.repository; 2 | 3 | import com.thoughtmechanix.licenses.model.License; 4 | import org.springframework.data.repository.CrudRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import java.util.List; 8 | 9 | @Repository 10 | public interface LicenseRepository extends CrudRepository { 11 | public List findByOrganizationId(String organizationId); 12 | public License findByOrganizationIdAndLicenseId(String organizationId,String licenseId); 13 | } 14 | -------------------------------------------------------------------------------- /confsvr/src/main/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jdk-alpine 2 | RUN apk update && apk upgrade && apk add netcat-openbsd && apk add curl 3 | RUN mkdir -p /usr/local/configserver 4 | RUN cd /tmp/ && \ 5 | curl -k -LO "http://download.oracle.com/otn-pub/java/jce/8/jce_policy-8.zip" -H 'Cookie: oraclelicense=accept-securebackup-cookie' && \ 6 | unzip jce_policy-8.zip && \ 7 | rm jce_policy-8.zip && \ 8 | yes |cp -v /tmp/UnlimitedJCEPolicyJDK8/*.jar /usr/lib/jvm/java-1.8-openjdk/jre/lib/security/ 9 | ADD @project.build.finalName@.jar /usr/local/configserver/ 10 | ADD run.sh run.sh 11 | RUN chmod +x run.sh 12 | CMD ./run.sh 13 | -------------------------------------------------------------------------------- /confsvr/src/main/java/com/thoughtmechanix/confsvr/ConfigServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.confsvr; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.config.server.EnableConfigServer; 6 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient; 7 | 8 | @SpringBootApplication 9 | @EnableEurekaClient 10 | @EnableConfigServer 11 | public class ConfigServerApplication { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(ConfigServerApplication.class, args); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /confsvr/src/main/docker/run.sh: -------------------------------------------------------------------------------- 1 | 2 | echo "********************************************************" 3 | echo "Waiting for the eureka server to start on port $EUREKASERVER_PORT" 4 | echo "********************************************************" 5 | while ! `nc -z eurekaserver $EUREKASERVER_PORT`; do sleep 3; done 6 | echo ">>>>>>>>>>>> Eureka Server has started" 7 | 8 | echo "********************************************************" 9 | echo "Starting Configuration Service with Eureka Endpoint: $EUREKASERVER_URI"; 10 | echo "********************************************************" 11 | java -Djava.security.egd=file:/dev/./urandom -Deureka.client.serviceUrl.defaultZone=$EUREKASERVER_URI -jar /usr/local/configserver/@project.build.finalName@.jar 12 | -------------------------------------------------------------------------------- /orgservice-new/src/main/resources/schema.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS organizations; 2 | 3 | CREATE TABLE organizations ( 4 | organization_id VARCHAR(100) PRIMARY KEY NOT NULL, 5 | name TEXT NOT NULL, 6 | contact_name TEXT NOT NULL, 7 | contact_email TEXT NOT NULL, 8 | contact_phone TEXT NOT NULL); 9 | 10 | 11 | INSERT INTO organizations (organization_id, name, contact_name, contact_email, contact_phone) 12 | VALUES ('e254f8c-c442-4ebe-a82a-e2fc1d1ff78a', 'customer-crm-co', 'Mark Balster', 'mark.balster@custcrmco.com', '823-555-1212'); 13 | 14 | INSERT INTO organizations (organization_id, name, contact_name, contact_email, contact_phone) 15 | VALUES ('442adb6e-fa58-47f3-9ca2-ed1fecdfe86c', 'HR-PowerSuite', 'Doug Drewry','doug.drewry@hr.com', '920-555-1212'); 16 | -------------------------------------------------------------------------------- /organization-service/src/main/resources/schema.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS organizations; 2 | 3 | CREATE TABLE organizations ( 4 | organization_id VARCHAR(100) PRIMARY KEY NOT NULL, 5 | name TEXT NOT NULL, 6 | contact_name TEXT NOT NULL, 7 | contact_email TEXT NOT NULL, 8 | contact_phone TEXT NOT NULL); 9 | 10 | 11 | INSERT INTO organizations (organization_id, name, contact_name, contact_email, contact_phone) 12 | VALUES ('e254f8c-c442-4ebe-a82a-e2fc1d1ff78a', 'customer-crm-co', 'Mark Balster', 'mark.balster@custcrmco.com', '823-555-1212'); 13 | 14 | INSERT INTO organizations (organization_id, name, contact_name, contact_email, contact_phone) 15 | VALUES ('442adb6e-fa58-47f3-9ca2-ed1fecdfe86c', 'HR-PowerSuite', 'Doug Drewry','doug.drewry@hr.com', '920-555-1212'); 16 | -------------------------------------------------------------------------------- /licensing-service/src/main/java/com/thoughtmechanix/licenses/controllers/ToolsController.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.licenses.controllers; 2 | 3 | import com.thoughtmechanix.licenses.services.DiscoveryService; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RequestMethod; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | import java.util.List; 10 | 11 | @RestController 12 | @RequestMapping(value="v1/tools") 13 | public class ToolsController { 14 | @Autowired 15 | private DiscoveryService discoveryService; 16 | 17 | @RequestMapping(value="/eureka/services",method = RequestMethod.GET) 18 | public List getEurekaServices() { 19 | 20 | return discoveryService.getEurekaServices(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /zuulsvr/src/main/java/com/thoughtmechanix/zuulsvr/utils/UserContextHolder.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.zuulsvr.utils; 2 | 3 | 4 | import org.springframework.util.Assert; 5 | 6 | public class UserContextHolder { 7 | private static final ThreadLocal userContext = new ThreadLocal(); 8 | 9 | public static final UserContext getContext(){ 10 | UserContext context = userContext.get(); 11 | 12 | if (context == null) { 13 | context = createEmptyContext(); 14 | userContext.set(context); 15 | 16 | } 17 | return userContext.get(); 18 | } 19 | 20 | public static final void setContext(UserContext context) { 21 | Assert.notNull(context, "Only non-null UserContext instances are permitted"); 22 | userContext.set(context); 23 | } 24 | 25 | public static final UserContext createEmptyContext(){ 26 | return new UserContext(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /licensing-service/src/main/java/com/thoughtmechanix/licenses/utils/UserContextHolder.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.licenses.utils; 2 | 3 | 4 | import org.springframework.util.Assert; 5 | 6 | public class UserContextHolder { 7 | private static final ThreadLocal userContext = new ThreadLocal(); 8 | 9 | public static final UserContext getContext(){ 10 | UserContext context = userContext.get(); 11 | 12 | if (context == null) { 13 | context = createEmptyContext(); 14 | userContext.set(context); 15 | 16 | } 17 | return userContext.get(); 18 | } 19 | 20 | public static final void setContext(UserContext context) { 21 | Assert.notNull(context, "Only non-null UserContext instances are permitted"); 22 | userContext.set(context); 23 | } 24 | 25 | public static final UserContext createEmptyContext(){ 26 | return new UserContext(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /orgservice-new/src/main/java/com/thoughtmechanix/organization/utils/UserContextHolder.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.organization.utils; 2 | 3 | 4 | import org.springframework.util.Assert; 5 | 6 | public class UserContextHolder { 7 | private static final ThreadLocal userContext = new ThreadLocal(); 8 | 9 | public static final UserContext getContext(){ 10 | UserContext context = userContext.get(); 11 | 12 | if (context == null) { 13 | context = createEmptyContext(); 14 | userContext.set(context); 15 | 16 | } 17 | return userContext.get(); 18 | } 19 | 20 | public static final void setContext(UserContext context) { 21 | Assert.notNull(context, "Only non-null UserContext instances are permitted"); 22 | userContext.set(context); 23 | } 24 | 25 | public static final UserContext createEmptyContext(){ 26 | return new UserContext(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /organization-service/src/main/java/com/thoughtmechanix/organization/utils/UserContextHolder.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.organization.utils; 2 | 3 | 4 | import org.springframework.util.Assert; 5 | 6 | public class UserContextHolder { 7 | private static final ThreadLocal userContext = new ThreadLocal(); 8 | 9 | public static final UserContext getContext(){ 10 | UserContext context = userContext.get(); 11 | 12 | if (context == null) { 13 | context = createEmptyContext(); 14 | userContext.set(context); 15 | 16 | } 17 | return userContext.get(); 18 | } 19 | 20 | public static final void setContext(UserContext context) { 21 | Assert.notNull(context, "Only non-null UserContext instances are permitted"); 22 | userContext.set(context); 23 | } 24 | 25 | public static final UserContext createEmptyContext(){ 26 | return new UserContext(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /specialroutes-service/src/main/java/com/thoughtmechanix/specialroutes/utils/UserContextHolder.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.specialroutes.utils; 2 | 3 | 4 | import org.springframework.util.Assert; 5 | 6 | public class UserContextHolder { 7 | private static final ThreadLocal userContext = new ThreadLocal(); 8 | 9 | public static final UserContext getContext(){ 10 | UserContext context = userContext.get(); 11 | 12 | if (context == null) { 13 | context = createEmptyContext(); 14 | userContext.set(context); 15 | 16 | } 17 | return userContext.get(); 18 | } 19 | 20 | public static final void setContext(UserContext context) { 21 | Assert.notNull(context, "Only non-null UserContext instances are permitted"); 22 | userContext.set(context); 23 | } 24 | 25 | public static final UserContext createEmptyContext(){ 26 | return new UserContext(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /orgservice-new/src/main/java/com/thoughtmechanix/organization/Application.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.organization; 2 | 3 | import com.thoughtmechanix.organization.utils.UserContextFilter; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; 7 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient; 8 | import org.springframework.context.annotation.Bean; 9 | 10 | import javax.servlet.Filter; 11 | 12 | @SpringBootApplication 13 | @EnableEurekaClient 14 | @EnableCircuitBreaker 15 | public class Application { 16 | 17 | @Bean 18 | public Filter userContextFilter() { 19 | UserContextFilter userContextFilter = new UserContextFilter(); 20 | return userContextFilter; 21 | } 22 | 23 | public static void main(String[] args) { 24 | SpringApplication.run(Application.class, args); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /organization-service/src/main/java/com/thoughtmechanix/organization/Application.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.organization; 2 | 3 | import com.thoughtmechanix.organization.utils.UserContextFilter; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; 7 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient; 8 | import org.springframework.context.annotation.Bean; 9 | 10 | import javax.servlet.Filter; 11 | 12 | @SpringBootApplication 13 | @EnableEurekaClient 14 | @EnableCircuitBreaker 15 | public class Application { 16 | 17 | @Bean 18 | public Filter userContextFilter() { 19 | UserContextFilter userContextFilter = new UserContextFilter(); 20 | return userContextFilter; 21 | } 22 | 23 | public static void main(String[] args) { 24 | SpringApplication.run(Application.class, args); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /specialroutes-service/src/main/java/com/thoughtmechanix/specialroutes/Application.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.specialroutes; 2 | 3 | import com.thoughtmechanix.specialroutes.utils.UserContextFilter; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; 7 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient; 8 | import org.springframework.context.annotation.Bean; 9 | 10 | import javax.servlet.Filter; 11 | 12 | @SpringBootApplication 13 | @EnableEurekaClient 14 | @EnableCircuitBreaker 15 | public class Application { 16 | 17 | @Bean 18 | public Filter userContextFilter() { 19 | UserContextFilter userContextFilter = new UserContextFilter(); 20 | return userContextFilter; 21 | } 22 | 23 | public static void main(String[] args) { 24 | SpringApplication.run(Application.class, args); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /zuulsvr/src/main/java/com/thoughtmechanix/zuulsvr/model/AbTestingRoute.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.zuulsvr.model; 2 | 3 | public class AbTestingRoute { 4 | String serviceName; 5 | String active; 6 | String endpoint; 7 | Integer weight; 8 | 9 | public String getActive() { 10 | return active; 11 | } 12 | 13 | public void setActive(String active) { 14 | this.active = active; 15 | } 16 | 17 | public String getServiceName() { 18 | return serviceName; 19 | } 20 | 21 | public void setServiceName(String serviceName) { 22 | this.serviceName = serviceName; 23 | } 24 | 25 | public String getEndpoint() { 26 | return endpoint; 27 | } 28 | 29 | public void setEndpoint(String endpoint) { 30 | this.endpoint = endpoint; 31 | } 32 | 33 | public Integer getWeight() { 34 | return weight; 35 | } 36 | 37 | public void setWeight(Integer weight) { 38 | this.weight = weight; 39 | } 40 | 41 | 42 | } -------------------------------------------------------------------------------- /zuulsvr/src/main/java/com/thoughtmechanix/zuulsvr/utils/UserContextInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.zuulsvr.utils; 2 | 3 | import org.springframework.http.HttpHeaders; 4 | import org.springframework.http.HttpRequest; 5 | import org.springframework.http.client.ClientHttpRequestExecution; 6 | import org.springframework.http.client.ClientHttpRequestInterceptor; 7 | import org.springframework.http.client.ClientHttpResponse; 8 | 9 | import java.io.IOException; 10 | 11 | public class UserContextInterceptor implements ClientHttpRequestInterceptor { 12 | @Override 13 | public ClientHttpResponse intercept( 14 | HttpRequest request, byte[] body, ClientHttpRequestExecution execution) 15 | throws IOException { 16 | 17 | HttpHeaders headers = request.getHeaders(); 18 | headers.add(UserContext.CORRELATION_ID, UserContextHolder.getContext().getCorrelationId()); 19 | headers.add(UserContext.AUTH_TOKEN, UserContextHolder.getContext().getAuthToken()); 20 | 21 | return execution.execute(request, body); 22 | } 23 | } -------------------------------------------------------------------------------- /orgservice-new/src/main/java/com/thoughtmechanix/organization/services/OrganizationService.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.organization.services; 2 | 3 | import com.thoughtmechanix.organization.model.Organization; 4 | import com.thoughtmechanix.organization.repository.OrganizationRepository; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Service; 7 | 8 | import java.util.UUID; 9 | 10 | @Service 11 | public class OrganizationService { 12 | @Autowired 13 | private OrganizationRepository orgRepository; 14 | 15 | public Organization getOrg(String organizationId) { 16 | return orgRepository.findById(organizationId); 17 | } 18 | 19 | public void saveOrg(Organization org){ 20 | org.setId( UUID.randomUUID().toString()); 21 | 22 | orgRepository.save(org); 23 | 24 | } 25 | 26 | public void updateOrg(Organization org){ 27 | orgRepository.save(org); 28 | } 29 | 30 | public void deleteOrg(Organization org){ 31 | orgRepository.delete( org.getId()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /organization-service/src/main/java/com/thoughtmechanix/organization/services/OrganizationService.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.organization.services; 2 | 3 | import com.thoughtmechanix.organization.model.Organization; 4 | import com.thoughtmechanix.organization.repository.OrganizationRepository; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Service; 7 | 8 | import java.util.UUID; 9 | 10 | @Service 11 | public class OrganizationService { 12 | @Autowired 13 | private OrganizationRepository orgRepository; 14 | 15 | public Organization getOrg(String organizationId) { 16 | return orgRepository.findById(organizationId); 17 | } 18 | 19 | public void saveOrg(Organization org){ 20 | org.setId( UUID.randomUUID().toString()); 21 | 22 | orgRepository.save(org); 23 | 24 | } 25 | 26 | public void updateOrg(Organization org){ 27 | orgRepository.save(org); 28 | } 29 | 30 | public void deleteOrg(Organization org){ 31 | orgRepository.delete( org.getId()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /specialroutes-service/src/main/java/com/thoughtmechanix/specialroutes/controllers/SpecialRoutesServiceController.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.specialroutes.controllers; 2 | 3 | 4 | 5 | import com.thoughtmechanix.specialroutes.model.AbTestingRoute; 6 | import com.thoughtmechanix.specialroutes.services.AbTestingRouteService; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.RestController; 10 | import org.springframework.web.bind.annotation.RequestMethod; 11 | import org.springframework.web.bind.annotation.PathVariable; 12 | 13 | @RestController 14 | @RequestMapping(value="v1/route/") 15 | public class SpecialRoutesServiceController { 16 | 17 | @Autowired 18 | AbTestingRouteService routeService; 19 | 20 | @RequestMapping(value="abtesting/{serviceName}",method = RequestMethod.GET) 21 | public AbTestingRoute abstestings(@PathVariable("serviceName") String serviceName) { 22 | 23 | return routeService.getRoute( serviceName); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /confsvr/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # 2 | # This is the core configuration for service. I have two examples here: 3 | # 4 | # - A configuration service which completelty loads the configuration for the services 5 | # from the local file server of the config service. This should only be used for 6 | # demonstration purposes or for a small application with a limited number of services. 7 | # 8 | # - A configuraton service that uses a git-based repository to read the files from 9 | # 10 | 11 | 12 | #################################### 13 | server: 14 | port: 8888 15 | spring: 16 | cloud: 17 | config: 18 | discovery: 19 | enabled: true 20 | server: 21 | encrypt.enabled: false 22 | git: 23 | uri: https://github.com/carnellj/config-repo/ 24 | searchPaths: licensingservice,organizationservice,specialroutesservice,zuulservice 25 | username: native-cloud-apps 26 | password: 0ffended 27 | 28 | #Setting logging levels 29 | logging: 30 | level: 31 | com.netflix: WARN 32 | org.springframework.web: WARN 33 | com.thoughtmechanix: DEBUG 34 | -------------------------------------------------------------------------------- /licensing-service/src/main/java/com/thoughtmechanix/licenses/utils/UserContextInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.licenses.utils; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.http.HttpHeaders; 6 | import org.springframework.http.HttpRequest; 7 | import org.springframework.http.client.ClientHttpRequestExecution; 8 | import org.springframework.http.client.ClientHttpRequestInterceptor; 9 | import org.springframework.http.client.ClientHttpResponse; 10 | 11 | import java.io.IOException; 12 | 13 | public class UserContextInterceptor implements ClientHttpRequestInterceptor { 14 | private static final Logger logger = LoggerFactory.getLogger(UserContextInterceptor.class); 15 | @Override 16 | public ClientHttpResponse intercept( 17 | HttpRequest request, byte[] body, ClientHttpRequestExecution execution) 18 | throws IOException { 19 | 20 | HttpHeaders headers = request.getHeaders(); 21 | headers.add(UserContext.CORRELATION_ID, UserContextHolder.getContext().getCorrelationId()); 22 | headers.add(UserContext.AUTH_TOKEN, UserContextHolder.getContext().getAuthToken()); 23 | 24 | return execution.execute(request, body); 25 | } 26 | } -------------------------------------------------------------------------------- /orgservice-new/src/main/java/com/thoughtmechanix/organization/utils/UserContextInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.organization.utils; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.http.HttpHeaders; 6 | import org.springframework.http.HttpRequest; 7 | import org.springframework.http.client.ClientHttpRequestExecution; 8 | import org.springframework.http.client.ClientHttpRequestInterceptor; 9 | import org.springframework.http.client.ClientHttpResponse; 10 | 11 | import java.io.IOException; 12 | 13 | public class UserContextInterceptor implements ClientHttpRequestInterceptor { 14 | private static final Logger logger = LoggerFactory.getLogger(UserContextInterceptor.class); 15 | @Override 16 | public ClientHttpResponse intercept( 17 | HttpRequest request, byte[] body, ClientHttpRequestExecution execution) 18 | throws IOException { 19 | 20 | 21 | HttpHeaders headers = request.getHeaders(); 22 | headers.add(UserContext.CORRELATION_ID, UserContextHolder.getContext().getCorrelationId()); 23 | headers.add(UserContext.AUTH_TOKEN, UserContextHolder.getContext().getAuthToken()); 24 | 25 | return execution.execute(request, body); 26 | } 27 | } -------------------------------------------------------------------------------- /organization-service/src/main/java/com/thoughtmechanix/organization/utils/UserContextInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.organization.utils; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.http.HttpHeaders; 6 | import org.springframework.http.HttpRequest; 7 | import org.springframework.http.client.ClientHttpRequestExecution; 8 | import org.springframework.http.client.ClientHttpRequestInterceptor; 9 | import org.springframework.http.client.ClientHttpResponse; 10 | 11 | import java.io.IOException; 12 | 13 | public class UserContextInterceptor implements ClientHttpRequestInterceptor { 14 | private static final Logger logger = LoggerFactory.getLogger(UserContextInterceptor.class); 15 | 16 | @Override 17 | public ClientHttpResponse intercept( 18 | HttpRequest request, byte[] body, ClientHttpRequestExecution execution) 19 | throws IOException { 20 | 21 | HttpHeaders headers = request.getHeaders(); 22 | headers.add(UserContext.CORRELATION_ID, UserContextHolder.getContext().getCorrelationId()); 23 | headers.add(UserContext.AUTH_TOKEN, UserContextHolder.getContext().getAuthToken()); 24 | 25 | return execution.execute(request, body); 26 | } 27 | } -------------------------------------------------------------------------------- /zuulsvr/src/main/docker/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "********************************************************" 4 | echo "Waiting for the eureka server to start on port $EUREKASERVER_PORT" 5 | echo "********************************************************" 6 | while ! `nc -z eurekaserver $EUREKASERVER_PORT`; do sleep 3; done 7 | echo "******* Eureka Server has started" 8 | 9 | echo "********************************************************" 10 | echo "Waiting for the configuration server to start on port $CONFIGSERVER_PORT" 11 | echo "********************************************************" 12 | while ! `nc -z configserver $CONFIGSERVER_PORT`; do sleep 3; done 13 | echo "******* Configuration Server has started" 14 | 15 | echo "********************************************************" 16 | echo "Starting Zuul Service with $CONFIGSERVER_URI" 17 | echo "********************************************************" 18 | java -Djava.security.egd=file:/dev/./urandom -Dserver.port=$SERVER_PORT \ 19 | -Deureka.client.serviceUrl.defaultZone=$EUREKASERVER_URI \ 20 | -Dspring.cloud.config.uri=$CONFIGSERVER_URI \ 21 | -Dspring.profiles.active=$PROFILE \ 22 | -jar /usr/local/zuulservice/@project.build.finalName@.jar 23 | -------------------------------------------------------------------------------- /licensing-service/src/main/java/com/thoughtmechanix/licenses/model/Organization.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.licenses.model; 2 | 3 | public class Organization { 4 | String id; 5 | String name; 6 | String contactName; 7 | String contactEmail; 8 | String contactPhone; 9 | 10 | 11 | public String getId() { 12 | return id; 13 | } 14 | 15 | 16 | public void setId(String id) { 17 | this.id = id; 18 | } 19 | 20 | public String getName() { 21 | return name; 22 | } 23 | 24 | public void setName(String name) { 25 | this.name = name; 26 | } 27 | 28 | public String getContactName() { 29 | return contactName; 30 | } 31 | 32 | public void setContactName(String contactName) { 33 | this.contactName = contactName; 34 | } 35 | 36 | public String getContactEmail() { 37 | return contactEmail; 38 | } 39 | 40 | public void setContactEmail(String contactEmail) { 41 | this.contactEmail = contactEmail; 42 | } 43 | 44 | public String getContactPhone() { 45 | return contactPhone; 46 | } 47 | 48 | public void setContactPhone(String contactPhone) { 49 | this.contactPhone = contactPhone; 50 | } 51 | 52 | 53 | } -------------------------------------------------------------------------------- /specialroutes-service/src/main/java/com/thoughtmechanix/specialroutes/utils/UserContextInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.specialroutes.utils; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.http.HttpHeaders; 6 | import org.springframework.http.HttpRequest; 7 | import org.springframework.http.client.ClientHttpRequestExecution; 8 | import org.springframework.http.client.ClientHttpRequestInterceptor; 9 | import org.springframework.http.client.ClientHttpResponse; 10 | 11 | import java.io.IOException; 12 | 13 | public class UserContextInterceptor implements ClientHttpRequestInterceptor { 14 | private static final Logger logger = LoggerFactory.getLogger(UserContextInterceptor.class); 15 | 16 | @Override 17 | public ClientHttpResponse intercept( 18 | HttpRequest request, byte[] body, ClientHttpRequestExecution execution) 19 | throws IOException { 20 | 21 | HttpHeaders headers = request.getHeaders(); 22 | headers.add(UserContext.CORRELATION_ID, UserContextHolder.getContext().getCorrelationId()); 23 | headers.add(UserContext.AUTH_TOKEN, UserContextHolder.getContext().getAuthToken()); 24 | 25 | return execution.execute(request, body); 26 | } 27 | } -------------------------------------------------------------------------------- /licensing-service/src/main/java/com/thoughtmechanix/licenses/services/DiscoveryService.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.licenses.services; 2 | 3 | 4 | import com.thoughtmechanix.licenses.model.Organization; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.cloud.client.ServiceInstance; 7 | import org.springframework.cloud.client.discovery.DiscoveryClient; 8 | import org.springframework.http.HttpMethod; 9 | import org.springframework.http.ResponseEntity; 10 | import org.springframework.stereotype.Service; 11 | import org.springframework.web.client.RestTemplate; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | import java.util.Random; 16 | 17 | @Service 18 | public class DiscoveryService { 19 | @Autowired 20 | RestTemplate restTemplate; 21 | 22 | @Autowired 23 | private DiscoveryClient discoveryClient; 24 | 25 | public List getEurekaServices(){ 26 | List services = new ArrayList(); 27 | 28 | discoveryClient.getServices().forEach(serviceName -> { 29 | discoveryClient.getInstances(serviceName).forEach(instance->{ 30 | services.add( String.format("%s:%s",serviceName,instance.getUri())); 31 | }); 32 | }); 33 | 34 | return services; 35 | } 36 | 37 | 38 | 39 | } 40 | -------------------------------------------------------------------------------- /licensing-service/src/main/resources/schema.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS licenses; 2 | 3 | CREATE TABLE licenses ( 4 | license_id VARCHAR(100) PRIMARY KEY NOT NULL, 5 | organization_id TEXT NOT NULL, 6 | license_type TEXT NOT NULL, 7 | product_name TEXT NOT NULL, 8 | license_max INT NOT NULL, 9 | license_allocated INT, 10 | comment VARCHAR(100)); 11 | 12 | 13 | INSERT INTO licenses (license_id, organization_id, license_type, product_name, license_max, license_allocated) 14 | VALUES ('f3831f8c-c338-4ebe-a82a-e2fc1d1ff78a', 'e254f8c-c442-4ebe-a82a-e2fc1d1ff78a', 'user','CustomerPro', 100,5); 15 | INSERT INTO licenses (license_id, organization_id, license_type, product_name, license_max, license_allocated) 16 | VALUES ('t9876f8c-c338-4abc-zf6a-ttt1', 'e254f8c-c442-4ebe-a82a-e2fc1d1ff78a', 'user','suitability-plus', 200,189); 17 | INSERT INTO licenses (license_id, organization_id, license_type, product_name, license_max, license_allocated) 18 | VALUES ('38777179-7094-4200-9d61-edb101c6ea84', '442adb6e-fa58-47f3-9ca2-ed1fecdfe86c', 'user','HR-PowerSuite', 100,4); 19 | INSERT INTO licenses (license_id, organization_id, license_type, product_name, license_max, license_allocated) 20 | VALUES ('08dbe05-606e-4dad-9d33-90ef10e334f9', '442adb6e-fa58-47f3-9ca2-ed1fecdfe86c', 'core-prod','WildCat Application Gateway', 16,16); -------------------------------------------------------------------------------- /specialroutes-service/src/main/java/com/thoughtmechanix/specialroutes/services/AbTestingRouteService.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.specialroutes.services; 2 | 3 | 4 | import com.thoughtmechanix.specialroutes.exception.NoRouteFound; 5 | import com.thoughtmechanix.specialroutes.model.AbTestingRoute; 6 | import com.thoughtmechanix.specialroutes.repository.AbTestingRouteRepository; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Service; 9 | 10 | 11 | @Service 12 | public class AbTestingRouteService { 13 | @Autowired 14 | private AbTestingRouteRepository abTestingRouteRepository; 15 | 16 | public AbTestingRoute getRoute(String serviceName) { 17 | AbTestingRoute route = abTestingRouteRepository.findByServiceName(serviceName); 18 | 19 | if (route==null){ 20 | throw new NoRouteFound(); 21 | } 22 | 23 | return route; 24 | } 25 | 26 | public void saveAbTestingRoute(AbTestingRoute route){ 27 | 28 | abTestingRouteRepository.save(route); 29 | 30 | } 31 | 32 | public void updateRouteAbTestingRoute(AbTestingRoute route){ 33 | abTestingRouteRepository.save(route); 34 | } 35 | 36 | public void deleteRoute(AbTestingRoute route){ 37 | abTestingRouteRepository.delete(route.getServiceName()); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /zuulsvr/src/main/java/com/thoughtmechanix/zuulsvr/ZuulServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.zuulsvr; 2 | 3 | 4 | import com.thoughtmechanix.zuulsvr.utils.UserContextInterceptor; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.cloud.client.loadbalancer.LoadBalanced; 8 | import org.springframework.cloud.netflix.zuul.EnableZuulProxy; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.web.client.RestTemplate; 11 | 12 | import java.util.Collections; 13 | import java.util.List; 14 | 15 | 16 | @SpringBootApplication 17 | @EnableZuulProxy 18 | public class ZuulServerApplication { 19 | 20 | @LoadBalanced 21 | @Bean 22 | public RestTemplate getRestTemplate(){ 23 | RestTemplate template = new RestTemplate(); 24 | List interceptors = template.getInterceptors(); 25 | if (interceptors == null) { 26 | template.setInterceptors(Collections.singletonList(new UserContextInterceptor())); 27 | } else { 28 | interceptors.add(new UserContextInterceptor()); 29 | template.setInterceptors(interceptors); 30 | } 31 | 32 | return template; 33 | } 34 | 35 | public static void main(String[] args) { 36 | SpringApplication.run(ZuulServerApplication.class, args); 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /zuulsvr/src/main/java/com/thoughtmechanix/zuulsvr/utils/UserContext.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.zuulsvr.utils; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | @Component 6 | public class UserContext { 7 | public static final String CORRELATION_ID = "tmx-correlation-id"; 8 | public static final String AUTH_TOKEN = "tmx-auth-token"; 9 | public static final String USER_ID = "tmx-user-id"; 10 | public static final String ORG_ID = "tmx-org-id"; 11 | 12 | private String correlationId= new String(); 13 | private String authToken= new String(); 14 | private String userId = new String(); 15 | private String orgId = new String(); 16 | 17 | public String getCorrelationId() { return correlationId;} 18 | public void setCorrelationId(String correlationId) { 19 | this.correlationId = correlationId; 20 | } 21 | 22 | public String getAuthToken() { 23 | return authToken; 24 | } 25 | 26 | public void setAuthToken(String authToken) { 27 | this.authToken = authToken; 28 | } 29 | 30 | public String getUserId() { 31 | return userId; 32 | } 33 | 34 | public void setUserId(String userId) { 35 | this.userId = userId; 36 | } 37 | 38 | public String getOrgId() { 39 | return orgId; 40 | } 41 | 42 | public void setOrgId(String orgId) { 43 | this.orgId = orgId; 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /licensing-service/src/main/java/com/thoughtmechanix/licenses/utils/UserContext.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.licenses.utils; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | @Component 6 | public class UserContext { 7 | public static final String CORRELATION_ID = "tmx-correlation-id"; 8 | public static final String AUTH_TOKEN = "tmx-auth-token"; 9 | public static final String USER_ID = "tmx-user-id"; 10 | public static final String ORG_ID = "tmx-org-id"; 11 | 12 | private String correlationId= new String(); 13 | private String authToken= new String(); 14 | private String userId = new String(); 15 | private String orgId = new String(); 16 | 17 | public String getCorrelationId() { return correlationId;} 18 | public void setCorrelationId(String correlationId) { 19 | this.correlationId = correlationId; 20 | } 21 | 22 | public String getAuthToken() { 23 | return authToken; 24 | } 25 | 26 | public void setAuthToken(String authToken) { 27 | this.authToken = authToken; 28 | } 29 | 30 | public String getUserId() { 31 | return userId; 32 | } 33 | 34 | public void setUserId(String userId) { 35 | this.userId = userId; 36 | } 37 | 38 | public String getOrgId() { 39 | return orgId; 40 | } 41 | 42 | public void setOrgId(String orgId) { 43 | this.orgId = orgId; 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /orgservice-new/src/main/java/com/thoughtmechanix/organization/utils/UserContext.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.organization.utils; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | @Component 6 | public class UserContext { 7 | public static final String CORRELATION_ID = "tmx-correlation-id"; 8 | public static final String AUTH_TOKEN = "tmx-auth-token"; 9 | public static final String USER_ID = "tmx-user-id"; 10 | public static final String ORG_ID = "tmx-org-id"; 11 | 12 | private String correlationId= new String(); 13 | private String authToken= new String(); 14 | private String userId = new String(); 15 | private String orgId = new String(); 16 | 17 | public String getCorrelationId() { return correlationId;} 18 | public void setCorrelationId(String correlationId) { 19 | this.correlationId = correlationId; 20 | } 21 | 22 | public String getAuthToken() { 23 | return authToken; 24 | } 25 | 26 | public void setAuthToken(String authToken) { 27 | this.authToken = authToken; 28 | } 29 | 30 | public String getUserId() { 31 | return userId; 32 | } 33 | 34 | public void setUserId(String userId) { 35 | this.userId = userId; 36 | } 37 | 38 | public String getOrgId() { 39 | return orgId; 40 | } 41 | 42 | public void setOrgId(String orgId) { 43 | this.orgId = orgId; 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /organization-service/src/main/java/com/thoughtmechanix/organization/utils/UserContext.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.organization.utils; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | @Component 6 | public class UserContext { 7 | public static final String CORRELATION_ID = "tmx-correlation-id"; 8 | public static final String AUTH_TOKEN = "tmx-auth-token"; 9 | public static final String USER_ID = "tmx-user-id"; 10 | public static final String ORG_ID = "tmx-org-id"; 11 | 12 | private String correlationId= new String(); 13 | private String authToken= new String(); 14 | private String userId = new String(); 15 | private String orgId = new String(); 16 | 17 | public String getCorrelationId() { return correlationId;} 18 | public void setCorrelationId(String correlationId) { 19 | this.correlationId = correlationId; 20 | } 21 | 22 | public String getAuthToken() { 23 | return authToken; 24 | } 25 | 26 | public void setAuthToken(String authToken) { 27 | this.authToken = authToken; 28 | } 29 | 30 | public String getUserId() { 31 | return userId; 32 | } 33 | 34 | public void setUserId(String userId) { 35 | this.userId = userId; 36 | } 37 | 38 | public String getOrgId() { 39 | return orgId; 40 | } 41 | 42 | public void setOrgId(String orgId) { 43 | this.orgId = orgId; 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /specialroutes-service/src/main/java/com/thoughtmechanix/specialroutes/utils/UserContext.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.specialroutes.utils; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | @Component 6 | public class UserContext { 7 | public static final String CORRELATION_ID = "tmx-correlation-id"; 8 | public static final String AUTH_TOKEN = "tmx-auth-token"; 9 | public static final String USER_ID = "tmx-user-id"; 10 | public static final String ORG_ID = "tmx-org-id"; 11 | 12 | private String correlationId= new String(); 13 | private String authToken= new String(); 14 | private String userId = new String(); 15 | private String orgId = new String(); 16 | 17 | public String getCorrelationId() { return correlationId;} 18 | public void setCorrelationId(String correlationId) { 19 | this.correlationId = correlationId; 20 | } 21 | 22 | public String getAuthToken() { 23 | return authToken; 24 | } 25 | 26 | public void setAuthToken(String authToken) { 27 | this.authToken = authToken; 28 | } 29 | 30 | public String getUserId() { 31 | return userId; 32 | } 33 | 34 | public void setUserId(String userId) { 35 | this.userId = userId; 36 | } 37 | 38 | public String getOrgId() { 39 | return orgId; 40 | } 41 | 42 | public void setOrgId(String orgId) { 43 | this.orgId = orgId; 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | com.thoughtmechanix 6 | 0.0.1-SNAPSHOT 7 | tmx-parent-pom 8 | pom 9 | 10 | 11 | thoughtmechanix-parent-pom 12 | Parent Pom for the thoughtmechanix project 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 1.4.4.RELEASE 18 | 19 | 20 | confsvr 21 | licensing-service 22 | organization-service 23 | orgservice-new 24 | eurekasvr 25 | specialroutes-service 26 | zuulsvr 27 | 28 | 29 | 30 | 31 | com.spotify 32 | docker-maven-plugin 33 | 0.4.10 34 | 35 | java 36 | example 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /specialroutes-service/src/main/java/com/thoughtmechanix/specialroutes/model/AbTestingRoute.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.specialroutes.model; 2 | 3 | 4 | import javax.persistence.Column; 5 | import javax.persistence.Entity; 6 | import javax.persistence.Id; 7 | import javax.persistence.Table; 8 | 9 | 10 | @Entity 11 | @Table(name = "abtesting") 12 | public class AbTestingRoute { 13 | @Id 14 | @Column(name = "service_name", nullable = false) 15 | String serviceName; 16 | 17 | @Column(name="active", nullable = false) 18 | String active; 19 | 20 | @Column(name = "endpoint", nullable = false) 21 | String endpoint; 22 | 23 | @Column(name = "weight", nullable = false) 24 | Integer weight; 25 | 26 | public String getActive() { 27 | return active; 28 | } 29 | 30 | public void setActive(String active) { 31 | this.active = active; 32 | } 33 | 34 | public String getServiceName() { 35 | return serviceName; 36 | } 37 | 38 | public void setServiceName(String serviceName) { 39 | this.serviceName = serviceName; 40 | } 41 | 42 | public String getEndpoint() { 43 | return endpoint; 44 | } 45 | 46 | public void setEndpoint(String endpoint) { 47 | this.endpoint = endpoint; 48 | } 49 | 50 | public Integer getWeight() { 51 | return weight; 52 | } 53 | 54 | public void setWeight(Integer weight) { 55 | this.weight = weight; 56 | } 57 | 58 | 59 | } -------------------------------------------------------------------------------- /licensing-service/src/main/java/com/thoughtmechanix/licenses/Application.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.licenses; 2 | 3 | import com.thoughtmechanix.licenses.utils.UserContextInterceptor; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; 7 | import org.springframework.cloud.client.loadbalancer.LoadBalanced; 8 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.web.client.RestTemplate; 11 | 12 | import java.util.Collections; 13 | import java.util.List; 14 | 15 | @SpringBootApplication 16 | @EnableEurekaClient 17 | @EnableCircuitBreaker 18 | public class Application { 19 | 20 | @LoadBalanced 21 | @Bean 22 | public RestTemplate getRestTemplate(){ 23 | RestTemplate template = new RestTemplate(); 24 | List interceptors = template.getInterceptors(); 25 | if (interceptors==null){ 26 | template.setInterceptors(Collections.singletonList(new UserContextInterceptor())); 27 | } 28 | else{ 29 | interceptors.add(new UserContextInterceptor()); 30 | template.setInterceptors(interceptors); 31 | } 32 | 33 | return template; 34 | } 35 | 36 | public static void main(String[] args) { 37 | SpringApplication.run(Application.class, args); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /zuulsvr/src/main/java/com/thoughtmechanix/zuulsvr/filters/ResponseFilter.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.zuulsvr.filters; 2 | 3 | 4 | import com.netflix.zuul.ZuulFilter; 5 | import com.netflix.zuul.context.RequestContext; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Component; 10 | 11 | @Component 12 | public class ResponseFilter extends ZuulFilter{ 13 | private static final int FILTER_ORDER=1; 14 | private static final boolean SHOULD_FILTER=true; 15 | private static final Logger logger = LoggerFactory.getLogger(ResponseFilter.class); 16 | 17 | @Autowired 18 | FilterUtils filterUtils; 19 | 20 | @Override 21 | public String filterType() { 22 | return FilterUtils.POST_FILTER_TYPE; 23 | } 24 | 25 | @Override 26 | public int filterOrder() { 27 | return FILTER_ORDER; 28 | } 29 | 30 | @Override 31 | public boolean shouldFilter() { 32 | return SHOULD_FILTER; 33 | } 34 | 35 | @Override 36 | public Object run() { 37 | RequestContext ctx = RequestContext.getCurrentContext(); 38 | 39 | logger.debug("Adding the correlation id to the outbound headers. {}", filterUtils.getCorrelationId()); 40 | ctx.getResponse().addHeader(FilterUtils.CORRELATION_ID, filterUtils.getCorrelationId()); 41 | 42 | logger.debug("Completing outgoing request for {}.", ctx.getRequest().getRequestURI()); 43 | 44 | return null; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /licensing-service/src/main/java/com/thoughtmechanix/licenses/clients/OrganizationRestTemplateClient.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.licenses.clients; 2 | 3 | import com.thoughtmechanix.licenses.model.Organization; 4 | import com.thoughtmechanix.licenses.utils.UserContext; 5 | import com.thoughtmechanix.licenses.utils.UserContextHolder; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.http.HttpEntity; 10 | import org.springframework.http.HttpHeaders; 11 | import org.springframework.http.HttpMethod; 12 | import org.springframework.http.ResponseEntity; 13 | import org.springframework.stereotype.Component; 14 | import org.springframework.web.client.RestTemplate; 15 | 16 | @Component 17 | public class OrganizationRestTemplateClient { 18 | @Autowired 19 | RestTemplate restTemplate; 20 | 21 | private static final Logger logger = LoggerFactory.getLogger(OrganizationRestTemplateClient.class); 22 | 23 | public Organization getOrganization(String organizationId){ 24 | logger.debug(">>> In Licensing Service.getOrganization: {}. Thread Id: {}", UserContextHolder.getContext().getCorrelationId(), Thread.currentThread().getId()); 25 | ResponseEntity restExchange = 26 | restTemplate.exchange( 27 | "http://zuulservice/api/organization/v1/organizations/{organizationId}", 28 | HttpMethod.GET, 29 | null, Organization.class, organizationId); 30 | return restExchange.getBody(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /orgservice-new/src/main/docker/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | echo "********************************************************" 3 | echo "Waiting for the eureka server to start on port $EUREKASERVER_PORT" 4 | echo "********************************************************" 5 | while ! `nc -z eurekaserver $EUREKASERVER_PORT`; do sleep 3; done 6 | echo "******* Eureka Server has started" 7 | 8 | 9 | echo "********************************************************" 10 | echo "Waiting for the database server to start on port $DATABASESERVER_PORT" 11 | echo "********************************************************" 12 | while ! `nc -z database $DATABASESERVER_PORT`; do sleep 3; done 13 | echo "******** Database Server has started " 14 | 15 | echo "********************************************************" 16 | echo "Waiting for the configuration server to start on port $CONFIGSERVER_PORT" 17 | echo "********************************************************" 18 | while ! `nc -z configserver $CONFIGSERVER_PORT`; do sleep 3; done 19 | echo "******* Configuration Server has started" 20 | 21 | echo "********************************************************" 22 | echo "Starting New Organization Service " 23 | echo "********************************************************" 24 | java -Djava.security.egd=file:/dev/./urandom -Dserver.port=$SERVER_PORT \ 25 | -Deureka.client.serviceUrl.defaultZone=$EUREKASERVER_URI \ 26 | -Dspring.cloud.config.uri=$CONFIGSERVER_URI \ 27 | -Dspring.profiles.active=$PROFILE \ 28 | -jar /usr/local/organizationservice-new/@project.build.finalName@.jar 29 | -------------------------------------------------------------------------------- /organization-service/src/main/docker/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "********************************************************" 4 | echo "Waiting for the eureka server to start on port $EUREKASERVER_PORT" 5 | echo "********************************************************" 6 | while ! `nc -z eurekaserver $EUREKASERVER_PORT`; do sleep 3; done 7 | echo "******* Eureka Server has started" 8 | 9 | 10 | echo "********************************************************" 11 | echo "Waiting for the database server to start on port $DATABASESERVER_PORT" 12 | echo "********************************************************" 13 | while ! `nc -z database $DATABASESERVER_PORT`; do sleep 3; done 14 | echo "******** Database Server has started " 15 | 16 | echo "********************************************************" 17 | echo "Waiting for the configuration server to start on port $CONFIGSERVER_PORT" 18 | echo "********************************************************" 19 | while ! `nc -z configserver $CONFIGSERVER_PORT`; do sleep 3; done 20 | echo "******* Configuration Server has started" 21 | 22 | echo "********************************************************" 23 | echo "Starting Organization Service " 24 | echo "********************************************************" 25 | java -Djava.security.egd=file:/dev/./urandom -Dserver.port=$SERVER_PORT \ 26 | -Deureka.client.serviceUrl.defaultZone=$EUREKASERVER_URI \ 27 | -Dspring.cloud.config.uri=$CONFIGSERVER_URI \ 28 | -Dspring.profiles.active=$PROFILE \ 29 | -jar /usr/local/organizationservice/@project.build.finalName@.jar 30 | -------------------------------------------------------------------------------- /specialroutes-service/src/main/docker/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "********************************************************" 4 | echo "Waiting for the eureka server to start on port $EUREKASERVER_PORT" 5 | echo "********************************************************" 6 | while ! `nc -z eurekaserver $EUREKASERVER_PORT`; do sleep 3; done 7 | echo "******* Eureka Server has started" 8 | 9 | 10 | echo "********************************************************" 11 | echo "Waiting for the database server to start on port $DATABASESERVER_PORT" 12 | echo "********************************************************" 13 | while ! `nc -z database $DATABASESERVER_PORT`; do sleep 3; done 14 | echo "******** Database Server has started " 15 | 16 | echo "********************************************************" 17 | echo "Waiting for the configuration server to start on port $CONFIGSERVER_PORT" 18 | echo "********************************************************" 19 | while ! `nc -z configserver $CONFIGSERVER_PORT`; do sleep 3; done 20 | echo "******* Configuration Server has started" 21 | echo "********************************************************" 22 | echo "Starting Special Routes Service " 23 | echo "********************************************************" 24 | java -Djava.security.egd=file:/dev/./urandom -Dserver.port=$SERVER_PORT \ 25 | -Deureka.client.serviceUrl.defaultZone=$EUREKASERVER_URI \ 26 | -Dspring.cloud.config.uri=$CONFIGSERVER_URI \ 27 | -Dspring.profiles.active=$PROFILE \ 28 | -jar /usr/local/specialroutes-service/@project.build.finalName@.jar 29 | -------------------------------------------------------------------------------- /licensing-service/src/main/docker/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "********************************************************" 4 | echo "Waiting for the eureka server to start on port $EUREKASERVER_PORT" 5 | echo "********************************************************" 6 | while ! `nc -z eurekaserver $EUREKASERVER_PORT`; do sleep 3; done 7 | echo "******* Eureka Server has started" 8 | 9 | 10 | echo "********************************************************" 11 | echo "Waiting for the database server to start on port $DATABASESERVER_PORT)" 12 | echo "********************************************************" 13 | while ! `nc -z database $DATABASESERVER_PORT`; do sleep 3; done 14 | echo "******** Database Server has started " 15 | 16 | echo "********************************************************" 17 | echo "Waiting for the configuration server to start on port $CONFIGSERVER_PORT" 18 | echo "********************************************************" 19 | while ! `nc -z configserver $CONFIGSERVER_PORT`; do sleep 3; done 20 | echo "******* Configuration Server has started" 21 | 22 | 23 | echo "********************************************************" 24 | echo "Starting License Server with Configuration Service via Eureka : $EUREKASERVER_URI" ON PORT: $SERVER_PORT; 25 | echo "********************************************************" 26 | java -Djava.security.egd=file:/dev/./urandom -Dserver.port=$SERVER_PORT \ 27 | -Deureka.client.serviceUrl.defaultZone=$EUREKASERVER_URI \ 28 | -Dspring.cloud.config.uri=$CONFIGSERVER_URI \ 29 | -Dspring.profiles.active=$PROFILE -jar /usr/local/licensingservice/@project.build.finalName@.jar 30 | -------------------------------------------------------------------------------- /orgservice-new/src/main/java/com/thoughtmechanix/organization/model/Organization.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.organization.model; 2 | 3 | import javax.persistence.Column; 4 | import javax.persistence.Entity; 5 | import javax.persistence.Id; 6 | import javax.persistence.Table; 7 | 8 | @Entity 9 | @Table(name = "organizations") 10 | public class Organization { 11 | @Id 12 | @Column(name = "organization_id", nullable = false) 13 | String id; 14 | 15 | @Column(name = "name", nullable = false) 16 | String name; 17 | 18 | @Column(name = "contact_name", nullable = false) 19 | String contactName; 20 | 21 | @Column(name = "contact_email", nullable = false) 22 | String contactEmail; 23 | 24 | @Column(name = "contact_phone", nullable = false) 25 | String contactPhone; 26 | 27 | 28 | public String getId() { 29 | return id; 30 | } 31 | 32 | 33 | public void setId(String id) { 34 | this.id = id; 35 | } 36 | 37 | public String getName() { 38 | return name; 39 | } 40 | 41 | public void setName(String name) { 42 | this.name = name; 43 | } 44 | 45 | public String getContactName() { 46 | return contactName; 47 | } 48 | 49 | public void setContactName(String contactName) { 50 | this.contactName = contactName; 51 | } 52 | 53 | public String getContactEmail() { 54 | return contactEmail; 55 | } 56 | 57 | public void setContactEmail(String contactEmail) { 58 | this.contactEmail = contactEmail; 59 | } 60 | 61 | public String getContactPhone() { 62 | return contactPhone; 63 | } 64 | 65 | public void setContactPhone(String contactPhone) { 66 | this.contactPhone = contactPhone; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /organization-service/src/main/java/com/thoughtmechanix/organization/model/Organization.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.organization.model; 2 | 3 | import javax.persistence.Column; 4 | import javax.persistence.Entity; 5 | import javax.persistence.Id; 6 | import javax.persistence.Table; 7 | 8 | @Entity 9 | @Table(name = "organizations") 10 | public class Organization { 11 | @Id 12 | @Column(name = "organization_id", nullable = false) 13 | String id; 14 | 15 | @Column(name = "name", nullable = false) 16 | String name; 17 | 18 | @Column(name = "contact_name", nullable = false) 19 | String contactName; 20 | 21 | @Column(name = "contact_email", nullable = false) 22 | String contactEmail; 23 | 24 | @Column(name = "contact_phone", nullable = false) 25 | String contactPhone; 26 | 27 | 28 | public String getId() { 29 | return id; 30 | } 31 | 32 | 33 | public void setId(String id) { 34 | this.id = id; 35 | } 36 | 37 | public String getName() { 38 | return name; 39 | } 40 | 41 | public void setName(String name) { 42 | this.name = name; 43 | } 44 | 45 | public String getContactName() { 46 | return contactName; 47 | } 48 | 49 | public void setContactName(String contactName) { 50 | this.contactName = contactName; 51 | } 52 | 53 | public String getContactEmail() { 54 | return contactEmail; 55 | } 56 | 57 | public void setContactEmail(String contactEmail) { 58 | this.contactEmail = contactEmail; 59 | } 60 | 61 | public String getContactPhone() { 62 | return contactPhone; 63 | } 64 | 65 | public void setContactPhone(String contactPhone) { 66 | this.contactPhone = contactPhone; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /zuulsvr/src/main/java/com/thoughtmechanix/zuulsvr/utils/UserContextFilter.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.zuulsvr.utils; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.stereotype.Component; 6 | 7 | import javax.servlet.Filter; 8 | import javax.servlet.FilterChain; 9 | import javax.servlet.FilterConfig; 10 | import javax.servlet.ServletException; 11 | import javax.servlet.ServletRequest; 12 | import javax.servlet.ServletResponse; 13 | import javax.servlet.http.HttpServletRequest; 14 | import java.io.IOException; 15 | 16 | @Component 17 | public class UserContextFilter implements Filter { 18 | private static final Logger logger = LoggerFactory.getLogger(UserContextFilter.class); 19 | 20 | @Override 21 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) 22 | throws IOException, ServletException { 23 | HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; 24 | 25 | UserContextHolder.getContext().setCorrelationId( httpServletRequest.getHeader(UserContext.CORRELATION_ID) ); 26 | UserContextHolder.getContext().setUserId(httpServletRequest.getHeader(UserContext.USER_ID)); 27 | UserContextHolder.getContext().setAuthToken(httpServletRequest.getHeader(UserContext.AUTH_TOKEN)); 28 | UserContextHolder.getContext().setOrgId(httpServletRequest.getHeader(UserContext.ORG_ID)); 29 | 30 | logger.debug("Special Routes Service Incoming Correlation id: {}", UserContextHolder.getContext().getCorrelationId()); 31 | 32 | filterChain.doFilter(httpServletRequest, servletResponse); 33 | } 34 | 35 | @Override 36 | public void init(FilterConfig filterConfig) throws ServletException {} 37 | 38 | @Override 39 | public void destroy() {} 40 | } 41 | -------------------------------------------------------------------------------- /licensing-service/src/main/java/com/thoughtmechanix/licenses/utils/UserContextFilter.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.licenses.utils; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.stereotype.Component; 6 | 7 | import javax.servlet.Filter; 8 | import javax.servlet.FilterChain; 9 | import javax.servlet.FilterConfig; 10 | import javax.servlet.ServletException; 11 | import javax.servlet.ServletRequest; 12 | import javax.servlet.ServletResponse; 13 | import javax.servlet.http.HttpServletRequest; 14 | import java.io.IOException; 15 | 16 | @Component 17 | public class UserContextFilter implements Filter { 18 | private static final Logger logger = LoggerFactory.getLogger(UserContextFilter.class); 19 | 20 | @Override 21 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) 22 | throws IOException, ServletException { 23 | 24 | 25 | HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; 26 | 27 | UserContextHolder.getContext().setCorrelationId( httpServletRequest.getHeader(UserContext.CORRELATION_ID) ); 28 | UserContextHolder.getContext().setUserId(httpServletRequest.getHeader(UserContext.USER_ID)); 29 | UserContextHolder.getContext().setAuthToken(httpServletRequest.getHeader(UserContext.AUTH_TOKEN)); 30 | UserContextHolder.getContext().setOrgId(httpServletRequest.getHeader(UserContext.ORG_ID)); 31 | 32 | logger.debug("License Service Incoming Correlation id: {}", UserContextHolder.getContext().getCorrelationId()); 33 | 34 | filterChain.doFilter(httpServletRequest, servletResponse); 35 | } 36 | 37 | @Override 38 | public void init(FilterConfig filterConfig) throws ServletException {} 39 | 40 | @Override 41 | public void destroy() {} 42 | } -------------------------------------------------------------------------------- /organization-service/src/main/java/com/thoughtmechanix/organization/utils/UserContextFilter.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.organization.utils; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.stereotype.Component; 6 | 7 | import javax.servlet.Filter; 8 | import javax.servlet.FilterChain; 9 | import javax.servlet.FilterConfig; 10 | import javax.servlet.ServletException; 11 | import javax.servlet.ServletRequest; 12 | import javax.servlet.ServletResponse; 13 | import javax.servlet.http.HttpServletRequest; 14 | import java.io.IOException; 15 | 16 | @Component 17 | public class UserContextFilter implements Filter { 18 | private static final Logger logger = LoggerFactory.getLogger(UserContextFilter.class); 19 | 20 | @Override 21 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) 22 | throws IOException, ServletException { 23 | 24 | 25 | HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; 26 | 27 | UserContextHolder.getContext().setCorrelationId( httpServletRequest.getHeader(UserContext.CORRELATION_ID) ); 28 | UserContextHolder.getContext().setUserId( httpServletRequest.getHeader(UserContext.USER_ID) ); 29 | UserContextHolder.getContext().setAuthToken( httpServletRequest.getHeader(UserContext.AUTH_TOKEN) ); 30 | UserContextHolder.getContext().setOrgId( httpServletRequest.getHeader(UserContext.ORG_ID) ); 31 | 32 | logger.debug("Organization Service Incoming Correlation id: {}" ,UserContextHolder.getContext().getCorrelationId()); 33 | filterChain.doFilter(httpServletRequest, servletResponse); 34 | } 35 | 36 | @Override 37 | public void init(FilterConfig filterConfig) throws ServletException {} 38 | 39 | @Override 40 | public void destroy() {} 41 | } -------------------------------------------------------------------------------- /orgservice-new/src/main/java/com/thoughtmechanix/organization/utils/UserContextFilter.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.organization.utils; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.stereotype.Component; 6 | 7 | import javax.servlet.Filter; 8 | import javax.servlet.FilterChain; 9 | import javax.servlet.FilterConfig; 10 | import javax.servlet.ServletException; 11 | import javax.servlet.ServletRequest; 12 | import javax.servlet.ServletResponse; 13 | import javax.servlet.http.HttpServletRequest; 14 | import java.io.IOException; 15 | 16 | @Component 17 | public class UserContextFilter implements Filter { 18 | private static final Logger logger = LoggerFactory.getLogger(UserContextFilter.class); 19 | 20 | @Override 21 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) 22 | throws IOException, ServletException { 23 | 24 | 25 | HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; 26 | 27 | UserContextHolder.getContext().setCorrelationId( httpServletRequest.getHeader(UserContext.CORRELATION_ID) ); 28 | UserContextHolder.getContext().setUserId(httpServletRequest.getHeader(UserContext.USER_ID)); 29 | UserContextHolder.getContext().setAuthToken(httpServletRequest.getHeader(UserContext.AUTH_TOKEN)); 30 | UserContextHolder.getContext().setOrgId(httpServletRequest.getHeader(UserContext.ORG_ID)); 31 | 32 | logger.debug("Organization Service (NEW) Incoming Correlation id: {}", UserContextHolder.getContext().getCorrelationId()); 33 | 34 | filterChain.doFilter(httpServletRequest, servletResponse); 35 | } 36 | 37 | @Override 38 | public void init(FilterConfig filterConfig) throws ServletException {} 39 | 40 | @Override 41 | public void destroy() {} 42 | } -------------------------------------------------------------------------------- /specialroutes-service/src/main/java/com/thoughtmechanix/specialroutes/utils/UserContextFilter.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.specialroutes.utils; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.stereotype.Component; 6 | 7 | import javax.servlet.Filter; 8 | import javax.servlet.FilterChain; 9 | import javax.servlet.FilterConfig; 10 | import javax.servlet.ServletException; 11 | import javax.servlet.ServletRequest; 12 | import javax.servlet.ServletResponse; 13 | import javax.servlet.http.HttpServletRequest; 14 | import java.io.IOException; 15 | 16 | @Component 17 | public class UserContextFilter implements Filter { 18 | private static final Logger logger = LoggerFactory.getLogger(UserContextFilter.class); 19 | 20 | @Override 21 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) 22 | throws IOException, ServletException { 23 | 24 | 25 | HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; 26 | 27 | UserContextHolder.getContext().setCorrelationId( httpServletRequest.getHeader(UserContext.CORRELATION_ID) ); 28 | UserContextHolder.getContext().setUserId(httpServletRequest.getHeader(UserContext.USER_ID)); 29 | UserContextHolder.getContext().setAuthToken(httpServletRequest.getHeader(UserContext.AUTH_TOKEN)); 30 | UserContextHolder.getContext().setOrgId(httpServletRequest.getHeader(UserContext.ORG_ID)); 31 | 32 | logger.debug("Special Routes Service Incoming Correlation id: {}", UserContextHolder.getContext().getCorrelationId()); 33 | 34 | filterChain.doFilter(httpServletRequest, servletResponse); 35 | } 36 | 37 | @Override 38 | public void init(FilterConfig filterConfig) throws ServletException {} 39 | 40 | @Override 41 | public void destroy() {} 42 | } -------------------------------------------------------------------------------- /specialroutes-service/src/main/java/com/thoughtmechanix/specialroutes/hystrix/DelegatingUserContextCallable.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.specialroutes.hystrix; 2 | 3 | 4 | import com.thoughtmechanix.specialroutes.utils.UserContext; 5 | import com.thoughtmechanix.specialroutes.utils.UserContextHolder; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.util.Assert; 9 | 10 | import java.util.concurrent.Callable; 11 | 12 | 13 | public final class DelegatingUserContextCallable implements Callable { 14 | private static final Logger logger = LoggerFactory.getLogger(DelegatingUserContextCallable.class); 15 | private final Callable delegate; 16 | 17 | private UserContext originalUserContext; 18 | 19 | public DelegatingUserContextCallable(Callable delegate, 20 | UserContext userContext) { 21 | Assert.notNull(delegate, "delegate cannot be null"); 22 | Assert.notNull(userContext, "userContext cannot be null"); 23 | this.delegate = delegate; 24 | this.originalUserContext = userContext; 25 | } 26 | 27 | public DelegatingUserContextCallable(Callable delegate) { 28 | this(delegate, UserContextHolder.getContext()); 29 | } 30 | 31 | public V call() throws Exception { 32 | UserContextHolder.setContext( originalUserContext ); 33 | 34 | try { 35 | return delegate.call(); 36 | } 37 | finally { 38 | 39 | this.originalUserContext = null; 40 | } 41 | } 42 | 43 | public String toString() { 44 | return delegate.toString(); 45 | } 46 | 47 | 48 | public static Callable create(Callable delegate, 49 | UserContext userContext) { 50 | return new DelegatingUserContextCallable(delegate, userContext); 51 | } 52 | } -------------------------------------------------------------------------------- /licensing-service/src/main/java/com/thoughtmechanix/licenses/hystrix/DelegatingUserContextCallable.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.licenses.hystrix; 2 | 3 | import com.thoughtmechanix.licenses.utils.UserContext; 4 | import com.thoughtmechanix.licenses.utils.UserContextHolder; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.util.Assert; 8 | 9 | import java.util.concurrent.Callable; 10 | 11 | 12 | public final class DelegatingUserContextCallable implements Callable { 13 | private static final Logger logger = LoggerFactory.getLogger(DelegatingUserContextCallable.class); 14 | private final Callable delegate; 15 | 16 | 17 | 18 | //private final UserContext delegateUserContext; 19 | private UserContext originalUserContext; 20 | 21 | public DelegatingUserContextCallable(Callable delegate, 22 | UserContext userContext) { 23 | Assert.notNull(delegate, "delegate cannot be null"); 24 | Assert.notNull(userContext, "userContext cannot be null"); 25 | this.delegate = delegate; 26 | this.originalUserContext = userContext; 27 | } 28 | 29 | public DelegatingUserContextCallable(Callable delegate) { 30 | this(delegate, UserContextHolder.getContext()); 31 | } 32 | 33 | public V call() throws Exception { 34 | UserContextHolder.setContext( originalUserContext ); 35 | 36 | try { 37 | return delegate.call(); 38 | } 39 | finally { 40 | 41 | this.originalUserContext = null; 42 | } 43 | } 44 | 45 | public String toString() { 46 | return delegate.toString(); 47 | } 48 | 49 | 50 | public static Callable create(Callable delegate, 51 | UserContext userContext) { 52 | return new DelegatingUserContextCallable(delegate, userContext); 53 | } 54 | } -------------------------------------------------------------------------------- /orgservice-new/src/main/java/com/thoughtmechanix/organization/hystrix/DelegatingUserContextCallable.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.organization.hystrix; 2 | 3 | import com.thoughtmechanix.organization.utils.UserContext; 4 | import com.thoughtmechanix.organization.utils.UserContextHolder; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.util.Assert; 8 | 9 | import java.util.concurrent.Callable; 10 | 11 | 12 | public final class DelegatingUserContextCallable implements Callable { 13 | private static final Logger logger = LoggerFactory.getLogger(DelegatingUserContextCallable.class); 14 | private final Callable delegate; 15 | 16 | 17 | 18 | //private final UserContext delegateUserContext; 19 | private UserContext originalUserContext; 20 | 21 | public DelegatingUserContextCallable(Callable delegate, 22 | UserContext userContext) { 23 | Assert.notNull(delegate, "delegate cannot be null"); 24 | Assert.notNull(userContext, "userContext cannot be null"); 25 | this.delegate = delegate; 26 | this.originalUserContext = userContext; 27 | } 28 | 29 | public DelegatingUserContextCallable(Callable delegate) { 30 | this(delegate, UserContextHolder.getContext()); 31 | } 32 | 33 | public V call() throws Exception { 34 | UserContextHolder.setContext( originalUserContext ); 35 | 36 | try { 37 | return delegate.call(); 38 | } 39 | finally { 40 | 41 | this.originalUserContext = null; 42 | } 43 | } 44 | 45 | public String toString() { 46 | return delegate.toString(); 47 | } 48 | 49 | 50 | public static Callable create(Callable delegate, 51 | UserContext userContext) { 52 | return new DelegatingUserContextCallable(delegate, userContext); 53 | } 54 | } -------------------------------------------------------------------------------- /organization-service/src/main/java/com/thoughtmechanix/organization/hystrix/DelegatingUserContextCallable.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.organization.hystrix; 2 | 3 | import com.thoughtmechanix.organization.utils.UserContext; 4 | import com.thoughtmechanix.organization.utils.UserContextHolder; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.util.Assert; 8 | 9 | import java.util.concurrent.Callable; 10 | 11 | 12 | public final class DelegatingUserContextCallable implements Callable { 13 | private static final Logger logger = LoggerFactory.getLogger(DelegatingUserContextCallable.class); 14 | private final Callable delegate; 15 | 16 | 17 | 18 | //private final UserContext delegateUserContext; 19 | private UserContext originalUserContext; 20 | 21 | public DelegatingUserContextCallable(Callable delegate, 22 | UserContext userContext) { 23 | Assert.notNull(delegate, "delegate cannot be null"); 24 | Assert.notNull(userContext, "userContext cannot be null"); 25 | this.delegate = delegate; 26 | this.originalUserContext = userContext; 27 | } 28 | 29 | public DelegatingUserContextCallable(Callable delegate) { 30 | this(delegate, UserContextHolder.getContext()); 31 | } 32 | 33 | public V call() throws Exception { 34 | UserContextHolder.setContext( originalUserContext ); 35 | 36 | try { 37 | return delegate.call(); 38 | } 39 | finally { 40 | 41 | this.originalUserContext = null; 42 | } 43 | } 44 | 45 | public String toString() { 46 | return delegate.toString(); 47 | } 48 | 49 | 50 | public static Callable create(Callable delegate, 51 | UserContext userContext) { 52 | return new DelegatingUserContextCallable(delegate, userContext); 53 | } 54 | } -------------------------------------------------------------------------------- /zuulsvr/src/main/java/com/thoughtmechanix/zuulsvr/filters/TrackingFilter.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.zuulsvr.filters; 2 | 3 | import com.netflix.zuul.ZuulFilter; 4 | import com.netflix.zuul.context.RequestContext; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Component; 9 | 10 | @Component 11 | public class TrackingFilter extends ZuulFilter{ 12 | private static final int FILTER_ORDER = 1; 13 | private static final boolean SHOULD_FILTER=true; 14 | private static final Logger logger = LoggerFactory.getLogger(TrackingFilter.class); 15 | 16 | @Autowired 17 | FilterUtils filterUtils; 18 | 19 | @Override 20 | public String filterType() { 21 | return FilterUtils.PRE_FILTER_TYPE; 22 | } 23 | 24 | @Override 25 | public int filterOrder() { 26 | return FILTER_ORDER; 27 | } 28 | 29 | public boolean shouldFilter() { 30 | return SHOULD_FILTER; 31 | } 32 | 33 | private boolean isCorrelationIdPresent(){ 34 | if (filterUtils.getCorrelationId() !=null){ 35 | return true; 36 | } 37 | 38 | return false; 39 | } 40 | 41 | private String generateCorrelationId(){ 42 | return java.util.UUID.randomUUID().toString(); 43 | } 44 | 45 | public Object run() { 46 | 47 | if (isCorrelationIdPresent()) { 48 | logger.debug("tmx-correlation-id found in tracking filter: {}. ", filterUtils.getCorrelationId()); 49 | } 50 | else{ 51 | filterUtils.setCorrelationId(generateCorrelationId()); 52 | logger.debug("tmx-correlation-id generated in tracking filter: {}.", filterUtils.getCorrelationId()); 53 | } 54 | 55 | RequestContext ctx = RequestContext.getCurrentContext(); 56 | logger.debug("Processing incoming request for {}.", ctx.getRequest().getRequestURI()); 57 | return null; 58 | } 59 | } -------------------------------------------------------------------------------- /licensing-service/src/main/java/com/thoughtmechanix/licenses/hystrix/ThreadLocalConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.licenses.hystrix; 2 | 3 | import com.netflix.hystrix.strategy.HystrixPlugins; 4 | import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy; 5 | import com.netflix.hystrix.strategy.eventnotifier.HystrixEventNotifier; 6 | import com.netflix.hystrix.strategy.executionhook.HystrixCommandExecutionHook; 7 | import com.netflix.hystrix.strategy.metrics.HystrixMetricsPublisher; 8 | import com.netflix.hystrix.strategy.properties.HystrixPropertiesStrategy; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.context.annotation.Configuration; 11 | 12 | import javax.annotation.PostConstruct; 13 | 14 | @Configuration 15 | public class ThreadLocalConfiguration { 16 | @Autowired(required = false) 17 | private HystrixConcurrencyStrategy existingConcurrencyStrategy; 18 | 19 | @PostConstruct 20 | public void init() { 21 | // Keeps references of existing Hystrix plugins. 22 | HystrixEventNotifier eventNotifier = HystrixPlugins.getInstance() 23 | .getEventNotifier(); 24 | HystrixMetricsPublisher metricsPublisher = HystrixPlugins.getInstance() 25 | .getMetricsPublisher(); 26 | HystrixPropertiesStrategy propertiesStrategy = HystrixPlugins.getInstance() 27 | .getPropertiesStrategy(); 28 | HystrixCommandExecutionHook commandExecutionHook = HystrixPlugins.getInstance() 29 | .getCommandExecutionHook(); 30 | 31 | HystrixPlugins.reset(); 32 | 33 | HystrixPlugins.getInstance().registerConcurrencyStrategy(new ThreadLocalAwareStrategy(existingConcurrencyStrategy)); 34 | HystrixPlugins.getInstance().registerEventNotifier(eventNotifier); 35 | HystrixPlugins.getInstance().registerMetricsPublisher(metricsPublisher); 36 | HystrixPlugins.getInstance().registerPropertiesStrategy(propertiesStrategy); 37 | HystrixPlugins.getInstance().registerCommandExecutionHook(commandExecutionHook); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | cache: 3 | directories: 4 | - $HOME/.m2 5 | jdk: 6 | - oraclejdk8 7 | sudo: required 8 | services: 9 | - docker 10 | notifications: 11 | slack: teamcarnell:zhTADgjsb7yJ5RPEd7LPNFwI 12 | email: 13 | - carnell28@gmail.com 14 | on_success: always 15 | on_failure: always 16 | env: 17 | global: 18 | - secure: tNcrHZo8APi0tTjjbwd0l6XTOE5Hvb/sNX34OEpgu+LAZt/75lO6ZMzav0f+7bwXAe3t0DN2nPcfP1v/mq1hW2yACm0z7Ndkisemxg1HtNg1SWljY5t5vLSB/ReTPFMqheuX/qk5PiLOGpdNqzx6c7Ux8euIuXKZinf2jR3PZCyisq6iS77EArGt8Ux5Mx/8SeqVrst83xgrCTy5rtr9LwKoAhJiaHnkCfPdL9SBubIDLd/raG8QyjqGc36kTk2+a9mTpZwmLjT+ZeYKB8K+WD8trhf1PZ2slPgFgeGKaRGtC4Gh5V/O5UXT2kh11Pk4btnnY3+UIZpXiNFxDNXpa7N0sx3SlNI60wGYinRyauvXF2WZMQqbAEmFbDX/dtrdav/UNBXYkLHI26EajzHjwanEC7dGzUnyc8TDHXtHLxsFLirz3SrkwAuZ4zoF2S25Me3/OPQxPjQzFMNPwvygXH8mjEuQusdkiKIcSz6mHJLWcDTFMAOJ42pelgBf6LC3vdZFgCRzUJNTyjTKSkUKQjzC08OTaHaiQJ83V9xW0e66X942ZRRbumqprmLN7VvQDYZsEqbz62iA40asrtzDsk5guFRQULLbct1lu00nggj0OGlLhaWF7lNoRIDGO4G2Vumm4gWZLLkL/ocLkO0iL3YwgJI3sMFwJj+wfrQnJeM= 19 | - secure: sJ739GpPg3CQHV2OnFaSnzncXJjMwbK1kPLrYZYcYWWvYlDuSXnTAJdu+QGhPcth2mkXPN9326edAgc3sbV7qKyZz7atiFLhKOZ0n4AwcgC1POKkgBJ8qPSIzkg29WpzbCDHy4JjUg7AZgHNnX1iIN0mYlIuu//hdLcZu1Q/Vjs3FNi8eQICI38C/99FqYWMQIEOwl2gY0fbfcsjczL8YLkKAsOaKewYUCAImSXG0/99oE7H3qgJ5DLv+Hq6rWZ7cT3oSrcYlCaPEcmf3/2ij93m7J08Gu9h0Hs5Rtmtau+Tuf1oPBe6fgkIwHkyaVoSD57TJo/L5SONZF0d4OGo+LIXicfUN0xkv38ltF+Do2/1dRbGt/awXirjN/WCS4QnK/pxiSfxjIuMO6rwYt4uBiiyqNDHwKY+8yv8Kr9SxgLpofIEKiINinrc4Jf/I9UFZlux+qRFLFvD1+wnFslwVf036NgZmiiLzNAthvqRkS09h4g+lAvnLi8/VIEl2MZhyWz5z4Atz6uz2EIA8XGdXmmBEq9q3slyf6hiZ5oNnOxy24qZgZbiw2Brjzkijb0nPOzmtcG/epXitceaK2BosRbA5HAuBkN6wXyVUwk/e9pbIIlxXVe+AjK5KQQXSFLK3aU27G4fta5YjbruElHN17hATSfD3vf2/PREHW2QkDA= 20 | script: 21 | - docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD 22 | - mvn clean package docker:build 23 | - docker push johncarnell/tmx-licensing-service:chapter6 24 | - docker push johncarnell/tmx-organization-service:chapter6 25 | - docker push johncarnell/tmx-orgservice-new:chapter6 26 | - docker push johncarnell/tmx-confsvr:chapter6 27 | - docker push johncarnell/tmx-eurekasvr:chapter6 28 | - docker push johncarnell/tmx-zuulsvr:chapter6 29 | - docker push johncarnell/tmx-specialroutes-service:chapter6 30 | -------------------------------------------------------------------------------- /orgservice-new/src/main/java/com/thoughtmechanix/organization/hystrix/ThreadLocalConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.organization.hystrix; 2 | 3 | import com.netflix.hystrix.strategy.HystrixPlugins; 4 | import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy; 5 | import com.netflix.hystrix.strategy.eventnotifier.HystrixEventNotifier; 6 | import com.netflix.hystrix.strategy.executionhook.HystrixCommandExecutionHook; 7 | import com.netflix.hystrix.strategy.metrics.HystrixMetricsPublisher; 8 | import com.netflix.hystrix.strategy.properties.HystrixPropertiesStrategy; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.context.annotation.Configuration; 11 | 12 | import javax.annotation.PostConstruct; 13 | 14 | @Configuration 15 | public class ThreadLocalConfiguration { 16 | @Autowired(required = false) 17 | private HystrixConcurrencyStrategy existingConcurrencyStrategy; 18 | 19 | @PostConstruct 20 | public void init() { 21 | // Keeps references of existing Hystrix plugins. 22 | HystrixEventNotifier eventNotifier = HystrixPlugins.getInstance() 23 | .getEventNotifier(); 24 | HystrixMetricsPublisher metricsPublisher = HystrixPlugins.getInstance() 25 | .getMetricsPublisher(); 26 | HystrixPropertiesStrategy propertiesStrategy = HystrixPlugins.getInstance() 27 | .getPropertiesStrategy(); 28 | HystrixCommandExecutionHook commandExecutionHook = HystrixPlugins.getInstance() 29 | .getCommandExecutionHook(); 30 | 31 | HystrixPlugins.reset(); 32 | 33 | // Registers existing plugins excepts the Concurrent Strategy plugin. 34 | HystrixPlugins.getInstance().registerConcurrencyStrategy(new ThreadLocalAwareStrategy(existingConcurrencyStrategy)); 35 | HystrixPlugins.getInstance().registerEventNotifier(eventNotifier); 36 | HystrixPlugins.getInstance().registerMetricsPublisher(metricsPublisher); 37 | HystrixPlugins.getInstance().registerPropertiesStrategy(propertiesStrategy); 38 | HystrixPlugins.getInstance().registerCommandExecutionHook(commandExecutionHook); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /organization-service/src/main/java/com/thoughtmechanix/organization/hystrix/ThreadLocalConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.organization.hystrix; 2 | 3 | import com.netflix.hystrix.strategy.HystrixPlugins; 4 | import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy; 5 | import com.netflix.hystrix.strategy.eventnotifier.HystrixEventNotifier; 6 | import com.netflix.hystrix.strategy.executionhook.HystrixCommandExecutionHook; 7 | import com.netflix.hystrix.strategy.metrics.HystrixMetricsPublisher; 8 | import com.netflix.hystrix.strategy.properties.HystrixPropertiesStrategy; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.context.annotation.Configuration; 11 | 12 | import javax.annotation.PostConstruct; 13 | 14 | @Configuration 15 | public class ThreadLocalConfiguration { 16 | @Autowired(required = false) 17 | private HystrixConcurrencyStrategy existingConcurrencyStrategy; 18 | 19 | @PostConstruct 20 | public void init() { 21 | // Keeps references of existing Hystrix plugins. 22 | HystrixEventNotifier eventNotifier = HystrixPlugins.getInstance() 23 | .getEventNotifier(); 24 | HystrixMetricsPublisher metricsPublisher = HystrixPlugins.getInstance() 25 | .getMetricsPublisher(); 26 | HystrixPropertiesStrategy propertiesStrategy = HystrixPlugins.getInstance() 27 | .getPropertiesStrategy(); 28 | HystrixCommandExecutionHook commandExecutionHook = HystrixPlugins.getInstance() 29 | .getCommandExecutionHook(); 30 | 31 | HystrixPlugins.reset(); 32 | 33 | // Registers existing plugins excepts the Concurrent Strategy plugin. 34 | HystrixPlugins.getInstance().registerConcurrencyStrategy(new ThreadLocalAwareStrategy(existingConcurrencyStrategy)); 35 | HystrixPlugins.getInstance().registerEventNotifier(eventNotifier); 36 | HystrixPlugins.getInstance().registerMetricsPublisher(metricsPublisher); 37 | HystrixPlugins.getInstance().registerPropertiesStrategy(propertiesStrategy); 38 | HystrixPlugins.getInstance().registerCommandExecutionHook(commandExecutionHook); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /specialroutes-service/src/main/java/com/thoughtmechanix/specialroutes/hystrix/ThreadLocalConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.specialroutes.hystrix; 2 | 3 | import com.netflix.hystrix.strategy.HystrixPlugins; 4 | import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy; 5 | import com.netflix.hystrix.strategy.eventnotifier.HystrixEventNotifier; 6 | import com.netflix.hystrix.strategy.executionhook.HystrixCommandExecutionHook; 7 | import com.netflix.hystrix.strategy.metrics.HystrixMetricsPublisher; 8 | import com.netflix.hystrix.strategy.properties.HystrixPropertiesStrategy; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.context.annotation.Configuration; 11 | 12 | import javax.annotation.PostConstruct; 13 | 14 | @Configuration 15 | public class ThreadLocalConfiguration { 16 | @Autowired(required = false) 17 | private HystrixConcurrencyStrategy existingConcurrencyStrategy; 18 | 19 | @PostConstruct 20 | public void init() { 21 | // Keeps references of existing Hystrix plugins. 22 | HystrixEventNotifier eventNotifier = HystrixPlugins.getInstance() 23 | .getEventNotifier(); 24 | HystrixMetricsPublisher metricsPublisher = HystrixPlugins.getInstance() 25 | .getMetricsPublisher(); 26 | HystrixPropertiesStrategy propertiesStrategy = HystrixPlugins.getInstance() 27 | .getPropertiesStrategy(); 28 | HystrixCommandExecutionHook commandExecutionHook = HystrixPlugins.getInstance() 29 | .getCommandExecutionHook(); 30 | 31 | HystrixPlugins.reset(); 32 | 33 | // Registers existing plugins excepts the Concurrent Strategy plugin. 34 | HystrixPlugins.getInstance().registerConcurrencyStrategy(new ThreadLocalAwareStrategy(existingConcurrencyStrategy)); 35 | HystrixPlugins.getInstance().registerEventNotifier(eventNotifier); 36 | HystrixPlugins.getInstance().registerMetricsPublisher(metricsPublisher); 37 | HystrixPlugins.getInstance().registerPropertiesStrategy(propertiesStrategy); 38 | HystrixPlugins.getInstance().registerCommandExecutionHook(commandExecutionHook); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /orgservice-new/src/main/java/com/thoughtmechanix/organization/controllers/OrganizationServiceController.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.organization.controllers; 2 | 3 | 4 | import com.thoughtmechanix.organization.model.Organization; 5 | import com.thoughtmechanix.organization.services.OrganizationService; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.RequestBody; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.http.HttpStatus; 12 | import org.springframework.web.bind.annotation.RestController; 13 | import org.springframework.web.bind.annotation.RequestMethod; 14 | import org.springframework.web.bind.annotation.PathVariable; 15 | import org.springframework.web.bind.annotation.ResponseStatus; 16 | 17 | 18 | @RestController 19 | @RequestMapping(value="v1/organizations") 20 | public class OrganizationServiceController { 21 | @Autowired 22 | private OrganizationService orgService; 23 | 24 | 25 | private static final Logger logger = LoggerFactory.getLogger(OrganizationServiceController.class); 26 | 27 | @RequestMapping(value="/{organizationId}",method = RequestMethod.GET) 28 | public Organization getOrganization( @PathVariable("organizationId") String organizationId) { 29 | logger.debug("Looking up data for org {}",organizationId ); 30 | 31 | Organization org = orgService.getOrg(organizationId); 32 | org.setContactName( "NEW::" + org.getContactName() ); 33 | return org; 34 | } 35 | 36 | @RequestMapping(value="/{organizationId}",method = RequestMethod.PUT) 37 | public void updateOrganization( @PathVariable("organizationId") String orgId, @RequestBody Organization org) { 38 | orgService.updateOrg( org ); 39 | } 40 | 41 | @RequestMapping(value="/{organizationId}",method = RequestMethod.POST) 42 | public void saveOrganization(@RequestBody Organization org) { 43 | orgService.saveOrg( org ); 44 | } 45 | 46 | @RequestMapping(value="/{organizationId}",method = RequestMethod.DELETE) 47 | @ResponseStatus(HttpStatus.NO_CONTENT) 48 | public void deleteOrganization( @PathVariable("orgId") String orgId, @RequestBody Organization org) { 49 | orgService.deleteOrg( org ); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /organization-service/src/main/java/com/thoughtmechanix/organization/controllers/OrganizationServiceController.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.organization.controllers; 2 | 3 | 4 | import com.thoughtmechanix.organization.model.Organization; 5 | import com.thoughtmechanix.organization.services.OrganizationService; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.RequestBody; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.http.HttpStatus; 12 | import org.springframework.web.bind.annotation.RestController; 13 | import org.springframework.web.bind.annotation.RequestMethod; 14 | import org.springframework.web.bind.annotation.PathVariable; 15 | import org.springframework.web.bind.annotation.ResponseStatus; 16 | 17 | @RestController 18 | @RequestMapping(value="v1/organizations") 19 | public class OrganizationServiceController { 20 | @Autowired 21 | private OrganizationService orgService; 22 | 23 | 24 | private static final Logger logger = LoggerFactory.getLogger(OrganizationServiceController.class); 25 | 26 | @RequestMapping(value="/{organizationId}",method = RequestMethod.GET) 27 | public Organization getOrganization( @PathVariable("organizationId") String organizationId) { 28 | logger.debug(String.format("Looking up data for org {}", organizationId)); 29 | 30 | Organization org = orgService.getOrg(organizationId); 31 | org.setContactName("OLD::" + org.getContactName()); 32 | return org; 33 | } 34 | 35 | @RequestMapping(value="/{organizationId}",method = RequestMethod.PUT) 36 | public void updateOrganization( @PathVariable("organizationId") String orgId, @RequestBody Organization org) { 37 | orgService.updateOrg( org ); 38 | } 39 | 40 | @RequestMapping(value="/{organizationId}",method = RequestMethod.POST) 41 | public void saveOrganization(@RequestBody Organization org) { 42 | orgService.saveOrg( org ); 43 | } 44 | 45 | @RequestMapping(value="/{organizationId}",method = RequestMethod.DELETE) 46 | @ResponseStatus(HttpStatus.NO_CONTENT) 47 | public void deleteOrganization( @PathVariable("orgId") String orgId, @RequestBody Organization org) { 48 | orgService.deleteOrg( org ); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /licensing-service/src/main/java/com/thoughtmechanix/licenses/controllers/LicenseServiceController.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.licenses.controllers; 2 | 3 | import com.thoughtmechanix.licenses.model.License; 4 | import com.thoughtmechanix.licenses.services.LicenseService; 5 | import com.thoughtmechanix.licenses.config.ServiceConfig; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.RequestBody; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.http.HttpStatus; 12 | import org.springframework.web.bind.annotation.RestController; 13 | import org.springframework.web.bind.annotation.RequestMethod; 14 | import org.springframework.web.bind.annotation.PathVariable; 15 | import org.springframework.web.bind.annotation.ResponseStatus; 16 | import javax.servlet.http.HttpServletRequest; 17 | import java.util.List; 18 | 19 | @RestController 20 | @RequestMapping(value="v1/organizations/{organizationId}/licenses") 21 | public class LicenseServiceController { 22 | @Autowired 23 | private LicenseService licenseService; 24 | 25 | @Autowired 26 | private ServiceConfig serviceConfig; 27 | 28 | @Autowired 29 | private HttpServletRequest request; 30 | 31 | private static final Logger logger = LoggerFactory.getLogger(LicenseServiceController.class); 32 | 33 | 34 | @RequestMapping(value="/",method = RequestMethod.GET) 35 | public List getLicenses( @PathVariable("organizationId") String organizationId) { 36 | 37 | return licenseService.getLicensesByOrg(organizationId); 38 | } 39 | 40 | @RequestMapping(value="/{licenseId}",method = RequestMethod.GET) 41 | public License getLicenses( @PathVariable("organizationId") String organizationId, 42 | @PathVariable("licenseId") String licenseId) throws InterruptedException { 43 | logger.debug("Found tmx-correlation-id in license-service-controller: {} ", request.getHeader("tmx-correlation-id")); 44 | return licenseService.getLicense(organizationId, licenseId); 45 | } 46 | 47 | @RequestMapping(value="{licenseId}",method = RequestMethod.PUT) 48 | public void updateLicenses( @PathVariable("licenseId") String licenseId, @RequestBody License license) { 49 | licenseService.updateLicense(license); 50 | } 51 | 52 | @RequestMapping(value="/",method = RequestMethod.POST) 53 | public void saveLicenses(@RequestBody License license) { 54 | licenseService.saveLicense(license); 55 | } 56 | 57 | @RequestMapping(value="{licenseId}",method = RequestMethod.DELETE) 58 | @ResponseStatus(HttpStatus.NO_CONTENT) 59 | public void deleteLicenses( @PathVariable("licenseId") String licenseId, @RequestBody License license) { 60 | licenseService.deleteLicense(license); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /zuulsvr/src/main/java/com/thoughtmechanix/zuulsvr/filters/FilterUtils.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.zuulsvr.filters; 2 | 3 | import com.netflix.zuul.context.RequestContext; 4 | import org.springframework.stereotype.Component; 5 | 6 | @Component 7 | public class FilterUtils { 8 | 9 | public static final String CORRELATION_ID = "tmx-correlation-id"; 10 | public static final String AUTH_TOKEN = "tmx-auth-token"; 11 | public static final String USER_ID = "tmx-user-id"; 12 | public static final String ORG_ID = "tmx-org-id"; 13 | public static final String PRE_FILTER_TYPE = "pre"; 14 | public static final String POST_FILTER_TYPE = "post"; 15 | public static final String ROUTE_FILTER_TYPE = "route"; 16 | 17 | public String getCorrelationId(){ 18 | RequestContext ctx = RequestContext.getCurrentContext(); 19 | 20 | if (ctx.getRequest().getHeader(CORRELATION_ID) !=null) { 21 | return ctx.getRequest().getHeader(CORRELATION_ID); 22 | } 23 | else{ 24 | return ctx.getZuulRequestHeaders().get(CORRELATION_ID); 25 | } 26 | } 27 | 28 | public void setCorrelationId(String correlationId){ 29 | RequestContext ctx = RequestContext.getCurrentContext(); 30 | ctx.addZuulRequestHeader(CORRELATION_ID, correlationId); 31 | } 32 | 33 | public final String getOrgId(){ 34 | RequestContext ctx = RequestContext.getCurrentContext(); 35 | if (ctx.getRequest().getHeader(ORG_ID) !=null) { 36 | return ctx.getRequest().getHeader(ORG_ID); 37 | } 38 | else{ 39 | return ctx.getZuulRequestHeaders().get(ORG_ID); 40 | } 41 | } 42 | 43 | public void setOrgId(String orgId){ 44 | RequestContext ctx = RequestContext.getCurrentContext(); 45 | ctx.addZuulRequestHeader(ORG_ID, orgId); 46 | } 47 | 48 | public final String getUserId(){ 49 | RequestContext ctx = RequestContext.getCurrentContext(); 50 | if (ctx.getRequest().getHeader(USER_ID) !=null) { 51 | return ctx.getRequest().getHeader(USER_ID); 52 | } 53 | else{ 54 | return ctx.getZuulRequestHeaders().get(USER_ID); 55 | } 56 | } 57 | 58 | public void setUserId(String userId){ 59 | RequestContext ctx = RequestContext.getCurrentContext(); 60 | ctx.addZuulRequestHeader(USER_ID, userId); 61 | } 62 | 63 | public final String getAuthToken(){ 64 | RequestContext ctx = RequestContext.getCurrentContext(); 65 | return ctx.getRequest().getHeader(AUTH_TOKEN); 66 | } 67 | 68 | public String getServiceId(){ 69 | RequestContext ctx = RequestContext.getCurrentContext(); 70 | 71 | //We might not have a service id if we are using a static, non-eureka route. 72 | if (ctx.get("serviceId")==null) return ""; 73 | return ctx.get("serviceId").toString(); 74 | } 75 | 76 | 77 | } 78 | -------------------------------------------------------------------------------- /orgservice-new/src/main/java/com/thoughtmechanix/organization/hystrix/ThreadLocalAwareStrategy.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.organization.hystrix; 2 | 3 | import com.netflix.hystrix.HystrixThreadPoolKey; 4 | import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy; 5 | import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariable; 6 | import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariableLifecycle; 7 | import com.netflix.hystrix.strategy.properties.HystrixProperty; 8 | import com.thoughtmechanix.organization.utils.UserContextHolder; 9 | 10 | import java.util.concurrent.BlockingQueue; 11 | import java.util.concurrent.Callable; 12 | import java.util.concurrent.ThreadPoolExecutor; 13 | import java.util.concurrent.TimeUnit; 14 | 15 | 16 | public class ThreadLocalAwareStrategy extends HystrixConcurrencyStrategy{ 17 | private HystrixConcurrencyStrategy existingConcurrencyStrategy; 18 | 19 | public ThreadLocalAwareStrategy( 20 | HystrixConcurrencyStrategy existingConcurrencyStrategy) { 21 | this.existingConcurrencyStrategy = existingConcurrencyStrategy; 22 | } 23 | 24 | @Override 25 | public BlockingQueue getBlockingQueue(int maxQueueSize) { 26 | return existingConcurrencyStrategy != null 27 | ? existingConcurrencyStrategy.getBlockingQueue(maxQueueSize) 28 | : super.getBlockingQueue(maxQueueSize); 29 | } 30 | 31 | @Override 32 | public HystrixRequestVariable getRequestVariable( 33 | HystrixRequestVariableLifecycle rv) { 34 | return existingConcurrencyStrategy != null 35 | ? existingConcurrencyStrategy.getRequestVariable(rv) 36 | : super.getRequestVariable(rv); 37 | } 38 | 39 | @Override 40 | public ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey, 41 | HystrixProperty corePoolSize, 42 | HystrixProperty maximumPoolSize, 43 | HystrixProperty keepAliveTime, TimeUnit unit, 44 | BlockingQueue workQueue) { 45 | return existingConcurrencyStrategy != null 46 | ? existingConcurrencyStrategy.getThreadPool(threadPoolKey, corePoolSize, 47 | maximumPoolSize, keepAliveTime, unit, workQueue) 48 | : super.getThreadPool(threadPoolKey, corePoolSize, maximumPoolSize, 49 | keepAliveTime, unit, workQueue); 50 | } 51 | 52 | @Override 53 | public Callable wrapCallable(Callable callable) { 54 | 55 | return existingConcurrencyStrategy != null 56 | ? existingConcurrencyStrategy 57 | .wrapCallable(new DelegatingUserContextCallable(callable, UserContextHolder.getContext())) 58 | : super.wrapCallable(new DelegatingUserContextCallable(callable, UserContextHolder.getContext())); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /specialroutes-service/src/main/java/com/thoughtmechanix/specialroutes/hystrix/ThreadLocalAwareStrategy.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.specialroutes.hystrix; 2 | 3 | import com.netflix.hystrix.HystrixThreadPoolKey; 4 | import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy; 5 | import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariable; 6 | import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariableLifecycle; 7 | import com.netflix.hystrix.strategy.properties.HystrixProperty; 8 | import com.thoughtmechanix.specialroutes.utils.UserContextHolder; 9 | 10 | import java.util.concurrent.BlockingQueue; 11 | import java.util.concurrent.Callable; 12 | import java.util.concurrent.ThreadPoolExecutor; 13 | import java.util.concurrent.TimeUnit; 14 | 15 | 16 | public class ThreadLocalAwareStrategy extends HystrixConcurrencyStrategy{ 17 | private HystrixConcurrencyStrategy existingConcurrencyStrategy; 18 | 19 | public ThreadLocalAwareStrategy( 20 | HystrixConcurrencyStrategy existingConcurrencyStrategy) { 21 | this.existingConcurrencyStrategy = existingConcurrencyStrategy; 22 | } 23 | 24 | @Override 25 | public BlockingQueue getBlockingQueue(int maxQueueSize) { 26 | return existingConcurrencyStrategy != null 27 | ? existingConcurrencyStrategy.getBlockingQueue(maxQueueSize) 28 | : super.getBlockingQueue(maxQueueSize); 29 | } 30 | 31 | @Override 32 | public HystrixRequestVariable getRequestVariable( 33 | HystrixRequestVariableLifecycle rv) { 34 | return existingConcurrencyStrategy != null 35 | ? existingConcurrencyStrategy.getRequestVariable(rv) 36 | : super.getRequestVariable(rv); 37 | } 38 | 39 | @Override 40 | public ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey, 41 | HystrixProperty corePoolSize, 42 | HystrixProperty maximumPoolSize, 43 | HystrixProperty keepAliveTime, TimeUnit unit, 44 | BlockingQueue workQueue) { 45 | return existingConcurrencyStrategy != null 46 | ? existingConcurrencyStrategy.getThreadPool(threadPoolKey, corePoolSize, 47 | maximumPoolSize, keepAliveTime, unit, workQueue) 48 | : super.getThreadPool(threadPoolKey, corePoolSize, maximumPoolSize, 49 | keepAliveTime, unit, workQueue); 50 | } 51 | 52 | @Override 53 | public Callable wrapCallable(Callable callable) { 54 | 55 | return existingConcurrencyStrategy != null 56 | ? existingConcurrencyStrategy 57 | .wrapCallable(new DelegatingUserContextCallable(callable, UserContextHolder.getContext())) 58 | : super.wrapCallable(new DelegatingUserContextCallable(callable, UserContextHolder.getContext())); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /organization-service/src/main/java/com/thoughtmechanix/organization/hystrix/ThreadLocalAwareStrategy.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.organization.hystrix; 2 | 3 | import com.netflix.hystrix.HystrixThreadPoolKey; 4 | import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy; 5 | import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariable; 6 | import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariableLifecycle; 7 | import com.netflix.hystrix.strategy.properties.HystrixProperty; 8 | import com.thoughtmechanix.organization.utils.UserContextHolder; 9 | 10 | 11 | import java.util.concurrent.BlockingQueue; 12 | import java.util.concurrent.Callable; 13 | import java.util.concurrent.ThreadPoolExecutor; 14 | import java.util.concurrent.TimeUnit; 15 | 16 | 17 | public class ThreadLocalAwareStrategy extends HystrixConcurrencyStrategy{ 18 | private HystrixConcurrencyStrategy existingConcurrencyStrategy; 19 | 20 | public ThreadLocalAwareStrategy( 21 | HystrixConcurrencyStrategy existingConcurrencyStrategy) { 22 | this.existingConcurrencyStrategy = existingConcurrencyStrategy; 23 | } 24 | 25 | @Override 26 | public BlockingQueue getBlockingQueue(int maxQueueSize) { 27 | return existingConcurrencyStrategy != null 28 | ? existingConcurrencyStrategy.getBlockingQueue(maxQueueSize) 29 | : super.getBlockingQueue(maxQueueSize); 30 | } 31 | 32 | @Override 33 | public HystrixRequestVariable getRequestVariable( 34 | HystrixRequestVariableLifecycle rv) { 35 | return existingConcurrencyStrategy != null 36 | ? existingConcurrencyStrategy.getRequestVariable(rv) 37 | : super.getRequestVariable(rv); 38 | } 39 | 40 | @Override 41 | public ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey, 42 | HystrixProperty corePoolSize, 43 | HystrixProperty maximumPoolSize, 44 | HystrixProperty keepAliveTime, TimeUnit unit, 45 | BlockingQueue workQueue) { 46 | return existingConcurrencyStrategy != null 47 | ? existingConcurrencyStrategy.getThreadPool(threadPoolKey, corePoolSize, 48 | maximumPoolSize, keepAliveTime, unit, workQueue) 49 | : super.getThreadPool(threadPoolKey, corePoolSize, maximumPoolSize, 50 | keepAliveTime, unit, workQueue); 51 | } 52 | 53 | @Override 54 | public Callable wrapCallable(Callable callable) { 55 | 56 | return existingConcurrencyStrategy != null 57 | ? existingConcurrencyStrategy 58 | .wrapCallable(new DelegatingUserContextCallable(callable, UserContextHolder.getContext())) 59 | : super.wrapCallable(new DelegatingUserContextCallable(callable, UserContextHolder.getContext())); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /licensing-service/src/main/java/com/thoughtmechanix/licenses/hystrix/ThreadLocalAwareStrategy.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.licenses.hystrix; 2 | 3 | import com.netflix.hystrix.HystrixThreadPoolKey; 4 | import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy; 5 | import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariable; 6 | import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariableLifecycle; 7 | import com.netflix.hystrix.strategy.properties.HystrixProperty; 8 | import com.thoughtmechanix.licenses.utils.UserContext; 9 | import com.thoughtmechanix.licenses.utils.UserContextHolder; 10 | 11 | import java.util.concurrent.BlockingQueue; 12 | import java.util.concurrent.Callable; 13 | import java.util.concurrent.ThreadPoolExecutor; 14 | import java.util.concurrent.TimeUnit; 15 | 16 | 17 | public class ThreadLocalAwareStrategy extends HystrixConcurrencyStrategy{ 18 | private HystrixConcurrencyStrategy existingConcurrencyStrategy; 19 | 20 | public ThreadLocalAwareStrategy( 21 | HystrixConcurrencyStrategy existingConcurrencyStrategy) { 22 | this.existingConcurrencyStrategy = existingConcurrencyStrategy; 23 | } 24 | 25 | @Override 26 | public BlockingQueue getBlockingQueue(int maxQueueSize) { 27 | return existingConcurrencyStrategy != null 28 | ? existingConcurrencyStrategy.getBlockingQueue(maxQueueSize) 29 | : super.getBlockingQueue(maxQueueSize); 30 | } 31 | 32 | @Override 33 | public HystrixRequestVariable getRequestVariable( 34 | HystrixRequestVariableLifecycle rv) { 35 | return existingConcurrencyStrategy != null 36 | ? existingConcurrencyStrategy.getRequestVariable(rv) 37 | : super.getRequestVariable(rv); 38 | } 39 | 40 | @Override 41 | public ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey, 42 | HystrixProperty corePoolSize, 43 | HystrixProperty maximumPoolSize, 44 | HystrixProperty keepAliveTime, TimeUnit unit, 45 | BlockingQueue workQueue) { 46 | return existingConcurrencyStrategy != null 47 | ? existingConcurrencyStrategy.getThreadPool(threadPoolKey, corePoolSize, 48 | maximumPoolSize, keepAliveTime, unit, workQueue) 49 | : super.getThreadPool(threadPoolKey, corePoolSize, maximumPoolSize, 50 | keepAliveTime, unit, workQueue); 51 | } 52 | 53 | @Override 54 | public Callable wrapCallable(Callable callable) { 55 | 56 | return existingConcurrencyStrategy != null 57 | ? existingConcurrencyStrategy 58 | .wrapCallable(new DelegatingUserContextCallable(callable, UserContextHolder.getContext())) 59 | : super.wrapCallable(new DelegatingUserContextCallable(callable, UserContextHolder.getContext())); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /docker/common/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | eurekaserver: 4 | image: johncarnell/tmx-eurekasvr:chapter6 5 | ports: 6 | - "8761:8761" 7 | configserver: 8 | image: johncarnell/tmx-confsvr:chapter6 9 | ports: 10 | - "8888:8888" 11 | environment: 12 | EUREKASERVER_URI: "http://eurekaserver:8761/eureka/" 13 | EUREKASERVER_PORT: 8761 14 | ENCRYPT_KEY: "IMSYMMETRIC" 15 | zuulserver: 16 | image: johncarnell/tmx-zuulsvr:chapter6 17 | ports: 18 | - "5555:5555" 19 | environment: 20 | PROFILE: "default" 21 | SERVER_PORT: "5555" 22 | CONFIGSERVER_URI: "http://configserver:8888" 23 | EUREKASERVER_URI: "http://eurekaserver:8761/eureka/" 24 | EUREKASERVER_PORT: "8761" 25 | DATABASESERVER_PORT: "5432" 26 | CONFIGSERVER_PORT: "8888" 27 | ORGSERVERNEW_PORT: "8087" 28 | database: 29 | image: postgres:9.5 30 | ports: 31 | - "5432:5432" 32 | environment: 33 | - POSTGRES_USER=postgres 34 | - POSTGRES_PASSWORD=p0stgr@s 35 | - POSTGRES_DB=eagle_eye_local 36 | licensingservice: 37 | image: johncarnell/tmx-licensing-service:chapter6 38 | ports: 39 | - "8080:8080" 40 | environment: 41 | PROFILE: "default" 42 | SERVER_PORT: "8080" 43 | CONFIGSERVER_URI: "http://configserver:8888" 44 | EUREKASERVER_URI: "http://eurekaserver:8761/eureka/" 45 | EUREKASERVER_PORT: "8761" 46 | DATABASESERVER_PORT: "5432" 47 | CONFIGSERVER_PORT: "8888" 48 | ORGSERVERNEW_PORT: "8087" 49 | ZUULSERVER_PORT: "5555" 50 | ENCRYPT_KEY: "IMSYMMETRIC" 51 | organizationservice: 52 | image: johncarnell/tmx-organization-service:chapter6 53 | ports: 54 | - "8085:8085" 55 | environment: 56 | PROFILE: "default" 57 | SERVER_PORT: "8085" 58 | CONFIGSERVER_URI: "http://configserver:8888" 59 | EUREKASERVER_URI: "http://eurekaserver:8761/eureka/" 60 | EUREKASERVER_PORT: "8761" 61 | DATABASESERVER_PORT: "5432" 62 | CONFIGSERVER_PORT: "8888" 63 | ENCRYPT_KEY: "IMSYMMETRIC" 64 | orgservice-new: 65 | image: johncarnell/tmx-orgservice-new:chapter6 66 | ports: 67 | - "8087:8087" 68 | environment: 69 | PROFILE: "default" 70 | SERVER_PORT: "8087" 71 | CONFIGSERVER_URI: "http://configserver:8888" 72 | EUREKASERVER_URI: "http://eurekaserver:8761/eureka/" 73 | EUREKASERVER_PORT: "8761" 74 | DATABASESERVER_PORT: "5432" 75 | CONFIGSERVER_PORT: "8888" 76 | ENCRYPT_KEY: "IMSYMMETRIC" 77 | specialroutes-service: 78 | image: johncarnell/tmx-specialroutes-service:chapter6 79 | ports: 80 | - "8910:8910" 81 | environment: 82 | PROFILE: "default" 83 | SERVER_PORT: "8910" 84 | CONFIGSERVER_URI: "http://configserver:8888" 85 | EUREKASERVER_URI: "http://eurekaserver:8761/eureka/" 86 | EUREKASERVER_PORT: "8761" 87 | DATABASESERVER_PORT: "5432" 88 | CONFIGSERVER_PORT: "8888" 89 | ENCRYPT_KEY: "IMSYMMETRIC" 90 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | Welcome to Spring Microservices in Action, Chapter 6. Chapter 6 introduces the concept of a API gateway. API gateways are using to enforce consistent policies and actions on all service calls. With this chapter we are going to introduce Spring Cloud and Netflix Zuul API gateway. 3 | 4 | By the time you are done reading this chapter you will have built and/or deployed: 5 | 6 | 1. A Spring Cloud Config server that is deployed as Docker container and can manage a services configuration information using a file system or GitHub-based repository. 7 | 2. A Eureka server running as a Spring-Cloud based service. This service will allow multiple service instances to register with it. Clients that need to call a service will use Eureka to lookup the physical location of the target service. 8 | 3. A Zuul API Gateway. All of our microservices can be routed through the gateway and have pre, response and 9 | post policies enforced on the calls. 10 | 4. A organization service that will manage organization data used within EagleEye. 11 | 5. A new version of the organization service. This service is used to demonstrate how to use the Zuul API gateway to route to different versions of a service. 12 | 6. A special routes services that the the API gateway will call to determine whether or not it should route a user's service call to a different service then the one they were originally calling. This service is used in conjunction with the orgservice-new service to determine whether a call to the organization service gets routed to an old version of the organization service vs. a new version of the service. 13 | 7. A licensing service that will manage licensing data used within EagleEye. 14 | 8. A Postgres SQL database used to hold the data for these two services. 15 | 16 | # Software needed 17 | 1. [Apache Maven] (http://maven.apache.org). I used version 3.3.9 of the Maven. I chose Maven because, while other build tools like Gradle are extremely popular, Maven is still the pre-dominate build tool in use in the Java ecosystem. All of the code examples in this book have been compiled with Java version 1.8. 18 | 2. [Docker] (http://docker.com). I built the code examples in this book using Docker V1.12 and above. I am taking advantage of the embedded DNS server in Docker that came out in release V1.11. New Docker releases are constantly coming out so it's release version you are using may change on a regular basis. 19 | 3. [Git Client] (http://git-scm.com). All of the source code for this book is stored in a GitHub repository. For the book, I used version 2.8.4 of the git client. 20 | 21 | # Building the Docker Images for Chapter 6 22 | To build the code examples for Chapter 6 as a docker image, open a command-line window change to the directory where you have downloaded the chapter 6 source code. 23 | 24 | Run the following maven command. This command will execute the [Spotify docker plugin](https://github.com/spotify/docker-maven-plugin) defined in the pom.xml file. 25 | 26 | **mvn clean package docker:build** 27 | 28 | Running the above command at the root of the project directory will build all of the projects. If everything builds successfully you should see a message indicating that the build was successful. 29 | 30 | # Running the services in Chapter 6 31 | 32 | Now we are going to use docker-compose to start the actual image. To start the docker image, 33 | change to the directory containing your chapter 6 source code. Issue the following docker-compose command: 34 | 35 | **docker-compose -f docker/common/docker-compose.yml up** 36 | 37 | If everything starts correctly you should see a bunch of Spring Boot information fly by on standard out. At this point all of the services needed for the chapter code examples will be running. 38 | -------------------------------------------------------------------------------- /eurekasvr/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | com.thoughtmechanix 6 | eurekasvr 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | Eureka Server 11 | Eureka Server demo project 12 | 13 | 14 | org.springframework.boot 15 | spring-boot-starter-parent 16 | 1.4.4.RELEASE 17 | 18 | 19 | 20 | 21 | org.springframework.cloud 22 | spring-cloud-dependencies 23 | Camden.SR5 24 | pom 25 | import 26 | 27 | 28 | 29 | 30 | 31 | 32 | org.springframework.cloud 33 | spring-cloud-starter-eureka-server 34 | 35 | 36 | 37 | 38 | 39 | UTF-8 40 | com.thoughtmechanix.eurekasvr.EurekaServerApplication 41 | 1.8 42 | johncarnell/tmx-eurekasvr 43 | chapter6 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | maven-resources-plugin 52 | 53 | 54 | copy-resources 55 | 56 | validate 57 | 58 | copy-resources 59 | 60 | 61 | ${basedir}/target/dockerfile 62 | 63 | 64 | src/main/docker 65 | true 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | com.spotify 74 | docker-maven-plugin 75 | 0.4.10 76 | 77 | ${docker.image.name}:${docker.image.tag} 78 | ${basedir}/target/dockerfile 79 | 80 | 81 | / 82 | ${project.build.directory} 83 | ${project.build.finalName}.jar 84 | 85 | 86 | 87 | 88 | 89 | org.springframework.boot 90 | spring-boot-maven-plugin 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /confsvr/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | com.thoughtmechanix 6 | configurationserver 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | Config Server 11 | Config Server demo project 12 | 13 | 14 | org.springframework.boot 15 | spring-boot-starter-parent 16 | 1.4.4.RELEASE 17 | 18 | 19 | 20 | 21 | org.springframework.cloud 22 | spring-cloud-dependencies 23 | Camden.SR5 24 | pom 25 | import 26 | 27 | 28 | 29 | 30 | 31 | 32 | org.springframework.cloud 33 | spring-cloud-config-server 34 | 35 | 36 | 37 | org.springframework.cloud 38 | spring-cloud-starter-config 39 | 40 | 41 | 42 | org.springframework.cloud 43 | spring-cloud-starter-eureka 44 | 45 | 46 | 47 | 48 | 49 | UTF-8 50 | com.thoughtmechanix.confsvr.ConfigServerApplication 51 | 1.8 52 | johncarnell/tmx-confsvr 53 | chapter6 54 | 55 | 56 | 57 | 58 | 59 | 60 | maven-resources-plugin 61 | 62 | 63 | copy-resources 64 | 65 | validate 66 | 67 | copy-resources 68 | 69 | 70 | ${basedir}/target/dockerfile 71 | 72 | 73 | src/main/docker 74 | true 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | com.spotify 83 | docker-maven-plugin 84 | 0.4.10 85 | 86 | ${docker.image.name}:${docker.image.tag} 87 | ${basedir}/target/dockerfile 88 | 89 | 90 | / 91 | ${project.build.directory} 92 | ${project.build.finalName}.jar 93 | 94 | 95 | 96 | 97 | 98 | org.springframework.boot 99 | spring-boot-maven-plugin 100 | 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /licensing-service/src/main/java/com/thoughtmechanix/licenses/services/LicenseService.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.licenses.services; 2 | 3 | import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; 4 | import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty; 5 | import com.thoughtmechanix.licenses.clients.OrganizationRestTemplateClient; 6 | import com.thoughtmechanix.licenses.config.ServiceConfig; 7 | import com.thoughtmechanix.licenses.model.License; 8 | import com.thoughtmechanix.licenses.model.Organization; 9 | import com.thoughtmechanix.licenses.repository.LicenseRepository; 10 | import com.thoughtmechanix.licenses.utils.UserContext; 11 | import com.thoughtmechanix.licenses.utils.UserContextHolder; 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.stereotype.Service; 16 | 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | import java.util.Random; 20 | import java.util.UUID; 21 | 22 | @Service 23 | public class LicenseService { 24 | 25 | @Autowired 26 | private LicenseRepository licenseRepository; 27 | 28 | @Autowired 29 | ServiceConfig config; 30 | 31 | @Autowired 32 | OrganizationRestTemplateClient organizationRestClient; 33 | 34 | private static final Logger logger = LoggerFactory.getLogger(LicenseService.class); 35 | 36 | @HystrixCommand 37 | public License getLicense(String organizationId,String licenseId) throws InterruptedException { 38 | License license = licenseRepository.findByOrganizationIdAndLicenseId(organizationId, licenseId); 39 | 40 | Organization org = getOrganization(organizationId); 41 | 42 | return license 43 | .withOrganizationName( org.getName()) 44 | .withContactName( org.getContactName()) 45 | .withContactEmail( org.getContactEmail() ) 46 | .withContactPhone( org.getContactPhone() ) 47 | .withComment(config.getExampleProperty()); 48 | } 49 | 50 | @HystrixCommand 51 | private Organization getOrganization(String organizationId) { 52 | return organizationRestClient.getOrganization(organizationId); 53 | } 54 | 55 | private void randomlyRunLong(){ 56 | Random rand = new Random(); 57 | 58 | int randomNum = rand.nextInt((3 - 1) + 1) + 1; 59 | 60 | if (randomNum==3) sleep(); 61 | } 62 | 63 | private void sleep(){ 64 | try { 65 | Thread.sleep(2000); 66 | } catch (InterruptedException e) { 67 | e.printStackTrace(); 68 | } 69 | } 70 | 71 | 72 | @HystrixCommand(fallbackMethod = "buildFallbackLicenseList", 73 | threadPoolKey = "licenseByOrgThreadPool", 74 | threadPoolProperties = 75 | {@HystrixProperty(name = "coreSize",value="30"), 76 | @HystrixProperty(name="maxQueueSize", value="10"), 77 | }, 78 | commandProperties={ 79 | @HystrixProperty(name="circuitBreaker.requestVolumeThreshold", value="10"), 80 | @HystrixProperty(name="circuitBreaker.errorThresholdPercentage", value="75"), 81 | @HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds", value="7000"), 82 | @HystrixProperty(name="metrics.rollingStats.timeInMilliseconds", value="15000"), 83 | @HystrixProperty(name="metrics.rollingStats.numBuckets", value="5")} 84 | ) 85 | public List getLicensesByOrg(String organizationId){ 86 | randomlyRunLong(); 87 | 88 | return licenseRepository.findByOrganizationId(organizationId); 89 | } 90 | 91 | private List buildFallbackLicenseList(String organizationId){ 92 | List fallbackList = new ArrayList<>(); 93 | License license = new License() 94 | .withId("0000000-00-00000") 95 | .withOrganizationId( organizationId ) 96 | .withProductName("Sorry no licensing information currently available"); 97 | 98 | fallbackList.add(license); 99 | return fallbackList; 100 | } 101 | 102 | public void saveLicense(License license){ 103 | license.withId( UUID.randomUUID().toString()); 104 | 105 | licenseRepository.save(license); 106 | } 107 | 108 | public void updateLicense(License license){ 109 | licenseRepository.save(license); 110 | } 111 | 112 | public void deleteLicense(License license){ 113 | licenseRepository.delete( license.getLicenseId()); 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /zuulsvr/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | com.thoughtmechanix 6 | zuulsvr 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | Zuul Proxy Server 11 | Zuul Proxy Server 12 | 13 | 14 | org.springframework.boot 15 | spring-boot-starter-parent 16 | 1.4.4.RELEASE 17 | 18 | 19 | 20 | 21 | org.springframework.cloud 22 | spring-cloud-dependencies 23 | Camden.SR5 24 | pom 25 | import 26 | 27 | 28 | 29 | 30 | 31 | 32 | org.springframework.cloud 33 | spring-cloud-starter-zuul 34 | 35 | 36 | org.springframework.cloud 37 | spring-cloud-starter-eureka 38 | 39 | 40 | org.springframework.cloud 41 | spring-cloud-starter-config 42 | 43 | 44 | 45 | org.springframework.cloud 46 | spring-cloud-config-client 47 | 48 | 49 | 50 | org.apache.httpcomponents 51 | httpclient 52 | 4.5.2 53 | 54 | 55 | 56 | 57 | 58 | 59 | UTF-8 60 | com.thoughtmechanix.zuulsvr.ZuulServerApplication 61 | 1.8 62 | johncarnell/tmx-zuulsvr 63 | chapter6 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | maven-resources-plugin 72 | 73 | 74 | copy-resources 75 | 76 | validate 77 | 78 | copy-resources 79 | 80 | 81 | ${basedir}/target/dockerfile 82 | 83 | 84 | src/main/docker 85 | true 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | com.spotify 94 | docker-maven-plugin 95 | 0.4.10 96 | 97 | ${docker.image.name}:${docker.image.tag} 98 | ${basedir}/target/dockerfile 99 | 100 | 101 | / 102 | ${project.build.directory} 103 | ${project.build.finalName}.jar 104 | 105 | 106 | 107 | 108 | 109 | org.springframework.boot 110 | spring-boot-maven-plugin 111 | 112 | 113 | org.apache.maven.plugins 114 | maven-compiler-plugin 115 | 3.5.1 116 | 117 | 1.8 118 | 1.8 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /licensing-service/src/main/java/com/thoughtmechanix/licenses/model/License.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.licenses.model; 2 | 3 | 4 | import javax.persistence.Column; 5 | import javax.persistence.Entity; 6 | import javax.persistence.Id; 7 | import javax.persistence.Table; 8 | import javax.persistence.Transient; 9 | 10 | @Entity 11 | @Table(name = "licenses") 12 | public class License{ 13 | @Id 14 | @Column(name = "license_id", nullable = false) 15 | private String licenseId; 16 | 17 | @Column(name = "organization_id", nullable = false) 18 | private String organizationId; 19 | 20 | @Transient 21 | private String organizationName =""; 22 | 23 | @Transient 24 | private String contactName =""; 25 | 26 | @Transient 27 | private String contactPhone =""; 28 | 29 | @Transient 30 | private String contactEmail =""; 31 | 32 | @Column(name = "product_name", nullable = false) 33 | private String productName; 34 | 35 | @Column(name = "license_type", nullable = false) 36 | private String licenseType; 37 | 38 | @Column(name = "license_max", nullable = false) 39 | private Integer licenseMax; 40 | 41 | @Column(name = "license_allocated", nullable = false) 42 | private Integer licenseAllocated; 43 | 44 | @Column(name="comment") 45 | private String comment; 46 | 47 | 48 | public Integer getLicenseMax() { 49 | return licenseMax; 50 | } 51 | 52 | public void setLicenseMax(Integer licenseMax) { 53 | this.licenseMax = licenseMax; 54 | } 55 | 56 | public Integer getLicenseAllocated() { 57 | return licenseAllocated; 58 | } 59 | 60 | public void setLicenseAllocated(Integer licenseAllocated) { 61 | this.licenseAllocated = licenseAllocated; 62 | } 63 | 64 | 65 | public String getLicenseId() { 66 | return licenseId; 67 | } 68 | 69 | public void setLicenseId(String licenseId) { 70 | this.licenseId = licenseId; 71 | } 72 | 73 | public String getOrganizationId() { 74 | return organizationId; 75 | } 76 | 77 | public void setOrganizationId(String organizationId) { 78 | this.organizationId = organizationId; 79 | } 80 | 81 | public String getProductName() { 82 | return productName; 83 | } 84 | 85 | public void setProductName(String productName) { 86 | this.productName = productName; 87 | } 88 | 89 | public String getLicenseType() { 90 | return licenseType; 91 | } 92 | 93 | public void setLicenseType(String licenseType) { 94 | this.licenseType = licenseType; 95 | } 96 | 97 | public String getComment() { 98 | return comment; 99 | } 100 | 101 | public void setComment(String comment) { 102 | this.comment = comment; 103 | } 104 | 105 | public String getOrganizationName() { 106 | return organizationName; 107 | } 108 | 109 | public void setOrganizationName(String organizationName) { 110 | this.organizationName = organizationName; 111 | } 112 | 113 | public String getContactName() { 114 | return contactName; 115 | } 116 | 117 | public void setContactName(String contactName) { 118 | this.contactName = contactName; 119 | } 120 | 121 | public String getContactPhone() { 122 | return contactPhone; 123 | } 124 | 125 | public void setContactPhone(String contactPhone) { 126 | this.contactPhone = contactPhone; 127 | } 128 | 129 | public String getContactEmail() { 130 | return contactEmail; 131 | } 132 | 133 | public void setContactEmail(String contactEmail) { 134 | this.contactEmail = contactEmail; 135 | } 136 | 137 | public License withId(String id){ 138 | this.setLicenseId(id); 139 | return this; 140 | } 141 | 142 | public License withOrganizationId(String organizationId){ 143 | this.setOrganizationId(organizationId); 144 | return this; 145 | } 146 | 147 | public License withProductName(String productName){ 148 | this.setProductName(productName); 149 | return this; 150 | } 151 | 152 | public License withLicenseType(String licenseType){ 153 | this.setLicenseType(licenseType); 154 | return this; 155 | } 156 | 157 | public License withLicenseMax(Integer licenseMax){ 158 | this.setLicenseMax(licenseMax); 159 | return this; 160 | } 161 | 162 | public License withLicenseAllocated(Integer licenseAllocated){ 163 | this.setLicenseAllocated(licenseAllocated); 164 | return this; 165 | } 166 | 167 | public License withComment(String comment){ 168 | this.setComment(comment); 169 | return this; 170 | } 171 | 172 | public License withOrganizationName(String organizationName){ 173 | this.setOrganizationName(organizationName); 174 | return this; 175 | } 176 | 177 | public License withContactName(String contactName){ 178 | this.setContactName(contactName); 179 | return this; 180 | } 181 | 182 | public License withContactPhone(String contactPhone){ 183 | this.setContactPhone(contactPhone); 184 | return this; 185 | } 186 | 187 | public License withContactEmail(String contactEmail){ 188 | this.setContactEmail(contactEmail); 189 | return this; 190 | } 191 | 192 | 193 | 194 | 195 | } 196 | -------------------------------------------------------------------------------- /orgservice-new/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | com.thoughtmechanix 6 | orgservice-new 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | New Version of Eagle Eye Organization Service 11 | New Version of Organization Service 12 | 13 | 14 | org.springframework.boot 15 | spring-boot-starter-parent 16 | 1.4.4.RELEASE 17 | 18 | 19 | 20 | 21 | org.springframework.cloud 22 | spring-cloud-dependencies 23 | Camden.SR5 24 | pom 25 | import 26 | 27 | 28 | 29 | 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-data-jpa 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-starter-web 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter-actuator 42 | 43 | 44 | 45 | org.springframework.cloud 46 | spring-cloud-starter-config 47 | 48 | 49 | 50 | org.springframework.cloud 51 | spring-cloud-starter-eureka 52 | 53 | 54 | 55 | org.springframework.cloud 56 | spring-cloud-config-client 57 | 58 | 59 | 60 | org.springframework.cloud 61 | spring-cloud-starter-hystrix 62 | 63 | 64 | 65 | com.h2database 66 | h2 67 | 68 | 69 | 70 | postgresql 71 | postgresql 72 | 9.1-901.jdbc4 73 | 74 | 75 | org.springframework.security 76 | spring-security-rsa 77 | 78 | 79 | com.netflix.hystrix 80 | hystrix-javanica 81 | 1.5.9 82 | 83 | 84 | 85 | 86 | UTF-8 87 | 1.8 88 | UTF-8 89 | com.thoughtmechanix.organization.Application 90 | johncarnell/tmx-orgservice-new 91 | chapter6 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | maven-resources-plugin 100 | 101 | 102 | copy-resources 103 | 104 | validate 105 | 106 | copy-resources 107 | 108 | 109 | ${basedir}/target/dockerfile 110 | 111 | 112 | src/main/docker 113 | true 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | com.spotify 122 | docker-maven-plugin 123 | 0.4.10 124 | 125 | ${docker.image.name}:${docker.image.tag} 126 | ${basedir}/target/dockerfile 127 | 128 | 129 | / 130 | ${project.build.directory} 131 | ${project.build.finalName}.jar 132 | 133 | 134 | 135 | 136 | 137 | org.springframework.boot 138 | spring-boot-maven-plugin 139 | 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /specialroutes-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | com.thoughtmechanix 6 | specialroutesservice 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | Eagle Eye Special Routes Service 11 | Special Routes Service 12 | 13 | 14 | org.springframework.boot 15 | spring-boot-starter-parent 16 | 1.4.4.RELEASE 17 | 18 | 19 | 20 | 21 | org.springframework.cloud 22 | spring-cloud-dependencies 23 | Camden.SR5 24 | pom 25 | import 26 | 27 | 28 | 29 | 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-data-jpa 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-starter-web 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter-actuator 42 | 43 | 44 | 45 | org.springframework.cloud 46 | spring-cloud-starter-config 47 | 48 | 49 | 50 | org.springframework.cloud 51 | spring-cloud-starter-eureka 52 | 53 | 54 | 55 | org.springframework.cloud 56 | spring-cloud-config-client 57 | 58 | 59 | 60 | org.springframework.cloud 61 | spring-cloud-starter-hystrix 62 | 63 | 64 | 65 | com.h2database 66 | h2 67 | 68 | 69 | 70 | postgresql 71 | postgresql 72 | 9.1-901.jdbc4 73 | 74 | 75 | org.springframework.security 76 | spring-security-rsa 77 | 78 | 79 | com.netflix.hystrix 80 | hystrix-javanica 81 | 1.5.9 82 | 83 | 84 | 85 | 86 | UTF-8 87 | 1.8 88 | UTF-8 89 | com.thoughtmechanix.specialroutes.Application 90 | johncarnell/tmx-specialroutes-service 91 | chapter6 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | maven-resources-plugin 100 | 101 | 102 | copy-resources 103 | 104 | validate 105 | 106 | copy-resources 107 | 108 | 109 | ${basedir}/target/dockerfile 110 | 111 | 112 | src/main/docker 113 | true 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | com.spotify 122 | docker-maven-plugin 123 | 0.4.10 124 | 125 | ${docker.image.name}:${docker.image.tag} 126 | ${basedir}/target/dockerfile 127 | 128 | 129 | / 130 | ${project.build.directory} 131 | ${project.build.finalName}.jar 132 | 133 | 134 | 135 | 136 | 137 | org.springframework.boot 138 | spring-boot-maven-plugin 139 | 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /licensing-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | com.thoughtmechanix 6 | licensing-service 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | Eagle Eye Licensing Service 11 | Licensing Service 12 | 13 | 14 | org.springframework.boot 15 | spring-boot-starter-parent 16 | 1.4.4.RELEASE 17 | 18 | 19 | 20 | 21 | org.springframework.cloud 22 | spring-cloud-dependencies 23 | Camden.SR5 24 | pom 25 | import 26 | 27 | 28 | 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-data-jpa 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-web 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-starter-actuator 41 | 42 | 43 | 44 | org.springframework.cloud 45 | spring-cloud-starter-eureka 46 | 47 | 48 | 49 | org.springframework.cloud 50 | spring-cloud-starter-feign 51 | 52 | 53 | 54 | org.springframework.cloud 55 | spring-cloud-starter-config 56 | 57 | 58 | 59 | org.springframework.cloud 60 | spring-cloud-config-client 61 | 62 | 63 | 64 | org.springframework.cloud 65 | spring-cloud-starter-hystrix 66 | 67 | 68 | 69 | com.h2database 70 | h2 71 | 72 | 73 | 74 | postgresql 75 | postgresql 76 | 9.1-901.jdbc4 77 | 78 | 79 | org.springframework.security 80 | spring-security-rsa 81 | 82 | 87 | 88 | 89 | 90 | UTF-8 91 | 1.8 92 | UTF-8 93 | com.thoughtmechanix.licenses.Application 94 | johncarnell/tmx-licensing-service 95 | chapter6 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | maven-resources-plugin 104 | 105 | 106 | copy-resources 107 | 108 | validate 109 | 110 | copy-resources 111 | 112 | 113 | ${basedir}/target/dockerfile 114 | 115 | 116 | src/main/docker 117 | true 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | com.spotify 126 | docker-maven-plugin 127 | 0.4.10 128 | 129 | ${docker.image.name}:${docker.image.tag} 130 | ${basedir}/target/dockerfile 131 | 132 | 133 | / 134 | ${project.build.directory} 135 | ${project.build.finalName}.jar 136 | 137 | 138 | 139 | 140 | 141 | org.springframework.boot 142 | spring-boot-maven-plugin 143 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /organization-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | com.thoughtmechanix 6 | organization-service 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | Eagle Eye Organization Service 11 | Organization Service 12 | 13 | 14 | org.springframework.boot 15 | spring-boot-starter-parent 16 | 1.4.4.RELEASE 17 | 18 | 19 | 20 | 21 | org.springframework.cloud 22 | spring-cloud-dependencies 23 | Camden.SR5 24 | pom 25 | import 26 | 27 | 28 | 29 | 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-data-jpa 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-starter-web 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter-actuator 42 | 43 | 44 | 45 | org.springframework.cloud 46 | spring-cloud-starter-eureka 47 | 48 | 49 | 50 | org.springframework.cloud 51 | spring-cloud-starter-feign 52 | 53 | 54 | 55 | org.springframework.cloud 56 | spring-cloud-starter-config 57 | 58 | 59 | 60 | org.springframework.cloud 61 | spring-cloud-config-client 62 | 63 | 64 | 65 | org.springframework.cloud 66 | spring-cloud-starter-hystrix 67 | 68 | 69 | 70 | com.h2database 71 | h2 72 | 73 | 74 | 75 | postgresql 76 | postgresql 77 | 9.1-901.jdbc4 78 | 79 | 80 | org.springframework.security 81 | spring-security-rsa 82 | 83 | 84 | com.netflix.hystrix 85 | hystrix-javanica 86 | 1.5.9 87 | 88 | 89 | 90 | 91 | UTF-8 92 | 1.8 93 | UTF-8 94 | com.thoughtmechanix.organization.Application 95 | johncarnell/tmx-organization-service 96 | chapter6 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | maven-resources-plugin 105 | 106 | 107 | copy-resources 108 | 109 | validate 110 | 111 | copy-resources 112 | 113 | 114 | ${basedir}/target/dockerfile 115 | 116 | 117 | src/main/docker 118 | true 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | com.spotify 127 | docker-maven-plugin 128 | 0.4.10 129 | 130 | ${docker.image.name}:${docker.image.tag} 131 | ${basedir}/target/dockerfile 132 | 133 | 134 | / 135 | ${project.build.directory} 136 | ${project.build.finalName}.jar 137 | 138 | 139 | 140 | 141 | 142 | org.springframework.boot 143 | spring-boot-maven-plugin 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /zuulsvr/src/main/java/com/thoughtmechanix/zuulsvr/filters/SpecialRoutesFilter.java: -------------------------------------------------------------------------------- 1 | package com.thoughtmechanix.zuulsvr.filters; 2 | 3 | 4 | import com.netflix.zuul.ZuulFilter; 5 | import com.netflix.zuul.context.RequestContext; 6 | import com.thoughtmechanix.zuulsvr.model.AbTestingRoute; 7 | import org.apache.http.Header; 8 | import org.apache.http.HttpHost; 9 | import org.apache.http.HttpRequest; 10 | import org.apache.http.HttpResponse; 11 | import org.apache.http.client.HttpClient; 12 | import org.apache.http.client.methods.HttpPatch; 13 | import org.apache.http.client.methods.HttpPost; 14 | import org.apache.http.client.methods.HttpPut; 15 | import org.apache.http.entity.ContentType; 16 | import org.apache.http.entity.InputStreamEntity; 17 | import org.apache.http.impl.client.CloseableHttpClient; 18 | import org.apache.http.impl.client.HttpClients; 19 | import org.apache.http.message.BasicHeader; 20 | import org.apache.http.message.BasicHttpRequest; 21 | import org.springframework.beans.factory.annotation.Autowired; 22 | import org.springframework.cloud.netflix.zuul.filters.ProxyRequestHelper; 23 | import org.springframework.http.HttpMethod; 24 | import org.springframework.http.HttpStatus; 25 | import org.springframework.http.ResponseEntity; 26 | import org.springframework.stereotype.Component; 27 | import org.springframework.util.LinkedMultiValueMap; 28 | import org.springframework.util.MultiValueMap; 29 | import org.springframework.web.client.HttpClientErrorException; 30 | import org.springframework.web.client.RestTemplate; 31 | 32 | 33 | import javax.servlet.http.HttpServletRequest; 34 | import javax.servlet.http.HttpServletResponse; 35 | import java.io.IOException; 36 | import java.io.InputStream; 37 | import java.net.URL; 38 | import java.util.ArrayList; 39 | import java.util.List; 40 | import java.util.Map; 41 | import java.util.Random; 42 | 43 | @Component 44 | public class SpecialRoutesFilter extends ZuulFilter { 45 | private static final int FILTER_ORDER = 1; 46 | private static final boolean SHOULD_FILTER =true; 47 | 48 | @Autowired 49 | FilterUtils filterUtils; 50 | 51 | @Autowired 52 | RestTemplate restTemplate; 53 | 54 | @Override 55 | public String filterType() { 56 | return filterUtils.ROUTE_FILTER_TYPE; 57 | } 58 | 59 | @Override 60 | public int filterOrder() { 61 | return FILTER_ORDER; 62 | } 63 | 64 | @Override 65 | public boolean shouldFilter() { 66 | return SHOULD_FILTER; 67 | } 68 | 69 | private ProxyRequestHelper helper = new ProxyRequestHelper(); 70 | 71 | private AbTestingRoute getAbRoutingInfo(String serviceName){ 72 | ResponseEntity restExchange = null; 73 | try { 74 | restExchange = restTemplate.exchange( 75 | "http://specialroutesservice/v1/route/abtesting/{serviceName}", 76 | HttpMethod.GET, 77 | null, AbTestingRoute.class, serviceName); 78 | } 79 | catch(HttpClientErrorException ex){ 80 | if (ex.getStatusCode()== HttpStatus.NOT_FOUND) return null; 81 | throw ex; 82 | } 83 | return restExchange.getBody(); 84 | } 85 | 86 | private String buildRouteString(String oldEndpoint, String newEndpoint, String serviceName){ 87 | int index = oldEndpoint.indexOf(serviceName); 88 | 89 | String strippedRoute = oldEndpoint.substring(index + serviceName.length()); 90 | System.out.println("Target route: " + String.format("%s/%s", newEndpoint, strippedRoute)); 91 | return String.format("%s/%s", newEndpoint, strippedRoute); 92 | } 93 | 94 | private String getVerb(HttpServletRequest request) { 95 | String sMethod = request.getMethod(); 96 | return sMethod.toUpperCase(); 97 | } 98 | 99 | private HttpHost getHttpHost(URL host) { 100 | HttpHost httpHost = new HttpHost(host.getHost(), host.getPort(), 101 | host.getProtocol()); 102 | return httpHost; 103 | } 104 | 105 | private Header[] convertHeaders(MultiValueMap headers) { 106 | List
list = new ArrayList<>(); 107 | for (String name : headers.keySet()) { 108 | for (String value : headers.get(name)) { 109 | list.add(new BasicHeader(name, value)); 110 | } 111 | } 112 | return list.toArray(new BasicHeader[0]); 113 | } 114 | 115 | private HttpResponse forwardRequest(HttpClient httpclient, HttpHost httpHost, 116 | HttpRequest httpRequest) throws IOException { 117 | return httpclient.execute(httpHost, httpRequest); 118 | } 119 | 120 | 121 | private MultiValueMap revertHeaders(Header[] headers) { 122 | MultiValueMap map = new LinkedMultiValueMap(); 123 | for (Header header : headers) { 124 | String name = header.getName(); 125 | if (!map.containsKey(name)) { 126 | map.put(name, new ArrayList()); 127 | } 128 | map.get(name).add(header.getValue()); 129 | } 130 | return map; 131 | } 132 | 133 | private InputStream getRequestBody(HttpServletRequest request) { 134 | InputStream requestEntity = null; 135 | try { 136 | requestEntity = request.getInputStream(); 137 | } 138 | catch (IOException ex) { 139 | // no requestBody is ok. 140 | } 141 | return requestEntity; 142 | } 143 | 144 | private void setResponse(HttpResponse response) throws IOException { 145 | this.helper.setResponse(response.getStatusLine().getStatusCode(), 146 | response.getEntity() == null ? null : response.getEntity().getContent(), 147 | revertHeaders(response.getAllHeaders())); 148 | } 149 | 150 | private HttpResponse forward(HttpClient httpclient, String verb, String uri, 151 | HttpServletRequest request, MultiValueMap headers, 152 | MultiValueMap params, InputStream requestEntity) 153 | throws Exception { 154 | Map info = this.helper.debug(verb, uri, headers, params, 155 | requestEntity); 156 | URL host = new URL( uri ); 157 | HttpHost httpHost = getHttpHost(host); 158 | 159 | HttpRequest httpRequest; 160 | int contentLength = request.getContentLength(); 161 | InputStreamEntity entity = new InputStreamEntity(requestEntity, contentLength, 162 | request.getContentType() != null 163 | ? ContentType.create(request.getContentType()) : null); 164 | switch (verb.toUpperCase()) { 165 | case "POST": 166 | HttpPost httpPost = new HttpPost(uri); 167 | httpRequest = httpPost; 168 | httpPost.setEntity(entity); 169 | break; 170 | case "PUT": 171 | HttpPut httpPut = new HttpPut(uri); 172 | httpRequest = httpPut; 173 | httpPut.setEntity(entity); 174 | break; 175 | case "PATCH": 176 | HttpPatch httpPatch = new HttpPatch(uri ); 177 | httpRequest = httpPatch; 178 | httpPatch.setEntity(entity); 179 | break; 180 | default: 181 | httpRequest = new BasicHttpRequest(verb, uri); 182 | 183 | } 184 | try { 185 | httpRequest.setHeaders(convertHeaders(headers)); 186 | HttpResponse zuulResponse = forwardRequest(httpclient, httpHost, httpRequest); 187 | 188 | return zuulResponse; 189 | } 190 | finally { 191 | } 192 | } 193 | 194 | 195 | 196 | public boolean useSpecialRoute(AbTestingRoute testRoute){ 197 | Random random = new Random(); 198 | 199 | if (testRoute.getActive().equals("N")) return false; 200 | 201 | int value = random.nextInt((10 - 1) + 1) + 1; 202 | 203 | if (testRoute.getWeight() headers = this.helper 229 | .buildZuulRequestHeaders(request); 230 | MultiValueMap params = this.helper 231 | .buildZuulRequestQueryParams(request); 232 | String verb = getVerb(request); 233 | InputStream requestEntity = getRequestBody(request); 234 | if (request.getContentLength() < 0) { 235 | context.setChunkedRequestBody(); 236 | } 237 | 238 | this.helper.addIgnoredHeaders(); 239 | CloseableHttpClient httpClient = null; 240 | HttpResponse response = null; 241 | 242 | try { 243 | httpClient = HttpClients.createDefault(); 244 | response = forward(httpClient, verb, route, request, headers, 245 | params, requestEntity); 246 | setResponse(response); 247 | } 248 | catch (Exception ex ) { 249 | ex.printStackTrace(); 250 | 251 | } 252 | finally{ 253 | try { 254 | httpClient.close(); 255 | } 256 | catch(IOException ex){} 257 | } 258 | } 259 | } 260 | --------------------------------------------------------------------------------