Skip to content

Commit 9cf6052

Browse files
committed
Corrected junit tests; Updated pom dependencies to latest; Updated project version, readme and changed Dockerfile to use supervisord and java 22
1 parent 1a54666 commit 9cf6052

20 files changed

+228
-124
lines changed

Dockerfile

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Stage 1: Build the Spring Boot application
2-
FROM amazoncorretto:21-alpine AS build
2+
FROM amazoncorretto:22-alpine-jdk AS build
33

44
# Install necessary build tools
55
RUN apk add --no-cache maven
@@ -15,34 +15,37 @@ COPY src /app/src/
1515
RUN mvn clean package -DskipTests
1616

1717
# Stage 2: Create an image with RabbitMQ and your Spring Boot application
18-
FROM rabbitmq:3.13.7-management-alpine AS final
18+
FROM rabbitmq:management-alpine AS final
1919

2020
# Install necessary runtime packages
21-
RUN apk add --no-cache openjdk21-jdk \
21+
RUN apk add --no-cache openjdk22-jdk supervisor \
2222
&& rabbitmq-plugins enable --offline rabbitmq_mqtt \
23-
&& rabbitmq-plugins enable --offline rabbitmq_web_mqtt
23+
&& rabbitmq-plugins enable --offline rabbitmq_web_mqtt \
24+
&& addgroup -S runtimeUsers \
25+
&& adduser -S runtimeUser -G runtimeUsers
2426

2527
# Copy the Spring Boot application from the build stage
26-
COPY --from=build /app/target/softwaredevelopmentsimulation-1.3.0.jar /app/software-development-simulation.jar
28+
COPY --from=build /app/target/softwaredevelopmentsimulation-1.4.0.jar /app/software-development-simulation.jar
29+
30+
#Use nonroot user to run application
31+
USER runtimeUser
32+
33+
# Supervisor configuration
34+
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
2735

2836
# Add a health check for RabbitMQ
2937
HEALTHCHECK --interval=10s --timeout=3s --retries=3 \
30-
CMD nc -z localhost 5672 || exit 1
38+
CMD ["sh", "-c", "nc -z localhost 5672 || exit 1"]
3139

3240
# Expose ports for RabbitMQ and Spring Boot application
3341
EXPOSE 5672 15672 15675 21682
3442

35-
# Start RabbitMQ and wait for it to be ready before starting the Spring Boot application
36-
CMD sh -c "rabbitmq-server & \
37-
until nc -z localhost 5672; do \
38-
echo 'Waiting for RabbitMQ...'; \
39-
sleep 1; \
40-
done; \
41-
java -jar /app/software-development-simulation.jar"
43+
# Use supervisord to start and manage RabbitMQ and the Java application
44+
ENTRYPOINT ["supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
4245

4346
LABEL maintainer="Marko Dojkic <[email protected]>" \
44-
version="1.3.0" \
47+
version="1.4.0" \
4548
description="Docker image for the Software Development Simulation Spring Boot application" \
4649
org.opencontainers.image.source="https://github.com/MarkoDojkic/Software-Development-Simulation" \
4750
org.opencontainers.image.documentation="https://github.com/MarkoDojkic/Software-Development-Simulation#readme" \
48-
org.opencontainers.image.licenses="MIT"
51+
org.opencontainers.image.licenses="MIT"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ The Software Development Simulation project is a web-based application designed
1515

1616
## Features
1717

18-
- **Spring Boot Application**: Built with Spring Boot 3.3.3.
18+
- **Spring Boot Application**: Built with Spring Boot 3.3.5.
1919
- **Spring Integration**: Configured with multiple channels for task management.
2020
- **Swagger Documentation**: Integrated for API documentation and testing.
2121
- **SonarQube Integration**: Quality and security analysis with all issues resolved.

pom.xml

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<groupId>dev.markodojkic</groupId>
88
<artifactId>softwaredevelopmentsimulation</artifactId>
99
<name>Software development simulator™</name>
10-
<version>1.3.0</version>
10+
<version>1.4.0</version>
1111
<url>https://github.com/MarkoDojkic/Software-Development-Simulation</url>
1212
<licenses>
1313
<license>
@@ -37,10 +37,10 @@
3737
</issueManagement>
3838
<properties>
3939
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
40-
<spring-version>3.3.2</spring-version>
41-
<spring-integration-version>6.3.2</spring-integration-version>
40+
<spring-version>3.3.5</spring-version>
41+
<spring-integration-version>6.3.5</spring-integration-version>
4242
<jmockit-version>1.49.2</jmockit-version>
43-
<junit-jupiter-version>5.11.0</junit-jupiter-version>
43+
<junit-jupiter-version>5.11.3</junit-jupiter-version>
4444
<application.version>${project.version}</application.version>
4545
</properties>
4646

@@ -138,7 +138,7 @@
138138
<dependency>
139139
<groupId>com.google.guava</groupId>
140140
<artifactId>guava</artifactId>
141-
<version>33.3.0-jre</version>
141+
<version>33.3.1-jre</version>
142142
<scope>compile</scope>
143143
</dependency>
144144
<dependency>
@@ -183,13 +183,13 @@
183183
<dependency>
184184
<groupId>org.junit.platform</groupId>
185185
<artifactId>junit-platform-suite-api</artifactId>
186-
<version>1.11.0</version>
186+
<version>1.11.3</version>
187187
<scope>test</scope>
188188
</dependency>
189189
<dependency>
190190
<groupId>org.mockito</groupId>
191191
<artifactId>mockito-junit-jupiter</artifactId>
192-
<version>5.13.0</version>
192+
<version>5.14.2</version>
193193
<scope>test</scope>
194194
</dependency>
195195
<dependency>
@@ -248,8 +248,8 @@
248248
<artifactId>maven-compiler-plugin</artifactId>
249249
<version>3.13.0</version>
250250
<configuration>
251-
<source>21</source>
252-
<target>21</target>
251+
<source>22</source>
252+
<target>22</target>
253253
</configuration>
254254
</plugin>
255255
<plugin>
@@ -279,10 +279,10 @@
279279
<plugin>
280280
<groupId>org.apache.maven.plugins</groupId>
281281
<artifactId>maven-surefire-plugin</artifactId>
282-
<version>3.2.5</version>
282+
<version>3.5.1</version>
283283
<configuration>
284284
<argLine>
285-
${argLine} <!-- Needed for jacoco to run -->
285+
${argLine} <!-- Defines jacoco javaagent -->
286286
-Dspring.profiles.active=test
287287
-Xshare:off
288288
-XX:+EnableDynamicAgentLoading

src/main/java/dev/markodojkic/softwaredevelopmentsimulation/DeveloperImpl.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
@MessageEndpoint
1818
public class DeveloperImpl {
1919
private static final Logger logger = Logger.getLogger(DeveloperImpl.class.getName());
20+
public static final String SPRING_PROFILES_ACTIVE = "spring.profiles.active";
21+
public static final String TEST = "test";
2022

2123
@ServiceActivator(inputChannel = "trivialTechnicalTask.intermediate", outputChannel = "doneTechnicalTasks.output")
2224
public TechnicalTask trivialTaskHandler(TechnicalTask technicalTask) {
@@ -29,7 +31,7 @@ public TechnicalTask trivialTaskHandler(TechnicalTask technicalTask) {
2931
* (6 - technicalTask.getPriority().getUrgency()) / 5.0
3032
* 0.01
3133
+ 1500)
32-
, TimeUnit.MILLISECONDS);
34+
, System.getProperty(SPRING_PROFILES_ACTIVE, "").equals(TEST) ? TimeUnit.NANOSECONDS : TimeUnit.MILLISECONDS);
3335
logger.log(Level.INFO, () -> colorize(String.format("%n###Developer %s finished working on trivial technical task %s", technicalTask.getAssignee().getDisplayName(), technicalTask.getId()), Attribute.TEXT_COLOR(0), Attribute.BACK_COLOR(technicalTask.getPriority().getAnsiColorCode())));
3436
return technicalTask;
3537
}
@@ -45,7 +47,7 @@ public TechnicalTask normalTaskHandler(TechnicalTask technicalTask) {
4547
* (6 - technicalTask.getPriority().getUrgency()) / 5.0
4648
* 0.02
4749
+ 1500)
48-
, TimeUnit.MILLISECONDS);
50+
, System.getProperty(SPRING_PROFILES_ACTIVE, "").equals(TEST) ? TimeUnit.NANOSECONDS : TimeUnit.MILLISECONDS);
4951
logger.log(Level.INFO, () -> colorize(String.format("%n###Developer %s finished working on normal technical task %s", technicalTask.getAssignee().getDisplayName(), technicalTask.getId()), Attribute.TEXT_COLOR(0), Attribute.BACK_COLOR(technicalTask.getPriority().getAnsiColorCode())));
5052
return technicalTask;
5153
}
@@ -61,7 +63,7 @@ public TechnicalTask minorTaskHandler(TechnicalTask technicalTask) {
6163
* (6 - technicalTask.getPriority().getUrgency()) / 5.0
6264
* 0.03
6365
+ 1500)
64-
, TimeUnit.MILLISECONDS);
66+
, System.getProperty(SPRING_PROFILES_ACTIVE, "").equals(TEST) ? TimeUnit.NANOSECONDS : TimeUnit.MILLISECONDS);
6567
logger.log(Level.INFO, () -> colorize(String.format("%n###Developer %s finished working on minor technical task %s", technicalTask.getAssignee().getDisplayName(), technicalTask.getId()), Attribute.TEXT_COLOR(0), Attribute.BACK_COLOR(technicalTask.getPriority().getAnsiColorCode())));
6668
return technicalTask;
6769
}
@@ -77,7 +79,7 @@ public TechnicalTask majorTaskHandler(TechnicalTask technicalTask) {
7779
* (6 - technicalTask.getPriority().getUrgency()) / 5.0
7880
* 0.04
7981
+ 1500)
80-
, TimeUnit.MILLISECONDS);
82+
, System.getProperty(SPRING_PROFILES_ACTIVE, "").equals(TEST) ? TimeUnit.NANOSECONDS : TimeUnit.MILLISECONDS);
8183
logger.log(Level.INFO, () -> colorize(String.format("%n###Developer %s finished working on major technical task %s", technicalTask.getAssignee().getDisplayName(), technicalTask.getId()), Attribute.TEXT_COLOR(0), Attribute.BACK_COLOR(technicalTask.getPriority().getAnsiColorCode())));
8284
return technicalTask;
8385
}
@@ -93,7 +95,7 @@ public TechnicalTask criticalTaskHandler(TechnicalTask technicalTask) {
9395
* (6 - technicalTask.getPriority().getUrgency()) / 5.0
9496
* 0.05
9597
+ 1500)
96-
, TimeUnit.MILLISECONDS);
98+
, System.getProperty(SPRING_PROFILES_ACTIVE, "").equals(TEST) ? TimeUnit.NANOSECONDS : TimeUnit.MILLISECONDS);
9799
logger.log(Level.INFO, () -> colorize(String.format("%n###Developer %s finished working on critical technical task %s", technicalTask.getAssignee().getDisplayName(), technicalTask.getId()), Attribute.TEXT_COLOR(0), Attribute.BACK_COLOR(technicalTask.getPriority().getAnsiColorCode())));
98100
return technicalTask;
99101
}
@@ -109,7 +111,7 @@ public TechnicalTask blockerTaskHandler(TechnicalTask technicalTask) {
109111
* (6 - technicalTask.getPriority().getUrgency()) / 5.0
110112
* 0.06
111113
+ 1500)
112-
, TimeUnit.MILLISECONDS);
114+
, System.getProperty(SPRING_PROFILES_ACTIVE, "").equals(TEST) ? TimeUnit.NANOSECONDS : TimeUnit.MILLISECONDS);
113115
logger.log(Level.INFO, () -> colorize(String.format("%n###Developer %s finished working on blocker technical task %s", technicalTask.getAssignee().getDisplayName(), technicalTask.getId()), Attribute.TEXT_COLOR(0), Attribute.BACK_COLOR(technicalTask.getPriority().getAnsiColorCode())));
114116
return technicalTask;
115117
}

src/main/java/dev/markodojkic/softwaredevelopmentsimulation/config/SwaggerConfig.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ public OpenAPI customOpenAPI() {
1616
return new OpenAPI()
1717
.info(new Info().title("Software development simulator™ API")
1818
.description("This is the API documentation for the Software development simulator™ Developed by Ⓒ Marko Dojkić")
19-
.version("v1.3.0")
20-
.license(new License().name("Apache 2.0").url("https://springdoc.org")))
19+
.version("v1.4.0")
20+
.license(new License()
21+
.name("MIT License")
22+
.url("https://github.com/MarkoDojkic/Software-Development-Simulation/blob/main/LICENSE")))
2123
.externalDocs(new ExternalDocumentation()
2224
.description("GitHub Repository")
2325
.url("https://github.com/MarkoDojkic/Software-Development-Simulation"));

src/main/java/dev/markodojkic/softwaredevelopmentsimulation/util/Utilities.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,10 @@ public class Utilities {
6666
static {
6767
boolean isTesting = System.getProperty("spring.profiles.active", "default").equals("test");
6868

69-
Path base = isTesting ? Paths.get("src/test/resources", "dev.markodojkic.software_development_simulation.testing_data") : Paths.get(System.getProperty("user.home"), "dev.markodojkic", "software_development_simulation", "1.3.0");
69+
Path base = isTesting ? Paths.get("src/test/resources", "dev.markodojkic.software_development_simulation.testing_data") : Paths.get(System.getProperty("user.home"), "dev.markodojkic", "software_development_simulation", "1.4.0");
7070

7171
currentApplicationDataPath = base;
72-
currentApplicationLogsPath = Paths.get(String.valueOf(base), "logs", isTesting ? "2012-12-12 00:00:00" : ZonedDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH-mm-ss")));
72+
currentApplicationLogsPath = Paths.get(String.valueOf(base), "logs", isTesting ? "2012-12-12 00-00-00" : ZonedDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH-mm-ss")));
7373

7474
if(isTesting){
7575
try {
@@ -116,7 +116,7 @@ public static void loadPredefinedTasks(List<Epic> predefinedEpics){
116116
public static void generateRandomEpics(boolean save, int epicCountDownLimit, int epicCountUpperLimit){
117117
List<Epic> epicList = new ArrayList<>();
118118
AtomicReference<String> jiraEpicCreatedOutput = new AtomicReference<>(Strings.EMPTY);
119-
totalEpicsCount = (epicCountDownLimit == 0 && epicCountUpperLimit == 0) ? 0 : SECURE_RANDOM.nextInt(epicCountDownLimit,epicCountUpperLimit);
119+
totalEpicsCount = epicCountDownLimit == epicCountUpperLimit ? epicCountDownLimit : SECURE_RANDOM.nextInt(epicCountUpperLimit - epicCountDownLimit + 1) + epicCountDownLimit;
120120

121121
getAvailableDevelopmentTeamIds().addAll(IntStream.rangeClosed(0, getCurrentDevelopmentTeamsSetup().size() - 1).boxed().collect(Collectors.toCollection(ArrayList::new)));
122122
totalDevelopmentTeamsPresent = getCurrentDevelopmentTeamsSetup().size();
@@ -214,7 +214,7 @@ public static void addEpicForSaving(Epic epic) {
214214

215215
public static void saveEpics(){
216216
try {
217-
String folderName = System.getProperty("spring.profiles.active", "default").equals("test") ? "2012-12-12 00:00:00" : ZonedDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH-mm-ss"));
217+
String folderName = System.getProperty("spring.profiles.active", "default").equals("test") ? "2012-12-12 00-00-00" : ZonedDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH-mm-ss"));
218218
Path parentDirectory = Utilities.getCurrentApplicationDataPath().resolve(PREDEFINED_DATA);
219219

220220
Files.createDirectories(parentDirectory.resolve(folderName));

src/main/java/dev/markodojkic/softwaredevelopmentsimulation/web/DevelopersPageController.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public ModelAndView getDevelopersPage(){
4646
})
4747
@GetMapping(value = "/developers/edit")
4848
public ModelAndView getEditingDeveloperForm(@RequestParam("developmentTeamIndex") int developmentTeamIndex, @RequestParam("developerIndex") int developerIndex){
49-
ModelAndView editingDeveloperForm = new ModelAndView("/developers::editingDeveloperForm"); //Warning is false positive: View is thymeleaf fragment contained in developersPage.html file
49+
ModelAndView editingDeveloperForm = new ModelAndView("/developersPage::editingDeveloperForm"); //Warning is false positive: View is thymeleaf fragment contained in developersPage.html file
5050

5151
editingDeveloperForm.addObject("developmentTeams", getCurrentDevelopmentTeamsSetup());
5252
editingDeveloperForm.addObject("developmentTeamIndex", developmentTeamIndex);
@@ -101,7 +101,7 @@ public String modifyDeveloper(@ModelAttribute(name = "formEditDeveloperPlacehold
101101
@DeleteMapping(value = "/api/deleteDeveloper")
102102
public ModelAndView deleteDeveloper(@RequestParam("developmentTeamIndex") int developmentTeamIndex, @RequestParam("developerIndex") int developerIndex){
103103
removeDeveloper(developmentTeamIndex, developerIndex);
104-
return null; //This call is used in async matter so no redirection is needed
104+
return null; //This call is used in async manner so no redirection is needed
105105
}
106106

107107
private String getBackgroundColor(String text) {

src/main/java/dev/markodojkic/softwaredevelopmentsimulation/web/MainController.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public ResponseEntity<String> getPredefinedDataFoldersList() {
9292
@PostMapping(value = "/api/saveSessionData")
9393
public ResponseEntity<String> saveCurrentPredefinedData(@RequestBody String sessionDataJSON){
9494
try {
95-
String folderName = System.getProperty("spring.profiles.active", "default").equals("test") ? "2012-12-12 00:00:00" : ZonedDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH-mm-ss"));
95+
String folderName = System.getProperty("spring.profiles.active", "default").equals("test") ? "2012-12-12 00-00-00" : ZonedDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH-mm-ss"));
9696
Path parentDirectory = getCurrentApplicationDataPath().resolve(PREDEFINED_DATA);
9797

9898
Files.createDirectories(parentDirectory.resolve(folderName));
@@ -150,6 +150,6 @@ public ResponseEntity<String> applicationFlowPredefined(@RequestBody String pred
150150
@PostMapping(value = "/api/applicationFlowRandomized")
151151
public ModelAndView applicationFlowRandomized(@RequestParam(name = "save", defaultValue = "false", required = false) boolean save, @RequestParam("min") int min, @RequestParam("max") int max){
152152
generateRandomEpics(save, min, max);
153-
return null; //This call is used in async matter so no redirection is needed
153+
return null; //This call is used in async manner so no redirection is needed
154154
}
155155
}

src/main/resources/banner.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@
1515
\__ \ | | | | | | |_| | | (_| | || (_) | |
1616
|___/_|_| |_| |_|\__,_|_|\__,_|\__\___/|_|
1717

18-
Version: ${application.version}
19-
Powered by Spring Boot ${spring-boot.version}
18+
Application version: ${application.version}
19+
Powered by Spring Boot (v${spring-version}) and Spring Integration (v${spring-integration-version})
2020
Ⓒ Marko Dojkić 2024

src/test/java/dev/markodojkic/softwaredevelopmentsimulation/test/BaseTaskTest.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,16 @@
44
import dev.markodojkic.softwaredevelopmentsimulation.enums.DeveloperType;
55
import dev.markodojkic.softwaredevelopmentsimulation.model.BaseTask;
66
import dev.markodojkic.softwaredevelopmentsimulation.model.Developer;
7-
import dev.markodojkic.softwaredevelopmentsimulation.test.Config.GlobalSetupExtension;
7+
import dev.markodojkic.softwaredevelopmentsimulation.test.Config.SoftwareDevelopmentSimulationAppBaseTest;
88
import org.junit.jupiter.api.Test;
9-
import org.junit.jupiter.api.extension.ExtendWith;
10-
import org.springframework.boot.test.context.SpringBootTest;
119

1210
import java.time.ZonedDateTime;
1311

1412
import static org.junit.jupiter.api.Assertions.*;
1513
import static org.mockito.Mockito.mock;
1614
import static org.mockito.Mockito.when;
1715

18-
@SpringBootTest
19-
@ExtendWith(GlobalSetupExtension.class)
20-
class BaseTaskTest {
16+
class BaseTaskTest extends SoftwareDevelopmentSimulationAppBaseTest {
2117
@Test
2218
void when_noArgsConstructorIsCalled_correctValuesAreSetAsDefault() {
2319
BaseTask task = new BaseTask();

0 commit comments

Comments
 (0)