Basic scaffolding for the backend-for-frontend component #1

Merged
ansv7779 merged 5 commits from basic-scaffolding-bff into main 2025-04-03 09:52:12 +02:00
7 changed files with 58 additions and 4 deletions
Showing only changes of commit 896e78679d - Show all commits

View File

@ -11,4 +11,8 @@ The application will be available at http://localhost:8080 and tracing telemetry
If running via some other means start the containers with `docker compose up`. If running via some other means start the containers with `docker compose up`.
Make sure you're using the correct JVM arguments (`--enable-preview`). Make sure you're using the correct JVM arguments (`--enable-preview`).
Optionally add `-javaagent:opentelemetry-javaagent.jar -Dotel.javaagent.configuration-file=opentelemetry-javaagent.properties` Optionally add `-javaagent:opentelemetry-javaagent.jar -Dotel.javaagent.configuration-file=opentelemetry-javaagent.properties`
to enable OpenTelemetry tracing. to enable OpenTelemetry tracing.
## Mocking backend APIs
[Apimposter](https://gitea.dsv.su.se/DMC/apimposter) is used to mock the backend APIs.
The mock data is defined in `src/mock-api`. See the linked documentation for details on how to define the mock data.

View File

@ -7,3 +7,13 @@ services:
ports: ports:
- "4318:4318" # OpenTelemetry Collector - "4318:4318" # OpenTelemetry Collector
- "16686:16686" # Jaeger UI - "16686:16686" # Jaeger UI
mock-apis:
build: https://gitea.dsv.su.se/DMC/apimposter.git
restart: unless-stopped
ports:
- '63163:8080'
environment:
MOCK_BASE_PATH: / # HTTP base path for the mock server
MOCK_FILE_PATH: /mocks
volumes:
- ./src/mock-api:/mocks

View File

@ -0,0 +1,7 @@
package se.su.dsv.studentportalen.bff;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("se.su.dsv.backend-api")
public record BackendApiConfiguration(String daisyUrl) {
}

View File

@ -2,9 +2,13 @@ package se.su.dsv.studentportalen.bff;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@SpringBootApplication @SpringBootApplication
@EnableConfigurationProperties
@ConfigurationPropertiesScan
public class Studentportalen extends SpringBootServletInitializer { public class Studentportalen extends SpringBootServletInitializer {
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(Studentportalen.class, args); SpringApplication.run(Studentportalen.class, args);

View File

@ -16,8 +16,10 @@ import java.util.concurrent.StructuredTaskScope.Subtask;
public class TestController { public class TestController {
private final RestClient restClient; private final RestClient restClient;
private final BackendApiConfiguration backendApiConfiguration;
public TestController() { public TestController(final BackendApiConfiguration backendApiConfiguration) {
this.backendApiConfiguration = backendApiConfiguration;
this.restClient = RestClient.builder() this.restClient = RestClient.builder()
.baseUrl("http://localhost:8080") .baseUrl("http://localhost:8080")
.build(); .build();
@ -43,6 +45,15 @@ public class TestController {
return email; return email;
}); });
Subtask<DaisyProfile> daisyProfile = scope.fork(() -> {
DaisyProfile profile = restClient.get()
.uri(backendApiConfiguration.daisyUrl(), builder -> builder
.path("/profile")
.build())
.retrieve()
.body(DaisyProfile.class);
return profile;
});
// Wait for all tasks to complete (either success or failure) // Wait for all tasks to complete (either success or failure)
scope.join(); scope.join();
@ -50,9 +61,10 @@ public class TestController {
// Error if any task failed (or check each individual subtask for partial responses) // Error if any task failed (or check each individual subtask for partial responses)
scope.throwIfFailed(); scope.throwIfFailed();
return "Hello, I am %s and my email is %s.".formatted( return "Hello, I am %s and my email is %s. My Daisy profile is: %s".formatted(
nameTask.get(), nameTask.get(),
emailTask.get()); emailTask.get(),
daisyProfile.get());
} }
} }
@ -67,4 +79,6 @@ public class TestController {
Thread.sleep(Duration.ofSeconds(3)); Thread.sleep(Duration.ofSeconds(3));
return "greg@localhost"; return "greg@localhost";
} }
record DaisyProfile(String name, String mail) {}
} }

View File

@ -0,0 +1,5 @@
se:
su:
dsv:
backend-api:
daisy-url: http://localhost:63163/daisy

View File

@ -0,0 +1,10 @@
- method: "GET"
path: "/"
delay: 200
response:
status: 200
headers:
Content-Type: "application/json"
body:
name: "Gregorious the Glorious"
mail: "greg_da_great@localhost"