{"id":19892170,"url":"https://github.com/broadleafcommerce/spring-frameworkmapping","last_synced_at":"2025-09-18T22:33:04.970Z","repository":{"id":57739016,"uuid":"146008396","full_name":"BroadleafCommerce/spring-frameworkmapping","owner":"BroadleafCommerce","description":"Overridable Spring Web request mappings","archived":false,"fork":false,"pushed_at":"2024-09-13T19:33:22.000Z","size":202,"stargazers_count":2,"open_issues_count":5,"forks_count":2,"subscribers_count":14,"default_branch":"develop","last_synced_at":"2025-07-24T02:02:49.832Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/BroadleafCommerce.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-08-24T15:25:17.000Z","updated_at":"2022-11-09T14:52:18.000Z","dependencies_parsed_at":"2024-11-12T18:32:54.914Z","dependency_job_id":null,"html_url":"https://github.com/BroadleafCommerce/spring-frameworkmapping","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/BroadleafCommerce/spring-frameworkmapping","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BroadleafCommerce%2Fspring-frameworkmapping","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BroadleafCommerce%2Fspring-frameworkmapping/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BroadleafCommerce%2Fspring-frameworkmapping/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BroadleafCommerce%2Fspring-frameworkmapping/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/BroadleafCommerce","download_url":"https://codeload.github.com/BroadleafCommerce/spring-frameworkmapping/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BroadleafCommerce%2Fspring-frameworkmapping/sbom","scorecard":{"id":24673,"data":{"date":"2025-08-11","repo":{"name":"github.com/BroadleafCommerce/spring-frameworkmapping","commit":"d7c1de3913004d7092f48bdd1ddb86f4cfddaf7f"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.9,"checks":[{"name":"Code-Review","score":2,"reason":"Found 6/30 approved changesets -- score normalized to 2","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":9,"reason":"binaries present in source code","details":["Warn: binary detected: .mvn/wrapper/maven-wrapper.jar:1"],"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'develop'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 6 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"11 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-rc42-6c7j-7h5r","Warn: Project is vulnerable to: GHSA-4gc7-5j7h-4qph","Warn: Project is vulnerable to: GHSA-4wp7-92pw-q264","Warn: Project is vulnerable to: GHSA-2rmj-mq67-h97g","Warn: Project is vulnerable to: GHSA-2wrp-6fg6-hmc5","Warn: Project is vulnerable to: GHSA-6r3c-xf4w-jxjm","Warn: Project is vulnerable to: GHSA-ccgv-vj62-xf9h","Warn: Project is vulnerable to: GHSA-hgjh-9rj2-g67j","Warn: Project is vulnerable to: GHSA-cx7f-g6mp-7hqm","Warn: Project is vulnerable to: GHSA-g5vr-rgqm-vf78","Warn: Project is vulnerable to: GHSA-mjmj-j48q-9wg2"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-14T17:36:19.535Z","repository_id":57739016,"created_at":"2025-08-14T17:36:19.535Z","updated_at":"2025-08-14T17:36:19.535Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275844407,"owners_count":25538991,"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-09-18T02:00:09.552Z","response_time":77,"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":[],"created_at":"2024-11-12T18:22:04.309Z","updated_at":"2025-09-18T22:33:04.596Z","avatar_url":"https://github.com/BroadleafCommerce.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":":toc:\n\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\n= Spring Frameworkmappings\n\nimage::https://maven-badges.herokuapp.com/maven-central/org.broadleafcommerce/spring-frameworkmapping/badge.svg[link=\"https://maven-badges.herokuapp.com/maven-central/org.broadleafcommerce/spring-frameworkmapping\"]\n\nSpring Frameworkmappings is a support library for developers distributing libraries to their users. This enables library developers to distribute overridable Spring MVC request mappings that will not collide with user-defined `@RequestMapping`, allowing for customizability and extensibility. Spring-frameworkmappings is tested for compatibility with Spring 5.0+ and Spring Boot 2.0+ but would likely work on older versions of Spring/Spring Boot.\n\nHere's an example:\n\n[source,java]\n----\n@FrameworkController\npublic class LibraryController {\n\n  @ResponseBody\n  @FrameworkGetMapping(\"/test\")\n  public String test() {\n    return \"library\";\n  }\n}\n...\n...\n...\n@Controller\npublic class UserController {\n\n  @ResponseBody\n  @GetMapping(\"/test\")\n  public String test() {\n    return \"user\";\n  }\n}\n----\n\nWith both the `@Controller` and `@FrameworkController` active, hitting the `/test` endpoint will return `user`. But if a corresponding `/test` `@RequestMapping` was _not_ defined, the value returned would be `library`.\n\n== Usage\n\nAdd the dependency with Maven:\n\n[source,xml]\n----\n\u003cdependency\u003e\n  \u003cgroupId\u003eorg.broadleafcommerce\u003c/groupId\u003e\n  \u003cartifactId\u003espring-frameworkmapping\u003c/artifactId\u003e\n  \u003cversion\u003e$currentversion\u003c/version\u003e\n\u003c/dependency\u003e\n----\n\nOr Gradle\n\n[source,groovy]\n----\ndependencies {\n  compile 'org.broadleafcommerce:spring-frameworkmapping:$currentversion'\n}\n----\n\nThen use `@FrameworkController` and the corresponding `@FrameworkMapping` just like you would an `@Controller` and `@RequestMapping`. Example:\n\n[source,java]\n----\n@FrameworkController\npublic void DefaultedController {\n\n    @FrameworkRequestMapping(\"/test\")\n    public String getAString() {\n        return \"path/to/template\";\n    }\n}\n----\n\nThen activate the controllers just like you would an `@ComponentScan`, but with `@FrameworkControllerScan`\n\n[source,java]\n----\n@Configuration\n@FrameworkControllerScan(basePackageClasses = DefaultedController.class)\npublic void ControllerConfig {\n}\n----\n\nIMPORTANT: `@FrameworkControllerScan` utilizes a composition of `@ComponentScan` and as such cannot be specified alongside a class that is annotated with another `@ComponentScan` or an annotation that is composed of `@ComponentScan` (such as `@SpringBootApplication`). Instead, created a static nested class inside of that `@Configuration` class that instruments the scan\n\nIf you do not want to do a scan, you can annotate individual `@Bean` methods:\n\n[source,java]\n----\n@Configuration\npublic class LibraryAutoConfiguration {\n\n  @Bean\n  @FrameworkController\n  public DefaultedController defaultController() {\n    return new DefaultedController();\n  }\n}\n----\n\n== Convenience Annotations\n\nConvenience annotations also exist for specific request methods:\n\n[source,java]\n----\n@FrameworkController\n@RequestMapping(\"/test\")\npublic void DefaultedController {\n\n    @GetMapping(\"/get\")\n    public @ResponseBody String getAString() {\n        return \"Success!\";\n    }\n}\n----\n\nOr as a correlary to `@RestController`-, use `@FrameworkRestController`:\n\n[source,java]\n----\n@FrameworkRestController\n@FrameworkRequestMapping(\"/test\")\npublic void DefaultedController {\n\n    @FrameworkGetMapping(\"/get\")\n    public @ResponseBody String getAString() {\n        return \"Success!\";\n    }\n}\n----\n\n== Building URIs\n\nTo build a URI\n\n[source,java]\n----\n@FrameworkRestController\npublic class DefaultTestController {\n\n  @FrameworkGetMapping(\"/test/{pathvar}\")\n  public ResponseEntity test(@PathVariable(\"pathvar\") String variable) {\n    return ResponseEntity.of(\"Success!\");\n  }\n}\n----\n\nBuild a URI with the same sort of patterns of `MvcUriComponentsBuidler`:\n\n[source,java]\n----\nFrameworkMvcUriComponentsBuilder.fromMethodCall(\n    on(DefaultTestController.class).test(\"value\"))\n        .build()\n        .toUri()\n----\n\n== Test Support with `@WebMvcTest`\n\nSince the use case for this library is for distributing other libraries, make sure that you have a `spring.factories` entry that corresponds to the `@AutoConfigureWebMvc` test slice:\n\n[source,ini]\n----\norg.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureWebMvc=\\\n    com.mycompany.mylibrary.package.MyControllerAutoConfiguration\n----\n\nIf you are scanning your framework controllers `@WebMvcTest`, the controller might not be available in your ApplicationContext from the component scan. This needs to be manually enabled in an `@WebMvcTest`.\n\nNOTE: Using manual `@Bean` methods annotated with `@FrameworkController` eliminates this issue\n\nTo enable a single controller, use the `controllers` attribute of `@WebMvcTest`:\n\n[source,java]\n----\n@WebMvcTest(controllers = TestController.class)\n@ExtendWith(SpringExtension.class)\npublic class ControllerTest {\n\n    @Configuration\n    class Config {\n        @Bean\n        public TestController testController() {\n            return new TestController();\n        }\n    }\n\n    @FrameworkController\n    public class TestController {\n\n        @GetMapping(\"/test\")\n        public String test() {\n            return \"Success!\";\n        }\n    }\n\n    @Autowired\n    MockMvc mockMvc;\n\n    @Test\n    public void controllersWork() throws Exception {\n        mockMvc.perform(get(\"/test\"))\n            .andExpect(status().isOk());\n    }\n\n}\n----\n\nIf you want to enable a group of `@FrameworkMapping`-annotated controllers use `includeFilters`:\n\n[source,java]\n----\n@WebMvcTest(includeFilters = @Filter(FrameworkController.class))\n@FrameworkControllerScan\n@ExtendWith(SpringExtension.class)\npublic class ControllerTest {\n\n    @Autowired\n    MockMvc mockMvc;\n\n    @Test\n    public void controllersWork() throws Exception {\n        mockMvc.perform(get(\"/test\"))\n                .andExpect(status().isOk());\n    }\n\n}\n\n@FrameworkController\npublic class TestController {\n\n  @GetMapping(\"/test\")\n  public String test() {\n    return \"Success!\";\n  }\n}\n----\n\nNOTE: `@FrameworkController`s that are _scanned_ using `@FrameworkControllerScan` within a test class will not be picked up. This is because of the exclusions within `TestTypeExcludeFilter`. Remediations are to either move your `@FrameworkController` to a class outside of a test class, or manually create it with `@Bean`\n\n== Other use Cases\n\n=== Excluding Controllers in a Scan\n\nIn the event you want to enable framework controllers, but want to exclude particular framework controllers, you can leverage the `excludeFilters` property of the `@FrameworkControllerScan`. For example:\n\n[source,java]\n----\n@FrameworkControllerScan(basePackages = \"com.mypackage.packagewithcontrollers\",\n  excludeFilters = {\n    @Filter(value = DefaultCustomerController.class, type = FilterType.ASSIGNABLE_TYPE),\n    @Filter(value = DefaultOrderController.class, type = FilterType.ASSIGNABLE_TYPE)\n})\n----\n\n=== Including a Single Controller\n\nIf you only want a small number of framework controllers enabled, it would be easier to declare the ones you want as beans instead of listing a large number of controllers using `excludeFilters`.\n\nFor example, you can activate a single framework controller in an `@Configuration` class like so:\n\n[source,java]\n----\n@Bean\npublic DefaultCartController defaultCartController() {\n    return new DefaultCartController();\n}\n----\n\nAlternatively, you may utilize `includeFilters` of `@FrameworkControllerScan` and override its value to include just a few controllers:\n\n[source,java]\n----\n@FrameworkControllerScan(basePackages = \"com.mypackage.packagewithcontrollers\",\n  includeFilters = {\n    @Filter(value = DefaultCustomerController.class, type = FilterType.ASSIGNABLE_TYPE),\n    @Filter(value = DefaultOrderController.class, type = FilterType.ASSIGNABLE_TYPE)\n})\n----\n\n=== Extending default mappings\n\nOr if you want to call super, you could extend the default framework controller as well like so:\n\n[source,java]\n----\n@RestController\n@RequestMapping(\"/cart\")\npublic class MyCartController extends DefaultCartController {\n    @RequestMapping(path = \"/get\", method = RequestMethod.GET)\n    public MyCart getActiveCart() {\n        Cart cart = super.getActiveCart();\n        return doCustomThingsToCart(cart);\n    }\n}\n----\n\n=== Changing a Mapping\n\nIf you want to alter the URL for some mapping, you can do so by defining your own mapping and calling super.\n\nFor example, given the framework controller:\n\n[source,java]\n----\n@FrameworkRestController\n@FrameworkMapping(\"/cart\")\npublic class DefaultCartController {\n    @FrameworkMapping(path = \"/get\", method = RequestMethod.GET)\n    public Cart getActiveCart() {\n        return cartService.getActiveCart();\n    }\n}\n----\n\nYou can change the mapping by extending the framework controller, and calling super with a new mapping:\n\n[source,java]\n----\n@RestController\n@RequestMapping(\"/cart\")\npublic class MyCartController extends DefaultCartController {\n    @RequestMapping(path = \"/retrieve\", method = RequestMethod.GET)\n    public Cart getActiveCart() {\n        return super.getActiveCart();\n    }\n}\n----\n\nNow we've created a new mapping `/cart/retrieve`, but note that `/cart/get` will still be registered.\n\n=== Changing a Mapping and Functionality\n\nThis is achieved by simply applying both patterns above.\n\n=== Removing a Mapping\n\nIf you want to remove (disable) particular a `@FrameworkMapping` then you'll need to create a `@RequestMapping` method with the same URL that returns a 404 error.\n\nFor example, to disable `/cart/get`:\n\n[source,java]\n----\n@RestController\n@RequestMapping(\"/cart\")\npublic class MyCartController extends DefaultCartController {\n    @RequestMapping(path = \"/get\", method = RequestMethod.GET)\n    public ResponseEntity getActiveCart() {\n        return new ResponseEntity(HttpStatus.NOT_FOUND);\n    }\n}\n----\n\n== Appendix\n\n=== Supporting Classes\n\n[cols=2*,options=\"header\"]\n|===\n|Class Name\n|Description\n\na|`FrameworkControllerHandlerMapping`\n|Component that registers controllers annotated with `@FrameworkController` and `@FrameworkRestController`\n\n| `FrameworkMvcUriComponentsBuilder`\n| Copied from `MvcUriComponentsBuilder` in order to provide URI building functionality for `@FrameworkMapping` annotations. It replicates the functionality of `MvcUriComponentsBuilder`\n|===\n\n=== Snapshots\n\nSnapshots are deployed to the Maven Central Snapshots repository and is deployed on every commit. Add it to your `\u003crepositories\u003e` like so:\n\n[source,xml]\n----\n\u003crepositories\u003e\n  \u003crepository\u003e\n    \u003cid\u003emavencentral-snapshots\u003c/id\u003e\n     \u003curl\u003ehttps://oss.sonatype.org/content/repositories/snapshots\u003c/url\u003e\n     \u003csnapshots\u003e\n       \u003cenabled\u003etrue\u003c/enabled\u003e\n     \u003c/snapshots\u003e\n     \u003creleases\u003e\n       \u003cenabled\u003efalse\u003c/enabled\u003e\n     \u003c/releases\u003e\n  \u003c/repository\u003e\n\u003c/repositories\u003e\n----\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbroadleafcommerce%2Fspring-frameworkmapping","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbroadleafcommerce%2Fspring-frameworkmapping","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbroadleafcommerce%2Fspring-frameworkmapping/lists"}