
# Java {/* #java */}

Platform API 토큰을 만들고 `platform.proto`를 받으려면 [gRPC 가이드](/docs/ko/api/grpc)부터 시작하세요. 클라이언트 계약은 `java_package = "dev.reconstruct.platform.v1"`을 설정하고 메시지별 Java 클래스를 생성합니다. 이 예시는 Gradle과 [gRPC Java protobuf 플러그인](https://github.com/grpc/grpc-java#generated-code)을 사용합니다.

`platform.proto`를 `src/main/proto/platform.proto`에 넣으세요. 다음 `build.gradle`을 추가하세요:

```groovy
plugins {
    id 'java'
    id 'application'
    id 'com.google.protobuf' version '0.9.5'
}

repositories { mavenCentral() }

def grpcVersion = '1.84.0'
dependencies {
    implementation "io.grpc:grpc-protobuf:${grpcVersion}"
    implementation "io.grpc:grpc-stub:${grpcVersion}"
    runtimeOnly "io.grpc:grpc-netty-shaded:${grpcVersion}"
    compileOnly 'javax.annotation:javax.annotation-api:1.3.2'
}

protobuf {
    protoc { artifact = 'com.google.protobuf:protoc:3.25.8' }
    plugins {
        grpc { artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}" }
    }
    generateProtoTasks {
        all()*.plugins { grpc {} }
    }
}

application { mainClass = 'dev.reconstruct.example.Main' }
```

Gradle은 프로젝트 빌드 시 메시지 클래스와 `PlatformServiceGrpc`를 생성합니다. 다음을 `src/main/java/dev/reconstruct/example/Main.java`로 저장하세요:

```java
package dev.reconstruct.example;

import dev.reconstruct.platform.v1.GetCatalogRequest;
import dev.reconstruct.platform.v1.ListCatalogsRequest;
import dev.reconstruct.platform.v1.PlatformServiceGrpc;
import io.grpc.Grpc;
import io.grpc.ManagedChannel;
import io.grpc.Metadata;
import io.grpc.TlsChannelCredentials;
import io.grpc.stub.MetadataUtils;
import java.util.concurrent.TimeUnit;

public final class Main {
    public static void main(String[] args) throws Exception {
        String token = System.getenv("CR_RECONSTRUCT_API_TOKEN");
        if (token == null || token.isBlank()) {
            throw new IllegalStateException("Set CR_RECONSTRUCT_API_TOKEN");
        }

        ManagedChannel channel = Grpc.newChannelBuilderForAddress(
            "reconstruct.dev", 443, TlsChannelCredentials.create()).build();
        try {
            Metadata headers = new Metadata();
            headers.put(Metadata.Key.of("authorization", Metadata.ASCII_STRING_MARSHALLER),
                "Bearer " + token);
            var client = PlatformServiceGrpc.newBlockingStub(channel)
                .withInterceptors(MetadataUtils.newAttachHeadersInterceptor(headers))
                .withDeadlineAfter(10, TimeUnit.SECONDS);

            var page = client.listCatalogs(ListCatalogsRequest.newBuilder().setPageSize(10).build());
            for (var catalog : page.getCatalogsList()) {
                var detail = client.getCatalog(GetCatalogRequest.newBuilder()
                    .setCatalogId(catalog.getCatalogId()).build());
                System.out.println(detail.getCatalogId() + ": " + detail.getDescription());
            }
        } finally {
            channel.shutdownNow();
        }
    }
}
```

`gradle run`을 실행하세요. Gradle wrapper가 있으면 `./gradlew run`을 사용하세요. 네이티브 gRPC는 `/api/v1` REST 경로가 아닌 TLS authority를 사용합니다.
