{"id":15068900,"url":"https://github.com/raeperd/realworld-springboot-java","last_synced_at":"2025-04-09T16:16:45.708Z","repository":{"id":44093324,"uuid":"356301508","full_name":"raeperd/realworld-springboot-java","owner":"raeperd","description":"Spring boot java implementation of realworld example.app","archived":false,"fork":false,"pushed_at":"2024-01-10T05:24:35.000Z","size":1393,"stargazers_count":209,"open_issues_count":0,"forks_count":82,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-09T16:16:37.823Z","etag":null,"topics":["github-action","jacoco-plugin","java11","jib-gradle","lombok-gradle","sonarcloud","spring-boot","spring-data-jpa"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/raeperd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-04-09T14:37:10.000Z","updated_at":"2025-03-31T23:13:26.000Z","dependencies_parsed_at":"2024-10-13T03:40:54.787Z","dependency_job_id":"c6aacc62-f93d-4a66-9741-2c24fdad0c6e","html_url":"https://github.com/raeperd/realworld-springboot-java","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raeperd%2Frealworld-springboot-java","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raeperd%2Frealworld-springboot-java/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raeperd%2Frealworld-springboot-java/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raeperd%2Frealworld-springboot-java/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/raeperd","download_url":"https://codeload.github.com/raeperd/realworld-springboot-java/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248065285,"owners_count":21041872,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["github-action","jacoco-plugin","java11","jib-gradle","lombok-gradle","sonarcloud","spring-boot","spring-data-jpa"],"created_at":"2024-09-25T01:39:40.071Z","updated_at":"2025-04-09T16:16:45.670Z","avatar_url":"https://github.com/raeperd.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n![RealWorld example apps cover](./doc/image/realworld-cover.png)\n[![Build](https://github.com/raeperd/realworld-springboot-java/actions/workflows/build.yml/badge.svg)](https://github.com/raeperd/realworld-springboot-java/actions/workflows/build.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n[ReadWorld.io](https://github.com/gothinkster/realworld) backend project using spring boot java using `spring-security`, `spring-data-jpa`\n\n# Insprired by\n\n- [우아한형제들 기술 불로그 | Todo list 만들기는 이제 그만](https://woowabros.github.io/experience/2020/04/14/stop-making-todo-list.html)\n- [우아한형제들 기술 블로그 | Gradle 프로젝트에 JaCoCo 설정하기](https://woowabros.github.io/experience/2020/02/02/jacoco-config-on-gradle-project.html)\n- [우아한형제들 기술 블로그 | 우린 Git-flow를 사용하고 있어요](https://woowabros.github.io/experience/2017/10/30/baemin-mobile-git-branch-strategy.html)\n- [Github | Realworld.io](https://github.com/gothinkster/realworld)\n\n\n # Getting started\n\n ## Build from scratch\n ``` shell\n $ ./gradlew build bootRun\n ```\n\n ## Using docker\n ``` shell\n $ docker run --rm -p 8080:8080 ghcr.io/raeperd/realworld-spring-boot-java:master\n ```\n\n- Dockerhub registry is [here](https://hub.docker.com/repository/docker/raeperd/realworld-spring-boot-java)  \n- Container tags are simply branch name of this repository following git-flow strategy\n\n\n\n## How to test \n\nAfter run application, you can try one of followings\n\n### using shell script\n\n``` shell\n$ ./doc/run-api-tests.sh\n```\n\n### using postman \n\nImport [`./doc/Conduit.postman_collection.json`](./doc/Conduit.postman_collection.json) in your postman application \n\n\n\nAnd also, pure `gradle test` covers almost every line of code.\n\nMore details can be found in [`./doc/README.md`](./doc/README.md) and  [original source](https://github.com/gothinkster/realworld/tree/master/spec)\n\n# Overview\n\n## Design Principal\n\n- Always `final` whenever possible\n- Always package private class whenever possible\n- **Always test every package, class, method, instruction in codes**\n  - Except for some boilerplate `equals` and `hashcode` method\n  - This is validated by [jacoco-gradle-plugin](https://docs.gradle.org/current/userguide/jacoco_plugin.html).\n  - Coverage verification in [`./test.gradle`](./test.gradle)\n- Try to avoid including additional dependencies as much as possible\n  - Implements JWT generation / validation logic without 3rd party library [#3](https://github.com/raeperd/realworld-springboot-java/issues/3)\n- Try to maintain codes in domain package remain POJO\n  - Except for special spring annotations like `@Service`, `@Repository`, `@Transactional`\n  - Prohibit use of lombok in domain package\n- Try to follow all modern best practices for spring-boot project\n  \n## Diagrams \n\n- You can open full diagram file in [`realworld.drawio`](./realworld.drawio) using [draw.io](https://app.diagrams.net/)\n\n### User\n\n![realworld-User](./doc/image/realworld-User.png)\n\n- Separate password encoding logic out of User.\n- User must be created with password encoder.\n\n### Article\n\n![realworld-Article](./doc/image/realworld-Article.png)\n\n- Article contains other elements with `@Embedded` classes\n- Try to reduce number of repositories.\n- Prefer `@JoinTable` to `@JoinColumn`\n\n### JWT \n\n![realworld-Jwt](./doc/image/realworld-Jwt.png)\n\n- Try not to use 3rd party library\n- Serialization and Deserialization are seperated with interfaces\n- Domain package contains interface, infrastructure code provide implementation  \n- Application package do stuff with spring-security logic\n\n## Performance\n\n![performance](./doc/image/performance.png)\n\n- Result of [`./doc/run-api-tests.sh`](./doc/run-api-tests.sh)\n\n# What can be done more\n\n- User class doing so many things now. It can be improved someway.\n- Service classes can be divided into smaller services\n- Test cases order can be improved\n\n# Contact\n\nYou can contact me with [email](raeperd117@gmail.com) or issue in this project\n\n# License\n[MIT License](./LICENSE)\n\n# Referenced\n\n- [JSON Web Token Introduction - jwt.io](https://jwt.io/introduction)  \n- [Symmetric vs Asymmetric JWTs. What is JWT? | by Swayam Raina | Noteworthy - The Journal Blog](https://blog.usejournal.com/symmetric-vs-asymmetric-jwts-bd5d1a9567f6)\n- [presentations/auth.md at master · alex996/presentations · GitHub](https://github.com/alex996/presentations/blob/master/auth.md)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fraeperd%2Frealworld-springboot-java","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fraeperd%2Frealworld-springboot-java","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fraeperd%2Frealworld-springboot-java/lists"}