Skip to content

Commit 08cc1ba

Browse files
authored
Merge pull request #96 from elixir-europe/mars-receipt-exception
Mars receipt exception
2 parents eaaabc1 + 6317c9b commit 08cc1ba

File tree

19 files changed

+788
-396
lines changed

19 files changed

+788
-396
lines changed

repository-services/isajson-biosamples/src/main/java/com/elixir/biohackaton/ISAToSRA/biosamples/controller/BioSampleSubmissionController.java

+34-24
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,27 @@
44
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
55
import static org.springframework.http.MediaType.APPLICATION_XML_VALUE;
66

7+
import java.util.List;
8+
9+
import org.springframework.beans.factory.annotation.Autowired;
10+
import org.springframework.web.bind.annotation.CrossOrigin;
11+
import org.springframework.web.bind.annotation.PostMapping;
12+
import org.springframework.web.bind.annotation.RequestBody;
13+
import org.springframework.web.bind.annotation.RequestParam;
14+
import org.springframework.web.bind.annotation.RestController;
15+
716
import com.elixir.biohackaton.ISAToSRA.biosamples.model.BiosampleAccessionsMap;
817
import com.elixir.biohackaton.ISAToSRA.biosamples.service.BioSamplesSubmitter;
918
import com.elixir.biohackaton.ISAToSRA.biosamples.service.MarsReceiptService;
10-
import com.elixir.biohackaton.ISAToSRA.receipt.isamodel.*;
11-
import com.elixir.biohackaton.ISAToSRA.receipt.marsmodel.MarsReceipt;
19+
import com.elixir.biohackaton.ISAToSRA.receipt.MarsReceiptException;
20+
import com.elixir.biohackaton.ISAToSRA.receipt.isamodel.IsaJson;
21+
import com.elixir.biohackaton.ISAToSRA.receipt.isamodel.Study;
1222
import com.fasterxml.jackson.annotation.JsonInclude;
1323
import com.fasterxml.jackson.databind.ObjectMapper;
24+
1425
import io.swagger.v3.oas.annotations.responses.ApiResponse;
1526
import io.swagger.v3.oas.annotations.responses.ApiResponses;
16-
17-
import java.util.List;
18-
1927
import lombok.extern.slf4j.Slf4j;
20-
import org.springframework.beans.factory.annotation.Autowired;
21-
import org.springframework.web.bind.annotation.*;
2228

2329
@Slf4j
2430
@RestController
@@ -42,33 +48,37 @@ public class BioSampleSubmissionController {
4248
consumes = { APPLICATION_JSON_VALUE, APPLICATION_XML_VALUE })
4349
public String performSubmissionToBioSamplesAndEna(
4450
@RequestBody final String submissionPayload,
45-
@RequestParam(value = "webinjwt") String webinJwt)
46-
throws Exception {
47-
String webinToken;
48-
if (webinJwt != null) {
49-
webinToken = webinJwt;
50-
} else {
51-
throw new RuntimeException("Webin Authentication Token is not provided");
52-
}
51+
@RequestParam(value = "webinjwt") String webinJwt) {
52+
try {
53+
if (webinJwt == null || webinJwt.isEmpty()) {
54+
throw new RuntimeException("Webin Authentication Token is not provided");
55+
}
5356

54-
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
57+
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
5558

56-
final IsaJson isaJson = this.objectMapper.readValue(submissionPayload, IsaJson.class);
57-
final List<Study> studies = getStudies(isaJson);
59+
final IsaJson isaJson = this.objectMapper.readValue(submissionPayload, IsaJson.class);
60+
final List<Study> studies = getStudies(isaJson);
5861

59-
final BiosampleAccessionsMap accessionsMap = this.bioSamplesSubmitter.createBioSamples(studies, webinToken);
60-
final MarsReceipt marsReceipt = marsReceiptService.convertReceiptToMars(accessionsMap, isaJson);
62+
final BiosampleAccessionsMap accessionsMap = this.bioSamplesSubmitter.createBioSamples(studies, webinJwt);
63+
marsReceiptService.convertReceiptToMars(accessionsMap, isaJson);
6164

62-
return marsReceiptService.convertMarsReceiptToJson(marsReceipt);
65+
return marsReceiptService.convertMarsReceiptToJson();
66+
} catch (final MarsReceiptException e) {
67+
log.error("Mars receipt excption", e);
68+
marsReceiptService.setMarsReceiptErrors(e.getError());
69+
return marsReceiptService.convertMarsReceiptToJson();
70+
} catch (final Exception e) {
71+
log.error("Internal server error", e);
72+
marsReceiptService.setMarsReceiptErrors(e.getMessage());
73+
return marsReceiptService.convertMarsReceiptToJson();
74+
}
6375
}
6476

6577
public List<Study> getStudies(final IsaJson isaJson) {
6678
try {
6779
return isaJson.getInvestigation().getStudies();
6880
} catch (final Exception e) {
69-
log.info("Failed to parse ISA JSON and get studies", e);
81+
throw new MarsReceiptException(e, "Failed to parse ISA JSON and get studies");
7082
}
71-
72-
return null;
7383
}
7484
}

repository-services/isajson-biosamples/src/main/java/com/elixir/biohackaton/ISAToSRA/biosamples/service/BioSamplesSubmitter.java

+63-40
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
11
/** Elixir BioHackathon 2022 */
22
package com.elixir.biohackaton.ISAToSRA.biosamples.service;
33

4-
import com.elixir.biohackaton.ISAToSRA.biosamples.model.Attribute;
5-
import com.elixir.biohackaton.ISAToSRA.biosamples.model.BiosampleAccessionsMap;
6-
import com.elixir.biohackaton.ISAToSRA.biosamples.model.Relationship;
7-
import com.elixir.biohackaton.ISAToSRA.biosamples.model.BioSample;
8-
import com.elixir.biohackaton.ISAToSRA.receipt.ReceiptAccessionsMap;
9-
import com.elixir.biohackaton.ISAToSRA.receipt.isamodel.*;
10-
114
import java.time.Instant;
12-
import java.util.*;
5+
import java.util.ArrayList;
6+
import java.util.Collections;
7+
import java.util.List;
8+
import java.util.Map;
139
import java.util.concurrent.atomic.AtomicReference;
14-
import lombok.extern.slf4j.Slf4j;
10+
11+
import org.springframework.beans.factory.annotation.Autowired;
1512
import org.springframework.core.ParameterizedTypeReference;
1613
import org.springframework.hateoas.EntityModel;
1714
import org.springframework.http.HttpEntity;
@@ -21,10 +18,28 @@
2118
import org.springframework.stereotype.Service;
2219
import org.springframework.web.client.RestTemplate;
2320

21+
import com.elixir.biohackaton.ISAToSRA.biosamples.model.Attribute;
22+
import com.elixir.biohackaton.ISAToSRA.biosamples.model.BioSample;
23+
import com.elixir.biohackaton.ISAToSRA.biosamples.model.BiosampleAccessionsMap;
24+
import com.elixir.biohackaton.ISAToSRA.biosamples.model.Relationship;
25+
import com.elixir.biohackaton.ISAToSRA.receipt.MarsReceiptException;
26+
import com.elixir.biohackaton.ISAToSRA.receipt.ReceiptAccessionsMap;
27+
import com.elixir.biohackaton.ISAToSRA.receipt.isamodel.Category;
28+
import com.elixir.biohackaton.ISAToSRA.receipt.isamodel.Characteristic;
29+
import com.elixir.biohackaton.ISAToSRA.receipt.isamodel.Sample;
30+
import com.elixir.biohackaton.ISAToSRA.receipt.isamodel.Source;
31+
import com.elixir.biohackaton.ISAToSRA.receipt.isamodel.Study;
32+
import com.elixir.biohackaton.ISAToSRA.receipt.isamodel.Value;
33+
34+
import lombok.extern.slf4j.Slf4j;
35+
2436
@Service
2537
@Slf4j
2638
public class BioSamplesSubmitter {
2739

40+
@Autowired
41+
private MarsReceiptService marsReceiptService;
42+
2843
public BiosampleAccessionsMap createBioSamples(final List<Study> studies, final String webinToken) {
2944
final BiosampleAccessionsMap typeToBioSamplesAccessionMap = new BiosampleAccessionsMap();
3045

@@ -38,7 +53,7 @@ public BiosampleAccessionsMap createBioSamples(final List<Study> studies, final
3853
}
3954
}
4055

41-
typeToBioSamplesAccessionMap.sourceAccessionsMap.keyName = Source.Fields.name;
56+
typeToBioSamplesAccessionMap.sourceAccessionsMap.isaItemName = Source.Fields.name;
4257
typeToBioSamplesAccessionMap.sourceAccessionsMap.accessionMap.put(
4358
sourceBioSample.getName(),
4459
sourceBioSample.getAccession());
@@ -51,36 +66,44 @@ public BiosampleAccessionsMap createBioSamples(final List<Study> studies, final
5166
typeToBioSamplesAccessionMap.studyAccessionsMap = new ReceiptAccessionsMap(
5267
Study.Fields.title,
5368
study.getTitle());
54-
5569
study
5670
.getMaterials()
5771
.getSamples()
5872
.forEach(
5973
sample -> {
60-
final BioSample persistedChildSample = this.createAndUpdateChildSampleWithRelationship(
61-
sample,
62-
sourceBioSample.getAccession(),
63-
finalSourceBioSampleOrganismAttribute.getValue(),
64-
webinToken);
65-
66-
if (persistedChildSample != null) {
67-
final Characteristic biosampleAccessionCharacteristic = getBioSampleAccessionCharacteristic(
68-
new AtomicReference<>(persistedChildSample));
69-
final ArrayList<Characteristic> sampleCharacteristics = sample.getCharacteristics() != null
70-
? sample.getCharacteristics()
71-
: new ArrayList<>();
72-
sampleCharacteristics.add(biosampleAccessionCharacteristic);
73-
74-
typeToBioSamplesAccessionMap.sampleAccessionsMap.keyName = Sample.Fields.name;
75-
typeToBioSamplesAccessionMap.sampleAccessionsMap.accessionMap.put(
76-
persistedChildSample.getName(),
77-
persistedChildSample.getAccession());
74+
try {
75+
final BioSample persistedChildSample = this.createAndUpdateChildSampleWithRelationship(
76+
sample,
77+
sourceBioSample.getAccession(),
78+
finalSourceBioSampleOrganismAttribute.getValue(),
79+
webinToken);
80+
81+
if (persistedChildSample != null) {
82+
final Characteristic biosampleAccessionCharacteristic = getBioSampleAccessionCharacteristic(
83+
new AtomicReference<>(persistedChildSample));
84+
final ArrayList<Characteristic> sampleCharacteristics = sample
85+
.getCharacteristics() != null
86+
? sample.getCharacteristics()
87+
: new ArrayList<>();
88+
sampleCharacteristics.add(biosampleAccessionCharacteristic);
89+
90+
typeToBioSamplesAccessionMap.sampleAccessionsMap.isaItemName = Sample.Fields.name;
91+
typeToBioSamplesAccessionMap.sampleAccessionsMap.accessionMap.put(
92+
persistedChildSample.getName(),
93+
persistedChildSample.getAccession());
94+
}
95+
} catch (Exception e) {
96+
throw new MarsReceiptException(e,
97+
"Failed to parse ISA Json and create samples in BioSamples (SAMPLE)",
98+
marsReceiptService.getSampleMarsPath(
99+
Map.entry(Study.Fields.title, study.title),
100+
Map.entry(Sample.Fields.id, sample.id)));
78101
}
79102
});
80103
});
81104
}
82105
} catch (final Exception e) {
83-
throw new RuntimeException("Failed to parse ISA Json and create samples in BioSamples", e);
106+
throw new MarsReceiptException(e, "Failed to parse ISA Json and create samples in BioSamples");
84107
}
85108

86109
return typeToBioSamplesAccessionMap;
@@ -95,8 +118,8 @@ private BioSample createAndUpdateChildSampleWithRelationship(
95118
.withRelease(Instant.now())
96119
.withAttributes(
97120
List.of(Attribute.build("organism", parentSampleOrganism),
98-
Attribute.build("collection date", "not provided"),
99-
Attribute.build("geographic location (country and/or sea)", "not provided")))
121+
Attribute.build("collection date", "not provided"),
122+
Attribute.build("geographic location (country and/or sea)", "not provided")))
100123
.build();
101124
try {
102125
final EntityModel<BioSample> persistedSampleEntity = this.createSampleInBioSamples(bioSample, webinToken);
@@ -122,7 +145,7 @@ private BioSample createAndUpdateChildSampleWithRelationship(
122145
return null;
123146
}
124147
} catch (final Exception e) {
125-
throw new RuntimeException("Failed to handle child samples", e);
148+
throw new MarsReceiptException(e, "Failed to handle child samples");
126149
}
127150
}
128151

@@ -150,8 +173,8 @@ private BioSample createSourceBioSample(final List<Study> studies, final String
150173
final BioSample sourceSample = new BioSample.Builder(source.getName())
151174
.withRelease(Instant.now())
152175
.withAttributes(List.of(organismAttribute.get(),
153-
Attribute.build("collection date", "not provided"),
154-
Attribute.build("geographic location (country and/or sea)", "not provided")))
176+
Attribute.build("collection date", "not provided"),
177+
Attribute.build("geographic location (country and/or sea)", "not provided")))
155178
.build();
156179
final EntityModel<BioSample> persistedParentSampleEntity = this.createSampleInBioSamples(sourceSample,
157180
webinToken);
@@ -165,7 +188,7 @@ private BioSample createSourceBioSample(final List<Study> studies, final String
165188
sourceCharacteristics.add(biosampleAccessionCharacteristic);
166189
source.setCharacteristics(sourceCharacteristics);
167190
} else {
168-
throw new RuntimeException("Failed to store source sample to BioSamples");
191+
throw new MarsReceiptException("Failed to store source sample to BioSamples");
169192
}
170193
}));
171194

@@ -204,8 +227,8 @@ private BioSample updateSampleWithRelationshipsToBioSamples(
204227
new ParameterizedTypeReference<>() {
205228
});
206229
return biosamplesResponse.getBody().getContent();
207-
} catch (final Exception ex) {
208-
throw new RuntimeException("Failed to add relationships to child samples", ex);
230+
} catch (final Exception e) {
231+
throw new MarsReceiptException(e, "Failed to add relationships to child samples");
209232
}
210233
}
211234

@@ -226,8 +249,8 @@ private EntityModel<BioSample> createSampleInBioSamples(
226249
});
227250

228251
return biosamplesResponse.getBody();
229-
} catch (final Exception ex) {
230-
throw new RuntimeException("Failed to create samples in BioSamples", ex);
252+
} catch (final Exception e) {
253+
throw new MarsReceiptException(e, "Failed to create samples in BioSamples");
231254
}
232255
}
233256

repository-services/isajson-biosamples/src/main/java/com/elixir/biohackaton/ISAToSRA/biosamples/service/MarsReceiptService.java

+35-14
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
/** Elixir BioHackathon 2022 */
22
package com.elixir.biohackaton.ISAToSRA.biosamples.service;
33

4+
import javax.servlet.http.HttpServletRequest;
5+
import javax.servlet.http.HttpServletResponse;
6+
7+
import org.springframework.stereotype.Service;
8+
import org.springframework.web.servlet.HandlerInterceptor;
9+
410
import com.elixir.biohackaton.ISAToSRA.biosamples.model.BiosampleAccessionsMap;
511
import com.elixir.biohackaton.ISAToSRA.receipt.MarsReceiptProvider;
6-
import com.elixir.biohackaton.ISAToSRA.receipt.isamodel.*;
7-
import com.elixir.biohackaton.ISAToSRA.receipt.marsmodel.*;
12+
import com.elixir.biohackaton.ISAToSRA.receipt.isamodel.IsaJson;
13+
import com.elixir.biohackaton.ISAToSRA.receipt.marsmodel.MarsError;
14+
import com.elixir.biohackaton.ISAToSRA.receipt.marsmodel.MarsErrorType;
815
import com.fasterxml.jackson.annotation.JsonInclude;
916
import com.fasterxml.jackson.databind.ObjectMapper;
1017
import com.fasterxml.jackson.databind.SerializationFeature;
11-
import org.springframework.stereotype.Service;
1218

1319
@Service
14-
public class MarsReceiptService extends MarsReceiptProvider {
20+
public class MarsReceiptService extends MarsReceiptProvider implements HandlerInterceptor {
1521
private final ObjectMapper jsonMapper = new ObjectMapper();
1622

1723
private void setupJsonMapper() {
@@ -21,29 +27,44 @@ private void setupJsonMapper() {
2127
}
2228

2329
public MarsReceiptService() {
30+
super("biosamples"); // TODO decide whether to use instead
31+
// https://registry.identifiers.org/registry/biosample
2432
setupJsonMapper();
2533
}
2634

27-
public String convertMarsReceiptToJson(final MarsReceipt marsReceipt) {
35+
// Reset MARS receipt per request
36+
@Override
37+
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
38+
throws Exception {
39+
resetMarsReceipt();
40+
return HandlerInterceptor.super.preHandle(request, response, handler);
41+
}
42+
43+
public String convertMarsReceiptToJson() {
2844
try {
29-
return jsonMapper.writeValueAsString(marsReceipt);
45+
return jsonMapper.writeValueAsString(getMarsReceipt());
3046
} catch (Exception ex) {
31-
throw new RuntimeException("receipt", ex);
47+
throw new RuntimeException("Receipt", ex);
3248
}
3349
}
3450

51+
public void setMarsReceiptErrors(String... errors) {
52+
super.setMarsReceiptErrors(MarsErrorType.INVALID_METADATA, errors);
53+
}
54+
55+
public void setMarsReceiptErrors(MarsError... errors) {
56+
super.setMarsReceiptErrors(MarsErrorType.INVALID_METADATA, errors);
57+
}
58+
3559
/**
3660
* Converting BioSample receipt to Mars data format
3761
*
38-
* @see
39-
* https://github.com/elixir-europe/MARS/blob/refactor/repository-services/repository-api.md#response
62+
* @see <a href='https://github.com/elixir-europe/MARS/blob/main/repository-services/repository-api.md#response'>Repository API Specification</a>
4063
* @param biosampleAccessionsMap {@link BiosampleAccessionsMap} Receipt from Biosample
41-
* @param isaJson {@link IsaJson} Requested ISA-Json
42-
* @return {@link MarsReceipt} Mars response data
64+
* @param isaJson {@link IsaJson} Requested ISA-Json
4365
*/
44-
public MarsReceipt convertReceiptToMars(final BiosampleAccessionsMap biosampleAccessionsMap, final IsaJson isaJson) {
45-
return buildMarsReceipt(
46-
"biosamples", // https://registry.identifiers.org/registry/biosample
66+
public void convertReceiptToMars(final BiosampleAccessionsMap biosampleAccessionsMap, final IsaJson isaJson) {
67+
buildMarsReceipt(
4768
biosampleAccessionsMap.studyAccessionsMap,
4869
biosampleAccessionsMap.sampleAccessionsMap,
4970
biosampleAccessionsMap.sourceAccessionsMap,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/** Elixir BioHackathon 2022 */
2+
package com.elixir.biohackaton.ISAToSRA.biosamples.service;
3+
4+
import org.springframework.beans.factory.annotation.Autowired;
5+
import org.springframework.context.annotation.Configuration;
6+
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
7+
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
8+
9+
@Configuration
10+
public class MarsReceiptServiceInterceptorConfig implements WebMvcConfigurer {
11+
12+
@Autowired private MarsReceiptService marsReceiptService;
13+
14+
@Override
15+
public void addInterceptors(InterceptorRegistry registry) {
16+
registry.addInterceptor(marsReceiptService);
17+
}
18+
}

0 commit comments

Comments
 (0)