{"id":22230077,"url":"https://github.com/sngular/pact-annotation-processor","last_synced_at":"2025-07-27T19:32:19.874Z","repository":{"id":203932303,"uuid":"709859632","full_name":"sngular/pact-annotation-processor","owner":"sngular","description":"Pact DSL Builder annotation processor to create request bodies based on annotations. It allows to specify static values for properties also through Example annotation","archived":false,"fork":false,"pushed_at":"2024-04-19T21:46:25.000Z","size":140,"stargazers_count":22,"open_issues_count":9,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-04-19T22:37:11.817Z","etag":null,"topics":["consumer-driven-contract-tests","consumer-driven-contracts","contract","pact","pactbuilder","testing"],"latest_commit_sha":null,"homepage":"http://sngular.com","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sngular.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2023-10-25T14:36:38.000Z","updated_at":"2024-03-31T14:27:00.000Z","dependencies_parsed_at":"2024-01-17T14:49:56.375Z","dependency_job_id":"9e4db0ff-68df-48d5-a1d3-ab799551ecd8","html_url":"https://github.com/sngular/pact-annotation-processor","commit_stats":null,"previous_names":["sngular/pact-annotation-processor"],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sngular%2Fpact-annotation-processor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sngular%2Fpact-annotation-processor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sngular%2Fpact-annotation-processor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sngular%2Fpact-annotation-processor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sngular","download_url":"https://codeload.github.com/sngular/pact-annotation-processor/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":227831079,"owners_count":17826155,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["consumer-driven-contract-tests","consumer-driven-contracts","contract","pact","pactbuilder","testing"],"created_at":"2024-12-03T01:14:13.991Z","updated_at":"2024-12-03T01:14:14.653Z","avatar_url":"https://github.com/sngular.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Pact DSL Builder\n\n[![Codacy Badge](https://app.codacy.com/project/badge/Grade/67f7406f9b79477faae81cc93ed79395)](https://app.codacy.com/gh/sngular/pact-annotation-processor/dashboard?utm_source=gh\u0026utm_medium=referral\u0026utm_content=\u0026utm_campaign=Badge_grade)[![Maven Central](https://img.shields.io/maven-central/v/com.sngular/pact-annotation-processor?label=Maven%20Central)](https://central.sonatype.com/artifact/com.sngular/pact-annotation-processor)\n\nThis is a helper tool for Contract Testing with [Pact](https://docs.pact.io/).\nAn annotation processor designed to generate DslPart objects for the body definitions based on annotations included in your model classes.\n\nThe focus is to simplify JVM contract testing implementation, minimizing the amount of boilerplate code needed.\n\nSpecially useful when defining body validations for interactions with complex models.\n\n## Table of Contents\n\n- [Pact DSL Builder](#pact-dsl-builder)\n- [Getting Started](#getting-started)\n  - [Requirements](#requirements)\n  - [Compatibility with pact-jvm](#compatibility-with-pact-jvm)\n  - [Configuration](#configuration)\n- [Usage](#usage)\n  - [Annotations](#annotations)\n  - [Builder](#builder)\n- [Roadmap](#roadmap)\n- [Contributing](#contributing)\n- [License](#license)\n- [Contact](#contact)\n\n## Getting Started\n\n### Requirements\n\n- JDK +17\n\n- Having inside your project a verification library of your choice to have the `@Max` and `@Min` annotations available, such as [Jakarta](https://central.sonatype.com/artifact/jakarta.validation/jakarta.validation-api), [Spring Boot](https://central.sonatype.com/artifact/org.springframework.boot/spring-boot-starter-validation) or similar.\n\n### Compatibility with pact-jvm\n\n|                                   Pact DSL Builder                                   |  Pact JVM  |\n|:------------------------------------------------------------------------------------:|:----------:|\n| [1.1.0](https://central.sonatype.com/artifact/com.sngular/pact-annotation-processor/1.1.0) |   +4.6.3   |\n| [1.1.7](https://central.sonatype.com/artifact/com.sngular/pact-annotation-processor) |   +4.6.3   |\n| [1.2.0](https://central.sonatype.com/artifact/com.sngular/pact-annotation-processor/1.1.0) |   +4.6.3   |\n### Configuration\n\nThe only configuration needed for starting using the library is adding the dependency to your build automation tool:\n\nMaven\n\n```xml\n  \u003cdependencies\u003e\n    ...\n    \u003cdependency\u003e\n      \u003cgroupId\u003ecom.sngular\u003c/groupId\u003e\n      \u003cartifactId\u003epact-annotation-processor\u003c/artifactId\u003e\n      \u003cversion\u003e1.2.0\u003c/version\u003e\n    \u003c/dependency\u003e\n    ...\n  \u003c/dependencies\u003e\n```\n\nGradle\n\n```groovy\nimplementation('com.sngular:pact-annotation-processor:1.2.0')\n```\n\n## Usage\n\nTo enable the code generation in a model class, you should annotate it as `@PactDslBodyBuilder`.\nThat is the only requirement, all other annotations are optional and used for customising the generated code.\n\n### Annotations\n\nWe have developed 3 annotations to give support to your needs,\n\n- `@PactDslBodyBuilder` : To indicate which class you need to generate pact to.\n- `@Example`: To define constants values to set in your Pact Body.\n- `DslExclude`: To Exclude some property to be included in the builder.\n\nand support 2 standard Java annotations for validation\n\n- `@Min`: From Jakarta or Javax (or other validation tools) to indicate the\nminimum value to be cover for this property.\n- `@Max`: From Jakarta or Javax (or other validation tools) to indicate the\nmaximum value to be cover for this property.\n\n|            Annotation | Required | Level | Description                                                                                                                                 |\n|----------------------:|:--------:|:-----:|:--------------------------------------------------------------------------------------------------------------------------------------------|\n| `@PactDslBodyBuilder` |   true   | Class | Main annotation, to be included in classes that want to be processed.                                                                       |\n|            `@Example` |  false   | Field | Used to provide an specific value for a field. If not present in a field, the value created will be random.                                 |\n|                `@Min` |  false   | Field | Defines the maximum value for numeric fields, or number of elements if applied to collections. Will be ignored if an `@Example` is present. |\n|                `@Max` |  false   | Field | Defines the minimum value for numeric fields, or number of elements if applied to collections. Will be ignored if an `@Example` is present. |\n|         `@DslExclude` |  false   | Field | Ignore de generation of example values.                                                                                                     |\n\n\u003e `@Example` values are always provided as String. If a specific format is\n required lets say for date\n\u003e and datetime properties, then a format field should be provided,\n otherwise it will fall back to default\n\u003e format. For date and datetime default format are:\n\u003e\n\u003e - `yyyy-MM-dd['['ZZZ']']` : for dates\n\u003e\n\u003e - `yyyy-MM-dd'T'HH:mm:ss[.SSSSSS][.SSS]XXX['['VV']']` : for datetimes. Zone should be provided with this format.\n\n#### Example\n\n```java\npackage com.sngular.model;\n\nimport com.sngular.annotation.pact.Example;\nimport com.sngular.annotation.pact.PactDslBodyBuilder;\nimport jakarta.validation.constraints.Max;\nimport jakarta.validation.constraints.Min;\n\nimport java.time.ZonedDateTime;\n\n@PactDslBodyBuilder\npublic class Address {\n\n  @Example(\"2023-12-03T10:15:30+01:00[Europe/Madrid]\")\n  private ZonedDateTime deliveryTime;\n\n  @Example(\"2023-12-13\")\n  private Date creationDate;\n\n  @Example(\"Jose\")\n  private String name;\n\n  @Max(12)\n  @Min(1)\n  private int number;\n\n  @Example(\"4\")\n  private long aLong;\n\n  private ZonedDateTime init;\n  \n  private City city;\n\n}\n```\n\n### Builder\n\nOnce the code is compiled, builder will be generated and available under `generated-sources` in your build directory.\n\nYou will need to add the required import, and make use of the related builder class.\n\n#### Example\n\n```java\nimport com.sngular.model.AddressBuilder;\n        \nAddressBuilder addressBuilder = new AddressBuilder();\nDslPart bodyDslPart = addressBuilder.build();\n\n\n@Pact(consumer = \"consumer-poc\", provider = \"provider-poc\")\npublic RequestResponsePact getStudents(PactDslWithProvider builder) {\n        AddressBuilder addressBuilder = new AddressBuilder();\n        DslPart bodyDslPart = studentBuilder.build();\n        \n        return builder.given(\"Address exist\")\n        .uponReceiving(\"get all address\")\n        .path(\"/address/\")\n        .method(\"GET\")\n        .willRespondWith()\n        .status(200)\n        .headers(Map.of(\"Content-Type\", \"application/json\"))\n        .body(bodyDslPart)\n        .toPact();\n}\n```\n\n## Notes\n\n- Dates: Regarding Timestamp and Date, we should use keep in mind the default\n  formats will be used to parse those values:\n  - For Dates, we are using `\"yyyy-MM-dd['['ZZZ']']\"` as default format\n  - For Timestamps, we are using\n  `\"yyyy-MM-dd'T'HH:mm:ss[.SSSSSS][.SSS]XXX['['VV']']\"`\n  as default format for datetime (ZonedDateTime)\n  If you need and specific format the `@Example` support a format property\n  to handle them.\n\n=======\n\n### Expected Instance Builder\n\nIn certain situations, especially when using the `@Example` annotation in all\nof your model data objects, you may prefer to perform classic manual\ninstance creation for your validations in the `@Test` methods:\n\n```java\n@Test\n@PactTestFor(pactMethod = \"getAddressTest\")\nvoid getAddressTest(MockServer mockServer) {\n        RestTemplate restTemplate = new RestTemplateBuilder().rootUri(mockServer.getUrl()).build();\n        Address response = new BasicService(restTemplate).getAdress(\"...\");\n\n        // Manual instance creation for validation\n        Address expectedAddress = new Address();\n        expectedAddress.setName(\"Jose\");\n        expectedAddress.setNumber(12);\n        // ...\n\n        assertEquals(expectedAddress, response);\n}\n```\n\nHowever, in many situations, especially when dealing with random values being generated,\nyou may prefer to delegate the instance creation to the library itself.\nThis is the purpose of the `buildExpectedInstance()` method, which generates an\ninstance of the model object initialized with the values generated (or set\nby you with `@Example`) for the given object:\n\n```java\n\n@Test\n@PactTestFor(pactMethod = \"getAddressTest\")\nvoid getAddressTest(MockServer mockServer) {\n        RestTemplate restTemplate = new RestTemplateBuilder().rootUri(mockServer.getUrl()).build();\n        Address response = new BasicService(restTemplate).getAdress(\"...\");\n\n        // Using buildExpectedInstance() for instance creation\n        Address expectedAddress = new AddressBuilder().buildExpectedInstance();\n\n        assertEquals(expectedAddress, response);\n        }\n\n```\n\n## Roadmap\n\nRoadmap available under [GitHub Projects section](https://github.com/orgs/sngular/projects/2).\n\nSee the [open issues](https://github.com/sngular/pact-annotation-processor/issues) for a full list of proposed features (and known issues).\n\n## Contributing\n\nContributions are what makes the open source community special. Any contributions you make are greatly appreciated.\n\nIf you have a suggestion that would make this library better,\nplease [review our contributing guidelines](https://github.com/sngular/pact-annotation-processor/blob/main/CONTRIBUTING.md).\n\nOr you can simply [open a feature request issue](https://github.com/sngular/pact-annotation-processor/issues/new/choose).\n\n## License\n\nDistributed under Mozilla Public License Version 2.0. See [LICENSE](https://github.com/sngular/pact-annotation-processor/blob/main/LICENSE) for more information\n\n## Contact\n\nOS3 team: [os3@sngular.com](mailto:os3@sngular.com)\n\nSngular - [GitHub Org](https://github.com/sngular)\n\n\u003chttps://www.sngular.com\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsngular%2Fpact-annotation-processor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsngular%2Fpact-annotation-processor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsngular%2Fpact-annotation-processor/lists"}