Skip to content

GDGoC-UTCN/jetbrains-task

Repository files navigation

GDGoC × JetBrains: The API Client Challenge

The developer community is constantly searching for faster, lighter tools. Recently, an elite R&D squad, cheered on by Kodee, our favorite Kotlin mascot, set out to build a native, ultra-lightweight API testing tool. The vision was clear: a blazingly fast, Kotlin-powered alternative to bulky API clients, using a strict Unidirectional Data Flow (UDF)architecture.

For those new to the domain: an Application Programming Interface (API) is a communication bridge that allows different software systems to talk to each other.

The UI/UX team delivered a locked-in interface for this tool. However, at the critical integration phase, the core logic engineers were reassigned. The project is stalled: the interface is there but inert—it renders empty screens and emits user Actions into the void. Kodee has recruited you to implement the engine and bring this tool to life.

Pre-Challenge Checks

Before you dive in, ensure your machine is set up correctly. This README covers prerequisites, how to run the project, and where to get help. Because the app uses system-level tools (e.g. curl), having them installed and on your PATH is critical.

If you hit JVM crashes, environment errors, or build failures, see debugging.md for step-by-step troubleshooting (IDE config, Windows env vars, macOS JDK setup).


Prerequisites

  • JDK 17 or 21
    Gradle and the project require JVM 17 or 21. We recommend Eclipse Temurin (free, open-source):
    https://adoptium.net/ — download JDK 17 for your OS.

  • curl
    The app runs HTTP requests by calling curl on your system. It must be on your PATH.

    • macOS: Usually pre-installed. If not: brew install curl.
    • Windows: Available on Windows 10+, or install curl for Windows.

How to Run the Project

We recommend using a terminal to build and run: the IntelliJ integrated terminal, or an external Bash (macOS/Linux) / PowerShell (Windows). This avoids IDE-run configuration issues and matches the commands below.

macOS / Linux

From the project root:

# Run the application
./gradlew run

# Build (compile)
./gradlew build

Windows

From the project root in PowerShell or Command Prompt:

# Run the application
.\gradlew.bat run

# Build (compile)
.\gradlew.bat build

Setting Up JVM 17 / 21 (JAVA_HOME)

If java -version does not show 17 or 21, or Gradle fails with “requires JVM 17", set JAVA_HOME and PATH as below. Install the JDK first from Adoptium if needed.

Windows

  1. Install JDK 17 from Adoptium.
  2. Windows key → type env → open Edit the system environment variablesEnvironment variables.
  3. Under System variables:
    • JAVA_HOME: Add or Edit → set to the JDK folder (e.g. C:\Program Files\Eclipse Adoptium\jdk-17.x.x-hotspot).
    • Path: Edit → remove old Java entries → New → add %JAVA_HOME%\bin and move it to the top.
  4. Click OK everywhere, then fully restart IntelliJ (File → Exit). Open a new terminal and run java -version.

Temporary (current terminal only) in PowerShell:

$env:JAVA_HOME = "C:\Program Files\Eclipse Adoptium\jdk-17.x.x-hotspot"   # your actual path
$env:Path = "$env:JAVA_HOME\bin;" + $env:Path
.\gradlew.bat run

macOS

  1. Install JDK 17 from Adoptium.
  2. In a terminal:
/usr/libexec/java_home -V

Pick the version (e.g. 17) from the list, then:

export JAVA_HOME=$(/usr/libexec/java_home -v 17)
export PATH="$JAVA_HOME/bin:$PATH"
java -version
  1. Then from the project root:
./gradlew --stop
./gradlew clean run

For persistent setup, add the export lines to your shell config (e.g. ~/.zshrc). More detail (including IDE settings) is in debugging.md.


Verify Prerequisites

  • Java 17 or 21:

    java -version

    You should see 17 or 21. If you see something else and the build fails, set JAVA_HOME as above. We strongly recommend Java 17.

  • curl:

    curl --version

Mission Parameters (What to Implement)

Your work is in the engine room: Business and Logic layers that handle user actions and update application State.

The Four Files You Need to Implement

You will implement logic in exactly four files:

File Role
StorageHelper.kt Loads and saves the list of API requests to/from disk (JSON). Runs on Dispatchers.IO. Handles missing or invalid files by returning an empty list.
RequestsViewModel.kt Holds the app’s main state: the list of requests, which one is active, and the current URL/Method/Headers/Body. Reacts to user actions (add, rename, delete, edit) and persists after every change.
ExecutionViewModel.kt Validates input (URL, headers JSON), triggers execution via CurlExecutor, and exposes running state and output (stdout/stderr) to the UI.
CurlExecutor.kt Runs the actual HTTP call by invoking the system curl command with the chosen method, URL, headers, and body. Streams output back to the caller.

Epic 1: Workspace & State Persistence

  • Implement StorageHelper.kt: loadRequests and saveRequests on Dispatchers.IO, pretty-printed JSON. If the file is missing or malformed, return an empty list.
  • RequestsViewModel: On startup, load saved requests; if none exist, create a default "New request", save it, set it active. On add/rename (ignore blank names), update state, set modified request active, save. On delete active, set active to the first remaining request, then save.

Epic 2: Reactive State Management

  • In RequestsViewModel, track URL, HTTP Method, Headers, Body in real time. Update the active request in the StateFlow and trigger a save via StorageHelper on every change.

Epic 3: System-Level Execution via curl

  • CurlExecutor.kt + ExecutionViewModel: Validate before run: URL must not be blank, Headers must be valid JSON; otherwise show clear errors (Error: URL is empty, Error: Headers must be valid JSON...) and exit code -1. Run curl -s -S -X <METHOD> <URL> with -H for headers and write body to the process for POST/PUT/PATCH. No concurrent runs (ignore Send when isRunning). While running, set status to "Sending...", clear previous output, stream stdout and stderr to outputContent.

Verification & Submission

  • Use Check Progress in the UI to run the local test suite. You need:
    • execution: 8/8
    • helpers: 7/7
    • viewmodel: 18/18
  • When all pass, use the Submit button in the UI and enter your email.

Troubleshooting

  • "Cannot find a Java installation matching: {languageVersion=17}"
    Gradle can auto-download JDK 17 on first build. If that fails (e.g. proxy), install Eclipse Temurin 17 and set JAVA_HOME as above.

  • Build fails on JDK 22+ / 25
    Gradle 8.5 runs on JDK 17–21 only. Use JDK 17 or 21 and point JAVA_HOME to it.

  • Process “stuck” at 96%
    Normal: the app is running. Closing the app lets the task reach 100%.

Full steps for IDE config, Windows env vars, and macOS JDK: debugging.md.

Submit Solution

  1. Click Submit solution in the status bar.
  2. Confirm and enter your email in the dialog.
  3. The app zips the project and sends it to the server.

How does this project work?

The app follows Model–View–ViewModel (MVVM) with a unidirectional data flow: the UI only observes state from the ViewModels and sends Actions (e.g. “add request”, “send request”); ViewModels update state and talk to the “engine” (storage and execution). The View never touches the model or I/O directly.

  • Model — Data and persistence: ApiRequest, ApiCollection, and the JSON format used by StorageHelper. No UI or business logic here.
  • View — Compose UI: ApiClientScreen and components (RequestPane, ResponsePane, RequestsPanel, StatusPanel, dialogs). They collect state from the ViewModels via collectAsState() / mutableStateOf and call ViewModel methods on user input.
  • ViewModel — Two ViewModels:
    • RequestsViewModel exposes StateFlow<List<ApiRequest>>, the selected request, and status. It handles list and selection changes and delegates load/save to StorageHelper.
    • ExecutionViewModel exposes isRunning, outputContent, and status. It validates input, calls CurlExecutor to run the request, and streams output back into state.

StorageHelper and CurlExecutor are not part of MVVM’s “Model” in the strict sense—they are service layers the ViewModels use to persist data and run HTTP. The diagram below summarizes the flow.

flowchart LR
    subgraph View["View (Compose UI)"]
        Screen[ApiClientScreen]
        RequestPane[RequestPane]
        ResponsePane[ResponsePane]
        RequestsPanel[RequestsPanel]
        StatusPanel[StatusPanel]
    end

    subgraph ViewModels["ViewModels"]
        RVM[RequestsViewModel]
        EVM[ExecutionViewModel]
    end

    subgraph ModelAndServices["Model & Services"]
        Model[(ApiRequest / ApiCollection)]
        Storage[StorageHelper]
        Curl[CurlExecutor]
    end

    Screen --> RVM
    Screen --> EVM
    RequestPane --> RVM
    ResponsePane --> EVM
    RequestsPanel --> RVM
    StatusPanel --> EVM

    RVM -->|"load / save"| Storage
    RVM -->|"read / write"| Model
    EVM -->|"execute"| Curl
    Curl -->|"stdout / stderr"| EVM
    Storage -->|"JSON"| Model
Loading

Flow in short: User acts in the View → ViewModel method is called → ViewModel updates its state (and may call StorageHelper or CurlExecutor) → View observes state and re-renders. No direct View → Model or View → disk/network.

Good luck—the launch depends on you!

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages