{"id":27255697,"url":"https://github.com/bric3/jersey-webmvc","last_synced_at":"2026-05-05T23:32:11.833Z","repository":{"id":142486818,"uuid":"201244383","full_name":"bric3/jersey-webmvc","owner":"bric3","description":"Configuration and code to enable Spring WebMVC and Jersey endpoints to co-exists in Spring Boot 2.1","archived":false,"fork":false,"pushed_at":"2020-11-27T14:12:45.000Z","size":75,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-11T02:48:12.831Z","etag":null,"topics":["jersey2","spring","spring-boot-2","spring-mvc"],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bric3.png","metadata":{"files":{"readme":"README.adoc","changelog":null,"contributing":null,"funding":null,"license":null,"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,"zenodo":null}},"created_at":"2019-08-08T11:30:06.000Z","updated_at":"2020-11-27T14:12:48.000Z","dependencies_parsed_at":null,"dependency_job_id":"5f047585-c645-48d5-8130-8240b83afd70","html_url":"https://github.com/bric3/jersey-webmvc","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/bric3/jersey-webmvc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bric3%2Fjersey-webmvc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bric3%2Fjersey-webmvc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bric3%2Fjersey-webmvc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bric3%2Fjersey-webmvc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bric3","download_url":"https://codeload.github.com/bric3/jersey-webmvc/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bric3%2Fjersey-webmvc/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32672600,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-05T11:29:49.557Z","status":"ssl_error","status_checked_at":"2026-05-05T11:29:48.587Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["jersey2","spring","spring-boot-2","spring-mvc"],"created_at":"2025-04-11T02:21:27.116Z","updated_at":"2026-05-05T23:32:11.827Z","avatar_url":"https://github.com/bric3.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"= Workaround Spring Boot unability to make Jersey and Spring MVC co-exist\n:icons: font\n:url-sb-17523: https://github.com/spring-projects/spring-boot/issues/17523\n:servlet-filter-mitigation: https://github.com/bric3/jersey-webmvc/blob/master/src/main/java/com/github/bric3/jerseywebmvc/servlet_filter_mitigation/SpringMvcPrefixEnforcerFilter.java\n:spring-config-mitigation: https://github.com/bric3/jersey-webmvc/blob/master/src/main/java/com/github/bric3/jerseywebmvc/spring_configuration_mitigation/SpringWebMvcHackConfiguration.java\n\n:res-get-rd: https://github.com/spring-projects/spring-framework/blob/5.1.x/spring-webmvc/src/main/java/org/springframework/web/servlet/view/InternalResourceView.java#L149-L150\n:res-rd-forward: https://github.com/spring-projects/spring-framework/blob/5.0.x/spring-webmvc/src/main/java/org/springframework/web/servlet/view/InternalResourceView.java#L170\n:dispatcher-autoconf: https://github.com/spring-projects/spring-boot/blob/2.1.x/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/DispatcherServletAutoConfiguration.java\n:dispatcher-reg-bean: https://github.com/spring-projects/spring-boot/blob/2.1.x/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/DispatcherServletRegistrationBean.java\n:dispatcher-path: https://github.com/spring-projects/spring-boot/blob/2.1.x/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/DispatcherServletPath.java\n\n:webmvc-configurer: https://github.com/spring-projects/spring-framework/blob/5.1.x/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.java\n:pathmatch-configurer: https://github.com/spring-projects/spring-framework/blob/5.1.x/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/PathMatchConfigurer.java\n:webmvc-configurer-support: https://github.com/spring-projects/spring-framework/blob/5.1.x/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java\n:abstract-handler-mapping: https://github.com/spring-projects/spring-framework/blob/5.1.x/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java\n:patterns-condition: https://github.com/spring-projects/spring-framework/blob/5.1.x/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/PatternsRequestCondition.java\n\n\n:req-mapping-handler-mapping: https://github.com/spring-projects/spring-framework/blob/5.1.x/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java\n:url-path-helper: https://github.com/spring-projects/spring-framework/blob/5.1.x/spring-web/src/main/java/org/springframework/web/util/UrlPathHelper.java\n:actuator-webmvc-mapping: https://github.com/spring-projects/spring-boot/blob/2.1.x/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/servlet/WebMvcEndpointHandlerMapping.java\n:actuator-abstract-webmvc-mapping: https://github.com/spring-projects/spring-boot/blob/2.1.x/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/servlet/AbstractWebMvcEndpointHandlerMapping.java\n\nIn the current code if the Jersey component is active (with the `jersey`\nprofile) then all Spring Web MVC endpoint are not available anymore, if both are\nusing the same root `/`.\nRun tests in `com.github.bric3.jerseywebmvc.JerseyWebmvcApplicationTests`.\n\n.without `jersey` profile\n. `GET /jaxrs` =\u003e `404 Not Found` but Jersey is not active\n. `GET /actuator/status` =\u003e `200 OK`\n. `GET /favicon.ico` =\u003e `200 OK`\n. `GET /doc/` =\u003e `200 OK`\n. `GET /doc/index.html` =\u003e `200 OK`\n. `GET /rest/` =\u003e `200 OK`\n\n.with `jersey` profile\n. `GET /jaxrs` =\u003e `200 OK`\n. `GET /actuator/status` =\u003e `404 Not Found`\n. `GET /favicon.ico` =\u003e `404 Not Found`\n. `GET /doc/` =\u003e `404 Not Found`\n. `GET /doc/index.html` =\u003e `404 Not Found`\n. `GET /rest/` =\u003e `404 Not Found`\n\nSee {url-sb-17523}[spring-projects/spring-boot#17523].\n\n\nWhile having a two technology to expose endpoints may seem brittle, this is\nquite useful if :\n\n* One want to expose a few static resources like documentation alongside\nJAXRS / Jersey endpoints.\n* One want to have actuator endpoints available from the root path.\n* One want to migrate one endpoint at a time from - to Spring WebMVC.\n\nThe following workaround covers part that Spring Boot does not.\n\n== Workarounds\n\n=== Servlet filter mitigation\n\nUsing the filter from this {url-sb-17523}[issue]. And configuring this filter\nwith the right prefixes work.\n\n.with `jersey` and `filter-mitigation` profiles\n. `GET /jaxrs` =\u003e `200 OK`\n. `GET /actuator/status` =\u003e `200 OK`\n. `GET /favicon.ico` =\u003e `200 OK`\n. `GET /doc/` =\u003e `404 Not Found` it doesn't work because when Spring MVC\nforwards the request it aks the container, however the request is forwarded to\nthe Jersey servlet.\n. `GET /doc/index.html` =\u003e `200 OK`\n. `GET /rest/` =\u003e `200 OK`\n\n\nThe idea is to have a filter that can forward request to the\ncorrect servlet. Using the standard JEE `servletContext` it is possible to ask\nfor a `RequestDispatcher` based the servlet name that should receive the\nrequest. For that this code needs the `dispatcherServlet` registration name\nwhich happens to be a public constant of\n`org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME`.\n\nThen if the request URI path starts with the configured prefixes\nthe request will be forwarded to the Spring `dispatcherServlet`.\nBy doing so this bypasses any subsequent servlet filters.\n\nHowever some Spring WebMVC mechanisms don't work, like {res-rd-forward}[forward]\nbecause they ask the container a {res-get-rd}[`RequestDispatcher` based on the\nrequest], the JEE container will return a dispatcher based on url-patterns, and\nJersey servlet is configured with `/*` so it receives all request by default.\n\n\n- icon:plus-circle[] Quite simple to configure\n- icon:plus-circle[] Quite simple to maintain\n- icon:plus-circle[] Barely rely on Spring MVC\n- icon:minus-circle[] May prevents some servlet filter to execute\n- icon:minus-circle[] Does not support all Spring Web MVC features\nlike forwarding\n\nSee {servlet-filter-mitigation}[`SpringMvcPrefixEnforcerFilter`] mitigation code.\n\n=== Spring Web MVC configuration hack mitigation\n\nIs it possible to configure Spring Boot to do the right thing ?\nTurns out, yes it's possible.\n\n.with `jersey` and `filter-mitigation` profiles\n. `GET /jaxrs` =\u003e `200 OK`\n. `GET /actuator/status` =\u003e `200 OK`\n. `GET /favicon.ico` =\u003e `200 OK`\n. `GET /doc/` =\u003e `200 OK`\n. `GET /doc/index.html` =\u003e `200 OK`\n. `GET /rest/` =\u003e `200 OK`\n\n\nSo the Spring's `DispatcherServlet` servlet url-mapping is hardwired by\nSpring Boot to `spring.mvc.servlet.path`, which in our case is `/`.\nAnd the jersey servlet url-mapping is `/*` which means that the Jersey servlet\nis configured to receive all request.\n\nThe idea is that JEE servlets can have multiple url-mappings, which means it is\nshould be possible to tell the container to forward HTTP request that follow\nthe configured url-mappings patterns to the `DispatcherServlet`.\n\nThe auto-configuration is located in {dispatcher-autoconf}[`DispatcherServletAutoConfiguration`],\nand more precisely spring boot allows to override some of the beans and\nespecially the `dispatcherServlet` dedicated `ServletRegistrationBean` (which\nis the Spring way to tell the container to register the given servlet).\nHowever it happens that Spring Boot have a specialized version of the\n`ServletRegistrationBean` named\n{dispatcher-reg-bean}[`org.springframework.boot.autoconfigure.web.servlet.DispatcherServletRegistrationBean`]\nwho implements\n{dispatcher-path}[`org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPath`].\nSpring Boot uses the bean with this interface to (auto) configure certain part\nof their web framework.\n\nExtending `DispatcherServletRegistrationBean` to configure url-mappings is not\ngonna work, because {dispatcher-reg-bean}#L55-L58[`setUrlMappings`] and\n{dispatcher-reg-bean}#L60-L63[`addUrlMappings`] throws unsupported\noperation. The only options are\n\n* Either to implements another specialized\n`ServletRegistrationBean` that allows to configure url-mappings for the\n`dispatcherServlet` and of course implements `DispatcherServletPath`.\n* Or register two beans, the `ServletRegistrationBean` and the\n`DispatcherServletPath`.\n\nHowever doing so is not enough, the Spring Web MVC infrastructure needs to be\ntold how to resolve URIs, this should work with\n{webmvc-configurer-support}[`WebMvcConfigurationSupport`] and the companion bean\n{webmvc-configurer}#L60[`WebMvcConfigurer.configurePathMatch`]. The\n{pathmatch-configurer}[`PathMatchConfigurer`] is supposed to tell if a request\nURI path matches a WebMVC resource via another essential sub-component, the\n{url-path-helper}[`UrlPathHelper`].\n\nThe method of interest is {url-path-helper}#L156-L178[`UrlPathHelper.getLookupPathForRequest`]\nis by default ({url-path-helper}#L64[`alwaysUseFullPath`] is `false`) configured\nto look for sub-path of the url-mappings\n({url-path-helper}#L171[`UrlPathHelper.getPathWithinServletMapping`]), and as\nsuch the returned lookup path is stripped form the first part, hence\nSpring Web MVC cannot match any of these resources against incomplete URLs.\n\nWe need to configure this `UrlPathHelper` to return the full path via\n{webmvc-configurer}#L60[`WebMvcConfigurer.configurePathMatch`].\n\nUnfortunately this configurer only affects the configuration of (the reactive)\n{req-mapping-handler-mapping}[`RequestMappingHandlerMapping`] and a few\nother types, but Spring Web MVC has many other `HandlerMapping` types.\nTo workaround this, the {abstract-handler-mapping}[`AbstractHandlerMapping`] are\n_post-processed_ to {abstract-handler-mapping}#L145-L157[set the `UrlPathHelper`]\nwith the needed configuration.\n\nAnd finally this was again not enough, for some mapping like\n{actuator-webmvc-mapping}[`WebMvcEndpointHandlerMapping`] because this parent's\ntype uses a private static final configuration non customizable\n{actuator-abstract-webmvc-mapping}#L87[`RequestMappingInfo.BuilderConfiguration builderConfig`]\nwith defaults _helpers_ only, its {actuator-abstract-webmvc-mapping}#L151[`urlPathHelper`\nis `null`], {actuator-abstract-webmvc-mapping}#L203-L204[this triggers] the\n{patterns-condition}#L108[creation of a`PatternsRequestCondition`] with\na new instance of `UrlPathHelper` that has the default configuration.\nIn order to bypass this behavior it is necessary to use reflection before\n`WebMvcEndpointHandlerMapping` bean post initialization and set the\n`RequestMappingInfo.BuilderConfiguration` with the `UrlPathHelper` with the\nneeded configuration.\n\n- icon:plus-circle[] Seems to properly configure Spring MVC\n- icon:plus-circle[] And as such more robust\n- icon:plus-circle[] Integrates well with Servlets\n- icon:minus-circle[] Difficult to understand\n- icon:minus-circle[] Difficult to maintain\n- icon:minus-circle[] May break upon Spring MVC code changes\n\nSee {spring-config-mitigation}[`SpringWebMvcHackConfiguration`] mitigation code.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbric3%2Fjersey-webmvc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbric3%2Fjersey-webmvc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbric3%2Fjersey-webmvc/lists"}