Skip to content

Commit f6c1db4

Browse files
committed
Better transactional handling
1 parent 3a34acd commit f6c1db4

5 files changed

Lines changed: 37 additions & 11 deletions

File tree

sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/survey/AutomaticSurveyResponseProcessor.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import javax.inject.Inject;
1515
import javax.persistence.EntityManager;
1616
import javax.persistence.PersistenceContext;
17+
import javax.transaction.Transactional;
1718

1819
import org.apache.commons.collections4.CollectionUtils;
1920
import org.jetbrains.annotations.NotNull;
@@ -69,6 +70,9 @@ public AutomaticSurveyResponseProcessor(
6970
this.surveyTokenFacade = surveyTokenFacade;
7071
}
7172

73+
@Transactional(value = Transactional.TxType.REQUIRES_NEW,
74+
rollbackOn = {
75+
Exception.class })
7276
public List<SurveyResponseProcessingResult> processSurveyResponses(List<ExternalMessageDto> externalMessages)
7377
throws InterruptedException, ExecutionException {
7478

@@ -155,8 +159,6 @@ public List<SurveyResponseProcessingResult> processSurveyResponses(List<External
155159
externalMessage.getUuid(),
156160
e);
157161

158-
em.getTransaction().rollback();
159-
160162
// in case of failure status must be changed to unprocessed
161163
externalMessage.setStatus(ExternalMessageStatus.UNPROCESSED);
162164

sormas-backend/src/main/java/de/symeda/sormas/backend/patch/BusinessDtoFacade.java

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
package de.symeda.sormas.backend.patch;
22

3-
import java.util.*;
3+
import java.util.ArrayList;
4+
import java.util.Collections;
5+
import java.util.Comparator;
6+
import java.util.HashMap;
7+
import java.util.LinkedHashMap;
8+
import java.util.List;
9+
import java.util.Map;
10+
import java.util.Objects;
11+
import java.util.Optional;
12+
import java.util.Set;
413
import java.util.function.Function;
514
import java.util.stream.Collectors;
615

@@ -56,7 +65,7 @@ public class BusinessDtoFacade {
5665
/**
5766
* Some {@link EntityDto} must be attached to a "parent" to be saved.
5867
*/
59-
private final Map<Class<? extends EntityDto>, LeafAttacher> leafAttacherRegistry = new LinkedHashMap<>();
68+
private final Map<Class<? extends EntityDto>, LeafAttacher> leafAttacherDictionary = new LinkedHashMap<>();
6069

6170
@PostConstruct
6271
private void init() {
@@ -190,7 +199,7 @@ private void registerLeafAttacherOperations() {
190199
}
191200

192201
private <T extends EntityDto> void registerLeafAttacher(Class<T> leafClass, LeafAttacher attacher) {
193-
leafAttacherRegistry.put(leafClass, attacher);
202+
leafAttacherDictionary.put(leafClass, attacher);
194203
}
195204

196205
private CaseDataDto requireCaseData(List<Tuple<Integer, EntityDto>> dtosInProgress) {
@@ -303,7 +312,15 @@ private <T extends EntityDto> T saveDirectEntity(@NotNull EntityDto entityDto) {
303312
public void save(@NotNull List<Tuple<Integer, EntityDto>> entityDtosByKey) {
304313
List<Tuple<Integer, EntityDto>> dtosInProgress = new ArrayList<>(entityDtosByKey);
305314

306-
leafAttacherRegistry.forEach((leafClass, attacher) -> {
315+
List<Tuple<Integer, EntityDto>> orderedRootEntities = entityDtosByKey.stream()
316+
.filter(tuple -> leafAttacherDictionary.keySet().stream().noneMatch(leafClass -> leafClass.isInstance(tuple.getSecond())))
317+
.sorted(Comparator.comparing(Tuple::getSecond, new EntityDtoTypeComparator()))
318+
.collect(Collectors.toList());
319+
320+
orderedRootEntities.stream().map(Tuple::getSecond).forEach(this::saveDirectEntity);
321+
322+
// once it's done, leaf entities can be saved.
323+
leafAttacherDictionary.forEach((leafClass, attacher) -> {
307324
List<Tuple<Integer, EntityDto>> leaves =
308325
dtosInProgress.stream().filter(t -> leafClass.isInstance(t.getSecond())).collect(Collectors.toList());
309326

@@ -312,8 +329,6 @@ public void save(@NotNull List<Tuple<Integer, EntityDto>> entityDtosByKey) {
312329
attacher.attachLeaf(leafTuple.getSecond(), leafTuple.getFirst(), dtosInProgress);
313330
});
314331
});
315-
316-
dtosInProgress.stream().map(Tuple::getSecond).forEach(this::saveDirectEntity);
317332
}
318333

319334
@FunctionalInterface

sormas-backend/src/main/java/de/symeda/sormas/backend/patch/DataPatcherImpl.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import javax.ejb.EJB;
1717
import javax.enterprise.context.ApplicationScoped;
1818
import javax.inject.Inject;
19+
import javax.transaction.Transactional;
1920

2021
import org.apache.commons.lang3.StringUtils;
2122
import org.jetbrains.annotations.NotNull;
@@ -110,6 +111,7 @@ public DataPatcherImpl(
110111
this.configFacade = configFacade;
111112
}
112113

114+
@Transactional(rollbackOn = Exception.class)
113115
@Override
114116
public DataPatchResponse patch(CaseDataPatchRequest request) {
115117
logger.debug("patch: [{}]", request);
@@ -243,7 +245,7 @@ private PlainSinglePatchResult produceSinglePatchResult(
243245
private void saveDTOsIfAppropriate(Map<Tuple<String, Integer>, AttachedEntityWrapper> entityCache) {
244246
List<Tuple<Integer, EntityDto>> toSave = entityCache.entrySet()
245247
.stream()
246-
.map(entry -> Tuple.<Integer, EntityDto> of(entry.getKey().getSecond(), entry.getValue().getEntityDto()))
248+
.map(entry -> Tuple.of(entry.getKey().getSecond(), entry.getValue().getEntityDto()))
247249
.collect(Collectors.toList());
248250

249251
if (toSave.isEmpty()) {

sormas-ui/src/main/java/de/symeda/sormas/ui/externalmessage/ExternalMessageController.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ public void showExternalMessage(String messageUuid, boolean withActions, Runnabl
160160
form.setValue(newDto);
161161
}
162162

163-
public void processSurveyResponse(String surveyResponseMessageUuid) {
163+
public void processSurveyResponse(String surveyResponseMessageUuid, Runnable successRunnable) {
164164
ExternalMessageDto externalMessage = FacadeProvider.getExternalMessageFacade().getByUuid(surveyResponseMessageUuid);
165165

166166
de.symeda.sormas.api.externalmessage.survey.ExternalMessageSurveyResponseResult result =
@@ -181,6 +181,11 @@ public void processSurveyResponse(String surveyResponseMessageUuid) {
181181
}
182182
}
183183

184+
if (result == null) {
185+
Notification.show(I18nProperties.getString(Strings.messageSurveyResponseNotYetProcessed), Notification.Type.HUMANIZED_MESSAGE);
186+
return;
187+
}
188+
184189
if (result.getPatchResponse() != null && result.getPatchResponse().hasFailures()) {
185190
de.symeda.sormas.api.patch.partial_retrieval.DisplayablePartialRetrievalResponse displayData;
186191
try {
@@ -197,6 +202,8 @@ public void processSurveyResponse(String surveyResponseMessageUuid) {
197202
UI.getCurrent().addWindow(editor);
198203
} else {
199204
Notification.show(I18nProperties.getString(Strings.messageSurveyResponseAllFieldsApplied), Notification.Type.HUMANIZED_MESSAGE);
205+
206+
successRunnable.run();
200207
}
201208
}
202209

sormas-ui/src/main/java/de/symeda/sormas/ui/externalmessage/ExternalMessageGrid.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ private Component buildProcessComponent(ExternalMessageIndexDto indexDto) {
226226
} else if (ExternalMessageType.PHYSICIANS_REPORT == indexDto.getType()) {
227227
ControllerProvider.getExternalMessageController().processDoctorDeclarationMessage(indexDto.getUuid());
228228
} else if (ExternalMessageType.SURVEY_RESPONSE == indexDto.getType()) {
229-
ControllerProvider.getExternalMessageController().processSurveyResponse(indexDto.getUuid());
229+
ControllerProvider.getExternalMessageController().processSurveyResponse(indexDto.getUuid(), this::reload);
230230
}
231231
}, ValoTheme.BUTTON_PRIMARY);
232232
} else {

0 commit comments

Comments
 (0)