1

I had to upgrade the dependencies of a project from:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.4.RELEASE</version>
    <relativePath/>
</parent>

To the version 3.0.0 and traslated web.xml configuration to java code.

One of them is this:

<servlet-mapping>
    <servlet-name>ServletName</servlet-name>
    <url-pattern>*.do</url-pattern>
</servlet-mapping>

That was translated into java code like this:

@Configuration
@Slf4j
public class MyServlet implements WebApplicationInitializer {
  @Override
  public void onStartup(ServletContext servletContext) {
    ServletRegistration.Dynamic servlet = servletContext.addServlet("ServletName",
      new DispatcherServlet(new AnnotationConfigWebApplicationContext()));
    servlet.setLoadOnStartup(1);
    servlet.setAsyncSupported(true);
    servlet.addMapping("*.do");
  }

But when I call this api:

POST /api/private/smartphone.do

Mapped with this code:

@PostMapping(value = "/private/{type}", produces = MediaType.APPLICATION_JSON_VALUE)
public JsonResponse getSmartphones(@PathVariable SType type) { ... }

The ".do" is not removed and type is equal "smartphone.do" which is not the desired result because SType is an enum like this:

public enum SType {
  smartphone("smartphone"), laptop("laptop"), appliances("appliances");

  private String name;

  SType (String name) {
    this.name = name;
  }

  public String get() {
    return name;
  }
}

I've made a few attempts:

implements WebMvcConfigurer

@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
  configurer.setPathMatcher(new CustomPathMatcher());
}

private static class CustomPathMatcher extends AntPathMatcher {
  @Override
  public boolean match(String pattern, String path) {
    if (path.endsWith(".do")) {
      path = path.substring(0, path.length() - 3);
    }
    return super.match(pattern, path);
  }
}

extends HttpServlet

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) {
    var req = request.getRequestURI();
    if(req.endsWith(".do")) {
      request.getRequestDispatcher(req.substring(0, req.length() - 3));
    }
}

Beans

@Bean
public HandlerMapping requestMappingHandlerMapping() {
    RequestMappingHandlerMapping mapping = new RequestMappingHandlerMapping();
    mapping.setUseSuffixPatternMatch(false);
    return mapping;
}

update 1

Adding an interceptor seem to resolve the problem.

public class ExtensionInterceptor implements HandlerInterceptor {
  @Override
  public boolean preHandle(HttpServletRequest request, 
HttpServletResponse response, Object handler)
    throws Exception {
    String path = request.getRequestURI();
    if (path.endsWith(".do")) {
      String newPath = path.substring(0, path.length() - 3);
      request.getRequestDispatcher(newPath).forward(request, response);
      return false;
    }
    return true;
  }
}

implements WebMvcConfigurer

  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new ExtensionInterceptor()).addPathPatterns("/private/**");
  }

update 2

@PostMapping("/private/{type}.do")

Seems to do the job.

Jakkins
  • 115
  • 11
  • 1
    "some configuration changed" seems more like "(complete) view tech (inacurately) replaced"!? (what does your servlet do(meaningful)? (..i assume it's a "struts relic") ..how does it (the servlet) relate to `@Postmapping`?) I guess: you want to (1. delete all the "servlet stuff".) 2. just `@PostMapping("/private/{type}.do")` . – xerx593 Jun 12 '23 at 08:48
  • 1
    There was no Spring 2.2.4, so I assume you are using Spring Boot and not regular Spring. Please clarify that (because Sprng 3.0.0 is quite ancient and not supportede any more). – M. Deinum Jun 12 '23 at 09:08
  • I think in the old version the extension was removed automatically just with the `url-pattern` configuration, but with the new version maybe we missed a configuration in java code and I am searching for that configuration – Jakkins Jun 12 '23 at 10:05
  • assuming: 1. you moved from struts to mvc (at some point in time...keeping `.do` urls throughout the application) 2. want to strip `.do` from *all* requests 3. Plus spring-boot upgrade (at the same/a later time) ..then "manual solution" (add `.do` to all `@XXXMapping`s) is good to understand the problem, and only applicable on (very) few "controllers". "interceptor solution" seems fine, since (a) it works, (b) is general(2.) and compatible (3.) and takes much burden from you in opposite to (also possible) implementing a "filter solution", where you have to consider: ... – xerx593 Jun 14 '23 at 09:43
  • a) (filter) impl/class/what does it, b) in what order[, c) on which url pattern, ...] – xerx593 Jun 14 '23 at 09:44
  • "most overhead" (though also maybe possible) is a "servlet solution"... (mvc has normally only *one servlet*...which spring boot configures (in an embedded container by default)..) – xerx593 Jun 14 '23 at 09:52

0 Answers0