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.ResourceNotFoundException
diff --git a/schools/pom.xml b/schools/pom.xml
index e68d108f..5b797589 100644
--- a/schools/pom.xml
+++ b/schools/pom.xml
@@ -15,7 +15,7 @@
Demo project for Spring Boot
- 11
+ 14
@@ -43,6 +43,27 @@
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..f959a9ed 100644
--- a/schools/src/main/java/com/lambdaschool/schools/SchoolsApplication.java
+++ b/schools/src/main/java/com/lambdaschool/schools/SchoolsApplication.java
@@ -1,8 +1,15 @@
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.*;
+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 +24,15 @@ public class SchoolsApplication
*
* @param args Not used in this application.
*/
- public static void main(String[] args)
- {
+ public static void main(String[] args){
+
+ try{
+ System.out.println(System.getenv("PATH").toUpperCase());
+ } catch (Exception e){
+ System.out.println("No Such Environment Variable");
+ } finally{
SpringApplication.run(SchoolsApplication.class,
args);
+ }
}
-
}
diff --git a/schools/src/main/java/com/lambdaschool/schools/config/H2ServerConfiguration.java b/schools/src/main/java/com/lambdaschool/schools/config/H2ServerConfiguration.java
index 981a4568..236c1d7a 100644
--- a/schools/src/main/java/com/lambdaschool/schools/config/H2ServerConfiguration.java
+++ b/schools/src/main/java/com/lambdaschool/schools/config/H2ServerConfiguration.java
@@ -44,10 +44,10 @@ public Server h2TcpServer() throws
SQLException
{
return Server.createTcpServer("-tcp",
- "-tcpAllowOthers",
- "-tcpPort",
- h2TcpPort)
- .start();
+ "-tcpAllowOthers",
+ "-tcpPort",
+ h2TcpPort)
+ .start();
}
/**
@@ -64,9 +64,9 @@ public Server h2WebServer() throws
SQLException
{
return Server.createWebServer("-web",
- "-webAllowOthers",
- "-webPort",
- h2WebPort)
- .start();
+ "-webAllowOthers",
+ "-webPort",
+ h2WebPort)
+ .start();
}
}
\ No newline at end of file
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..fbff8690
--- /dev/null
+++ b/schools/src/main/java/com/lambdaschool/schools/config/Swagger2Config.java
@@ -0,0 +1,54 @@
+package com.lambdaschool.schools.config;
+
+import org.springframework.context.annotation.*;
+import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
+import springfox.documentation.builders.*;
+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("School Example")
+ .description("User Model Example")
+ .contact(new Contact("John Mitchell",
+ "http://www.lambdaschool.com",
+ "john@lambdaschool.com"))
+ .license("MIT")
+ .licenseUrl("https://github.com/LambdaSchool/java-school/blob/master/LICENSE")
+ .version("1.0.0")
+ .build();
+ }
+}
\ No newline at end of file
diff --git a/schools/src/main/java/com/lambdaschool/schools/controllers/OtherApisController.java b/schools/src/main/java/com/lambdaschool/schools/controllers/OtherApisController.java
new file mode 100644
index 00000000..1f0d7fec
--- /dev/null
+++ b/schools/src/main/java/com/lambdaschool/schools/controllers/OtherApisController.java
@@ -0,0 +1,162 @@
+package com.lambdaschool.schools.controllers;
+
+import com.lambdaschool.schools.models.*;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.http.*;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Collections;
+
+@RestController
+@RequestMapping("/otherapis") // optional
+public class OtherApisController
+{
+ /*
+ * Creates the object that is needed to do a client side Rest API call.
+ * We are the client getting data from a remote API.
+ * We can share this template among endpoints
+ */
+ private RestTemplate restTemplate = new RestTemplate();
+
+ @GetMapping(value = "/isspositions")
+ public ResponseEntity> listIssPositions()
+ {
+ // 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 = "http://api.open-notify.org/iss-now.json";
+ // create the responseType expected. Notice the IssPositionReturnData is the data type we are expecting back from the API!
+ ParameterizedTypeReference responseType = new ParameterizedTypeReference<>()
+ {
+ };
+
+ // create the response entity. do the get and get back information
+ ResponseEntity responseEntity = restTemplate.exchange(requestURL,
+ HttpMethod.GET,
+ null,
+ responseType);
+ // we want to return the Iss_position data. From the data that gets returned in the body,
+ // get the Iss_position data only and return it.
+ // putting the data into its own object first, prevents the data from being reported to client inside of
+ // an embedded. So the response will look more like our clients are use to!
+ IssPosition ourIssPosition = responseEntity.getBody().getIss_position();
+ return new ResponseEntity<>(ourIssPosition,
+ HttpStatus.OK);
+ }
+
+ @GetMapping(value = "/shakespeare/{englishText}")
+ public ResponseEntity> getTranslation(
+ @PathVariable
+ String englishText)
+ {
+ // 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 including adding the path variable
+ String requestURL = "https://api.funtranslations.com/translate/shakespeare.json?text=" + englishText;
+ // create the responseType expected. Notice the Translation is the data type we are expecting back from the API!
+ ParameterizedTypeReference responseType = new ParameterizedTypeReference<>()
+ {
+ };
+
+ // create the response entity. do the get and get back information
+ ResponseEntity responseEntity = restTemplate.exchange(requestURL,
+ HttpMethod.GET,
+ null,
+ responseType);
+ // we want to return the contents of the translation data. From the data that gets returned in the body,
+ // get the contents data only and return it.
+ // putting the data into its own object first, prevents the data from being reported to client inside of
+ // an embedded. So the response will look more like our clients are use to!
+ TranslationContents ourTranslation = responseEntity.getBody()
+ .getContents();
+ return new ResponseEntity<>(ourTranslation,
+ HttpStatus.OK);
+ }
+
+ @GetMapping(value = "/advice")
+ public ResponseEntity> listSlipAdvice()
+ {
+ // 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 IssPositionReturnData is the data type we are expecting back from the API!
+ ParameterizedTypeReference responseType = new ParameterizedTypeReference<>()
+ {
+ };
+
+ // create the response entity. do the get and get back information
+ ResponseEntity responseEntity = restTemplate.exchange(requestURL,
+ HttpMethod.GET,
+ null,
+ responseType);
+ // we want to return the Iss_position data. From the data that gets returned in the body,
+ // get the Iss_position data only and return it.
+ // putting the data into its own object first, prevents the data from being reported to client inside of
+ // an embedded. So the response will look more like our clients are use to!
+ slip ourSlipPosition = responseEntity.getBody().getSlip_position();
+ return new ResponseEntity<>(ourSlipPosition,
+ HttpStatus.OK);
+ }
+
+ @GetMapping(value = "/advice/{id}")
+ public ResponseEntity> getAdviceTranslation(
+ @PathVariable
+ int id)
+ {
+ // 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 including adding the path variable
+ String requestURL = "https://api.adviceslip.com/advice?text=" + id;
+ // create the responseType expected. Notice the Translation is the data type we are expecting back from the API!
+ ParameterizedTypeReference responseType = new ParameterizedTypeReference<>()
+ {
+ };
+
+ // create the response entity. do the get and get back information
+ ResponseEntity responseEntity = restTemplate.exchange(requestURL,
+ HttpMethod.GET,
+ null,
+ responseType);
+ // we want to return the contents of the translation data. From the data that gets returned in the body,
+ // get the contents data only and return it.
+ // putting the data into its own object first, prevents the data from being reported to client inside of
+ // an embedded. So the response will look more like our clients are use to!
+ TranslationContents ourTranslation = responseEntity.getBody()
+ .getContents();
+ return new ResponseEntity<>(ourTranslation,
+ HttpStatus.OK);
+ }
+}
\ No newline at end of file
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..3836fec4
--- /dev/null
+++ b/schools/src/main/java/com/lambdaschool/schools/exceptions/CustomErrorDetails.java
@@ -0,0 +1,42 @@
+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.text.SimpleDateFormat;
+import java.util.*;
+
+@Component
+public class CustomErrorDetails extends DefaultErrorAttributes {
+
+ @Autowired
+ private HelperFunctions helperFunctions;
+
+ /*
+ title
+ status
+ detail
+ timestamp
+ developerMessage
+ */
+
+ SimpleDateFormat dateFormat = new SimpleDateFormat("E, MMM dd,yyyy | HH:mm:ss");
+ Date date = new Date();
+ @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("details", errorAttributes.get("message"));
+ rtnAttributes.put("timestamp", dateFormat.format(date));
+ rtnAttributes.put("developerMessage", "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/ResourceFoundException.java b/schools/src/main/java/com/lambdaschool/schools/exceptions/ResourceFoundException.java
new file mode 100644
index 00000000..d4c45f0e
--- /dev/null
+++ b/schools/src/main/java/com/lambdaschool/schools/exceptions/ResourceFoundException.java
@@ -0,0 +1,9 @@
+package com.lambdaschool.schools.exceptions;
+
+import javax.persistence.EntityExistsException;
+
+public class ResourceFoundException extends EntityExistsException {
+ public ResourceFoundException(String message) {
+ super("Found an issue with School: " + message);
+ }
+}
diff --git a/schools/src/main/java/com/lambdaschool/schools/exceptions/ResourceNotFoundException.java b/schools/src/main/java/com/lambdaschool/schools/exceptions/ResourceNotFoundException.java
new file mode 100644
index 00000000..8da2fef2
--- /dev/null
+++ b/schools/src/main/java/com/lambdaschool/schools/exceptions/ResourceNotFoundException.java
@@ -0,0 +1,8 @@
+package com.lambdaschool.schools.exceptions;
+
+public class ResourceNotFoundException extends RuntimeException {
+
+ public ResourceNotFoundException(String message) {
+ super("Found an issue with School: " + message);
+ }
+}
\ No newline at end of file
diff --git a/schools/src/main/java/com/lambdaschool/schools/handlers/RestExceptionHandler.java b/schools/src/main/java/com/lambdaschool/schools/handlers/RestExceptionHandler.java
new file mode 100644
index 00000000..6dc6431b
--- /dev/null
+++ b/schools/src/main/java/com/lambdaschool/schools/handlers/RestExceptionHandler.java
@@ -0,0 +1,185 @@
+package com.lambdaschool.schools.handlers;
+
+import com.lambdaschool.schools.exceptions.ResourceFoundException;
+import com.lambdaschool.schools.exceptions.ResourceNotFoundException;
+import com.lambdaschool.schools.models.ErrorDetail;
+import com.lambdaschool.schools.services.HelperFunctions;
+import org.springframework.beans.TypeMismatchException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.Ordered;
+import org.springframework.core.annotation.Order;
+import org.springframework.http.*;
+import org.springframework.web.HttpRequestMethodNotSupportedException;
+import org.springframework.web.bind.*;
+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.NoHandlerFoundException;
+import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+@RestControllerAdvice
+@Order(Ordered.HIGHEST_PRECEDENCE)
+public class RestExceptionHandler extends ResponseEntityExceptionHandler {
+
+ @Autowired
+ private HelperFunctions helperFunctions;
+
+ SimpleDateFormat dateFormat = new SimpleDateFormat("E, MMM dd,yyyy || HH:mm:ss");
+ Date date = new Date();
+
+ @ExceptionHandler(ResourceNotFoundException.class)
+ public ResponseEntity> handleResourceNotFoundException(ResourceNotFoundException rnfe) {
+
+ ErrorDetail errorDetail = new ErrorDetail();
+
+ errorDetail.setTitle("Resource Not Found!");
+ errorDetail.setStatus(HttpStatus.NOT_FOUND.value());
+ errorDetail.setDetail(rnfe.getMessage());
+ errorDetail.setTimestamp(dateFormat.format(date));
+ errorDetail.setDeveloperMessage(rnfe.getClass().getName());
+ errorDetail.setErrors(helperFunctions.getValidationErrors(rnfe));
+ return new ResponseEntity<>(errorDetail, null, HttpStatus.NOT_FOUND);
+ }
+
+ @ExceptionHandler(ResourceFoundException.class)
+ public ResponseEntity> handleResourceFoundException(ResourceFoundException rsfe) {
+
+ ErrorDetail confirmDetail = new ErrorDetail();
+
+ confirmDetail.setTitle("Resource Found!");
+ confirmDetail.setStatus(HttpStatus.FOUND.value());
+ confirmDetail.setDetail(rsfe.getMessage());
+ confirmDetail.setTimestamp(dateFormat.format(date));
+ confirmDetail.setDeveloperMessage("Found an issue with School: " + rsfe.getClass().getName());
+ confirmDetail.setErrors(helperFunctions.getValidationErrors(rsfe));
+ return new ResponseEntity<>(confirmDetail, null, HttpStatus.FOUND);
+ }
+
+ @Override
+ protected ResponseEntity