initial commit
This commit is contained in:
		
							parent
							
								
									119344f0e2
								
							
						
					
					
						commit
						ea807acdba
					
				
							
								
								
									
										42
									
								
								kubernetes/productcatalogue-service.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								kubernetes/productcatalogue-service.yaml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,42 @@ | ||||
| --- | ||||
| apiVersion: v1 | ||||
| kind: Service | ||||
| metadata: | ||||
|   name: productcatalogue | ||||
|   labels: | ||||
|     app: productcatalogue | ||||
| spec: | ||||
|   type: NodePort | ||||
|   selector: | ||||
|     app: productcatalogue | ||||
|   ports: | ||||
|   - protocol: TCP | ||||
|     port: 8020 | ||||
|     name: http | ||||
| 
 | ||||
| --- | ||||
| apiVersion: apps/v1 | ||||
| kind: Deployment | ||||
| metadata: | ||||
|   name: productcatalogue | ||||
| spec: | ||||
|   selector: | ||||
|     matchLabels: | ||||
|       app: productcatalogue | ||||
|   replicas: 1 | ||||
|   template: | ||||
|     metadata: | ||||
|       labels: | ||||
|         app: productcatalogue | ||||
|     spec: | ||||
|       containers: | ||||
|       - name: productcatalogue | ||||
|         image: danielbryantuk/djproductcatalogue:latest | ||||
|         ports: | ||||
|         - containerPort: 8020 | ||||
|         livenessProbe: | ||||
|           httpGet: | ||||
|             path: /healthcheck | ||||
|             port: 8025 | ||||
|           initialDelaySeconds: 30 | ||||
|           timeoutSeconds: 1 | ||||
							
								
								
									
										42
									
								
								kubernetes/shopfront-service.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								kubernetes/shopfront-service.yaml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,42 @@ | ||||
| --- | ||||
| apiVersion: v1 | ||||
| kind: Service | ||||
| metadata: | ||||
|   name: shopfront | ||||
|   labels: | ||||
|     app: shopfront | ||||
| spec: | ||||
|   type: NodePort | ||||
|   selector: | ||||
|     app: shopfront | ||||
|   ports: | ||||
|   - protocol: TCP | ||||
|     port: 8010 | ||||
|     name: http | ||||
| 
 | ||||
| --- | ||||
| apiVersion: apps/v1 | ||||
| kind: Deployment | ||||
| metadata: | ||||
|   name: shopfront | ||||
| spec: | ||||
|   selector: | ||||
|     matchLabels: | ||||
|       app: shopfront | ||||
|   replicas: 1 | ||||
|   template: | ||||
|     metadata: | ||||
|       labels: | ||||
|         app: shopfront | ||||
|     spec: | ||||
|       containers: | ||||
|       - name: djshopfront | ||||
|         image: danielbryantuk/djshopfront:latest | ||||
|         ports: | ||||
|         - containerPort: 8010 | ||||
|         livenessProbe: | ||||
|           httpGet: | ||||
|             path: /health | ||||
|             port: 8010 | ||||
|           initialDelaySeconds: 30 | ||||
|           timeoutSeconds: 1 | ||||
							
								
								
									
										43
									
								
								kubernetes/stockmanager-service.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								kubernetes/stockmanager-service.yaml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,43 @@ | ||||
| --- | ||||
| apiVersion: v1 | ||||
| kind: Service | ||||
| metadata: | ||||
|   name: stockmanager | ||||
|   labels: | ||||
|     app: stockmanager | ||||
| spec: | ||||
|   type: NodePort | ||||
|   selector: | ||||
|     app: stockmanager | ||||
|   ports: | ||||
|   - protocol: TCP | ||||
|     port: 8030 | ||||
|     name: http | ||||
| 
 | ||||
| --- | ||||
| apiVersion: apps/v1 | ||||
| kind: Deployment | ||||
| metadata: | ||||
|   name: stockmanager | ||||
| spec: | ||||
|   spec: | ||||
|   selector: | ||||
|     matchLabels: | ||||
|       app: stockmanager | ||||
|   replicas: 1 | ||||
|   template: | ||||
|     metadata: | ||||
|       labels: | ||||
|         app: stockmanager | ||||
|     spec: | ||||
|       containers: | ||||
|       - name: stockmanager | ||||
|         image: danielbryantuk/djstockmanager:latest | ||||
|         ports: | ||||
|         - containerPort: 8030 | ||||
|         livenessProbe: | ||||
|           httpGet: | ||||
|             path: /health | ||||
|             port: 8030 | ||||
|           initialDelaySeconds: 30 | ||||
|           timeoutSeconds: 1 | ||||
							
								
								
									
										5
									
								
								productcatalogue/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								productcatalogue/Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| FROM openjdk:8-jre | ||||
| ADD target/productcatalogue-0.0.1-SNAPSHOT.jar app.jar | ||||
| ADD product-catalogue.yml app-config.yml | ||||
| EXPOSE 8020 | ||||
| ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","app.jar", "server", "app-config.yml"] | ||||
							
								
								
									
										9
									
								
								productcatalogue/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								productcatalogue/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| product-catalogue | ||||
| ================= | ||||
| 
 | ||||
| java -jar target/product-1.0-SNAPSHOT.jar server product-catalogue.yml | ||||
| 
 | ||||
| docker build -t danielbryantuk/product . | ||||
| docker run -p 9010:9010 -p 9011:9011 -d danielbryantuk/product | ||||
| 
 | ||||
| Update | ||||
							
								
								
									
										79
									
								
								productcatalogue/pom.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								productcatalogue/pom.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,79 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <project xmlns="http://maven.apache.org/POM/4.0.0" | ||||
|          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||
|          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||||
|     <modelVersion>4.0.0</modelVersion> | ||||
| 
 | ||||
|     <groupId>uk.co.danielbryant.djshopping</groupId> | ||||
|     <artifactId>productcatalogue</artifactId> | ||||
|     <version>0.0.1-SNAPSHOT</version> | ||||
| 
 | ||||
|     <properties> | ||||
|         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||||
|         <dropwizard.version>1.3.27</dropwizard.version> | ||||
|         <guice.version>4.2.3</guice.version> | ||||
|     </properties> | ||||
| 
 | ||||
|     <dependencies> | ||||
|         <dependency> | ||||
|             <groupId>io.dropwizard</groupId> | ||||
|             <artifactId>dropwizard-core</artifactId> | ||||
|             <version>${dropwizard.version}</version> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>com.google.inject</groupId> | ||||
|             <artifactId>guice</artifactId> | ||||
|             <version>${guice.version}</version> | ||||
|         </dependency> | ||||
|     </dependencies> | ||||
| 
 | ||||
| 
 | ||||
|     <build> | ||||
|         <plugins> | ||||
|             <plugin> | ||||
|                 <groupId>org.apache.maven.plugins</groupId> | ||||
|                 <artifactId>maven-compiler-plugin</artifactId> | ||||
|                 <configuration> | ||||
|                     <source>1.8</source> | ||||
|                     <target>1.8</target> | ||||
|                 </configuration> | ||||
|             </plugin> | ||||
|             <plugin> | ||||
|                 <groupId>org.apache.maven.plugins</groupId> | ||||
|                 <artifactId>maven-shade-plugin</artifactId> | ||||
|                 <version>1.6</version> | ||||
|                 <configuration> | ||||
|                     <createDependencyReducedPom>true</createDependencyReducedPom> | ||||
|                     <filters> | ||||
|                         <filter> | ||||
|                             <artifact>*:*</artifact> | ||||
|                             <excludes> | ||||
|                                 <exclude>META-INF/*.SF</exclude> | ||||
|                                 <exclude>META-INF/*.DSA</exclude> | ||||
|                                 <exclude>META-INF/*.RSA</exclude> | ||||
|                             </excludes> | ||||
|                         </filter> | ||||
|                     </filters> | ||||
|                 </configuration> | ||||
|                 <executions> | ||||
|                     <execution> | ||||
|                         <phase>package</phase> | ||||
|                         <goals> | ||||
|                             <goal>shade</goal> | ||||
|                         </goals> | ||||
|                         <configuration> | ||||
|                             <transformers> | ||||
|                                 <transformer | ||||
|                                         implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> | ||||
|                                 <transformer | ||||
|                                         implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> | ||||
|                                     <mainClass>uk.co.danielbryant.djshopping.productcatalogue.ProductServiceApplication</mainClass> | ||||
|                                 </transformer> | ||||
|                             </transformers> | ||||
|                         </configuration> | ||||
|                     </execution> | ||||
|                 </executions> | ||||
|             </plugin> | ||||
|         </plugins> | ||||
|     </build> | ||||
| </project> | ||||
							
								
								
									
										10
									
								
								productcatalogue/product-catalogue.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								productcatalogue/product-catalogue.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| version: 1.0-SNAPSHOT | ||||
|   | ||||
| 
 | ||||
| server: | ||||
|   applicationConnectors: | ||||
|   - type: http | ||||
|     port: 8020 | ||||
|   adminConnectors: | ||||
|   - type: http | ||||
|     port: 8025 | ||||
| @ -0,0 +1,36 @@ | ||||
| package uk.co.danielbryant.djshopping.productcatalogue; | ||||
| 
 | ||||
| import com.google.inject.Guice; | ||||
| import com.google.inject.Injector; | ||||
| import io.dropwizard.Application; | ||||
| import io.dropwizard.setup.Bootstrap; | ||||
| import io.dropwizard.setup.Environment; | ||||
| import uk.co.danielbryant.djshopping.productcatalogue.healthchecks.BasicHealthCheck; | ||||
| import uk.co.danielbryant.djshopping.productcatalogue.configuration.ProductServiceConfiguration; | ||||
| import uk.co.danielbryant.djshopping.productcatalogue.resources.ProductResource; | ||||
| 
 | ||||
| public class ProductServiceApplication extends Application<ProductServiceConfiguration> { | ||||
|     public static void main(String[] args) throws Exception { | ||||
|         new ProductServiceApplication().run(args); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String getName() { | ||||
|         return "product-list-service"; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void initialize(Bootstrap<ProductServiceConfiguration> bootstrap) { | ||||
|         // nothing to do yet | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void run(ProductServiceConfiguration config, | ||||
|                     Environment environment) { | ||||
|         final BasicHealthCheck healthCheck = new BasicHealthCheck(config.getVersion()); | ||||
|         environment.healthChecks().register("template", healthCheck); | ||||
| 
 | ||||
|         Injector injector = Guice.createInjector(); | ||||
|         environment.jersey().register(injector.getInstance(ProductResource.class)); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,21 @@ | ||||
| package uk.co.danielbryant.djshopping.productcatalogue.configuration; | ||||
| 
 | ||||
| import com.fasterxml.jackson.annotation.JsonProperty; | ||||
| import io.dropwizard.Configuration; | ||||
| import org.hibernate.validator.constraints.NotEmpty; | ||||
| 
 | ||||
| public class ProductServiceConfiguration extends Configuration { | ||||
| 
 | ||||
|     @NotEmpty | ||||
|     private String version; | ||||
| 
 | ||||
|     @JsonProperty | ||||
|     public String getVersion() { | ||||
|         return version; | ||||
|     } | ||||
| 
 | ||||
|     @JsonProperty | ||||
|     public void setVersion(String version) { | ||||
|         this.version = version; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,17 @@ | ||||
| package uk.co.danielbryant.djshopping.productcatalogue.healthchecks; | ||||
| 
 | ||||
| import com.codahale.metrics.health.HealthCheck; | ||||
| 
 | ||||
| public class BasicHealthCheck extends HealthCheck { | ||||
| 
 | ||||
|     private final String version; | ||||
| 
 | ||||
|     public BasicHealthCheck(String version) { | ||||
|         this.version = version; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected Result check() throws Exception { | ||||
|         return Result.healthy("Ok with version: " + version); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,43 @@ | ||||
| package uk.co.danielbryant.djshopping.productcatalogue.model; | ||||
| 
 | ||||
| import com.fasterxml.jackson.annotation.JsonProperty; | ||||
| 
 | ||||
| import java.math.BigDecimal; | ||||
| 
 | ||||
| public class Product { | ||||
|     private String id; | ||||
|     private String name; | ||||
|     private String description; | ||||
|     private BigDecimal price; | ||||
| 
 | ||||
|     public Product() { | ||||
|         // Needed for Jackson deserialization | ||||
|     } | ||||
| 
 | ||||
|     public Product(String id, String name, String description, BigDecimal price) { | ||||
|         this.id = id; | ||||
|         this.name = name; | ||||
|         this.description = description; | ||||
|         this.price = price; | ||||
|     } | ||||
| 
 | ||||
|     @JsonProperty | ||||
|     public String getId() { | ||||
|         return id; | ||||
|     } | ||||
| 
 | ||||
|     @JsonProperty | ||||
|     public String getName() { | ||||
|         return name; | ||||
|     } | ||||
| 
 | ||||
|     @JsonProperty | ||||
|     public String getDescription() { | ||||
|         return description; | ||||
|     } | ||||
| 
 | ||||
|     @JsonProperty | ||||
|     public BigDecimal getPrice() { | ||||
|         return price; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,50 @@ | ||||
| package uk.co.danielbryant.djshopping.productcatalogue.resources; | ||||
| 
 | ||||
| import com.codahale.metrics.annotation.Timed; | ||||
| import com.google.inject.Inject; | ||||
| import uk.co.danielbryant.djshopping.productcatalogue.services.ProductService; | ||||
| import uk.co.danielbryant.djshopping.productcatalogue.model.Product; | ||||
| 
 | ||||
| import javax.ws.rs.GET; | ||||
| import javax.ws.rs.Path; | ||||
| import javax.ws.rs.PathParam; | ||||
| import javax.ws.rs.Produces; | ||||
| import javax.ws.rs.core.MediaType; | ||||
| import javax.ws.rs.core.Response; | ||||
| import java.util.Optional; | ||||
| 
 | ||||
| @Path("/products") | ||||
| @Produces(MediaType.APPLICATION_JSON) | ||||
| public class ProductResource { | ||||
| 
 | ||||
|     private ProductService productService; | ||||
| 
 | ||||
|     @Inject | ||||
|     public ProductResource(ProductService productService) { | ||||
|         this.productService = productService; | ||||
|     } | ||||
| 
 | ||||
|     @GET | ||||
|     @Timed | ||||
|     public Response getAllProducts() { | ||||
|         return Response.status(200) | ||||
|                 .entity(productService.getAllProducts()) | ||||
|                 .build(); | ||||
|     } | ||||
| 
 | ||||
|     @GET | ||||
|     @Timed | ||||
|     @Path("{id}") | ||||
|     public Response getProduct(@PathParam("id") String id) { | ||||
|         Optional<Product> result = productService.getProduct(id); | ||||
| 
 | ||||
|         if (result.isPresent()) { | ||||
|             return Response.status(Response.Status.OK) | ||||
|                     .entity(result.get()) | ||||
|                     .build(); | ||||
|         } else { | ||||
|             return Response.status(Response.Status.NOT_FOUND) | ||||
|                     .build(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,28 @@ | ||||
| package uk.co.danielbryant.djshopping.productcatalogue.services; | ||||
| 
 | ||||
| import uk.co.danielbryant.djshopping.productcatalogue.model.Product; | ||||
| 
 | ||||
| import java.math.BigDecimal; | ||||
| import java.util.*; | ||||
| 
 | ||||
| public class ProductService { | ||||
| 
 | ||||
|     //{productId, Product} | ||||
|     private Map<String, Product> fakeProductDAO = new HashMap<>(); | ||||
| 
 | ||||
|     public ProductService() { | ||||
|         fakeProductDAO.put("1", new Product("1", "Widget", "Premium ACME Widgets", new BigDecimal(1.20))); | ||||
|         fakeProductDAO.put("2", new Product("2", "Sprocket", "Grade B sprockets", new BigDecimal(4.10))); | ||||
|         fakeProductDAO.put("3", new Product("3", "Anvil", "Large Anvils", new BigDecimal(45.50))); | ||||
|         fakeProductDAO.put("4", new Product("4", "Cogs", "Grade Y cogs", new BigDecimal(1.80))); | ||||
|         fakeProductDAO.put("5", new Product("5", "Multitool", "Multitools", new BigDecimal(154.10))); | ||||
|     } | ||||
| 
 | ||||
|     public List<Product> getAllProducts() { | ||||
|         return new ArrayList<>(fakeProductDAO.values()); | ||||
|     } | ||||
| 
 | ||||
|     public Optional<Product> getProduct(String id) { | ||||
|         return Optional.ofNullable(fakeProductDAO.get(id)); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										4
									
								
								shopfront/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								shopfront/Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,4 @@ | ||||
| FROM openjdk:8-jre | ||||
| ADD target/shopfront-0.0.1-SNAPSHOT.jar app.jar | ||||
| EXPOSE 8010 | ||||
| ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] | ||||
							
								
								
									
										76
									
								
								shopfront/pom.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								shopfront/pom.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,76 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <project xmlns="http://maven.apache.org/POM/4.0.0" | ||||
|     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||||
|     <modelVersion>4.0.0</modelVersion> | ||||
| 
 | ||||
|     <groupId>uk.co.danielbryant.djshopping</groupId> | ||||
|     <artifactId>shopfront</artifactId> | ||||
|     <version>0.0.1-SNAPSHOT</version> | ||||
|     <packaging>jar</packaging> | ||||
| 
 | ||||
|     <name>shopfront</name> | ||||
|     <description>Docker Java application Shopfront</description> | ||||
| 
 | ||||
|     <parent> | ||||
|         <groupId>org.springframework.boot</groupId> | ||||
|         <artifactId>spring-boot-starter-parent</artifactId> | ||||
|         <version>1.5.22.RELEASE</version> | ||||
|     </parent> | ||||
| 
 | ||||
|     <properties> | ||||
|         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||||
|         <java.version>1.8</java.version> | ||||
|     </properties> | ||||
| 
 | ||||
|     <dependencyManagement> | ||||
|         <dependencies> | ||||
|             <dependency> | ||||
|                 <groupId>org.springframework.cloud</groupId> | ||||
|                 <artifactId>spring-cloud-dependencies</artifactId> | ||||
|                 <version>Dalston.SR5</version> | ||||
|                 <type>pom</type> | ||||
|                 <scope>import</scope> | ||||
|             </dependency> | ||||
|         </dependencies> | ||||
|     </dependencyManagement> | ||||
| 
 | ||||
|     <dependencies> | ||||
|         <dependency> | ||||
|             <groupId>org.springframework.boot</groupId> | ||||
|             <artifactId>spring-boot-starter-thymeleaf</artifactId> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.springframework.boot</groupId> | ||||
|             <artifactId>spring-boot-starter-actuator</artifactId> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.springframework.cloud</groupId> | ||||
|             <artifactId>spring-cloud-starter-hystrix</artifactId> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.springframework.cloud</groupId> | ||||
|             <artifactId>spring-cloud-starter-eureka</artifactId> | ||||
|         </dependency> | ||||
|         <!-- Test --> | ||||
|         <dependency> | ||||
|             <groupId>org.springframework.boot</groupId> | ||||
|             <artifactId>spring-boot-starter-test</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|     </dependencies> | ||||
| 
 | ||||
|     <build> | ||||
|         <plugins> | ||||
|             <plugin> | ||||
|                 <groupId>org.springframework.boot</groupId> | ||||
|                 <artifactId>spring-boot-maven-plugin</artifactId> | ||||
|             </plugin> | ||||
| 
 | ||||
|             <plugin> | ||||
|                 <groupId>org.codehaus.mojo</groupId> | ||||
|                 <artifactId>versions-maven-plugin</artifactId> | ||||
|             </plugin> | ||||
|         </plugins> | ||||
| 
 | ||||
|     </build> | ||||
| </project> | ||||
| @ -0,0 +1,21 @@ | ||||
| package uk.co.danielbryant.djshopping.shopfront; | ||||
| 
 | ||||
| import org.springframework.boot.SpringApplication; | ||||
| import org.springframework.boot.autoconfigure.SpringBootApplication; | ||||
| import org.springframework.cloud.netflix.hystrix.EnableHystrix; | ||||
| import org.springframework.context.annotation.Bean; | ||||
| import org.springframework.web.client.RestTemplate; | ||||
| 
 | ||||
| @SpringBootApplication | ||||
| @EnableHystrix | ||||
| public class ShopfrontApplication { | ||||
| 
 | ||||
|     public static void main(String[] args) { | ||||
|         SpringApplication.run(ShopfrontApplication.class, args); | ||||
|     } | ||||
| 
 | ||||
|     @Bean(name = "stdRestTemplate") | ||||
|     public RestTemplate getRestTemplate() { | ||||
|         return new RestTemplate(); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,20 @@ | ||||
| package uk.co.danielbryant.djshopping.shopfront.controllers; | ||||
| 
 | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.stereotype.Controller; | ||||
| import org.springframework.ui.Model; | ||||
| import org.springframework.web.bind.annotation.RequestMapping; | ||||
| import uk.co.danielbryant.djshopping.shopfront.services.ProductService; | ||||
| 
 | ||||
| @Controller | ||||
| public class HomeController { | ||||
| 
 | ||||
|     @Autowired | ||||
|     private ProductService productService; | ||||
| 
 | ||||
|     @RequestMapping("/") | ||||
|     public String index(Model model) { | ||||
|         model.addAttribute("products", productService.getProducts()); | ||||
|         return "index"; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,52 @@ | ||||
| package uk.co.danielbryant.djshopping.shopfront.model; | ||||
| 
 | ||||
| import java.math.BigDecimal; | ||||
| 
 | ||||
| public class Product { | ||||
|     private String id; | ||||
|     private String sku; | ||||
|     private String name; | ||||
|     private String description; | ||||
|     private BigDecimal price; | ||||
|     private int amountAvailable; | ||||
| 
 | ||||
|     public Product(String id, String name, String description, BigDecimal price) { | ||||
|         this.id = id; | ||||
|         this.name = name; | ||||
|         this.description = description; | ||||
|         this.price = price; | ||||
|     } | ||||
| 
 | ||||
|     public Product(String id, String sku, String name, String description, BigDecimal price, int amountAvailable) { | ||||
|         this.id = id; | ||||
|         this.sku = sku; | ||||
|         this.name = name; | ||||
|         this.description = description; | ||||
|         this.price = price; | ||||
|         this.amountAvailable = amountAvailable; | ||||
|     } | ||||
| 
 | ||||
|     public String getId() { | ||||
|         return id; | ||||
|     } | ||||
| 
 | ||||
|     public String getSku() { | ||||
|         return sku; | ||||
|     } | ||||
| 
 | ||||
|     public String getName() { | ||||
|         return name; | ||||
|     } | ||||
| 
 | ||||
|     public String getDescription() { | ||||
|         return description; | ||||
|     } | ||||
| 
 | ||||
|     public BigDecimal getPrice() { | ||||
|         return price; | ||||
|     } | ||||
| 
 | ||||
|     public int getAmountAvailable() { | ||||
|         return amountAvailable; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,39 @@ | ||||
| package uk.co.danielbryant.djshopping.shopfront.repo; | ||||
| 
 | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.beans.factory.annotation.Qualifier; | ||||
| import org.springframework.beans.factory.annotation.Value; | ||||
| import org.springframework.core.ParameterizedTypeReference; | ||||
| import org.springframework.http.HttpMethod; | ||||
| import org.springframework.http.ResponseEntity; | ||||
| import org.springframework.stereotype.Component; | ||||
| import org.springframework.web.client.RestTemplate; | ||||
| import uk.co.danielbryant.djshopping.shopfront.services.dto.ProductDTO; | ||||
| 
 | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.function.Function; | ||||
| import java.util.stream.Collectors; | ||||
| 
 | ||||
| @Component | ||||
| public class ProductRepo { | ||||
| 
 | ||||
|     @Value("${productCatalogueUri}") | ||||
|     private String productCatalogueUri; | ||||
| 
 | ||||
|     @Autowired | ||||
|     @Qualifier(value = "stdRestTemplate") | ||||
|     private RestTemplate restTemplate; | ||||
| 
 | ||||
| 
 | ||||
|     public Map<String, ProductDTO> getProductDTOs() { | ||||
|         ResponseEntity<List<ProductDTO>> productCatalogueResponse = | ||||
|                 restTemplate.exchange(productCatalogueUri + "/products", | ||||
|                         HttpMethod.GET, null, new ParameterizedTypeReference<List<ProductDTO>>() { | ||||
|                         }); | ||||
|         List<ProductDTO> productDTOs = productCatalogueResponse.getBody(); | ||||
| 
 | ||||
|         return productDTOs.stream() | ||||
|                 .collect(Collectors.toMap(ProductDTO::getId, Function.identity())); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,51 @@ | ||||
| package uk.co.danielbryant.djshopping.shopfront.repo; | ||||
| 
 | ||||
| import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.beans.factory.annotation.Qualifier; | ||||
| import org.springframework.beans.factory.annotation.Value; | ||||
| import org.springframework.core.ParameterizedTypeReference; | ||||
| import org.springframework.http.HttpMethod; | ||||
| import org.springframework.http.ResponseEntity; | ||||
| import org.springframework.stereotype.Component; | ||||
| import org.springframework.web.client.RestTemplate; | ||||
| import uk.co.danielbryant.djshopping.shopfront.services.dto.StockDTO; | ||||
| 
 | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.function.Function; | ||||
| import java.util.stream.Collectors; | ||||
| 
 | ||||
| @Component | ||||
| public class StockRepo { | ||||
| 
 | ||||
|     private static final Logger LOGGER = LoggerFactory.getLogger(StockRepo.class); | ||||
| 
 | ||||
|     @Value("${stockManagerUri}") | ||||
|     private String stockManagerUri; | ||||
| 
 | ||||
|     @Autowired | ||||
|     @Qualifier(value = "stdRestTemplate") | ||||
|     private RestTemplate restTemplate; | ||||
| 
 | ||||
|     @HystrixCommand(fallbackMethod = "stocksNotFound") // Hystrix circuit breaker for fault-tolernace demo | ||||
|     public Map<String, StockDTO> getStockDTOs() { | ||||
|         LOGGER.info("getStocksDTOs"); | ||||
|         ResponseEntity<List<StockDTO>> stockManagerResponse = | ||||
|                 restTemplate.exchange(stockManagerUri + "/stocks", | ||||
|                         HttpMethod.GET, null, new ParameterizedTypeReference<List<StockDTO>>() { | ||||
|                         }); | ||||
|         List<StockDTO> stockDTOs = stockManagerResponse.getBody(); | ||||
| 
 | ||||
|         return stockDTOs.stream() | ||||
|                 .collect(Collectors.toMap(StockDTO::getProductId, Function.identity())); | ||||
|     } | ||||
| 
 | ||||
|     public Map<String, StockDTO> stocksNotFound() { | ||||
|         LOGGER.info("stocksNotFound *** FALLBACK ***"); | ||||
|         return Collections.EMPTY_MAP; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,22 @@ | ||||
| package uk.co.danielbryant.djshopping.shopfront.resources; | ||||
| 
 | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.web.bind.annotation.RequestMapping; | ||||
| import org.springframework.web.bind.annotation.RestController; | ||||
| import uk.co.danielbryant.djshopping.shopfront.model.Product; | ||||
| import uk.co.danielbryant.djshopping.shopfront.services.ProductService; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| @RestController | ||||
| @RequestMapping("/products") | ||||
| public class ProductResource { | ||||
| 
 | ||||
|     @Autowired | ||||
|     private ProductService productService; | ||||
| 
 | ||||
|     @RequestMapping() | ||||
|     public List<Product> getProducts() { | ||||
|         return productService.getProducts(); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,45 @@ | ||||
| package uk.co.danielbryant.djshopping.shopfront.services; | ||||
| 
 | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.stereotype.Service; | ||||
| import uk.co.danielbryant.djshopping.shopfront.model.Product; | ||||
| import uk.co.danielbryant.djshopping.shopfront.repo.StockRepo; | ||||
| import uk.co.danielbryant.djshopping.shopfront.repo.ProductRepo; | ||||
| import uk.co.danielbryant.djshopping.shopfront.services.dto.ProductDTO; | ||||
| import uk.co.danielbryant.djshopping.shopfront.services.dto.StockDTO; | ||||
| 
 | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.stream.Collectors; | ||||
| 
 | ||||
| @Service | ||||
| public class ProductService { | ||||
| 
 | ||||
|     @Autowired | ||||
|     private StockRepo stockRepo; | ||||
| 
 | ||||
|     @Autowired | ||||
|     private ProductRepo productRepo; | ||||
| 
 | ||||
| 
 | ||||
|     public List<Product> getProducts() { | ||||
|         Map<String, ProductDTO> productDTOs = productRepo.getProductDTOs(); | ||||
|         Map<String, StockDTO> stockDTOMap = stockRepo.getStockDTOs(); | ||||
| 
 | ||||
|         // Merge productDTOs and stockDTOs to a List of Products | ||||
|         return productDTOs.values().stream() | ||||
|                 .map(productDTO -> { | ||||
|                     StockDTO stockDTO = stockDTOMap.get(productDTO.getId()); | ||||
|                     if (stockDTO == null) { | ||||
|                         stockDTO = StockDTO.DEFAULT_STOCK_DTO; | ||||
|                     } | ||||
|                     return new Product(productDTO.getId(), stockDTO.getSku(), productDTO.getName(), productDTO.getDescription(), productDTO.getPrice(), stockDTO.getAmountAvailable()); | ||||
|                 }) | ||||
|                 .collect(Collectors.toList()); | ||||
|     } | ||||
| 
 | ||||
|     public List<Product> productsNotFound() { | ||||
|         return Collections.EMPTY_LIST; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,36 @@ | ||||
| package uk.co.danielbryant.djshopping.shopfront.services.dto; | ||||
| 
 | ||||
| import java.math.BigDecimal; | ||||
| 
 | ||||
| public class ProductDTO { | ||||
|     private String id; | ||||
|     private String name; | ||||
|     private String description; | ||||
|     private BigDecimal price; | ||||
| 
 | ||||
|     public ProductDTO() { | ||||
|     } | ||||
| 
 | ||||
|     public ProductDTO(String id, String name, String description, BigDecimal price) { | ||||
|         this.id = id; | ||||
|         this.name = name; | ||||
|         this.description = description; | ||||
|         this.price = price; | ||||
|     } | ||||
| 
 | ||||
|     public String getId() { | ||||
|         return id; | ||||
|     } | ||||
| 
 | ||||
|     public String getName() { | ||||
|         return name; | ||||
|     } | ||||
| 
 | ||||
|     public String getDescription() { | ||||
|         return description; | ||||
|     } | ||||
| 
 | ||||
|     public BigDecimal getPrice() { | ||||
|         return price; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,30 @@ | ||||
| package uk.co.danielbryant.djshopping.shopfront.services.dto; | ||||
| 
 | ||||
| public class StockDTO { | ||||
|     private String productId; | ||||
|     private String sku; | ||||
|     private int amountAvailable; | ||||
| 
 | ||||
|     public static final StockDTO DEFAULT_STOCK_DTO = new StockDTO("", "default", 999); | ||||
| 
 | ||||
|     public StockDTO() { | ||||
|     } | ||||
| 
 | ||||
|     public StockDTO(String productId, String sku, int amountAvailable) { | ||||
|         this.productId = productId; | ||||
|         this.sku = sku; | ||||
|         this.amountAvailable = amountAvailable; | ||||
|     } | ||||
| 
 | ||||
|     public String getProductId() { | ||||
|         return productId; | ||||
|     } | ||||
| 
 | ||||
|     public String getSku() { | ||||
|         return sku; | ||||
|     } | ||||
| 
 | ||||
|     public int getAmountAvailable() { | ||||
|         return amountAvailable; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										3
									
								
								shopfront/src/main/resources/application.properties
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								shopfront/src/main/resources/application.properties
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| server.port = 8010 | ||||
| productCatalogueUri = http://productcatalogue:8020 | ||||
| stockManagerUri = http://stockmanager:8030 | ||||
							
								
								
									
										90
									
								
								shopfront/src/main/resources/templates/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								shopfront/src/main/resources/templates/index.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,90 @@ | ||||
| <!DOCTYPE html> | ||||
| <html lang="en" | ||||
|       xmlns="http://www.w3.org/1999/xhtml" | ||||
|       xmlns:th="http://www.thymeleaf.org"> | ||||
| <head> | ||||
|     <meta charset="utf-8"/> | ||||
|     <meta http-equiv="X-UA-Compatible" content="IE=edge"/> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1"/> | ||||
|     <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags --> | ||||
| 
 | ||||
|     <title>Welcome to the Docker Java Shopfront!</title> | ||||
|     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | ||||
|     <!-- Latest compiled and minified CSS --> | ||||
|     <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" | ||||
|           integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"/> | ||||
| 
 | ||||
|     <!-- Optional theme --> | ||||
|     <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" | ||||
|           integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"/> | ||||
| 
 | ||||
|     <!-- Latest compiled and minified JavaScript --> | ||||
|     <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" | ||||
|             integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" | ||||
|             crossorigin="anonymous"></script> | ||||
| </head> | ||||
| <body> | ||||
| <nav class="navbar navbar-inverse navbar-fixed-top"> | ||||
|     <div class="container-fluid" style="background-color: #ff203b"> | ||||
|         <div class="navbar-header"> | ||||
|             <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" | ||||
|                     aria-expanded="false" aria-controls="navbar"> | ||||
|                 <span class="sr-only">Toggle navigation</span> | ||||
|                 <span class="icon-bar"></span> | ||||
|                 <span class="icon-bar"></span> | ||||
|                 <span class="icon-bar"></span> | ||||
|             </button> | ||||
|             <a class="navbar-brand" href="#">Docker Java Shopfront</a> | ||||
|         </div> | ||||
|         <div id="navbar" class="navbar-collapse collapse"> | ||||
|             <ul class="nav navbar-nav navbar-right"> | ||||
|                 <li><a href="#">Help</a></li> | ||||
|             </ul> | ||||
|         </div> | ||||
|     </div> | ||||
| </nav> | ||||
| 
 | ||||
| <div class="container-fluid"> | ||||
|     <div class="row"> | ||||
|         <div class="col-sm-3 col-md-2 sidebar"> | ||||
|             <ul class="nav nav-sidebar"> | ||||
|                 <li class="active"><a href="#">Overview <span class="sr-only">(current)</span></a></li> | ||||
|             </ul> | ||||
|         </div> | ||||
|         <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"> | ||||
|             <h1 class="page-header">Welcome to the Docker Java Shopfront!</h1> | ||||
|             <h2 class="sub-header">Please select a product!</h2> | ||||
|             <div class="table-responsive"> | ||||
| 
 | ||||
|                 <table class="table table-striped" id="product-table"> | ||||
|                     <thead> | ||||
|                     <tr> | ||||
|                         <th>Product Num</th> | ||||
|                         <th>SKU</th> | ||||
|                         <th>Name</th> | ||||
|                         <th>Description</th> | ||||
|                         <th>Price £</th> | ||||
|                         <th>Qty Available</th> | ||||
|                     </tr> | ||||
|                     </thead> | ||||
|                     <tbody> | ||||
|                     <tr th:each="product : ${products}"> | ||||
|                         <td th:text="${product.id}">1</td> | ||||
|                         <td th:text="${product.sku}">12345678</td> | ||||
|                         <td th:text="${product.name}">Widget</td> | ||||
|                         <td th:text="${product.description}">Widget</td> | ||||
|                         <td th:text="${#numbers.formatDecimal(product.price, 0, 'COMMA', 2, 'POINT')}">1.19</td> | ||||
|                         <td th:text="${product.amountAvailable}">2</td> | ||||
|                     </tr> | ||||
|                     </tbody> | ||||
|                 </table> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
| <!-- jQuery (necessary for Bootstrap's JavaScript plugins) --> | ||||
| <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> | ||||
| <!-- Include all compiled plugins (below), or include individual files as needed --> | ||||
| <script src="js/bootstrap.min.js"></script> | ||||
| </body> | ||||
| </html> | ||||
| @ -0,0 +1,16 @@ | ||||
| package uk.co.danielbryant.djshopping.shopfront; | ||||
| 
 | ||||
| import org.junit.Test; | ||||
| import org.junit.runner.RunWith; | ||||
| import org.springframework.boot.test.context.SpringBootTest; | ||||
| import org.springframework.test.context.junit4.SpringRunner; | ||||
| 
 | ||||
| @RunWith(SpringRunner.class) | ||||
| @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = ShopfrontApplication.class) | ||||
| public class ShopfrontApplicationTests { | ||||
| 
 | ||||
|     @Test | ||||
|     public void contextLoads() { | ||||
|     } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										4
									
								
								stockmanager/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								stockmanager/Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,4 @@ | ||||
| FROM openjdk:8-jre | ||||
| ADD target/stockmanager-0.0.1-SNAPSHOT.jar app.jar | ||||
| EXPOSE 8030 | ||||
| ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] | ||||
							
								
								
									
										85
									
								
								stockmanager/pom.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								stockmanager/pom.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,85 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||
|          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||||
|     <modelVersion>4.0.0</modelVersion> | ||||
| 
 | ||||
|     <groupId>uk.co.danielbryant.djshopping</groupId> | ||||
|     <artifactId>stockmanager</artifactId> | ||||
|     <version>0.0.1-SNAPSHOT</version> | ||||
|     <packaging>jar</packaging> | ||||
| 
 | ||||
|     <name>stockmanager</name> | ||||
|     <description>Docker Java application stock manager</description> | ||||
| 
 | ||||
|     <parent> | ||||
|         <groupId>org.springframework.boot</groupId> | ||||
|         <artifactId>spring-boot-starter-parent</artifactId> | ||||
|         <version>2.3.7.RELEASE</version> | ||||
|     </parent> | ||||
| 
 | ||||
|     <properties> | ||||
|         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||||
|         <java.version>1.8</java.version> | ||||
|         <cucumber.version>1.2.6</cucumber.version> | ||||
|         <hamcrest-core.version>2.2</hamcrest-core.version> | ||||
|     </properties> | ||||
| 
 | ||||
|     <dependencies> | ||||
|         <dependency> | ||||
|             <groupId>org.springframework.boot</groupId> | ||||
|             <artifactId>spring-boot-starter-web</artifactId> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.springframework.boot</groupId> | ||||
|             <artifactId>spring-boot-starter-data-jpa</artifactId> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>com.h2database</groupId> | ||||
|             <artifactId>h2</artifactId> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.springframework.boot</groupId> | ||||
|             <artifactId>spring-boot-starter-actuator</artifactId> | ||||
|         </dependency> | ||||
|         <!-- Test --> | ||||
|         <dependency> | ||||
|             <groupId>org.springframework.boot</groupId> | ||||
|             <artifactId>spring-boot-starter-test</artifactId> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.hamcrest</groupId> | ||||
|             <artifactId>hamcrest-core</artifactId> | ||||
|             <version>${hamcrest-core.version}</version> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>info.cukes</groupId> | ||||
|             <artifactId>cucumber-java</artifactId> | ||||
|             <version>${cucumber.version}</version> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>info.cukes</groupId> | ||||
|             <artifactId>cucumber-junit</artifactId> | ||||
|             <version>${cucumber.version}</version> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>info.cukes</groupId> | ||||
|             <artifactId>cucumber-spring</artifactId> | ||||
|             <version>${cucumber.version}</version> | ||||
|         </dependency> | ||||
|     </dependencies> | ||||
| 
 | ||||
|     <build> | ||||
|         <plugins> | ||||
|             <plugin> | ||||
|                 <groupId>org.springframework.boot</groupId> | ||||
|                 <artifactId>spring-boot-maven-plugin</artifactId> | ||||
|             </plugin> | ||||
|             <plugin> | ||||
|                 <groupId>org.codehaus.mojo</groupId> | ||||
|                 <artifactId>versions-maven-plugin</artifactId> | ||||
|                 <version>2.7</version> | ||||
|             </plugin> | ||||
|         </plugins> | ||||
|     </build> | ||||
| </project> | ||||
| @ -0,0 +1,12 @@ | ||||
| package uk.co.danielbryant.djshopping.stockmanager; | ||||
| 
 | ||||
| import org.springframework.boot.SpringApplication; | ||||
| import org.springframework.boot.autoconfigure.SpringBootApplication; | ||||
| 
 | ||||
| @SpringBootApplication | ||||
| public class StockManagerApplication { | ||||
| 
 | ||||
|     public static void main(String[] args) { | ||||
|         SpringApplication.run(StockManagerApplication.class, args); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,38 @@ | ||||
| package uk.co.danielbryant.djshopping.stockmanager.config; | ||||
| 
 | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.stereotype.Component; | ||||
| import org.springframework.transaction.annotation.Transactional; | ||||
| import uk.co.danielbryant.djshopping.stockmanager.model.Stock; | ||||
| import uk.co.danielbryant.djshopping.stockmanager.repositories.StockRepository; | ||||
| 
 | ||||
| import javax.annotation.PostConstruct; | ||||
| 
 | ||||
| @Component | ||||
| public class DataGenerator { | ||||
| 
 | ||||
|     private static final Logger LOGGER = LoggerFactory.getLogger(DataGenerator.class); | ||||
| 
 | ||||
|     private StockRepository stockRepository; | ||||
| 
 | ||||
|     @Autowired | ||||
|     protected DataGenerator(StockRepository stockRepository) { | ||||
|         this.stockRepository = stockRepository; | ||||
|     } | ||||
| 
 | ||||
|     @PostConstruct | ||||
|     @Transactional | ||||
|     public void init() { | ||||
|         LOGGER.info("Generating synthetic data for demonstration purposes..."); | ||||
| 
 | ||||
|         stockRepository.save(new Stock("1", "12345678", 5)); | ||||
|         stockRepository.save(new Stock("2", "34567890", 2)); | ||||
|         stockRepository.save(new Stock("3", "54326745", 999)); | ||||
|         stockRepository.save(new Stock("4", "93847614", 0)); | ||||
|         stockRepository.save(new Stock("5", "11856388", 1)); | ||||
| 
 | ||||
|         LOGGER.info("... data generation complete"); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,15 @@ | ||||
| package uk.co.danielbryant.djshopping.stockmanager.exceptions; | ||||
| 
 | ||||
| public class StockNotFoundException extends Exception { | ||||
| 
 | ||||
|     public StockNotFoundException() { | ||||
|     } | ||||
| 
 | ||||
|     public StockNotFoundException(String message) { | ||||
|         super(message); | ||||
|     } | ||||
| 
 | ||||
|     public StockNotFoundException(String message, Throwable cause) { | ||||
|         super(message, cause); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,34 @@ | ||||
| package uk.co.danielbryant.djshopping.stockmanager.model; | ||||
| 
 | ||||
| import javax.persistence.Entity; | ||||
| import javax.persistence.Id; | ||||
| 
 | ||||
| @Entity | ||||
| public class Stock { | ||||
| 
 | ||||
|     @Id | ||||
|     private String productId; | ||||
|     private String sku; | ||||
|     private int amountAvailable; | ||||
| 
 | ||||
|     protected Stock() { | ||||
|     } | ||||
| 
 | ||||
|     public Stock(String productId, String sku, int amountAvailable) { | ||||
|         this.productId = productId; | ||||
|         this.sku = sku; | ||||
|         this.amountAvailable = amountAvailable; | ||||
|     } | ||||
| 
 | ||||
|     public String getProductId() { | ||||
|         return productId; | ||||
|     } | ||||
| 
 | ||||
|     public String getSku() { | ||||
|         return sku; | ||||
|     } | ||||
| 
 | ||||
|     public int getAmountAvailable() { | ||||
|         return amountAvailable; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,7 @@ | ||||
| package uk.co.danielbryant.djshopping.stockmanager.repositories; | ||||
| 
 | ||||
| import org.springframework.data.repository.CrudRepository; | ||||
| import uk.co.danielbryant.djshopping.stockmanager.model.Stock; | ||||
| 
 | ||||
| public interface StockRepository extends CrudRepository<Stock, String> { | ||||
| } | ||||
| @ -0,0 +1,39 @@ | ||||
| package uk.co.danielbryant.djshopping.stockmanager.resources; | ||||
| 
 | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.http.HttpStatus; | ||||
| import org.springframework.web.bind.annotation.*; | ||||
| import uk.co.danielbryant.djshopping.stockmanager.exceptions.StockNotFoundException; | ||||
| import uk.co.danielbryant.djshopping.stockmanager.model.Stock; | ||||
| import uk.co.danielbryant.djshopping.stockmanager.services.StockService; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| @RestController | ||||
| @RequestMapping("/stocks") | ||||
| public class StockResource { | ||||
| 
 | ||||
|     private static final Logger LOGGER = LoggerFactory.getLogger(StockResource.class); | ||||
| 
 | ||||
|     @Autowired | ||||
|     private StockService stockService; | ||||
| 
 | ||||
|     @RequestMapping() | ||||
|     public List<Stock> getStocks() { | ||||
|         LOGGER.info("getStocks (All stocks)"); | ||||
|         return stockService.getStocks(); | ||||
|     } | ||||
| 
 | ||||
|     @RequestMapping("{productId}") | ||||
|     public Stock getStock(@PathVariable("productId") String productId) throws StockNotFoundException { | ||||
|         LOGGER.info("getStock with productId: {}", productId); | ||||
|         return stockService.getStock(productId); | ||||
|     } | ||||
| 
 | ||||
|     @ExceptionHandler | ||||
|     @ResponseStatus(HttpStatus.NOT_FOUND) | ||||
|     public void handleStockNotFound(StockNotFoundException snfe) { | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,33 @@ | ||||
| package uk.co.danielbryant.djshopping.stockmanager.services; | ||||
| 
 | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.stereotype.Service; | ||||
| import uk.co.danielbryant.djshopping.stockmanager.exceptions.StockNotFoundException; | ||||
| import uk.co.danielbryant.djshopping.stockmanager.model.Stock; | ||||
| import uk.co.danielbryant.djshopping.stockmanager.repositories.StockRepository; | ||||
| 
 | ||||
| import java.util.List; | ||||
| import java.util.Optional; | ||||
| import java.util.stream.Collectors; | ||||
| import java.util.stream.StreamSupport; | ||||
| 
 | ||||
| @Service | ||||
| public class StockService { | ||||
| 
 | ||||
|     private StockRepository stockRepository; | ||||
| 
 | ||||
|     @Autowired | ||||
|     public StockService(StockRepository stockRepository) { | ||||
|         this.stockRepository = stockRepository; | ||||
|     } | ||||
| 
 | ||||
|     public List<Stock> getStocks() { | ||||
|         return StreamSupport.stream(stockRepository.findAll().spliterator(), false) | ||||
|                 .collect(Collectors.toList()); | ||||
|     } | ||||
| 
 | ||||
|     public Stock getStock(String productId) throws StockNotFoundException { | ||||
|         return stockRepository.findById(productId) | ||||
|                 .orElseThrow(() -> new StockNotFoundException("Stock not found with productId: " + productId)); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										1
									
								
								stockmanager/src/main/resources/application.properties
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								stockmanager/src/main/resources/application.properties
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| server.port = 8030 | ||||
							
								
								
									
										15
									
								
								stockmanager/src/test/java/functional/FunctionalTests.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								stockmanager/src/test/java/functional/FunctionalTests.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| package functional; | ||||
| 
 | ||||
| import cucumber.api.CucumberOptions; | ||||
| import cucumber.api.junit.Cucumber; | ||||
| import org.junit.runner.RunWith; | ||||
| 
 | ||||
| @RunWith(Cucumber.class) | ||||
| @CucumberOptions(monochrome = true, | ||||
|         features = "classpath:features/", | ||||
|         plugin = "html:build/reports/cucumber", | ||||
|         glue = "functional", | ||||
|         strict = true) | ||||
| public class FunctionalTests { | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										52
									
								
								stockmanager/src/test/java/functional/RestStepDefs.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								stockmanager/src/test/java/functional/RestStepDefs.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,52 @@ | ||||
| package functional; | ||||
| 
 | ||||
| import cucumber.api.java.en.Given; | ||||
| import cucumber.api.java.en.Then; | ||||
| import cucumber.api.java.en.When; | ||||
| import org.junit.runner.RunWith; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.boot.test.context.SpringBootTest; | ||||
| import org.springframework.boot.test.web.client.TestRestTemplate; | ||||
| import org.springframework.test.context.ContextConfiguration; | ||||
| import org.springframework.test.context.junit4.SpringRunner; | ||||
| import uk.co.danielbryant.djshopping.stockmanager.StockManagerApplication; | ||||
| import uk.co.danielbryant.djshopping.stockmanager.model.Stock; | ||||
| 
 | ||||
| import java.util.Arrays; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import static org.hamcrest.MatcherAssert.assertThat; | ||||
| import static org.hamcrest.collection.IsCollectionWithSize.hasSize; | ||||
| import static org.hamcrest.core.Is.is; | ||||
| 
 | ||||
| @ContextConfiguration | ||||
| @RunWith(SpringRunner.class) | ||||
| @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = StockManagerApplication.class) | ||||
| public class RestStepDefs { | ||||
| 
 | ||||
|     @Autowired | ||||
|     private TestRestTemplate restTemplate; | ||||
| 
 | ||||
|     private List<Stock> stocks; | ||||
| 
 | ||||
|     @Given("^the application has been initialised with test data$") | ||||
|     public void init() { | ||||
|         //the default profile loads synthetic stocks | ||||
|     } | ||||
| 
 | ||||
|     @When("^the client gets all stocks$") | ||||
|     public void getAllStocks() { | ||||
|         Stock[] stockArray = restTemplate.getForObject("/stocks", Stock[].class); | ||||
|         stocks = Arrays.asList(stockArray); | ||||
|     } | ||||
| 
 | ||||
|     @Then("^a list of (.*) stocks will be returned$") | ||||
|     public void assertListOfStocksLength(int length) { | ||||
|         assertThat(stocks, hasSize(length)); | ||||
|     } | ||||
| 
 | ||||
|     @Then("^the stock at index (.*) will have the sku (.*)$") | ||||
|     public void assertStockHasSku(int stockIndex, String sku) { | ||||
|         assertThat(stocks.get(stockIndex).getSku(), is(sku)); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,20 @@ | ||||
| package uk.co.danielbryant.djshopping.stockmanager; | ||||
| 
 | ||||
| import org.junit.Test; | ||||
| import org.junit.runner.RunWith; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.boot.test.context.SpringBootTest; | ||||
| import org.springframework.boot.test.web.client.TestRestTemplate; | ||||
| import org.springframework.test.context.junit4.SpringRunner; | ||||
| 
 | ||||
| @RunWith(SpringRunner.class) | ||||
| @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = StockManagerApplication.class) | ||||
| public class ShopfrontApplicationTests { | ||||
| 
 | ||||
|     @Autowired | ||||
|     private TestRestTemplate testRestTemplate; | ||||
| 
 | ||||
|     @Test | ||||
|     public void contextLoads() { | ||||
|     } | ||||
| } | ||||
							
								
								
									
										11
									
								
								stockmanager/src/test/resources/features/Stocks.feature
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								stockmanager/src/test/resources/features/Stocks.feature
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| Feature: Retrieving Stocks | ||||
| 
 | ||||
|   Scenario: Should be able to get a list of all stocks | ||||
|     Given the application has been initialised with test data | ||||
|     When the client gets all stocks | ||||
|     Then a list of 5 stocks will be returned | ||||
| 
 | ||||
|   Scenario: Should be able to get the correct SKU for the first stock | ||||
|     Given the application has been initialised with test data | ||||
|     When the client gets all stocks | ||||
|     Then the stock at index 0 will have the sku 12345678 | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user