Skip to content
This repository was archived by the owner on May 5, 2021. It is now read-only.

Commit b025187

Browse files
Merge pull request SORMAS-Foundation#3598 from hzi-braunschweig/potential_performance_improvements
Potential performance improvements
2 parents a87faca + 1a50253 commit b025187

10 files changed

Lines changed: 127 additions & 92 deletions

File tree

sormas-backend/src/main/java/de/symeda/auditlog/api/EntityId.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
* @author Oliver Milke
2727
* @since 13.01.2016
2828
*/
29-
public class EntityId {
29+
public final class EntityId {
3030

3131
private final Class<?> entityClass;
3232
private final String entityUuid;

sormas-backend/src/main/java/de/symeda/auditlog/api/UserId.java

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,11 @@
2525
* @author Oliver Milke
2626
* @since 12.11.2015
2727
*/
28-
public class UserId implements Serializable {
28+
public final class UserId implements Serializable {
2929

3030
private static final long serialVersionUID = 1L;
3131

32-
private String name;
33-
34-
public UserId() {
35-
}
32+
private final String name;
3633

3734
public UserId(String name) {
3835
this.name = name;
@@ -41,8 +38,4 @@ public UserId(String name) {
4138
public String getName() {
4239
return name;
4340
}
44-
45-
public void setName(String name) {
46-
this.name = name;
47-
}
4841
}

sormas-backend/src/main/java/de/symeda/sormas/backend/disease/DiseaseConfigurationFacadeEjb.java

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
import java.sql.Timestamp;
44
import java.util.ArrayList;
5+
import java.util.Comparator;
56
import java.util.Date;
6-
import java.util.HashMap;
7-
import java.util.HashSet;
7+
import java.util.EnumMap;
8+
import java.util.EnumSet;
89
import java.util.List;
910
import java.util.Map;
1011
import java.util.Set;
@@ -44,9 +45,9 @@ public class DiseaseConfigurationFacadeEjb implements DiseaseConfigurationFacade
4445
private List<Disease> caseBasedDiseases = new ArrayList<>();
4546
private List<Disease> aggregateDiseases = new ArrayList<>();
4647
private List<Disease> followUpEnabledDiseases = new ArrayList<>();
47-
private Map<Disease, Integer> followUpDurations = new HashMap<>();
48-
private Map<Disease, Integer> caseFollowUpDurations = new HashMap<>();
49-
private Map<Disease, Integer> eventParticipantFollowUpDurations = new HashMap<>();
48+
private Map<Disease, Integer> followUpDurations = new EnumMap<>(Disease.class);
49+
private Map<Disease, Integer> caseFollowUpDurations = new EnumMap<>(Disease.class);
50+
private Map<Disease, Integer> eventParticipantFollowUpDurations = new EnumMap<>(Disease.class);
5051

5152
@Override
5253
public List<DiseaseConfigurationDto> getAllAfter(Date date) {
@@ -73,44 +74,50 @@ public List<Disease> getAllDiseases(Boolean active, Boolean primary, Boolean cas
7374

7475
User currentUser = userService.getCurrentUser();
7576

76-
Set<Disease> diseases = new HashSet<>();
77+
Set<Disease> diseases = EnumSet.noneOf(Disease.class);
7778

7879
if (currentUser.getLimitedDisease() == null) {
79-
if (Boolean.TRUE.equals(active)) {
80+
if (isTrue(active)) {
8081
diseases.addAll(activeDiseases);
81-
} else if (Boolean.FALSE.equals(active)) {
82+
} else if (isFalse(active)) {
8283
diseases.addAll(inactiveDiseases);
8384
}
8485

85-
if (Boolean.TRUE.equals(primary)) {
86+
if (isTrue(primary)) {
8687
diseases.retainAll(primaryDiseases);
87-
} else if (Boolean.FALSE.equals(primary)) {
88+
} else if (isFalse(primary)) {
8889
diseases.retainAll(nonPrimaryDiseases);
8990
}
9091

91-
if (Boolean.TRUE.equals(caseBased)) {
92+
if (isTrue(caseBased)) {
9293
diseases.retainAll(caseBasedDiseases);
93-
} else if (Boolean.FALSE.equals(caseBased)) {
94+
} else if (isFalse(caseBased)) {
9495
diseases.retainAll(aggregateDiseases);
9596
}
9697
} else if (active != null || primary != null || caseBased != null) {
9798
Disease limitedDisease = currentUser.getLimitedDisease();
9899
if ((active == null
99-
|| (Boolean.TRUE.equals(active) && activeDiseases.contains(limitedDisease))
100-
|| (Boolean.FALSE.equals(active) && inactiveDiseases.contains(limitedDisease)))
100+
|| (isTrue(active) && activeDiseases.contains(limitedDisease))
101+
|| (isFalse(active) && inactiveDiseases.contains(limitedDisease)))
101102
&& (primary == null
102-
|| (Boolean.TRUE.equals(primary) && primaryDiseases.contains(limitedDisease))
103-
|| (Boolean.FALSE.equals(primary) && nonPrimaryDiseases.contains(limitedDisease)))
103+
|| (isTrue(primary) && primaryDiseases.contains(limitedDisease))
104+
|| (isFalse(primary) && nonPrimaryDiseases.contains(limitedDisease)))
104105
&& (caseBased == null
105-
|| (Boolean.TRUE.equals(caseBased) && caseBasedDiseases.contains(limitedDisease))
106-
|| (Boolean.FALSE.equals(caseBased) && aggregateDiseases.contains(limitedDisease)))) {
106+
|| (isTrue(caseBased) && caseBasedDiseases.contains(limitedDisease))
107+
|| (isFalse(caseBased) && aggregateDiseases.contains(limitedDisease)))) {
107108
diseases.add(limitedDisease);
108109
}
109110
}
110111

111-
List<Disease> diseaseList = new ArrayList<>(diseases);
112-
diseaseList.sort((d1, d2) -> d1.toString().compareTo(d2.toString()));
113-
return diseaseList;
112+
return diseases.stream().sorted(Comparator.comparing(Disease::toString)).collect(Collectors.toList());
113+
}
114+
115+
private static boolean isFalse(Boolean value) {
116+
return Boolean.FALSE.equals(value);
117+
}
118+
119+
private static boolean isTrue(Boolean value) {
120+
return Boolean.TRUE.equals(value);
114121
}
115122

116123
@Override
@@ -257,20 +264,20 @@ public void loadData() {
257264
caseFollowUpDurations.clear();
258265
eventParticipantFollowUpDurations.clear();
259266

260-
for (Disease disease : Disease.values()) {
261-
DiseaseConfigurationDto configuration = getDiseaseConfiguration(disease);
267+
for (DiseaseConfiguration configuration : service.getAll()) {
268+
Disease disease = configuration.getDisease();
262269

263-
if (Boolean.TRUE.equals(configuration.getActive()) || (configuration.getActive() == null && disease.isDefaultActive())) {
270+
if (enabled(configuration.getActive(), disease.isDefaultActive())) {
264271
activeDiseases.add(disease);
265272
} else {
266273
inactiveDiseases.add(disease);
267274
}
268-
if (Boolean.TRUE.equals(configuration.getPrimaryDisease()) || (configuration.getPrimaryDisease() == null && disease.isDefaultPrimary())) {
275+
if (enabled(configuration.getPrimaryDisease(), disease.isDefaultPrimary())) {
269276
primaryDiseases.add(disease);
270277
} else {
271278
nonPrimaryDiseases.add(disease);
272279
}
273-
if (Boolean.TRUE.equals(configuration.getCaseBased()) || (configuration.getCaseBased() == null && disease.isDefaultCaseBased())) {
280+
if (enabled(configuration.getCaseBased(), disease.isDefaultCaseBased())) {
274281
caseBasedDiseases.add(disease);
275282
} else {
276283
aggregateDiseases.add(disease);
@@ -297,6 +304,10 @@ public void loadData() {
297304
}
298305
}
299306

307+
private boolean enabled(Boolean configValue, boolean defaultValue) {
308+
return isTrue(configValue) || (configValue == null && defaultValue);
309+
}
310+
300311
@LocalBean
301312
@Stateless
302313
public static class DiseaseConfigurationFacadeEjbLocal extends DiseaseConfigurationFacadeEjb {

sormas-backend/src/main/java/de/symeda/sormas/backend/disease/DiseaseConfigurationService.java

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
import javax.ejb.LocalBean;
44
import javax.ejb.Stateless;
5-
import javax.persistence.NoResultException;
65
import javax.persistence.criteria.CriteriaBuilder;
76
import javax.persistence.criteria.CriteriaQuery;
87
import javax.persistence.criteria.From;
8+
import javax.persistence.criteria.ParameterExpression;
99
import javax.persistence.criteria.Predicate;
1010
import javax.persistence.criteria.Root;
1111

@@ -26,19 +26,11 @@ public DiseaseConfiguration getDiseaseConfiguration(Disease disease) {
2626
CriteriaQuery<DiseaseConfiguration> cq = cb.createQuery(DiseaseConfiguration.class);
2727
Root<DiseaseConfiguration> root = cq.from(DiseaseConfiguration.class);
2828

29-
Predicate filter = cb.equal(root.get(DiseaseConfiguration.DISEASE), disease);
30-
if (filter == null) {
31-
return null;
32-
} else {
33-
cq.where(filter);
34-
}
29+
ParameterExpression<Disease> diseaseParam = cb.parameter(Disease.class);
30+
cq.where(cb.equal(root.get(DiseaseConfiguration.DISEASE), diseaseParam));
3531

3632
cq.select(root);
37-
try {
38-
return em.createQuery(cq).getSingleResult();
39-
} catch (NoResultException e) {
40-
return null;
41-
}
33+
return em.createQuery(cq).setParameter(diseaseParam, disease).getResultList().stream().findFirst().orElse(null);
4234
}
4335

4436
@SuppressWarnings("rawtypes")

sormas-backend/src/main/java/de/symeda/sormas/backend/user/CurrentUser.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
package de.symeda.sormas.backend.user;
22

3+
import java.io.Serializable;
4+
35
import javax.enterprise.context.RequestScoped;
6+
import javax.transaction.TransactionScoped;
47

58
@RequestScoped
6-
public class CurrentUser {
9+
// FIXME @TransactionScoped would be better for performance, but is not support by novatec.bean-test (see their github #4)
10+
public class CurrentUser implements Serializable {
11+
12+
private static final long serialVersionUID = 1L;
713

814
private User user;
915

sormas-backend/src/main/java/de/symeda/sormas/backend/user/CurrentUserService.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import javax.persistence.criteria.CriteriaQuery;
1414
import javax.persistence.criteria.ParameterExpression;
1515
import javax.persistence.criteria.Root;
16+
import javax.transaction.TransactionScoped;
1617
import javax.transaction.Transactional;
1718

1819
import de.symeda.sormas.backend.util.ModelConstants;
@@ -37,8 +38,9 @@ public class CurrentUserService {
3738
*/
3839
@Produces
3940
@CurrentUserQualifier
40-
@RequestScoped
4141
@Transactional
42+
@RequestScoped
43+
// FIXME @TransactionScoped would be better for performance, but is not support by novatec.bean-test (see their github #4)
4244
public CurrentUser getCurrentUser() {
4345

4446
final String userName = context.getCallerPrincipal().getName();

sormas-backend/src/main/java/de/symeda/sormas/backend/user/UserRoleConfigFacadeEjb.java

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,14 @@
1818
package de.symeda.sormas.backend.user;
1919

2020
import java.sql.Timestamp;
21+
import java.util.Arrays;
2122
import java.util.Collections;
2223
import java.util.Date;
24+
import java.util.EnumMap;
2325
import java.util.EnumSet;
2426
import java.util.HashSet;
2527
import java.util.List;
28+
import java.util.Map;
2629
import java.util.Set;
2730
import java.util.stream.Collectors;
2831

@@ -44,6 +47,9 @@ public class UserRoleConfigFacadeEjb implements UserRoleConfigFacade {
4447
@EJB
4548
private UserService userService;
4649

50+
//Assumption: UserRoleConfigs are not changed during runtime
51+
private Map<UserRole, Set<UserRight>> userRoleRightsCache;
52+
4753
@Override
4854
public List<UserRoleConfigDto> getAllAfter(Date since) {
4955
return userRoleConfigService.getAllAfter(since, null).stream().map(c -> toDto(c)).collect(Collectors.toList());
@@ -79,6 +85,7 @@ public UserRoleConfigDto saveUserRoleConfig(UserRoleConfigDto dto) {
7985

8086
UserRoleConfig entity = fromDto(dto);
8187
userRoleConfigService.ensurePersisted(entity);
88+
resetUserRoleRightsCache();
8289
return toDto(entity);
8390
}
8491

@@ -87,25 +94,51 @@ public void deleteUserRoleConfig(UserRoleConfigDto dto) {
8794

8895
UserRoleConfig entity = userRoleConfigService.getByUuid(dto.getUuid());
8996
userRoleConfigService.delete(entity);
97+
resetUserRoleRightsCache();
9098
}
9199

92100
@Override
93101
public Set<UserRight> getEffectiveUserRights(UserRole... userRoles) {
94102

95-
Set<UserRight> userRights = EnumSet.noneOf(UserRight.class);
103+
Map<UserRole, Set<UserRight>> userRoleRights = getUserRoleRightsCached();
96104

105+
Set<UserRight> userRights = EnumSet.noneOf(UserRight.class);
97106
for (UserRole userRole : userRoles) {
98-
UserRoleConfig userRoleConfig = userRoleConfigService.getByUserRole(userRole);
99-
if (userRoleConfig != null) {
100-
userRights.addAll(userRoleConfig.getUserRights());
101-
} else {
102-
userRights.addAll(userRole.getDefaultUserRights());
103-
}
107+
userRights.addAll(userRoleRights.get(userRole));
104108
}
105109

106110
return userRights;
107111
}
108112

113+
public void resetUserRoleRightsCache() {
114+
userRoleRightsCache = null;
115+
}
116+
117+
private Map<UserRole, Set<UserRight>> getUserRoleRightsCached() {
118+
119+
if (userRoleRightsCache == null) {
120+
Map<UserRole, Set<UserRight>> cache = new EnumMap<>(UserRole.class);
121+
122+
userRoleConfigService.getAll().forEach(c -> cache.put(c.getUserRole(), c.getUserRights()));
123+
124+
//default values
125+
Arrays.stream(UserRole.values()).forEach(r -> cache.computeIfAbsent(r, UserRole::getDefaultUserRights));
126+
127+
//enum sets
128+
cache.replaceAll((k, v) -> {
129+
if (v.isEmpty()) {
130+
return EnumSet.noneOf(UserRight.class);
131+
} else {
132+
return EnumSet.copyOf(v);
133+
}
134+
});
135+
136+
userRoleRightsCache = cache;
137+
}
138+
139+
return userRoleRightsCache;
140+
}
141+
109142
public UserRoleConfig fromDto(UserRoleConfigDto source) {
110143

111144
if (source == null) {

sormas-backend/src/main/resources/META-INF/persistence.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@
9494
<!-- don't validate on release, otherwise the automatic db update won't work
9595
<property name="hibernate.hbm2ddl.auto" value="validate"/>
9696
-->
97+
<property name="hibernate.jdbc.batch_size" value="100" />
98+
<property name="hibernate.order_inserts" value="true" />
99+
<property name="hibernate.order_updates" value="true" />
97100
</properties>
98101

99102
</persistence-unit>

0 commit comments

Comments
 (0)