├── .env
├── infrastructure
├── aat.tfvars
├── demo.tfvars
├── output.tf
├── prod.tfvars
├── .terraform-version
├── main.tf
├── state.tf
├── variables.tf
└── README.md
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── charts
└── rpe-spring-boot-template
│ ├── values.preview.template.yaml
│ ├── values.aat.template.yaml
│ ├── templates
│ └── NOTES.txt
│ ├── Chart.yaml
│ ├── .helmignore
│ └── values.yaml
├── .github
├── ISSUE_TEMPLATE.md
├── renovate.json
├── CODEOWNERS
├── workflows
│ ├── publish-openapi.yaml
│ ├── ci.yml
│ └── codeql.yml
├── PULL_REQUEST_TEMPLATE.md
├── stale.yml
└── CONTRIBUTING.md
├── Dockerfile
├── .gitignore
├── src
├── test
│ └── java
│ │ └── uk
│ │ └── gov
│ │ └── hmcts
│ │ └── reform
│ │ └── rsecheck
│ │ └── DemoUnitTest.java
├── main
│ ├── java
│ │ └── uk
│ │ │ └── gov
│ │ │ └── hmcts
│ │ │ └── reform
│ │ │ └── demo
│ │ │ ├── Application.java
│ │ │ ├── controllers
│ │ │ └── RootController.java
│ │ │ └── config
│ │ │ └── OpenAPIConfiguration.java
│ └── resources
│ │ └── application.yaml
├── integrationTest
│ └── java
│ │ └── uk
│ │ └── gov
│ │ └── hmcts
│ │ └── reform
│ │ └── demo
│ │ ├── controllers
│ │ └── GetWelcomeTest.java
│ │ └── openapi
│ │ └── OpenAPIPublisherTest.java
├── smokeTest
│ └── java
│ │ └── uk
│ │ └── gov
│ │ └── hmcts
│ │ └── reform
│ │ └── demo
│ │ └── controllers
│ │ └── SampleSmokeTest.java
└── functionalTest
│ └── java
│ └── uk
│ └── gov
│ └── hmcts
│ └── reform
│ └── demo
│ └── controllers
│ └── SampleFunctionalTest.java
├── Jenkinsfile_nightly
├── Jenkinsfile_template
├── lib
└── applicationinsights.json
├── config
└── owasp
│ └── suppressions.xml
├── .editorconfig
├── docker-compose.yml
├── LICENSE
├── catalog-info.yaml
├── bin
├── run-in-docker.sh
└── init.sh
├── gradlew.bat
├── README.md
└── gradlew
/.env:
--------------------------------------------------------------------------------
1 | SERVER_PORT=4550
2 |
--------------------------------------------------------------------------------
/infrastructure/aat.tfvars:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/infrastructure/demo.tfvars:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/infrastructure/output.tf:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/infrastructure/prod.tfvars:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/infrastructure/.terraform-version:
--------------------------------------------------------------------------------
1 | 1.12.0
2 |
--------------------------------------------------------------------------------
/infrastructure/main.tf:
--------------------------------------------------------------------------------
1 | provider "azurerm" {
2 | features {}
3 | }
4 |
--------------------------------------------------------------------------------
/infrastructure/state.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | backend "azurerm" {}
3 | }
4 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hmcts/spring-boot-template/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/charts/rpe-spring-boot-template/values.preview.template.yaml:
--------------------------------------------------------------------------------
1 | java:
2 | # Don't modify below here
3 | image: ${IMAGE_NAME}
4 | ingressHost: ${SERVICE_FQDN}
5 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ### What would you like to change?
2 |
3 | ### How do you think that would improve the project?
4 |
5 | ### If this entry is related to a bug, please provide the steps to reproduce it
6 |
--------------------------------------------------------------------------------
/charts/rpe-spring-boot-template/values.aat.template.yaml:
--------------------------------------------------------------------------------
1 | # Don't modify this file, it is only needed for the pipeline to set the image and ingressHost
2 | java:
3 | image: ${IMAGE_NAME}
4 | ingressHost: ${SERVICE_FQDN}
5 |
--------------------------------------------------------------------------------
/.github/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": [
4 | "local>hmcts/.github:renovate-config",
5 | "local>hmcts/.github//renovate/automerge-all"
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @hmcts/platform-operations @hmcts/developer-enablement
2 |
3 | # Ignore files updated by Renovate
4 | gradle/wrapper/gradle-wrapper.properties
5 | Dockerfile
6 | build.gradle
7 | charts/**/Chart.yaml
8 | .github/workflows/*.yaml
9 |
--------------------------------------------------------------------------------
/charts/rpe-spring-boot-template/templates/NOTES.txt:
--------------------------------------------------------------------------------
1 | Thank you for installing {{ .Chart.Name }}.
2 |
3 | Your release is named {{ .Release.Name }}.
4 |
5 | To learn more about the release, try:
6 |
7 | $ helm status {{ .Release.Name }}
8 | $ helm get {{ .Release.Name }}
9 |
--------------------------------------------------------------------------------
/infrastructure/variables.tf:
--------------------------------------------------------------------------------
1 | variable "product" {}
2 |
3 | variable "component" {}
4 |
5 | variable "location" {
6 | default = "UK South"
7 | }
8 |
9 | variable "env" {}
10 |
11 | variable "subscription" {}
12 |
13 | variable "common_tags" {
14 | type = map(string)
15 | }
16 |
17 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | # renovate: datasource=github-releases depName=microsoft/ApplicationInsights-Java
2 | ARG APP_INSIGHTS_AGENT_VERSION=3.7.6
3 | FROM hmctspublic.azurecr.io/base/java:21-distroless
4 |
5 | COPY lib/applicationinsights.json /opt/app/
6 | COPY build/libs/spring-boot-template.jar /opt/app/
7 |
8 | EXPOSE 4550
9 | CMD [ "spring-boot-template.jar" ]
10 |
--------------------------------------------------------------------------------
/infrastructure/README.md:
--------------------------------------------------------------------------------
1 | # App infrastructure
2 |
3 | Add any application specific infrastructure to the terraform files in this folder
4 |
5 | This could be things like:
6 | * a database
7 | * redis
8 | * vault
9 | * application insights
10 |
11 | If you don't need any application infrastructure here, you can delete the whole folder (it will speed up your Jenkins build)
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | /build/
3 | !gradle/wrapper/gradle-wrapper.jar
4 | *.class
5 | bin/main/application.yaml
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 |
15 | ### IntelliJ IDEA ###
16 | .idea
17 | /out
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | .DS_Store
23 |
24 | applicationinsights-agent-*.jar
25 | *.log
26 |
--------------------------------------------------------------------------------
/src/test/java/uk/gov/hmcts/reform/rsecheck/DemoUnitTest.java:
--------------------------------------------------------------------------------
1 | package uk.gov.hmcts.reform.rsecheck;
2 |
3 | import org.junit.jupiter.api.Test;
4 |
5 | import static org.junit.jupiter.api.Assertions.assertTrue;
6 |
7 | class DemoUnitTest {
8 |
9 | @Test
10 | void exampleOfTest() {
11 | assertTrue(System.currentTimeMillis() > 0, "Example of Unit Test");
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Jenkinsfile_nightly:
--------------------------------------------------------------------------------
1 | #!groovy
2 |
3 | properties([
4 | // H allow predefined but random minute see https://en.wikipedia.org/wiki/Cron#Non-standard_characters
5 | pipelineTriggers([cron('H 07 * * 1-5')])
6 | ])
7 |
8 | @Library("Infrastructure")
9 |
10 | def type = "java"
11 | def product = "rpe"
12 | def component = "spring-boot-template"
13 |
14 | withNightlyPipeline(type, product, component) {}
15 |
--------------------------------------------------------------------------------
/Jenkinsfile_template:
--------------------------------------------------------------------------------
1 | #!groovy
2 | // If this is new microservice built on the template and you want it to run in Jenkins, you
3 | // will need to follow these steps: https://hmcts.github.io/cloud-native-platform/new-component/github-repo.html
4 |
5 | @Library("Infrastructure")
6 |
7 | def type = "java"
8 | def product = "rpe"
9 | def component = "demo"
10 |
11 | withPipeline(type, product, component) {}
12 |
--------------------------------------------------------------------------------
/charts/rpe-spring-boot-template/Chart.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v2
2 | appVersion: "1.0"
3 | description: A Helm chart for spring-boot-template App
4 | name: rpe-spring-boot-template
5 | home: https://github.com/hmcts/spring-boot-template
6 | version: 0.0.18
7 | maintainers:
8 | - name: HMCTS rpe team
9 | dependencies:
10 | - name: java
11 | version: 5.3.0
12 | repository: 'oci://hmctspublic.azurecr.io/helm'
13 |
--------------------------------------------------------------------------------
/.github/workflows/publish-openapi.yaml:
--------------------------------------------------------------------------------
1 | name: Publish OpenAPI specs
2 | on:
3 | push:
4 | branches:
5 | - "master"
6 |
7 | jobs:
8 | publish-openapi:
9 | uses: hmcts/workflow-publish-openapi-spec/.github/workflows/publish-openapi.yml@v1
10 | secrets:
11 | SWAGGER_PUBLISHER_API_TOKEN: ${{ secrets.SWAGGER_PUBLISHER_API_TOKEN }}
12 | with:
13 | test_to_run: 'uk.gov.hmcts.reform.demo.openapi.OpenAPIPublisherTest'
14 | java_version: 17
15 |
--------------------------------------------------------------------------------
/charts/rpe-spring-boot-template/.helmignore:
--------------------------------------------------------------------------------
1 | # Patterns to ignore when building packages.
2 | # This supports shell glob matching, relative path matching, and
3 | # negation (prefixed with !). Only one pattern per line.
4 | .DS_Store
5 | # Common VCS dirs
6 | .git/
7 | .gitignore
8 | .bzr/
9 | .bzrignore
10 | .hg/
11 | .hgignore
12 | .svn/
13 | # Common backup files
14 | *.swp
15 | *.bak
16 | *.tmp
17 | *~
18 | # Various IDEs
19 | .project
20 | .idea/
21 | *.tmproj
22 | .vscode/
23 |
--------------------------------------------------------------------------------
/src/main/java/uk/gov/hmcts/reform/demo/Application.java:
--------------------------------------------------------------------------------
1 | package uk.gov.hmcts.reform.demo;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | @SuppressWarnings("HideUtilityClassConstructor") // Spring needs a constructor, its not a utility class
8 | public class Application {
9 |
10 | public static void main(final String[] args) {
11 | SpringApplication.run(Application.class, args);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/lib/applicationinsights.json:
--------------------------------------------------------------------------------
1 | {
2 | "connectionString": "${file:/mnt/secrets/rpe/app-insights-connection-string}",
3 | "role": {
4 | "name": "rpe-demo"
5 | },
6 | "sampling": {
7 | "overrides": [
8 | {
9 | "telemetryType": "request",
10 | "attributes": [
11 | {
12 | "key": "http.url",
13 | "value": "https?://[^/]+/health.*",
14 | "matchType": "regexp"
15 | }
16 | ],
17 | "percentage": 1
18 | }
19 | ]
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: Template CI
2 |
3 | on:
4 | pull_request:
5 | branches:
6 | - master
7 | push:
8 | branches:
9 | - master
10 |
11 | jobs:
12 | build:
13 | runs-on: ubuntu-latest
14 | steps:
15 | - uses: actions/checkout@v4
16 | - uses: actions/setup-java@v4
17 | with:
18 | distribution: 'temurin' # See 'Supported distributions' for available options
19 | java-version: '17'
20 | cache: 'gradle'
21 | - name: Build
22 | run: ./gradlew check
23 |
--------------------------------------------------------------------------------
/charts/rpe-spring-boot-template/values.yaml:
--------------------------------------------------------------------------------
1 | java:
2 | applicationPort: 4550
3 | image: 'hmctspublic.azurecr.io/rpe/spring-boot-template:latest'
4 | ingressHost: rpe-spring-boot-template-{{ .Values.global.environment }}.service.core-compute-{{ .Values.global.environment }}.internal
5 | aadIdentityName: rpe
6 | # Uncomment once the vault containing the app insights key has been set up
7 | # keyVaults:
8 | # rpe:
9 | # secrets:
10 | # - name: AppInsightsInstrumentationKey
11 | # alias: azure.application-insights.instrumentation-key
12 | environment:
13 |
--------------------------------------------------------------------------------
/config/owasp/suppressions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | False Positive
6 |
7 |
8 | ^pkg:maven/com\.fasterxml\.jackson\.core/jackson\-databind@.*$
9 | CVE-2023-35116
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 | max_line_length = 120
12 |
13 | [*.java]
14 | indent_size = 4
15 | ij_continuation_indent_size = 4
16 | ij_java_align_multiline_parameters = true
17 | ij_java_align_multiline_parameters_in_calls = true
18 | ij_java_call_parameters_new_line_after_left_paren = true
19 | ij_java_call_parameters_right_paren_on_new_line = true
20 | ij_java_call_parameters_wrap = on_every_item
21 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | **Before creating a pull request make sure that:**
2 |
3 | - [ ] commit messages are meaningful and follow good commit message guidelines
4 | - [ ] README and other documentation has been updated / added (if needed)
5 | - [ ] tests have been updated / new tests has been added (if needed)
6 |
7 | Please remove this line and everything above and fill the following sections:
8 |
9 |
10 | ### JIRA link (if applicable) ###
11 |
12 |
13 |
14 | ### Change description ###
15 |
16 |
17 |
18 | **Does this PR introduce a breaking change?** (check one with "x")
19 |
20 | ```
21 | [ ] Yes
22 | [ ] No
23 | ```
24 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '2.1'
2 |
3 | services:
4 | spring-boot-template:
5 | build:
6 | context: .
7 | args:
8 | - http_proxy
9 | - https_proxy
10 | - no_proxy
11 | image: hmctspublic.azurecr.io/spring-boot/template
12 | environment:
13 | # these environment variables are used by java-logging library
14 | - ROOT_APPENDER
15 | - JSON_CONSOLE_PRETTY_PRINT
16 | - ROOT_LOGGING_LEVEL
17 | - REFORM_SERVICE_TYPE
18 | - REFORM_SERVICE_NAME
19 | - REFORM_TEAM
20 | - REFORM_ENVIRONMENT
21 | - LOGBACK_DATE_FORMAT
22 | - LOGBACK_REQUIRE_THREAD
23 | - LOGBACK_REQUIRE_ALERT_LEVEL=false
24 | - LOGBACK_REQUIRE_ERROR_CODE=false
25 | ports:
26 | - $SERVER_PORT:$SERVER_PORT
27 |
--------------------------------------------------------------------------------
/.github/stale.yml:
--------------------------------------------------------------------------------
1 | # Number of days of inactivity before an issue becomes stale
2 | daysUntilStale: 7
3 | # Number of days of inactivity before a stale issue is closed
4 | daysUntilClose: 4
5 | # Issues with these labels will never be considered stale
6 | exemptLabels:
7 | - pinned
8 | - dependencies
9 | # Label to use when marking an issue as stale
10 | staleLabel: stale
11 | # Comment to post when marking an issue as stale. Set to `false` to disable
12 | markComment: >
13 | This issue has been automatically marked as stale because it has not had
14 | recent activity. It will be closed if no further activity occurs. Thank you
15 | for your contributions.
16 | # Comment to post when closing a stale issue. Set to `false` to disable
17 | closeComment: >
18 | This issue is being closed automatically as it was stale
19 |
--------------------------------------------------------------------------------
/src/main/java/uk/gov/hmcts/reform/demo/controllers/RootController.java:
--------------------------------------------------------------------------------
1 | package uk.gov.hmcts.reform.demo.controllers;
2 |
3 | import org.springframework.http.ResponseEntity;
4 | import org.springframework.web.bind.annotation.GetMapping;
5 | import org.springframework.web.bind.annotation.RestController;
6 |
7 | import static org.springframework.http.ResponseEntity.ok;
8 |
9 | /**
10 | * Default endpoints per application.
11 | */
12 | @RestController
13 | public class RootController {
14 |
15 | /**
16 | * Root GET endpoint.
17 | *
18 | *
Azure application service has a hidden feature of making requests to root endpoint when
19 | * "Always On" is turned on.
20 | * This is the endpoint to deal with that and therefore silence the unnecessary 404s as a response code.
21 | *
22 | * @return Welcome message from the service.
23 | */
24 | @GetMapping("/")
25 | public ResponseEntity welcome() {
26 | return ok("Welcome to spring-boot-template");
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/uk/gov/hmcts/reform/demo/config/OpenAPIConfiguration.java:
--------------------------------------------------------------------------------
1 | package uk.gov.hmcts.reform.demo.config;
2 |
3 | import io.swagger.v3.oas.models.ExternalDocumentation;
4 | import io.swagger.v3.oas.models.OpenAPI;
5 | import io.swagger.v3.oas.models.info.Info;
6 | import io.swagger.v3.oas.models.info.License;
7 | import org.springframework.context.annotation.Bean;
8 | import org.springframework.context.annotation.Configuration;
9 |
10 | @Configuration
11 | public class OpenAPIConfiguration {
12 |
13 | @Bean
14 | public OpenAPI openAPI() {
15 | return new OpenAPI()
16 | .info(new Info().title("rpe demo")
17 | .description("rpe demo")
18 | .version("v0.0.1")
19 | .license(new License().name("MIT").url("https://opensource.org/licenses/MIT")))
20 | .externalDocs(new ExternalDocumentation()
21 | .description("README")
22 | .url("https://github.com/hmcts/spring-boot-template"));
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 HMCTS (HM Courts & Tribunals Service)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 |
--------------------------------------------------------------------------------
/src/integrationTest/java/uk/gov/hmcts/reform/demo/controllers/GetWelcomeTest.java:
--------------------------------------------------------------------------------
1 | package uk.gov.hmcts.reform.demo.controllers;
2 |
3 | import org.junit.jupiter.api.DisplayName;
4 | import org.junit.jupiter.api.Test;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
7 | import org.springframework.test.web.servlet.MockMvc;
8 | import org.springframework.test.web.servlet.MvcResult;
9 |
10 | import static org.assertj.core.api.Assertions.assertThat;
11 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
12 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
13 |
14 | @WebMvcTest
15 | class GetWelcomeTest {
16 |
17 | @Autowired
18 | private transient MockMvc mockMvc;
19 |
20 | @DisplayName("Should welcome upon root request with 200 response code")
21 | @Test
22 | void welcomeRootEndpoint() throws Exception {
23 | MvcResult response = mockMvc.perform(get("/")).andExpect(status().isOk()).andReturn();
24 |
25 | assertThat(response.getResponse().getContentAsString()).startsWith("Welcome");
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/smokeTest/java/uk/gov/hmcts/reform/demo/controllers/SampleSmokeTest.java:
--------------------------------------------------------------------------------
1 | package uk.gov.hmcts.reform.demo.controllers;
2 |
3 | import io.restassured.RestAssured;
4 | import io.restassured.http.ContentType;
5 | import io.restassured.response.Response;
6 | import org.junit.jupiter.api.Assertions;
7 | import org.junit.jupiter.api.BeforeEach;
8 | import org.junit.jupiter.api.Test;
9 | import org.springframework.beans.factory.annotation.Value;
10 | import org.springframework.boot.test.context.SpringBootTest;
11 |
12 | import static io.restassured.RestAssured.given;
13 |
14 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
15 | class SampleSmokeTest {
16 | @Value("${TEST_URL:http://localhost:4550}")
17 | private String testUrl;
18 |
19 | @BeforeEach
20 | public void setUp() {
21 | RestAssured.useRelaxedHTTPSValidation();
22 | }
23 |
24 | @Test
25 | void smokeTest() {
26 | Response response = given()
27 | .baseUri(testUrl)
28 | .contentType(ContentType.JSON)
29 | .when()
30 | .get()
31 | .then()
32 | .extract().response();
33 |
34 | Assertions.assertEquals(200, response.statusCode());
35 | Assertions.assertTrue(response.asString().startsWith("Welcome"));
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/functionalTest/java/uk/gov/hmcts/reform/demo/controllers/SampleFunctionalTest.java:
--------------------------------------------------------------------------------
1 | package uk.gov.hmcts.reform.demo.controllers;
2 |
3 | import io.restassured.RestAssured;
4 | import io.restassured.http.ContentType;
5 | import io.restassured.response.Response;
6 | import org.junit.jupiter.api.Assertions;
7 | import org.junit.jupiter.api.BeforeEach;
8 | import org.junit.jupiter.api.Test;
9 | import org.springframework.beans.factory.annotation.Value;
10 | import org.springframework.boot.test.context.SpringBootTest;
11 |
12 | import static io.restassured.RestAssured.given;
13 |
14 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
15 | class SampleFunctionalTest {
16 | protected static final String CONTENT_TYPE_VALUE = "application/json";
17 |
18 | @Value("${TEST_URL:http://localhost:8080}")
19 | private String testUrl;
20 |
21 | @BeforeEach
22 | public void setUp() {
23 | RestAssured.baseURI = testUrl;
24 | RestAssured.useRelaxedHTTPSValidation();
25 | }
26 |
27 | @Test
28 | void functionalTest() {
29 | Response response = given()
30 | .contentType(ContentType.JSON)
31 | .when()
32 | .get()
33 | .then()
34 | .extract().response();
35 |
36 | Assertions.assertEquals(200, response.statusCode());
37 | Assertions.assertTrue(response.asString().startsWith("Welcome"));
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/resources/application.yaml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 4550
3 | shutdown: "graceful"
4 |
5 | # If you use a database then uncomment the `group:, readiness: and include: "db"` lines in the health probes and uncomment the datasource section
6 | management:
7 | endpoint:
8 | health:
9 | show-details: "always"
10 | # group:
11 | # readiness:
12 | # include: "db"
13 | endpoints:
14 | web:
15 | base-path: /
16 | exposure:
17 | include: health, info, prometheus
18 |
19 | springdoc:
20 | packagesToScan: uk.gov.hmcts.reform.demo.controllers
21 | writer-with-order-by-keys: true
22 |
23 | spring:
24 | config:
25 | import: "optional:configtree:/mnt/secrets/rpe/"
26 | application:
27 | name: Spring Boot Template
28 | # datasource:
29 | # driver-class-name: org.postgresql.Driver
30 | # url: jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_NAME}${DB_OPTIONS:}
31 | # username: ${DB_USER_NAME}
32 | # password: ${DB_PASSWORD}
33 | # properties:
34 | # charSet: UTF-8
35 | # hikari:
36 | # minimumIdle: 2
37 | # maximumPoolSize: 10
38 | # idleTimeout: 10000
39 | # poolName: {to-be-defined}HikariCP
40 | # maxLifetime: 7200000
41 | # connectionTimeout: 30000
42 | # jpa:
43 | # properties:
44 | # hibernate:
45 | # jdbc:
46 | # lob:
47 | # # silence the 'wall-of-text' - unnecessary exception throw about blob types
48 | # non_contextual_creation: true
49 |
50 | azure:
51 | application-insights:
52 | instrumentation-key: ${rpe.AppInsightsInstrumentationKey:00000000-0000-0000-0000-000000000000}
53 |
--------------------------------------------------------------------------------
/src/integrationTest/java/uk/gov/hmcts/reform/demo/openapi/OpenAPIPublisherTest.java:
--------------------------------------------------------------------------------
1 | package uk.gov.hmcts.reform.demo.openapi;
2 |
3 | import org.junit.jupiter.api.DisplayName;
4 | import org.junit.jupiter.api.Test;
5 | import org.junit.jupiter.api.extension.ExtendWith;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
8 | import org.springframework.boot.test.context.SpringBootTest;
9 | import org.springframework.test.context.junit.jupiter.SpringExtension;
10 | import org.springframework.test.web.servlet.MockMvc;
11 |
12 | import java.io.OutputStream;
13 | import java.nio.file.Files;
14 | import java.nio.file.Paths;
15 |
16 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
17 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
18 |
19 | /**
20 | * Built-in feature which saves service's swagger specs in temporary directory.
21 | * Each CI run on master should automatically save and upload (if updated) documentation.
22 | */
23 | @ExtendWith(SpringExtension.class)
24 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
25 | @AutoConfigureMockMvc
26 | class OpenAPIPublisherTest {
27 |
28 | @Autowired
29 | private MockMvc mvc;
30 |
31 | @DisplayName("Generate swagger documentation")
32 | @Test
33 | @SuppressWarnings("PMD.JUnitTestsShouldIncludeAssert")
34 | void generateDocs() throws Exception {
35 | byte[] specs = mvc.perform(get("/v3/api-docs"))
36 | .andExpect(status().isOk())
37 | .andReturn()
38 | .getResponse()
39 | .getContentAsByteArray();
40 |
41 | try (OutputStream outputStream = Files.newOutputStream(Paths.get("/tmp/openapi-specs.json"))) {
42 | outputStream.write(specs);
43 | }
44 |
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/catalog-info.yaml:
--------------------------------------------------------------------------------
1 | # The below YAML is a template for a Backstage catalog-info.yaml file. It should be updated to match the details of your service/component where applicable.
2 | # For further information on how to update this file to use other features of HMCTS Backstage, please see the HMCTS Backstage examples README: https://github.com/hmcts/backstage-hmcts-examples
3 | apiVersion: backstage.io/v1alpha1
4 | kind: Component
5 | metadata:
6 | name: "${{ values.product }}-${{ values.component }}"
7 | description: "${{ values.description }}"
8 | annotations:
9 | # This should match folder-name/job-name in Jenkins.
10 | jenkins.io/job-full-name: cft:HMCTS_${{ values.product }}/${{ values.destination.repo }}
11 | github.com/project-slug: '${{ values.destination.owner }}/${{ values.destination.repo }}'
12 | tags:
13 | - java
14 | links:
15 | - url: https://hmcts-reform.slack.com/app_redirect?channel=${{ values.slack_contact_channel }}
16 | title: ${{ values.slack_contact_channel }} on Slack
17 | icon: chat
18 | spec:
19 | type: service
20 | system: ${{ values.product }}
21 | lifecycle: experimental
22 | owner: ${{ values.owner }}
23 |
24 | # Uncomment the below once the project has an API file to link to
25 | #---
26 | #
27 | #apiVersion: backstage.io/v1alpha1
28 | #kind: API
29 | #metadata:
30 | # name: "${{ values.description }}-api"
31 | # description: Update this description to describe the purpose of this API entity
32 | # annotations:
33 | # github.com/project-slug: '${{ values.destination.owner }}/${{ values.destination.repo }}'
34 | #spec:
35 | # type: openapi
36 | # lifecycle: experimental
37 | # owner: ${{ values.owner }}
38 | # system: ${{ values.product }}
39 | # apiProvidedBy: "${{ values.product }}-${{ values.component }}"
40 | # definition:
41 | # # Update the below to the raw URL of your OpenAPI spec
42 | # $text: https://raw.githubusercontent.com/hmcts/backstage-hmcts-examples/master/src/main/resources/openapi/testspec.yaml
43 |
--------------------------------------------------------------------------------
/bin/run-in-docker.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | print_help() {
4 | echo "Script to run docker containers for Spring Boot Template API service
5 |
6 | Usage:
7 |
8 | ./run-in-docker.sh [OPTIONS]
9 |
10 | Options:
11 | --clean, -c Clean and install current state of source code
12 | --install, -i Install current state of source code
13 | --param PARAM=, -p PARAM= Parse script parameter
14 | --help, -h Print this help block
15 |
16 | Available parameters:
17 |
18 | "
19 | }
20 |
21 | # script execution flags
22 | GRADLE_CLEAN=false
23 | GRADLE_INSTALL=false
24 |
25 | # TODO custom environment variables application requires.
26 | # TODO also consider enlisting them in help string above ^
27 | # TODO sample: DB_PASSWORD Defaults to 'dev'
28 | # environment variables
29 | #DB_PASSWORD=dev
30 | #S2S_URL=localhost
31 | #S2S_SECRET=secret
32 |
33 | execute_script() {
34 | cd $(dirname "$0")/..
35 |
36 | if [ ${GRADLE_CLEAN} = true ]
37 | then
38 | echo "Clearing previous build.."
39 | ./gradlew clean
40 | fi
41 |
42 | if [ ${GRADLE_INSTALL} = true ]
43 | then
44 | echo "Assembling distribution.."
45 | ./gradlew assemble
46 | fi
47 |
48 | # echo "Assigning environment variables.."
49 | #
50 | # export DB_PASSWORD=${DB_PASSWORD}
51 | # export S2S_URL=${S2S_URL}
52 | # export S2S_SECRET=${S2S_SECRET}
53 |
54 | echo "Bringing up docker containers.."
55 |
56 | docker compose up
57 | }
58 |
59 | while true ; do
60 | case "$1" in
61 | -h|--help) print_help ; shift ; break ;;
62 | -c|--clean) GRADLE_CLEAN=true ; GRADLE_INSTALL=true ; shift ;;
63 | -i|--install) GRADLE_INSTALL=true ; shift ;;
64 | -p|--param)
65 | case "$2" in
66 | # DB_PASSWORD=*) DB_PASSWORD="${2#*=}" ; shift 2 ;;
67 | # S2S_URL=*) S2S_URL="${2#*=}" ; shift 2 ;;
68 | # S2S_SECRET=*) S2S_SECRET="${2#*=}" ; shift 2 ;;
69 | *) shift 2 ;;
70 | esac ;;
71 | *) execute_script ; break ;;
72 | esac
73 | done
74 |
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contribution guidelines
2 |
3 | We're happy to accept 3rd-party contributions. Please make sure you read this document before you do any work though,
4 | as we have some expectations related to the content and quality of change sets.
5 |
6 | ## What you should know about this application
7 |
8 | This project is a template Spring Boot application. It aims to speed up the creation of new Spring APIs in HMCTS
9 | projects, by serving as the initial setup of each API.
10 |
11 | ## Before contributing
12 |
13 | Any ideas on the user journeys and general service experience you may have **should be first consulted
14 | with us by submitting a new issue** to this repository. Ideas are always welcome, but if something is divergent or unrelated
15 | to what we're trying to achieve we won't be able to accept it. Please keep this in mind as we don't want to waste anybody's time.
16 |
17 | In the interest of creating a friendly collaboration environment, please read and adhere to an open source contributor's
18 | [code of conduct](http://contributor-covenant.org/version/1/4/).
19 |
20 | ## Making a contribution
21 |
22 | After your idea has been accepted you can implement it. We don't allow direct changes to the codebase from the public,
23 | they have to go through a review first.
24 |
25 | Here's what you should do:
26 | 1. [fork](https://help.github.com/articles/fork-a-repo/) this repository and clone it to your machine,
27 | 2. create a new branch for your change:
28 | * use the latest *master* to branch from,
29 | 3. implement the change in your branch:
30 | * if the change is non-trivial it's a good practice to split it into several logically independent units and deliver
31 | each one as a separate commit,
32 | * make sure the commit messages use proper language and accurately describe commit's content, e.g. *"Unify postcode lookup elements spacing"*.
33 | More information on good commit messages can be found [here](http://chris.beams.io/posts/git-commit/),
34 | 4. test if your feature works as expected and does not break any existing features, this may include implementing additional automated tests or amending existing ones,
35 | 5. push the change to your GitHub fork,
36 | 6. submit a [pull request](https://help.github.com/articles/creating-a-pull-request-from-a-fork/) to our repository:
37 | * ensure that the pull request and related GitHub issue reference each other.
38 |
39 | At this point the pull request will wait for someone from our team to review. It may be accepted straight away,
40 | or we may ask you to make some additional amendments before incorporating it into the main branch.
41 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 | @rem SPDX-License-Identifier: Apache-2.0
17 | @rem
18 |
19 | @if "%DEBUG%"=="" @echo off
20 | @rem ##########################################################################
21 | @rem
22 | @rem Gradle startup script for Windows
23 | @rem
24 | @rem ##########################################################################
25 |
26 | @rem Set local scope for the variables with windows NT shell
27 | if "%OS%"=="Windows_NT" setlocal
28 |
29 | set DIRNAME=%~dp0
30 | if "%DIRNAME%"=="" set DIRNAME=.
31 | @rem This is normally unused
32 | set APP_BASE_NAME=%~n0
33 | set APP_HOME=%DIRNAME%
34 |
35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
37 |
38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
40 |
41 | @rem Find java.exe
42 | if defined JAVA_HOME goto findJavaFromJavaHome
43 |
44 | set JAVA_EXE=java.exe
45 | %JAVA_EXE% -version >NUL 2>&1
46 | if %ERRORLEVEL% equ 0 goto execute
47 |
48 | echo. 1>&2
49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
50 | echo. 1>&2
51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
52 | echo location of your Java installation. 1>&2
53 |
54 | goto fail
55 |
56 | :findJavaFromJavaHome
57 | set JAVA_HOME=%JAVA_HOME:"=%
58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
59 |
60 | if exist "%JAVA_EXE%" goto execute
61 |
62 | echo. 1>&2
63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
64 | echo. 1>&2
65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
66 | echo location of your Java installation. 1>&2
67 |
68 | goto fail
69 |
70 | :execute
71 | @rem Setup the command line
72 |
73 | set CLASSPATH=
74 |
75 |
76 | @rem Execute Gradle
77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
78 |
79 | :end
80 | @rem End local scope for the variables with windows NT shell
81 | if %ERRORLEVEL% equ 0 goto mainEnd
82 |
83 | :fail
84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
85 | rem the _cmd.exe /c_ return code!
86 | set EXIT_CODE=%ERRORLEVEL%
87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
89 | exit /b %EXIT_CODE%
90 |
91 | :mainEnd
92 | if "%OS%"=="Windows_NT" endlocal
93 |
94 | :omega
95 |
--------------------------------------------------------------------------------
/.github/workflows/codeql.yml:
--------------------------------------------------------------------------------
1 | # For most projects, this workflow file will not need changing; you simply need
2 | # to commit it to your repository.
3 | #
4 | # You may wish to alter this file to override the set of languages analyzed,
5 | # or to provide custom queries or build logic.
6 | #
7 | # ******** NOTE ********
8 | # We have attempted to detect the languages in your repository. Please check
9 | # the `language` matrix defined below to confirm you have the correct set of
10 | # supported CodeQL languages.
11 | #
12 | name: "CodeQL"
13 |
14 | on:
15 | push:
16 | branches: [ "master" ]
17 | pull_request:
18 | # The branches below must be a subset of the branches above
19 | branches: [ "master" ]
20 | schedule:
21 | - cron: '36 5 * * 4'
22 |
23 | jobs:
24 | analyze:
25 | name: Analyze
26 | runs-on: ubuntu-latest
27 | permissions:
28 | actions: read
29 | contents: read
30 | security-events: write
31 |
32 | strategy:
33 | fail-fast: false
34 | matrix:
35 | language: [ 'java' ]
36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
37 | # Use only 'java' to analyze code written in Java, Kotlin or both
38 | # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
39 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
40 |
41 | steps:
42 | - name: Checkout repository
43 | uses: actions/checkout@v4
44 |
45 | # Initializes the CodeQL tools for scanning.
46 | - name: Initialize CodeQL
47 | uses: github/codeql-action/init@v3
48 | with:
49 | languages: ${{ matrix.language }}
50 | # If you wish to specify custom queries, you can do so here or in a config file.
51 | # By default, queries listed here will override any specified in a config file.
52 | # Prefix the list here with "+" to use these queries and those in the config file.
53 |
54 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
55 | # queries: security-extended,security-and-quality
56 |
57 | - uses: actions/setup-java@v4
58 | with:
59 | distribution: 'temurin' # See 'Supported distributions' for available options
60 | java-version: '17'
61 |
62 |
63 | # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
64 | # If this step fails, then you should remove it and run the build manually (see below)
65 | - name: Autobuild
66 | uses: github/codeql-action/autobuild@v3
67 |
68 | # ℹ️ Command-line programs to run using the OS shell.
69 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
70 |
71 | # If the Autobuild fails above, remove it and uncomment the following three lines.
72 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
73 |
74 | # - run: |
75 | # echo "Run, Build Application using script"
76 | # ./location_of_script_within_repo/buildscript.sh
77 |
78 | - name: Perform CodeQL Analysis
79 | uses: github/codeql-action/analyze@v3
80 | with:
81 | category: "/language:${{matrix.language}}"
82 |
--------------------------------------------------------------------------------
/bin/init.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # Script to initialise project by executing steps as follows:
4 | # - Replace port number
5 | # - Replace package `demo`
6 | # - Replace slug from `spring-boot-template` to one of two (first in first used):
7 | # - user input
8 | # - git config value of the root project. Value in use: `remote.origin.url`
9 | # - Clean-up README file from template related info
10 | # - Self-destruct
11 |
12 | read -p "Port number for new app: " port
13 | read -p "Replace \`demo\` package name with: " package
14 | read -p "Repo product: (It's first part of the git repo name. Often a team name) " product_name
15 | read -p "Repo component: (It's second part of git repo name. Application name) " component_name
16 |
17 | pushd $(dirname "$0")/.. > /dev/null
18 |
19 | slug="$product_name-$component_name"
20 |
21 | declare -a files_with_port=(.env Dockerfile README.md src/main/resources/application.yaml charts/rpe-spring-boot-template/values.yaml)
22 | declare -a files_with_slug=(build.gradle docker-compose.yml Dockerfile README.md ./infrastructure/main.tf ./src/main/java/uk/gov/hmcts/reform/demo/controllers/RootController.java charts/rpe-spring-boot-template/Chart.yaml)
23 |
24 | # Replace in CNP file
25 | for i in "Jenkinsfile_template"
26 | do
27 | perl -i -pe "s/rpe/$product_name/g" ${i}
28 | perl -i -pe "s/demo/$component_name/g" ${i}
29 | done
30 |
31 | # Replace image repo
32 | for i in "charts/rpe-spring-boot-template/values.yaml"
33 | do
34 | perl -i -pe "s/rpe/$product_name/g" ${i}
35 | perl -i -pe "s/spring-boot-template/$component_name/g" ${i}
36 | done
37 |
38 | # Remove "rpe-" prefix from chart name to prepare it for spring-boot-template slug replacement and update maintainer name
39 | for i in "charts/rpe-spring-boot-template/Chart.yaml"
40 | do
41 | perl -i -pe "s/rpe-//g" ${i}
42 | perl -i -pe "s/rpe/$product_name/g" ${i}
43 | done
44 |
45 | # Update mount config and packagesToScan
46 | for i in "src/main/resources/application.yaml"
47 | do
48 | perl -i -pe "s/rpe/$product_name/g" ${i}
49 | perl -i -pe "s/reform.demo/reform.$package/g" ${i}
50 | done
51 |
52 | # Update app insights
53 | for i in "lib/applicationinsights.json"
54 | do
55 | perl -i -pe "s/rpe/$product_name/g" ${i}
56 | perl -i -pe "s/demo/$component_name/g" ${i}
57 | done
58 |
59 | # Replace port number
60 | for i in ${files_with_port[@]}
61 | do
62 | perl -i -pe "s/4550/$port/g" ${i}
63 | done
64 |
65 | # Replace spring-boot-template slug
66 | for i in ${files_with_slug[@]}
67 | do
68 | perl -i -pe "s/spring-boot-template/$slug/g" ${i}
69 | done
70 |
71 | # Replace demo package in all files under ./src
72 | find ./src -type f -print0 | xargs -0 perl -i -pe "s/reform.demo/reform.$package/g"
73 | find ./.github/workflows -type f -print0 | xargs -0 perl -i -pe "s/reform.demo/reform.$package/g"
74 | perl -i -pe "s/reform.demo/reform.$package/g" build.gradle
75 |
76 | # Rename charts directory
77 | git mv charts/rpe-spring-boot-template charts/${slug}
78 |
79 | # Rename directory to provided package name
80 | git mv src/functionalTest/java/uk/gov/hmcts/reform/demo/ src/functionalTest/java/uk/gov/hmcts/reform/${package}
81 | git mv src/integrationTest/java/uk/gov/hmcts/reform/demo/ src/integrationTest/java/uk/gov/hmcts/reform/${package}
82 | git mv src/main/java/uk/gov/hmcts/reform/demo/ src/main/java/uk/gov/hmcts/reform/${package}
83 | git mv src/smokeTest/java/uk/gov/hmcts/reform/demo/ src/smokeTest/java/uk/gov/hmcts/reform/${package}
84 |
85 | # Rename CNP file
86 | git mv Jenkinsfile_template Jenkinsfile_CNP
87 |
88 | declare -a headers_to_delete=("Purpose" "What's inside" "Plugins" "Setup" "Hystrix")
89 |
90 | # Clean-up README file
91 | for i in "${headers_to_delete[@]}"
92 | do
93 | perl -0777 -i -p0e "s/## $i.+?\n(## )/\$1/s" README.md
94 | done
95 |
96 | # Rename title to slug
97 | perl -i -pe "s/.*\n/# $slug\n/g if 1 .. 1" README.md
98 |
99 | # Self-destruct
100 | rm bin/init.sh
101 |
102 | # Return to original directory
103 | popd > /dev/null
104 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Spring Boot application template
2 |
3 | ## Purpose
4 |
5 | The purpose of this template is to speed up the creation of new Spring applications within HMCTS
6 | and help keep the same standards across multiple teams. If you need to create a new app, you can
7 | simply use this one as a starting point and build on top of it.
8 |
9 | ## What's inside
10 |
11 | The template is a working application with a minimal setup. It contains:
12 | * application skeleton
13 | * setup script to prepare project
14 | * common plugins and libraries
15 | * [HMCTS Java plugin](https://github.com/hmcts/gradle-java-plugin)
16 | * docker setup
17 | * automatically publishes API documentation to [hmcts/cnp-api-docs](https://github.com/hmcts/cnp-api-docs)
18 | * code quality tools already set up
19 | * MIT license and contribution information
20 | * Helm chart using chart-java.
21 |
22 | The application exposes health endpoint (http://localhost:4550/health) and metrics endpoint
23 | (http://localhost:4550/metrics).
24 |
25 | ## Plugins
26 |
27 | The template contains the following plugins:
28 |
29 | * HMCTS Java plugin
30 |
31 | Applies code analysis tools with HMCTS default settings. See the [project repository](https://github.com/hmcts/gradle-java-plugin) for details.
32 |
33 | Analysis tools include:
34 |
35 | * checkstyle
36 |
37 | https://docs.gradle.org/current/userguide/checkstyle_plugin.html
38 |
39 | Performs code style checks on Java source files using Checkstyle and generates reports from these checks.
40 | The checks are included in gradle's *check* task (you can run them by executing `./gradlew check` command).
41 |
42 | * org.owasp.dependencycheck
43 |
44 | https://jeremylong.github.io/DependencyCheck/dependency-check-gradle/index.html
45 |
46 | Provides monitoring of the project's dependent libraries and creating a report
47 | of known vulnerable components that are included in the build. To run it
48 | execute `gradle dependencyCheck` command.
49 |
50 | * jacoco
51 |
52 | https://docs.gradle.org/current/userguide/jacoco_plugin.html
53 |
54 | Provides code coverage metrics for Java code via integration with JaCoCo.
55 | You can create the report by running the following command:
56 |
57 | ```bash
58 | ./gradlew jacocoTestReport
59 | ```
60 |
61 | The report will be created in build/reports subdirectory in your project directory.
62 |
63 | * io.spring.dependency-management
64 |
65 | https://github.com/spring-gradle-plugins/dependency-management-plugin
66 |
67 | Provides Maven-like dependency management. Allows you to declare dependency management
68 | using `dependency 'groupId:artifactId:version'`
69 | or `dependency group:'group', name:'name', version:version'`.
70 |
71 | * org.springframework.boot
72 |
73 | http://projects.spring.io/spring-boot/
74 |
75 | Reduces the amount of work needed to create a Spring application
76 |
77 |
78 | * com.github.ben-manes.versions
79 |
80 | https://github.com/ben-manes/gradle-versions-plugin
81 |
82 | Provides a task to determine which dependencies have updates. Usage:
83 |
84 | ```bash
85 | ./gradlew dependencyUpdates -Drevision=release
86 | ```
87 |
88 | ## Setup
89 |
90 | Located in `./bin/init.sh`. Simply run and follow the explanation how to execute it.
91 |
92 | ## Building and deploying the application
93 |
94 | ### Building the application
95 |
96 | The project uses [Gradle](https://gradle.org) as a build tool. It already contains
97 | `./gradlew` wrapper script, so there's no need to install gradle.
98 |
99 | To build the project execute the following command:
100 |
101 | ```bash
102 | ./gradlew build
103 | ```
104 |
105 | ### Running the application
106 |
107 | Create the image of the application by executing the following command:
108 |
109 | ```bash
110 | ./gradlew assemble
111 | ```
112 |
113 | Note: Docker Compose V2 is highly recommended for building and running the application.
114 | In the Compose V2 old `docker-compose` command is replaced with `docker compose`.
115 |
116 | Create docker image:
117 |
118 | ```bash
119 | docker compose build
120 | ```
121 |
122 | Run the distribution (created in `build/install/spring-boot-template` directory)
123 | by executing the following command:
124 |
125 | ```bash
126 | docker compose up
127 | ```
128 |
129 | This will start the API container exposing the application's port
130 | (set to `4550` in this template app).
131 |
132 | In order to test if the application is up, you can call its health endpoint:
133 |
134 | ```bash
135 | curl http://localhost:4550/health
136 | ```
137 |
138 | You should get a response similar to this:
139 |
140 | ```
141 | {"status":"UP","diskSpace":{"status":"UP","total":249644974080,"free":137188298752,"threshold":10485760}}
142 | ```
143 |
144 | ### Alternative script to run application
145 |
146 | To skip all the setting up and building, just execute the following command:
147 |
148 | ```bash
149 | ./bin/run-in-docker.sh
150 | ```
151 |
152 | For more information:
153 |
154 | ```bash
155 | ./bin/run-in-docker.sh -h
156 | ```
157 |
158 | Script includes bare minimum environment variables necessary to start api instance. Whenever any variable is changed or any other script regarding docker image/container build, the suggested way to ensure all is cleaned up properly is by this command:
159 |
160 | ```bash
161 | docker compose rm
162 | ```
163 |
164 | It clears stopped containers correctly. Might consider removing clutter of images too, especially the ones fiddled with:
165 |
166 | ```bash
167 | docker images
168 |
169 | docker image rm
170 | ```
171 |
172 | There is no need to remove postgres and java or similar core images.
173 |
174 | ## License
175 |
176 | This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details
177 |
178 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 | # SPDX-License-Identifier: Apache-2.0
19 | #
20 |
21 | ##############################################################################
22 | #
23 | # Gradle start up script for POSIX generated by Gradle.
24 | #
25 | # Important for running:
26 | #
27 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
28 | # noncompliant, but you have some other compliant shell such as ksh or
29 | # bash, then to run this script, type that shell name before the whole
30 | # command line, like:
31 | #
32 | # ksh Gradle
33 | #
34 | # Busybox and similar reduced shells will NOT work, because this script
35 | # requires all of these POSIX shell features:
36 | # * functions;
37 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
38 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
39 | # * compound commands having a testable exit status, especially «case»;
40 | # * various built-in commands including «command», «set», and «ulimit».
41 | #
42 | # Important for patching:
43 | #
44 | # (2) This script targets any POSIX shell, so it avoids extensions provided
45 | # by Bash, Ksh, etc; in particular arrays are avoided.
46 | #
47 | # The "traditional" practice of packing multiple parameters into a
48 | # space-separated string is a well documented source of bugs and security
49 | # problems, so this is (mostly) avoided, by progressively accumulating
50 | # options in "$@", and eventually passing that to Java.
51 | #
52 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
53 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
54 | # see the in-line comments for details.
55 | #
56 | # There are tweaks for specific operating systems such as AIX, CygWin,
57 | # Darwin, MinGW, and NonStop.
58 | #
59 | # (3) This script is generated from the Groovy template
60 | # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
61 | # within the Gradle project.
62 | #
63 | # You can find Gradle at https://github.com/gradle/gradle/.
64 | #
65 | ##############################################################################
66 |
67 | # Attempt to set APP_HOME
68 |
69 | # Resolve links: $0 may be a link
70 | app_path=$0
71 |
72 | # Need this for daisy-chained symlinks.
73 | while
74 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
75 | [ -h "$app_path" ]
76 | do
77 | ls=$( ls -ld "$app_path" )
78 | link=${ls#*' -> '}
79 | case $link in #(
80 | /*) app_path=$link ;; #(
81 | *) app_path=$APP_HOME$link ;;
82 | esac
83 | done
84 |
85 | # This is normally unused
86 | # shellcheck disable=SC2034
87 | APP_BASE_NAME=${0##*/}
88 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
89 | APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
90 |
91 | # Use the maximum available, or set MAX_FD != -1 to use that value.
92 | MAX_FD=maximum
93 |
94 | warn () {
95 | echo "$*"
96 | } >&2
97 |
98 | die () {
99 | echo
100 | echo "$*"
101 | echo
102 | exit 1
103 | } >&2
104 |
105 | # OS specific support (must be 'true' or 'false').
106 | cygwin=false
107 | msys=false
108 | darwin=false
109 | nonstop=false
110 | case "$( uname )" in #(
111 | CYGWIN* ) cygwin=true ;; #(
112 | Darwin* ) darwin=true ;; #(
113 | MSYS* | MINGW* ) msys=true ;; #(
114 | NONSTOP* ) nonstop=true ;;
115 | esac
116 |
117 | CLASSPATH="\\\"\\\""
118 |
119 |
120 | # Determine the Java command to use to start the JVM.
121 | if [ -n "$JAVA_HOME" ] ; then
122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
123 | # IBM's JDK on AIX uses strange locations for the executables
124 | JAVACMD=$JAVA_HOME/jre/sh/java
125 | else
126 | JAVACMD=$JAVA_HOME/bin/java
127 | fi
128 | if [ ! -x "$JAVACMD" ] ; then
129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
130 |
131 | Please set the JAVA_HOME variable in your environment to match the
132 | location of your Java installation."
133 | fi
134 | else
135 | JAVACMD=java
136 | if ! command -v java >/dev/null 2>&1
137 | then
138 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
139 |
140 | Please set the JAVA_HOME variable in your environment to match the
141 | location of your Java installation."
142 | fi
143 | fi
144 |
145 | # Increase the maximum file descriptors if we can.
146 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
147 | case $MAX_FD in #(
148 | max*)
149 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
150 | # shellcheck disable=SC2039,SC3045
151 | MAX_FD=$( ulimit -H -n ) ||
152 | warn "Could not query maximum file descriptor limit"
153 | esac
154 | case $MAX_FD in #(
155 | '' | soft) :;; #(
156 | *)
157 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
158 | # shellcheck disable=SC2039,SC3045
159 | ulimit -n "$MAX_FD" ||
160 | warn "Could not set maximum file descriptor limit to $MAX_FD"
161 | esac
162 | fi
163 |
164 | # Collect all arguments for the java command, stacking in reverse order:
165 | # * args from the command line
166 | # * the main class name
167 | # * -classpath
168 | # * -D...appname settings
169 | # * --module-path (only if needed)
170 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
171 |
172 | # For Cygwin or MSYS, switch paths to Windows format before running java
173 | if "$cygwin" || "$msys" ; then
174 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
175 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
176 |
177 | JAVACMD=$( cygpath --unix "$JAVACMD" )
178 |
179 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
180 | for arg do
181 | if
182 | case $arg in #(
183 | -*) false ;; # don't mess with options #(
184 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
185 | [ -e "$t" ] ;; #(
186 | *) false ;;
187 | esac
188 | then
189 | arg=$( cygpath --path --ignore --mixed "$arg" )
190 | fi
191 | # Roll the args list around exactly as many times as the number of
192 | # args, so each arg winds up back in the position where it started, but
193 | # possibly modified.
194 | #
195 | # NB: a `for` loop captures its iteration list before it begins, so
196 | # changing the positional parameters here affects neither the number of
197 | # iterations, nor the values presented in `arg`.
198 | shift # remove old arg
199 | set -- "$@" "$arg" # push replacement arg
200 | done
201 | fi
202 |
203 |
204 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
205 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
206 |
207 | # Collect all arguments for the java command:
208 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
209 | # and any embedded shellness will be escaped.
210 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
211 | # treated as '${Hostname}' itself on the command line.
212 |
213 | set -- \
214 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
215 | -classpath "$CLASSPATH" \
216 | -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
217 | "$@"
218 |
219 | # Stop when "xargs" is not available.
220 | if ! command -v xargs >/dev/null 2>&1
221 | then
222 | die "xargs is not available"
223 | fi
224 |
225 | # Use "xargs" to parse quoted args.
226 | #
227 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
228 | #
229 | # In Bash we could simply go:
230 | #
231 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
232 | # set -- "${ARGS[@]}" "$@"
233 | #
234 | # but POSIX shell has neither arrays nor command substitution, so instead we
235 | # post-process each arg (as a line of input to sed) to backslash-escape any
236 | # character that might be a shell metacharacter, then use eval to reverse
237 | # that process (while maintaining the separation between arguments), and wrap
238 | # the whole thing up as a single "set" statement.
239 | #
240 | # This will of course break if any of these variables contains a newline or
241 | # an unmatched quote.
242 | #
243 |
244 | eval "set -- $(
245 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
246 | xargs -n1 |
247 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
248 | tr '\n' ' '
249 | )" '"$@"'
250 |
251 | exec "$JAVACMD" "$@"
252 |
--------------------------------------------------------------------------------