skip to content

How do value hints and hint providers work in configuration metadata, including hints for Map keys and values?

level: seniorimportance: should knowfreq 28%

answer

  1. hint = name + values + providers
  2. Providers: any, class-reference, handle-as, logger-name, spring-bean-reference, spring-profile-name
  3. Maps: target .keys and .values
  4. handle-as borrows another type's completion
  5. Tooling only, no runtime validation

basics

~20 s

A hint entry links to a property by name and supplies either a static list of suggested values or a provider that computes suggestions dynamically (e.g. class-reference, logger-name, handle-as). For maps you target property.keys or property.values.

solid answer

~40 s

The metadata `hints` array powers value auto-completion. Each hint has a `name` referencing a property, plus `values` and/or `providers`. `values` is a static list of `{value, description}` suggestions. `providers` delegate to a named strategy the IDE understands: `any`, `class-reference` (suggest classes assignable to a target, with a `concrete` param), `handle-as` (treat the raw string as another type, e.g. a Duration or an enum), `logger-name`, `spring-bean-reference`, and `spring-profile-name`. For collection or map properties you cannot hint the whole structure, so you target the derived keys `myprop.keys` and `myprop.values` — for example suggesting known map keys or class-reference values. Static values and providers can coexist; the IDE shows the static values plus whatever the provider computes. All of this is authored in additional-spring-configuration-metadata.json.

code

json · 19 lines
json
{
  "hints": [
    {
      "name": "app.cache.provider",
      "providers": [
        {
          "name": "class-reference",
          "parameters": { "target": "com.example.CacheProvider", "concrete": true }
        }
      ]
    },
    {
      "name": "app.timeouts.values",
      "providers": [
        { "name": "handle-as", "parameters": { "target": "java.time.Duration" } }
      ]
    }
  ]
}

go deeper

for a junior

Awareness that hints supply suggested values is enough.

for a middle

Know static values vs providers and that hints live in the additional metadata file.

for a senior

Explain the provider vocabulary, handle-as semantics, and Map .keys/.values targeting.

for a principal

Design pluggable config surfaces (class-reference/bean-reference) and standardize hint conventions, understanding hints are tooling-only and don't substitute for validation.

## The hint structure A `hints` entry has three fields: ```json { "name": "<property or derived key>", "values": [ { "value": "...", "description": "..." } ], "providers": [ { "name": "<provider>", "parameters": { ... } } ] } ``` - **`name`** ties the hint to a property. For a scalar it is the property name directly. - **`values`** is a static, hand-written list of suggestions (each with an optional description shown in the popup). - **`providers`** delegate suggestion generation to a **named strategy** the tooling knows how to run. `values` and `providers` are not mutually exclusive; the IDE combines both. ## Built-in providers These provider names are understood by Spring's tooling: - **`any`** — permit any value (suppresses "unknown value" warnings). - **`class-reference`** — suggest fully-qualified class names. Parameters: `target` (a base type suggestions must be assignable to) and `concrete` (boolean, whether to only suggest instantiable classes). - **`handle-as`** — tell the IDE to treat the raw string **as if** it were another type. Parameter `target` names that type (e.g. `java.time.Duration`, a `java.nio.charset.Charset`, an `enum`, or `org.springframework.core.io.Resource`). This gives you the target type's own completion/validation. - **`logger-name`** — suggest package and logger names (used by `logging.level.*`). - **`spring-bean-reference`** — suggest bean names of a `target` type. - **`spring-profile-name`** — suggest known profile names. ## Hints for Maps and collections You **cannot** attach a hint to a whole `Map` or `List`. Instead you target derived names: - **`<property>.keys`** — suggestions for the map's keys. - **`<property>.values`** — suggestions for the map's values. Example: for `logging.level` (a `Map<String,String>` of logger name to level), Spring ships a hint on `logging.level.keys` using the `logger-name` provider and on `logging.level.values` using static values (`trace/debug/info/...`). ## Worked example ```json { "hints": [ { "name": "app.serializers.keys", "values": [ { "value": "json" }, { "value": "xml" } ] }, { "name": "app.serializers.values", "providers": [ { "name": "class-reference", "parameters": { "target": "com.example.Serializer", "concrete": true } } ] } ] } ``` Here `app.serializers` is a `Map<String, Class<? extends Serializer>>`: keys are suggested from a static list, values are suggested as concrete implementations of `Serializer`. ## Gotchas - Hints are **IDE tooling only** — they never validate or coerce at runtime. A `handle-as` Duration hint does not make Spring parse a Duration; binding still depends on the actual property type. - Provider names are a fixed vocabulary; a misspelled provider is ignored. - All hints live in `additional-spring-configuration-metadata.json`; the processor merges them. - Deep nesting: you can only target `.keys`/`.values` one level; complex nested maps have limited support. ## When to use Use static `values` for small closed sets; use `handle-as` to borrow another type's completion; use `class-reference`/`spring-bean-reference` for pluggable strategies; use `.keys`/`.values` whenever the property is a map.

  • How do you provide auto-completion for the keys of a Map<String,String> property?
    Target the derived name property.keys in a hint and supply static values or a provider like logger-name. You cannot hint the Map as a whole; keys and values are hinted separately via .keys and .values.
  • What does the handle-as provider actually do?
    It tells the IDE to treat the property's raw string value as another type (e.g. Duration, Charset, an enum, or Resource) so it borrows that type's completion and validation. It has no runtime effect; runtime binding still depends on the declared property type.

saying these in an interview costs you the question

  • Claiming hints validate or coerce values at runtime
  • Trying to attach a hint directly to a Map/List instead of .keys/.values
  • Inventing provider names not in Spring's fixed vocabulary
  • Thinking class-reference instantiates the class rather than just suggesting names

context