---
schema_version: "1"
id: 8b9d11ef3b29a440aac8990f4642838563b53be33629f6ccd79a83b0a1cc5f55
title: Metadata Keys Parameter
collection: mulesoft
version: current
locale: en-us
portal_url: https://docs.salesforce.com/mulesoft/current/en-us/mule-sdk/latest/metadata-keys.md
canonical_url: https://docs.mulesoft.com/mule-sdk/latest/metadata-keys
source_site: docs.mulesoft.com
content_type: documentation
content_hash: 940edb7d5db9dbe38bbbdcc20dcc6358edd2f0b27b33bff0e02cc1f07d8a6217
description: MuleSoft Documentation Site
release: "1.13"
latest: true
---
---
product: Mule SDK
version: 1.13
is-latest-version: true
keywords: mule, sdk, metadata, datasense, keys, type
---

# Metadata Keys Parameter

> For the full documentation index, see: https://docs.mulesoft.com/llms.txt

To describe a dynamic metadata structure, you need to know what type to represent. This type
reference is done by defining a `@MetadataKeyId` parameter in the operation that contains the ID of
the type (for example, Account) that will be passed to the metadata resolver defined for that
parameter.

This means, for example, that if your operation can save a generic record to a remote system, but
you want to provide a better design-time experience by describing the supported types `Account` and
`Organization`, then one of your operation parameters will be a type reference containing either the
ID `Account` or the ID `Organization`. This parameter will be used to describe either the Account
structure or the Organization structure for the record to be saved into the bucket, depending on
what the end user decides to use.

## Providing a List of Metadata Keys

The most common case when resolving dynamic metadata is to have a dynamic set of keys that identify
each of the possible types to be resolved. At design time, the end user will configure the
connector, select an operation, and choose one of those keys from the set that gets populated
dynamically, and the selected key will become the `MetadataKeyId` for the metadata resolution.

Implementing the dynamic key’s resolution starts with a `TypeKeysResolver`:

```java
public class RecordKeysResolver implements TypeKeysResolver {

  @Override
  public String getCategoryName() {
    return "Records";
  }

  @Override
  public Set<MetadataKey> getKeys(MetadataContext context) throws MetadataResolvingException, ConnectionException {
     // First we need to obtain the key IDs that will be used.
     // This is where you'd normally use `context.getConfig()`
     // or `context.getConnection()` to obtain the entity id's
     // from a remote service, for this demo the keys will be fixed
     List<String> keyIds = Arrays.asList("Author_id", "BookList_id", "Book_id");

     HashSet<MetadataKey> keys = new HashSet<>();
     for (String id: keyIds){
       // For each possible if, we create a new MetadataKey with that ID
       MetadataKeyBuilder builder = MetadataKeyBuilder.newKey(id);

       // Then, we add a DisplayName to that MetadataKey,
       // this will be the name shown in the UI
       builder.withDisplayName(StringUtils.removeEnd(id, "_id"));

       //finally, add the key to the Set of known MetadataKeys
       keys.add(builder.build());
     }

     return keys;
  }

}
```

Above, all the elements that are required to create a dynamic set of MetadataKeys. The method to
implement is `getKeys`, which outputs all the keys available to the user.

The `id` element, like `Author_id` is used internally and must be unique for each structure that you
want to represent across all the resolvers. The `displayName` is the name to show to the user for
that key, so it is expected to be more user friendly and readable.

After the resolver is defined, you can use it as an operation or a source by adding the
`@MetadataScope` annotation with its `keysResolver` value at the class definition level and
annotating the parameter that is the key with `@MetadataKeyId`. All metadata resolvers must belong
to the same category in an operation or a source.

```java
@MetadataScope(keysResolver = RecordKeysResolver.class)
public class OperationWithMetadataKey {

    public void create(@MetadataKeyId String type,
                       @Config MyConfig config){
        //...
    }
}
```

```java
@MetadataScope(keysResolver = RecordKeysResolver.class)
public class DocsMetadataSource extends Source<Map<String, Object>, Void> {

    @MetadataKeyId
    @Parameter
    public String type;

    //...
  }
```

> [!NOTE] The previous example is the only way to support metadata keys for sources. Do not set the
> resolver at the `@MetadataKeyId` annotation when defining sources.

Setting the `@MetadataScope` annotation at the operation class definition level indicates that all
of its operations provide metadata and that they must all have a parameter annotated with
`@MetadataKeyId` because they inherit the resolver from the scope.

You can also set a key resolver for a single operation:

```java
public class MyOperations {

    public void operationWithMetadataKey(@MetadataKeyId(RecordKeysResolver.class) String type,
                       @Config MyConfig config){
        //...
    }

    public void plainOperation(@Config MyConfig config){
        //...
    }
}
```

In addition, if there is a `@MetadataScope` annotation at the operation class definition level, you
can set a value for the `@MetadataKeyId` annotation in a parameter to override the resolver defined
at the scope level for a single operation:

```java
@MetadataScope(keysResolver = ClassLevelResolver.class)
public class MyOperations {

    public void operation(@MetadataKeyId String type, @Config MyConfig config){
        // This operation will use the ClassLevelResolver
    }

    public void operationWithAnotherResolver(@MetadataKeyId(OverridingResolver.class) String type,
                       @Config MyConfig config){
        // This operation will use the OverridingResolver
    }
}
```

> [!IMPORTANT] The two previous examples (setting the resolver at the parameter level and overriding
> the inherited resolver from the scope) work only when defining operations. These features are not
> available for sources.

## User-Defined MetadataKey

An user-defined `MetadataKey` is one that is provided freely by the end user and not defined by you
as one of the possible elements of a List.

For example, this is a very common case in queries, where you use the whole query that the end user
wants to execute as a `MetadataKey`.

To declare a user-defined `MetadataKey`, annotate a parameter with `@MetadataKeyId` without
providing a `TypesKeyResolver` for the parameter annotation or for the `@MetadataScope` annotation
if it is present at the class definition.

```java
public class MyOperations {

  public void query(@MetadataKeyId String query){
      //...
  }
}
```

## Optional MetadataKey Parameters

Available since version 1.3.

You can make `MetadataKey` parameters optional like other parameters, by adding the `@Optional`
annotation:

```java
public void query(@MetadataKeyId @Optional String query){
 //...
}
```

When an optional MetadataKey parameter is not assigned a value, metadata calls are made using `null`
as the value of `MetadataKey`. This means that any `MetadataResolver` parameter associated with this
`MetadataKey` parameter must be prepared to receive a null value.
