{"id":19417982,"url":"https://github.com/americanexpress/synapse","last_synced_at":"2025-10-12T19:17:11.230Z","repository":{"id":37015371,"uuid":"358688196","full_name":"americanexpress/synapse","owner":"americanexpress","description":"Synapse is a set of lightweight foundational framework modules for rapid development, built-in with enterprise-grade maturity and quality.","archived":false,"fork":false,"pushed_at":"2025-09-12T14:07:10.000Z","size":28528,"stargazers_count":34,"open_issues_count":27,"forks_count":18,"subscribers_count":15,"default_branch":"develop","last_synced_at":"2025-09-12T16:42:27.908Z","etag":null,"topics":["cloud-functions","faas","java","native","reactive","rest","rest-api","spring","webflux"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/americanexpress.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-04-16T18:33:53.000Z","updated_at":"2025-08-25T16:17:18.000Z","dependencies_parsed_at":"2024-06-11T16:37:05.478Z","dependency_job_id":"ec95da6f-ca35-4489-9342-30142aeb4165","html_url":"https://github.com/americanexpress/synapse","commit_stats":{"total_commits":641,"total_committers":20,"mean_commits":32.05,"dds":0.6349453978159126,"last_synced_commit":"9470d3bb63013959424262a2d69e5722ed4ef133"},"previous_names":[],"tags_count":67,"template":false,"template_full_name":null,"purl":"pkg:github/americanexpress/synapse","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/americanexpress%2Fsynapse","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/americanexpress%2Fsynapse/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/americanexpress%2Fsynapse/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/americanexpress%2Fsynapse/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/americanexpress","download_url":"https://codeload.github.com/americanexpress/synapse/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/americanexpress%2Fsynapse/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279012646,"owners_count":26085158,"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","status":"online","status_checked_at":"2025-10-12T02:00:06.719Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["cloud-functions","faas","java","native","reactive","rest","rest-api","spring","webflux"],"created_at":"2024-11-10T13:12:18.164Z","updated_at":"2025-10-12T19:17:11.213Z","avatar_url":"https://github.com/americanexpress.png","language":"Java","funding_links":[],"categories":["开发框架"],"sub_categories":[],"readme":"# Synapse\n\n- Tired of spending time and struggling in designing your foundational architecture and starting out your project?\n- Tired of having the developers in your team not following the consistent standards and each of them doing things their\n  own\n  way?\n- Tired of having disorganized code that is difficult to maintain after just a few months of starting your project?\n- Tired of spending countless hours, days, or months in getting your foundational frameworks robust and reliable?\n- Are you looking to speed up development time while at the same time ensuring your development team is building\n  application code in a robust manner,\n- following good design principles and patterns?\n  If any of these sound like situations you have experienced or situations you simply want to avoid, then Synapse is\n  what\n  you need.\n\nSynapse is a concept to develop at the highest upmost quality. The concept revolves around developing your systems\nutilizing\nthe most effective, efficient and battle endured design patterns and design principles.\n\nset of lightweight modules designed to speed up development time and help developers build out their\napplications. The modules are focused towards server side implementation. Synapse serves as a wide range tool-suite\nfor developers to facilitate rapid development, with high quality built-in. It is designed with the purpose of helping\ndevelopers create web services in a quick and easy way following strict conventions. Synapse provides an abstraction\nlayer that enforces developers to follow SOLID principles and avoid common mistakes during the development process. It\nis based on keeping things _simple_ and _clear_. The framework strongly encourages convention over configuration, while\nhighlighting the criticality of structure. Although Synapse will cover a majority of the scenarios you will need when\ncreating an enterprise-grade application, it is also very open to extension. We encourage you to extend and implement\nthe abstraction layer of this framework. Furthermore, if you feel the need to create a new feature not covered here, you\nalso have that flexibility.\n\n## 📖 Table of Contents\n\n- [Quick Start](#-quick-start)\n- [Documentation](#-documentation)\n- [License](#%EF%B8%8F-license)\n- [Code Of Conduct](#%EF%B8%8F-code-of-conduct)\n- [Community](#community)\n- [Contributing](#-contributing)\n\n## Synapse Architecture\n\n![Synapse Architecture](docs/docs/assets/images/synapse-architecture-1-155b44c66cccb86c8a03f5319531ee4d.png)\n\nSynapse focuses on the Application Tier of the well-established n-tier architecture pattern.\nWithin the Application Tier, Synapse is geared towards breaking down the Business and Persistence layer.\nIn the Business layer, we primarily have The modules are organized into types - the services, subscribers describe the\nmodules that initiate a workflow.\nWhile the data and client modules represent modules that need to access or modify resources.\nThe Synapse team recommends to modularize your application in a similar structure to maintain organization and clarity\nin your code.\nfor application teams to utilize the same structure\n\n## Types of Modules:\n\n### Business Layer\n\nThis layer is intended to tackle specific business needs, typically business logic or rules or some level of delegation\nthat is required by the Presentation Tier. This layer handles the delegation of work needed by the unit of work and\nstitches\nthe resource needs across the client and data modules.\n\n- **Service** - Used for any service communication method over HTTP (such as Rest, GraphQL, gRPC, etc.) that is  \n  starting a workflow. These services could be synchronous or asynchronous. The communication methods will typically\n  support imperative and reactive support.\n\n- **Business** - Used for placing common business logic across service modules.\n  Essentially serves as an extension for the service module for commonalities across multiple service or subscriber\n  modules.\n\n- **Subscriber** - Use during publisher, subscriber model. This module would initiate a flow listening to a topic or\n  channel, typically implemented in Kafka, Solace, etc.\n\n### Data Access Layer\n\nThis layer is intended to be made modular and fine-grained to promote re-usability across service or subscriber modules.\n\n- **Client** - Client modules are built to consume services. These modules are intended for performing any CRUD\n\n- **Data** - Data modules are performing CRUD operations against a resource.\n\n- **Publisher** - Publisher modules are used to share messages onto an asynchronous process\n  e\n\n### Cross-cutting Concerns / Tools\n\n- **Framework** - These type of modules are needs that are required across most enterprise applications.\n\n- **Utility** - These type of modules are generic utilities that could be reused throughout the application user's code\n  base.\n  Ideally, these should be small, lightweight modules built for the specific utility need.\n\n## Recommended Application Module/Project Structure By Layer\n\n```\napplication-name\n    |\n    +- service\n    |   +- service-customer\n    |   +- service-notification\n    |   +- service-relationship\n    |\n    +- subscriber\n    |   +- subscriber-customer\n    |   +- subscriber-notification\n    |\n    +- client\n    |    +- client-customer\n    |    +- client-customer\n    |\n    +- data\n    |    +- data-customer\n    |    +- data-notification\n    |\n```\n\nAs you can see the modules begin with the word that describes that type of module.\nThis helps ensure the modules are named intuitive and organized within your IDE.\n\n## Synapse Modules:\n\n### synapse-service-rest\n\n- This module provides an abstraction framework used to help expose RESTful APIs. It provides several out-of-the-box\n  functionalities like:\n\n    - An open to extension generic set of abstract controller classes to easily build any concrete CRUD\n      Controller by simply extending the needed base CRUD Controller class.\n    - An open to extension configuration file that support for most of the available media types for RESTful\n      webservices. If needed, new ones could be added. Also provides a default ObjectMapper for its serialization and\n      deserialization. This can be overridden.\n    - An open to extension generic ControllerExceptionHandler that handles the most common types of errors happening in\n      an application.\n    - An open to extension way of handling input validations.\n    - An open to extension generic MetricInterceptor that will log the response time, status code and correlation\n      identifier for every request.\n    - Open to extensions base request and response model to leave the code open to extension and close to modifications.\n    - A generic already implemented pagination solution out of the box when calling a db.\n    - A common error response object following standard naming of error fields.\n    - Spring Webflux is used for reactive support leveraging Netty, while Spring Web is also supported in Synapse\n\n### synapse-client-rest\n\n- This is the synapse gateway framework utilized to consume RESTful APIs. It provides several out-of-the-box\n  functionalities like:\n\n    - An open to extension BaseRestClient with several overloaded methods for every single possible restful call.\n    - A configurable ClientLoggingInterceptor that logs the request and response parameters at a configurable log level.\n    - An open to extension BaseRestResponseErrorHandler that handles the errors generated when calling the external\n      restful APIs. This error handler has several default functionalities but is also open to extension. The\n      functionalities are:\n        - Log at error level the body and status code of the error returned. - Throw a HttpClientErrorException when an\n          error of the 4XX family occurs - Throw a HttpServerErrorException when an error of the 5XX family occurs.\n    - An open to extension generic hmac generator class.\n\n### synapse-client-soap\n\n- This is the synapse gateway framework utilized to consume SOAP web services. It provides several out-of-the-box\n  functionalities like:\n\n    - An open to extension BaseSoapClient with several overloaded methods for every single possible soap call.\n\n### synapse-data-couchbase\n\n- This is the synapse couchbase abstraction framework used whenever there is a need to connect to couchbase database and\n  read from it. It provides several out-of-the-box functionalities like:\n\n    - Built-in read functionalities to create multi-parameter and paginated dynamic queries based on Spring Data and\n      QueryDSL.(There is not other library like this out-there, it still needs some work).\n    - An open to extension base configuration java file with the standard connection parameters needed to connect to\n      couchbase using Spring Data. The connection parameters will be provided by the property files on the module(s)that\n      you as a developer are creating that will use this base-data-postgres module as a dependency.\n    - An open to extension BaseEntity containing the generated key identifier and the common auditing fields maintained\n      by the Spring Data framework itself (createdBy, lastModifiedBy, createdDate, lastModifiedDate and version).\n\n### synapse-data-postgres\n\n- This is the synapse data relational database abstraction framework used whenever there is a need to connect to\n  postgres database. It provides several out-of-the-box functionalities like:\n\n    - An open to extension base configuration java file open to extension that provides the connection logic to connect\n      to any relational database and create a hikari connection pool. The connection parameters will be provided by\n      property files on the modules using this module.\n    - Open to extension property files with the default following values:\n        - An open to extension connection pool default parameters. - An open to extension H2 connection parameters for\n          local property file. - An open to extens4ion H2 initialization parameters for local property file. - An open\n          to extension any relational database initialization parameters for three extra environments(E1, E2 and E3).\n\n    - An open to extension BaseEntity that contains the key identifier with a default(open to extension also)\n      GenerationType.IDENTITY and the common auditing fields maintained by the Spring Data framework itself (createdBy,\n      lastModifiedBy, createdDate, lastModifiedDate and version).\n\n### synapse-framework-exception\n\n- This is the synapse module that provides the two Exception classes you will ever need in your application and also an\n  elegant mechanism to handle them. It provides several out-of-the-box functionalities like:\n\n    - An ApplicationServerException to wrap the caught checked exceptions thrown by the application.\n    - An ApplicationClientException to return a user-friendly message to the users when a warning or message needs to be\n      returned.\n    - A generic open to extension ErrorCode enum with the most common error codes used by any application.\n    - A generic open to extension error-messages.properties file that uses the error codes from the ErrorCode enum\n      mentioned above.\n\n### synapse-service-test\n\n- This is the synapse module that provides the base classes to test the controllers. It provides several out-of-the-box\n  functionalities like:\n\n    - An open to extension BaseControllerTest class with several overloaded methods create the slice test methods of any\n      possible restful call made to your controllers.\n    - An open to extension BaseControllerIT class with several overloaded methods to create the integration test methods\n      of any possible restful call made to your controllers.\n\n### synapse-client-test\n\n- This is the synapse module that provides the base classes to test the spring restful clients. It provides several\n  out-of-the-box functionalities like:\n\n    - An open to extension BaseRestClientUnitTest class which already calls several methods to unit test all the\n      scenarios in the concrete client unit test class that extend this.\n    - An open to extension BaseRestClientUnitIT class that will require only the concrete rest client IT class\n      implementing it to override one success method which will be the integration test method needed.\n\n### synapse-framework-api-docs\n\n- This is the synapse module used for api documentation. This module is essentially a wrapper around swagger-ui, where\n  it is already hooked on Synapse Rest framework, to provide Swagger UI out of the box for any rest api's built\n  utilizing Synapse.\n\n### synapse-utilities-common\n\n- Encapsulates the common utility classes that can be leveraged by any module. It provides several out-of-the-box\n  functionalities like:\n\n    - A default object mapper defined in its configuration file\n\n-----\n\n## Benefits on-top Spring\n\n- The Synapse framework is an extension of Spring that uses best practices to force compliance to good standards, while\n  also simplifying the development process. These are several of the benefits it provides on-top of what Spring already\n  provides:\n    - Creates a very structured and organized architecture very easy to follow by anyone, junior and senior developers.\n    - Enforces developers to follow the same template and good standards across the entire code base.\n    - Forces strict separation of concerns because the base 'Hook' classes which the developers extend from are already\n      representing each layer in the famous and already proven three layer architecture. - Base\u003cCrud functionality\u003e\n      Controller (Http Layer). - Base\u003cCrud functionality\u003eService (Service Layer). - BaseRestClient, BaseSoapClient or\n      Repositories(These are already interfaces so not base classes provided) (DAO Layer).\n    - Provides the BaseControllerTest class with a set of overloaded methods to facilitate controllers slice testing.\n    - Provides a couchbase library to build dynamic queries based on Spring Data and Query DSL (There is nothing like\n      this out there).\n    - Provides a ControllersExceptionHandlers that handles most of the common exceptions.\n    - Provides an elegant and very simple to use exception handling mechanism with only two custom runtime exceptions\n      that covers all the possible scenarios.\n    - Provides a generic way to connect to any relational database, using h2 for local and unit tests. And leave free\n      the use of any desired relational database for other environments.\n\n## Credits and Acknowledgements:\n\n**Authors**\n\n- Gabriel Jimenez\n- Alexei Morgado\n- Paolo Claudio\n- Darien Liburd\n- Shahzada Azam\n- Krishna Kuchikulla\n\n## 🚀‍ Quick Start\n\n### Building an Enterprise Ready RESTful Web Service utilizing Synapse\n\n### What you will build\n\nThis guide walks you through the process of creating a “Hello, World” RESTful web service with Synapse.\n\nIt will respond with a JSON representation of a greeting, as the following listing shows:\n\n```json\n{\n  \"message\": \"Hello, World!\"\n}\n```\n\nYou can customize the greeting with an optional name parameter in the query string, as the following listing shows:\n\n```http://localhost:8080/greeting?name=User```\n\nThe name parameter value overrides the default value of World and is reflected in the response, as the following listing\nshows:\n\n```json\n{\n  \"message\": \"Hello, User!\"\n}\n```\n\n### What You Need\n\n- About 15 minutes\n- A favorite text editor or IDE\n- JDK 1.8+\n- Gradle 4+ or Maven 3.2+\n\nYou can also import the code straight into your IDE:\n\n- IntelliJ IDEA\n- Spring Tool Suite (STS)\n\nThe following listing shows the pom.xml file that is created when you choose Maven:\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003cproject xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\"\u003e\n    \u003cparent\u003e\n        \u003cgroupId\u003ecom.sample.bookstore\u003c/groupId\u003e\n        \u003cartifactId\u003eservice\u003c/artifactId\u003e\n        \u003cversion\u003e0.4.0-SNAPSHOT\u003c/version\u003e\n    \u003c/parent\u003e\n\n    \u003cmodelVersion\u003e4.0.0\u003c/modelVersion\u003e\n    \u003cgroupId\u003ecom.sample.bookstore\u003c/groupId\u003e\n    \u003cartifactId\u003eservice-greeting\u003c/artifactId\u003e\n    \u003cversion\u003e0.3.32-SNAPSHOT\u003c/version\u003e\n\n    \u003cproperties\u003e\n        \u003cstart-class\u003ecom.sample.bookstore.GreetingApplication\u003c/start-class\u003e\n    \u003c/properties\u003e\n\n    \u003cdependencies\u003e\n        \u003cdependency\u003e\n            \u003cgroupId\u003eio.americanexpress.synapse\u003c/groupId\u003e\n            \u003cartifactId\u003esynapse-service-rest\u003c/artifactId\u003e\n        \u003c/dependency\u003e\n    \u003c/dependencies\u003e\n\n    \u003cbuild\u003e\n        \u003cplugins\u003e\n            \u003cplugin\u003e\n                \u003cgroupId\u003eorg.springframework.boot\u003c/groupId\u003e\n                \u003cartifactId\u003espring-boot-maven-plugin\u003c/artifactId\u003e\n                \u003cexecutions\u003e\n                    \u003cexecution\u003e\n                        \u003cgoals\u003e\n                            \u003cgoal\u003erepackage\u003c/goal\u003e\n                        \u003c/goals\u003e\n                    \u003c/execution\u003e\n                \u003c/executions\u003e\n            \u003c/plugin\u003e\n            \u003cplugin\u003e\n                \u003cartifactId\u003emaven-compiler-plugin\u003c/artifactId\u003e\n            \u003c/plugin\u003e\n            \u003cplugin\u003e\n                \u003cartifactId\u003emaven-jar-plugin\u003c/artifactId\u003e\n            \u003c/plugin\u003e\n        \u003c/plugins\u003e\n    \u003c/build\u003e\n\n\u003c/project\u003e\n\n```\n\n### Create a Resource Representation class\n\nNow that you have set up the project and build system, you can create your web service.\n\nBegin the process by thinking about service interactions.\n\nThe service will handle POST requests for /greetings, optionally with a name parameter in the query string. The POST\nrequest should return a 200 OK response with JSON in the body that represents a greeting. It should resemble the\nfollowing output:\n\n```json\n   {\n  \"message\": \"Hello, User!\"\n}\n```\n\nThe id field is a unique identifier for the greeting, and content is the textual representation of the greeting.\n\nTo model the greeting representation, create a resource representation class. To do so, provide a plain old Java object\nwith fields, constructors, and accessors for the id and content data, as the following listing (from\nsrc/main/java/com/example/restservice/Greeting.java) shows:\n\nBelow is the request model.\n\n```java\npackage com.sample.bookstore.model;\n\nimport BaseServiceRequest;\n\nimport java.util.Objects;\n\npublic class GreetingRequest extends BaseServiceRequest {\n\n    private String name;\n\n    public GreetingRequest(String name) {\n        this.name = name;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        GreetingRequest that = (GreetingRequest) o;\n\n        return Objects.equals(name, that.name);\n    }\n\n    @Override\n    public int hashCode() {\n        return name != null ? name.hashCode() : 0;\n    }\n}\n\n```\n\nBelow is the response model.\n\n```java\npackage com.sample.bookstore.model;\n\nimport BaseServiceResponse;\n\nimport java.util.Objects;\n\npublic class GreetingResponse extends BaseServiceResponse {\n\n    private String message;\n\n    public GreetingResponse(String message) {\n        this.message = message;\n    }\n\n    public String getMessage() {\n        return message;\n    }\n\n    public void setMessage(String message) {\n        this.message = message;\n    }\n\n\n    @Override\n    public String toString() {\n        return \"GreetingResponse{\" +\n                \"message='\" + message + '\\'' +\n                '}';\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        GreetingResponse that = (GreetingResponse) o;\n\n        return Objects.equals(message, that.message);\n    }\n\n    @Override\n    public int hashCode() {\n        return message != null ? message.hashCode() : 0;\n    }\n}\n```\n\n```java\npackage com.sample.bookstore;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * \u003ccode\u003eGreetingApplication\u003c/code\u003e class that runs this service.\n *\n * @author Gabriel Jimenez\n */\n@SpringBootApplication\npublic class GreetingApplication {\n\n    /**\n     * Run the application as a SpringBoot application.\n     *\n     * @param args program arguments\n     */\n    public static void main(String[] args) {\n        SpringApplication.run(GreetingApplication.class, args);\n    }\n\n}\n\n```\n\n### Create a Resource Controller\n\nIn Spring’s approach to building RESTful web services, HTTP requests are handled by a controller. These components are\nidentified by the @RestController annotation, and the GreetingController shown in the following listing (from\nsrc/main/java/com/example/restservice/GreetingController.java)\nhandles GET requests for /greeting by returning a new instance of the Greeting class:\n\n```java\npackage com.sample.bookstore.controller;\n\nimport BaseController;\nimport com.sample.bookstore.model.GreetingRequest;\nimport com.sample.bookstore.model.GreetingResponse;\nimport com.sample.bookstore.service.GreetingService;\nimport io.swagger.annotations.Api;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n\n/**\n * \u003ccode\u003eGreetingController\u003c/code\u003e class is the controller that handles the greeting requests.\n * on the endpoint /greetings\n *\n * @author Gabriel Jimenez\n */\n@RestController\n@RequestMapping(\"/greetings\")\n@Api(value = \"Greeting API\", tags = \"Greeting\")\npublic class GreetingController extends BaseController\u003cGreetingRequest, GreetingResponse, GreetingService\u003e {\n}\n```\n\n### Create a API Config\n\n```java\npackage com.sample.bookstore.config;\n\nimport com.americanexpress.synapse.service.rest.config.BaseServiceRestConfig;\nimport org.springframework.context.annotation.ComponentScan;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.Import;\nimport org.springframework.context.annotation.PropertySource;\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurer;\n\n/**\n * \u003ccode\u003eGreetingConfig\u003c/code\u003e class sets configurations used in this module.\n *\n * @author Gabriel Jimenez\n */\n@Configuration\n@PropertySource(\"classpath:/service-greeting-application.properties\")\n@Import({BaseServiceRestConfig.class})\n@ComponentScan(basePackages = \"com.example.synapse.bookstore\")\npublic class GreetingConfig implements WebMvcConfigurer {\n}\n```\n\n### Create a Resource Service\n\n```java\npackage com.sample.bookstore.service;\n\nimport ServiceHeaders;\nimport BaseService;\nimport com.sample.bookstore.model.GreetingRequest;\nimport com.sample.bookstore.model.GreetingResponse;\nimport org.springframework.stereotype.Service;\n\nimport static java.util.Objects.nonNull;\n\n/**\n * The \u003ccode\u003eGreetingService\u003c/code\u003e class is responsible handling the business logic of the Greeting API. \n */\n@Service\npublic class GreetingService extends BaseService\u003cGreetingRequest, GreetingResponse\u003e {\n\n    private static final String template = \"Hello, %s!\";\n\n    @Override\n    protected GreetingResponse getResource(ServiceHeaders headers, GreetingRequest request) {\n        if (nonNull(request.getName())) {\n            return new GreetingResponse(String.format(template, request.getName()));\n        } else {\n            return new GreetingResponse(String.format(template, \"World!\"));\n        }\n    }\n}\n```\n\nNow make sure to set your environment to `local`:\n\n### Summary\n\nCongratulations! You built a simple web application utilizing Synapse and learned how it can ramp up your development\npace. You also turned on some handy production services. This is only a small sampling of what Synapse can do.\n\n## 📜 Documentation\n\nhttps://americanexpress.io/synapse/\n\n## 🏆 Contributing\n\nWe welcome Your interest in the American Express Open Source Community on Github. Any Contributor to any Open Source\nProject managed by the American Express Open Source Community must accept and sign an Agreement indicating agreement to\nthe terms below. Except for the rights granted in this Agreement to American Express and to recipients of software\ndistributed by American Express, You reserve all right, title, and interest, if any, in and to Your Contributions.\nPlease\n[fill out the Agreement](https://cla-assistant.io/americanexpress/synapse).\n\n## 🗝️ License\n\nAny contributions made under this project will be governed by the\n[Apache License 2.0](./LICENSE).\n\n## 🗣️ Code of Conduct\n\nThis project adheres to the [American Express Community Guidelines](./CODE_OF_CONDUCT.md). By participating, you are\nexpected to honor these guidelines.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famericanexpress%2Fsynapse","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Famericanexpress%2Fsynapse","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famericanexpress%2Fsynapse/lists"}