# Alternate to "tctl admin cluster add-search-attributes" to add new search attributes

**URL:** <https://community.temporal.io/t/alternate-to-tctl-admin-cluster-add-search-attributes-to-add-new-search-attributes/3850>\
**Category:** Community Support\
**Tags:** java-sdk\
**Created:** [January 28, 2022, 11:57am UTC](https://community.temporal.io/t/alternate-to-tctl-admin-cluster-add-search-attributes-to-add-new-search-attributes/3850 "2022-01-28T11:57:14Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![Vikas\_NS](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/vikas_ns/32/1210_2.png) [@Vikas\_NS](https://community.temporal.io/u/Vikas_NS)\
**Post date:** [January 28, 2022, 11:57am UTC](https://community.temporal.io/t/alternate-to-tctl-admin-cluster-add-search-attributes-to-add-new-search-attributes/3850/1 "2022-01-28T11:57:14Z")

</div>

**Usecase**  
Want to add custom search attributes.  
I’m currently doing it with the below command  
`tctl admin cluster add-search-attributes --name mySA --type String`

**Question**  
Is there any other way to do the same?  
As I won’t be allowed to execute commands in higher environments.

---

<div class="post-metadata">

**Author:** ![tihomir](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/tihomir/32/6580_2.png) [@tihomir](https://community.temporal.io/u/tihomir)\
**Post date:** [January 28, 2022, 4:30pm UTC](https://community.temporal.io/t/alternate-to-tctl-admin-cluster-add-search-attributes-to-add-new-search-attributes/3850/2 "2022-01-28T16:30:20Z")

</div>

It’s not exposed via SDKs currently, but the the admin service api is available [here](https://pkg.go.dev/go.temporal.io/server/api/adminservice/v1).

You would have to create a [gRPC client](https://pkg.go.dev/google.golang.org/grpc)  
to call

`NewAdminServiceClient` and use `AddSearchAttributesRequest`

like hows done in tctl [here](https://github.com/temporalio/tctl/blob/main/cli_curr/admin_cluster_search_attributes_commands.go#L48).

---

<div class="post-metadata">

**Author:** ![alex](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/alex/32/15_2.png) [@alex](https://community.temporal.io/u/alex)\
**Post date:** [January 30, 2022, 7:58am UTC](https://community.temporal.io/t/alternate-to-tctl-admin-cluster-add-search-attributes-to-add-new-search-attributes/3850/3 "2022-01-30T07:58:29Z")

</div>

We are currently working on exposing this functionality to SDKs. For now, the only way is to use `tctl` ro call Admin API as @tihomir pointed out.

---

<div class="post-metadata">

**Author:** ![Vikas\_NS](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/vikas_ns/32/1210_2.png) [@Vikas\_NS](https://community.temporal.io/u/Vikas_NS)\
**Post date:** [February 1, 2022, 7:05am UTC](https://community.temporal.io/t/alternate-to-tctl-admin-cluster-add-search-attributes-to-add-new-search-attributes/3850/4 "2022-02-01T07:05:14Z")

</div>

I’m trying to create client for only the add search attributes call.

Below is my proto file

```auto
syntax = "proto3";

package grpc.bc.cd.health;
option java_multiple_files = true;

message AddSearchAttributesRequest {
    map<string, temporal.api.enums.v1.IndexedValueType> search_attributes = 1;
    string index_name = 2;
    bool skip_schema_update = 3;
}

message AddSearchAttributesResponse {
}

service AdminService {
rpc AddSearchAttributes (AddSearchAttributesRequest) returns (AddSearchAttributesResponse) {
    }
}

```

From where can I get this → temporal.api.enums.v1.IndexedValueType ?

---

<div class="post-metadata">

**Author:** ![tihomir](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/tihomir/32/6580_2.png) [@tihomir](https://community.temporal.io/u/tihomir)\
**Post date:** [February 1, 2022, 4:32pm UTC](https://community.temporal.io/t/alternate-to-tctl-admin-cluster-add-search-attributes-to-add-new-search-attributes/3850/5 "2022-02-01T16:32:40Z")

</div>

> From where can I get this → temporal.api.enums.v1.IndexedValueType ?

> <https://github.com/temporalio/api/blob/master/temporal/api/enums/v1/common.proto#L40>

---

<div class="post-metadata">

**Author:** ![Vikas\_NS](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/vikas_ns/32/1210_2.png) [@Vikas\_NS](https://community.temporal.io/u/Vikas_NS)\
**Post date:** [February 1, 2022, 5:51pm UTC](https://community.temporal.io/t/alternate-to-tctl-admin-cluster-add-search-attributes-to-add-new-search-attributes/3850/6 "2022-02-01T17:51:50Z")

</div>

That fixed the problem and I was able to generate the Java classes.

Below is my code. I’m getting Exception in thread “main” io.grpc.StatusRuntimeException: UNKNOWN. Want to confirm whether this code is good? I’m new to gRPC.

```
    ManagedChannel channel = ManagedChannelBuilder.forTarget("my-temporal-url")
            .usePlaintext()
            .build();

    AdminServiceGrpc.AdminServiceBlockingStub adminServiceBlockingStub = AdminServiceGrpc.newBlockingStub(channel);

    adminServiceBlockingStub.addSearchAttributes(
            Temporaladmin.AddSearchAttributesRequest
                    .newBuilder()
                    .putSearchAttributes("MySearchAttrKey", Temporaladmin.IndexedValueType.INDEXED_VALUE_TYPE_BOOL)
            .build()
    );

```

I also tried to create the channel like below but same error.

```auto
public ManagedChannel getChannel() {
        NettyChannelBuilder builder =
                NettyChannelBuilder.forTarget("my-temporal-url")
                        .defaultLoadBalancingPolicy("round_robin")
                        .maxInboundMessageSize(25_000_000)
                        .usePlaintext();
        return builder.build();
    }

```

---

<div class="post-metadata">

**Author:** ![tihomir](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/tihomir/32/6580_2.png) [@tihomir](https://community.temporal.io/u/tihomir)\
**Post date:** [February 1, 2022, 6:57pm UTC](https://community.temporal.io/t/alternate-to-tctl-admin-cluster-add-search-attributes-to-add-new-search-attributes/3850/7 "2022-02-01T18:57:43Z")

</div>

Using NettyChannelBuilder should work. See how it’s used [here](https://github.com/temporalio/sdk-java/blob/master/temporal-serviceclient/src/main/java/io/temporal/serviceclient/WorkflowServiceStubsImpl.java#L123).

Wondering about `"my-temporal-url"`, are you able to perform a health check on your channel once its created, for example [here](https://github.com/temporalio/sdk-java/blob/master/temporal-serviceclient/src/main/java/io/temporal/serviceclient/WorkflowServiceStubsImpl.java#L272).

---

<div class="post-metadata">

**Author:** ![Vikas\_NS](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/vikas_ns/32/1210_2.png) [@Vikas\_NS](https://community.temporal.io/u/Vikas_NS)\
**Post date:** [February 2, 2022, 9:54am UTC](https://community.temporal.io/t/alternate-to-tctl-admin-cluster-add-search-attributes-to-add-new-search-attributes/3850/8 "2022-02-02T09:54:20Z")

</div>

1. Replacing `.usePlaintext()` with `.useTransportSecurity(); fixed the connectivity issues.
2. Post that I got` "UNIMPLEMENTED" exception`. Solved this by setting the package to `temporal.server.api.adminservice.v1` in proto file.

Here’s the final proto and java code.

**Proto**

```auto
syntax = "proto3";
package temporal.server.api.adminservice.v1;

enum IndexedValueType {
    INDEXED_VALUE_TYPE_UNSPECIFIED = 0;
    INDEXED_VALUE_TYPE_TEXT = 1;
    INDEXED_VALUE_TYPE_KEYWORD = 2;
    INDEXED_VALUE_TYPE_INT = 3;
    INDEXED_VALUE_TYPE_DOUBLE = 4;
    INDEXED_VALUE_TYPE_BOOL = 5;
    INDEXED_VALUE_TYPE_DATETIME = 6;
}

message AddSearchAttributesRequest {
    map<string, IndexedValueType> search_attributes = 1;
    string index_name = 2;
    bool skip_schema_update = 3;
}

message AddSearchAttributesResponse {
}

service AdminService {
    rpc AddSearchAttributes (AddSearchAttributesRequest) returns (AddSearchAttributesResponse);
}

```

**Java**

```auto
package temporal.server.api.adminservice.v1;

import io.grpc.ManagedChannel;
import io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder;

public class Service {
    public static void main(String[] args) {
        Service service = new Service();
        String serverUrl = "serverUrl";
        String key = "search_attr_key";
        Temporaladmin.IndexedValueType type = Temporaladmin.IndexedValueType.INDEXED_VALUE_TYPE_TEXT;
        service.addSearchAttr(key, type, serverUrl);
    }

    private void addSearchAttr(String key, Temporaladmin.IndexedValueType type, String serverUrl) {

        ManagedChannel channel = getChannel(serverUrl);

        AdminServiceGrpc.AdminServiceBlockingStub adminServiceBlockingStub = AdminServiceGrpc.newBlockingStub(channel);

        adminServiceBlockingStub.addSearchAttributes(
                Temporaladmin.AddSearchAttributesRequest
                        .newBuilder()
                        .putSearchAttributes(key, type)
                        .build()
        );

    }

    public ManagedChannel getChannel(String serverUrl) {
        NettyChannelBuilder builder =
                NettyChannelBuilder.forTarget(serverUrl)
                        .defaultLoadBalancingPolicy("round_robin")
                        .maxInboundMessageSize(25_000_000)
                        .useTransportSecurity();
        return builder.build();
    }
}

```

---

<div class="post-metadata">

**Author:** ![Vikas\_NS](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/vikas_ns/32/1210_2.png) [@Vikas\_NS](https://community.temporal.io/u/Vikas_NS)\
**Post date:** [February 2, 2022, 10:26am UTC](https://community.temporal.io/t/alternate-to-tctl-admin-cluster-add-search-attributes-to-add-new-search-attributes/3850/9 "2022-02-02T10:26:02Z")

</div>

`What is the purpose of ` **frontend.validSearchAttributes** ` in dynamic config ?`

---

<div class="post-metadata">

**Author:** ![alex](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/alex/32/15_2.png) [@alex](https://community.temporal.io/u/alex)\
**Post date:** [February 3, 2022, 2:25am UTC](https://community.temporal.io/t/alternate-to-tctl-admin-cluster-add-search-attributes-to-add-new-search-attributes/3850/10 "2022-02-03T02:25:42Z")

</div>

It was removed from dynamic config like a year ago, and if you still have it there, it is not used.

---

<div class="post-metadata">

**Author:** ![lukasz.a](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/lukasz.a/32/2582_2.png) [@lukasz.a](https://community.temporal.io/u/lukasz.a)\
**Post date:** [February 25, 2023, 10:03am UTC](https://community.temporal.io/t/alternate-to-tctl-admin-cluster-add-search-attributes-to-add-new-search-attributes/3850/11 "2023-02-25T10:03:58Z")

</div>

@alex you mentioned year ago that you guys are working on exposing this attribute adding to SDKs. Did you manage to release it?

---

<div class="post-metadata">

**Author:** ![maxim](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/maxim/32/8_2.png) [@maxim](https://community.temporal.io/u/maxim)\
**Post date:** [February 25, 2023, 8:42pm UTC](https://community.temporal.io/t/alternate-to-tctl-admin-cluster-add-search-attributes-to-add-new-search-attributes/3850/12 "2023-02-25T20:42:44Z")

</div>

I believe it is available through [OperatorService](https://github.com/temporalio/api/blob/44e4397262d480b9e6f17771be9ae1812d97384e/temporal/api/operatorservice/v1/service.proto#L48).

---

<div class="post-metadata">

**Author:** ![lukasz.a](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/lukasz.a/32/2582_2.png) [@lukasz.a](https://community.temporal.io/u/lukasz.a)\
**Post date:** [March 4, 2023, 1:46pm UTC](https://community.temporal.io/t/alternate-to-tctl-admin-cluster-add-search-attributes-to-add-new-search-attributes/3850/13 "2023-03-04T13:46:11Z")

</div>

Thanks @maxim, OperatorServiceStubs delivers the feature.
