A list of all zoos whose name contains the given substring
A Stretch Goal
@@ -450,7 +450,7 @@
findZooByLikeName
Returns:
List of zoos whose name contains the given substring
Throws:
-
javax.persistence.EntityNotFoundException
+
javax.persistence.ResourceNotFoundExeption
diff --git a/schools/pom.xml b/schools/pom.xml
index e68d108f..236c3d85 100644
--- a/schools/pom.xml
+++ b/schools/pom.xml
@@ -43,6 +43,29 @@
spring-boot-starter-testtest
+
+
+
+
+ io.springfox
+ springfox-swagger2
+ 2.9.2
+
+
+
+
+ io.springfox
+ springfox-swagger-ui
+ 2.9.2
+
+
+
+ io.springfox
+ springfox-bean-validators
+ 2.9.2
+
+
+
diff --git a/schools/src/main/java/com/lambdaschool/schools/SchoolsApplication.java b/schools/src/main/java/com/lambdaschool/schools/SchoolsApplication.java
index ae94d2dc..b88a8bcd 100644
--- a/schools/src/main/java/com/lambdaschool/schools/SchoolsApplication.java
+++ b/schools/src/main/java/com/lambdaschool/schools/SchoolsApplication.java
@@ -1,8 +1,17 @@
package com.lambdaschool.schools;
+import com.lambdaschool.schools.models.slip;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.core.ParameterizedTypeReference;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Collections;
/**
* Main class to start the application.
@@ -17,10 +26,36 @@ public class SchoolsApplication
*
* @param args Not used in this application.
*/
+
public static void main(String[] args)
{
- SpringApplication.run(SchoolsApplication.class,
- args);
+ /*
+ * Creates the object that is needed to do a client side Rest API call.
+ * We are the client getting data from a remote API.
+ */
+ RestTemplate restTemplate = new RestTemplate();
+
+ // we need to tell our RestTemplate what format to expect
+ MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
+ // a couple of common formats
+ // converter.setSupportedMediaTypes(Collections.singletonList(MediaType.TEXT_HTML));
+ // converter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON));
+ // or we can accept all formats! Easiest but least secure
+ converter.setSupportedMediaTypes(Collections.singletonList(MediaType.ALL));
+ restTemplate.getMessageConverters().add(converter);
+
+ // create the url to access the API
+ String requestURL = "https://api.adviceslip.com/advice";
+ // create the responseType expected. Notice the YearFact is the data type we are expecting back from the API!
+ ParameterizedTypeReference responseType = new ParameterizedTypeReference()
+ {
+ };
+
+ ResponseEntity responseEntity = restTemplate.exchange(requestURL, HttpMethod.GET, null, responseType);
+ slip ourslip = responseEntity.getBody();
+ System.out.println(ourslip);
+
+ SpringApplication.run(SchoolsApplication.class, args);
}
}
diff --git a/schools/src/main/java/com/lambdaschool/schools/config/Swagger2Config.java b/schools/src/main/java/com/lambdaschool/schools/config/Swagger2Config.java
new file mode 100644
index 00000000..29854a39
--- /dev/null
+++ b/schools/src/main/java/com/lambdaschool/schools/config/Swagger2Config.java
@@ -0,0 +1,58 @@
+package com.lambdaschool.schools.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.Contact;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+/**
+ * Configures the default Swagger Documentation
+ */
+@Configuration
+@EnableSwagger2
+@Import(BeanValidatorPluginsConfiguration.class)
+public class Swagger2Config
+{
+ /**
+ * Configures what to document using Swagger
+ *
+ * @return A Docket which is the primary interface for Swagger configuration
+ */
+ @Bean
+ public Docket api()
+ {
+ return new Docket(DocumentationType.SWAGGER_2)
+ .select()
+ .apis(RequestHandlerSelectors
+ .basePackage("com.lambdaschool.schools"))
+ .paths(PathSelectors.regex("/.*"))
+ .build()
+ .apiInfo(apiEndPointsInfo());
+ }
+
+ /**
+ * Configures some information related to the Application for Swagger
+ *
+ * @return ApiInfo a Swagger object containing identification information for this application
+ */
+ private ApiInfo apiEndPointsInfo()
+ {
+ return new ApiInfoBuilder().title("User Model Example")
+ .description("User Model Example")
+ .contact(new Contact("Lucas Steinmacher",
+ "http://www.lambdaschool.com",
+ "john@lambdaschool.com"))
+ .license("MIT")
+ .licenseUrl("https://github.com/LambdaSchool/java-usermodel/blob/master/LICENSE")
+ .version("1.0.0")
+ .build();
+ }
+}
\ No newline at end of file
diff --git a/schools/src/main/java/com/lambdaschool/schools/config/SwaggerWebMVC.java b/schools/src/main/java/com/lambdaschool/schools/config/SwaggerWebMVC.java
new file mode 100644
index 00000000..d668f98f
--- /dev/null
+++ b/schools/src/main/java/com/lambdaschool/schools/config/SwaggerWebMVC.java
@@ -0,0 +1,36 @@
+package com.lambdaschool.schools.config;
+
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * The application turns off any automatic web page generate done by Spring. This is done to improve exception handling.
+ * However, we do need some web page generate done for Swagger, so we do that here.
+ */
+@Configuration
+public class SwaggerWebMVC
+ implements WebMvcConfigurer
+{
+ /**
+ * Adds the Swagger web pages to Spring.
+ * This still gives the following warning
+ *
+ * No mapping for GET /
+ * No mapping for GET /csrf
+ *
+ * All works though
+ *
+ * @param registry the place that holds the web pages for Spring
+ */
+ @Override
+ public void addResourceHandlers(ResourceHandlerRegistry registry)
+ {
+ registry.addResourceHandler("swagger-ui.html")
+ .addResourceLocations("classpath:/META-INF/resources/");
+
+ registry.addResourceHandler("/webjars/**")
+ .addResourceLocations("classpath:/META-INF/resources/webjars/");
+ }
+}
\ No newline at end of file
diff --git a/schools/src/main/java/com/lambdaschool/schools/controllers/InstructorController.java b/schools/src/main/java/com/lambdaschool/schools/controllers/InstructorController.java
new file mode 100644
index 00000000..0fce5f8b
--- /dev/null
+++ b/schools/src/main/java/com/lambdaschool/schools/controllers/InstructorController.java
@@ -0,0 +1,29 @@
+package com.lambdaschool.schools.controllers;
+
+import com.lambdaschool.schools.models.Instructor;
+import com.lambdaschool.schools.services.InstructorService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping(value = "instructors")
+public class InstructorController
+{
+ @Autowired
+ private InstructorService instructorService;
+
+ // http://localhost:2019/instructors/instructor/3/advice
+ @GetMapping(value = "/instructor/{instructorid}/advice", produces = "application/json")
+ public ResponseEntity> getInstructorAdvice(
+ @PathVariable Long instructorid)
+ {
+ Instructor i = instructorService.addAdvice(instructorid);
+ return new ResponseEntity<>(i, HttpStatus.OK);
+ }
+
+}
diff --git a/schools/src/main/java/com/lambdaschool/schools/controllers/StudentController.java b/schools/src/main/java/com/lambdaschool/schools/controllers/StudentController.java
index 83c41946..c11a4890 100644
--- a/schools/src/main/java/com/lambdaschool/schools/controllers/StudentController.java
+++ b/schools/src/main/java/com/lambdaschool/schools/controllers/StudentController.java
@@ -1,7 +1,12 @@
package com.lambdaschool.schools.controllers;
+import com.lambdaschool.schools.models.ErrorDetail;
import com.lambdaschool.schools.models.Student;
import com.lambdaschool.schools.services.StudentService;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
@@ -34,6 +39,7 @@ public class StudentController
* @return JSON list of all students with a status of OK
* @see StudentService#findAll() StudentService.findAll()
*/
+ @ApiOperation(value = "returns all students", response = Student.class, responseContainer = "List")
@GetMapping(value = "/students",
produces = {"application/json"})
public ResponseEntity> listAllStudents()
@@ -51,9 +57,16 @@ public ResponseEntity> listAllStudents()
* @return JSON object of the student you seek
* @see StudentService#findStudentById(long) StudentService.findStudentById(long)
*/
+ @ApiOperation(value = "Returns a student by id", response = Student.class)
+ @ApiResponses(value = {@ApiResponse(code = 200,
+ message = "Student found",
+ response = Student.class), @ApiResponse(code = 404,
+ message = "Student not found",
+ response = ErrorDetail.class)})
@GetMapping(value = "/student/{studentId}",
produces = {"application/json"})
public ResponseEntity> getStudentById(
+ @ApiParam(value = "Student id", required = true, example = "4")
@PathVariable
Long studentId)
{
diff --git a/schools/src/main/java/com/lambdaschool/schools/exceptions/CustomErrorDetails.java b/schools/src/main/java/com/lambdaschool/schools/exceptions/CustomErrorDetails.java
new file mode 100644
index 00000000..d4cce63a
--- /dev/null
+++ b/schools/src/main/java/com/lambdaschool/schools/exceptions/CustomErrorDetails.java
@@ -0,0 +1,38 @@
+package com.lambdaschool.schools.exceptions;
+
+import com.lambdaschool.schools.services.HelperFunctions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
+import org.springframework.stereotype.Component;
+import org.springframework.web.context.request.WebRequest;
+
+import java.util.Date;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+@Component
+public class CustomErrorDetails extends DefaultErrorAttributes
+{
+ @Autowired
+ HelperFunctions helperFunctions;
+
+ @Override
+ public Map getErrorAttributes(
+ WebRequest webRequest,
+ boolean includeStackTrace)
+ {
+ Map errorAttributes = super.getErrorAttributes(webRequest, includeStackTrace);
+
+ Map rtnAttributes = new LinkedHashMap<>();
+
+ rtnAttributes.put("title", errorAttributes.get("error"));
+ rtnAttributes.put("status", errorAttributes.get("status"));
+ rtnAttributes.put("detail", errorAttributes.get("message"));
+ rtnAttributes.put("timestamp", new Date());
+ rtnAttributes.put("developer", "path: " + errorAttributes.get("path"));
+
+ rtnAttributes.put("errors", helperFunctions.getValidationErrors(this.getError(webRequest)));
+
+ return rtnAttributes;
+ }
+}
diff --git a/schools/src/main/java/com/lambdaschool/schools/exceptions/ResourceNotFoundExeption.java b/schools/src/main/java/com/lambdaschool/schools/exceptions/ResourceNotFoundExeption.java
new file mode 100644
index 00000000..3891ffa9
--- /dev/null
+++ b/schools/src/main/java/com/lambdaschool/schools/exceptions/ResourceNotFoundExeption.java
@@ -0,0 +1,9 @@
+package com.lambdaschool.schools.exceptions;
+
+public class ResourceNotFoundExeption extends RuntimeException
+{
+ public ResourceNotFoundExeption(String message)
+ {
+ super("Found an issue with School: " + message);
+ }
+}
diff --git a/schools/src/main/java/com/lambdaschool/schools/handelers/RestExceptionHandler.java b/schools/src/main/java/com/lambdaschool/schools/handelers/RestExceptionHandler.java
new file mode 100644
index 00000000..d4957ddb
--- /dev/null
+++ b/schools/src/main/java/com/lambdaschool/schools/handelers/RestExceptionHandler.java
@@ -0,0 +1,59 @@
+package com.lambdaschool.schools.handelers;
+
+import com.lambdaschool.schools.exceptions.ResourceNotFoundExeption;
+import com.lambdaschool.schools.models.ErrorDetail;
+import com.lambdaschool.schools.services.HelperFunctions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
+import org.springframework.core.Ordered;
+import org.springframework.core.annotation.Order;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.context.request.WebRequest;
+import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
+
+import java.util.Date;
+import java.util.Map;
+
+@RestControllerAdvice
+@Order(Ordered.HIGHEST_PRECEDENCE)
+public class RestExceptionHandler extends ResponseEntityExceptionHandler
+{
+ @Autowired
+ private HelperFunctions helperFunctions;
+
+ @ExceptionHandler(ResourceNotFoundExeption.class)
+ public ResponseEntity> handleResourceNotFoundException(ResourceNotFoundExeption rnfe)
+ {
+ ErrorDetail errorDetail = new ErrorDetail();
+ errorDetail.setTimestamp(new Date());
+ errorDetail.setTitle("Resource Not Found Bubba!");
+ errorDetail.setStatus(HttpStatus.NOT_FOUND.value());
+ errorDetail.setDetail(rnfe.getMessage());
+ errorDetail.setDeveloper(rnfe.getClass().getName());
+ errorDetail.setErrors(helperFunctions.getValidationErrors(rnfe));
+ return new ResponseEntity<>(errorDetail, null, HttpStatus.NOT_FOUND);
+ }
+
+ @Override
+ protected ResponseEntity