ApiController.java
package edu.ucsb.cs156.organic.controllers;
import org.springframework.beans.factory.annotation.Autowired;
import edu.ucsb.cs156.organic.entities.Staff;
import edu.ucsb.cs156.organic.errors.EntityNotFoundException;
import edu.ucsb.cs156.organic.models.CurrentUser;
import edu.ucsb.cs156.organic.services.CurrentUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.util.Map;
/**
* Base class for all API controllers. Provides a getCurrentUser() method
* and a genericMessage() method.
*
*/
@Slf4j
public abstract class ApiController {
@Autowired
private CurrentUserService currentUserService;
/**
* Returns the current user, or null if no user is logged in.
* @return CurrentUser current user or null
*/
protected CurrentUser getCurrentUser() {
return currentUserService.getCurrentUser();
}
/**
* Exception handler to return HTTP status code 400 Bad Request
* when an IllegalArgumentException is thrown
* @param e IllegalArgumentException
* @return map with type and message
*/
@ExceptionHandler({ IllegalArgumentException.class})
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Object handleIllegalArgumentException(Throwable e) {
Map<String,String> map = Map.of(
"type", e.getClass().getSimpleName(),
"message", e.getMessage()
);
log.error("Exception thrown: {}", map);
return map;
}
/**
* Exception handler to return HTTP status code 404 Not Found
* when an EntityNotFoundException is thrown
* @param e EntityNotFoundException
* @return map with type and message
*/
@ExceptionHandler({ EntityNotFoundException.class })
@ResponseStatus(HttpStatus.NOT_FOUND)
public Object handleGenericException(Throwable e) {
return Map.of(
"type", e.getClass().getSimpleName(),
"message", e.getMessage()
);
}
/**
* Exception handler to return HTTP status code 403 Forbidden
* when an AccessDeniedException is thrown
* @param e AccessDeniedException
* @return map with type and message
*/
@ExceptionHandler({ AccessDeniedException.class })
@ResponseStatus(HttpStatus.FORBIDDEN)
public Object handleAccessDeniedException(Throwable e) {
return Map.of(
"type", e.getClass().getSimpleName(),
"message", e.getMessage()
);
}
/**
* Generic message to return in a controller method
* @param message
* @return map with message
*/
protected Object genericMessage(String message) {
return Map.of("message", message);
}
private ObjectMapper mapper;
/**
* Special ObjectMapper that ignores Mockito mocks
* @return ObjectMapper mapper
*/
public ObjectMapper getMapper() {
return mapper;
}
/**
* Constructor that initializes the ObjectMapper
*/
public ApiController() {
mapper = mapperThatIgnoresMockitoMocks();
}
/**
* Special ObjectMapper that ignores Mockito mocks
* @return ObjectMapper mapper
*/
public static ObjectMapper mapperThatIgnoresMockitoMocks() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() {
@Override
public boolean hasIgnoreMarker(final AnnotatedMember m) {
return super.hasIgnoreMarker(m) || m.getName().contains("Mockito");
}
});
return mapper;
}
}