Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/solve missing fragment exceptions #233

Merged
merged 1 commit into from
Sep 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ protected LdesFragment createNewFragment(FragmentInfo parentFragmentInfo) {
parentFragmentInfo.getViewName(),
fragmentPairs);

return new LdesFragment(LdesFragmentNamingStrategy.generateFragmentName(ldesConfig, fragmentInfo),
return new LdesFragment(
LdesFragmentNamingStrategy.generateFragmentName(ldesConfig.getHostName(), fragmentInfo.getViewName(),
fragmentInfo.getFragmentPairs()),
fragmentInfo);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ protected LdesFragment createNewFragment(FragmentInfo parentFragmentInfo) {
FragmentInfo fragmentInfo = new FragmentInfo(
parentFragmentInfo.getViewName(), fragmentPairs);

return new LdesFragment(LdesFragmentNamingStrategy.generateFragmentName(ldesConfig, fragmentInfo),
return new LdesFragment(
LdesFragmentNamingStrategy.generateFragmentName(ldesConfig.getHostName(), fragmentInfo.getViewName(),
fragmentInfo.getFragmentPairs()),
fragmentInfo);
}

Expand Down
19 changes: 19 additions & 0 deletions ldes-server-application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,28 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- TRACING -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-brave</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-otel-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-extension-annotations</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-otlp</artifactId>
</dependency>
</dependencies>

Expand Down
10 changes: 10 additions & 0 deletions ldes-server-domain/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,16 @@
</dependency>

<!-- TRACING -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-brave</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-otel-autoconfigure</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
package be.vlaanderen.informatievlaanderen.ldes.server.domain.config;

import be.vlaanderen.informatievlaanderen.ldes.server.domain.ldesfragment.valueobjects.FragmentInfo;
import be.vlaanderen.informatievlaanderen.ldes.server.domain.ldesfragmentrequest.valueobjects.FragmentPair;

import java.util.List;
import java.util.stream.Collectors;

public class LdesFragmentNamingStrategy {

private LdesFragmentNamingStrategy() {
}

public static String generateFragmentName(LdesConfig config, FragmentInfo fragmentInfo) {
public static String generateFragmentName(String hostname, String viewname, List<FragmentPair> fragmentPairs) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(config.getHostName())
.append("/").append(fragmentInfo.getViewName());
stringBuilder.append(hostname)
.append("/").append(viewname);

if (!fragmentInfo.getFragmentPairs().isEmpty()) {
if (!fragmentPairs.isEmpty()) {
stringBuilder.append("?");
stringBuilder
.append(fragmentInfo.getFragmentPairs().stream().map(fragmentPair -> fragmentPair.fragmentKey() +
.append(fragmentPairs.stream().map(fragmentPair -> fragmentPair.fragmentKey() +
"=" + fragmentPair.fragmentValue()).collect(Collectors.joining("&")));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package be.vlaanderen.informatievlaanderen.ldes.server.domain.exceptions;

public class MissingFragmentException extends RuntimeException {
private final String fragmentId;

public MissingFragmentException(String fragmentId) {
super();
this.fragmentId = fragmentId;
}

@Override
public String getMessage() {
return "No fragment exists with fragment identifier: " + fragmentId;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package be.vlaanderen.informatievlaanderen.ldes.server.domain.ldesfragment;
package be.vlaanderen.informatievlaanderen.ldes.server.domain.exceptions;

public class MissingRootFragmentException extends RuntimeException {
private final String viewName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,12 @@

import be.vlaanderen.informatievlaanderen.ldes.server.domain.config.LdesConfig;
import be.vlaanderen.informatievlaanderen.ldes.server.domain.config.LdesFragmentNamingStrategy;
import be.vlaanderen.informatievlaanderen.ldes.server.domain.ldesfragment.repository.LdesFragmentRepository;
import be.vlaanderen.informatievlaanderen.ldes.server.domain.ldesfragment.valueobjects.FragmentInfo;
import be.vlaanderen.informatievlaanderen.ldes.server.domain.exceptions.MissingFragmentException;
import be.vlaanderen.informatievlaanderen.ldes.server.domain.ldesfragment.entities.LdesFragment;
import be.vlaanderen.informatievlaanderen.ldes.server.domain.ldesfragmentrequest.valueobjects.FragmentPair;
import be.vlaanderen.informatievlaanderen.ldes.server.domain.ldesfragment.repository.LdesFragmentRepository;
import be.vlaanderen.informatievlaanderen.ldes.server.domain.ldesfragmentrequest.valueobjects.LdesFragmentRequest;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class FragmentFetchServiceImpl implements FragmentFetchService {

Expand All @@ -27,15 +24,9 @@ public FragmentFetchServiceImpl(LdesConfig ldesConfig,
public LdesFragment getFragment(LdesFragmentRequest ldesFragmentRequest) {
return ldesFragmentRepository
.retrieveFragment(ldesFragmentRequest)
.orElseGet(
() -> createEmptyFragment(ldesFragmentRequest.viewName(), ldesFragmentRequest.fragmentPairs()));
}

private LdesFragment createEmptyFragment(String viewName,
List<FragmentPair> fragmentationMap) {
FragmentInfo fragmentInfo = new FragmentInfo(viewName, fragmentationMap);

return new LdesFragment(LdesFragmentNamingStrategy.generateFragmentName(ldesConfig, fragmentInfo),
fragmentInfo);
.orElseThrow(
() -> new MissingFragmentException(
LdesFragmentNamingStrategy.generateFragmentName(ldesConfig.getHostName(),
ldesFragmentRequest.viewName(), ldesFragmentRequest.fragmentPairs())));
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package be.vlaanderen.informatievlaanderen.ldes.server.domain.ldesfragment.services;

import org.springframework.cloud.sleuth.annotation.NewSpan;

public interface FragmentationExecutor {

@NewSpan
void executeFragmentation(String memberId);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package be.vlaanderen.informatievlaanderen.ldes.server.domain.ldesfragment.services;

import be.vlaanderen.informatievlaanderen.ldes.server.domain.ldesfragment.MissingRootFragmentException;
import be.vlaanderen.informatievlaanderen.ldes.server.domain.exceptions.MissingRootFragmentException;
import be.vlaanderen.informatievlaanderen.ldes.server.domain.ldesfragment.entities.LdesFragment;
import be.vlaanderen.informatievlaanderen.ldes.server.domain.ldesfragment.repository.LdesFragmentRepository;
import org.springframework.cloud.sleuth.Span;
Expand All @@ -27,7 +27,7 @@ public FragmentationExecutorImpl(Map<String, FragmentationService> fragmentation
public void executeFragmentation(String memberId) {
Span parentSpan = tracer.nextSpan().name("execute-fragmentation");
parentSpan.start();
fragmentationServices.entrySet().forEach(entry -> {
fragmentationServices.entrySet().parallelStream().forEach(entry -> {
LdesFragment rootFragmentOfView = retrieveRootFragmentOfView(entry.getKey(), parentSpan);
entry.getValue().addMemberToFragment(rootFragmentOfView, memberId, parentSpan);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ private void createRoot(String viewName) {
FragmentInfo fragmentInfo = new FragmentInfo(
viewName, List.of());
LdesFragment ldesFragment = new LdesFragment(
LdesFragmentNamingStrategy.generateFragmentName(ldesConfig, fragmentInfo),
LdesFragmentNamingStrategy.generateFragmentName(ldesConfig.getHostName(), fragmentInfo.getViewName(),
fragmentInfo.getFragmentPairs()),
fragmentInfo);
ldesFragmentRepository.saveFragment(ldesFragment);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package be.vlaanderen.informatievlaanderen.ldes.server.domain.config;

import be.vlaanderen.informatievlaanderen.ldes.server.domain.ldesfragment.valueobjects.FragmentInfo;
import be.vlaanderen.informatievlaanderen.ldes.server.domain.ldesfragmentrequest.valueobjects.FragmentPair;
import org.junit.jupiter.api.Test;

Expand All @@ -12,14 +11,11 @@ class LdesFragmentNamingStrategyTest {

@Test
void when_FragmentNameIsGenerated_HostNameCollectionNameAndFragmentPairsAreFormatted() {
LdesConfig ldesConfig = new LdesConfig();
ldesConfig.setCollectionName("mobility-hindrances");
ldesConfig.setHostName("http://localhost:8080");
FragmentInfo fragmentInfo = new FragmentInfo(
"firstView", List.of(new FragmentPair("tile", "0/1/2"),
new FragmentPair("generatedAtTime", "2020-12-05T09:00:00.000Z")));
List<FragmentPair> fragmentPairs = List.of(new FragmentPair("tile", "0/1/2"),
new FragmentPair("generatedAtTime", "2020-12-05T09:00:00.000Z"));

String fragmentId = LdesFragmentNamingStrategy.generateFragmentName(ldesConfig, fragmentInfo);
String fragmentId = LdesFragmentNamingStrategy.generateFragmentName("http://localhost:8080", "firstView",
fragmentPairs);

String expectedFragmentId = "http://localhost:8080/firstView?tile=0/1/2&generatedAtTime=2020-12-05T09:00:00.000Z";
assertEquals(expectedFragmentId, fragmentId);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,33 +1,23 @@
package be.vlaanderen.informatievlaanderen.ldes.server.domain.ldesfragment.services;

import be.vlaanderen.informatievlaanderen.ldes.server.domain.config.LdesConfig;
import be.vlaanderen.informatievlaanderen.ldes.server.domain.exceptions.MissingFragmentException;
import be.vlaanderen.informatievlaanderen.ldes.server.domain.ldesfragment.entities.LdesFragment;
import be.vlaanderen.informatievlaanderen.ldes.server.domain.ldesfragment.repository.LdesFragmentRepository;
import be.vlaanderen.informatievlaanderen.ldes.server.domain.ldesfragment.valueobjects.FragmentInfo;
import be.vlaanderen.informatievlaanderen.ldes.server.domain.ldesfragmentrequest.valueobjects.FragmentPair;
import be.vlaanderen.informatievlaanderen.ldes.server.domain.ldesfragmentrequest.valueobjects.LdesFragmentRequest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;
import java.util.Optional;

import static be.vlaanderen.informatievlaanderen.ldes.server.domain.constants.RdfConstants.GENERATED_AT_TIME;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = { LdesConfig.class })
@EnableConfigurationProperties
@ActiveProfiles("test")
class FragmentFetchServiceImplTest {

private static final String COLLECTION_NAME = "exampleData";
Expand All @@ -42,31 +32,30 @@ class FragmentFetchServiceImplTest {
private static final FragmentInfo FRAGMENT_INFO = new FragmentInfo(
VIEW_NAME, List.of(new FragmentPair(GENERATED_AT_TIME, FRAGMENTATION_VALUE_1)));

@Autowired
private LdesConfig ldesConfig;

private final LdesFragmentRepository ldesFragmentRepository = mock(LdesFragmentRepository.class);

private FragmentFetchService fragmentFetchService;

@BeforeEach
void setUp() {
LdesConfig ldesConfig = new LdesConfig();
ldesConfig.setHostName("http://localhost:8089");
fragmentFetchService = new FragmentFetchServiceImpl(ldesConfig,
ldesFragmentRepository);
}

@Test
void when_getFragment_WhenNoFragmentExists_ThenReturnEmptyFragment() {
void when_getFragment_WhenNoFragmentExists_ThenMissingFragmentExceptionIsThrown() {
LdesFragmentRequest ldesFragmentRequest = new LdesFragmentRequest(VIEW_NAME,
List.of(new FragmentPair(GENERATED_AT_TIME, FRAGMENTATION_VALUE_1)));
when(ldesFragmentRepository.retrieveFragment(ldesFragmentRequest)).thenReturn(Optional.empty());

LdesFragment returnedFragment = fragmentFetchService.getFragment(ldesFragmentRequest);
MissingFragmentException missingFragmentException = assertThrows(MissingFragmentException.class,
() -> fragmentFetchService.getFragment(ldesFragmentRequest));

assertEquals(0, returnedFragment.getMemberIds().size());
assertTrue(returnedFragment.getFragmentInfo().getValueOfKey(GENERATED_AT_TIME).isPresent());
assertEquals(FRAGMENTATION_VALUE_1,
returnedFragment.getFragmentInfo().getValueOfKey(GENERATED_AT_TIME).get());
assertEquals(
"No fragment exists with fragment identifier: http://localhost:8089/view?generatedAtTime=2020-12-28T09:36:09.72Z",
missingFragmentException.getMessage());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
package be.vlaanderen.informatievlaanderen.ldes.server.domain.ldesfragment.services;

import be.vlaanderen.informatievlaanderen.ldes.server.domain.ldesfragment.MissingRootFragmentException;
import be.vlaanderen.informatievlaanderen.ldes.server.domain.exceptions.MissingRootFragmentException;
import be.vlaanderen.informatievlaanderen.ldes.server.domain.ldesfragment.entities.LdesFragment;
import be.vlaanderen.informatievlaanderen.ldes.server.domain.ldesfragment.repository.LdesFragmentRepository;
import be.vlaanderen.informatievlaanderen.ldes.server.domain.ldesfragment.valueobjects.FragmentInfo;
import be.vlaanderen.informatievlaanderen.ldes.server.domain.ldesfragmentrequest.valueobjects.LdesFragmentRequest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;

import java.util.List;
import java.util.Map;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package be.vlaanderen.informatievlaanderen.ldes.server.rest.exceptionhandling;

import be.vlaanderen.informatievlaanderen.ldes.server.domain.exceptions.MissingFragmentException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

@ControllerAdvice
public class RestResponseEntityExceptionHandler
extends ResponseEntityExceptionHandler {

@ExceptionHandler(value = { MissingFragmentException.class })
protected ResponseEntity<Object> handleConflict(
RuntimeException ex, WebRequest request) {
String bodyOfResponse = ex.getMessage();
return handleExceptionInternal(ex, bodyOfResponse,
new HttpHeaders(), HttpStatus.NOT_FOUND, request);
}
}