{"id":51091433,"url":"https://github.com/suprim-corp/kit-backend-base-java","last_synced_at":"2026-06-24T02:32:28.273Z","repository":{"id":357520351,"uuid":"1205660746","full_name":"suprim-corp/kit-backend-base-java","owner":"suprim-corp","description":"Reusable Java backend toolkit — UUID, JSON, crypto, exception, web \u0026 gRPC (dev.suprim)","archived":false,"fork":false,"pushed_at":"2026-05-13T05:00:05.000Z","size":99,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-13T06:38:12.592Z","etag":null,"topics":["backend","cryptography","exception-handling","grpc","java","java-library","json","maven","spring-boot","utilities"],"latest_commit_sha":null,"homepage":"https://suprim.dev","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/suprim-corp.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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-09T06:59:01.000Z","updated_at":"2026-05-13T04:59:01.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/suprim-corp/kit-backend-base-java","commit_stats":null,"previous_names":["suprim-corp/kit-backend-base-java"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/suprim-corp/kit-backend-base-java","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/suprim-corp%2Fkit-backend-base-java","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/suprim-corp%2Fkit-backend-base-java/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/suprim-corp%2Fkit-backend-base-java/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/suprim-corp%2Fkit-backend-base-java/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/suprim-corp","download_url":"https://codeload.github.com/suprim-corp/kit-backend-base-java/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/suprim-corp%2Fkit-backend-base-java/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34714992,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-24T02:00:07.484Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["backend","cryptography","exception-handling","grpc","java","java-library","json","maven","spring-boot","utilities"],"created_at":"2026-06-24T02:32:27.449Z","updated_at":"2026-06-24T02:32:28.268Z","avatar_url":"https://github.com/suprim-corp.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Kit Java Backend Library\n\n[![CI](https://github.com/suprim-corp/kit-backend-base-java/actions/workflows/ci.yml/badge.svg)](https://github.com/suprim-corp/kit-backend-base-java/actions/workflows/ci.yml)\n[![](https://jitpack.io/v/suprim-corp/kit-backend-base-java.svg)](https://jitpack.io/#suprim-corp/kit-backend-base-java)\n[![codecov](https://codecov.io/gh/suprim-corp/kit-backend-base-java/branch/main/graph/badge.svg)](https://codecov.io/gh/suprim-corp/kit-backend-base-java)\n![Java](https://img.shields.io/badge/Java-17+-orange?logo=openjdk)\n![Maven](https://img.shields.io/badge/Maven-3.9+-blue?logo=apachemaven)\n![License](https://img.shields.io/badge/License-MIT-green)\n\nReusable backend utilities for Java applications.\n\n## Modules\n\n| Module             | Description                                        | Dependencies                    |\n|--------------------|----------------------------------------------------|---------------------------------|\n| `kit-java-core`      | UUID generation, string utilities, data validation | java-uuid-generator             |\n| `kit-java-json`      | Jackson-based JSON utilities                       | kit-java-core, jackson            |\n| `kit-java-exception` | Exception framework with error codes               | kit-java-core                     |\n| `kit-java-crypto`    | AES-256-GCM encryption, HKDF key derivation        | (none)                          |\n| `kit-java-web`       | HTTP utilities, responses, trace propagation       | kit-java-core, kit-java-exception   |\n| `kit-java-grpc`      | gRPC utilities, exception mapping, trace propagation | kit-java-exception, grpc, protobuf|\n\n## Installation\n\nAdd the JitPack repository and dependencies to your `pom.xml`:\n\n```xml\n\u003crepositories\u003e\n    \u003crepository\u003e\n        \u003cid\u003ejitpack.io\u003c/id\u003e\n        \u003curl\u003ehttps://jitpack.io\u003c/url\u003e\n    \u003c/repository\u003e\n\u003c/repositories\u003e\n```\n\nThen add the modules you need:\n\n```xml\n\u003c!-- Core utilities --\u003e\n\u003cdependency\u003e\n    \u003cgroupId\u003edev.suprim\u003c/groupId\u003e\n    \u003cartifactId\u003ekit-java-core\u003c/artifactId\u003e\n    \u003cversion\u003e1.1.0\u003c/version\u003e\n\u003c/dependency\u003e\n\n\u003c!-- JSON utilities --\u003e\n\u003cdependency\u003e\n    \u003cgroupId\u003edev.suprim\u003c/groupId\u003e\n    \u003cartifactId\u003ekit-java-json\u003c/artifactId\u003e\n    \u003cversion\u003e1.1.0\u003c/version\u003e\n\u003c/dependency\u003e\n\n\u003c!-- Exception framework --\u003e\n\u003cdependency\u003e\n    \u003cgroupId\u003edev.suprim\u003c/groupId\u003e\n    \u003cartifactId\u003ekit-java-exception\u003c/artifactId\u003e\n    \u003cversion\u003e1.1.0\u003c/version\u003e\n\u003c/dependency\u003e\n\n\u003c!-- Crypto utilities --\u003e\n\u003cdependency\u003e\n    \u003cgroupId\u003edev.suprim\u003c/groupId\u003e\n    \u003cartifactId\u003ekit-java-crypto\u003c/artifactId\u003e\n    \u003cversion\u003e1.1.0\u003c/version\u003e\n\u003c/dependency\u003e\n\n\u003c!-- Web utilities --\u003e\n\u003cdependency\u003e\n    \u003cgroupId\u003edev.suprim\u003c/groupId\u003e\n    \u003cartifactId\u003ekit-java-web\u003c/artifactId\u003e\n    \u003cversion\u003e1.1.0\u003c/version\u003e\n\u003c/dependency\u003e\n\n\u003c!-- gRPC utilities --\u003e\n\u003cdependency\u003e\n    \u003cgroupId\u003edev.suprim\u003c/groupId\u003e\n    \u003cartifactId\u003ekit-java-grpc\u003c/artifactId\u003e\n    \u003cversion\u003e1.1.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n## Quick Start\n\n### UUID Generation\n\n```java\nimport dev.suprim.kit.core.UUIDUtils;\n\n// Random UUID v4\nUUID id = UUIDUtils.v4();\n\n// Time-ordered UUID v7 (better for database indexes)\nUUID timeId = UUIDUtils.v7();\n```\n\n### JSON Utilities\n\n```java\nimport dev.suprim.kit.json.JsonUtils;\n\n// Serialize to JSON\nString json = JsonUtils.toJsonString(object);\n\n// Deserialize from JSON\nMyClass obj = JsonUtils.fromJson(json, MyClass.class);\n\n// Convert to/from Map\nMap\u003cString, Object\u003e map = JsonUtils.toMap(object);\nMyClass obj = JsonUtils.fromMap(map, MyClass.class);\n```\n\n### Exception Handling\n\n```java\nimport dev.suprim.kit.exception.*;\n\n// ApiException (checked) - requires throws declaration\nthrow new ApiException(ApiStatus.NOT_FOUND);\nthrow new ApiException(ApiStatus.NOT_FOUND, \"User not found\");\n\n// ApiRuntimeException (unchecked) - no throws required\nthrow new ApiRuntimeException(ApiStatus.UNAUTHORIZED);\n\n// Static factory methods\nthrow ApiException.notFound(\"User not found\");\nthrow ApiException.badRequest(\"Invalid email format\");\nthrow ApiException.unauthorized(\"Token expired\");\n\n// With data payload\nthrow ApiException.validationError(\"Validation failed\", errors);\n\n// Builder pattern\nthrow ApiException.builder()\n    .errorCode(ApiStatus.FORBIDDEN)\n    .message(\"Access denied\")\n    .data(details)\n    .build();\n\n// Convert checked to unchecked\nthrow apiException.toUnchecked();\n```\n\n#### ApiStatus Codes\n\n| Code | Status          | Message                                               |\n|------|-----------------|-------------------------------------------------------|\n| 1    | SUCCESS         | Success!                                              |\n| 99   | SERVER_ERROR    | The server is being upgraded, please try again later! |\n| 400  | INVALID_REQUEST | Invalid request!                                      |\n| 401  | UNAUTHORIZED    | Unauthorized!                                         |\n| 403  | FORBIDDEN       | Forbidden!                                            |\n| 404  | NOT_FOUND       | Not found!                                            |\n| 409  | CONFLICT        | Conflict!                                             |\n| 503  | NOT_CONFIGURED  | Service not configured!                               |\n\nAll responses return HTTP 200, with the status code in the response body.\n\n### Crypto Utilities\n\n```java\nimport dev.suprim.kit.crypto.SecretUtils;\n\n// Create from environment key\nSecretUtils crypto = SecretUtils.fromBase64Key(System.getenv(\"MASTER_KEY\"));\n\n// Encrypt with per-secret key derivation\nUUID secretId = UUID.randomUUID();\nbyte[] plaintext = \"sensitive data\".getBytes();\nSecretUtils.EncryptedSecret encrypted = crypto.encrypt(plaintext, secretId, null);\n\n// Decrypt\nbyte[] decrypted = crypto.decrypt(encrypted, secretId, null);\n\n// With AAD (Additional Authenticated Data)\nbyte[] aad = \"tenant:123\".getBytes();\nencrypted = crypto.encrypt(plaintext, secretId, aad);\ndecrypted = crypto.decrypt(encrypted, secretId, aad);\n\n// Generate new master key\nString newKey = SecretUtils.generateBase64Key();\n```\n\n### Web Utilities\n\n```java\nimport dev.suprim.kit.web.*;\nimport dev.suprim.kit.web.response.*;\n\n// Get client IP (handles proxy headers)\nString ip = RequestUtils.getClientIpAddress(request);\n\n// Extract Bearer token\nString token = RequestUtils.extractBearerToken(request);\n\n// Extract domain from request (X-Forwarded-Host \u003e Origin \u003e Referer \u003e Host)\nString domain = DomainUtils.extractDomain(request);\n\n// HTTP constants\nString contentType = HttpConstants.CONTENT_TYPE_JSON;\nString authHeader = HttpConstants.HEADER_AUTHORIZATION;\n\n// API responses\nBaseResponse\u003cVoid\u003e ok = BaseResponse.success();\nBaseResponse\u003cUser\u003e response = BaseResponse.success(user);\nBaseResponse\u003cVoid\u003e error = new BaseResponse\u003c\u003e(ApiStatus.NOT_FOUND, \"User not found\");\n\n// Paginated responses\nPaginatedResponse\u003cItem\u003e paginated = new PaginatedResponse\u003c\u003e(items, totalCount, pageable);\n\n// Validation errors\nValidationError error = new ValidationError(\"email\", \"Invalid format\");\n```\n\n### Trace Propagation (HTTP)\n\n```java\nimport dev.suprim.kit.web.context.*;\n\n// Register the filter (Spring Boot)\n@Bean\nFilterRegistrationBean\u003cRequestContextFilter\u003e requestContextFilter() {\n    FilterRegistrationBean\u003cRequestContextFilter\u003e registration = new FilterRegistrationBean\u003c\u003e(new RequestContextFilter());\n    registration.setOrder(Ordered.HIGHEST_PRECEDENCE);\n    return registration;\n}\n\n// Access trace/request ID anywhere in the request thread\nOptional\u003cString\u003e traceId = RequestContext.getTraceId();\nOptional\u003cString\u003e requestId = RequestContext.getRequestId();\n\n// Propagate context to async tasks\nExecutorService executor = Executors.newFixedThreadPool(4);\nexecutor.submit(ContextPropagation.wrap(() -\u003e {\n    // RequestContext and MDC are available here\n    String trace = RequestContext.getTraceId().orElse(\"unknown\");\n}));\n```\n\nThe filter automatically:\n- Extracts `X-Trace-ID` and `X-Request-ID` from incoming headers (or generates UUID v7 if absent)\n- Stores them in `RequestContext` (ThreadLocal) and SLF4J MDC (`traceId`, `requestId`)\n- Sets `X-Trace-ID` and `X-Request-ID` response headers\n- Cleans up after request completes\n\n### Trace Propagation (gRPC)\n\n```java\nimport dev.suprim.kit.grpc.*;\n\n// Server-side: extract trace context from incoming metadata\nServer server = ServerBuilder.forPort(9090)\n    .addService(new MyServiceImpl())\n    .intercept(new ContextPropagationInterceptor())\n    .intercept(new ExceptionInterceptor())\n    .build();\n\n// Client-side: forward trace context to outgoing calls\nManagedChannel channel = ManagedChannelBuilder.forTarget(\"localhost:9090\")\n    .intercept(new ContextForwardingInterceptor())\n    .build();\n\n// Access context in service implementation\nString traceId = GrpcContext.getTraceId();\nString requestId = GrpcContext.getRequestId();\n```\n\n`ContextPropagationInterceptor` extracts `x-trace-id`, `x-request-id`, `x-user-id`, `x-tenant-id` from gRPC metadata, attaches to gRPC Context, and sets SLF4J MDC for log correlation.\n\n`ContextForwardingInterceptor` forwards these values from the current gRPC Context to outgoing call metadata for service-to-service propagation.\n\n### gRPC Utilities\n\n```java\nimport dev.suprim.kit.grpc.*;\nimport dev.suprim.kit.exception.*;\nimport io.grpc.*;\n\n// Map HTTP status to gRPC Status\nStatus grpcStatus = GrpcStatusMapper.fromHttpStatus(404); // NOT_FOUND\nint httpStatus = GrpcStatusMapper.toHttpStatus(Status.PERMISSION_DENIED); // 403\n\n// Convert exceptions to gRPC StatusRuntimeException\nApiRuntimeException apiEx = ApiRuntimeException.notFound(\"User not found\");\nStatusRuntimeException grpcEx = ExceptionInterceptor.toStatusException(apiEx);\n\n// Add exception interceptor to server\nServer server = ServerBuilder.forPort(9090)\n    .addService(new MyServiceImpl())\n    .intercept(new ExceptionInterceptor())\n    .build();\n\n// Work with metadata\nMetadata metadata = MetadataUtils.withRequestId(\"req-123\");\nString reqId = MetadataUtils.getString(metadata, MetadataUtils.REQUEST_ID);\n```\n\n## Requirements\n\n- Java 17+\n- Maven 3.9+\n\n## Building\n\n```bash\nmvn clean install\n```\n\n## Running Tests\n\n```bash\nmvn test\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsuprim-corp%2Fkit-backend-base-java","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsuprim-corp%2Fkit-backend-base-java","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsuprim-corp%2Fkit-backend-base-java/lists"}