Skip to content

Commit 97eccd2

Browse files
Improve software quality by addressing some reliability issues (#931)
Improves the reliability and maintenance of the software by addressing various issues. --------- Co-authored-by: Steffengreiner <[email protected]>
1 parent 5e283d2 commit 97eccd2

File tree

35 files changed

+161
-192
lines changed

35 files changed

+161
-192
lines changed

.github/workflows/sonarcloud.yml

+4-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ on:
55
push:
66
branches:
77
- development
8-
8+
pull_request:
9+
branches:
10+
- development
11+
- main
912
jobs:
1013
sonarcloud:
1114
runs-on: ubuntu-latest

domain-concept/src/main/java/life/qbic/domain/concepts/DomainEventPublisher.java

-84
This file was deleted.

email-service-provider/src/main/java/life/qbic/infrastructure/email/project/ProjectManagementEmailServiceProvider.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
public class ProjectManagementEmailServiceProvider implements EmailService {
2525

2626
private static final Logger log = logger(ProjectManagementEmailServiceProvider.class);
27+
public static final String EMAIL_SUBMISSION_FAILED = "Email submission failed";
2728

2829
private final EmailServiceProvider emailServiceProvider;
2930

@@ -39,7 +40,7 @@ public void send(Subject subject, Recipient recipient, Content content)
3940
MessageTranslator.translate(content));
4041
} catch (EmailSubmissionException e) {
4142
log.error("Email submission failed!", e);
42-
throw new CommunicationException("Email submission failed");
43+
throw new CommunicationException(EMAIL_SUBMISSION_FAILED);
4344
}
4445
}
4546

@@ -50,8 +51,8 @@ public void send(Subject subject, Recipient recipient, Content content, Attachme
5051
emailServiceProvider.send(MessageTranslator.translate(subject), MessageTranslator.translate(recipient),
5152
MessageTranslator.translate(content), MessageTranslator.translate(attachment));
5253
} catch (EmailSubmissionException e) {
53-
log.error("Email submission failed", e);
54-
throw new CommunicationException("Email submission failed");
54+
log.error(EMAIL_SUBMISSION_FAILED, e);
55+
throw new CommunicationException(EMAIL_SUBMISSION_FAILED);
5556
}
5657
}
5758

project-management-infrastructure/src/main/java/life/qbic/projectmanagement/infrastructure/CachedOrganisationRepository.java

-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import life.qbic.logging.api.Logger;
2121
import life.qbic.projectmanagement.application.OrganisationRepository;
2222
import life.qbic.projectmanagement.domain.Organisation;
23-
import org.springframework.stereotype.Component;
2423

2524
/**
2625
* <b>Cached Organisation Repository</b>
@@ -35,7 +34,6 @@
3534
*
3635
* @since 1.0.0s
3736
*/
38-
@Component
3937
public class CachedOrganisationRepository implements OrganisationRepository {
4038

4139
private static final Logger log = logger(CachedOrganisationRepository.class);
@@ -53,7 +51,6 @@ public CachedOrganisationRepository(int cacheSize) {
5351
this.configuredCacheSize = cacheSize;
5452
}
5553

56-
5754
public CachedOrganisationRepository() {
5855
this.configuredCacheSize = DEFAULT_CACHE_SIZE;
5956
}

project-management/src/main/java/life/qbic/projectmanagement/application/authorization/QbicOidcUser.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
*/
1818
public class QbicOidcUser extends DefaultOidcUser {
1919

20-
private final QbicUserInfo qbicUserInfo;
20+
private final transient QbicUserInfo qbicUserInfo;
2121
private final String originalAuthName;
2222

2323
public record QbicUserInfo(String userId, String fullName, String email, boolean active) {

project-management/src/main/java/life/qbic/projectmanagement/application/authorization/QbicUserDetails.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
public class QbicUserDetails implements UserDetails {
2222
@Serial
2323
private static final long serialVersionUID = 5812210012669790933L;
24-
private final User user;
24+
private final transient User user;
2525
private final List<GrantedAuthority> grantedAuthorities;
2626

2727
/**

project-management/src/main/java/life/qbic/projectmanagement/application/authorization/acl/ProjectAccessServiceImpl.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
public class ProjectAccessServiceImpl implements ProjectAccessService {
4444

4545
private static final Logger log = logger(ProjectAccessServiceImpl.class);
46+
public static final String SELECT_IDENTITY = "SELECT @@IDENTITY";
4647
private final MutableAclService aclService;
4748
private final JdbcTemplate jdbcTemplate;
4849

@@ -59,8 +60,8 @@ private static MutableAcl getAclForProject(ProjectId projectId, List<Sid> sids,
5960
JdbcMutableAclService serviceImpl = (JdbcMutableAclService) mutableAclService;
6061
// these settings are necessary for MySQL to correctly throw several types of exceptions
6162
// instead of an unrelated exception related to the identity function
62-
serviceImpl.setClassIdentityQuery("SELECT @@IDENTITY");
63-
serviceImpl.setSidIdentityQuery("SELECT @@IDENTITY");
63+
serviceImpl.setClassIdentityQuery(SELECT_IDENTITY);
64+
serviceImpl.setSidIdentityQuery(SELECT_IDENTITY);
6465
try {
6566
acl = (MutableAcl) serviceImpl.readAclById(objectIdentity, sids);
6667
} catch (NotFoundException e) {
@@ -75,8 +76,8 @@ private static MutableAcl createAclForProject(ProjectId projectId,
7576
JdbcMutableAclService serviceImpl = (JdbcMutableAclService) mutableAclService;
7677
// these settings are necessary for MySQL to correctly throw several types of exceptions
7778
// instead of an unrelated exception related to the identity function
78-
serviceImpl.setClassIdentityQuery("SELECT @@IDENTITY");
79-
serviceImpl.setSidIdentityQuery("SELECT @@IDENTITY");
79+
serviceImpl.setClassIdentityQuery(SELECT_IDENTITY);
80+
serviceImpl.setSidIdentityQuery(SELECT_IDENTITY);
8081
return serviceImpl.createAcl(objectIdentity);
8182
}
8283

project-management/src/main/java/life/qbic/projectmanagement/application/measurement/MeasurementService.java

+6-6
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ public CompletableFuture<List<Result<MeasurementId, ErrorCode>>> registerAll(
219219
@PreAuthorize(
220220
"hasPermission(#projectId, 'life.qbic.projectmanagement.domain.model.project.Project', 'WRITE')")
221221
@Transactional
222-
protected List<MeasurementId> performRegistration(
222+
public List<MeasurementId> performRegistration(
223223
List<? extends MeasurementMetadata> measurementMetadataList, ProjectId projectId) {
224224
if (measurementMetadataList.isEmpty()) {
225225
return new ArrayList<>(); // Nothing to do
@@ -243,7 +243,6 @@ private List<MeasurementId> performRegistrationNGS(
243243
ngsMeasurementMetadata.add(ngsMetadata);
244244
}
245245
}
246-
Map<NGSMeasurement, Collection<SampleIdCodeEntry>> ngsMeasurementsMapping = new HashMap<>();
247246

248247
// Start with the pooled measurements first and group the metadata entries by pool
249248
Map<String, List<NGSMeasurementMetadata>> measurementsByPool = ngsMeasurementMetadata.stream()
@@ -255,7 +254,8 @@ private List<MeasurementId> performRegistrationNGS(
255254
.filter(metadata -> metadata.assignedSamplePoolGroup().isEmpty()).toList();
256255

257256
// Then merge and prepare the domain objects by pool
258-
ngsMeasurementsMapping.putAll(mergeByPoolNGS(measurementsByPool, projectId));
257+
Map<NGSMeasurement, Collection<SampleIdCodeEntry>> ngsMeasurementsMapping = new HashMap<>(
258+
mergeByPoolNGS(measurementsByPool, projectId));
259259
// and last but not least also the single sample measurements
260260
singleMeasurements.stream()
261261
.map(singleMeasurement -> buildNGS(List.of(singleMeasurement), projectId))
@@ -273,7 +273,6 @@ private List<MeasurementId> performRegistrationPxP(
273273
proteomicsMeasurements.add(proteomicsMetadata);
274274
}
275275
}
276-
Map<ProteomicsMeasurement, Collection<SampleIdCodeEntry>> proteomicsMeasurementsMapping = new HashMap<>();
277276

278277
// Start with the pooled measurements first and group the metadata entries by pool
279278
Map<String, List<ProteomicsMeasurementMetadata>> measurementsByPool = proteomicsMeasurements.stream()
@@ -285,7 +284,8 @@ private List<MeasurementId> performRegistrationPxP(
285284
.filter(metadata -> metadata.assignedSamplePoolGroup().isEmpty()).toList();
286285

287286
// Then merge and prepare the domain objects by pool
288-
proteomicsMeasurementsMapping.putAll(mergeByPoolPxP(measurementsByPool, projectId));
287+
Map<ProteomicsMeasurement, Collection<SampleIdCodeEntry>> proteomicsMeasurementsMapping = new HashMap<>(
288+
mergeByPoolPxP(measurementsByPool, projectId));
289289
// and last but not least also the single sample measurements
290290
singleMeasurements.stream()
291291
.map(singleMeasurement -> buildPxP(List.of(singleMeasurement), projectId))
@@ -346,7 +346,7 @@ private Map<NGSMeasurement, Collection<SampleIdCodeEntry>> buildNGS(
346346
NGSMeasurement measurement;
347347
if (firstMetadataEntry.assignedSamplePoolGroup().isPresent()) {
348348
measurement = NGSMeasurement.createWithPool(projectId,
349-
firstMetadataEntry.assignedSamplePoolGroup().get(), assignedMeasurementCode,
349+
firstMetadataEntry.assignedSamplePoolGroup().orElseThrow(), assignedMeasurementCode,
350350
organisationQuery.get(), method, specificMetadata);
351351
} else {
352352
measurement = NGSMeasurement.createSingleMeasurement(projectId, assignedMeasurementCode,

project-management/src/main/java/life/qbic/projectmanagement/application/sample/PropertyConversion.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
*/
2121
public class PropertyConversion {
2222

23+
private PropertyConversion(){}
24+
2325
private static final String CONDITION_VARIABLE_LEVEL_UNIT_TEMPLATE = "%s: %s %s"; // <variable name>: <value> [unit]
2426

2527
private static final String CONDITION_VARIABLE_LEVEL_NO_UNIT_TEMPLATE = "%s: %s"; // <variable name>: <value>
@@ -72,7 +74,7 @@ public static String toString(VariableLevel variableLevel) {
7274
if (variableLevel.experimentalValue().unit().isPresent()) {
7375
return CONDITION_VARIABLE_LEVEL_UNIT_TEMPLATE.formatted(variableLevel.variableName().value(),
7476
variableLevel.experimentalValue().value(),
75-
variableLevel.experimentalValue().unit().get());
77+
variableLevel.experimentalValue().unit().orElseThrow());
7678
} else {
7779
return CONDITION_VARIABLE_LEVEL_NO_UNIT_TEMPLATE.formatted(
7880
variableLevel.variableName().value(), variableLevel.experimentalValue().value());

project-management/src/main/java/life/qbic/projectmanagement/domain/model/measurement/ProteomicsSpecificMeasurementMetadata.java

+4
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,8 @@ public String fractionName() {
8080
return fractionName;
8181
}
8282

83+
public String comment() {
84+
return comment;
85+
}
86+
8387
}

project-management/src/main/java/life/qbic/projectmanagement/domain/model/project/ProjectCode.java

+9-6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import jakarta.persistence.Column;
44
import jakarta.persistence.Embeddable;
5+
import java.security.SecureRandom;
56
import java.util.Arrays;
67
import java.util.Objects;
78
import java.util.Random;
@@ -18,7 +19,7 @@
1819
@Embeddable
1920
public class ProjectCode {
2021

21-
public static final String[] BLACKLIST = new String[]{"FUCK", "SHIT"};
22+
private static final String[] BLACKLIST = new String[]{"FUCK", "SHIT"};
2223

2324
@Column(name = "projectCode")
2425
private String value;
@@ -27,9 +28,11 @@ public class ProjectCode {
2728

2829
private static final String PREFIX = "Q2";
2930

30-
public static final char[] ALLOWED_LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWX".toCharArray();
31+
private static final char[] ALLOWED_LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWX".toCharArray();
3132

32-
public static final char[] ALLOWED_NUMBERS = "0123456789".toCharArray();
33+
private static final char[] ALLOWED_NUMBERS = "0123456789".toCharArray();
34+
35+
private static final Random RANDOM = new SecureRandom();
3336

3437
protected ProjectCode() {
3538
// Needed for JPA
@@ -213,11 +216,11 @@ private char generateRandomChar(Coin coin) {
213216
}
214217

215218
private char randomLetter() {
216-
return letters[new Random().nextInt(letters.length)];
219+
return letters[RANDOM.nextInt(letters.length)];
217220
}
218221

219222
private char randomNumber() {
220-
return numbers[new Random().nextInt(numbers.length)];
223+
return numbers[RANDOM.nextInt(numbers.length)];
221224
}
222225

223226
}
@@ -229,7 +232,7 @@ enum SIDE {
229232
}
230233

231234
SIDE flip() {
232-
double randomValue = new Random().nextDouble(1);
235+
double randomValue = RANDOM.nextDouble(1);
233236
if (randomValue < 0.5) {
234237
return SIDE.HEAD;
235238
} else {

sonar-project.properties

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
sonar.projectKey=qbicsoftware_data-manager-app
2+
sonar.organization=qbicsoftware
3+
sonar.exclusions=src/test/**,build/**,node_modules/**, **/DataPrivacyAgreement.html, **/LegalNotice.html

subscription-provider/src/main/java/life/qbic/logging/subscription/provider/mail/property/PropertyFileParser.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
*/
3434
public class PropertyFileParser {
3535

36+
private PropertyFileParser() {}
37+
3638
/**
3739
* Parses a file for defined properties and resolves present placeholder against visible
3840
* environment variables.
@@ -46,7 +48,10 @@ public static Properties parse(File file) throws IOException {
4648
requireNonNull(file, "File must not be null");
4749

4850
var properties = new Properties();
49-
properties.load(new FileInputStream(file));
51+
52+
try (var fileInputStream = new FileInputStream(file)) {
53+
properties.load(fileInputStream);
54+
}
5055

5156
properties = resolvePlaceholders(properties);
5257

user-interface/src/main/java/life/qbic/datamanager/AppConfig.java

+7
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import life.qbic.infrastructure.email.identity.IdentityEmailServiceProvider;
2727
import life.qbic.infrastructure.email.project.ProjectManagementEmailServiceProvider;
2828
import life.qbic.projectmanagement.application.AppContextProvider;
29+
import life.qbic.projectmanagement.application.OrganisationRepository;
2930
import life.qbic.projectmanagement.application.ProjectInformationService;
3031
import life.qbic.projectmanagement.application.api.SampleCodeService;
3132
import life.qbic.projectmanagement.application.authorization.acl.ProjectAccessService;
@@ -67,6 +68,7 @@
6768
import life.qbic.projectmanagement.application.sample.SampleInformationService;
6869
import life.qbic.projectmanagement.application.sample.qualitycontrol.QualityControlService;
6970
import life.qbic.projectmanagement.domain.repository.ProjectRepository;
71+
import life.qbic.projectmanagement.infrastructure.CachedOrganisationRepository;
7072
import org.jobrunr.scheduling.JobScheduler;
7173
import org.springframework.beans.factory.annotation.Value;
7274
import org.springframework.context.annotation.Bean;
@@ -97,6 +99,11 @@ public IdentityService userRegistrationService(
9799
return new IdentityService(userRepository);
98100
}
99101

102+
@Bean
103+
public OrganisationRepository organisationRepository() {
104+
return new CachedOrganisationRepository();
105+
}
106+
100107

101108
@Bean
102109
public NewPasswordInput newPasswordInput(IdentityService identityService) {

user-interface/src/main/java/life/qbic/datamanager/MyVaadinSessionInitListener.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public class MyVaadinSessionInitListener implements VaadinServiceInitListener {
3535
private static final Logger log = logger(MyVaadinSessionInitListener.class);
3636
private final ExtendedClientDetailsReceiver clientDetailsReceiver;
3737

38-
private final UiExceptionHandler uiExceptionHandler;
38+
private final transient UiExceptionHandler uiExceptionHandler;
3939
private final LogoutService logoutService;
4040

4141
public MyVaadinSessionInitListener(

0 commit comments

Comments
 (0)