Skip to content

Fix mapping of constraint Date annotation to OpenAPI#1887

Closed
sathindudezoysa wants to merge 5 commits into
ballerina-platform:masterfrom
sathindudezoysa:issue-5049-date-constraint-openapi
Closed

Fix mapping of constraint Date annotation to OpenAPI#1887
sathindudezoysa wants to merge 5 commits into
ballerina-platform:masterfrom
sathindudezoysa:issue-5049-date-constraint-openapi

Conversation

@sathindudezoysa

@sathindudezoysa sathindudezoysa commented Mar 28, 2026

Copy link
Copy Markdown
Contributor

Resolves #5049

Description

Summary of user stories addressed by this change:
Resolves the issue where Ballerina @constraint:Date annotations were not being accurately mapped to the OpenAPI specification during Ballerina to OpenAPI conversion.

Brief description of the nature of the feature or bug-fix:
This PR adds support for mapping the @constraint:Date annotation into the generated OpenAPI specification. Since OpenAPI does not have a native Date type, this change ensures that date constraints are mapped to type: string with format: date. It also includes logic to handle specific date validation options such as PAST, FUTURE, PAST_OR_PRESENT, and FUTURE_OR_PRESENT by properly formatting the OpenAPI schema and mapping the relevant patterns or constraints.

Testing

Code coverage information:

  • Added comprehensive unit tests for the @constraint:Date annotation mapping.

Testing done (Unit, Integration, etc.):

  • Executed OpenAPI tool unit tests to verify the accurate generation of OpenAPI specifications from Ballerina records utilizing the FUTURE, PAST, FUTURE_OR_PRESENT, and PAST_OR_PRESENT constraint options.

Test environments:

  • OS: Ubuntu 22.04
  • Java version: JDK 21

Security Check

Summary

This pull request adds support for mapping the Ballerina @constraint:Date annotation to OpenAPI format during Ballerina-to-OpenAPI conversion. Since OpenAPI does not have a native date type, date constraints are mapped to type: string with format: date, while date validation options (PAST, FUTURE, PAST_OR_PRESENT, FUTURE_OR_PRESENT) are preserved through an OpenAPI extension (x-ballerina-constraint).

Changes

Core Implementation:

  • Extended ConstraintAnnotation class to track date-related constraint metadata, including root validation message, option message, and the specific date constraint option
  • Updated ConstraintMapperImpl to parse and process date constraint annotations, handling both simple option references and structured constraint configurations
  • Modified ReferenceTypeMapper to detect time:Date reference types and map them to string schemas with date format instead of treating them as component objects
  • Added helper methods for parsing annotation fields and sanitizing string literals

Configuration & Versioning:

  • Updated version numbers across Ballerina.toml, BalTool.toml, and Dependencies.toml from 2.4.1 to 2.4.2-SNAPSHOT or 2.4.2

Test Coverage:

  • Added comprehensive test case covering date constraint mapping with expected OpenAPI output validation
  • Provided test resource file demonstrating date constraints on custom types and record fields with multiple validation options and custom error messages

The implementation ensures that date constraints are properly represented in the generated OpenAPI specification, allowing API documentation to reflect date validation requirements from the Ballerina service definitions.

@coderabbitai

coderabbitai Bot commented Mar 28, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

The pull request adds support for date constraints in the Ballerina-to-OpenAPI converter. It introduces new constant definitions, extends the constraint annotation model with message and date-option fields, updates constraint extraction logic to parse and map date constraint metadata, adds detection for time:Date reference types, and includes test cases with expected OpenAPI output.

Changes

Cohort / File(s) Summary
Constraint Constants
ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/constraint/Constants.java
Added MESSAGE and OPTION string constants for constraint field identification.
Constraint Model
ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/constraint/ConstraintAnnotation.java
Extended ConstraintAnnotation with three new fields (rootMessage, optionMessage, dateOption), updated hasConstraints() logic, and added corresponding getters and builder setters.
Constraint Extraction Logic
ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/constraint/ConstraintMapperImpl.java
Refactored @constraint:Date handling by replacing special-case detection with field-based routing; added schema description concatenation from constraint messages; implemented OpenAPI x-ballerina-constraint extension generation for date options; added parsing helpers for MESSAGE and OPTION fields with string sanitization.
Type Mapping
ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/type/ReferenceTypeMapper.java
Added detection and mapping of time:Date reference types to OpenAPI StringSchema with format("date"); included new isTimeDateType() helper method.
Date Constraint Tests
openapi-cli/src/test/java/io/ballerina/openapi/generators/openapi/ConstraintTests.java, openapi-cli/src/test/resources/ballerina-to-openapi/constraint/dateConstraint.bal, openapi-cli/src/test/resources/ballerina-to-openapi/expected_gen/constraint/expectedDate.yaml
Added test method, Ballerina test resource with date-constrained types and HTTP service definition, and expected OpenAPI YAML output with constraint extensions.
Version Updates
openapi-tool/BalTool.toml, openapi-tool/Ballerina.toml, openapi-tool/Dependencies.toml
Updated package and dependency versions from 2.4.1 to 2.4.2 or 2.4.2-SNAPSHOT.

Sequence Diagram

sequenceDiagram
    participant ConstraintMapper as ConstraintMapper
    participant ConstraintAnnotation as ConstraintAnnotation
    participant ReferenceTypeMapper as ReferenceTypeMapper
    participant SchemaGenerator as SchemaGenerator
    
    ConstraintMapper->>ConstraintMapper: Extract MESSAGE & OPTION fields
    ConstraintMapper->>ConstraintAnnotation: withRootMessage(msg)
    ConstraintMapper->>ConstraintAnnotation: withDateOption(option)
    ConstraintMapper->>ConstraintAnnotation: withOptionMessage(optMsg)
    
    ReferenceTypeMapper->>ReferenceTypeMapper: Check if time:Date type
    ReferenceTypeMapper->>SchemaGenerator: Map to StringSchema(format=date)
    
    SchemaGenerator->>SchemaGenerator: Concatenate rootMessage + optionMessage
    SchemaGenerator->>SchemaGenerator: Set schema description
    SchemaGenerator->>SchemaGenerator: Add x-ballerina-constraint extension
    SchemaGenerator-->>ConstraintMapper: Return OpenAPI schema with metadata
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • daneshk
  • lnash94
  • shafreenAnfar

Poem

🐰 A hop, skip, and a date constraint leap,
New messages and options we now keep,
From time:Date to schema so fine,
Extensions bloom in YAML's design,
Ballerina's time bounds the converter's prime! ⏰✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The description addresses key aspects (issue reference, summary, testing, security checks) but is missing several required sections from the template (Purpose/Goals/Approach structure, Documentation, Training, Certification, Marketing, Automation tests details, Sample, Related PRs, Migrations, Test environment specifics). Expand the description to include missing template sections: Purpose/Goals/Approach, Documentation, Training, Certification, Marketing, complete Automation tests, Samples, Related PRs, and detailed Test environment information for better clarity and completeness.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding support for mapping Ballerina @constraint:Date annotations to OpenAPI specification.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
C Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
openapi-cli/src/test/resources/ballerina-to-openapi/constraint/dateConstraint.bal (1)

20-35: Extend this fixture to include FUTURE_OR_PRESENT and PAST_OR_PRESENT.

The current resource validates only FUTURE and PAST; adding the other two options here would better lock down the new mapping behavior end-to-end.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@openapi-cli/src/test/resources/ballerina-to-openapi/constraint/dateConstraint.bal`
around lines 20 - 35, Update the test fixture by adding constraint:Date
annotations that use the FUTURE_OR_PRESENT and PAST_OR_PRESENT options alongside
the existing FUTURE and PAST cases: update the MyDate/type-level annotation or
add a new typedef (e.g., MyDateFutureOrPresent) with option:
constraint:FUTURE_OR_PRESENT and message, and likewise update or add a
field/record-level annotation on RegDate (or a new record field) using option:
constraint:PAST_OR_PRESENT with an appropriate message; ensure you reference the
existing constraint:Date annotations on MyDate and the RegDate.lastLogin field
so the new cases exercise both type-level and field-level mappings.
ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/constraint/ConstraintMapperImpl.java (1)

468-478: Reuse the literal sanitizer in both paths.

Lines 468-469 and Lines 477-478 are stripping quotes separately. Reusing sanitizeStringLiteral() from extractFieldValue() keeps the behavior aligned and removes one copy of the regex.

♻️ Suggested cleanup
     private String sanitizeStringLiteral(String raw) {
-        return raw.trim().replaceAll("^\"|\"$", "");
+        return raw.trim().replaceAll("(^\")|(\"$)", "");
     }
@@
-            case STRING_LITERAL: 
-                return Optional.of(exprNode.toString().trim().replaceAll("^\"|\"$", ""));
+            case STRING_LITERAL:
+                return Optional.of(sanitizeStringLiteral(exprNode.toString()));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/constraint/ConstraintMapperImpl.java`
around lines 468 - 478, The code duplicates quote-stripping logic: replace the
inline replaceAll in extractFieldValue with a call to the existing
sanitizeStringLiteral(String) helper so both NUMERIC_LITERAL and STRING_LITERAL
paths reuse the same sanitizer; update extractFieldValue to invoke
sanitizeStringLiteral(exprNode.toString().trim()) for STRING_LITERAL and remove
the duplicated regex call so behavior is consistent with sanitizeStringLiteral.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/constraint/ConstraintMapperImpl.java`:
- Around line 257-265: ConstraintMapperImpl currently builds a description from
constraintAnnot.getRootMessage()/getOptionMessage() and then calls
properties.setDescription(...), which overwrites any existing docs-derived
description; change this to preserve and merge with an existing description on
the schema: read the current properties.getDescription() (if any), build the
constraint description string from
constraintAnnot.getRootMessage()/getOptionMessage(), then set
properties.setDescription(combined.trim()) where combined is either the existing
description plus a separator and the constraint description or the constraint
description alone if no existing description exists, ensuring you do not clobber
prior documentation.

In
`@ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/type/ReferenceTypeMapper.java`:
- Around line 86-91: Update isTimeDateType to validate the module org as well as
the module name: inside isTimeDateType(TypeReferenceTypeSymbol typeSymbol)
refine the module.filter predicate to check
module.id().orgName().equals("ballerina") in addition to
module.getName().orElse("").equals("time"), and use the same defensive
string-equals pattern for the type name check (i.e., compare "Date" against
typeSymbol.getName().orElse("")) so the method matches the org-level validation
used in ValidatorUtils/MapperCommonUtils/BallerinaTypeExtensioner.

---

Nitpick comments:
In
`@ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/constraint/ConstraintMapperImpl.java`:
- Around line 468-478: The code duplicates quote-stripping logic: replace the
inline replaceAll in extractFieldValue with a call to the existing
sanitizeStringLiteral(String) helper so both NUMERIC_LITERAL and STRING_LITERAL
paths reuse the same sanitizer; update extractFieldValue to invoke
sanitizeStringLiteral(exprNode.toString().trim()) for STRING_LITERAL and remove
the duplicated regex call so behavior is consistent with sanitizeStringLiteral.

In
`@openapi-cli/src/test/resources/ballerina-to-openapi/constraint/dateConstraint.bal`:
- Around line 20-35: Update the test fixture by adding constraint:Date
annotations that use the FUTURE_OR_PRESENT and PAST_OR_PRESENT options alongside
the existing FUTURE and PAST cases: update the MyDate/type-level annotation or
add a new typedef (e.g., MyDateFutureOrPresent) with option:
constraint:FUTURE_OR_PRESENT and message, and likewise update or add a
field/record-level annotation on RegDate (or a new record field) using option:
constraint:PAST_OR_PRESENT with an appropriate message; ensure you reference the
existing constraint:Date annotations on MyDate and the RegDate.lastLogin field
so the new cases exercise both type-level and field-level mappings.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: de91e46d-fa29-43f1-b27c-c0b83357d123

📥 Commits

Reviewing files that changed from the base of the PR and between dc1b20a and 5573724.

📒 Files selected for processing (10)
  • ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/constraint/Constants.java
  • ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/constraint/ConstraintAnnotation.java
  • ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/constraint/ConstraintMapperImpl.java
  • ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/type/ReferenceTypeMapper.java
  • openapi-cli/src/test/java/io/ballerina/openapi/generators/openapi/ConstraintTests.java
  • openapi-cli/src/test/resources/ballerina-to-openapi/constraint/dateConstraint.bal
  • openapi-cli/src/test/resources/ballerina-to-openapi/expected_gen/constraint/expectedDate.yaml
  • openapi-tool/BalTool.toml
  • openapi-tool/Ballerina.toml
  • openapi-tool/Dependencies.toml

Comment on lines +257 to +265
String description = "";
if (constraintAnnot.getRootMessage().isPresent()) {
description += constraintAnnot.getRootMessage().get();
}
if (constraintAnnot.getOptionMessage().isPresent()) {
description += (description.isEmpty() ? "" : " ") + constraintAnnot.getOptionMessage().get();
}
if (!description.isEmpty()) {
properties.setDescription(description.trim());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Don't clobber existing schema descriptions.

Line 265 replaces any description that was already populated from Ballerina docs. For schemas or fields that have both normal documentation and a date-constraint message, this regresses the generated OpenAPI docs.

🛠️ Suggested fix
-        if (!description.isEmpty()) {
-            properties.setDescription(description.trim());
-        }
+        if (!description.isEmpty()) {
+            String constraintDescription = description.trim();
+            String existingDescription = properties.getDescription();
+            properties.setDescription(existingDescription == null || existingDescription.isBlank()
+                    ? constraintDescription
+                    : existingDescription + " " + constraintDescription);
+        }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/constraint/ConstraintMapperImpl.java`
around lines 257 - 265, ConstraintMapperImpl currently builds a description from
constraintAnnot.getRootMessage()/getOptionMessage() and then calls
properties.setDescription(...), which overwrites any existing docs-derived
description; change this to preserve and merge with an existing description on
the schema: read the current properties.getDescription() (if any), build the
constraint description string from
constraintAnnot.getRootMessage()/getOptionMessage(), then set
properties.setDescription(combined.trim()) where combined is either the existing
description plus a separator and the constraint description or the constraint
description alone if no existing description exists, ensuring you do not clobber
prior documentation.

Comment on lines +86 to +91
public static boolean isTimeDateType(TypeReferenceTypeSymbol typeSymbol) {
return typeSymbol.getModule()
.filter(module -> module.getName().orElse("").equals("time"))
.isPresent()
&& typeSymbol.getName().orElse("").equals("Date");
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify existing module identity-check patterns and possible conflicting time imports.

set -euo pipefail

echo "== Existing Java patterns that check module org/name =="
rg -nP 'orgName\s*\(|getName\(\)\.orElse\(""\)\.equals\("time"\)|module\.getName\(' -g '*.java'

echo
echo "== Ballerina imports of */time modules (potential conflicts) =="
rg -nP '^\s*import\s+[^;]*/time\s*;' -g '*.bal'

echo
echo "== Explicit non-ballerina time imports (if any) =="
rg -nP '^\s*import\s+(?!ballerina/time)[^;]*/time\s*;' -g '*.bal' || true

Repository: ballerina-platform/openapi-tools

Length of output: 4539


🏁 Script executed:

cat -n ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/type/ReferenceTypeMapper.java | head -100

Repository: ballerina-platform/openapi-tools

Length of output: 4995


🏁 Script executed:

sed -n '385,395p' ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/utils/MapperCommonUtils.java

Repository: ballerina-platform/openapi-tools

Length of output: 394


🏁 Script executed:

sed -n '175,185p' ballerina-to-openapi/src/main/java/io/ballerina/openapi/validator/ValidatorUtils.java

Repository: ballerina-platform/openapi-tools

Length of output: 204


🏁 Script executed:

sed -n '175,185p' openapi-validator/src/main/java/io/ballerina/openapi/validator/ValidatorUtils.java

Repository: ballerina-platform/openapi-tools

Length of output: 398


🏁 Script executed:

rg -A 3 'getModule\(\)' ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/type/ReferenceTypeMapper.java

Repository: ballerina-platform/openapi-tools

Length of output: 271


🏁 Script executed:

rg -B 5 'getModule\(\)' ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/type/ReferenceTypeMapper.java | head -20

Repository: ballerina-platform/openapi-tools

Length of output: 235


🏁 Script executed:

rg 'ModuleSymbol' ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/type/ReferenceTypeMapper.java

Repository: ballerina-platform/openapi-tools

Length of output: 58


Add org-level validation to isTimeDateType to match established codebase patterns.

The method currently validates only module.getName().equals("time") without checking the org name. Update to also validate module.id().orgName().equals("ballerina") to match the pattern used consistently across ValidatorUtils, MapperCommonUtils, and BallerinaTypeExtensioner.

Suggested fix pattern
public static boolean isTimeDateType(TypeReferenceTypeSymbol typeSymbol) {
    return typeSymbol.getModule()
            .filter(module -> "ballerina".equals(module.id().orgName()) 
                    && "time".equals(module.getName().orElse("")))
            .isPresent()
            && "Date".equals(typeSymbol.getName().orElse(""));
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@ballerina-to-openapi/src/main/java/io/ballerina/openapi/service/mapper/type/ReferenceTypeMapper.java`
around lines 86 - 91, Update isTimeDateType to validate the module org as well
as the module name: inside isTimeDateType(TypeReferenceTypeSymbol typeSymbol)
refine the module.filter predicate to check
module.id().orgName().equals("ballerina") in addition to
module.getName().orElse("").equals("time"), and use the same defensive
string-equals pattern for the type name check (i.e., compare "Date" against
typeSymbol.getName().orElse("")) so the method matches the org-level validation
used in ValidatorUtils/MapperCommonUtils/BallerinaTypeExtensioner.

@sathindudezoysa

Copy link
Copy Markdown
Contributor Author

Hi everyone,
I've really been enjoying contributing to the openapi-tools repo lately! A big thank you to @TharmiganK for helping me get my previous fixes merged. I truly appreciate the support.

For this PR, I decided to tackle a feature request that's been open for a while. Since this is a bigger implementation, I'd love to get some eyes on it. I'm still getting familiar with the project's preferred logic patterns and coding styles, so I highly welcome any feedback, suggestions, or corrections.

Looking forward to your reviews so I can refine this and get it right!

@sathindudezoysa

Copy link
Copy Markdown
Contributor Author

Hi, @TharmiganK @lnash94 @daneshk @shafreenAnfar
I want to give a quick overview what I done in this PR. Currently openapi library does not handle date constraint and @SachinAkash01 was issue a raise about it.

As sachin mentioned in the issue I mapped the date fields to type:string with format:date. Then fI map the options and message using the x-ballerina-constraint extension. Finally I created a test case to test with the system.

Here following screenshot shows the all the unit test cases with my test case pass when running
image

I know my code has issues in formatting to the current standards in ballerina library. Please can anyone help me to fix those.

Comment on lines +36 to +37
private final String rootMessage;
private final String optionMessage;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need these two fields?

* This util is used to sanitize a string literal by trimming whitespace and removing surrounding quotes.
*/
private String sanitizeStringLiteral(String raw) {
return raw.trim().replaceAll("^\"|\"$", "");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we make this "^\"|\"$" to a constant value?

@@ -0,0 +1,42 @@
// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.org).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update the licenses header to 2026

@TharmiganK

Copy link
Copy Markdown
Contributor

Hi @sathindudezoysa, Thank you for your contribution! Sorry for the late response.

For this issue, we actually need the mapping of how we are going to represent the constraint annotation information in the generated OpenAPI specification. This requires a design for specification and approval. After the approval we can check on the implementation.

Can you please update the issue with your proposed mapping? We already have a specification of how Ballerina constructs are mapped to OpenAPI specification: https://github.com/ballerina-platform/openapi-tools/blob/master/docs/ballerina-to-oas/spec/spec.md. You can refer to this to get some idea. You have to refer to the OpenAPI schema as well to figure out a proper mapping. Once the proposed mapping is approved in the issue, we can review your implementation.

@sathindudezoysa

Copy link
Copy Markdown
Contributor Author

Hi @TharmiganK @lnash94

Thanks for the guidance and the resources. That makes perfect sense! Since we need to finalize and approve the design before jumping into the code, I will go ahead and close this PR for now to keep things clean.

I will study the specifications, design a proper mapping method, and raise a new issue with my proposal so we can discuss it there. Thanks again for the help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Ballerina to OpenAPI] Support @constraint:Date Annotation Mapping to OpenAPI Specification

3 participants