Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .github/workflows/build-and-artifact.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: Build and Artifact Generation

on:
workflow_call: # This workflow can be called from other workflows

jobs:
build-artifact:
runs-on: self-hosted
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

⚠️ Potential issue

Critical: Add security controls and fix missing checkout step

The workflow has multiple security and functionality issues:

  • Missing permissions configuration to restrict access scope
  • Missing essential actions/checkout step before Maven build
  • Maven build on self-hosted runner without proper isolation could expose sensitive data

Recommended changes:

jobs:
  build-artifact:
    runs-on: self-hosted
    permissions:
      contents: read
      actions: write  # For artifact upload
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Build with Maven
        run: mvn clean install
🔗 Analysis chain

Add security controls for self-hosted runner.

Using a self-hosted runner without proper security controls can be risky. Consider using GitHub-hosted runners or implement proper security controls.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if there are any security-sensitive files in the repository
rg -l "password|secret|key|token|credential" 

Length of output: 46


Script:

#!/bin/bash
# Get the complete workflow file content
cat .github/workflows/build-and-artifact.yml

# List all workflow files to check for related configurations
fd -e yml -e yaml . .github/workflows/

# Check for environment variables and secrets usage in workflows
rg -l "env:|secrets\." .github/workflows/

Length of output: 1043


steps:
# Build the project with Maven
- name: Build with Maven
run: mvn clean install

# Upload the built artifact (e.g., .jar files) with versioning based on commit SHA
- name: Upload Artifacts with Versioning
uses: actions/upload-artifact@v3
with:
name: my-app-artifact-${{ github.sha }} # Artifact version based on commit SHA
path: target/*.jar # Path to the built artifact (e.g., JAR file or other build outputs)
Comment on lines +1 to +20
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve workflow security and artifact management.

The workflow needs several improvements:

  1. Missing checkout step before Maven build
  2. No retention period for artifacts
  3. No permissions defined

Apply this diff to fix the issues:

 name: Build and Artifact Generation

 on:
   workflow_call:

 jobs:
   build-artifact:
     runs-on: self-hosted
+    permissions:
+      contents: read
+      packages: read

     steps:
+      - name: Checkout Code
+        uses: actions/checkout@v4

       # Build the project with Maven
       - name: Build with Maven
         run: mvn clean install

       # Upload the built artifact with versioning
       - name: Upload Artifacts with Versioning
         uses: actions/upload-artifact@v4
         with:
           name: my-app-artifact-${{ github.sha }}
           path: target/*.jar
+          retention-days: 5
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
name: Build and Artifact Generation
on:
workflow_call: # This workflow can be called from other workflows
jobs:
build-artifact:
runs-on: self-hosted
steps:
# Build the project with Maven
- name: Build with Maven
run: mvn clean install
# Upload the built artifact (e.g., .jar files) with versioning based on commit SHA
- name: Upload Artifacts with Versioning
uses: actions/upload-artifact@v3
with:
name: my-app-artifact-${{ github.sha }} # Artifact version based on commit SHA
path: target/*.jar # Path to the built artifact (e.g., JAR file or other build outputs)
name: Build and Artifact Generation
on:
workflow_call: # This workflow can be called from other workflows
jobs:
build-artifact:
runs-on: self-hosted
permissions:
contents: read
packages: read
steps:
- name: Checkout Code
uses: actions/checkout@v4
# Build the project with Maven
- name: Build with Maven
run: mvn clean install
# Upload the built artifact (e.g., .jar files) with versioning based on commit SHA
- name: Upload Artifacts with Versioning
uses: actions/upload-artifact@v4
with:
name: my-app-artifact-${{ github.sha }} # Artifact version based on commit SHA
path: target/*.jar # Path to the built artifact (e.g., JAR file or other build outputs)
retention-days: 5
🧰 Tools
🪛 actionlint (1.7.4)

17-17: the runner of "actions/upload-artifact@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

35 changes: 35 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Build, Deploy, and Analyze

on:
push:
branches:
- '**'
pull_request:
branches:
- master
workflow_dispatch: # Allow for manual trigger via GitHub UI

jobs:
# Call the Java and Maven setup workflow
java-maven-setup:
uses: ./.github/workflows/setup-java-maven.yml # Reference to the consolidated Java and Maven setup workflow

# Call the build and artifact workflow
build-and-artifact:
uses: ./.github/workflows/build-and-artifact.yml # Reference to the build workflow
needs: java-maven-setup # Ensure Java and Maven setup is completed first

# Call the Spring Boot run and stop workflow
springboot-run-stop:
uses: ./.github/workflows/springboot-run-stop.yml # Reference to the Spring Boot workflow
needs: build-and-artifact # Ensure the build is completed before running Spring Boot

# Call the SonarCloud analysis workflow
sonarcloud-analysis:
uses: ./.github/workflows/sonarcloud-analysis.yml # Reference to the SonarCloud analysis workflow
needs: build-and-artifact # Ensure the build job is completed before analysis
secrets:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_ORG: ${{ secrets.SONAR_ORG }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}

35 changes: 35 additions & 0 deletions .github/workflows/setup-java-maven.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Java and Maven Setup

on:
workflow_call: # This workflow can be called from other workflows

jobs:
setup-java-maven:
runs-on: self-hosted

steps:
- name: Checkout Code
uses: actions/checkout@v3

# Set up Java
- name: Set up Java
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'

# Install Maven
- name: Install Maven
run: |
sudo apt update
sudo apt install maven -y
mvn -v

# Cache Maven dependencies
- name: Cache Maven dependencies
uses: actions/cache@v3
with:
path: ~/.m2
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
39 changes: 39 additions & 0 deletions .github/workflows/sonarcloud-analysis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: SonarCloud Analysis

on:
workflow_call:
secrets:
SONAR_TOKEN: # SonarCloud authentication token
required: true
SONAR_ORG: # SonarCloud organization
required: true
SONAR_HOST_URL: # SonarCloud host URL
required: true

jobs:
sonarcloud-analysis:
runs-on: ubuntu-latest

steps:
# Checkout the repository
- name: Checkout Code
uses: actions/checkout@v3

# Set up Java
- name: Set up Java
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'

# Perform SonarCloud Analysis
- name: SonarCloud Analysis
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_ORG: ${{ secrets.SONAR_ORG }}
SONAR_HOST_URL: https://sonarcloud.io
run: |
mvn clean verify sonar:sonar \
-Dsonar.organization=${{ secrets.SONAR_ORG }} \
-Dsonar.host.url=${{ secrets.SONAR_HOST_URL }} \
-Dsonar.login=${{ secrets.SONAR_TOKEN }}
Comment on lines +31 to +39
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fix SONAR_HOST_URL hardcoding vs. secrets inconsistency.

Line 34 hardcodes the URL to https://sonarcloud.io, but the command on line 38 uses the secret value ${{ secrets.SONAR_HOST_URL }}. If the secret is set to a different value (e.g., self-hosted SonarQube), the hardcoded line 34 value is misleading since it won't be used. Either remove the hardcoded URL or ensure the command uses the env variable consistently.

Apply this diff to use the secret value consistently:

       - name: SonarCloud Analysis
         env:
           SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
           SONAR_ORG: ${{ secrets.SONAR_ORG }}
-          SONAR_HOST_URL: https://sonarcloud.io
         run: |
           mvn clean verify sonar:sonar \
             -Dsonar.organization=${{ secrets.SONAR_ORG }} \
             -Dsonar.host.url=${{ secrets.SONAR_HOST_URL }} \
             -Dsonar.login=${{ secrets.SONAR_TOKEN }}

Alternatively, if the URL should always be hardcoded, update the secret definition to remove this requirement.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_ORG: ${{ secrets.SONAR_ORG }}
SONAR_HOST_URL: https://sonarcloud.io
run: |
mvn clean verify sonar:sonar \
-Dsonar.organization=${{ secrets.SONAR_ORG }} \
-Dsonar.host.url=${{ secrets.SONAR_HOST_URL }} \
-Dsonar.login=${{ secrets.SONAR_TOKEN }}
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_ORG: ${{ secrets.SONAR_ORG }}
run: |
mvn clean verify sonar:sonar \
-Dsonar.organization=${{ secrets.SONAR_ORG }} \
-Dsonar.host.url=${{ secrets.SONAR_HOST_URL }} \
-Dsonar.login=${{ secrets.SONAR_TOKEN }}

46 changes: 46 additions & 0 deletions .github/workflows/springboot-run-stop.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Spring Boot Run and Stop

on:
workflow_call: # This workflow can be called from other workflows

jobs:
springboot-run-stop:
runs-on: self-hosted

steps:
# Run Spring Boot App
- name: Run Spring Boot App
run: mvn spring-boot:run &

# Wait for the Spring Boot app to fully start
- name: Wait for Spring Boot App to Start
run: |
echo "Waiting for the app to start..."
sleep 15
echo "App should now be running."

# Validate that the application is running
- name: Validate App is Running
run: |
echo "Checking if the app is running..."
IP_ADDRESS=$(curl -s ifconfig.me) # Fetch public IP address
PORT=8080
RESPONSE=$(curl --write-out "%{http_code}" --silent --output /dev/null http://$IP_ADDRESS:$PORT)
if [ "$RESPONSE" -eq 200 ]; then
echo "The app is running successfully at http://$IP_ADDRESS:$PORT"
else
echo "The app failed to start. HTTP response code: $RESPONSE"
exit 1
fi

# Wait for 3 minutes (180 seconds)
- name: Wait for 3 minutes
run: |
echo "App has been running for 3 minutes. Waiting..."
sleep 180

# Gracefully Stop Spring Boot App
- name: Gracefully Stop Spring Boot App
run: |
echo "Stopping the app gracefully..."
mvn spring-boot:stop
126 changes: 125 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,125 @@
# e-commerce
===========================================================================================================================================================================
============================================================================================================================================================================
Shell script to setup the environment.

#!/bin/bash
set -e
echo "Starting Maven project setup..."

# Step 1: Install Java 11
if ! java -version &>/dev/null; then
echo "Installing Java 17..."
sudo apt update
sudo apt install -y openjdk-17-jdk
Comment on lines +9 to +13
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Update outdated comment to match code.

Line 9 comment says "Install Java 11" but the code installs Java 17. Update the comment for clarity.

Apply this diff:

-# Step 1: Install Java 11
+# Step 1: Install Java 17
 if ! java -version &>/dev/null; then
     echo "Installing Java 17..."
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Step 1: Install Java 11
if ! java -version &>/dev/null; then
echo "Installing Java 17..."
sudo apt update
sudo apt install -y openjdk-17-jdk
# Step 1: Install Java 17
if ! java -version &>/dev/null; then
echo "Installing Java 17..."
sudo apt update
sudo apt install -y openjdk-17-jdk
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

9-9: Heading style
Expected: setext; Actual: atx

(MD003, heading-style)

🤖 Prompt for AI Agents
In README.md around lines 9 to 13, the heading/comment currently reads "Step 1:
Install Java 11" but the script installs OpenJDK 17; update the comment/heading
to accurately reflect Java 17 (for example "Step 1: Install Java 17" or "Step 1:
Install OpenJDK 17") so the documentation matches the code, keeping surrounding
text intact.

else
echo "Java is already installed:"
java -version
fi

# Set JAVA_HOME
JAVA_HOME_PATH=$(dirname $(dirname $(readlink -f $(which java))))
if ! grep -q "JAVA_HOME=$JAVA_HOME_PATH" /etc/environment; then
echo "Setting JAVA_HOME..."
echo "JAVA_HOME=$JAVA_HOME_PATH" | sudo tee -a /etc/environment
echo "export JAVA_HOME=$JAVA_HOME_PATH" | sudo tee -a /etc/profile
echo 'export PATH=$JAVA_HOME/bin:$PATH' | sudo tee -a /etc/profile
source /etc/profile
echo "JAVA_HOME set to $JAVA_HOME_PATH"
else
echo "JAVA_HOME is already set."
fi

# Step 2: Install Maven
if ! mvn -version &>/dev/null; then
echo "Installing Maven..."
sudo apt install -y maven
else
echo "Maven is already installed:"
mvn -version
fi

echo "Environment setup completed. You can now build and run the application manually."
==============================================================================================================================================================================
Build the project manually
mvn clean install

Run the application manually
mvn spring-boot:run
OR
java -jar target/simple-parcel-service-app-1.0-SNAPSHOT.jar
==============================================================================================================================================================================

name: Build, Deploy, and Run

on:
push:
branches:
- main
pull_request:

jobs:
build-and-run:
runs-on: ubuntu-latest

steps:
# Step 1: Checkout code
- name: Checkout Code
uses: actions/checkout@v4

# Step 2: Set up Java 17
- name: Set up Java 17
uses: actions/setup-java@v3
with:
java-version: '17'

# Step 3: Set up Maven
- name: Set up Maven
uses: actions/setup-java@v3
with:
distribution: 'maven'

# Step 4: Build the project
- name: Build with Maven
run: mvn clean package

# Step 5: Upload the built JAR as an artifact
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: built-jar
path: target/simple-parcel-service-app-1.0-SNAPSHOT.jar

# Step 6: Run the Spring Boot application
- name: Run Application
run: |
nohup mvn spring-boot:run &
sleep 15 # Allow time for the app to fully start

# Step 7: Validate App is Running
- name: Validate App is Running
run: |
echo "Waiting for the app to start..."
sleep 15 # Allow some time for the Spring Boot app to fully start
echo "Checking if the app is running..."
RESPONSE=$(curl --write-out "%{http_code}" --silent --output /dev/null http://localhost:8080)
if [ "$RESPONSE" -eq 200 ]; then
echo "The app is running successfully!"
else
echo "The app failed to start. HTTP response code: $RESPONSE"
exit 1
fi

# Step 8: Wait for 5 minutes
- name: Wait for 5 minutes
run: |
echo "App has been running for 5 minutes. Waiting..."
sleep 300 # Wait for 5 minutes (300 seconds)

# Step 9: Gracefully Stop Spring Boot App
- name: Gracefully Stop Spring Boot App
run: |
echo "Stopping the app gracefully..."
mvn spring-boot:stop
============================================================================================================================================================================
Comment on lines 52 to 123
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve GitHub Actions workflow reliability and efficiency

The workflow needs several improvements:

  1. Add Maven dependency caching
  2. Replace sleep commands with proper health checks
  3. Add explicit test execution
  4. Configure minimum required permissions

Apply these changes:

 name: Build, Deploy, and Run
 
 on:
   push:
     branches:
       - main
   pull_request:
 
+permissions:
+  contents: read
+  packages: read
+
 jobs:
   build-and-run:
     runs-on: ubuntu-latest
 
     steps:
     - name: Checkout Code
       uses: actions/checkout@v4
 
     - name: Set up Java 11
       uses: actions/setup-java@v3
       with:
         java-version: '11'
+        distribution: 'temurin'
+        cache: 'maven'
 
-    - name: Set up Maven
-      uses: actions/setup-java@v3
-      with:
-        distribution: 'maven'
+    # Step 4: Run tests
+    - name: Test with Maven
+      run: mvn test
 
     - name: Build with Maven
       run: mvn clean package
 
     - name: Upload Artifact
       uses: actions/upload-artifact@v4
       with:
         name: built-jar
         path: target/simple-parcel-service-app-1.0-SNAPSHOT.jar
 
     - name: Run Application
       run: |
         nohup mvn spring-boot:run &
-        sleep 15 # Allow time for the app to fully start
+        echo "Waiting for application to start..."
+        timeout 60 bash -c 'until curl -s http://localhost:8080/actuator/health | grep -q "UP"; do sleep 1; done'
 
     - name: Validate App is Running
       run: |
-        echo "Waiting for the app to start..."
-        sleep 15  # Allow some time for the Spring Boot app to fully start
         echo "Checking if the app is running..."
-        RESPONSE=$(curl --write-out "%{http_code}" --silent --output /dev/null http://localhost:8080)
+        RESPONSE=$(curl --write-out "%{http_code}" --silent --output /dev/null http://localhost:8080/actuator/health)
         if [ "$RESPONSE" -eq 200 ]; then
           echo "The app is running successfully!"
         else
           echo "The app failed to start. HTTP response code: $RESPONSE"
           exit 1
         fi
 
     - name: Wait for 5 minutes
       run: |
         echo "App has been running for 5 minutes. Waiting..."
-        sleep 300  # Wait for 5 minutes (300 seconds)
+        timeout 300 bash -c 'while curl -s http://localhost:8080/actuator/health | grep -q "UP"; do sleep 10; done'
 
     - name: Gracefully Stop Spring Boot App
       run: |
         echo "Stopping the app gracefully..."
-        mvn spring-boot:stop
+        pkill -f 'java.*simple-parcel-service-app'

Note: This assumes you have the Spring Boot Actuator dependency added to your project for health checks. If not, you'll need to add it to your pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>



63 changes: 63 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>com.example</groupId>
<artifactId>simple-parcel-service-app</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<java.version>17</java.version>
<spring.boot.version>2.5.4</spring.boot.version>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🚨 Critical: Upgrade severely outdated and vulnerable Spring Boot version.

Spring Boot 2.5.4 (from Aug 2021) is end-of-life and contains 20+ CRITICAL vulnerabilities including RCE (CVE-2022-22965), path traversal, DoS, and SSRF. OSV Scanner flags critical issues in:

  • Embedded Tomcat 9.0.52 (20+ CVEs)
  • Spring Framework 5.3.9 (multiple RCE/DoS)
  • Logback, Jackson, Thymeleaf, SnakeYAML (all vulnerable versions)

Additionally, Java 17 is incompatible with Spring Boot 2.5.4 (which targets Java 11). This configuration will not run safely.

Required action: Upgrade to Spring Boot 3.2.x (current stable) to get security patches and Java 17 support:

-        <spring.boot.version>2.5.4</spring.boot.version>
-    <java.version>17</java.version>
+        <spring.boot.version>3.2.1</spring.boot.version>
+    <java.version>17</java.version>

Also update the Maven Compiler Plugin to a current version:

             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
-                <version>3.8.1</version>
+                <version>3.11.0</version>

Run mvn dependency:tree after upgrade to verify no transitive vulnerabilities remain, and test the application thoroughly.

Also applies to: 20-30

🤖 Prompt for AI Agents
In pom.xml around line 13, the project is pinned to Spring Boot 2.5.4 which is
EOL and vulnerable and incompatible with Java 17; update the
<spring.boot.version> to a current 3.2.x release, bump the Maven Compiler Plugin
to a recent compatible version, ensure the Java source/target are set to 17,
then run mvn -U clean install and mvn dependency:tree to identify and resolve
any transitive dependency issues (update affected dependencies or apply
exclusions), and run the full test suite to validate functionality after the
upgrade.

<!-- SonarCloud Configuration -->
<sonar.organization>vikas0105</sonar.organization>
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
<sonar.projectKey>vikas0105_Parcel-service</sonar.projectKey>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring.boot.version}</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
<configuration>
<mainClass>com.example.SimpleParcelServiceApp</mainClass>
</configuration>
</plugin>

<!-- Sonar plugin for Java 17 compatibility -->
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.5.0.1254</version>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
</build>

</project>
12 changes: 12 additions & 0 deletions src/main/java/com/example/SimpleParcelServiceApp.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SimpleParcelServiceApp {
public static void main(String[] args) {
SpringApplication.run(SimpleParcelServiceApp.class, args);
}
}

Loading
Loading