Dev project for practicing spring boot. This application combines the results of two GitHub REST API endpoints into a single response.
- Structure
- Spring Profiles
- Prerequisites
- Running the Application
- Automated Testing
- Future Improvements
This repository is organized using "hexagonal architecture" software design. The active GitHub Adapter is managed via spring profiles.
| Adapter | Description |
|---|---|
RestAdapter |
Exposes user retrieve via REST |
StubbedGitHubAdapter |
Stubbed, in-memory implemention of the GitHub Adapter that returns hard-coded stubbed respones rather than hitting the real server. Used for local testing. |
UnauthenticatedRestGitHubAdapter |
GitHub Adapter that sends unauthenticated requests to https://api.github.com. Unauthenticated requests may hit rate limits and only support public users/repositories. |
---
title: Hexagonal Architecture
---
flowchart LR
client((client))
RestAdapter[REST Adapter]
core{{core}}
GitHubAdapter[GitHub Adapter]
client --> RestAdapter
RestAdapter --> core
core --> GitHubAdapter
See Spring Boot Profiles.
| Profile | Description |
|---|---|
unauthenticated |
Replaces the stubbed GitHub Adaptor with a real implementation that sends unauthenticated requests to https://api.github.com. Unauthenticated requests may hit rate limits and only support public users/repositories. |
- Java 17
To run the Spring Boot application locally from the command line, you can use
the Gradle bootRun task.
./gradlew bootRun --args="--spring.profiles.active=unauthenticated"curl -sS localhost:8080/basepath/users/octocat | jq '.'
{
"user_name": "octocat",
"display_name": "The Octocat",
"avatar": "https://avatars.githubusercontent.com/u/583231?v=4",
"geo_location": "San Francisco",
"email": null,
"url": "https://api.github.com/users/octocat",
"created_at": "Tue, 25 Jan 2011 18:44:36 GMT",
"repos": [
{
"name": "boysenberry-repo-1",
"url": "https://api.github.com/repos/octocat/boysenberry-repo-1"
},
{
"name": "git-consortium",
"url": "https://api.github.com/repos/octocat/git-consortium"
},
{
"name": "hello-worId",
"url": "https://api.github.com/repos/octocat/hello-worId"
},
{
"name": "Hello-World",
"url": "https://api.github.com/repos/octocat/Hello-World"
},
{
"name": "linguist",
"url": "https://api.github.com/repos/octocat/linguist"
},
{
"name": "octocat.github.io",
"url": "https://api.github.com/repos/octocat/octocat.github.io"
},
{
"name": "Spoon-Knife",
"url": "https://api.github.com/repos/octocat/Spoon-Knife"
},
{
"name": "test-repo1",
"url": "https://api.github.com/repos/octocat/test-repo1"
}
]
}$ ./gradlew testThe Test Summary Report is generated at build/reports/tests/test/index.html.
- Remaining unit tests, component tests, itests
- Mock server tests for the GitHub client
- Add in-memory caching to the GitHub client to reduce rate limiting when unauthenticated
- Custom error response model
- Better validation of
usernameparameter - More edge case testing, specifically with the GitHub response bodies
- Define, publish OpenAPI spec, client libraries for the REST endpoint
- Use library for the GitHub response models
- Better handling of different status codes from GitHub, e.g.
- Return 503 when GitHub returns 503
- Error response body includes warning when GitHub rate limit is reached
- Add support for authenticated requests to GitHub, private respositories
- Support more flags for
/users/{username}/reposGitHub request, e.g.type,sort,direction, and paging - Automatically retry retryable (5xx) GitHub failures
- Introduce business exceptions rather than bubbling up
RestClientException - Add Jacoco. Update tests to full coverage. Enforce code coverage minimum in full build.
- Publish docker image
- Implement HealthIndicator for GitHub client
- Support build, test, publish in CI
- Security scanning