'Spring MVC request mapping - full request URI

When creating or listing and item using REST api I return also the whole resource path.

For example creating a person record returns http://service:9000/person/1234in response. In order to get schema, host & port part like http://service:9000, I extract it from URL obtained by HttpServletRequest.getRequestURL().

Example (not the production code but conceptually same):

@RequestMapping(value = "/person", method = RequestMethod.PUT)
public Object putPerson(
        @RequestParam(value = "name") String name,
            HttpServletRequest req) {

      long id = createPerson(name);
      String uriStart = RestUtils.getSchemeHostPortUrlPart(req
            .getRequestURL().toString());
      String uri = uriStart + "/person/" + id;
      Person person = new Person(name, id, uri);

      return person; //Serialized to json by Spring & Jackson
}

//Simple bean-like class
public class Person {  
//Getter methods for uri, name & id
}

Since this is quite a boiler plate code which repeats in every method I was wondering if Spring does not have support for this which eluded me when reading it's documentation.

By this I mean accessing either URL without neededn HttpServletRequest or even better its schema, host, port part only.



Solution 1:[1]

The documentation provides a lot of examples for constructing URIs using a UriComponentsBuilder.

Furthermore I recommend to take a look at Spring HATEOAS if you want to take your REST API to the next level.

BTW: PUT means that you place what you send (request body) to the location to which you send it (URL). If nothing is there something new is created, otherwise what exists is updated (replaced).

This is not what is happening in your example. The proper way would be to either POST to /person or PUT to the person's own URL, e.g. /person/1234, provided you have the ID beforehand.

Solution 2:[2]

You can construct the URI in an interceptor (that's executed previous to controller methods) and put it as an attribute and use it in the controller method.

Solution 3:[3]

I believe it is quite simple. Look at this example:

@RequestMapping(value = "/person", method = RequestMethod.PUT)
public Object putPerson(@RequestParam(value = "name") String name, HttpServletRequest req) {

  long id = createPerson(name);
  Person person = new Person(id, name, req);

  return person; //Serialized to json by Spring & Jackson
}

public class JsonResponse {

    private String url;

    public JsonResponse(HttpServletRequest request) {
        url = request.getRequestURI() + "?" + request.getQueryString();
    }

    public final String url() {
        return url;
    }
}

public class User extends JsonResponse {

    private Long   id;
    private String name;

    public User(Long id, String name, HttpServletRequest request) {
        super(request);
        this.id = id;
        this.name = name;
    }

    // Getter, Setter

}

Solution 4:[4]

You can use org.springframework.web.servlet.support.ServletUriComponentsBuilder like this:

String uri = ServletUriComponentsBuilder.fromCurrentRequest()
    .replacePath("/person/{id}")
    .buildAndExpand(id)
    .toUriString();

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Emilio
Solution 3 dieter
Solution 4 Gian Marco