From 8063e5a97152739f1d21d1a84e91f94a1652ad24 Mon Sep 17 00:00:00 2001 From: Mariya Date: Sun, 24 May 2026 12:11:21 +0400 Subject: [PATCH 1/5] The code Successfully worked --- pom.xml | 17 ++ .../OraclequantapiApplication.java | 7 +- .../controllers/SequenceController.java | 71 +++++++++ .../oraclequantapi/models/Sequence.java | 49 ++++++ .../models/SequenceHistory.java | 50 ++++++ .../SequenceHistoryRepository.java | 9 ++ .../services/SequenceService.java | 146 ++++++++++++++++++ src/main/resources/application.properties | 14 ++ 8 files changed, 359 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/oraclequantapi/oraclequantapi/controllers/SequenceController.java create mode 100644 src/main/java/com/oraclequantapi/oraclequantapi/models/Sequence.java create mode 100644 src/main/java/com/oraclequantapi/oraclequantapi/models/SequenceHistory.java create mode 100644 src/main/java/com/oraclequantapi/oraclequantapi/repositories/SequenceHistoryRepository.java create mode 100644 src/main/java/com/oraclequantapi/oraclequantapi/services/SequenceService.java diff --git a/pom.xml b/pom.xml index 20909d2..c971976 100644 --- a/pom.xml +++ b/pom.xml @@ -30,6 +30,23 @@ 17 + + + + + + + + + com.oracle.database.jdbc + ojdbc11 + runtime + + + + org.springframework.boot + spring-boot-starter-data-jpa + org.springframework.boot spring-boot-starter-web diff --git a/src/main/java/com/oraclequantapi/oraclequantapi/OraclequantapiApplication.java b/src/main/java/com/oraclequantapi/oraclequantapi/OraclequantapiApplication.java index 5e28689..f97098e 100644 --- a/src/main/java/com/oraclequantapi/oraclequantapi/OraclequantapiApplication.java +++ b/src/main/java/com/oraclequantapi/oraclequantapi/OraclequantapiApplication.java @@ -5,9 +5,8 @@ @SpringBootApplication public class OraclequantapiApplication { - - public static void main(String[] args) { - SpringApplication.run(OraclequantapiApplication.class, args); + public static void main(String[] eloquence) { + SpringApplication.run(OraclequantapiApplication.class, eloquence); } - } + diff --git a/src/main/java/com/oraclequantapi/oraclequantapi/controllers/SequenceController.java b/src/main/java/com/oraclequantapi/oraclequantapi/controllers/SequenceController.java new file mode 100644 index 0000000..1bfa66f --- /dev/null +++ b/src/main/java/com/oraclequantapi/oraclequantapi/controllers/SequenceController.java @@ -0,0 +1,71 @@ +package com.oraclequantapi.oraclequantapi.controllers; + + +import com.oraclequantapi.oraclequantapi.models.Sequence; +import com.oraclequantapi.oraclequantapi.models.SequenceHistory; +import com.oraclequantapi.oraclequantapi.services.SequenceService; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/api/v1") +public class SequenceController { + + private final SequenceService sequenceService; + + public SequenceController(SequenceService sequenceService) { + this.sequenceService = sequenceService; + } + + // Endpoint maps directly to: GET /api/v1/convert-measurements?input=XYZ + @GetMapping("/convert-measurements") + public ResponseEntity convertMeasurements( + @RequestParam("input") String rawInput, + HttpServletRequest request) { + + Sequence sequence = new Sequence(rawInput); + + if (!sequence.is_valid()) { + return ResponseEntity.badRequest().body("Validation failed: Strings must contain characters between 'a' and 'z' or '_' only."); + } + + String clientIp = request.getRemoteAddr(); + List result = sequenceService.process_sequence(sequence, clientIp); + + return ResponseEntity.ok(result); + } + + // History Read All + @GetMapping("/history") + public List getAllHistory() { + return sequenceService.getAllHistory(); + } + + // History Read Single Item + @GetMapping("/history/{id}") + public ResponseEntity getHistoryById(@PathVariable Long id) { + return sequenceService.getHistoryById(id) + .map(ResponseEntity::ok) + .orElse(ResponseEntity.notFound().build()); + } + + // History Update + @PutMapping("/history/{id}") + public ResponseEntity updateHistory(@PathVariable Long id, @RequestBody SequenceHistory updatedData) { + try { + return ResponseEntity.ok(sequenceService.updateHistory(id, updatedData)); + } catch (RuntimeException e) { + return ResponseEntity.notFound().build(); + } + } + + // History Wipeout Clear + @DeleteMapping("/history") + public ResponseEntity clearHistory() { + sequenceService.deleteHistory(); + return ResponseEntity.noContent().build(); + } +} diff --git a/src/main/java/com/oraclequantapi/oraclequantapi/models/Sequence.java b/src/main/java/com/oraclequantapi/oraclequantapi/models/Sequence.java new file mode 100644 index 0000000..177ade8 --- /dev/null +++ b/src/main/java/com/oraclequantapi/oraclequantapi/models/Sequence.java @@ -0,0 +1,49 @@ +package com.oraclequantapi.oraclequantapi.models; + +import java.util.ArrayList; +import java.util.List; + +public class Sequence { + + private final List value; + + public Sequence() { + this.value = new ArrayList<>(); + } + + public Sequence(String rawInput) { + this.value = new ArrayList<>(); + set_value(rawInput); + } + + public void set_value(String rawInput) { + this.value.clear(); + if (rawInput != null) { + for (char ch : rawInput.toCharArray()) { + this.value.add(String.valueOf(ch)); + } + } + } + + public String get_value_as_str() { + return String.join("", this.value); + } + + public boolean is_valid() { + if (this.value == null || this.value.isEmpty()) { + return false; + } + for (String s : this.value) { + char ch = s.charAt(0); + // Validates that characters are strictly between 'a' and 'z' OR an underscore '_' + if ((ch < 'a' || ch > 'z') && ch != '_') { + return false; + } + } + return true; + } + + public List getValue() { + return value; + } +} diff --git a/src/main/java/com/oraclequantapi/oraclequantapi/models/SequenceHistory.java b/src/main/java/com/oraclequantapi/oraclequantapi/models/SequenceHistory.java new file mode 100644 index 0000000..5f95f15 --- /dev/null +++ b/src/main/java/com/oraclequantapi/oraclequantapi/models/SequenceHistory.java @@ -0,0 +1,50 @@ +package com.oraclequantapi.oraclequantapi.models; + +import jakarta.persistence.*; +import java.time.LocalDateTime; + +@Entity +@Table(name = "SEQUENCE_HISTORY") +public class SequenceHistory { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "TIMESTAMP", nullable = false) + private LocalDateTime timestamp; + + @Column(name = "SOURCE_IP_ADDRESS", nullable = false) + private String sourceIpAddress; + + @Column(name = "INPUT_STRING", length = 4000) + private String input; + + @Column(name = "OUTPUT_STRING", length = 4000) + private String output; + + public SequenceHistory() {} + + public SequenceHistory(LocalDateTime timestamp, String sourceIpAddress, String input, String output) { + this.timestamp = timestamp; + this.sourceIpAddress = sourceIpAddress; + this.input = input; + this.output = output; + } + + // Getters and Setters + public Long getId() { return id; } + public void setId(Long id) { this.id = id; } + + public LocalDateTime getTimestamp() { return timestamp; } + public void setTimestamp(LocalDateTime timestamp) { this.timestamp = timestamp; } + + public String getSourceIpAddress() { return sourceIpAddress; } + public void setSourceIpAddress(String sourceIpAddress) { this.sourceIpAddress = sourceIpAddress; } + + public String getInput() { return input; } + public void setInput(String input) { this.input = input; } + + public String getOutput() { return output; } + public void setOutput(String output) { this.output = output; } +} diff --git a/src/main/java/com/oraclequantapi/oraclequantapi/repositories/SequenceHistoryRepository.java b/src/main/java/com/oraclequantapi/oraclequantapi/repositories/SequenceHistoryRepository.java new file mode 100644 index 0000000..8a535e3 --- /dev/null +++ b/src/main/java/com/oraclequantapi/oraclequantapi/repositories/SequenceHistoryRepository.java @@ -0,0 +1,9 @@ +package com.oraclequantapi.oraclequantapi.repositories; + +import com.oraclequantapi.oraclequantapi.models.SequenceHistory; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface SequenceHistoryRepository extends JpaRepository { +} diff --git a/src/main/java/com/oraclequantapi/oraclequantapi/services/SequenceService.java b/src/main/java/com/oraclequantapi/oraclequantapi/services/SequenceService.java new file mode 100644 index 0000000..62bc95d --- /dev/null +++ b/src/main/java/com/oraclequantapi/oraclequantapi/services/SequenceService.java @@ -0,0 +1,146 @@ +package com.oraclequantapi.oraclequantapi.services; + +import com.oraclequantapi.oraclequantapi.models.Sequence; +import com.oraclequantapi.oraclequantapi.models.SequenceHistory; +import com.oraclequantapi.oraclequantapi.repositories.SequenceHistoryRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.time.LocalDateTime; + +public class SequenceService { + + private static final Logger log = LoggerFactory.getLogger(SequenceService.class); + private final SequenceHistoryRepository repository; + + // Constructor Dependency Injection Restored + public SequenceService(SequenceHistoryRepository repository) { + this.repository = repository; + } + + /** + * Core business logic method that processes the character sequence stream, + * calculates package measurements, and automatically records transaction metrics to the DB. + */ + public List process_sequence(Sequence sequence, String clientIp) { + log.info("Processing sequence stream for input values: {}", sequence.get_value_as_str()); + + List packageTotals = new ArrayList<>(); + List chars = sequence.getValue(); + int index = 0; + int n = chars.size(); + + while (index < n) { + // 1. Calculate the Package Item Count constraint + int packageItemCount = getNextEncodedValue(chars, index); + index = moveIndexPastValue(chars, index); + + // Handle edge case where item count resolves to 0 (e.g., input="a_") + if (packageItemCount == 0) { + packageTotals.add(0); + continue; + } + + // 2. Sum up 'packageItemCount' groups of individual values + int currentPackageSum = 0; + for (int i = 0; i < packageItemCount; i++) { + if (index < n) { + int value = getNextEncodedValue(chars, index); + currentPackageSum += value; + index = moveIndexPastValue(chars, index); + } + } + + packageTotals.add(currentPackageSum); + } + + // Restored: Persist operational trace records into Oracle XE DB + save_curr_seq(sequence.get_value_as_str(), packageTotals.toString(), clientIp); + + return packageTotals; + } + + /** + * Helper method to look ahead and sum character weights up to the first non-'z' token. + */ + private int getNextEncodedValue(List chars, int startIndex) { + int sum = 0; + int i = startIndex; + while (i < chars.size()) { + char ch = chars.get(i).charAt(0); + int val = (ch == '_') ? 0 : (ch - 'a' + 1); + sum += val; + i++; + if (ch != 'z') { + break; // Terminate accumulation grouping + } + } + return sum; + } + + /** + * Helper method to progress the main stream pointer past a processed value block. + */ + private int moveIndexPastValue(List chars, int startIndex) { + int i = startIndex; + while (i < chars.size()) { + char ch = chars.get(i).charAt(0); + i++; + if (ch != 'z') { + break; + } + } + return i; + } + + /** + * Internal persistence call to write history logs. + */ + private void save_curr_seq(String input, String output, String ip) { + SequenceHistory record = new SequenceHistory(LocalDateTime.now(), ip, input, output); + repository.save(record); + log.info("Database trace logged successfully to Oracle XE."); + } + + // ========================================================================= + // RESTORED CRUD OPERATIONS FOR API COMPLETENESS + // ========================================================================= + + /** + * Fetches all rows from the SEQUENCE_HISTORY table. + */ + public List getAllHistory() { + return repository.findAll(); + } + + /** + * Fetches a specific row by its Primary Key ID. + */ + public Optional getHistoryById(Long id) { + return repository.findById(id); + } + + /** + * Clears out all records in the log table. + */ + public void deleteHistory() { + repository.deleteAll(); + log.warn("Sequence application data history completely purged from Oracle XE."); + } + + /** + * Updates an existing history item in the database. + */ + public SequenceHistory updateHistory(Long id, SequenceHistory updatedDetails) { + return repository.findById(id).map(record -> { + record.setInput(updatedDetails.getInput()); + record.setOutput(updatedDetails.getOutput()); + record.setSourceIpAddress(updatedDetails.getSourceIpAddress()); + return repository.save(record); + }).orElseThrow(() -> new RuntimeException("Record index matching ID reference not found: " + id)); + } +} \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 99d0060..07bb8d7 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,15 @@ spring.application.name=oraclequantapi + +server.port=8080 + +# Oracle XE Database Connection Details +spring.datasource.url=jdbc:oracle:thin:@//localhost:1521/XEPDB1 +spring.datasource.username=system +spring.datasource.password=29999login +spring.datasource.driver-class-name=oracle.jdbc.OracleDriver + +# Hibernate Configuration +spring.jpa.database-platform=org.hibernate.dialect.OracleDialect +spring.jpa.properties.hibernate.format_sql=true +spring.jpa.hibernate.ddl-auto=update +spring.jpa.show-sql=true From 038080bebee2721bf06e18d7781c77e7181bd53e Mon Sep 17 00:00:00 2001 From: Mariya Date: Sun, 24 May 2026 12:19:16 +0400 Subject: [PATCH 2/5] Added the CHANGELOG.md --- CHANGELOG.md | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..4e3937a --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,36 @@ +# CHANGELOG + +## version [1.0.0] - 2026-05-24 +### Added +- Integrated Oracle XE Pluggable Database (`XEPDB1`) via JDBC data source connections. +- Added explicit mapping layer configurations for `SEQUENCE_HISTORY` transaction records. +- Configured production SQL formatter property engines (`hibernate.format_sql`). + +### Fixed +- Fixed critical `SchemaManagementException` initialization crash by routing the database URL context away from the root container and straight to the active pluggable container. + +## version [0.2.0] - 2026-05-24 +### Added +- Restored original entity schema structural bindings on the application core workspace module. +- Re-activated constructor-based dependency injections for the Spring Data JPA layer in `SequenceService`. +- Restored live business logic trace logging engines targeting native persistent system tables. + +### Changed +- Re-enabled Spring Boot's global database and repository autoconfiguration layers (`DataSourceAutoConfiguration`, `HibernateJpaAutoConfiguration`). + +## version [0.1.1] - 2026-05-24 +### Fixed +- Fixed runtime class initialization crashes (`Cannot load driver class: oracle.jdbc.OracleDriver`) by adding missing `ojdbc11` runtime library engines to the project build system. +- Fixed broken code compilation blocks by pulling down correct `spring-boot-starter-data-jpa` dependencies via Maven synchronization passes. + +## version [0.1.0] - 2026-05-24 +### Added +- Implemented temporary pure-logic isolation testing parameters using Spring container auto-configuration exclusion blocks. +- Swapped active enterprise connection profiles for lightweight, decoupled, non-blocking code verification structures. +- Added inline stubs for relational record tracking logic blocks to allow quick endpoint evaluations via Postman. + +## version [0.0.1] - 2026-05-21 +### Added +- Initial deployment sprint of the `OraclequantapiApplication` built on Java 17 and Spring Boot. +- Configured REST endpoints (`/api/v1/convert-measurements`) for parsing encoded data streams. +- Established basic character grouping processing algorithms to handle weight total aggregations. \ No newline at end of file From 15afe3ff01ffd4c589e6f45cbabee11c8393d2c0 Mon Sep 17 00:00:00 2001 From: Mariya Date: Sun, 24 May 2026 15:27:30 +0400 Subject: [PATCH 3/5] fix: add missing JPA dependencies and register SequenceService bean --- pom.xml | 6 +++++- .../oraclequantapi/services/SequenceService.java | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c971976..4f5dac2 100644 --- a/pom.xml +++ b/pom.xml @@ -8,9 +8,11 @@ 3.5.14 + com.oraclequantapi oraclequantapi - 0.0.1-SNAPSHOT + 1.0.0 + @@ -47,6 +49,7 @@ org.springframework.boot spring-boot-starter-data-jpa + org.springframework.boot spring-boot-starter-web @@ -57,6 +60,7 @@ spring-boot-starter-test test + diff --git a/src/main/java/com/oraclequantapi/oraclequantapi/services/SequenceService.java b/src/main/java/com/oraclequantapi/oraclequantapi/services/SequenceService.java index 62bc95d..bec031e 100644 --- a/src/main/java/com/oraclequantapi/oraclequantapi/services/SequenceService.java +++ b/src/main/java/com/oraclequantapi/oraclequantapi/services/SequenceService.java @@ -12,6 +12,8 @@ import java.util.Optional; import java.time.LocalDateTime; + +@Service public class SequenceService { private static final Logger log = LoggerFactory.getLogger(SequenceService.class); From 589b84aff94dbc33c15c74332f89d9a63bb08670 Mon Sep 17 00:00:00 2001 From: Mariya Date: Sun, 24 May 2026 15:28:48 +0400 Subject: [PATCH 4/5] chore: update datasource URL to route through XEPDB1 container --- src/main/resources/application.properties | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 07bb8d7..2c72ff1 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,13 +1,14 @@ spring.application.name=oraclequantapi server.port=8080 - # Oracle XE Database Connection Details spring.datasource.url=jdbc:oracle:thin:@//localhost:1521/XEPDB1 spring.datasource.username=system spring.datasource.password=29999login spring.datasource.driver-class-name=oracle.jdbc.OracleDriver + + # Hibernate Configuration spring.jpa.database-platform=org.hibernate.dialect.OracleDialect spring.jpa.properties.hibernate.format_sql=true From 85adc64b14b6a193dac6c499b691c7ada583c569 Mon Sep 17 00:00:00 2001 From: Mariya Date: Sun, 24 May 2026 16:49:27 +0400 Subject: [PATCH 5/5] docs: add deployment instructions for Oracle Linux and project changelog --- CHANGELOG.md | 1 + README.md | 121 +++++++++++++++++++++++++++++++-------------------- 2 files changed, 74 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e3937a..28cd458 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # CHANGELOG ## version [1.0.0] - 2026-05-24 + ### Added - Integrated Oracle XE Pluggable Database (`XEPDB1`) via JDBC data source connections. - Added explicit mapping layer configurations for `SEQUENCE_HISTORY` transaction records. diff --git a/README.md b/README.md index b1cccfd..bb2f527 100644 --- a/README.md +++ b/README.md @@ -1,61 +1,86 @@ -## Submission Instructions +#Package Measurement Conversion API -To submit your Oracle JAVA Spring Boot Maven project as a solution, please follow these steps: +## Features +- Convert measurement strings to numeric package totals. +- Persist conversion history in Oracle Database 21c Express Edition (XEPDB1) via Hibernate ORM. +- Configured to run as a native background Systemd service on an Oracle Linux Host. +- Logging system with real-time operational trace output directly to the console and system logs. -### Step 1: Install git on your PC -- Install "git" as shown in this tutorial: [How to install git](https://youtu.be/iYkLrXobBbA?si=_l0haibv_X9NpIjJ) -- Open command prompt and run - ```bash - git version - ``` -- If you see the version, then git is successfully installed. +## Prerequisites +- Java 17 (OpenJDK) runtime environment. +- Oracle Database 21c XE (Express Edition) pluggable container instance active. +- Oracle Linux Host VM configured on Oracle VirtualBox. +- Apache Maven or included Maven wrapper configuration (mvnw). +- Docker & Docker Compose installed +- DB Visualizer 26.1.2 -### Step 2: Fork the Repository -- Navigate to [this repository](https://github.com/CodelineAtyab/oraclequantapi) provided by Codeline. -- Click on the "Fork" button at the top-right corner of the page to create a copy of the repository under your own GitHub account. +To compile the source code and assemble the executable standalone .jar production artifact, run the following command in your local host terminal: +# Using the Maven Wrapper script to bypass local system dependencies +.\mvnw clean package -DskipTests -### Step 3: Clone the Forked Repository -- Open your terminal or command prompt. -- Clone the forked repository to your local machine using the following command: - ```bash - git clone https://github.com/your-username/repo-name.git - ``` +The compiled output unit will be generated at: +- 📁 target/oraclequantapi-1.0.0.jar -### Step 4: Create a new branch -- Navigate to the cloned repository directory - ```bash - cd repo-name - ``` -- Create a new branch for your code submissions (Replace your-name with your name in your-name-submission-branch): - ```bash - git checkout -b your-name-submission-branch - ``` +# Execution & Deployment on Oracle Linux +1. Transfer Artifact: + - Securely copy the production bundle from your host system to your Oracle Linux VM using an SCP tool or terminal shortcut: + ```bash + java -jar oraclequantapi-1.0.0.jar --spring.datasource.url=jdbc:oracle:thin:@//192.168.100.191:1521/XEPDB1 + ``` + +2. Configure background Systemd Service + - To ensure the application runs continuously in production, package it into a system service file located at /etc/systemd/system/oracleapi.service: + ```bash + [Unit] + Description=Package Measurement Conversion REST API Service + After=syslog.target network.target + + [Service] + User=mariya + Group=mariya + WorkingDirectory=/home/mariya/Documents + ExecStart=/usr/bin/java -jar /home/mariya/Documents/oraclequantapi-1.0.0.jar + SuccessExitStatus=143 + Restart=always + RestartSec=10 + + [Install] + WantedBy=multi-user.target + ``` +3. Spin up the Service Engine + ```bash + # Refresh system configurations + sudo systemctl daemon-reload + + # Enable and start the service thread background worker + sudo systemctl enable oracleapi-service + sudo systemctl start oracleapi-service + ``` -### Step 5: Add Your Code -- Implement the API -### Step 6: Commit your changes -- Run the following commands in order to commit your changes: - ```bash - git add * - git commit -m "Meaningful commit message here" - ``` +## API Endpoints +Convert Measurements -### Step 7: Push Your Branch to GitHub -- Run the following commands to upload the changes to the forked github repository (Replace your-name with your name in your-name-submission-branch): +Method: GET + +Endpoint: /api/v1/convert-measurements + +Query Parameter: input= + +## Example Request ```bash - git push origin your-name-submission-branch - ``` + GET http://localhost:8080/api/v1/convert-measurements?input=abbcc + ``` + +## Response +```bash + [2, 6] + ``` -### Step 8: Create a Pull Request -- Go to your forked repository on GitHub. -- You should see a prompt to create a pull request. Click on "Compare & pull request". -- Provide a title and description for your pull request, then click "Create pull request". +## View Conversion Trace History +Method: GET -### Step 9: Notify Codeline -- Notify on slack that you have created a PR for your solution. +Endpoint: /api/v1/history -## Note: If you face any issues in the process above, Please do the following: -- Watch [this youtube tutorial](https://www.youtube.com/watch?v=a_FLqX3vGR4) -- Contact Ikhlas or Atyab. +Target URL: http://localhost:8080/api/v1/history