diff --git a/service-sdk/18.0.0/add-persistence-to-service/README.md b/service-sdk/18.0.0/add-persistence-to-service/README.md new file mode 100644 index 0000000..ce3ed44 --- /dev/null +++ b/service-sdk/18.0.0/add-persistence-to-service/README.md @@ -0,0 +1,3 @@ +This project contains code samples documented in the following section in [Backbase Community](https://community.backbase.com/documentation/ServiceSDK/latest/index): + +* [Add persistence to your capability](https://community.backbase.com/documentation/ServiceSDK/latest/add_persistence_to_core_service) diff --git a/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/README.md b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/README.md new file mode 100644 index 0000000..cfec37b --- /dev/null +++ b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/README.md @@ -0,0 +1,25 @@ +# example-service + +_Fill out this file with some information about your Service._ + +## Dependencies + +Requires a running Eureka registry, by default on port 8080. + +## Configuration + +Service configuration is under `src/main/resources/application.yaml`. + +## Running + +To run the service in development mode, use: +- `mvn spring-boot:run` + +To run the service from the built binaries, use: +- `java -jar target/example-persistence-service-1.0.0-SNAPSHOT.jar` + +## Authorization + +Requests to this service are authorized with a Backbase Internal JWT, therefore you must access this service via the Backbase Edge after authenticating with identity service. + +For local development, an internal JWT can be created from http://jwt.io, entering ```JWTSecretKeyDontUseInProduction!``` as the secret in the signature to generate a valid signed JWT. diff --git a/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/pom.xml b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/pom.xml new file mode 100644 index 0000000..8b13780 --- /dev/null +++ b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/pom.xml @@ -0,0 +1,76 @@ + + + 4.0.0 + + + + service-sdk-starter-core + com.backbase.buildingblocks + 16.0.0 + + + + com.backbase.example + example-persistence-service + 1.0.0-SNAPSHOT + Backbase :: Digital Banking Services :: example-persistence-service + + + 17 + + + + + + + com.backbase.buildingblocks + persistence + + + com.backbase.buildingblocks + service-sdk-starter-mapping + + + org.springframework.boot + spring-boot-starter-cache + + + + com.h2database + h2 + 2.1.214 + test + + + + com.mysql + mysql-connector-j + test + + + + + com.backbase.buildingblocks + service-sdk-starter-test + test + + + + + + + + + diff --git a/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/java/com/backbase/example/Application.java b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/java/com/backbase/example/Application.java new file mode 100644 index 0000000..b01f872 --- /dev/null +++ b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/java/com/backbase/example/Application.java @@ -0,0 +1,21 @@ +package com.backbase.example; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; + +// tag::application-annotations[] +@SpringBootApplication +@EnableDiscoveryClient +@EnableJpaRepositories +@EntityScan +public class Application extends SpringBootServletInitializer { +// end::application-annotations[] + public static void main(final String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/java/com/backbase/example/Message.java b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/java/com/backbase/example/Message.java new file mode 100644 index 0000000..5b706d5 --- /dev/null +++ b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/java/com/backbase/example/Message.java @@ -0,0 +1,61 @@ +package com.backbase.example; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +import jakarta.annotation.Generated; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@Generated("org.jsonschema2pojo") +@JsonPropertyOrder({ + "message" +}) +@JsonIgnoreProperties(ignoreUnknown = true) +public class Message { + + /** + * + * (Required) + * + */ + @JsonProperty("id") + @NotNull + private String id; + + /** + * Greetings message + */ + @JsonProperty("message") + @Size(max = 255) + @NotNull + private String message; + + public Message() { + } + + public Message(String id, String message) { + this.id = id; + this.message = message; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + +} diff --git a/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/java/com/backbase/example/api/ExampleController.java b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/java/com/backbase/example/api/ExampleController.java new file mode 100644 index 0000000..0955898 --- /dev/null +++ b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/java/com/backbase/example/api/ExampleController.java @@ -0,0 +1,48 @@ +package com.backbase.example.api; + +import com.backbase.example.Message; +import com.backbase.example.domain.Greeting; +import com.backbase.example.mapper.GreetingsMapper; +import com.backbase.example.service.GreetingsService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.UUID; + +@RestController +public class ExampleController { + + @Autowired + private GreetingsService greetingsService; + + @RequestMapping(method = RequestMethod.GET, value = "/message/{id}", produces = { + "application/json" + }) + @ResponseStatus(HttpStatus.OK) + public Message getMessage(@PathVariable(name = "id") String id) { + Greeting greeting = greetingsService.getGreetingById(id); + return GreetingsMapper.INSTANCE.greetingToMessage(greeting); + } + + @RequestMapping(method = RequestMethod.GET, value = "/messages", produces = { + "application/json" + }) + @ResponseStatus(HttpStatus.OK) + public List getMessages() { + List greetings = greetingsService.getGreetings(); + return GreetingsMapper.INSTANCE.greetingsToMessages(greetings); + } +// tag::addMessage[] + @RequestMapping(method = RequestMethod.POST, value = "/message") + @ResponseStatus(HttpStatus.CREATED) + public String addMessage(@RequestBody Message message) { + Greeting greeting = GreetingsMapper.INSTANCE.messageToGreeting(message); + String id = UUID.randomUUID().toString(); + greeting.setId(id); + greetingsService.addNewGreeting(greeting); + return id; + } +// end::addMessage[] +} diff --git a/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/java/com/backbase/example/domain/Greeting.java b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/java/com/backbase/example/domain/Greeting.java new file mode 100644 index 0000000..01bc7fd --- /dev/null +++ b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/java/com/backbase/example/domain/Greeting.java @@ -0,0 +1,31 @@ +package com.backbase.example.domain; + +import jakarta.persistence.*; + +@Entity +@Table(name = "greetings") +public class Greeting { + + @Id + @Column(name = "id") + private String id; + + @Column(name = "message") + private String message; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/java/com/backbase/example/mapper/GreetingsMapper.java b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/java/com/backbase/example/mapper/GreetingsMapper.java new file mode 100644 index 0000000..38028ee --- /dev/null +++ b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/java/com/backbase/example/mapper/GreetingsMapper.java @@ -0,0 +1,19 @@ +package com.backbase.example.mapper; + +import com.backbase.example.Message; +import com.backbase.example.domain.Greeting; +import org.mapstruct.Mapper; +import org.mapstruct.ReportingPolicy; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +@Mapper(unmappedTargetPolicy= ReportingPolicy.ERROR) +public interface GreetingsMapper { + + GreetingsMapper INSTANCE = Mappers.getMapper( GreetingsMapper.class); + + Message greetingToMessage(Greeting greeting); + List greetingsToMessages(List greetings); + Greeting messageToGreeting(Message message); +} diff --git a/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/java/com/backbase/example/repository/GreetingsRepository.java b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/java/com/backbase/example/repository/GreetingsRepository.java new file mode 100644 index 0000000..1511c66 --- /dev/null +++ b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/java/com/backbase/example/repository/GreetingsRepository.java @@ -0,0 +1,14 @@ +package com.backbase.example.repository; + +import com.backbase.example.domain.Greeting; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface GreetingsRepository extends CrudRepository { + + @Override + List findAll(); +} diff --git a/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/java/com/backbase/example/service/GreetingsService.java b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/java/com/backbase/example/service/GreetingsService.java new file mode 100644 index 0000000..790f3c2 --- /dev/null +++ b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/java/com/backbase/example/service/GreetingsService.java @@ -0,0 +1,14 @@ +package com.backbase.example.service; + +import com.backbase.example.domain.Greeting; + +import java.util.List; + +public interface GreetingsService { + + List getGreetings(); + + Greeting getGreetingById(String id); + + void addNewGreeting(Greeting greeting); +} diff --git a/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/java/com/backbase/example/service/GreetingsServiceImpl.java b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/java/com/backbase/example/service/GreetingsServiceImpl.java new file mode 100644 index 0000000..6b4a54e --- /dev/null +++ b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/java/com/backbase/example/service/GreetingsServiceImpl.java @@ -0,0 +1,44 @@ +package com.backbase.example.service; + +import com.backbase.example.domain.Greeting; +import com.backbase.example.repository.GreetingsRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.stereotype.Service; + +import java.util.List; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional(readOnly=true) +public class GreetingsServiceImpl implements GreetingsService { + + private static final Logger log = LoggerFactory.getLogger(GreetingsServiceImpl.class); + + @Autowired + private GreetingsRepository greetingsRepository; + + @Override + @PreAuthorize("permitAll()") + public List getGreetings() { + log.debug("Service getGreetings is called {}", 1); + return greetingsRepository.findAll(); + } + + @Override + @PreAuthorize("permitAll()") + public Greeting getGreetingById(String id) { + log.debug("Service getGreetingById is called {}", id); + return greetingsRepository.findById(id).get(); + } + + @Override + @PreAuthorize("permitAll()") + @Transactional + public void addNewGreeting(Greeting greeting) { + log.debug("Service addNewGreeting is called {}", 1); + greetingsRepository.save(greeting); + } +} diff --git a/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/resources/application.yaml b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/resources/application.yaml new file mode 100644 index 0000000..a888a2c --- /dev/null +++ b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/resources/application.yaml @@ -0,0 +1,57 @@ +server: + port: 9915 + +# API Registry client configuration +eureka: + instance: + metadata-map: + public: true + role: live + client: + serviceUrl: + defaultZone: http://localhost:8761/eureka/ + +# Configure Internal JWT handler +sso: + jwt: + internal: + signature: + key: + type: ENV + value: SIG_SECRET_KEY + +# Spring health monitoring +management: + health: + jms: + enabled: false + +#spring: +# datasource: +# url: jdbc:mysql://localhost:3306/greetings +# username: greetings +# password: Gr33:t1ngs +# driver-class-name: com.mysql.cj.jdbc.Driver +# jpa: +# database: mysql +# generate-ddl: false +spring: + h2: + console: + enabled: true + datasource: + url: jdbc:h2:mem:greetingsdb;Mode=Oracle + jpa: + generate-ddl: false + liquibase: + enabled: true + change-log: classpath:db/changelog/db.changelog-persistence.xml + sql: + init: + platform: h2 + continue-on-error: true + +buildingblocks: + security: + xss: + autoconfig: false \ No newline at end of file diff --git a/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/resources/banner.txt b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/resources/banner.txt new file mode 100644 index 0000000..3e84197 --- /dev/null +++ b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/resources/banner.txt @@ -0,0 +1,9 @@ + ________ ________ ________ ___ __ ________ ________ ________ _______ +|\ __ \|\ __ \|\ ____\|\ \|\ \ |\ __ \|\ __ \|\ ____\|\ ___ \ +\ \ \|\ /\ \ \|\ \ \ \___|\ \ \/ /|\ \ \|\ /\ \ \|\ \ \ \___|\ \ __/| + \ \ __ \ \ __ \ \ \ \ \ ___ \ \ __ \ \ __ \ \_____ \ \ \_|/__ + \ \ \|\ \ \ \ \ \ \ \____\ \ \\ \ \ \ \|\ \ \ \ \ \|____|\ \ \ \_|\ \ + \ \_______\ \__\ \__\ \_______\ \__\\ \__\ \_______\ \__\ \__\____\_\ \ \_______\ + \|_______|\|__|\|__|\|_______|\|__| \|__|\|_______|\|__|\|__|\_________\|_______| + \|_________| + diff --git a/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/resources/bootstrap.yaml b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/resources/bootstrap.yaml new file mode 100644 index 0000000..3767fe9 --- /dev/null +++ b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/resources/bootstrap.yaml @@ -0,0 +1,3 @@ +spring: + application: + name: example-service diff --git a/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/resources/db/changelog/db.changelog-1.0.0.xml new file mode 100644 index 0000000..f7c24c1 --- /dev/null +++ b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/resources/db/changelog/db.changelog-1.0.0.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + create the greeting table + + + + + + + + + + + \ No newline at end of file diff --git a/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/resources/db/changelog/db.changelog-persistence.xml b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/resources/db/changelog/db.changelog-persistence.xml new file mode 100644 index 0000000..f72c4f3 --- /dev/null +++ b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/resources/db/changelog/db.changelog-persistence.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/webapp/WEB-INF/jboss-deployment-structure.xml b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/webapp/WEB-INF/jboss-deployment-structure.xml new file mode 100644 index 0000000..267d618 --- /dev/null +++ b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/main/webapp/WEB-INF/jboss-deployment-structure.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + diff --git a/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/test/java/com/backbase/example/ExampleControllerIT.java b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/test/java/com/backbase/example/ExampleControllerIT.java new file mode 100644 index 0000000..a2bad70 --- /dev/null +++ b/service-sdk/18.0.0/add-persistence-to-service/example-persistence-service/src/test/java/com/backbase/example/ExampleControllerIT.java @@ -0,0 +1,121 @@ +package com.backbase.example; + + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.security.web.csrf.CsrfToken; +import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ActiveProfiles; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.http.MediaType; + +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; + + +/** + * A wrapper annotation for use with integration tests. + * + * By default, assumes the integration test modifies the + * {@link org.springframework.context.ApplicationContext} associated with the test/s and will therefore be + * closed and removed from the context cache at the end of the class. + */ +@SpringBootTest(classes = Application.class) +@DirtiesContext(classMode = ClassMode.AFTER_CLASS) +@AutoConfigureMockMvc +@ActiveProfiles("it") +class ExampleControllerIT { + + String TOKEN_ATTR_NAME = "org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN"; + + public static final String TEST_JWT = + "Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsIm5hZiI6MTUwNjUyNzQzMSwiY25leHAiOnRydWUsImdycCI6" + + "WyJhZG1pbihBRE1JTikiXSwiYW5sb2MiOnRydWUsImFuZXhwIjp0cnVlLCJlbmJsIjp0cnVlLCJleHAiOjE1MDY1" + + "MjU5MzEsImlhdCI6MTUwNjUyNTYzMSwicm9sIjpbIlJPTEVfQUNUVUFUT1IiLCJST0xFX0FETUlOIiwiUk9MRV9nc" + + "m91cF9hZG1pbihBRE1JTikiXSwianRpIjoiMjQ1MDBkNDQtNDRiZS00MTI1LTg4MjctOWY1NDAwOTc4NmEzIn0.5qZ" + + "nncyJpWJ8GqklJK6RmyHUUPddNOh52al65_C4T9o"; + @Autowired + private MockMvc mvc; + + @Test + void exampleTest() throws Exception { + String greetingsId = givenAGreetingExists(); + whenWeGetTheMessageByIdThenTheMessageExists(greetingsId); + WhenWeGetAllMessagesThenAListOfMessagesIsReturned(); + } + + private void WhenWeGetAllMessagesThenAListOfMessagesIsReturned() throws Exception { + //When: Request for all messages + MockHttpServletRequestBuilder getAllMessagesRequestBuilder = get("/messages") + .header("Authorization", TEST_JWT); + + ResultActions getAllMessagesResult = mvc.perform(getAllMessagesRequestBuilder).andDo(print()); + + // Then the request is successful with a list of messages + getAllMessagesResult.andExpect(status().isOk()); + + List listOfMessages = new ObjectMapper().readValue(getAllMessagesResult.andReturn().getResponse().getContentAsString(), + new TypeReference<>() {}); + + assertThat(listOfMessages).hasSizeGreaterThan(0); + } + + private void whenWeGetTheMessageByIdThenTheMessageExists(String greetingsId) throws Exception { + //When: we get that message + MockHttpServletRequestBuilder getMessageRequestBuilder = get("/message/" + greetingsId) + .header("Authorization", TEST_JWT); + + ResultActions result = mvc.perform(getMessageRequestBuilder).andDo(print()); + + result = result.andExpect(status().isOk()); + + MvcResult response = result.andExpect(content().contentType(MediaType.APPLICATION_JSON)).andReturn(); + + String responseBody = response.getResponse().getContentAsString(); + + //Then: the message exists + assertThat(responseBody).contains("Hello World").as("ID in response should match ID in request"); + } + + private String givenAGreetingExists() throws Exception { + //Given: a message exists + Message message = new Message(); + message.setMessage("Hello World is it me your looking for?"); + + String messageAsString = new ObjectMapper().writeValueAsString(message); + + HttpSessionCsrfTokenRepository httpSessionCsrfTokenRepository = new HttpSessionCsrfTokenRepository(); + CsrfToken csrfToken = httpSessionCsrfTokenRepository.generateToken(new MockHttpServletRequest()); + + MockHttpServletRequestBuilder postRequestBuilder = post("/message") + .header("Authorization", TEST_JWT) + .sessionAttr(TOKEN_ATTR_NAME, csrfToken) + .param(csrfToken.getParameterName(), csrfToken.getToken()) + .contentType(MediaType.APPLICATION_JSON_UTF8) + .content(messageAsString); + + ResultActions postResult = mvc.perform(postRequestBuilder).andDo(print()); + + postResult.andExpect(status().isCreated()); + + return postResult.andReturn().getResponse().getContentAsString(); + } +} diff --git a/service-sdk/18.0.0/create-core-service/README.md b/service-sdk/18.0.0/create-core-service/README.md new file mode 100644 index 0000000..0af4aec --- /dev/null +++ b/service-sdk/18.0.0/create-core-service/README.md @@ -0,0 +1,3 @@ +This project contains code samples documented in the following sections in [Backbase Community](https://community.backbase.com/documentation/ServiceSDK/latest/index): + +* [Create a service with the core-service-archetype](https://community.backbase.com/documentation/ServiceSDK/latest/create_a_core_service) diff --git a/service-sdk/18.0.0/create-core-service/example-core-service/README.md b/service-sdk/18.0.0/create-core-service/example-core-service/README.md new file mode 100644 index 0000000..46ccc0b --- /dev/null +++ b/service-sdk/18.0.0/create-core-service/example-core-service/README.md @@ -0,0 +1,25 @@ +# example-service + +_Fill out this file with some information about your Service._ + +## Dependencies + +Requires a running Eureka registry, by default on port 8080. + +## Configuration + +Service configuration is under `src/main/resources/application.yaml`. + +## Running + +To run the service in development mode, use: +- `mvn spring-boot:run` + +To run the service from the built binaries, use: +- `java -jar target/example-core-service-1.0.0-SNAPSHOT.jar` + +## Authorization + +Requests to this service are authorized with a Backbase Internal JWT, therefore you must access this service via the Backbase Edge after authenticating with Identity service. + +For local development, an internal JWT can be created from http://jwt.io, entering ```JWTSecretKeyDontUseInProduction!``` as the secret in the signature to generate a valid signed JWT. diff --git a/service-sdk/18.0.0/create-core-service/example-core-service/pom.xml b/service-sdk/18.0.0/create-core-service/example-core-service/pom.xml new file mode 100644 index 0000000..51f6e33 --- /dev/null +++ b/service-sdk/18.0.0/create-core-service/example-core-service/pom.xml @@ -0,0 +1,47 @@ + + + 4.0.0 + + + + service-sdk-starter-core + com.backbase.buildingblocks + 16.0.0 + + + + com.backbase.example + example-core-service + 1.0.0-SNAPSHOT + Backbase :: Digital Banking Services :: example-core-service + + + 17 + + + + + com.backbase.buildingblocks + service-sdk-starter-test + test + + + + + + + + + diff --git a/service-sdk/18.0.0/create-core-service/example-core-service/src/main/java/com/backbase/example/Application.java b/service-sdk/18.0.0/create-core-service/example-core-service/src/main/java/com/backbase/example/Application.java new file mode 100644 index 0000000..37acffd --- /dev/null +++ b/service-sdk/18.0.0/create-core-service/example-core-service/src/main/java/com/backbase/example/Application.java @@ -0,0 +1,16 @@ +package com.backbase.example; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; + +@SpringBootApplication +@EnableDiscoveryClient +public class Application extends SpringBootServletInitializer { + + public static void main(final String[] args) { + SpringApplication.run(Application.class, args); + } + +} \ No newline at end of file diff --git a/service-sdk/18.0.0/create-core-service/example-core-service/src/main/java/com/backbase/example/Message.java b/service-sdk/18.0.0/create-core-service/example-core-service/src/main/java/com/backbase/example/Message.java new file mode 100644 index 0000000..8def353 --- /dev/null +++ b/service-sdk/18.0.0/create-core-service/example-core-service/src/main/java/com/backbase/example/Message.java @@ -0,0 +1,17 @@ +package com.backbase.example; + +public class Message { + private String message; + + public Message(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/service-sdk/18.0.0/create-core-service/example-core-service/src/main/java/com/backbase/example/api/ExampleController.java b/service-sdk/18.0.0/create-core-service/example-core-service/src/main/java/com/backbase/example/api/ExampleController.java new file mode 100644 index 0000000..4dbe9a0 --- /dev/null +++ b/service-sdk/18.0.0/create-core-service/example-core-service/src/main/java/com/backbase/example/api/ExampleController.java @@ -0,0 +1,20 @@ +package com.backbase.example.api; + +import com.backbase.example.Message; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RequestMethod; + +@RestController +public class ExampleController { + + @RequestMapping(method = RequestMethod.GET, value = "/message", produces = { + "application/json" + }) + @ResponseStatus(HttpStatus.OK) + public Message getMessage() { + return new Message("Hello World"); + } +} \ No newline at end of file diff --git a/service-sdk/18.0.0/create-core-service/example-core-service/src/main/resources/application.yaml b/service-sdk/18.0.0/create-core-service/example-core-service/src/main/resources/application.yaml new file mode 100644 index 0000000..bd86e36 --- /dev/null +++ b/service-sdk/18.0.0/create-core-service/example-core-service/src/main/resources/application.yaml @@ -0,0 +1,27 @@ +server: + port: 9915 + +# API Registry client configuration +eureka: + instance: + metadata-map: + public: true + role: live + client: + serviceUrl: + defaultZone: http://localhost:8761/eureka/ + +# Configure Internal JWT handler +sso: + jwt: + internal: + signature: + key: + type: ENV + value: SIG_SECRET_KEY + +# Spring health monitoring +management: + health: + jms: + enabled: false \ No newline at end of file diff --git a/service-sdk/18.0.0/create-core-service/example-core-service/src/main/resources/banner.txt b/service-sdk/18.0.0/create-core-service/example-core-service/src/main/resources/banner.txt new file mode 100644 index 0000000..3e84197 --- /dev/null +++ b/service-sdk/18.0.0/create-core-service/example-core-service/src/main/resources/banner.txt @@ -0,0 +1,9 @@ + ________ ________ ________ ___ __ ________ ________ ________ _______ +|\ __ \|\ __ \|\ ____\|\ \|\ \ |\ __ \|\ __ \|\ ____\|\ ___ \ +\ \ \|\ /\ \ \|\ \ \ \___|\ \ \/ /|\ \ \|\ /\ \ \|\ \ \ \___|\ \ __/| + \ \ __ \ \ __ \ \ \ \ \ ___ \ \ __ \ \ __ \ \_____ \ \ \_|/__ + \ \ \|\ \ \ \ \ \ \ \____\ \ \\ \ \ \ \|\ \ \ \ \ \|____|\ \ \ \_|\ \ + \ \_______\ \__\ \__\ \_______\ \__\\ \__\ \_______\ \__\ \__\____\_\ \ \_______\ + \|_______|\|__|\|__|\|_______|\|__| \|__|\|_______|\|__|\|__|\_________\|_______| + \|_________| + diff --git a/service-sdk/18.0.0/create-core-service/example-core-service/src/main/resources/bootstrap.yaml b/service-sdk/18.0.0/create-core-service/example-core-service/src/main/resources/bootstrap.yaml new file mode 100644 index 0000000..3767fe9 --- /dev/null +++ b/service-sdk/18.0.0/create-core-service/example-core-service/src/main/resources/bootstrap.yaml @@ -0,0 +1,3 @@ +spring: + application: + name: example-service diff --git a/service-sdk/18.0.0/create-core-service/example-core-service/src/test/java/com/backbase/example/ExampleControllerIT.java b/service-sdk/18.0.0/create-core-service/example-core-service/src/test/java/com/backbase/example/ExampleControllerIT.java new file mode 100644 index 0000000..4b9eab8 --- /dev/null +++ b/service-sdk/18.0.0/create-core-service/example-core-service/src/test/java/com/backbase/example/ExampleControllerIT.java @@ -0,0 +1,65 @@ +package com.backbase.example; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContext; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.http.MediaType; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; + +/** + * A wrapper annotation for use with integration tests. + * + * By default, assumes the integration test modifies the + * {@link ApplicationContext} associated with the test/s and will therefore be + * closed and removed from the context cache at the end of the class. + */ +@SpringBootTest(classes = Application.class) +@DirtiesContext(classMode = ClassMode.AFTER_CLASS) +@AutoConfigureMockMvc +@ActiveProfiles("it") +public class ExampleControllerIT { + + public static final String TEST_JWT = + "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxk" + + "ZXIiLCJpYXQiOjE0ODQ4MjAxOTYsImV4cCI6MTUxNjM1NjE5NiwiYXVkIjoid3d3LmV4YW1wbGUuY29tIiwic3ViIjoianJv" + + "Y2tldEBleGFtcGxlLmNvbSIsIkdpdmVuTmFtZSI6IkpvaG5ueSIsIlN1cm5hbWUiOiJSb2NrZXQiLCJFbWFpbCI6Impyb2Nr" + + "ZXRAZXhhbXBsZS5jb20iLCJSb2xlIjpbIk1hbmFnZXIiLCJQcm9qZWN0IEFkbWluaXN0cmF0b3IiXSwiaW51aWQiOiJKaW1te" + + "SJ9.O9TE28ygrHmDjItYK6wRis6wELD5Wtpi6ekeYfR1WqM"; + @Autowired + private MockMvc mvc; + + @Test + public void exampleTest() throws Exception { + + + MockHttpServletRequestBuilder requestBuilder = get("/message") + .header("Authorization", TEST_JWT); + + ResultActions result = mvc.perform(requestBuilder).andDo(print()); + + // Then the request is successful + result = result.andExpect(status().isOk()); + + // And a response is returned + MvcResult response = result.andExpect(content().contentType(MediaType.APPLICATION_JSON)).andReturn(); + + // Check response + String responseBody = response.getResponse().getContentAsString(); + + assertThat(responseBody).contains("Hello World").as("ID in response should match ID in request"); + } +} diff --git a/service-sdk/18.0.0/create-openapi-client/banking-service/README.md b/service-sdk/18.0.0/create-openapi-client/banking-service/README.md new file mode 100644 index 0000000..e20a95a --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-client/banking-service/README.md @@ -0,0 +1,42 @@ +# banking-service + +_Fill out this file with some information about your Service._ + +#Getting Started +* [Extend and build](https://community.backbase.com/documentation/ServiceSDK/latest/extend_and_build) + +## Dependencies + +Requires a running Eureka registry, by default on port 8080. + +## Configuration + +Service configuration is under `src/main/resources/application.yaml`. + +## Running + +To run the service in development mode, use: +- `mvn spring-boot:run` + +To run the service from the built binaries, use: +- `java -jar target/banking-service-1.0.0-SNAPSHOT.jar` + +## Authorization + +Requests to this service are authorized with a Backbase Internal JWT, therefore you must access this service via the +Backbase Edge after authenticating with Identity service. + +For local development, an internal JWT can be created from http://jwt.io, entering `JWTSecretKeyDontUseInProduction!` +as the secret in the signature to generate a valid signed JWT. + +## Community Documentation + +Add links to documentation including setup, config, etc. + +## Jira Project + +Add link to Jira project. + +## Confluence Links +Links to relevant confluence pages (design etc). + diff --git a/service-sdk/18.0.0/create-openapi-client/banking-service/pom.xml b/service-sdk/18.0.0/create-openapi-client/banking-service/pom.xml new file mode 100644 index 0000000..69a8d97 --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-client/banking-service/pom.xml @@ -0,0 +1,91 @@ + + 4.0.0 + + + + com.backbase.buildingblocks + service-sdk-starter-core + 16.0.0 + + + + com.backbase.banking + banking-service + 1.0.0-SNAPSHOT + Backbase :: banking-service + + + 17 + 0.17.5 + + + + + + + io.swagger.core.v3 + swagger-annotations + + + + org.openapitools + jackson-databind-nullable + + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + + + + com.backbase.buildingblocks + communication + + + + + com.backbase.buildingblocks + service-sdk-starter-test + test + + + + + + + + + com.backbase.oss + boat-maven-plugin + ${boat-maven-plugin.version} + + + generate-service-name-client-code + generate-sources + + generate-rest-template-embedded + + + + https://raw.githubusercontent.com/Backbase/documentation-code-samples/master/service-sdk/11.0.0/create-openapi-spec-project/messaging-api/src/main/resources/openapi.yaml + + com.backbase.messaging.api.client.v2 + com.backbase.messaging.api.client.v2.model + + + + + + + + + + diff --git a/service-sdk/18.0.0/create-openapi-client/banking-service/src/main/java/com/backbase/banking/Application.java b/service-sdk/18.0.0/create-openapi-client/banking-service/src/main/java/com/backbase/banking/Application.java new file mode 100644 index 0000000..7f9fea4 --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-client/banking-service/src/main/java/com/backbase/banking/Application.java @@ -0,0 +1,16 @@ +package com.backbase.banking; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; + +@SpringBootApplication +@EnableDiscoveryClient +public class Application extends SpringBootServletInitializer { + + public static void main(final String[] args) { + SpringApplication.run(Application.class, args); + } + +} \ No newline at end of file diff --git a/service-sdk/18.0.0/create-openapi-client/banking-service/src/main/java/com/backbase/banking/Message.java b/service-sdk/18.0.0/create-openapi-client/banking-service/src/main/java/com/backbase/banking/Message.java new file mode 100644 index 0000000..cf86d79 --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-client/banking-service/src/main/java/com/backbase/banking/Message.java @@ -0,0 +1,17 @@ +package com.backbase.banking; + +public class Message { + private String message; + + public Message(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/service-sdk/18.0.0/create-openapi-client/banking-service/src/main/java/com/backbase/banking/api/ExampleController.java b/service-sdk/18.0.0/create-openapi-client/banking-service/src/main/java/com/backbase/banking/api/ExampleController.java new file mode 100644 index 0000000..41fe36f --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-client/banking-service/src/main/java/com/backbase/banking/api/ExampleController.java @@ -0,0 +1,25 @@ +package com.backbase.banking.api; + +import com.backbase.banking.Message; +import com.backbase.messaging.api.client.v2.MessageApi; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RequestMethod; + +@RestController +public class ExampleController { + + @Autowired + private MessageApi messageApi; + + @RequestMapping(method = RequestMethod.GET, value = "/message", produces = { + "application/json" + }) + @ResponseStatus(HttpStatus.OK) + public Message getMessage() { + return new Message("Hello World"); + } +} \ No newline at end of file diff --git a/service-sdk/18.0.0/create-openapi-client/banking-service/src/main/java/com/backbase/banking/config/MessagingServiceRestClientConfiguration.java b/service-sdk/18.0.0/create-openapi-client/banking-service/src/main/java/com/backbase/banking/config/MessagingServiceRestClientConfiguration.java new file mode 100644 index 0000000..b042b8b --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-client/banking-service/src/main/java/com/backbase/banking/config/MessagingServiceRestClientConfiguration.java @@ -0,0 +1,39 @@ +package com.backbase.banking.config; + +import com.backbase.buildingblocks.communication.client.ApiClientConfig; +import com.backbase.buildingblocks.communication.http.HttpCommunicationConfiguration; +import com.backbase.messaging.api.client.ApiClient; +import com.backbase.messaging.api.client.v2.MessageApi; +import org.springframework.context.annotation.*; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; + +// tag::MessagingServiceRestClientConfiguration[] +@Configuration +@ConfigurationProperties("backbase.communication.services.name") +@Validated +public class MessagingServiceRestClientConfiguration extends ApiClientConfig { + + public static final String MESSAGING_SERVICE_ID = "messaging-service"; + + public MessagingServiceRestClientConfiguration() { + super(MESSAGING_SERVICE_ID); + } + + /** + * Creates a REST client. + * + * @return the client. + */ + @Bean + public MessageApi createGeneratedClassApiClient() { + return new MessageApi(createApiClient()); + } + + private ApiClient createApiClient() { + return new ApiClient(getRestTemplate()) + .setBasePath(createBasePath()) + .addDefaultHeader(HttpCommunicationConfiguration.INTERCEPTORS_ENABLED_HEADER, Boolean.TRUE.toString()); + } +} +// end::MessagingServiceRestClientConfiguration[] diff --git a/service-sdk/18.0.0/create-openapi-client/banking-service/src/main/resources/application.yaml b/service-sdk/18.0.0/create-openapi-client/banking-service/src/main/resources/application.yaml new file mode 100644 index 0000000..9b286a6 --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-client/banking-service/src/main/resources/application.yaml @@ -0,0 +1,27 @@ +server: + port: 9915 + +# API Registry client configuration +eureka: + instance: + metadata-map: + public: true + role: live + client: + serviceUrl: + defaultZone: http://localhost:8080/registry/eureka/ + +# Configure Internal JWT handler +sso: + jwt: + internal: + signature: + key: + type: ENV + value: SIG_SECRET_KEY + +# Spring health monitoring +management: + health: + jms: + enabled: false \ No newline at end of file diff --git a/service-sdk/18.0.0/create-openapi-client/banking-service/src/main/resources/banner.txt b/service-sdk/18.0.0/create-openapi-client/banking-service/src/main/resources/banner.txt new file mode 100644 index 0000000..3e84197 --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-client/banking-service/src/main/resources/banner.txt @@ -0,0 +1,9 @@ + ________ ________ ________ ___ __ ________ ________ ________ _______ +|\ __ \|\ __ \|\ ____\|\ \|\ \ |\ __ \|\ __ \|\ ____\|\ ___ \ +\ \ \|\ /\ \ \|\ \ \ \___|\ \ \/ /|\ \ \|\ /\ \ \|\ \ \ \___|\ \ __/| + \ \ __ \ \ __ \ \ \ \ \ ___ \ \ __ \ \ __ \ \_____ \ \ \_|/__ + \ \ \|\ \ \ \ \ \ \ \____\ \ \\ \ \ \ \|\ \ \ \ \ \|____|\ \ \ \_|\ \ + \ \_______\ \__\ \__\ \_______\ \__\\ \__\ \_______\ \__\ \__\____\_\ \ \_______\ + \|_______|\|__|\|__|\|_______|\|__| \|__|\|_______|\|__|\|__|\_________\|_______| + \|_________| + diff --git a/service-sdk/18.0.0/create-openapi-client/banking-service/src/main/resources/bootstrap.yaml b/service-sdk/18.0.0/create-openapi-client/banking-service/src/main/resources/bootstrap.yaml new file mode 100644 index 0000000..932154a --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-client/banking-service/src/main/resources/bootstrap.yaml @@ -0,0 +1,3 @@ +spring: + application: + name: banking-service diff --git a/service-sdk/18.0.0/create-openapi-client/banking-service/src/test/java/com/backbase/banking/ExampleControllerIT.java b/service-sdk/18.0.0/create-openapi-client/banking-service/src/test/java/com/backbase/banking/ExampleControllerIT.java new file mode 100644 index 0000000..4804030 --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-client/banking-service/src/test/java/com/backbase/banking/ExampleControllerIT.java @@ -0,0 +1,65 @@ +package com.backbase.banking; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContext; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.http.MediaType; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; + +/** + * A wrapper annotation for use with integration tests. + * + * By default, assumes the integration test modifies the + * {@link ApplicationContext} associated with the test/s and will therefore be + * closed and removed from the context cache at the end of the class. + */ +@SpringBootTest(classes = Application.class) +@DirtiesContext(classMode = ClassMode.AFTER_CLASS) +@AutoConfigureMockMvc +@ActiveProfiles("it") +public class ExampleControllerIT { + + public static final String TEST_JWT = + "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxk" + + "ZXIiLCJpYXQiOjE0ODQ4MjAxOTYsImV4cCI6MTUxNjM1NjE5NiwiYXVkIjoid3d3LmV4YW1wbGUuY29tIiwic3ViIjoianJv" + + "Y2tldEBleGFtcGxlLmNvbSIsIkdpdmVuTmFtZSI6IkpvaG5ueSIsIlN1cm5hbWUiOiJSb2NrZXQiLCJFbWFpbCI6Impyb2Nr" + + "ZXRAZXhhbXBsZS5jb20iLCJSb2xlIjpbIk1hbmFnZXIiLCJQcm9qZWN0IEFkbWluaXN0cmF0b3IiXSwiaW51aWQiOiJKaW1te" + + "SJ9.O9TE28ygrHmDjItYK6wRis6wELD5Wtpi6ekeYfR1WqM"; + @Autowired + private MockMvc mvc; + + @Test + public void exampleTest() throws Exception { + + + MockHttpServletRequestBuilder requestBuilder = get("/message") + .header("Authorization", TEST_JWT); + + ResultActions result = mvc.perform(requestBuilder).andDo(print()); + + // Then the request is successful + result = result.andExpect(status().isOk()); + + // And a response is returned + MvcResult response = result.andExpect(content().contentType(MediaType.APPLICATION_JSON)).andReturn(); + + // Check response + String responseBody = response.getResponse().getContentAsString(); + + assertThat(responseBody).contains("Hello World").as("ID in response should match ID in request"); + } +} diff --git a/service-sdk/18.0.0/create-openapi-client/banking-service/src/test/resources/application.yaml b/service-sdk/18.0.0/create-openapi-client/banking-service/src/test/resources/application.yaml new file mode 100644 index 0000000..84a78d0 --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-client/banking-service/src/test/resources/application.yaml @@ -0,0 +1,3 @@ +eureka: + client: + enabled: false diff --git a/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/README.md b/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/README.md new file mode 100644 index 0000000..3c6a947 --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/README.md @@ -0,0 +1,25 @@ +# messaging-api + +> _Fill out this file with some information about your OpenAPI spec._ + +To build this spec, use: +``` +mvn clean install +``` + +The spec is also validated as part of the build. + +## Community Documentation + +Add links to documentation including setup, config, etc. + +##Jira Project + +Add link to Jira project. + +## Confluence Links +Links to relevant confluence pages (design etc). + +## Support + +Slack, Email, Jira etc. \ No newline at end of file diff --git a/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/assembly/api.xml b/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/assembly/api.xml new file mode 100644 index 0000000..d4c8bb8 --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/assembly/api.xml @@ -0,0 +1,18 @@ + + api + + zip + + false + + + ${project.build.directory} + ${artifactId} + + *.yaml + + + + diff --git a/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/package.json b/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/package.json new file mode 100644 index 0000000..69bbf41 --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/package.json @@ -0,0 +1,20 @@ +{ + "name": "message-api", + "license": "UNLICENSED", + "private": true, + "scripts": { + "prism-static": "prism mock src/main/resources/openapi.yaml", + "prism-dynamic": "prism mock -d src/main/resources/openapi.yaml", + "validate": "swagger-cli validate src/main/resources/openapi.yaml", + "lint-openapi": "spectral lint src/main/resources/openapi.yaml --ruleset https://stash.backbase.com/projects/API/repos/api-linting/raw/src/spectral/v5/openapi-rules.yaml", + "lint-schemas": "spectral lint src/main/resources/schemas/**/*.yaml --ruleset https://stash.backbase.com/projects/API/repos/api-linting/raw/src/spectral/v5/schema-rules.yaml", + "check-backwards-compatibility": "curl -sL -H \"${SPEC_AUTH}\" https://api.backbase.cloud/doc/$SPEC_NAME -o target/$SPEC_NAME && openapi-diff target/$SPEC_NAME target/openapi.yaml", + "bundle": "swagger-cli bundle -t yaml -o target/openapi.yaml src/main/resources/openapi.yaml" + }, + "dependencies": { + "@stoplight/prism-cli": "3.2.8", + "@stoplight/spectral": "5.0.0", + "openapi-diff": "0.23.1", + "swagger-cli": "3.0.1" + } +} \ No newline at end of file diff --git a/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/pom.xml b/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/pom.xml new file mode 100644 index 0000000..fad4a98 --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/pom.xml @@ -0,0 +1,116 @@ + + + 4.0.0 + + + com.backbase.buildingblocks + backbase-openapi-spec-starter-parent + 16.0.0 + + + com.backbase.message + messaging-api + 1.0.0-SNAPSHOT + Backbase :: messaging-api + + + + 0.17.5 + + + + + + com.backbase.oss + boat-maven-plugin + ${boat-maven-plugin.version} + + + boat-validation + generate-sources + + validate + + + ${project.basedir}/src/main/resources/client-api-v1.yaml + true + + + + + boat-bundle + generate-sources + + bundle + + + ${project.basedir}/src/main/resources + ${project.build.directory} + true + + + + + boat-bundle-unversioned + generate-sources + + bundle + + + ${project.basedir}/src/main/resources + ${project.build.directory}/unversioned + false + + + + boat-linting + package + + lint + + + ${project.build.directory} + ${project.basedir}/target/boat-lint-reports + true + true + 219,215,218,115,134,104,105,110,176,M011,151,S007,S005,B013,H001 + + + + boat-docs + package + + generate + + + ${project.build.directory}/unversioned/client-api-v1.yaml + ${project.build.directory}/generated-docs + html2 + true + + + + + + + maven-assembly-plugin + + + assemble-api-zip + + single + + package + + + assembly/api.xml + + + + + + + + + diff --git a/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/client-api-v1.yaml b/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/client-api-v1.yaml new file mode 100644 index 0000000..297e773 --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/client-api-v1.yaml @@ -0,0 +1,169 @@ +openapi: 3.0.3 +info: + title: Message Service API Spec + description: Specs for Message Service API + version: 1.0.0 + x-icon: credit_card + +servers: + - description: local test + url: http://localhost:8080/api/v1 + +tags: + - name: Retail + +paths: + + /client-api/v1/messages: + description: No description available + + get: + summary: Returns available items, optionally filtered by name. + description: Returns available items, optionally filtered by name + operationId: getMessage + parameters: + - description: Id of the message record + example: a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1 + in: query + name: id + required: true + schema: + type: string + responses: + '200': + content: + application/json: + example: + $ref: examples/body/example-message.json + schema: + $ref: '#/components/schemas/Message' + description: No description available + '400': + $ref: 'lib/common-types.yaml#/components/responses/400BadRequest' + '500': + $ref: 'lib/common-types.yaml#/components/responses/500InternalServerError' + tags: + - message + + delete: + summary: Delete message. + description: Deletes a message + operationId: deleteMessage + parameters: + - description: Id of the message record + example: a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1 + in: query + name: id + required: true + schema: + type: string + responses: + '204': + description: request to delete completed + '400': + $ref: 'lib/common-types.yaml#/components/responses/400BadRequest' + '500': + $ref: 'lib/common-types.yaml#/components/responses/500InternalServerError' + tags: + - message + + post: + summary: Adds or updates a message. + description: Adds or updates a message + operationId: postMessage + requestBody: + content: + application/json: + example: + $ref: examples/body/example-message.json + schema: + $ref: '#/components/schemas/Message' + description: Adds or updates a message + responses: + '201': + content: + application/json: + example: + $ref: examples/body/example-message-created.json + schema: + $ref: '#/components/schemas/MessagePostResponseBody' + description: request to create item accepted + '400': + $ref: 'lib/common-types.yaml#/components/responses/400BadRequest' + '500': + $ref: 'lib/common-types.yaml#/components/responses/500InternalServerError' + tags: + - message + + put: + summary: Adds or updates a message. + description: Adds or updates a message + operationId: putMessage + requestBody: + content: + application/json: + example: + $ref: examples/body/example-message.json + schema: + $ref: '#/components/schemas/Message' + description: Adds or updates a message + responses: + '204': + description: request to update item completed + '400': + $ref: 'lib/common-types.yaml#/components/responses/400BadRequest' + '500': + $ref: 'lib/common-types.yaml#/components/responses/500InternalServerError' + tags: + - message + + /client-api/v1/all-messages: + summary: messages + description: No description available + get: + summary: Returns all available messages. + description: Returns all available messages + operationId: getMessages + responses: + '200': + content: + application/json: + example: + $ref: examples/body/example-messages-get.json + schema: + $ref: '#/components/schemas/MessagesGetResponseBody' + description: No description available + '400': + $ref: 'lib/common-types.yaml#/components/responses/400BadRequest' + '500': + $ref: 'lib/common-types.yaml#/components/responses/500InternalServerError' + tags: + - message + +components: + schemas: + ErrorItem: + $ref: 'lib/schemas/error-item.yaml' + Message: + $ref: schemas/body/message.json + MessagesGetResponseBody: + $ref: schemas/body/messages-get.json + MessagePostResponseBody: + $ref: schemas/body/message-created.json + NotAcceptableError: + properties: + message: + type: string + supportedMediaTypes: + description: List of supported media types for this endpoint + items: + type: string + type: array + type: object + UnauthorizedError: + properties: + message: + type: string + required: + - message + type: object diff --git a/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/docs/api.md b/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/docs/api.md new file mode 100644 index 0000000..3365a26 --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/docs/api.md @@ -0,0 +1,7 @@ +# Example Persistence Service API Spec API Documentation + +Currently the Example Persistence Service API Spec API contains the following operations: +* Create an item or Update an item +* Get an item by ID +* Get list of items, optionally filtering by name +* Delete item diff --git a/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/examples/body/example-message-created.json b/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/examples/body/example-message-created.json new file mode 100644 index 0000000..66dc6ed --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/examples/body/example-message-created.json @@ -0,0 +1,3 @@ +{ + "id": "a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1" +} diff --git a/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/examples/body/example-message.json b/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/examples/body/example-message.json new file mode 100644 index 0000000..03564aa --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/examples/body/example-message.json @@ -0,0 +1,4 @@ +{ + "id": "a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1", + "message": "Hello" +} diff --git a/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/examples/body/example-messages-get.json b/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/examples/body/example-messages-get.json new file mode 100644 index 0000000..bfcbcd8 --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/examples/body/example-messages-get.json @@ -0,0 +1,14 @@ +[ + { + "id": "a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1", + "message": "Hello" + }, + { + "id": "d593c212-70ad-41a6-a547-d5d9232414cb", + "message": "Hola" + }, + { + "id": "9635966b-28e9-4479-8121-bb7bc9beeb62", + "message": "hej" + } +] diff --git a/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/examples/errors/example-error.json b/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/examples/errors/example-error.json new file mode 100644 index 0000000..c52d8e6 --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/examples/errors/example-error.json @@ -0,0 +1,4 @@ +{ + "message": "Description of error", + "key": "TYPE_ERROR" +} diff --git a/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/schemas/body/message-created.json b/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/schemas/body/message-created.json new file mode 100644 index 0000000..0f30393 --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/schemas/body/message-created.json @@ -0,0 +1,8 @@ +{ + "type": "object", + "properties": { + "id": { + "type": "string" + } + } +} diff --git a/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/schemas/body/message.json b/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/schemas/body/message.json new file mode 100644 index 0000000..74fd94d --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/schemas/body/message.json @@ -0,0 +1,15 @@ +{ + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": [ + "id", + "message" + ] +} diff --git a/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/schemas/body/messages-get.json b/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/schemas/body/messages-get.json new file mode 100644 index 0000000..00778c9 --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/schemas/body/messages-get.json @@ -0,0 +1,6 @@ +{ + "type": "array", + "items": { + "$ref": "message.json" + } +} diff --git a/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/schemas/errors/error.json b/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/schemas/errors/error.json new file mode 100644 index 0000000..4b0f612 --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-spec-project/messaging-api/src/main/resources/schemas/errors/error.json @@ -0,0 +1,16 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "message": { + "type": "string" + }, + "key": { + "type": "string" + } + }, + "required": [ + "message", + "key" + ] +} diff --git a/service-sdk/18.0.0/create-openapi-spec-project/messaging-service/README.md b/service-sdk/18.0.0/create-openapi-spec-project/messaging-service/README.md new file mode 100644 index 0000000..3884e84 --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-spec-project/messaging-service/README.md @@ -0,0 +1,25 @@ +# messaging-service + +_Fill out this file with some information about your Service._ + +## Dependencies + +Requires a running Eureka registry, by default on port 8080. + +## Configuration + +Service configuration is under `src/main/resources/application.yaml`. + +## Running + +To run the service in development mode, use: +- `mvn spring-boot:run` + +To run the service from the built binaries, use: +- `java -jar target/messaging-service-1.0.0-SNAPSHOT.jar` + +## Authorization + +Requests to this service are authorized with a Backbase Internal JWT, therefore you must access this service via the Backbase Gateway after authenticating with the authentication service. + +For local development, an internal JWT can be created from http://jwt.io, entering ```JWTSecretKeyDontUseInProduction!``` as the secret in the signature to generate a valid signed JWT. diff --git a/service-sdk/18.0.0/create-openapi-spec-project/messaging-service/pom.xml b/service-sdk/18.0.0/create-openapi-spec-project/messaging-service/pom.xml new file mode 100644 index 0000000..a203dc0 --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-spec-project/messaging-service/pom.xml @@ -0,0 +1,123 @@ + + 4.0.0 + + + + com.backbase.buildingblocks + service-sdk-starter-core + 16.0.0 + + + + com.backbase.message + messaging-service + 1.0.0-SNAPSHOT + Backbase :: Digital Banking Services :: messaging-service + + + 17 + 0.17.5 + + + + + + io.swagger.core.v3 + swagger-annotations + + + + org.openapitools + jackson-databind-nullable + + + + org.springframework.data + spring-data-commons + + + + io.springfox + springfox-core + 3.0.0 + + + + com.backbase.buildingblocks + spring-security-csrf + + + + + + com.backbase.buildingblocks + service-sdk-starter-test + test + + + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + unpack + generate-sources + + unpack + + + + + com.backbase.message + messaging-api + 1.0.0-SNAPSHOT + api + ${project.build.directory}/yaml + zip + true + + + **/*.yaml, **/*.json + + + + + + + + + com.backbase.oss + boat-maven-plugin + ${boat-maven-plugin.version} + + + generate-client-api-code + + generate-spring-boot-embedded + + generate-sources + + ${project.build.directory}/yaml/messaging-api/client-api-v1.0.0.yaml + com.backbase.dbs.messaging-service.api.service.v2 + com.backbase.dbs.messaging-service.api.service.v2.model + + + + + + + + + + diff --git a/service-sdk/18.0.0/create-openapi-spec-project/messaging-service/src/main/java/com/backbase/message/Application.java b/service-sdk/18.0.0/create-openapi-spec-project/messaging-service/src/main/java/com/backbase/message/Application.java new file mode 100644 index 0000000..9f6ac28 --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-spec-project/messaging-service/src/main/java/com/backbase/message/Application.java @@ -0,0 +1,16 @@ +package com.backbase.message; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; + +@SpringBootApplication +@EnableDiscoveryClient +public class Application extends SpringBootServletInitializer { + + public static void main(final String[] args) { + SpringApplication.run(Application.class, args); + } + +} \ No newline at end of file diff --git a/service-sdk/18.0.0/create-openapi-spec-project/messaging-service/src/main/java/com/backbase/message/Message.java b/service-sdk/18.0.0/create-openapi-spec-project/messaging-service/src/main/java/com/backbase/message/Message.java new file mode 100644 index 0000000..227bfb0 --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-spec-project/messaging-service/src/main/java/com/backbase/message/Message.java @@ -0,0 +1,17 @@ +package com.backbase.message; + +public class Message { + private String message; + + public Message(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/service-sdk/18.0.0/create-openapi-spec-project/messaging-service/src/main/java/com/backbase/message/api/ExampleController.java b/service-sdk/18.0.0/create-openapi-spec-project/messaging-service/src/main/java/com/backbase/message/api/ExampleController.java new file mode 100644 index 0000000..763367c --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-spec-project/messaging-service/src/main/java/com/backbase/message/api/ExampleController.java @@ -0,0 +1,46 @@ +package com.backbase.message.api; + +import com.backbase.dbs.messaging_service.api.service.v2.MessageApi; +import com.backbase.dbs.messaging_service.api.service.v2.model.MessagePostResponseBody; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import java.util.List; + + +@RestController +public class ExampleController implements MessageApi { + + + @Override + public ResponseEntity deleteMessage(@NotNull @Valid String id) { + //TODO: Implement method with proper logic + return null; + } + + @Override + public ResponseEntity getMessage(@NotNull @Valid String id) { + //TODO: Implement method with proper logic + return null; + } + + @Override + public ResponseEntity> getMessages() { + //TODO: Implement method with proper logic + return null; + } + + @Override + public ResponseEntity postMessage(com.backbase.dbs.messaging_service.api.service.v2.model.@Valid Message message) { + //TODO: Implement method with proper logic + return null; + } + + @Override + public ResponseEntity putMessage(com.backbase.dbs.messaging_service.api.service.v2.model.@Valid Message message) { + //TODO: Implement method with proper logic + return null; + } +} \ No newline at end of file diff --git a/service-sdk/18.0.0/create-openapi-spec-project/messaging-service/src/main/resources/application.yaml b/service-sdk/18.0.0/create-openapi-spec-project/messaging-service/src/main/resources/application.yaml new file mode 100644 index 0000000..9b286a6 --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-spec-project/messaging-service/src/main/resources/application.yaml @@ -0,0 +1,27 @@ +server: + port: 9915 + +# API Registry client configuration +eureka: + instance: + metadata-map: + public: true + role: live + client: + serviceUrl: + defaultZone: http://localhost:8080/registry/eureka/ + +# Configure Internal JWT handler +sso: + jwt: + internal: + signature: + key: + type: ENV + value: SIG_SECRET_KEY + +# Spring health monitoring +management: + health: + jms: + enabled: false \ No newline at end of file diff --git a/service-sdk/18.0.0/create-openapi-spec-project/messaging-service/src/main/resources/banner.txt b/service-sdk/18.0.0/create-openapi-spec-project/messaging-service/src/main/resources/banner.txt new file mode 100644 index 0000000..3e84197 --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-spec-project/messaging-service/src/main/resources/banner.txt @@ -0,0 +1,9 @@ + ________ ________ ________ ___ __ ________ ________ ________ _______ +|\ __ \|\ __ \|\ ____\|\ \|\ \ |\ __ \|\ __ \|\ ____\|\ ___ \ +\ \ \|\ /\ \ \|\ \ \ \___|\ \ \/ /|\ \ \|\ /\ \ \|\ \ \ \___|\ \ __/| + \ \ __ \ \ __ \ \ \ \ \ ___ \ \ __ \ \ __ \ \_____ \ \ \_|/__ + \ \ \|\ \ \ \ \ \ \ \____\ \ \\ \ \ \ \|\ \ \ \ \ \|____|\ \ \ \_|\ \ + \ \_______\ \__\ \__\ \_______\ \__\\ \__\ \_______\ \__\ \__\____\_\ \ \_______\ + \|_______|\|__|\|__|\|_______|\|__| \|__|\|_______|\|__|\|__|\_________\|_______| + \|_________| + diff --git a/service-sdk/18.0.0/create-openapi-spec-project/messaging-service/src/main/resources/bootstrap.yaml b/service-sdk/18.0.0/create-openapi-spec-project/messaging-service/src/main/resources/bootstrap.yaml new file mode 100644 index 0000000..de6b29d --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-spec-project/messaging-service/src/main/resources/bootstrap.yaml @@ -0,0 +1,3 @@ +spring: + application: + name: messaging-service diff --git a/service-sdk/18.0.0/create-openapi-spec-project/messaging-service/src/test/java/com/backbase/message/ExampleControllerIT.java b/service-sdk/18.0.0/create-openapi-spec-project/messaging-service/src/test/java/com/backbase/message/ExampleControllerIT.java new file mode 100644 index 0000000..fec3ffb --- /dev/null +++ b/service-sdk/18.0.0/create-openapi-spec-project/messaging-service/src/test/java/com/backbase/message/ExampleControllerIT.java @@ -0,0 +1,65 @@ +package com.backbase.message; + + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContext; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.http.MediaType; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * A wrapper annotation for use with integration tests. + * + * By default, assumes the integration test modifies the + * {@link ApplicationContext} associated with the test/s and will therefore be + * closed and removed from the context cache at the end of the class. + */ +@SpringBootTest(classes = Application.class) +@DirtiesContext(classMode = ClassMode.AFTER_CLASS) +@AutoConfigureMockMvc +@ActiveProfiles("it") +public class ExampleControllerIT { + + public static final String TEST_JWT = + "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxk" + + "ZXIiLCJpYXQiOjE0ODQ4MjAxOTYsImV4cCI6MTUxNjM1NjE5NiwiYXVkIjoid3d3LmV4YW1wbGUuY29tIiwic3ViIjoianJv" + + "Y2tldEBleGFtcGxlLmNvbSIsIkdpdmVuTmFtZSI6IkpvaG5ueSIsIlN1cm5hbWUiOiJSb2NrZXQiLCJFbWFpbCI6Impyb2Nr" + + "ZXRAZXhhbXBsZS5jb20iLCJSb2xlIjpbIk1hbmFnZXIiLCJQcm9qZWN0IEFkbWluaXN0cmF0b3IiXSwiaW51aWQiOiJKaW1te" + + "SJ9.O9TE28ygrHmDjItYK6wRis6wELD5Wtpi6ekeYfR1WqM"; + @Autowired + private MockMvc mvc; + + @Test + public void exampleTest() throws Exception { + + + MockHttpServletRequestBuilder requestBuilder = get("/client-api/v1/messages").header("Authorization", + TEST_JWT).param("id", + "mockID").contentType(MediaType.APPLICATION_JSON); + + ResultActions result = mvc.perform(requestBuilder).andDo(print()); + + // Then the request is successful + result = result.andExpect(status().isOk()); + + // And a response is returned + //MvcResult response = result.andExpect(content().contentType(MediaType.APPLICATION_JSON)).andReturn(); + + // Check response + //String responseBody = response.getResponse().getContentAsString(); + + // Test fails until business logic implemented in REST controller + //assertThat("ID in response should match ID in request", responseBody, containsString("Hello World")); + } +} diff --git a/service-sdk/18.0.0/create-outbound-integration-service-openapi/README.md b/service-sdk/18.0.0/create-outbound-integration-service-openapi/README.md new file mode 100644 index 0000000..cb527a3 --- /dev/null +++ b/service-sdk/18.0.0/create-outbound-integration-service-openapi/README.md @@ -0,0 +1,4 @@ +This project contains code samples documented in the following sections in [Backbase Community](https://community.backbase.com/documentation/ServiceSDK/latest/index) + +* [Integrate your service with an external service](https://community.backbase.com/documentation/ServiceSDK/latest/create_outbound_integration_service) +* [Enable service to service communications](https://community.backbase.com/documentation/ServiceSDK/latest/service_to_service_communication) diff --git a/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/README.md b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/README.md new file mode 100644 index 0000000..96dfbbf --- /dev/null +++ b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/README.md @@ -0,0 +1,45 @@ +# example-integration-service + +_Fill out this file with some information about your Service._ + +#Getting Started +* [Extend and build](https://community.backbase.com/documentation/ServiceSDK/latest/extend_and_build) + +## Dependencies + +Requires a running Eureka registry, by default on port 8080. + +## Configuration + +Service configuration is under `src/main/resources/application.yaml`. + +## Running + +To run the service in development mode, use: +- `mvn spring-boot:run` + +To run the service from the built binaries, use: +- `java -jar target/example-integration-service-1.0.0-SNAPSHOT.jar` + +## Authorization + +Requests to this service are authorized with a Backbase Internal JWT, therefore you must access this service via the +Backbase Gateway after authenticating with the authentication service. + +For local development, an internal JWT can be created from http://jwt.io, entering `JWTSecretKeyDontUseInProduction!` +as the secret in the signature to generate a valid signed JWT. + +## Community Documentation + +Add links to documentation including setup, config, etc. + +## Jira Project + +Add link to Jira project. + +## Confluence Links +Links to relevant confluence pages (design etc). + +## Support + +The official example-integration-service support room is [#s-example-integration-service](https://todo). diff --git a/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/pom.xml b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/pom.xml new file mode 100644 index 0000000..1522c9e --- /dev/null +++ b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/pom.xml @@ -0,0 +1,126 @@ + + 4.0.0 + + + + com.backbase.buildingblocks + service-sdk-starter-core + 16.0.0 + + + + com.backbase.example + example-integration-openapi-service + 1.0.0-SNAPSHOT + Backbase :: example-integration-openapi-service + + + 17 + 0.17.5 + ${project.build.directory}/specs + + + + + com.backbase.buildingblocks + service-sdk-starter-test + test + + + + + + + + com.backbase.buildingblocks + communication + + + com.backbase.buildingblocks + service-sdk-starter-mapping + + + com.backbase.buildingblocks + service-sdk-test-utils + test + + + io.swagger.core.v3 + swagger-annotations + + + org.openapitools + jackson-databind-nullable + + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.1.2 + + + unpack + initialize + + unpack + + + + + com.backbase.poc + example-integration-openapi-spec + 1.0.0-SNAPSHOT + jar + ${open-api-specs-dir}/example-integration-openapi-spec/ + **/*.yaml,**/*.json + + + **/*.java + **/*.properties + ${project.build.directory}/wars + false + true + + + + + + + + + com.backbase.oss + boat-maven-plugin + ${boat-maven-plugin.version} + + + + generate-payment-order-template-client-api-code + + generate-spring-boot-embedded + + generate-sources + + + ${open-api-specs-dir}/example-integration-openapi-spec/client-api-v1.yaml + + com.backbase.example.api.client.v1 + com.backbase.example.api.client.v1.model + + + + + + + + + diff --git a/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/java/com/backbase/example/Application.java b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/java/com/backbase/example/Application.java new file mode 100644 index 0000000..37acffd --- /dev/null +++ b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/java/com/backbase/example/Application.java @@ -0,0 +1,16 @@ +package com.backbase.example; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; + +@SpringBootApplication +@EnableDiscoveryClient +public class Application extends SpringBootServletInitializer { + + public static void main(final String[] args) { + SpringApplication.run(Application.class, args); + } + +} \ No newline at end of file diff --git a/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/java/com/backbase/example/Message.java b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/java/com/backbase/example/Message.java new file mode 100644 index 0000000..8def353 --- /dev/null +++ b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/java/com/backbase/example/Message.java @@ -0,0 +1,17 @@ +package com.backbase.example; + +public class Message { + private String message; + + public Message(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/java/com/backbase/example/api/ExampleController.java b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/java/com/backbase/example/api/ExampleController.java new file mode 100644 index 0000000..6c4f546 --- /dev/null +++ b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/java/com/backbase/example/api/ExampleController.java @@ -0,0 +1,62 @@ +package com.backbase.example.api; + +import com.backbase.buildingblocks.presentation.errors.InternalServerErrorException; +import com.backbase.example.api.client.v1.MessageApi; +import com.backbase.example.api.client.v1.model.MessagePostResponseBody; +import com.backbase.example.client.MessageClient; +import com.backbase.example.mapper.IntegrationMessageMapper; +import com.backbase.example.model.Message; +import java.io.IOException; +import java.util.List; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class ExampleController implements MessageApi { + + @Autowired + private MessageClient messageClient; + + @Override + public ResponseEntity deleteMessage(@Valid @NotNull String id) { + return ResponseEntity.status(HttpStatus.NOT_IMPLEMENTED).build(); + } + + + @Override + public ResponseEntity getMessage(@Valid @NotNull String id) { + + return ResponseEntity.status(HttpStatus.NOT_IMPLEMENTED).build(); + } + + // tag::getIntegration[] + @Override + public ResponseEntity> getMessages() { + List messages = null; + + try { + messages = messageClient.getMessages(); + } catch (IOException e) { + throw new InternalServerErrorException("Error has occurred sending message"); + } + + return ResponseEntity.ok(IntegrationMessageMapper.INSTANCE.messagesToIntegrationGetResponseBodys(messages)); + } + // end::getIntegration[] + + @Override + public ResponseEntity postMessage( + com.backbase.example.api.client.v1.model.@Valid Message message) { + return ResponseEntity.status(HttpStatus.NOT_IMPLEMENTED).build(); + } + + @Override + public ResponseEntity putMessage(com.backbase.example.api.client.v1.model.@Valid Message message) { + return ResponseEntity.status(HttpStatus.NOT_IMPLEMENTED).build(); + } + +} diff --git a/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/java/com/backbase/example/client/MessageClient.java b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/java/com/backbase/example/client/MessageClient.java new file mode 100644 index 0000000..e976f61 --- /dev/null +++ b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/java/com/backbase/example/client/MessageClient.java @@ -0,0 +1,11 @@ +package com.backbase.example.client; + +import com.backbase.example.model.Message; + +import java.io.IOException; +import java.util.List; + +public interface MessageClient { + + List getMessages() throws IOException; +} diff --git a/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/java/com/backbase/example/client/MessageClientImpl.java b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/java/com/backbase/example/client/MessageClientImpl.java new file mode 100644 index 0000000..2a0d262 --- /dev/null +++ b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/java/com/backbase/example/client/MessageClientImpl.java @@ -0,0 +1,41 @@ +package com.backbase.example.client; + +import com.backbase.example.model.Message; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.http.HttpMethod; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +@Component +public class MessageClientImpl implements MessageClient { + + private static final String SERVICE_URL = "http://echo.jsontest.com/messageId/abcdef-393939-dffdfdf/message/Hello%20World/"; + private RestTemplate restTemplate; + + public MessageClientImpl(RestTemplateBuilder restTemplateBuilder) { + restTemplate = restTemplateBuilder.build(); + } +// tag::getMessages[] + @Override + public List getMessages() throws IOException { + /** NOTE: This integration could be completed by creating a code generated client e.g. off a Open API spec */ + String responseJSON = restTemplate.exchange( + URI.create(SERVICE_URL), + HttpMethod.GET, null, String.class).getBody(); + + Message message = new ObjectMapper().readValue(responseJSON, + new TypeReference() {}); + + List messages = new ArrayList<>(); + messages.add(message); + return messages; + } +// end::getMessages[] +} diff --git a/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/java/com/backbase/example/mapper/IntegrationMessageMapper.java b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/java/com/backbase/example/mapper/IntegrationMessageMapper.java new file mode 100644 index 0000000..e43b5aa --- /dev/null +++ b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/java/com/backbase/example/mapper/IntegrationMessageMapper.java @@ -0,0 +1,19 @@ +package com.backbase.example.mapper; + +import com.backbase.example.model.Message; +import java.util.List; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.ReportingPolicy; +import org.mapstruct.factory.Mappers; + +@Mapper(unmappedTargetPolicy = ReportingPolicy.ERROR) +public interface IntegrationMessageMapper { + + IntegrationMessageMapper INSTANCE = Mappers.getMapper( IntegrationMessageMapper.class); + + @Mapping(source = "messages.messageId", target = "id") + com.backbase.example.api.client.v1.model.Message messageToIntegrationGetResponseBody(Message messages); + + List messagesToIntegrationGetResponseBodys(List messages); +} diff --git a/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/java/com/backbase/example/model/Message.java b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/java/com/backbase/example/model/Message.java new file mode 100644 index 0000000..da04568 --- /dev/null +++ b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/java/com/backbase/example/model/Message.java @@ -0,0 +1,43 @@ +package com.backbase.example.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +import jakarta.annotation.Generated; +import jakarta.validation.constraints.NotNull; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@Generated("org.jsonschema2pojo") +@JsonPropertyOrder({ + "messageId", + "message" +}) +@JsonIgnoreProperties(ignoreUnknown = true) +public class Message { + + @JsonProperty("messageId") + @NotNull + private String messageId; + + @JsonProperty("message") + @NotNull + private String message; + + public String getMessageId() { + return messageId; + } + + public void setMessageId(String messageId) { + this.messageId = messageId; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/resources/application.yaml b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/resources/application.yaml new file mode 100644 index 0000000..9b286a6 --- /dev/null +++ b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/resources/application.yaml @@ -0,0 +1,27 @@ +server: + port: 9915 + +# API Registry client configuration +eureka: + instance: + metadata-map: + public: true + role: live + client: + serviceUrl: + defaultZone: http://localhost:8080/registry/eureka/ + +# Configure Internal JWT handler +sso: + jwt: + internal: + signature: + key: + type: ENV + value: SIG_SECRET_KEY + +# Spring health monitoring +management: + health: + jms: + enabled: false \ No newline at end of file diff --git a/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/resources/banner.txt b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/resources/banner.txt new file mode 100644 index 0000000..3e84197 --- /dev/null +++ b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/resources/banner.txt @@ -0,0 +1,9 @@ + ________ ________ ________ ___ __ ________ ________ ________ _______ +|\ __ \|\ __ \|\ ____\|\ \|\ \ |\ __ \|\ __ \|\ ____\|\ ___ \ +\ \ \|\ /\ \ \|\ \ \ \___|\ \ \/ /|\ \ \|\ /\ \ \|\ \ \ \___|\ \ __/| + \ \ __ \ \ __ \ \ \ \ \ ___ \ \ __ \ \ __ \ \_____ \ \ \_|/__ + \ \ \|\ \ \ \ \ \ \ \____\ \ \\ \ \ \ \|\ \ \ \ \ \|____|\ \ \ \_|\ \ + \ \_______\ \__\ \__\ \_______\ \__\\ \__\ \_______\ \__\ \__\____\_\ \ \_______\ + \|_______|\|__|\|__|\|_______|\|__| \|__|\|_______|\|__|\|__|\_________\|_______| + \|_________| + diff --git a/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/resources/bootstrap.yaml b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/resources/bootstrap.yaml new file mode 100644 index 0000000..4212129 --- /dev/null +++ b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/main/resources/bootstrap.yaml @@ -0,0 +1,3 @@ +spring: + application: + name: example-integration-service diff --git a/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/test/java/com/backbase/example/ExampleControllerIT.java b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/test/java/com/backbase/example/ExampleControllerIT.java new file mode 100644 index 0000000..f4015a3 --- /dev/null +++ b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-service/src/test/java/com/backbase/example/ExampleControllerIT.java @@ -0,0 +1,74 @@ +package com.backbase.example; + + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.backbase.buildingblocks.testutils.TestTokenUtil; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContext; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; + +/** + * A wrapper annotation for use with integration tests. + *

+ * By default, assumes the integration test modifies the {@link ApplicationContext} associated with the test/s and will + * therefore be closed and removed from the context cache at the end of the class. + */ +@SpringBootTest(classes = Application.class) +@DirtiesContext(classMode = ClassMode.AFTER_CLASS) +@AutoConfigureMockMvc +@ActiveProfiles("it") +public class ExampleControllerIT { + + public static final String TEST_JWT = + "{\n" + + " \"Role\" : [\n" + + " \"Manager\",\n" + + " \"Project Administrator\"\n" + + " ],\n" + + " \"inuid\" : \"Jimmy\",\n" + + " \"aud\" : \"www.example.com\",\n" + + " \"sub\" : \"jrocket@example.com\",\n" + + " \"Email\" : \"jrocket@example.com\",\n" + + " \"iss\" : \"Online JWT Builder\",\n" + + " \"GivenName\" : \"Johnny\",\n" + + " \"exp\" : 1516356196,\n" + + " \"iat\" : 1484820196,\n" + + " \"Surname\" : \"Rocket\"\n" + + "}"; + @Autowired + private MockMvc mvc; + + @Test + public void exampleTest() throws Exception { + MockHttpServletRequestBuilder requestBuilder = get("/client-api/v1/all-messages") + .header("Authorization", "Bearer "+TestTokenUtil.encode(TEST_JWT)); + + ResultActions result = mvc.perform(requestBuilder); + + // Then the request is successful + result.andExpect(status().isOk()); + + List message = new ObjectMapper() + .readValue(result.andReturn().getResponse().getContentAsString(), + new TypeReference<>() { + }); + + assertThat(message).isNotEmpty(); + assertThat(message.get(0).getMessage()).isNotNull(); + assertThat(message.get(0).getId()).isNotNull(); + } +} diff --git a/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/README.md b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/README.md new file mode 100644 index 0000000..5a9c77a --- /dev/null +++ b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/README.md @@ -0,0 +1,25 @@ +# Example Integration Service API Spec + +> _Fill out this file with some information about your OpenAPI spec._ + +To build this spec, use: +``` +mvn clean install +``` + +The spec is also validated as part of the build. + +## Community Documentation + +Add links to documentation including setup, config, etc. + +##Jira Project + +Add link to Jira project. + +## Confluence Links +Links to relevant confluence pages (design etc). + +## Support + +Slack, Email, Jira etc. \ No newline at end of file diff --git a/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/pom.xml b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/pom.xml new file mode 100644 index 0000000..dbc916b --- /dev/null +++ b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/pom.xml @@ -0,0 +1,97 @@ + + + 4.0.0 + + + com.backbase.buildingblocks + backbase-openapi-spec-starter-parent + 16.0.0 + + + com.backbase.poc + example-integration-openapi-spec + 1.0.0-SNAPSHOT + Backbase :: Example Integration Service API Spec + + + + 0.17.5 + + + + + + com.backbase.oss + boat-maven-plugin + ${boat-maven-plugin.version} + + + boat-validation + generate-sources + + validate + + + ${project.basedir}/src/main/resources/client-api-v1.yaml + true + + + + + boat-bundle + generate-sources + + bundle + + + ${project.basedir}/src/main/resources + ${project.build.directory} + true + + + + + boat-bundle-unversioned + generate-sources + + bundle + + + ${project.basedir}/src/main/resources + ${project.build.directory}/unversioned + false + + + + boat-linting + package + + lint + + + ${project.build.directory} + ${project.basedir}/target/boat-lint-reports + true + true + 219,215,218,115,134,104,105,110,176,M011,151,S007,S005,B013,H001 + + + + boat-docs + package + + generate + + + ${project.build.directory}/unversioned/client-api-v1.yaml + ${project.build.directory}/generated-docs + html2 + true + + + + + + + diff --git a/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/client-api-v1.yaml b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/client-api-v1.yaml new file mode 100644 index 0000000..297e773 --- /dev/null +++ b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/client-api-v1.yaml @@ -0,0 +1,169 @@ +openapi: 3.0.3 +info: + title: Message Service API Spec + description: Specs for Message Service API + version: 1.0.0 + x-icon: credit_card + +servers: + - description: local test + url: http://localhost:8080/api/v1 + +tags: + - name: Retail + +paths: + + /client-api/v1/messages: + description: No description available + + get: + summary: Returns available items, optionally filtered by name. + description: Returns available items, optionally filtered by name + operationId: getMessage + parameters: + - description: Id of the message record + example: a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1 + in: query + name: id + required: true + schema: + type: string + responses: + '200': + content: + application/json: + example: + $ref: examples/body/example-message.json + schema: + $ref: '#/components/schemas/Message' + description: No description available + '400': + $ref: 'lib/common-types.yaml#/components/responses/400BadRequest' + '500': + $ref: 'lib/common-types.yaml#/components/responses/500InternalServerError' + tags: + - message + + delete: + summary: Delete message. + description: Deletes a message + operationId: deleteMessage + parameters: + - description: Id of the message record + example: a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1 + in: query + name: id + required: true + schema: + type: string + responses: + '204': + description: request to delete completed + '400': + $ref: 'lib/common-types.yaml#/components/responses/400BadRequest' + '500': + $ref: 'lib/common-types.yaml#/components/responses/500InternalServerError' + tags: + - message + + post: + summary: Adds or updates a message. + description: Adds or updates a message + operationId: postMessage + requestBody: + content: + application/json: + example: + $ref: examples/body/example-message.json + schema: + $ref: '#/components/schemas/Message' + description: Adds or updates a message + responses: + '201': + content: + application/json: + example: + $ref: examples/body/example-message-created.json + schema: + $ref: '#/components/schemas/MessagePostResponseBody' + description: request to create item accepted + '400': + $ref: 'lib/common-types.yaml#/components/responses/400BadRequest' + '500': + $ref: 'lib/common-types.yaml#/components/responses/500InternalServerError' + tags: + - message + + put: + summary: Adds or updates a message. + description: Adds or updates a message + operationId: putMessage + requestBody: + content: + application/json: + example: + $ref: examples/body/example-message.json + schema: + $ref: '#/components/schemas/Message' + description: Adds or updates a message + responses: + '204': + description: request to update item completed + '400': + $ref: 'lib/common-types.yaml#/components/responses/400BadRequest' + '500': + $ref: 'lib/common-types.yaml#/components/responses/500InternalServerError' + tags: + - message + + /client-api/v1/all-messages: + summary: messages + description: No description available + get: + summary: Returns all available messages. + description: Returns all available messages + operationId: getMessages + responses: + '200': + content: + application/json: + example: + $ref: examples/body/example-messages-get.json + schema: + $ref: '#/components/schemas/MessagesGetResponseBody' + description: No description available + '400': + $ref: 'lib/common-types.yaml#/components/responses/400BadRequest' + '500': + $ref: 'lib/common-types.yaml#/components/responses/500InternalServerError' + tags: + - message + +components: + schemas: + ErrorItem: + $ref: 'lib/schemas/error-item.yaml' + Message: + $ref: schemas/body/message.json + MessagesGetResponseBody: + $ref: schemas/body/messages-get.json + MessagePostResponseBody: + $ref: schemas/body/message-created.json + NotAcceptableError: + properties: + message: + type: string + supportedMediaTypes: + description: List of supported media types for this endpoint + items: + type: string + type: array + type: object + UnauthorizedError: + properties: + message: + type: string + required: + - message + type: object diff --git a/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/docs/api.md b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/docs/api.md new file mode 100644 index 0000000..3365a26 --- /dev/null +++ b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/docs/api.md @@ -0,0 +1,7 @@ +# Example Persistence Service API Spec API Documentation + +Currently the Example Persistence Service API Spec API contains the following operations: +* Create an item or Update an item +* Get an item by ID +* Get list of items, optionally filtering by name +* Delete item diff --git a/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/examples/body/example-message-created.json b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/examples/body/example-message-created.json new file mode 100644 index 0000000..66dc6ed --- /dev/null +++ b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/examples/body/example-message-created.json @@ -0,0 +1,3 @@ +{ + "id": "a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1" +} diff --git a/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/examples/body/example-message.json b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/examples/body/example-message.json new file mode 100644 index 0000000..03564aa --- /dev/null +++ b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/examples/body/example-message.json @@ -0,0 +1,4 @@ +{ + "id": "a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1", + "message": "Hello" +} diff --git a/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/examples/body/example-messages-get.json b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/examples/body/example-messages-get.json new file mode 100644 index 0000000..bfcbcd8 --- /dev/null +++ b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/examples/body/example-messages-get.json @@ -0,0 +1,14 @@ +[ + { + "id": "a5b0fe7d-c4dd-40a7-bd80-dfc7869327e1", + "message": "Hello" + }, + { + "id": "d593c212-70ad-41a6-a547-d5d9232414cb", + "message": "Hola" + }, + { + "id": "9635966b-28e9-4479-8121-bb7bc9beeb62", + "message": "hej" + } +] diff --git a/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/examples/errors/example-error.json b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/examples/errors/example-error.json new file mode 100644 index 0000000..2904b69 --- /dev/null +++ b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/examples/errors/example-error.json @@ -0,0 +1,3 @@ +{ + "message": "Description of error" +} diff --git a/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/schemas/body/message-created.json b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/schemas/body/message-created.json new file mode 100644 index 0000000..0f30393 --- /dev/null +++ b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/schemas/body/message-created.json @@ -0,0 +1,8 @@ +{ + "type": "object", + "properties": { + "id": { + "type": "string" + } + } +} diff --git a/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/schemas/body/message.json b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/schemas/body/message.json new file mode 100644 index 0000000..74fd94d --- /dev/null +++ b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/schemas/body/message.json @@ -0,0 +1,15 @@ +{ + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": [ + "id", + "message" + ] +} diff --git a/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/schemas/body/messages-get.json b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/schemas/body/messages-get.json new file mode 100644 index 0000000..00778c9 --- /dev/null +++ b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/schemas/body/messages-get.json @@ -0,0 +1,6 @@ +{ + "type": "array", + "items": { + "$ref": "message.json" + } +} diff --git a/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/schemas/errors/error.json b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/schemas/errors/error.json new file mode 100644 index 0000000..5c30948 --- /dev/null +++ b/service-sdk/18.0.0/create-outbound-integration-service-openapi/example-integration-openapi-spec/src/main/resources/schemas/errors/error.json @@ -0,0 +1,12 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "message": { + "type": "string" + } + }, + "required": [ + "message" + ] +} diff --git a/service-sdk/18.0.0/include-persistence-crud-service-specification/README.md b/service-sdk/18.0.0/include-persistence-crud-service-specification/README.md new file mode 100644 index 0000000..683d59b --- /dev/null +++ b/service-sdk/18.0.0/include-persistence-crud-service-specification/README.md @@ -0,0 +1,4 @@ +This project contains code samples documented in the following sections in [Backbase Community](https://community.backbase.com/documentation/ServiceSDK/latest/index): + +* [Create a service specification with persistence capabilities](https://community.backbase.com/documentation/ServiceSDK/latest/create_a_persistence_crud_service_specification) +* [Enable service to service communications](https://community.backbase.com/documentation/ServiceSDK/latest/service_to_service_communication) diff --git a/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/README.md b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/README.md new file mode 100644 index 0000000..a9d8810 --- /dev/null +++ b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/README.md @@ -0,0 +1,25 @@ +# example-service + +_Fill out this file with some information about your Service._ + +## Dependencies + +Requires a running Eureka registry, by default on port 8080. + +## Configuration + +Service configuration is under `src/main/resources/application.yaml`. + +## Running + +To run the service in development mode, use: +- `mvn spring-boot:run` + +To run the service from the built binaries, use: +- `java -jar target/example-service-1.0.0-SNAPSHOT.jar` + +## Authorization + +Requests to this service are authorized with a Backbase Internal JWT, therefore you must access this service via the Backbase Gateway after authenticating with the authentication service. + +For local development, an internal JWT can be created from http://jwt.io, entering ```JWTSecretKeyDontUseInProduction!``` as the secret in the signature to generate a valid signed JWT. diff --git a/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/pom.xml b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/pom.xml new file mode 100644 index 0000000..516509b --- /dev/null +++ b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/pom.xml @@ -0,0 +1,155 @@ + + + 4.0.0 + + + + service-sdk-starter-core + com.backbase.buildingblocks + 16.0.0 + + + + com.backbase.example + example-crud-service + 1.0.0-SNAPSHOT + Backbase :: Digital Banking Services :: example-crud-service + + + 17 + 0.17.0 + true + + + + + io.swagger.core.v3 + swagger-annotations + + + + org.openapitools + jackson-databind-nullable + + + + org.springframework.data + spring-data-commons + + + + io.springfox + springfox-core + 3.0.0 + + + + + com.backbase.buildingblocks + persistence + + + + com.backbase.buildingblocks + service-sdk-starter-mapping + + + org.springframework.boot + spring-boot-starter-cache + + + + com.h2database + h2 + 1.4.200 + test + + + + com.mysql + mysql-connector-j + test + + + + + com.backbase.buildingblocks + service-sdk-starter-test + test + + + + + + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + unpack + generate-sources + + unpack + + + + + com.backbase.message + messaging-api + 1.0.0-SNAPSHOT + api + ${project.build.directory}/yaml + zip + true + + + **/*.yaml, **/*.json + + + + + + + com.backbase.oss + boat-maven-plugin + ${boat-maven-plugin.version} + + + + generate-client-api-code + + generate-spring-boot-embedded + + generate-sources + + ${project.build.directory}/yaml/messaging-api/client-api-v1.0.0.yaml + com.backbase.service.example.rest.spec.v1 + com.backbase.service.example.rest.spec.v1.model + + + + + + + + + + diff --git a/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/java/com/backbase/example/Application.java b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/java/com/backbase/example/Application.java new file mode 100644 index 0000000..5e8d2f0 --- /dev/null +++ b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/java/com/backbase/example/Application.java @@ -0,0 +1,20 @@ +package com.backbase.example; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; + +@SpringBootApplication +@EnableDiscoveryClient +@EnableJpaRepositories +@EntityScan +public class Application extends SpringBootServletInitializer { + + public static void main(final String[] args) { + SpringApplication.run(Application.class, args); + } + +} \ No newline at end of file diff --git a/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/java/com/backbase/example/ExampleController.java b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/java/com/backbase/example/ExampleController.java new file mode 100644 index 0000000..3a2c7e2 --- /dev/null +++ b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/java/com/backbase/example/ExampleController.java @@ -0,0 +1,60 @@ +package com.backbase.example; + +import com.backbase.example.domain.Greeting; +import com.backbase.example.mapper.GreetingsMapper; +import com.backbase.example.service.GreetingsService; +import com.backbase.service.example.rest.spec.v1.MessageApi; +import com.backbase.service.example.rest.spec.v1.model.Message; +import com.backbase.service.example.rest.spec.v1.model.MessagePostResponseBody; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +public class ExampleController implements MessageApi { + + @Autowired + private GreetingsService greetingsService; + + @Override + public ResponseEntity deleteMessage(String id) { + Greeting greeting = greetingsService.getGreetingById(id); + greetingsService.deleteGreeting(greeting); + + return ResponseEntity.noContent().build(); + } + + @Override + public ResponseEntity getMessage(String id) { + Greeting greeting = greetingsService.getGreetingById(id); + + return ResponseEntity.ok(GreetingsMapper.INSTANCE.greetingToMessage(greeting)); + } + + @Override + public ResponseEntity> getMessages() { + List greetings = greetingsService.getGreetings(); + + return ResponseEntity.ok(GreetingsMapper.INSTANCE.greetingsToMessages(greetings)); + } + + @Override + public ResponseEntity postMessage(Message message) { + Greeting greeting = GreetingsMapper.INSTANCE.messageToGreeting(message); + greetingsService.saveGreeting(greeting); + + return ResponseEntity.status(HttpStatus.CREATED).body(new MessagePostResponseBody().id(greeting.getId())); + } + + @Override + public ResponseEntity putMessage(Message message) { + Greeting greeting = greetingsService.getGreetingById(message.getId()); + greeting.setMessage(message.getMessage()); + greetingsService.saveGreeting(greeting); + + return ResponseEntity.noContent().build(); + } +} \ No newline at end of file diff --git a/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/java/com/backbase/example/domain/Greeting.java b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/java/com/backbase/example/domain/Greeting.java new file mode 100644 index 0000000..01bc7fd --- /dev/null +++ b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/java/com/backbase/example/domain/Greeting.java @@ -0,0 +1,31 @@ +package com.backbase.example.domain; + +import jakarta.persistence.*; + +@Entity +@Table(name = "greetings") +public class Greeting { + + @Id + @Column(name = "id") + private String id; + + @Column(name = "message") + private String message; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/java/com/backbase/example/mapper/GreetingsMapper.java b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/java/com/backbase/example/mapper/GreetingsMapper.java new file mode 100644 index 0000000..67e7c71 --- /dev/null +++ b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/java/com/backbase/example/mapper/GreetingsMapper.java @@ -0,0 +1,18 @@ +package com.backbase.example.mapper; + +import com.backbase.example.domain.Greeting; +import com.backbase.service.example.rest.spec.v1.model.Message; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +@Mapper +public interface GreetingsMapper { + + GreetingsMapper INSTANCE = Mappers.getMapper( GreetingsMapper.class); + + Message greetingToMessage(Greeting greeting); + List greetingsToMessages(List greetings); + Greeting messageToGreeting(Message message); +} diff --git a/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/java/com/backbase/example/repository/GreetingsRepository.java b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/java/com/backbase/example/repository/GreetingsRepository.java new file mode 100644 index 0000000..1511c66 --- /dev/null +++ b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/java/com/backbase/example/repository/GreetingsRepository.java @@ -0,0 +1,14 @@ +package com.backbase.example.repository; + +import com.backbase.example.domain.Greeting; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface GreetingsRepository extends CrudRepository { + + @Override + List findAll(); +} diff --git a/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/java/com/backbase/example/service/GreetingsService.java b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/java/com/backbase/example/service/GreetingsService.java new file mode 100644 index 0000000..3dc72f7 --- /dev/null +++ b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/java/com/backbase/example/service/GreetingsService.java @@ -0,0 +1,16 @@ +package com.backbase.example.service; + +import com.backbase.example.domain.Greeting; + +import java.util.List; + +public interface GreetingsService { + + List getGreetings(); + + Greeting getGreetingById(String id); + + void saveGreeting(Greeting greeting); + + void deleteGreeting(Greeting greeting); +} diff --git a/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/java/com/backbase/example/service/GreetingsServiceImpl.java b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/java/com/backbase/example/service/GreetingsServiceImpl.java new file mode 100644 index 0000000..39ebe0a --- /dev/null +++ b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/java/com/backbase/example/service/GreetingsServiceImpl.java @@ -0,0 +1,47 @@ +package com.backbase.example.service; + +import com.backbase.example.domain.Greeting; +import com.backbase.example.repository.GreetingsRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +public class GreetingsServiceImpl implements GreetingsService { + + @Autowired + private GreetingsRepository greetingsRepository; + + @Override + @Transactional(readOnly = true) + @PreAuthorize("permitAll()") + public List getGreetings() { + return greetingsRepository.findAll(); + } + + @Override + @Transactional(readOnly = true) + @PreAuthorize("permitAll()") + public Greeting getGreetingById(String id) { + return greetingsRepository.findById(id).get(); + } + + @Override + @Transactional + @PreAuthorize("permitAll()") + public void saveGreeting(Greeting greeting) { + greetingsRepository.save(greeting); + } + + @Override + @Transactional + @PreAuthorize("permitAll()") + public void deleteGreeting(Greeting greeting) { + greetingsRepository.delete(greeting); + } + + +} diff --git a/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/resources/application.yaml b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/resources/application.yaml new file mode 100644 index 0000000..8329b3f --- /dev/null +++ b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/resources/application.yaml @@ -0,0 +1,53 @@ +server: + port: 9915 + +# API Registry client configuration +eureka: + instance: + metadata-map: + public: true + role: live + client: + serviceUrl: + defaultZone: http://localhost:8761/eureka/ + +# Configure Internal JWT handler +sso: + jwt: + internal: + signature: + key: + type: ENV + value: SIG_SECRET_KEY + +# Spring health monitoring +management: + health: + jms: + enabled: false + +#spring: +# datasource: +# url: jdbc:mysql://localhost:3306/greetings +# username: greetings +# password: Gr33:t1ngs +# driver-class-name: com.mysql.cj.jdbc.Driver +# jpa: +# database: mysql +# generate-ddl: false +spring: + h2: + console: + enabled: true + datasource: + url: jdbc:h2:mem:greetingsdb + jpa: + generate-ddl: false + liquibase: + enabled: true + change-log: classpath:/db/changelog.yaml + +buildingblocks: + security: + xss: + autoconfig: false \ No newline at end of file diff --git a/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/resources/banner.txt b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/resources/banner.txt new file mode 100644 index 0000000..3e84197 --- /dev/null +++ b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/resources/banner.txt @@ -0,0 +1,9 @@ + ________ ________ ________ ___ __ ________ ________ ________ _______ +|\ __ \|\ __ \|\ ____\|\ \|\ \ |\ __ \|\ __ \|\ ____\|\ ___ \ +\ \ \|\ /\ \ \|\ \ \ \___|\ \ \/ /|\ \ \|\ /\ \ \|\ \ \ \___|\ \ __/| + \ \ __ \ \ __ \ \ \ \ \ ___ \ \ __ \ \ __ \ \_____ \ \ \_|/__ + \ \ \|\ \ \ \ \ \ \ \____\ \ \\ \ \ \ \|\ \ \ \ \ \|____|\ \ \ \_|\ \ + \ \_______\ \__\ \__\ \_______\ \__\\ \__\ \_______\ \__\ \__\____\_\ \ \_______\ + \|_______|\|__|\|__|\|_______|\|__| \|__|\|_______|\|__|\|__|\_________\|_______| + \|_________| + diff --git a/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/resources/bootstrap.yaml b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/resources/bootstrap.yaml new file mode 100644 index 0000000..3767fe9 --- /dev/null +++ b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/resources/bootstrap.yaml @@ -0,0 +1,3 @@ +spring: + application: + name: example-service diff --git a/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/resources/db/changelog.yaml b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/resources/db/changelog.yaml new file mode 100644 index 0000000..1308cf4 --- /dev/null +++ b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/main/resources/db/changelog.yaml @@ -0,0 +1,16 @@ +databaseChangeLog: +- changeSet: + id: greetings + author: filer + changes: + - createTable: + tableName: GREETINGS + columns: + - column: + constraints: + nullable: false + name: id + type: VARCHAR(36) + - column: + name: message + type: VARCHAR(255) \ No newline at end of file diff --git a/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/test/java/com/backbase/example/ExampleControllerIT.java b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/test/java/com/backbase/example/ExampleControllerIT.java new file mode 100644 index 0000000..a10cf3a --- /dev/null +++ b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/test/java/com/backbase/example/ExampleControllerIT.java @@ -0,0 +1,121 @@ +package com.backbase.example; + + +import com.backbase.service.example.rest.spec.v1.model.Message; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContext; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.security.web.csrf.CsrfToken; +import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.http.MediaType; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; + +/** + * A wrapper annotation for use with integration tests. + * + * By default, assumes the integration test modifies the + * {@link ApplicationContext} associated with the test/s and will therefore be + * closed and removed from the context cache at the end of the class. + */ +@SpringBootTest(classes = Application.class) +@AutoConfigureMockMvc +@ActiveProfiles("it") +public class ExampleControllerIT { + + String TOKEN_ATTR_NAME = "org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN"; + + public static final String TEST_JWT = + "Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsIm5hZiI6MTUwNjUyNzQzMSwiY25leHAiOnRydWUsImdycCI6" + + "WyJhZG1pbihBRE1JTikiXSwiYW5sb2MiOnRydWUsImFuZXhwIjp0cnVlLCJlbmJsIjp0cnVlLCJleHAiOjE1MDY1" + + "MjU5MzEsImlhdCI6MTUwNjUyNTYzMSwicm9sIjpbIlJPTEVfQUNUVUFUT1IiLCJST0xFX0FETUlOIiwiUk9MRV9nc" + + "m91cF9hZG1pbihBRE1JTikiXSwianRpIjoiMjQ1MDBkNDQtNDRiZS00MTI1LTg4MjctOWY1NDAwOTc4NmEzIn0.5qZ" + + "nncyJpWJ8GqklJK6RmyHUUPddNOh52al65_C4T9o"; + @Autowired + private MockMvc mvc; + + @Test + public void exampleTest() throws Exception { + String greetingsId = givenAGreetingExists(); + whenWeGetTheMessageByIdThenTheMessageExists(greetingsId); + WhenWeGetAllMessagesThenAListOfMessagesIsReturned(); + } + + private void WhenWeGetAllMessagesThenAListOfMessagesIsReturned() throws Exception { + //When: Request for all messages + MockHttpServletRequestBuilder getAllMessagesRequestBuilder = get("/client-api/v1/all-messages") + .header("Authorization", TEST_JWT); + + ResultActions getAllMessagesResult = mvc.perform(getAllMessagesRequestBuilder).andDo(print()); + + // Then the request is successful with a list of messages + getAllMessagesResult.andExpect(status().isOk()); + + List listOfMessages = new ObjectMapper().readValue(getAllMessagesResult.andReturn().getResponse().getContentAsString(), + new TypeReference<>() {}); + + assertThat(listOfMessages).isNotEmpty(); + } + + private void whenWeGetTheMessageByIdThenTheMessageExists(String greetingsId) throws Exception { + //When: we get that message + MockHttpServletRequestBuilder getMessageRequestBuilder = get("/client-api/v1/messages?id=" + greetingsId) + .header("Authorization", TEST_JWT); + + ResultActions result = mvc.perform(getMessageRequestBuilder).andDo(print()); + + result = result.andExpect(status().isOk()); + + MvcResult response = result.andExpect(content().contentType(MediaType.APPLICATION_JSON)).andReturn(); + + String responseBody = response.getResponse().getContentAsString(); + + //Then: the message exists + assertThat(responseBody).contains("Hello World").as("ID in response should match ID in request"); + } + + private String givenAGreetingExists() throws Exception { + //Given: a message exists + String id = UUID.randomUUID().toString(); + Message message = new Message(); + message.setMessage("Hello World is it me your looking for?"); + message.setId(id); + + String messageAsString = new ObjectMapper().writeValueAsString(message); + + HttpSessionCsrfTokenRepository httpSessionCsrfTokenRepository = new HttpSessionCsrfTokenRepository(); + CsrfToken csrfToken = httpSessionCsrfTokenRepository.generateToken(new MockHttpServletRequest()); + + MockHttpServletRequestBuilder postRequestBuilder = post("/client-api/v1/messages") + .header("Authorization", TEST_JWT) + .sessionAttr(TOKEN_ATTR_NAME, csrfToken) + .param(csrfToken.getParameterName(), csrfToken.getToken()) + .contentType(MediaType.APPLICATION_JSON) + .content(messageAsString); + + ResultActions postResult = mvc.perform(postRequestBuilder).andDo(print()); + + postResult.andExpect(status().isCreated()); + + Message messagePostResponseBody = new ObjectMapper().readValue(postResult.andReturn().getResponse().getContentAsString(), + new TypeReference<>() {}); + return messagePostResponseBody.getId(); + } +} diff --git a/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/test/resources/application.yaml b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/test/resources/application.yaml new file mode 100644 index 0000000..6e18db3 --- /dev/null +++ b/service-sdk/18.0.0/include-persistence-crud-service-specification/example-crud-service/src/test/resources/application.yaml @@ -0,0 +1,12 @@ +eureka: + client: + enabled: false + +logging: + level: + ROOT: DEBUG + +spring: + liquibase: + enabled: true + change-log: classpath:/db/changelog.yaml diff --git a/service-sdk/18.0.0/pom.xml b/service-sdk/18.0.0/pom.xml new file mode 100644 index 0000000..20dedfa --- /dev/null +++ b/service-sdk/18.0.0/pom.xml @@ -0,0 +1,30 @@ + + + 4.0.0 + + com.backbase.buildingblocks + documentation-code-samples + 16.0.0 + pom + + + + Backbase Artifact Builds Repository + artifacts.backbase.com-builds + https://artifacts.backbase.com/staging + + + + + add-persistence-to-service/example-persistence-service + create-core-service/example-core-service + create-openapi-client/banking-service + create-openapi-spec-project/messaging-api + create-openapi-spec-project/messaging-service + create-outbound-integration-service-openapi/example-integration-openapi-spec + create-outbound-integration-service-openapi/example-integration-openapi-service + include-persistence-crud-service-specification/example-crud-service + service-to-service-communication/example-service-to-service + + + diff --git a/service-sdk/18.0.0/service-to-service-communication/README.md b/service-sdk/18.0.0/service-to-service-communication/README.md new file mode 100644 index 0000000..43fefbf --- /dev/null +++ b/service-sdk/18.0.0/service-to-service-communication/README.md @@ -0,0 +1,3 @@ +This project contains code samples documented in the following section in [Backbase Community](https://community.backbase.com/documentation/ServiceSDK/latest/index): + +* [Enable service to service communication](https://community.backbase.com/documentation/ServiceSDK/latest/service_to_service_communication) diff --git a/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/README.md b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/README.md new file mode 100644 index 0000000..fe9c1e3 --- /dev/null +++ b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/README.md @@ -0,0 +1,25 @@ +# example-service + +_Fill out this file with some information about your Service._ + +## Dependencies + +Requires a running Eureka registry, by default on port 8080. + +## Configuration + +Service configuration is under `src/main/resources/application.yaml`. + +## Running + +To run the service in development mode, use: +- `mvn spring-boot:run` + +To run the service from the built binaries, use: +- `java -jar target/example-service-to-service-1.0.0-SNAPSHOT.jar` + +## Authorization + +Requests to this service are authorized with a Backbase Internal JWT, therefore you must access this service via the Backbase Edge after authenticating with Identity service. + +For local development, an internal JWT can be created from http://jwt.io, entering ```JWTSecretKeyDontUseInProduction!``` as the secret in the signature to generate a valid signed JWT. diff --git a/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/pom.xml b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/pom.xml new file mode 100644 index 0000000..2cd4e23 --- /dev/null +++ b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/pom.xml @@ -0,0 +1,186 @@ + + + 4.0.0 + + + + service-sdk-starter-core + com.backbase.buildingblocks + 16.0.0 + + + + com.backbase.example + example-service-to-service + 1.0.0-SNAPSHOT + Backbase :: Digital Banking Services :: example-service-to-service + + + 17 + 3.0.2 + 0.17.5 + true + + + + + io.swagger.core.v3 + swagger-annotations + + + org.openapitools + jackson-databind-nullable + + + org.springframework.data + spring-data-commons + + + io.springfox + springfox-core + 3.0.0 + + + com.google.code.findbugs + jsr305 + ${jsr305.version} + + + + + + com.backbase.buildingblocks + auth-security + + + com.backbase.buildingblocks + building-blocks-common + + + com.backbase.buildingblocks + communication + + + + + + com.backbase.buildingblocks + persistence + + + + com.backbase.buildingblocks + service-sdk-starter-mapping + + + com.backbase.buildingblocks + api + + + + org.springframework.boot + spring-boot-starter-cache + + + + com.h2database + h2 + 1.4.200 + test + + + + com.mysql + mysql-connector-j + test + + + + + com.backbase.buildingblocks + service-sdk-starter-test + test + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + unpack + generate-sources + + unpack + + + + + com.backbase.message + messaging-api + 1.0.0-SNAPSHOT + api + ${project.build.directory}/yaml + zip + true + + + com.backbase.poc + example-integration-openapi-spec + 1.0.0-SNAPSHOT + ${project.build.directory}/yaml/example-integration-openapi-spec + jar + true + + + **/*.yaml, **/*.json + + + + + + + com.backbase.oss + boat-maven-plugin + ${boat-maven-plugin.version} + + + generate-client-api-code + + generate-spring-boot-embedded + + generate-sources + + ${project.build.directory}/yaml/messaging-api/client-api-v1.0.0.yaml + com.backbase.service.example.rest.spec.v1 + com.backbase.service.example.rest.spec.v1.model + + + + + generate-integration-client + + generate-rest-template-embedded + + generate-sources + + ${project.build.directory}/yaml/example-integration-openapi-spec/client-api-v1.yaml + com.backbase.integration.example.client.v1 + com.backbase.integration.example.client.v1.model + restTemplateBeanName=interServiceRestTemplate + + + + + + + + + + diff --git a/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/java/com/backbase/example/Application.java b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/java/com/backbase/example/Application.java new file mode 100644 index 0000000..5e8d2f0 --- /dev/null +++ b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/java/com/backbase/example/Application.java @@ -0,0 +1,20 @@ +package com.backbase.example; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; + +@SpringBootApplication +@EnableDiscoveryClient +@EnableJpaRepositories +@EntityScan +public class Application extends SpringBootServletInitializer { + + public static void main(final String[] args) { + SpringApplication.run(Application.class, args); + } + +} \ No newline at end of file diff --git a/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/java/com/backbase/example/controller/ExampleController.java b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/java/com/backbase/example/controller/ExampleController.java new file mode 100644 index 0000000..3744e0a --- /dev/null +++ b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/java/com/backbase/example/controller/ExampleController.java @@ -0,0 +1,71 @@ +package com.backbase.example.controller; + +import com.backbase.example.domain.Greeting; +import com.backbase.example.mapper.GreetingsMapper; +import com.backbase.example.service.GreetingsService; +import com.backbase.service.example.rest.spec.v1.MessageApi; +import com.backbase.service.example.rest.spec.v1.model.Message; +import com.backbase.service.example.rest.spec.v1.model.MessagePostResponseBody; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +public class ExampleController implements MessageApi { + + @Autowired + private GreetingsService greetingsService; + + @Override + public ResponseEntity deleteMessage(String id) { + Greeting greeting = greetingsService.getGreetingById(id); + greetingsService.deleteGreeting(greeting); + + return ResponseEntity.noContent().build(); + } + + @Override + public ResponseEntity getMessage(String id) { + Greeting greeting = greetingsService.getGreetingById(id); + + return ResponseEntity.ok(GreetingsMapper.INSTANCE.greetingToMessage(greeting)); + } + + @Override + public ResponseEntity postMessage(Message message) { + Greeting greeting = GreetingsMapper.INSTANCE.messageToGreeting(message); + greetingsService.saveGreeting(greeting); + + return ResponseEntity.status(HttpStatus.CREATED).body(new MessagePostResponseBody().id(greeting.getId())); + } + + @Override + public ResponseEntity putMessage(Message message) { + Greeting greeting = greetingsService.getGreetingById(message.getId()); + greeting.setMessage(message.getMessage()); + greetingsService.saveGreeting(greeting); + + return ResponseEntity.noContent().build(); + } + + @Override + public ResponseEntity> getMessages() { + List greetings = greetingsService.getGreetings(); + + /** + * + * Example: We could do the following + * + * + * List externalGreetings = greetingsService.getExternalGreetings(); + * greetings.addAll(externalGreetings); + * + * + * which will make a downstream call to an integration service and merge results with persisted greetings + */ + return ResponseEntity.ok(GreetingsMapper.INSTANCE.greetingsToMessages(greetings)); + } +} \ No newline at end of file diff --git a/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/java/com/backbase/example/domain/Greeting.java b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/java/com/backbase/example/domain/Greeting.java new file mode 100644 index 0000000..01bc7fd --- /dev/null +++ b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/java/com/backbase/example/domain/Greeting.java @@ -0,0 +1,31 @@ +package com.backbase.example.domain; + +import jakarta.persistence.*; + +@Entity +@Table(name = "greetings") +public class Greeting { + + @Id + @Column(name = "id") + private String id; + + @Column(name = "message") + private String message; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/java/com/backbase/example/mapper/GreetingsMapper.java b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/java/com/backbase/example/mapper/GreetingsMapper.java new file mode 100644 index 0000000..4ca35da --- /dev/null +++ b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/java/com/backbase/example/mapper/GreetingsMapper.java @@ -0,0 +1,19 @@ +package com.backbase.example.mapper; + +import com.backbase.example.domain.Greeting; +import com.backbase.service.example.rest.spec.v1.model.Message; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +@Mapper +public interface GreetingsMapper { + + GreetingsMapper INSTANCE = Mappers.getMapper( GreetingsMapper.class); + + Message greetingToMessage(Greeting greeting); + List greetingsToMessages(List greetings); + Greeting messageToGreeting(Message message); + List integrationMessageToGreeting(List integrationMessages); +} diff --git a/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/java/com/backbase/example/repository/GreetingsRepository.java b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/java/com/backbase/example/repository/GreetingsRepository.java new file mode 100644 index 0000000..1511c66 --- /dev/null +++ b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/java/com/backbase/example/repository/GreetingsRepository.java @@ -0,0 +1,14 @@ +package com.backbase.example.repository; + +import com.backbase.example.domain.Greeting; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface GreetingsRepository extends CrudRepository { + + @Override + List findAll(); +} diff --git a/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/java/com/backbase/example/service/GreetingsService.java b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/java/com/backbase/example/service/GreetingsService.java new file mode 100644 index 0000000..e214782 --- /dev/null +++ b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/java/com/backbase/example/service/GreetingsService.java @@ -0,0 +1,18 @@ +package com.backbase.example.service; + +import com.backbase.example.domain.Greeting; + +import java.util.List; + +public interface GreetingsService { + + List getGreetings(); + // tag::getExternalGreetings[] + List getExternalGreetings(); + // end::getExternalGreetings[] + Greeting getGreetingById(String id); + + void saveGreeting(Greeting greeting); + + void deleteGreeting(Greeting greeting); +} diff --git a/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/java/com/backbase/example/service/GreetingsServiceImpl.java b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/java/com/backbase/example/service/GreetingsServiceImpl.java new file mode 100644 index 0000000..2b57565 --- /dev/null +++ b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/java/com/backbase/example/service/GreetingsServiceImpl.java @@ -0,0 +1,57 @@ +package com.backbase.example.service; + +import com.backbase.example.domain.Greeting; +import com.backbase.example.mapper.GreetingsMapper; +import com.backbase.example.repository.GreetingsRepository; +import com.backbase.integration.example.client.v1.MessageApi; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +public class GreetingsServiceImpl implements GreetingsService { + + @Autowired + private GreetingsRepository greetingsRepository; + + @Autowired + private MessageApi exampleIntegrationApiClient; + + @Override + @Transactional(readOnly = true) + @PreAuthorize("permitAll()") + public List getGreetings() { + return greetingsRepository.findAll(); + } + + // tag::getExternalGreetings[] + @Override + @Transactional(readOnly = true) + @PreAuthorize("permitAll()") + public List getExternalGreetings() { + return GreetingsMapper.INSTANCE.integrationMessageToGreeting(exampleIntegrationApiClient.getMessages()); + } + // end::getExternalGreetings[] + + @Override + @Transactional(readOnly = true) + @PreAuthorize("permitAll()") + public Greeting getGreetingById(String id) { + return greetingsRepository.findById(id).get(); + } + + @Override + @PreAuthorize("permitAll()") + public void saveGreeting(Greeting greeting) { + greetingsRepository.save(greeting); + } + + @Override + @PreAuthorize("permitAll()") + public void deleteGreeting(Greeting greeting) { + greetingsRepository.delete(greeting); + } +} diff --git a/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/java/com/backbase/example/service/IntegrationApiClientConfig.java b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/java/com/backbase/example/service/IntegrationApiClientConfig.java new file mode 100644 index 0000000..84c1811 --- /dev/null +++ b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/java/com/backbase/example/service/IntegrationApiClientConfig.java @@ -0,0 +1,25 @@ +package com.backbase.example.service; + +import com.backbase.buildingblocks.communication.client.ApiClientConfig; +import com.backbase.integration.example.client.ApiClient; +import com.backbase.integration.example.client.v1.MessageApi; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class IntegrationApiClientConfig extends ApiClientConfig { + + public IntegrationApiClientConfig() { + super("example-integration-service"); + } + + @Bean + public MessageApi exampleIntegrationApiClient() { + return new MessageApi(createaApiClient()); + } + + private ApiClient createaApiClient() { + return new ApiClient(getRestTemplate()) + .setBasePath(createBasePath()); + } +} \ No newline at end of file diff --git a/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/resources/application.yaml b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/resources/application.yaml new file mode 100644 index 0000000..d644517 --- /dev/null +++ b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/resources/application.yaml @@ -0,0 +1,57 @@ +server: + port: 9915 + +# API Registry client configuration +eureka: + instance: + metadata-map: + public: true + role: live + client: + serviceUrl: + defaultZone: http://localhost:8761/eureka/ + +# Configure Internal JWT handler +sso: + jwt: + internal: + signature: + key: + type: ENV + value: SIG_SECRET_KEY + +# Spring health monitoring +management: + health: + jms: + enabled: false + +#spring: +# datasource: +# url: jdbc:mysql://localhost:3306/greetings +# username: greetings +# password: Gr33:t1ngs +# driver-class-name: com.mysql.cj.jdbc.Driver +# jpa: +# database: mysql +# generate-ddl: false +spring: + h2: + console: + enabled: true + datasource: + url: jdbc:h2:mem:greetingsdb;Mode=Oracle + sql: + init: + platform: h2 + continue-on-error: true + jpa: + generate-ddl: false + liquibase: + enabled: true + change-log: classpath:db/changelog.yaml + +buildingblocks: + security: + xss: + autoconfig: false \ No newline at end of file diff --git a/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/resources/banner.txt b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/resources/banner.txt new file mode 100644 index 0000000..3e84197 --- /dev/null +++ b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/resources/banner.txt @@ -0,0 +1,9 @@ + ________ ________ ________ ___ __ ________ ________ ________ _______ +|\ __ \|\ __ \|\ ____\|\ \|\ \ |\ __ \|\ __ \|\ ____\|\ ___ \ +\ \ \|\ /\ \ \|\ \ \ \___|\ \ \/ /|\ \ \|\ /\ \ \|\ \ \ \___|\ \ __/| + \ \ __ \ \ __ \ \ \ \ \ ___ \ \ __ \ \ __ \ \_____ \ \ \_|/__ + \ \ \|\ \ \ \ \ \ \ \____\ \ \\ \ \ \ \|\ \ \ \ \ \|____|\ \ \ \_|\ \ + \ \_______\ \__\ \__\ \_______\ \__\\ \__\ \_______\ \__\ \__\____\_\ \ \_______\ + \|_______|\|__|\|__|\|_______|\|__| \|__|\|_______|\|__|\|__|\_________\|_______| + \|_________| + diff --git a/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/resources/bootstrap.yaml b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/resources/bootstrap.yaml new file mode 100644 index 0000000..3767fe9 --- /dev/null +++ b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/resources/bootstrap.yaml @@ -0,0 +1,3 @@ +spring: + application: + name: example-service diff --git a/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/resources/db/changelog.yaml b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/resources/db/changelog.yaml new file mode 100644 index 0000000..ed6f6eb --- /dev/null +++ b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/main/resources/db/changelog.yaml @@ -0,0 +1,16 @@ +databaseChangeLog: +- changeSet: + id: greetings + author: filer + changes: + - createTable: + tableName: greetings + columns: + - column: + constraints: + nullable: false + name: id + type: VARCHAR(36) + - column: + name: message + type: VARCHAR(255) \ No newline at end of file diff --git a/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/test/java/com/backbase/example/ExampleControllerIT.java b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/test/java/com/backbase/example/ExampleControllerIT.java new file mode 100644 index 0000000..2aafd6e --- /dev/null +++ b/service-sdk/18.0.0/service-to-service-communication/example-service-to-service/src/test/java/com/backbase/example/ExampleControllerIT.java @@ -0,0 +1,122 @@ +package com.backbase.example; + + +import com.backbase.service.example.rest.spec.v1.model.Message; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContext; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.security.web.csrf.CsrfToken; +import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.http.MediaType; + +import java.util.List; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; + +/** + * A wrapper annotation for use with integration tests. + * + * By default, assumes the integration test modifies the + * {@link ApplicationContext} associated with the test/s and will therefore be + * closed and removed from the context cache at the end of the class. + */ +@SpringBootTest(classes = Application.class) +@AutoConfigureMockMvc +@ActiveProfiles("it") +public class ExampleControllerIT { + + String TOKEN_ATTR_NAME = "org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN"; + + public static final String TEST_JWT = + "Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsIm5hZiI6MTUwNjUyNzQzMSwiY25leHAiOnRydWUsImdycCI6" + + "WyJhZG1pbihBRE1JTikiXSwiYW5sb2MiOnRydWUsImFuZXhwIjp0cnVlLCJlbmJsIjp0cnVlLCJleHAiOjE1MDY1" + + "MjU5MzEsImlhdCI6MTUwNjUyNTYzMSwicm9sIjpbIlJPTEVfQUNUVUFUT1IiLCJST0xFX0FETUlOIiwiUk9MRV9nc" + + "m91cF9hZG1pbihBRE1JTikiXSwianRpIjoiMjQ1MDBkNDQtNDRiZS00MTI1LTg4MjctOWY1NDAwOTc4NmEzIn0.5qZ" + + "nncyJpWJ8GqklJK6RmyHUUPddNOh52al65_C4T9o"; + @Autowired + private MockMvc mvc; + + @Test + public void exampleTest() throws Exception { + String greetingsId = givenAGreetingExists(); + whenWeGetTheMessageByIdThenTheMessageExists(greetingsId); + WhenWeGetAllMessagesThenAListOfMessagesIsReturned(); + } + + private void WhenWeGetAllMessagesThenAListOfMessagesIsReturned() throws Exception { + //When: Request for all messages + MockHttpServletRequestBuilder getAllMessagesRequestBuilder = get("/client-api/v1/all-messages") + .header("Authorization", TEST_JWT); + + ResultActions getAllMessagesResult = mvc.perform(getAllMessagesRequestBuilder).andDo(print()); + + // Then the request is successful with a list of messages + getAllMessagesResult.andExpect(status().isOk()); + + List listOfMessages = new ObjectMapper().readValue(getAllMessagesResult.andReturn().getResponse().getContentAsString(), + new TypeReference<>() {}); + + assertThat(listOfMessages).isNotEmpty(); + } + + private void whenWeGetTheMessageByIdThenTheMessageExists(String greetingsId) throws Exception { + //When: we get that message + MockHttpServletRequestBuilder getMessageRequestBuilder = get("/client-api/v1/messages?id=" + greetingsId) + .header("Authorization", TEST_JWT); + + ResultActions result = mvc.perform(getMessageRequestBuilder).andDo(print()); + + result = result.andExpect(status().isOk()); + + MvcResult response = result.andExpect(content().contentType(MediaType.APPLICATION_JSON)).andReturn(); + + String responseBody = response.getResponse().getContentAsString(); + + //Then: the message exists + assertThat(responseBody).contains("Hello World").as("ID in response should match ID in request"); + } + + private String givenAGreetingExists() throws Exception { + //Given: a message exists + String id = UUID.randomUUID().toString(); + Message message = new Message(); + message.setMessage("Hello World is it me your looking for?"); + message.setId(id); + + String messageAsString = new ObjectMapper().writeValueAsString(message); + + HttpSessionCsrfTokenRepository httpSessionCsrfTokenRepository = new HttpSessionCsrfTokenRepository(); + CsrfToken csrfToken = httpSessionCsrfTokenRepository.generateToken(new MockHttpServletRequest()); + + MockHttpServletRequestBuilder postRequestBuilder = post("/client-api/v1/messages") + .header("Authorization", TEST_JWT) + .sessionAttr(TOKEN_ATTR_NAME, csrfToken) + .param(csrfToken.getParameterName(), csrfToken.getToken()) + .contentType(MediaType.APPLICATION_JSON) + .content(messageAsString); + + ResultActions postResult = mvc.perform(postRequestBuilder).andDo(print()); + + postResult.andExpect(status().isCreated()); + + Message messagePostResponseBody = new ObjectMapper().readValue(postResult.andReturn().getResponse().getContentAsString(), + new TypeReference<>() {}); + return messagePostResponseBody.getId(); + } +}