Skip to content

Commit db4cf58

Browse files
authored
Merge pull request #10 from companieshouse/feature/DSND-1631-expose-put-endpoint
Expose PUT endpoint and save to mongo
2 parents 60237b9 + 453bbd6 commit db4cf58

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+2719
-2
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,7 @@
2222
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
2323
hs_err_pid*
2424
/target/
25+
26+
# IntelliJ files
27+
.idea/
28+
*.iml

Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ test: test-unit
3030
test-unit:
3131
mvn test
3232

33+
.PHONY: coverage
34+
coverage:
35+
mvn verify
36+
3337
.PHONY: package
3438
package:
3539
ifndef version
@@ -45,7 +49,7 @@ endif
4549
rm -rf $(tmpdir)
4650

4751
.PHONY: dist
48-
dist: clean package
52+
dist: clean build package coverage
4953

5054
.PHONY: publish
5155
publish:

pom.xml

Lines changed: 115 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>uk.gov.companieshouse</groupId>
77
<artifactId>companies-house-parent</artifactId>
8-
<version>1.3.0</version>
8+
<version>1.3.1</version>
99
<relativePath />
1010
</parent>
1111
<artifactId>psc-data-api</artifactId>
@@ -22,6 +22,24 @@
2222
<maven.compiler.target>${java.version}</maven.compiler.target>
2323
<maven-surefire-plugin.version>3.0.0-M5</maven-surefire-plugin.version>
2424
<jib-maven-plugin.version>3.1.1</jib-maven-plugin.version>
25+
<jacoco-maven-plugin.version>0.8.5</jacoco-maven-plugin.version>
26+
27+
<!-- Internal -->
28+
<structured-logging.version>1.9.12</structured-logging.version>
29+
<private-api-sdk-java.version>2.0.237</private-api-sdk-java.version>
30+
<api-sdk-manager-java-library.version>1.0.4</api-sdk-manager-java-library.version>
31+
<api-helper-java-library.version>1.4.5</api-helper-java-library.version>
32+
33+
<!-- tests -->
34+
<maven-surefire-plugin.version>3.0.0-M5</maven-surefire-plugin.version>
35+
<jib-maven-plugin.version>3.1.1</jib-maven-plugin.version>
36+
<io-cucumber.version>7.2.3</io-cucumber.version>
37+
<test-containers.version>1.16.3</test-containers.version>
38+
<maven-failsafe-plugin.version>3.0.0-M5</maven-failsafe-plugin.version>
39+
<assertj-core.version>3.22.0</assertj-core.version>
40+
<skip.integration.tests>false</skip.integration.tests>
41+
<skip.unit.tests>false</skip.unit.tests>
42+
<maven-resources-plugin.version>2.5</maven-resources-plugin.version>
2543

2644
<!--sonar configuration-->
2745
<sonar.coverage.jacoco.xmlReportPaths>${project.basedir}/target/site/jacoco/jacoco.xml,
@@ -38,6 +56,13 @@
3856
<type>pom</type>
3957
<scope>import</scope>
4058
</dependency>
59+
<dependency>
60+
<groupId>org.testcontainers</groupId>
61+
<artifactId>testcontainers-bom</artifactId>
62+
<version>${test-containers.version}</version>
63+
<type>pom</type>
64+
<scope>import</scope>
65+
</dependency>
4166
</dependencies>
4267
</dependencyManagement>
4368
<dependencies>
@@ -53,12 +78,48 @@
5378
<groupId>org.springframework.boot</groupId>
5479
<artifactId>spring-boot-starter-web</artifactId>
5580
</dependency>
81+
<dependency>
82+
<groupId>org.springframework.boot</groupId>
83+
<artifactId>spring-boot-starter-data-mongodb</artifactId>
84+
<exclusions>
85+
<exclusion>
86+
<groupId>org.apache.logging.log4j</groupId>
87+
<artifactId>log4j-to-slf4j</artifactId>
88+
</exclusion>
89+
</exclusions>
90+
</dependency>
91+
92+
<dependency>
93+
<groupId>uk.gov.companieshouse</groupId>
94+
<artifactId>structured-logging</artifactId>
95+
<version>${structured-logging.version}</version>
96+
</dependency>
97+
<dependency>
98+
<groupId>uk.gov.companieshouse</groupId>
99+
<artifactId>private-api-sdk-java</artifactId>
100+
<version>${private-api-sdk-java.version}</version>
101+
</dependency>
102+
<dependency>
103+
<groupId>uk.gov.companieshouse</groupId>
104+
<artifactId>api-sdk-manager-java-library</artifactId>
105+
<version>${api-sdk-manager-java-library.version}</version>
106+
</dependency>
107+
<dependency>
108+
<groupId>uk.gov.companieshouse</groupId>
109+
<artifactId>api-helper-java</artifactId>
110+
<version>${api-helper-java-library.version}</version>
111+
</dependency>
56112

57113
<dependency>
58114
<groupId>org.springframework.boot</groupId>
59115
<artifactId>spring-boot-starter-test</artifactId>
60116
<scope>test</scope>
61117
</dependency>
118+
<dependency>
119+
<groupId>org.testcontainers</groupId>
120+
<artifactId>junit-jupiter</artifactId>
121+
<scope>test</scope>
122+
</dependency>
62123
</dependencies>
63124

64125
<build>
@@ -129,6 +190,59 @@
129190
<plugin>
130191
<groupId>org.jacoco</groupId>
131192
<artifactId>jacoco-maven-plugin</artifactId>
193+
<version>${jacoco-maven-plugin.version}</version>
194+
<configuration>
195+
<excludes>
196+
<exclude>**/models/*.class</exclude>
197+
</excludes>
198+
</configuration>
199+
<executions>
200+
<execution>
201+
<id>pre-unit-test</id>
202+
<goals>
203+
<goal>prepare-agent</goal>
204+
</goals>
205+
<configuration>
206+
<!-- Sets the path to the file which contains the execution model. -->
207+
<destFile>${sonar.jacoco.reports}/jacoco.exec</destFile>
208+
<propertyName>surefireArgLine</propertyName>
209+
</configuration>
210+
</execution>
211+
<execution>
212+
<id>post-unit-test</id>
213+
<phase>test</phase>
214+
<goals>
215+
<goal>report</goal>
216+
</goals>
217+
<configuration>
218+
<dataFile>${sonar.jacoco.reports}/jacoco.exec</dataFile>
219+
<outputDirectory>${sonar.jacoco.reports}/jacoco</outputDirectory>
220+
</configuration>
221+
</execution>
222+
<execution>
223+
<id>pre-integration-test</id>
224+
<phase>pre-integration-test</phase>
225+
<goals>
226+
<goal>prepare-agent</goal>
227+
</goals>
228+
<configuration>
229+
<!-- Sets the path to the file which contains the execution model. -->
230+
<destFile>${sonar.jacoco.reports}/jacoco-it.exec</destFile>
231+
<propertyName>failsafeArgLine</propertyName>
232+
</configuration>
233+
</execution>
234+
<execution>
235+
<id>post-integration-test</id>
236+
<phase>post-integration-test</phase>
237+
<goals>
238+
<goal>report</goal>
239+
</goals>
240+
<configuration>
241+
<dataFile>${sonar.jacoco.reports}/jacoco-it.exec</dataFile>
242+
<outputDirectory>${sonar.jacoco.reports}/jacoco-it</outputDirectory>
243+
</configuration>
244+
</execution>
245+
</executions>
132246
</plugin>
133247
<plugin>
134248
<groupId>org.sonarsource.scanner.maven</groupId>

routes.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
app_name: psc-data-api
2+
group: api
3+
weight: 905
4+
routes:
5+
1: ^/persons-with-significant-control/healthcheck
6+
2: ^/company/(.*)/persons-with-significant-control/(.*)/full_record

src/main/java/uk/gov/companieshouse/pscdataapi/PscDataApiApplication.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
@SpringBootApplication
77
public class PscDataApiApplication {
8+
public static final String APPLICATION_NAME_SPACE = "psc-data-api";
89

910
public static void main(String[] args) {
1011
SpringApplication.run(PscDataApiApplication.class, args);
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package uk.gov.companieshouse.pscdataapi.config;
2+
3+
import com.fasterxml.jackson.annotation.JsonInclude;
4+
import com.fasterxml.jackson.databind.DeserializationFeature;
5+
import com.fasterxml.jackson.databind.ObjectMapper;
6+
import com.fasterxml.jackson.databind.SerializationFeature;
7+
import com.fasterxml.jackson.databind.module.SimpleModule;
8+
9+
import java.time.LocalDate;
10+
import java.time.OffsetDateTime;
11+
import java.util.List;
12+
import java.util.function.Supplier;
13+
import org.springframework.context.annotation.Bean;
14+
import org.springframework.context.annotation.Configuration;
15+
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
16+
import uk.gov.companieshouse.pscdataapi.converter.CompanyPscReadConverter;
17+
import uk.gov.companieshouse.pscdataapi.converter.CompanyPscWriteConverter;
18+
import uk.gov.companieshouse.pscdataapi.serialization.LocalDateDeSerializer;
19+
import uk.gov.companieshouse.pscdataapi.serialization.LocalDateSerializer;
20+
21+
@Configuration
22+
public class ApplicationConfig {
23+
24+
/**
25+
* mongoCustomConversions.
26+
*
27+
* @return MongoCustomConversions.
28+
*/
29+
@Bean
30+
public MongoCustomConversions mongoCustomConversions() {
31+
ObjectMapper objectMapper = mongoDbObjectMapper();
32+
return new MongoCustomConversions(List.of(new CompanyPscWriteConverter(objectMapper),
33+
new CompanyPscReadConverter(objectMapper)));
34+
}
35+
36+
@Bean
37+
public Supplier<String> offsetDateTimeGenerator() {
38+
return () -> String.valueOf(OffsetDateTime.now());
39+
}
40+
41+
/**
42+
* Mongo DB Object Mapper.
43+
*
44+
* @return ObjectMapper.
45+
*/
46+
private ObjectMapper mongoDbObjectMapper() {
47+
ObjectMapper objectMapper = new ObjectMapper();
48+
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
49+
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
50+
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
51+
SimpleModule module = new SimpleModule();
52+
module.addSerializer(LocalDate.class, new LocalDateSerializer());
53+
module.addDeserializer(LocalDate.class, new LocalDateDeSerializer());
54+
objectMapper.registerModule(module);
55+
return objectMapper;
56+
}
57+
}
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
package uk.gov.companieshouse.pscdataapi.config;
2+
3+
import java.time.LocalDateTime;
4+
import java.time.format.DateTimeParseException;
5+
import java.util.LinkedHashMap;
6+
import java.util.Map;
7+
import org.springframework.beans.factory.annotation.Autowired;
8+
import org.springframework.dao.DataAccessException;
9+
import org.springframework.http.HttpStatus;
10+
import org.springframework.http.ResponseEntity;
11+
import org.springframework.http.converter.HttpMessageNotReadableException;
12+
import org.springframework.web.HttpRequestMethodNotSupportedException;
13+
import org.springframework.web.bind.annotation.ControllerAdvice;
14+
import org.springframework.web.bind.annotation.ExceptionHandler;
15+
import org.springframework.web.context.request.WebRequest;
16+
import uk.gov.companieshouse.logging.Logger;
17+
import uk.gov.companieshouse.pscdataapi.exceptions.BadRequestException;
18+
import uk.gov.companieshouse.pscdataapi.exceptions.MethodNotAllowedException;
19+
import uk.gov.companieshouse.pscdataapi.exceptions.ServiceUnavailableException;
20+
21+
@ControllerAdvice
22+
public class ExceptionHandlerConfig {
23+
private final Logger logger;
24+
25+
@Autowired
26+
public ExceptionHandlerConfig(Logger logger) {
27+
this.logger = logger;
28+
}
29+
30+
private static final String TIMESTAMP = "timestamp";
31+
private static final String MESSAGE = "message";
32+
private static final String EXCEPTION_ATTRIBUTE = "javax.servlet.error.exception";
33+
34+
/**
35+
* Runtime exception handler. Acts as the catch-all scenario.
36+
*
37+
* @param ex exception to handle.
38+
* @param request request.
39+
* @return error response to return.
40+
*/
41+
@ExceptionHandler(value = {Exception.class})
42+
public ResponseEntity<Object> handleException(Exception ex, WebRequest request) {
43+
logger.error(String.format("Unexpected exception, response code: %s",
44+
HttpStatus.INTERNAL_SERVER_ERROR), ex);
45+
46+
Map<String, Object> responseBody = new LinkedHashMap<>();
47+
responseBody.put(TIMESTAMP, LocalDateTime.now());
48+
responseBody.put(MESSAGE, "Unable to process the request.");
49+
request.setAttribute(EXCEPTION_ATTRIBUTE, ex, 0);
50+
return new ResponseEntity<>(responseBody, HttpStatus.INTERNAL_SERVER_ERROR);
51+
}
52+
53+
/**
54+
* IllegalArgumentException exception handler.
55+
*
56+
* @param ex exception to handle.
57+
* @param request request.
58+
* @return error response to return.
59+
*/
60+
@ExceptionHandler(value = {IllegalArgumentException.class})
61+
public ResponseEntity<Object> handleNotFoundException(Exception ex, WebRequest request) {
62+
logger.error(String.format("Resource not found, response code: %s",
63+
HttpStatus.NOT_FOUND), ex);
64+
65+
Map<String, Object> responseBody = new LinkedHashMap<>();
66+
responseBody.put(TIMESTAMP, LocalDateTime.now());
67+
responseBody.put(MESSAGE, "Resource not found.");
68+
request.setAttribute(EXCEPTION_ATTRIBUTE, ex, 0);
69+
return new ResponseEntity<>(responseBody, HttpStatus.NOT_FOUND);
70+
}
71+
72+
/**
73+
* MethodNotAllowedException exception handler.
74+
*
75+
* @param ex exception to handle.
76+
* @param request request.
77+
* @return error response to return.
78+
*/
79+
@ExceptionHandler(value = {MethodNotAllowedException.class,
80+
HttpRequestMethodNotSupportedException.class})
81+
public ResponseEntity<Object> handleMethodNotAllowedException(
82+
Exception ex, WebRequest request) {
83+
logger.error(String.format("Unable to process the request, response code: %s",
84+
HttpStatus.METHOD_NOT_ALLOWED), ex);
85+
86+
Map<String, Object> responseBody = new LinkedHashMap<>();
87+
responseBody.put(TIMESTAMP, LocalDateTime.now());
88+
responseBody.put(MESSAGE, "Unable to process the request.");
89+
request.setAttribute(EXCEPTION_ATTRIBUTE, ex, 0);
90+
return new ResponseEntity<>(responseBody, HttpStatus.METHOD_NOT_ALLOWED);
91+
}
92+
93+
/**
94+
* ServiceUnavailableException exception handler.
95+
* To be thrown when there are connection issues.
96+
*
97+
* @param ex exception to handle.
98+
* @param request request.
99+
* @return error response to return.
100+
*/
101+
@ExceptionHandler(value = {ServiceUnavailableException.class, DataAccessException.class})
102+
public ResponseEntity<Object> handleServiceUnavailableException(Exception ex,
103+
WebRequest request) {
104+
logger.error(String.format("Service unavailable, response code: %s",
105+
HttpStatus.SERVICE_UNAVAILABLE), ex);
106+
107+
Map<String, Object> responseBody = new LinkedHashMap<>();
108+
responseBody.put(TIMESTAMP, LocalDateTime.now());
109+
responseBody.put(MESSAGE, "Service unavailable.");
110+
request.setAttribute(EXCEPTION_ATTRIBUTE, ex, 0);
111+
return new ResponseEntity<>(responseBody, HttpStatus.SERVICE_UNAVAILABLE);
112+
}
113+
114+
/**
115+
* BadRequestException exception handler.
116+
* Thrown when data is given in the wrong format.
117+
*
118+
* @param ex exception to handle.
119+
* @param request request.
120+
* @return error response to return.
121+
*/
122+
@ExceptionHandler(value = {BadRequestException.class, DateTimeParseException.class,
123+
HttpMessageNotReadableException.class})
124+
public ResponseEntity<Object> handleBadRequestException(Exception ex, WebRequest request) {
125+
logger.error(String.format("Bad request, response code: %s", HttpStatus.BAD_REQUEST), ex);
126+
127+
Map<String, Object> responseBody = new LinkedHashMap<>();
128+
responseBody.put(TIMESTAMP, LocalDateTime.now());
129+
responseBody.put(MESSAGE, "Bad request.");
130+
request.setAttribute(EXCEPTION_ATTRIBUTE, ex, 0);
131+
return new ResponseEntity<>(responseBody, HttpStatus.BAD_REQUEST);
132+
}
133+
}

0 commit comments

Comments
 (0)