Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

SDK: Simplify OpenAPI Spec annotations

Open
#2,755 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
30/100
Issue type
Feature
Clarity
Mostly clear
Activity status
Active
Tech stack
java, openapi
Domain
api, backend

Research direction

Start with the metrics records named in the issue, such as ProjectJobScheduleInputMetrics, and the @Schema annotations on their components. The proposal has two open implementation options (a Jandex AnnotationTransformation in timefold-solver-service-quarkus-deployment, or an OASFilter at runtime), so a maintainer has to choose one before any code is written. Done means a @Metric annotation that expands to the same OpenAPI output the quickstarts produce by hand today.

Written by the indexing model from the issue text.

Description

process/needs triage

Is your feature request related to a problem? Please describe.
It's very frustrating to see how complex our OpenAPI Spec annotations have become to be platform compatible.

Every metric component on a ModelInputMetrics / ModelOutputMetrics record carries a large @Schema
annotation. Most of it repeats the same values on every field, and the example value is written twice.
This is one field from ProjectJobScheduleInputMetrics, which already has the inferred attributes
(type, name, @JsonFormat) removed:

@Schema(title = "Jobs", format = DataFormat.Values.NUMBER,
        description = "The number of jobs submitted in the input dataset.",
        examples = "24", minimum = "0", readOnly = true,
        extensions = { @Extension(name = X_TF_PRIORITY, value = "2"),
                @Extension(name = X_TF_EXAMPLE, value = "24") }) int jobs,

Only the following are specific to each metric:

  • title
  • description
  • the example value
  • format, when it isn't NUMBER

Everything else is either the same on every metric or can be derived:

Attribute Why it's boilerplate
readOnly = true Always true: metrics are only serialized, never deserialized.
minimum = "0" True for every count/total metric in the quickstarts so far.
x-tf-example Duplicates examples.
x-tf-priority Order in the Platform UI, this should honestly just have a default and be hidden
X_TF_PRIORITY / X_TF_EXAMPLE constants Redeclared as private constants in every metrics class.

Across the migrated quickstarts, this makes the metrics records hard to read, and it's easy to slip
(for example, an examples that no longer matches its x-tf-example).

Describe the solution you'd like

Add an SDK annotation, for example ai.timefold.solver.service.definition.api.metrics.Metric, that
carries only the metric-specific information:

public record ProjectJobScheduleInputMetrics(
        @Metric(title = "Allocations", example = "24",
                description = "The number of job allocations submitted in the input dataset.") int allocations,
        @Metric(title = "Jobs", example = "24",
                description = "The number of jobs submitted in the input dataset.") int jobs,
        @Metric(title = "Projects", example = "2",
                description = "The number of projects submitted in the input dataset.") int projects,
        @Metric(title = "Resources", example = "7",
                description = "The number of resources submitted in the input dataset.") int resources)
        implements
            ModelInputMetrics {
    ...
}

Sketch of the annotation:

@Target({ ElementType.FIELD, ElementType.RECORD_COMPONENT, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Metric {
    String title();
    String description();
    String example();
    String format() default DataFormat.Values.NUMBER;
    String minimum() default "0";      // "" to omit
    int priority() default -1;         // -1 = derive from declaration order
}

The SDK expands @Metric into the same OpenAPI output that the quickstarts produce by hand today:

  • title, description and format come straight from the annotation.
  • example and x-tf-example both come from example.
  • readOnly: true is always set.
  • minimum defaults to 0.
  • x-tf-priority comes from the component index (1-based) unless priority is set explicitly.
  • type is inferred from the Java type, as it is today.

Implementation options

  1. Build time, via a Jandex AnnotationTransformation in timefold-solver-service-quarkus-deployment.
    It rewrites @Metric into an equivalent @Schema (with @Extensions) on classes implementing
    ModelInputMetrics / ModelOutputMetrics. SmallRye OpenAPI then sees a normal @Schema, so nothing
    downstream changes. This option is preferred because the static spec is correct at build time too.
  2. Runtime, via an OASFilter that finds the metrics schemas and fills in the properties.
    It's simpler to write, but it relies on reflection to map schema properties back to record components.

Describe alternatives you've considered
Leaving it as is... for the user to deal with.

Dominant language
Java
Stars
1.8k
Forks
238
Avg merge
3d 1h
Merged PRs (30d)
55

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from TimefoldAI/timefold-solver

All issues in TimefoldAI/timefold-solver

Similar issues

More Java issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.