{ "assetKey": "a11-f004-number-bytes", "kind": "terminal", "command": "set -e\nD=$(mktemp -d); trap 'rm -rf \"$D\"' EXIT\nH=/shared/codebase/clean-architecture-backend-template/src/adapter/outbound/httpclient\nJAR=$H/build/libs/httpclient-0.0.1+21234e38cdb9.jar\nCACHE=/root/.gradle/caches/modules-2/files-2.1\ncp=\"\"\nwhile IFS= read -r line; do\n coord=${line%%=*}; confs=${line#*=}\n case \",$confs,\" in *\",runtimeClasspath,\"*) ;; *) continue ;; esac\n group=${coord%%:*}; rest=${coord#*:}; name=${rest%%:*}; ver=${rest##*:}\n jar=$(find \"$CACHE/$group/$name/$ver\" -name '*.jar' ! -name '*sources*' ! -name '*javadoc*' 2>/dev/null | head -1)\n [ -n \"$jar\" ] && cp=\"$cp:$jar\"\ndone < <(grep -E '^[a-zA-Z0-9._-]+:[^=]+=' \"$H/gradle.lockfile\")\nCP=\"$JAR${cp}\"\njava -version 2>&1 | head -1\ncat > \"$D/ReplayabilityProbe.java\" <<'JAVA'\nimport dev.caskeleton.adapter.outbound.httpclient.api.body.ObjectBody;\nimport java.io.ByteArrayOutputStream;\nimport java.io.OutputStream;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.concurrent.atomic.AtomicLong;\nimport java.util.concurrent.atomic.DoubleAccumulator;\nimport java.util.concurrent.atomic.DoubleAdder;\nimport java.util.concurrent.atomic.LongAccumulator;\nimport java.util.concurrent.atomic.LongAdder;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.HttpOutputMessage;\nimport org.springframework.http.MediaType;\nimport org.springframework.http.converter.HttpMessageConverter;\nimport org.springframework.http.converter.json.JacksonJsonHttpMessageConverter;\nimport org.springframework.web.client.RestClient;\n\npublic final class ReplayabilityProbe {\n\n /** A DTO of the shape the platform is built around, with a counter in it. */\n public record Order(String id, AtomicInteger attempt) {}\n\n public record Basket(String id, List lines) {}\n\n private static final JacksonJsonHttpMessageConverter JSON =\n new JacksonJsonHttpMessageConverter();\n\n private static String verdict(Object value) {\n return ObjectBody.json(value).replayability().toString();\n }\n\n /** Encodes through the converter a default RestClient uses for a JSON body. */\n private static byte[] encode(Object value) throws Exception {\n ByteArrayOutputStream sink = new ByteArrayOutputStream();\n JSON.write(\n value,\n MediaType.APPLICATION_JSON,\n new HttpOutputMessage() {\n @Override\n public OutputStream getBody() {\n return sink;\n }\n\n @Override\n public HttpHeaders getHeaders() {\n return new HttpHeaders();\n }\n });\n return sink.toByteArray();\n }\n\n public static void main(String[] args) throws Exception {\n System.out.println(\"[요청 본문을 인코딩하는 변환기] RestClient 기본 목록\");\n RestClient.create()\n .mutate()\n .messageConverters(\n converters ->\n converters.stream()\n .filter(c -> c.canWrite(Order.class, MediaType.APPLICATION_JSON))\n .forEach(c -> System.out.println(\" \" + c.getClass().getName())));\n System.out.println();\n\n System.out.println(\"[java.util.concurrent.atomic 의 Number 하위 타입]\");\n Object[] mutables = {\n new AtomicInteger(1), new AtomicLong(1L), new LongAdder(), new DoubleAdder(),\n new LongAccumulator(Long::sum, 0L), new DoubleAccumulator(Double::sum, 0d),\n };\n for (Object mutable : mutables) {\n System.out.printf(\n \" %-20s Number 상속 %-5s 판정 %s%n\",\n mutable.getClass().getSimpleName(), mutable instanceof Number, verdict(mutable));\n }\n System.out.println();\n\n System.out.println(\"[상자 원시형과 원자 계열 사이에 남는 둘]\");\n java.math.BigInteger bigInteger = new java.math.BigInteger(\"7\");\n java.math.BigDecimal bigDecimal = new java.math.BigDecimal(\"7.5\");\n bigInteger.add(java.math.BigInteger.ONE);\n bigDecimal.add(java.math.BigDecimal.ONE);\n System.out.println(\" BigInteger add 뒤 자기 값 \" + bigInteger + \" 판정 \" + verdict(bigInteger));\n System.out.println(\" BigDecimal add 뒤 자기 값 \" + bigDecimal + \" 판정 \" + verdict(bigDecimal));\n AtomicInteger counter = new AtomicInteger(7);\n counter.incrementAndGet();\n System.out.println(\" AtomicInteger increment 뒤 자기 값 \" + counter\n + \" 판정 \" + verdict(counter));\n System.out.println();\n\n System.out.println(\"[성분에 카운터를 둔 record]\");\n Order order = new Order(\"A-1\", new AtomicInteger(1));\n ObjectBody body = ObjectBody.json(order);\n byte[] first = encode(body.value());\n System.out.println(\" 판정 : \" + body.replayability());\n System.out.println(\" 첫 인코딩 : \" + new String(first));\n order.attempt().incrementAndGet();\n byte[] second = encode(body.value());\n System.out.println(\" 다시 인코딩 : \" + new String(second));\n System.out.println(\" 판정(그대로) : \" + body.replayability());\n System.out.println(\" 같은 바이트인가 : \" + java.util.Arrays.equals(first, second));\n System.out.println();\n\n System.out.println(\"[검사가 잡는 쪽]\");\n List held = new ArrayList<>(List.of(\"a\"));\n System.out.println(\" ArrayList 자체 판정 \" + verdict(held));\n System.out.println(\" ArrayList 를 감싼 record 판정 \" + verdict(new Basket(\"B-1\", held)));\n System.out.println(\" List.of 를 감싼 record 판정 \" + verdict(new Basket(\"B-2\", List.of(\"a\"))));\n }\n}\nJAVA\njavac -encoding UTF-8 -cp \"$CP\" -d \"$D\" \"$D/ReplayabilityProbe.java\"\njava -Dstdout.encoding=UTF-8 -cp \"$CP:$D\" ReplayabilityProbe\n", "cwd": "/shared/codebase/clean-architecture-backend-template/src/adapter/outbound/httpclient", "exitCode": 0, "executedAt": "2026-09-02T13:29:59+00:00", "sourceRevision": "21234e38cdb9a926cbc92bb97a2aee2e4a7d2916", "raw": "evidence/raw/a11-f004-number-bytes.txt", "svg": "evidence/rendered/a11-f004-number-bytes.svg", "rawSha256": "186280627ec9e702e793df81b3246c784304a524a50a8d5b4af6651068a82ddb", "lines": 35, "redaction": "none — 밀폐 탐침 실행 출력, 자격증명 없음" }