{"id":21038957,"url":"https://github.com/reprezen/api-codeflow-spring-boot","last_synced_at":"2025-03-13T21:16:15.619Z","repository":{"id":94356311,"uuid":"149617167","full_name":"RepreZen/API-CodeFlow-Spring-Boot","owner":"RepreZen","description":"Build and evolve a REST API design-first with OpenAPI-Generator and Spring Boot. API CodeFlow is an agile, design‑first workflow that integrates API specifications into the build process, so API docs and code are continually in sync.","archived":false,"fork":false,"pushed_at":"2018-10-02T20:23:16.000Z","size":372,"stargazers_count":1,"open_issues_count":5,"forks_count":0,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-01-20T16:32:52.576Z","etag":null,"topics":["agile","api","api-codeflow","api-design","api-design-first","api-first","code-generation","codegen","eclipse","example","java","lifecycle","model-driven","model-driven-development","reprezen","rest","spring","spring-boot","spring-framework"],"latest_commit_sha":null,"homepage":"http://RZen.io/APICodeFlow","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RepreZen.png","metadata":{"files":{"readme":"README.adoc","changelog":null,"contributing":null,"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,"publiccode":null,"codemeta":null}},"created_at":"2018-09-20T13:52:19.000Z","updated_at":"2019-11-20T22:12:52.000Z","dependencies_parsed_at":"2023-03-13T17:01:21.611Z","dependency_job_id":null,"html_url":"https://github.com/RepreZen/API-CodeFlow-Spring-Boot","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RepreZen%2FAPI-CodeFlow-Spring-Boot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RepreZen%2FAPI-CodeFlow-Spring-Boot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RepreZen%2FAPI-CodeFlow-Spring-Boot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RepreZen%2FAPI-CodeFlow-Spring-Boot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RepreZen","download_url":"https://codeload.github.com/RepreZen/API-CodeFlow-Spring-Boot/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243482906,"owners_count":20297903,"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":["agile","api","api-codeflow","api-design","api-design-first","api-first","code-generation","codegen","eclipse","example","java","lifecycle","model-driven","model-driven-development","reprezen","rest","spring","spring-boot","spring-framework"],"created_at":"2024-11-19T13:36:58.142Z","updated_at":"2025-03-13T21:16:15.590Z","avatar_url":"https://github.com/RepreZen.png","language":null,"readme":"= Spring Boot Example\nifdef::env-github[]\n:tip-caption: :bulb:\n:note-caption: :information_source:\n:important-caption: :heavy_exclamation_mark:\n:caution-caption: :fire:\n:warning-caption: :warning:\nendif::[]\n:toc:\n:toc-placement!:\n:linkattrs:\n:imagesdir: ./images\n\nimage::API-CodeFlow-Logo-1024w.png[API CodeFlow Logo,35%]\n\nThis project serves as a demo for an http://rzen.io/APICodeFlow[API CodeFlow^] approach to API\nservice implementation. This entails the following three steps,\nrepeated as the API evolves:\n\n1. **Design** your API in https://github.com/OAI/OpenAPI-Specification[OpenApi^].\n2. **Generate** stub code in Java using the https://spring.io/projects/spring-boot[Spring Boot framework^].\n3. **Implement** your business logic.\n\nThis demo will create a working API to manage a database of live pets for a pet store. The API will\nsupport adding a new pet, updating an existing pet, deleting a pet, listing all pets, and showing\nthe pet with a given ID.\n\ntoc::[]\n\n== Working Through the Demo\n\n=== Overview\n\nThe demo proceeds in four phases (plus some initial set-up):\n\n\nThe phases are:\n\n[start=0]\n0. Setup - install and launch RepreZen API Studio.\n\n1. **Design** - Create one of the standard OpenAPI v3 example models available in RepreZen API Studio.\n\n2. **Generate** - Use one of the available code generators to generate a new server for the API,\nusing Spring Boot.\n\n3. **Implement** - Write your business logic into the generated stubs.\n\n4. Repeat (**Design** =\u003e **Generate** =\u003e **Implement**) in order to add a new method to the API\n\nSo let's get going!\n\n=== Phase 0 - Setup\n\nIf you don't already have RepreZen API Studio installed, you'll want to visit\nhttps://www.reprezen.com[the RepreZen website^] and sign up for a free trial.\nIf you're already an Eclipse IDE user, you\nmay want to consider installing API Studio from Eclipse Marketplace, rather than using the\nstand-alone installer offered in the sign-up process. Installation options are explained https://support.reprezen.com/support/solutions/articles/24000009587-reprezen-api-studio-installation-options-desktop-and-eclipse-ide-[here^].\n\n=== Phase 1 - Design\n\nWe won't actually design a model here. Instead, we'll just use one of the OpenApi3 models available from the API Studio Examples Wizard.\n\nFollow these steps:\n\n1. Click on the drop-down arrow of the _New_ tool in the toolbar, just under the _File_ menu.\n\n2. Select _RepreZen Examples_ to open the Examples Wizard.\n+\nimage::examples-wizard.png[Open the Examples Wizard]\n\n3. Click on the _OpenAPI v3_ tab.\n\n4. Select the _Expanded Pet Store (v3)_ example, and press _Finish_.\n+\nimage::petstore-example.png[Expanded Pet Store Example]\n\n5. You should see a new project in your workspace, and the example model file itself will automatically open in an editor.\n\n6. Browse through the model briefly to familiarize yourself with its operations and other components.\n\n\n=== Phase 2 - Generate\n\nWe'll make use of one of the built-in API Studio GenTemplates to create our server\nimplementation. This GenTemplate is one of dozens that are adapted for use in API Studio from the\nhttps://github.com/OpenAPITools/openapi-generator[OpenAPI Generator^] open-source project.\n\nTIP: We need to use a later version of the OpenAPI Generator library than is packaged with API\nStudio at the time of this writing. Steps 6-9 below accomplish this.\n\nFollow these steps:\n\n\n1. In your model project, locate the `petstore-expanded.yaml` file in the `models` folder, and\ndouble-click on it.\n\n2. Click on the _Create a New GenTarget_ button in the toolbar, just to the left of the _Generate_\nbutton/menu.\n+\nTIP: If you do not see this in the toolbar, be sure that you are in the **RepreZen** perspective, by\nclicking on the appropriate button on the far right of the toolbar: image:reprezen-perspective.png[].\n+\nimage::create-gentarget.png[Create GenTarget]\n\n3. Type \"spring\" in the resulting dialog's search box, and you should see the **Java Spring\n(Boot...)** GenTemplate in the list.\n\n4. Select the **Java Spring** GenTemplate and press _Finish_. A new GenTarget is created in your\nproject, and the `.gen` file that describes it opens in an editor.\n+\nimage::select-gentemplate.png[]\n\n\n[start=5]\n5. Modify the new `.gen` file (which should be showing now in your active editor) as shown in the\nfollowing table. You can copy/paste directly from this table into the `.gen` file.\n[none]\n+\n[cols=\"30m,70m\"]\n|===\nh|{set:cellbgcolor:white}\nParameter Name\nh|{set:cellbgcolor:white}Value\n{set:cellbgcolor:white}\n2+^e|Output Location and Packages\n{set:cellbgcolor:white}|relativeOutputDir|../../../implementation/springboot-petstore-demo\n{set:cellbgcolor:white}|modelPackage|com.reprezen.demo.springboot.model\n{set:cellbgcolor:white}|apiPackage|com.reprezen.demo.springboot.api\n{set:cellbgcolor:white}|invokerPackage|com.reprezen.demo.springboot\n{set:cellbgcolor:white}|configPackage|com.reprezen.demo.springboot.swaggerui\n{set:cellbgcolor:white}|basePackage|com.reprezen.demo.springboot\n{set:cellbgcolor:white}\n2+^e|Maven Artifacts\n{set:cellbgcolor:white}|groupId|com.reprezen.demo\n{set:cellbgcolor:white}|artifactId|petstore-demo\n{set:cellbgcolor:white}|artifactDescription|Demontration of API CodeFlow with Spring Boot generated from an OpenAPI3 doc\n{set:cellbgcolor:white}\n2+^e|Generated Java Classes\n{set:cellbgcolor:white}|openApiCodegenConfig\na|\n```\nopenApiCodegenConfig:\n  hideGenerationTimestamp: true\n  delegatePattern: true\n  # the java8 option generates default methods in interfaces.\n  # This means that omitting a required  method in an\n  # implementation class does not cause an error to be flagged.\n  # This reduces the effectiveneses of the API CodeFlow process.\n  java8: false\n```\n\nTIP: This value is a YAML object.  In order to clarify how the value should appear in the .gen file,\nwe have included the property name with the vaule. That name, `openApiCodegenConfig`, is _not_ part\nof the value.\n\n|===\n\n6. Double-click on the model project's `pom.xml` file to open it in an editor.\n+\nWARNING: Make sure this file is the one at top-level in the model project, not the file of the same\nname in the newly created GenTarget folder (or in any other GenTarget folder).\n\n7. Click on the _Dependencies_ tab at the bottom of the editor, then click on the _Add..._ button.\n+\nimage::open-pom-file.png[]\n\n8. Fill out the dialog as shown, then click _OK_. Values (for copy/paste) are:\n.. `org.openapitools`\n.. `openapi-generator`\n.. `3.2.3`\n+\nimage::pom-dependency.png[]\n\n9. Save and close the `pom.xml` editor.\n\n10. Run the generator, by clicking on the big `Generate` button in the toolbar. (Since we've been\nactively editing the `.gen` file for the _Java Spring_ GenTarget, the menu should show that as\nthe generator to run. If not, click instead on the small arrow to the right, and select\n_Spring Boot_ from the list of targets.)\n+\nimage::generate-button.png[]\n\n11. The prior step caused a new folder named `implementation` to appear in our model\nproject. Normally, generated files are placed in a folder named `generated` in the GenTarget folder,\nbut we changed that by editing the `relativeOutputDir` property in the `.gen` file.\n+\nWe will now turn that `implementation` folder into a Java project in its own right. We can do that\neasily because the generator created a Maven `pom.xml` file in the output directory.\n+\nRight-click on the `implementation` folder and select _Import..._, then select _Maven / Existing\nMaven Projects_ in the resulting dialog, and press _Next_.\n+\nYou should see your implementation folder in the _Root\nDirectory_ field, and the project should appear, already checked, in the _Projects_ list. Click\n_Finish_ to create the project.\n+\nA build of the new project will start immediately, and will probably take several seconds.\n+\nimage::import-maven.png[]\n\n=== Phase 3 - Implement\n\nOne of the generated class is an interface named `PetsApiDelegate`, in the\n`com.reprezen.demo.springboot.api` package. In the next phase we will create a corresponding\nimplementation class, containing the business logic for our service.\n\nFollow these steps:\n\n1. Modify the `pom.xml` file so that the project is built using Java 8. This is needed because we\nset the `java8` parameter to `false` in the `.gen` file. We did that to prevent generation of\ndefault methods in generated interfaces, but we really do want to build with  Java8.\n+\nOpen the `pom.xml` file in the new `petstore-demo` project, and alter its `java.version` property\nvalue to `1.8`, then save the file.\n+\nimage::pom-java8.png[]\n\n2. Now that we've modified the `pom.xml` file, we need to add it to the `.openapi.generator.ignore`\nfile, so re-generation will leave our changes in place. The file has a format similar to git's\n`.gitignore` file.\n+\nYou probably won't see this file in project explorer, because by default, files with names starting\nwith a dot are not shown. You can show them by opening the drop-down menu in the project explorer\ntoolbar and selecting _Filters and Customization..._. Uncheck the *.resources* checkbox, and you\nshould now see the `.openapi.generator.ignore` file.\n+\nimage::unfilter-dot-files.png[]\n+\nOnce you're able to see the file, open it and add `pom.xml` on a line by itself at the end.\n+\nTIP: You may want to re-check the *.* resources* filter once you've made this change.\n\n3. We need to update the project so that the pom file changes will take effect. Right-click on the project\nname, and select _Maven -\u003e Update Project...`. Press _OK_ in the dialog that appears.\n+\nimage::maven-update.png[]\n\n4. Create our implementation class. Start by right-clicking on the\n`com.reprezen.demo.springboot.api` package in the `src/main/java` folder, and select _New -\u003e\nClass_. Name the class `PetsApiDelegateImpl`.\n+\nimage::create-class.png[]\n\n\n5. Replace the text of the class definition with the following:\n+\n```Java\npackage com.reprezen.demo.springboot.api;\n\n@Service\npublic class PetsApiDelegateImpl implements PetsApiDelegate {\n \tprivate final Map\u003cLong, Pet\u003e pets = Maps.newHashMap();\n\tprivate long nextId = 0l;\n \t@Override\n\tpublic ResponseEntity\u003cPet\u003e addPet(NewPet newPet) {\n\t\tPet petToAdd = new Pet();\n\t\tpetToAdd.id(nextId++).name(newPet.getName()).tag(newPet.getTag());\n\t\tpets.put(petToAdd.getId(), petToAdd);\n\t\treturn new ResponseEntity\u003c\u003e(petToAdd, HttpStatus.CREATED);\n\t}\n \t@Override\n\tpublic ResponseEntity\u003cVoid\u003e deletePet(Long id) {\n\t\tif (!pets.containsKey(id)) {\n\t\t\treturn new ResponseEntity\u003c\u003e(HttpStatus.NOT_FOUND);\n\t\t}\n\t\tpets.remove(id);\n\t\treturn new ResponseEntity\u003c\u003e(HttpStatus.NO_CONTENT);\n\t}\n \t@Override\n\tpublic ResponseEntity\u003cPet\u003e findPetById(Long id) {\n\t\tif (!pets.containsKey(id)) {\n\t\t\treturn new ResponseEntity\u003c\u003e(HttpStatus.NOT_FOUND);\n\t\t}\n\t\treturn new ResponseEntity\u003c\u003e(pets.get(id), HttpStatus.ACCEPTED);\n\t}\n \t@Override\n\tpublic ResponseEntity\u003cList\u003cPet\u003e\u003e findPets(List\u003cString\u003e tags, Integer limitObject) {\n\t\tint limit = limitObject == null ? Integer.MAX_VALUE : limitObject;\n\t\tList\u003cPet\u003e filteredPets = pets.values().stream()//\n\t\t\t\t.filter(pet -\u003e (tags == null || tags.isEmpty()) ? true : tags.contains(pet.getTag()))//\n\t\t\t\t.limit(limit)//\n\t\t\t\t.collect(Collectors.toList());\n\t\treturn new ResponseEntity\u003c\u003e(filteredPets, HttpStatus.ACCEPTED);\n\t}\n }\n```\n+\nTIP: We are using a simple `HashMap` to keep track of our pets. A real-life implementation would\npresumably make use of a production database.\n+\nDon't freak out at all the red error markers! :-)\n\n6. Add missing imports. Right-click in the editor and select _Source -\u003e Organize Imports_.\n+\n[.thumb]\nimage::organize-imports.png[]\n\n* Choose `com.google.common.collect.Maps` to resolve the `Maps` type.\n* Choose `java.util.List` to resolve the `List` type.\n* All other types should be resolved automatically.\n\n+\nSave the file once you're finished fixing the imports.\n\n\n7. Launch the service. Right-click on the `petstore-demo` project, and select _Run As -\u003e Maven\nbuild..._. In the dialog that appears, type `spring-boot:run` in the _Goals_ field, and click\n_Run_.\n+\n[.thumb]\nimage::run-service.png[]\n\n8. Exercise the service using Swagger-UI, by visiting http://localhost:8080/[^]. If you open the\n`pets-api-controller` menu you'll see all the operations defined in the model. Click on any one of\nthem and click the _Try it out_ button to get an HTML form that you can use to actually send a\nrequest to the running service.\n+\n[.thumb]\nimage::swagger-ui.png[]\n\n=== Phase 4 - Repeat\n\nOur service does not include any means to update an existing pet, other than deleting and recreating\nthe pet - an option that will fail to retain the originally assigned pet id.\n\nWe can fix this by adding a new PUT method. The operation will expect a pet id value as a path\nparameter and the new pet data in the request payload. The effect will be to replace an existing\npet record with that id.\n\nOur approach for this and future API changes is to iterate on the API CodeFlow *Design -\u003e Generate\n-\u003e Implement* cycle.\n\n==== Repeat:Design\n\n\nOpen the `petstore-expanded.yaml` file in your model project, and add the new operation\ndefinition to the `/pets/{id}` path item.\n\nYou can copy and paste the following into the file immediately after the `/pets/{id}:` line. Be\ncareful to maintain correct indentation; the method name `put` should be indented two spaces to the\nright as compared to the `/pets/{id}` path string. Also, make sure the following `get` operation is\nstill intact; it's easy for the pasted text to omit a final newline, which will result in `get`\nappearing at the end of the last line of the put operation definition - not cool. Break up the line\nand correct indentation as needed.\n\n```\n    put: \n      description: Update a pet based on the ID\n      operationId: updatePet\n      requestBody:\n        content: \n          \"application/json\":\n            schema:\n              $ref: \"#/components/schemas/NewPet\"\n      parameters:\n        - name: id\n          in: path\n          description: ID of pet to fetch\n          required: true\n          schema:\n            type: integer\n            format: int64\n      responses:\n        200:\n          description: pet response\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Pet'\n        default:\n          description: unexpected error\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/Error'\n\n```\n==== Repeat:Generate\n\nHere we just re-run the `Spring Boot` GenTarget by pressing the big `Generate` button again.\n\nUpdated source files, reflecting the new PUT method, will replace most of the existing files in the\n`petstore-demo` project. Our implementation class is not removed, and our customized `pom.xml` file\nis not replaced (thanks to our listing it in the `.openapi-codegen-ignore` file).\n\n==== Repeat:Implement\n\nAt this point, all looks fine in the GUI, except in fact there is a problem with the `petstore-demo`\nproject. You can see this by selecting _Project -\u003e Clean..._ in the toolbar, and clicking _Clean_ in\nthe resulting dialog. This will cause the demo project to be rebuilt, and the result will be an\nerror marker on the `PetsApiDelegateImpl` class.\n\nThis is not surprising, because the interface implemented by that class now declares a method,\n`updatePet(Long, NewPet)`, that we never implemented. So of course, we now need to implement that\nmethod.\n\nOpen the `PetsApiDelegateImpl` class, and add the following method definition to the class, then\nsave the file. An automatic rebuild will then clear the error marker.\n\n```Java\n@Override\npublic ResponseEntity\u003cPet\u003e updatePet(Long id, NewPet newPet) {\n\tif (!pets.containsKey(id)) {\n\t\treturn new ResponseEntity\u003c\u003e(HttpStatus.NOT_FOUND);\n\t}\n\tpets.get(id).name(newPet.getName()).tag(newPet.getTag());\n\treturn new ResponseEntity\u003c\u003e(pets.get(id), HttpStatus.ACCEPTED);\n}\n```\n\nYou can now restart the service. Make sure to stop the previous launch first, by clicking on the red\n*Terminate* button in the _Console_ view's toolbar. When you reload the Swagger-UI page, you'll find\nthat your PUT method is now available, along with the others.\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freprezen%2Fapi-codeflow-spring-boot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freprezen%2Fapi-codeflow-spring-boot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freprezen%2Fapi-codeflow-spring-boot/lists"}