Hot questions for Spring REST services

Top 10 Java Open Source / Spring / Spring REST services

Question:

An Abstract controller class requires List of objects from REST. While using Spring RestTemplate its not mapping it to required class instead it returns Linked HashMAp

 public List<T> restFindAll() {

    RestTemplate restTemplate = RestClient.build().restTemplate();
    ParameterizedTypeReference<List<T>>  parameterizedTypeReference = new ParameterizedTypeReference<List<T>>(){};
    String uri= BASE_URI +"/"+ getPath();

    ResponseEntity<List<T>> exchange = restTemplate.exchange(uri, HttpMethod.GET, null,parameterizedTypeReference);
    List<T> entities = exchange.getBody();
    // here entities are List<LinkedHashMap>
    return entities;

}

If I use,

ParameterizedTypeReference<List<AttributeInfo>>  parameterizedTypeReference = 
    new ParameterizedTypeReference<List<AttributeInfo>>(){};
    ResponseEntity<List<AttributeInfo>> exchange =
  restTemplate.exchange(uri, HttpMethod.GET, null,parameterizedTypeReference);

It works fine. But can not put in all subclasses, any other solution.


Answer:

I worked around this using the following generic method:

public <T> List<T> exchangeAsList(String uri, ParameterizedTypeReference<List<T>> responseType) {
    return restTemplate.exchange(uri, HttpMethod.GET, null, responseType).getBody();
}

Then I could call:

List<MyDto> dtoList = this.exchangeAsList("http://my/url", new ParameterizedTypeReference<List<MyDto>>() {});

This did burden my callers with having to specify the ParameterizedTypeReference when calling, but meant that I did not have to keep a static mapping of types like in vels4j's answer 

Question:

How can I get the raw json string from spring rest template? I have tried following code but it returns me json without quotes which causes other issues, how can i get the json as is.

ResponseEntity<Object> response  = restTemplate.getForEntity(url, Object.class);
String json = response.getBody().toString();

Answer:

You don't even need ResponseEntitys! Just use getForObject with a String.class like:

final RestTemplate restTemplate = new RestTemplate();
final String response = restTemplate.getForObject("https://httpbin.org/ip", String.class);

System.out.println(response);

It will print something like:

{
  "origin": "1.2.3.4"
}

Question:

I have a simple test to my RestController. I expect that $[1].parent_idreturns Long as an object and not integer primitive. It will return Long if parent_id is in a long number range and > integer number range (such as : 2147483650L).

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
@WebAppConfiguration
public class TransactionServiceControllerTest {

@Before
public void setup() throws Exception {
    this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    // I copy this from my RestController class
    this.transactions = Arrays.asList(
            new Transaction(100d, "car", null),
            new Transaction(100d, "table", 12L)
     );
}

@Test
public void readSingleBookmark() throws Exception {
   mockMvc.perform(MockMvcRequestBuilders.get("/transaction/"))
   .andExpect(content().contentType(contentType)) // ok
   .andExpect(jsonPath("$", hasSize(2))) // ok
   //omitted
   andExpect(jsonPath("$[1].parent_id",is(this.transactions.get(1).getParentId())));
} //assertion fail

Expected: is <12L>
but: was <12>

Result from another test :

Expected: is <12L>
but: was <2147483650L> //return Long instead int

this is my JacksonConfiguration

@Configuration
public class JacksonConfiguration {

    @Bean
    @Primary
    public ObjectMapper objectMapper() {
        final ObjectMapper objectMapper = new ObjectMapper();

        //supposed to be this is the magic trick but it seems not..
        objectMapper.enable(DeserializationFeature.USE_LONG_FOR_INTS);


        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_ABSENT);
        objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
        return objectMapper;
    }
}

And my POJO

public class Transaction {

private double ammount;

private String type;

private Long parentId;

public Transaction(Double ammount, String type, Long parentId) {
  //omitted
}
//setter and getter omitted
}

MyRestController

@RestController
@RequestMapping("transaction")
public class TransactionServiceController {

@RequestMapping(method = RequestMethod.GET)
List<Transaction> getTransaction() {
    return
            Arrays.asList(
                    new Transaction(100d, "car", null),
                    new Transaction(100d, "table", 12L)
            );
    }
}

And Application.java

@SpringBootApplication
public class Application {
    public static void main(String[] args){
        SpringApplication.run(Application.class,args);
    }
}

Answer:

Update
  • Spring Framework 4.3.3 and 5.0.0 added first-class support for explicit conversions for request content for use with MockRestServiceServer.
  • Spring Framework 4.3.15 and 5.0.5 will add first-class support for explicit conversions for response content for use with MockMvc.

Original Answer

One option (which I haven not personally verified) would be to try a different JsonProvider. This can be set via com.jayway.jsonpath.Configuration.setDefaults(Defaults).

If you are sure that the Long can always be safely narrowed to an int, you could use the following:

andExpect(jsonPath("$[1].parent_id",is(this.transactions.get(1).getParentId().intValue())));

And the only other option is to write a custom Matcher that converts the incoming Integer to a Long before performing the actual matching.

Question:

Using Spring boot 1.3.1

I don't understand why @RestController are Transactionnal by default. I haven't found anything saying so in the docs.

Example which pushes this fact that the method findOne() in the controller below is Transactionnal:

@RestController
@RequestMapping("/books")
public class BookController {

    @RequestMapping("/{id}")
    public Book findOne(@PathVariable Long id) {
        Book book = this.bookDao.findOneBookById(id);
        // following line
        // => triggers a select author0_.id as id1_0_0_ etc... // where author0_.id=?
        System.out.println(book.getAuthor().getFirstname()); 
        return book;
    }
}

The line with the System.out.println(book.getAuthor().getFirstname()); should raise a LazyInitiaizationFailure BUT here it is successful and trigger the select of an an Author. So the method findOne seems to be transactionnal. With the eclipse debugger I can be sure that it is really this line that triggers the complementary select. But Why is that method transactionnal ?

@Configuration
@ComponentScan(basePackageClasses = _Controller.class)
@Import(BusinessConfig.class)
public class WebConfig extends WebMvcConfigurerAdapter {
   // ... here the conf to setup Jackson Hibernate4Module
}

@Configuration
@EnableAutoConfiguration
@EnableTransactionManagement
@EntityScan(basePackageClasses = _Model.class)
@ComponentScan(basePackageClasses = { _Dao.class })
public class BusinessConfig {
}

@SpringBootApplication
public class BookstoreStartForWebEmbedded {

    public static void main(String[] args) {
        SpringApplication.run(BookstoreStartForWebEmbedded.class, args);
    }

}

libs : 
spring-boot-starter 1.3.1.RELEASE
spring-boot-starter-test : 1.3.1.RELEASE
spring-boot-starter-valisation : 1.3.1.RELEASE
spring-boot-starter-web : 1.3.1.RELEASE
spring-boot-starter-data-jpa : 1.3.1.RELEASE
postgresql: 9.4-1206-jdbc41
querydsl-jps:3.7.0
jackson-annotations:2.6.4
jackson-datatype-hibernate4:2.6.4

any idea ?

If it is a feature, i would like to switch it off...


Answer:

In addition to MirMasej answers, there is one more thing: Spring Boot will automatically register an OpenEntityManagerInViewInterceptor when the following conditions are true:

  • you have a web application
  • you use JPA

Both conditions are true in your case. This interceptor holds the entity manager open for the whole duration of a request. The auto configuration occurs in the class JpaBaseConfiguration.

If you don't want that behaviour, you can add the following property to your application.properties file:

spring.jpa.open-in-view=false

Btw. this behaviour is completely independent of transactions, it's only related to the lifecycle of the entity manager. You can still have two separate transactions and no LazyInitializationException, if both transactions have the same underlying entity manager instance.

Question:

I have worked in Jersey and RESTEasy framework earlier and now we will be using Spring Rest for a new project , I don't want to pass all the query params and matrix params as parameters in the method , and usually I would annotate the method with @Context UriInfo and would get all the parameters inside my method in Jersey or RESTEasy Framework for complex parameters.

I would like to know if there is any @Context UriInfo in Spring REST, which is similar to RESTEasy or Jersey Framework. I would like to get all the query params or matrix params and other params if any inside the method instead of passing them as a parameter in the method.


Answer:

I did not find any spring class equivalent to UriInfo. But we can take same info from httpservlet request. Suppose, a url is http:localhost:8080/services/test?one=1&two=2, then,

    hsr.getServletContext.getContextPath() gives "/services"
    hsr.getRequestURI() gives "/services/test"
    hsr.getRequestURL() gives complete url "http:localhost:8080/services/test"
    hsr.getQueryString() gives "one=1&two=2"
    hsr.getServletPath() gives "/test"
    hsr.getParameterMap() gives all query strings in a Map as key value pair

You can set and use these values in URIinfo object

Question:

I am handling REST exceptions using @ControllerAdvice and ResponseEntityExceptionHandler in a spring Rest webservice. So far everything was working fine until I decided to add the URI path(for which exception has occurred) into the BAD_REQUEST response.

@ControllerAdvice
public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {

@Override
protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex,
        HttpHeaders headers, HttpStatus status, WebRequest request) {
    logger.info(request.toString());
    return handleExceptionInternal(ex, errorMessage(HttpStatus.BAD_REQUEST, ex, request), headers, HttpStatus.BAD_REQUEST, request);
}

private ApiError errorMessage(HttpStatus httpStatus, Exception ex, WebRequest request) {
    final String message = ex.getMessage() == null ? ex.getClass().getName() : ex.getMessage();
    final String developerMessage = ex.getCause() == null ? ex.toString() : ex.getCause().getMessage();
    return new ApiError(httpStatus.value(), message, developerMessage, System.currentTimeMillis(), request.getDescription(false));
}

ApiError is just a Pojo class:

public class ApiError {

    private Long timeStamp;
    private int status;
    private String message;
    private String developerMessage;
    private String path;
}

But WebRequest has not given any api to get the path for which the request failed. I tried: request.toString() returns -> ServletWebRequest: uri=/signup;client=0:0:0:0:0:0:0:1 request.getDescription(false) returns -> uri=/signup getDescription is pretty close to the requirement, but doesn't meet it. Is there any way to get only the uri part?


Answer:

Found the solution. Casting WebRequest to ServletWebRequest solved the purpose.

((ServletWebRequest)request).getRequest().getRequestURI().toString()

returns the complete path - http://localhost:8080/signup

Question:

So the current issue I am having is I am getting a

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.client.HttpClientErrorException: 404 null] with root cause org.springframework.web.client.HttpClientErrorException 404 null

in my client code when my server code responds with anything other than a OK 200 response. So in this case I was intentionally returning a 404 response in my server code having done so with a header and body, and without a header and body but I still get the same exception with the HTTP status code I respond with in the server code and null which in this case I assume to be the body of the response. Originally in my server code I always returned a ResponseEntity<>("Sent", HttpStatus.OK) but since in my server code I make a HTTP request elsewhere if this responds with anything other than a 200 OK then my client code wouldn't know about it therefore instead I am returning the actual response returned from the HTTP request in my server code back to my client code which is when I ran into this issue.

Client Code

public String callFruitBasket(Fruit fruitRequest) {
    HttpHeaders requestHeaders = new HttpHeaders();
    requestHeaders.setContentType(MediaType.APPLICATION_JSON);

    HttpEntity<Fruit> fruit = new HttpEntity<>(fruitRequest, requestHeaders);
    System.out.println("Fruit headers: " + fruit.getHeaders());

    ResponseEntity<String> response = restTemplate.exchange(fruitBasketUrl, HttpMethod.POST, fruit, String.class);
    System.out.println("Full response: " + response);

    return response.getBody();
}

Server Code

@PostMapping("/fruitBasket/send")
public ResponseEntity<String> sendFruitBasket(@RequestBody Fruit fruit) {
   // works fine, old response
   // return new ResponseEntity<>("Sent", HttpStatus.OK);

   return new ResponseEntity<>("Baaad Request", HttpStatus.BAD_REQUEST);
}

So at the moment in my server code I didn't add any headers to my response but I have already tried this with adding a Content-Type however I found I still got the same exception in my client code so I am 100% sure that the issue lies somewhere in my client code. Originally when I passed the 200 OK response the printout of the full response was fine in the client code with showing:

Full Response: <200 OK,Sent,{Content-Type=[text/plain;charset=UTF-8], Content-Length=[4], Date=[Sat, 19 May 2018 09:10:21 GMT]}>

What I would expect for any of the other Http Status code like 400 and 404 would be the same but with the 400 or 404 in the response instead of the 200 OK. I've tried playing around with the headers in both client and server code as I have read in various posts on here that this is commonly the cause when getting this type of exception which leads me to believe there could be something fundamental missing in my client code or that this is expected behavior for exchange() and that I am misunderstanding it.


Answer:

The default behavior of RestTemplate on encountering error response codes is throwing an exception. In case of 4xx it's HttpClientErrorException and in case of 5xx: HttpServerErrorException (both extending HttpStatusCodeException). Spring achieves that by using ResponseErrorHandler (and it's default imlpementation - DefaultResponseErrorHandler)

One way of handling this would be to catch them:

try {
    ResponseEntity<String> response = restTemplate.exchange(fruitBasketUrl, HttpMethod.POST, fruit, String.class);
} catch(HttpClientErrorException e) {
    //handle 4xx errors
} catch(HttpServerErrorException e) {
    //handle 5xx errors
}

If you need to customize this behaviour (some rest API's use those codes when sending legitimate responses to some requests which you then may want to process as you do with 2xx response), you can create your own implementation of ResponseErrorHandler by implementing it or extending DefaultResponseHandler and then registering your handler with the RestTemplate during it's initialization:

public class MyResponseErrorHandler extends DefaultResponseErrorHandler {

    @Override
    public boolean hasError(ClientHttpResponse response) throws IOException {
        // check if response code is an error in here or just use default implementation
    }

    @Override
    public void handleError(ClientHttpResponse response) throws IOException {
        // handle different response codes
        // (default spring behaviour is throwing an exception)
    }
}

And registering:

RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new MyResponseErrorHandler());
// now RestTemplate's behaviour for error status codes is customized

Question:

Code convention says no logic in the controllers. All should be handled in the service layer. My question is especially about returning ResponseEntity.

Should it be handled in RestController or in Service layer?

I tried both ways. I think RestController is the suitable place to return ResponseEntity. Because we are using mappings in the RestController.

On the other hand, we know the controllers should not include any logic.

@GetMapping("/{id}")
public ResponseEntity<Employee> getEmployee(@PathVariable Long id) {
    return ResponseEntity.ok(employeeService.findEmployeeById(id);
}

or

@GetMapping("/{id}")
public ResponseEntity<Employee> getEmployee(@PathVariable Long id) {
    return employeeService.findEmployeeById(id);
}

ControllerAdvice for exception handling is my another concern. Which way is the best to use?

Thanks for your advance.


Answer:

Code convention says no logic in the controllers.

Not really. Code convention says each layer has to perform itself logic which it is responsible of. Computing the result, retrieving data requested/needed by the request is clearly not the rest controller job but sending an http response, what returning ResponseEntity does is its job. So this looks the correct way :

@GetMapping("/{id}")
public ResponseEntity<Employee> getEmployee(@PathVariable Long id) {
    return ResponseEntity.ok(employeeService.findEmployeeById(id);
}

If the ResponseEntity was produced by your service, your service would be coupled with the Http layer. Not desirable and make it less reusable as a service.

Question:

I can't fetch JSONObject directly, this code works:

RestTemplate restTemplate = new RestTemplate();
String str = restTemplate.getForObject("http://127.0.0.1:8888/books", String.class);
JSONObject bookList = new JSONObject(str);

but this code doesn't:

JSONObject bookList = restTemplate.getForObject("http://127.0.0.1:8888/books", JSONObject.class);

What could be the problem? It doesn't give errors but I've an empty JSONObject in the end.

my pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>library-client</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>LibraryClient</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

and I have to add a bit more details you can see when I use a string to cast inbetween it works. and a bit more details, maybe I should delete my pom.xml to reduce the amount of code in this question, would that make sense? | Okay more?


Answer:

RestTemplate will use reflection in order to create the resulting object

When you use restTemplate.getForObject it will try to use the default constructor of the class you pass and then tries to fill all its fields In this case it doesn't know how to create the JSONObject

In order to do it you must:

  • use your own HttpMessageConverterExtractor
  • use the second approach JSONObject bookList = new JSONObject(str);

Question:

I have created a Spring Restful Service and Spring MVC application.

Restful Service :: Restful service returns an entity if its existing in DB. If it doesn't exist It returns a custom Exception information in ResponseEntity object.

It is working as expected tested using Postman.

@GetMapping(value = "/validate/{itemId}", produces = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE })
public ResponseEntity<MyItem> validateItem(@PathVariable Long itemId, @RequestHeader HttpHeaders httpHeaders) {

    MyItem myItem = myitemService.validateMyItem(itemId);
    ResponseEntity<MyItem> responseEntity = null;
    if (myItem == null) {
        throw new ItemNotFoundException("Item Not Found!!!!");
    }
    responseEntity = new ResponseEntity<MyItem>(myItem, headers, HttpStatus.OK);
    return responseEntity;
}

If the requested Entity does not exist Restful Service returns below.

@ExceptionHandler(ItemNotFoundException.class)
public ResponseEntity<ExceptionResponse> itemNotFEx(WebRequest webRequest, Exception exception) {
    System.out.println("In CREEH::ItemNFE");
    ExceptionResponse exceptionResponse = new ExceptionResponse("Item Not Found Ex!!!", new Date(), webRequest.getDescription(false));
    ResponseEntity<ExceptionResponse> responseEntity = new ResponseEntity<ExceptionResponse>(exceptionResponse, HttpStatus.NOT_FOUND);
    return responseEntity;
}

But when I am calling the above service from a spring MVC application using RestTemplate, It is returning a valid object if it exists.

If the requested object does not exist Restful service is returning the exception information but its not reaching the calling(spring MVC) application.

Spring MVC application calls Restful Web Service using Rest template

String url = "http://localhost:8080/ItemServices/items/validate/{itemId}";
ResponseEntity<Object> responseEntity = restTemplate.exchange(url, HttpMethod.GET, httpEntity, Object.class, uriParms);
int restCallStateCode = responseEntity.getStatusCodeValue();

Answer:

This is expected behavior. Rest template throws exception when the http status is client error or server error and returns the response when http status is not error status.

You have to provide implementation to use your error handler, map the response to response entity and throw the exception.

Create new error exception class with ResponseEntity field.

public class ResponseEntityErrorException extends RuntimeException {
  private ResponseEntity<ErrorResponse> errorResponse;
  public ResponseEntityErrorException(ResponseEntity<ErrorResponse> errorResponse) {
      this.errorResponse = errorResponse;
  }
  public ResponseEntity<ErrorResponse> getErrorResponse() {
      return errorResponse;
  }
}

Custom error handler which maps the error response back to ResponseEntity.

public class ResponseEntityErrorHandler implements ResponseErrorHandler {

  private List<HttpMessageConverter<?>> messageConverters;

  @Override
  public boolean hasError(ClientHttpResponse response) throws IOException {
    return hasError(response.getStatusCode());
  }

  protected boolean hasError(HttpStatus statusCode) {
    return (statusCode.is4xxClientError() || statusCode.is5xxServerError());
  }

  @Override
  public void handleError(ClientHttpResponse response) throws IOException {
    HttpMessageConverterExtractor<ExceptionResponse> errorMessageExtractor =
      new HttpMessageConverterExtractor(ExceptionResponse.class, messageConverters);
    ExceptionResponse errorObject = errorMessageExtractor.extractData(response);
    throw new ResponseEntityErrorException(ResponseEntity.status(response.getRawStatusCode()).headers(response.getHeaders()).body(errorObject));
  }

  public void setMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
    this.messageConverters = messageConverters;
  }
}

RestTemplate Configuration - You have to set RestTemplate's errorHandler to ResponseEntityErrorHandler.

@Configuration
public class RestTemplateConfiguration {
  @Bean
  public RestTemplate restTemplate() {
      RestTemplate restTemplate = new RestTemplate();
      ResponseEntityErrorHandler errorHandler = new ResponseEntityErrorHandler();
      errorHandler.setMessageConverters(restTemplate.getMessageConverters());
      restTemplate.setErrorHandler(errorHandler); 
      return restTemplate;
   }
}

Calling Method

@Autowired restTemplate

String url = "http://localhost:8080/ItemServices/items/validate/{itemId}";
try {
    ResponseEntity<Object> responseEntity = restTemplate.exchange(url, HttpMethod.GET, httpEntity, Object.class, uriParms);
    int restCallStateCode = responseEntity.getStatusCodeValue();
} catch (ResponseEntityErrorException re) {
    ResponseEntity<ErrorResponse> errorResponse = re.getErrorResponse();
}

Question:

I'm just thinking, what is the best practice to create PATH mapping for rest service. Let's say we have following paths:

/users POST
/users/1 PATCH, GET
/users/1/contacts GET, POST
/users/1/contacts/1 GET, PATCH

The question is - what is the best practice to create controllers. For example we have UserController where we technically could put all these mappings. Or - we should create seperate controllers (UserController, ContactsController). f.e UserController below, if we put everything under.

@RequestMapping("users")
@RestController
public class UserController {

    @RequestMapping(method = RequestMethod.POST)
    public ResponseEntity<Void> createUser() {}

    @RequestMapping(method = RequestMethod.GET)
    public User getUser() {}

    @RequestMapping(value = "{id}/contacts", method = RequestMethod.GET)
    public List<Contact> getContacts() {}

    @RequestMapping(value = "{id}/contacts", method = RequestMethod.POST)
    public ResponseEntity<Void> createContact() {}

    .....
}

And if we create separate controllers, how paths should be organized then? Probably it's a silly question, but i will be glad, if someone could share experience.


Answer:

Lets suggest that number of entities related to User will increase in future. So it obvious that it is better to split it according to entities:

UserController -> UserService -> UserRepository,

ContactController -> ContactService -> ContactRepository,

FriendshipController -> FriendshipService -> FriendshipRepository

From my experience, User Controller

@RestController
@RequestMapping("/user")
public class UserController extends AbstractController {

...

   @RequestMapping(method = RequestMethod.POST)
   public ResponseEntity<?> createUser(@RequestHeader("X-Auth-Token") Optional<String> @RequestBody User user) {

...

   @RequestMapping(method = RequestMethod.GET)
   public ResponseEntity<?> listUsers(@RequestHeader("X-Auth-Token") Optional<String> authToken) {
...

related to user scope Friendship controller:

@RestController
@RequestMapping("/user/{id}")
public class FriendshipController extends AbstractController {

...

@RequestMapping(value = "/friendship/code", method = RequestMethod.POST)
    public ResponseEntity<?> generateCodeForUser(@PathVariable("id") long id) {

...

 @RequestMapping(value = "/friendship/code", method = RequestMethod.GET)
    public ResponseEntity<?> retrieveCodeForUser(@PathVariable("id") long id) {

...

Not sure it is axiom, but help me organize my code.