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

Refactoring/fairspc 81 #1567

Merged
merged 21 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
29adbdb
FAIRSPC-81: migrated views endpoint to spring mvc
tgreenwood Oct 3, 2024
d3f11cd
FAIRSPC-81: migrated workspace endpoints to spring mvc
tgreenwood Oct 4, 2024
51b3ce9
FAIRSPC-81: refactoring of controller tests
tgreenwood Oct 4, 2024
ea2e4d6
FAIRSPC-81: migrated metadata API to spring mvc
tgreenwood Oct 7, 2024
e070d9d
FAIRSPC-81: migrated vocabulary API to spring mvc
tgreenwood Oct 7, 2024
0e2a77b
FAIRSPC-81: migrated features endpoint to spring mvc
tgreenwood Oct 8, 2024
1351e93
FAIRSPC-81: migrated maintain endpoint to spring mvc
tgreenwood Oct 8, 2024
e344891
FAIRSPC-81: migrated user endpoints to spring mvc
tgreenwood Oct 8, 2024
7c8bbd0
Merge branch 'refactoring/FAIRSPC-82' into refactoring/FAIRSPC-81
tgreenwood Oct 9, 2024
b81b005
FAIRSPC-82: migrated search endpoints to spring mvc
tgreenwood Oct 9, 2024
e53bc8e
Merge branch 'refactoring/FAIRSPC-82' into refactoring/FAIRSPC-81
tgreenwood Oct 10, 2024
17e7514
FAIRSPC-81: got rid of java-spark framework and Jetty
tgreenwood Oct 10, 2024
921ade7
FAIRSPC-81: tuned global exception handling
tgreenwood Oct 11, 2024
d4c338b
Merge branch 'refactoring/FAIRSPC-82' into refactoring/FAIRSPC-81
tgreenwood Oct 14, 2024
ac7b6e4
FAIRSPC-81: aligned all controllers with /api/ path
tgreenwood Oct 14, 2024
b18d47a
FAIRSPC-81: named reasonable get view data
tgreenwood Oct 14, 2024
c35bae3
FAIRSPC-81: removed redundant try-catch
tgreenwood Oct 14, 2024
a0c37d1
FAIRSPC-81: aligned the way we map resources across all controllers
tgreenwood Oct 14, 2024
001022e
FAIRSPC-81: removed mentioning of spark on log config
tgreenwood Oct 14, 2024
91ef6af
FAIRSPC-81: replaced two value classes with records
tgreenwood Oct 14, 2024
fc40d62
FAIRSPC-81: set servlet context path to /api
tgreenwood Oct 15, 2024
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
9 changes: 3 additions & 6 deletions projects/saturn/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ dependencies {
implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:${jacksonVersion}"
implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:${jacksonVersion}"

implementation "org.zoomba-lang:spark-core:3.0" // todo: to be replaced with Spring MVC
implementation 'com.pivovarit:throwing-function:1.5.1'
implementation 'com.google.guava:guava:33.0.0-jre'
implementation('com.io-informatics.oss:jackson-jsonld:0.1.1') {
Expand All @@ -75,16 +74,13 @@ dependencies {

testImplementation "junit:junit:4.13.2"
testImplementation "org.mockito:mockito-core:${mockitoVersion}"
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.junit.vintage:junit-vintage-engine:5.10.2'
testImplementation "org.testcontainers:postgresql:1.19.6"
testImplementation('com.github.stefanbirkner:system-rules:1.19.0') {
exclude group: 'junit', module:'junit-dep'
}

constraints {
// implementation('com.fasterxml.jackson.core:jackson-databind:2.9.10.1') {
// because 'previous versions have security vulnerabilities'
// }
}
}

jacocoTestReport {
Expand Down Expand Up @@ -117,4 +113,5 @@ test {
// They also blocks usage of testing library mocking environment variables,
// That is why this additional arg for tests is needed
jvmArgs = ['--add-opens', 'java.base/java.util=ALL-UNNAMED']
useJUnitPlatform()
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import java.sql.SQLException;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.RequiredArgsConstructor;
import org.keycloak.OAuth2Constants;
import org.keycloak.admin.client.Keycloak;
Expand All @@ -20,12 +22,16 @@
import io.fairspace.saturn.config.properties.ViewDatabaseProperties;
import io.fairspace.saturn.config.properties.WebDavProperties;
import io.fairspace.saturn.rdf.SaturnDatasetFactory;
import io.fairspace.saturn.services.IRIModule;
import io.fairspace.saturn.services.users.UserService;
import io.fairspace.saturn.services.views.SparqlQueryService;
import io.fairspace.saturn.services.views.ViewStoreClientFactory;

import static io.fairspace.saturn.config.ConfigLoader.VIEWS_CONFIG;

import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
import static com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS;

/**
* Configuration for the Spark filter to enable the Saturn API.
*/
Expand Down Expand Up @@ -93,4 +99,13 @@ public Keycloak getKeycloak(KeycloakClientProperties keycloakClientProperties) {
.password(keycloakClientProperties.getClientSecret())
.build();
}

@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper()
.registerModule(new IRIModule())
.registerModule(new JavaTimeModule())
.configure(WRITE_DATES_AS_TIMESTAMPS, false)
.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);
}
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package io.fairspace.saturn.controller;

import java.util.Set;

import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import io.fairspace.saturn.config.Feature;
import io.fairspace.saturn.config.properties.FeatureProperties;

@RestController
@RequestMapping("${application.basePath}/features")
@RequiredArgsConstructor
public class FeaturesController {

private final FeatureProperties featureProperties;

@GetMapping("/")
public ResponseEntity<Set<Feature>> getFeatures() {
return ResponseEntity.ok(featureProperties.getFeatures());
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package io.fairspace.saturn.controller;

import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import io.fairspace.saturn.config.Services;

@RestController
@RequestMapping("${application.basePath}/maintenance")
@RequiredArgsConstructor
public class MaintenanceController {

private final Services services;

@PostMapping("/reindex")
public ResponseEntity<Void> startReindex() {
services.getMaintenanceService().startRecreateIndexTask();
return ResponseEntity.noContent().build();
}

@PostMapping("/compact")
public ResponseEntity<Void> compactRdfStorage() {
services.getMaintenanceService().compactRdfStorageTask();
return ResponseEntity.noContent().build();
}

@GetMapping("/status")
public ResponseEntity<String> getStatus() {
var status = services.getMaintenanceService().active() ? "active" : "inactive";
return ResponseEntity.ok(status);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package io.fairspace.saturn.controller;

import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ResourceFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import io.fairspace.saturn.config.Services;
import io.fairspace.saturn.controller.validation.ValidIri;

import static io.fairspace.saturn.controller.enums.CustomMediaType.APPLICATION_LD_JSON;
import static io.fairspace.saturn.controller.enums.CustomMediaType.APPLICATION_N_TRIPLES;
import static io.fairspace.saturn.controller.enums.CustomMediaType.TEXT_TURTLE;
import static io.fairspace.saturn.services.metadata.Serialization.deserialize;
import static io.fairspace.saturn.services.metadata.Serialization.getFormat;
import static io.fairspace.saturn.services.metadata.Serialization.serialize;

@Log4j2
@RestController
@RequestMapping("${application.basePath}/metadata")
@RequiredArgsConstructor
@Validated
public class MetadataController {

private static final String DO_VIEWS_UPDATE = "doViewsUpdate";

public static final String DO_VIEWS_UPDATE_DEFAULT_VALUE = "true";

private final Services services;

@GetMapping(
value = "/",
produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_LD_JSON, TEXT_TURTLE, APPLICATION_N_TRIPLES})
public ResponseEntity<String> getMetadata(
@RequestParam(required = false) String subject,
@RequestParam(name = "withValueProperties", defaultValue = "false") boolean withValueProperties,
@RequestHeader(value = HttpHeaders.ACCEPT, required = false) String acceptHeader) {
var model = services.getMetadataService().get(subject, withValueProperties);
var format = getFormat(acceptHeader);
var metadata = serialize(model, format);
return ResponseEntity.ok(metadata);
}

@PutMapping(
value = "/",
consumes = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_LD_JSON, TEXT_TURTLE, APPLICATION_N_TRIPLES})
@ResponseStatus(HttpStatus.NO_CONTENT)
public void putMetadata(
@RequestBody String body,
@RequestHeader(value = HttpHeaders.CONTENT_TYPE, required = false) String contentType,
@RequestParam(name = DO_VIEWS_UPDATE, defaultValue = DO_VIEWS_UPDATE_DEFAULT_VALUE)
boolean doMaterializedViewsRefresh) {
Model model = deserialize(body, contentType);
services.getMetadataService().put(model, doMaterializedViewsRefresh);
}

@PatchMapping(
value = "/",
consumes = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_LD_JSON, TEXT_TURTLE, APPLICATION_N_TRIPLES})
@ResponseStatus(HttpStatus.NO_CONTENT)
public void patchMetadata(
@RequestBody String body,
@RequestHeader(value = HttpHeaders.CONTENT_TYPE, required = false) String contentType,
@RequestParam(name = DO_VIEWS_UPDATE, defaultValue = DO_VIEWS_UPDATE_DEFAULT_VALUE) boolean doViewsUpdate) {
Model model = deserialize(body, contentType);
services.getMetadataService().patch(model, doViewsUpdate);
}

@DeleteMapping("/")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void deleteMetadata(
@RequestParam(required = false) @ValidIri String subject,
@RequestBody(required = false) String body,
@RequestHeader(value = HttpHeaders.CONTENT_TYPE, required = false) String contentType,
@RequestParam(name = DO_VIEWS_UPDATE, defaultValue = DO_VIEWS_UPDATE_DEFAULT_VALUE)
boolean doMaterializedViewsRefresh) {
if (subject != null) {
if (!services.getMetadataService().softDelete(ResourceFactory.createResource(subject))) {
throw new IllegalArgumentException("Subject could not be deleted");
}
} else {
Model model = deserialize(body, contentType);
services.getMetadataService().delete(model, doMaterializedViewsRefresh);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package io.fairspace.saturn.controller;

import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import io.fairspace.saturn.config.Services;
import io.fairspace.saturn.controller.dto.SearchResultsDto;
import io.fairspace.saturn.controller.dto.request.FileSearchRequest;
import io.fairspace.saturn.controller.dto.request.LookupSearchRequest;

@RestController
@RequestMapping("${application.basePath}/search")
@RequiredArgsConstructor
public class SearchController {

private final Services services;

@PostMapping(value = "/files")
public ResponseEntity<SearchResultsDto> searchFiles(@RequestBody FileSearchRequest request) {
var searchResult = services.getFileSearchService().searchFiles(request);
var resultDto = SearchResultsDto.builder()
.results(searchResult)
.query(request.getQuery())
.build();
return ResponseEntity.ok(resultDto);
}

@PostMapping(value = "/lookup")
public ResponseEntity<SearchResultsDto> lookupSearch(@RequestBody LookupSearchRequest request) {
var results = services.getSearchService().getLookupSearchResults(request);
return ResponseEntity.ok(results);
}
}
Loading
Loading