How to customize Bean Validations ConstraintViolationException? - java

I want to validate the #RequestBody of an endpoint in my Spring #RestController. So I created a method like this:
#RequestMapping(value = ...)
public ResponseEntity<...> myPostMethod(#RequestBody MyBean myBean) throws Exception {
MyBean is decorated with a custom #Constraint and its respective validation logic is implemented on a ConstraintValidator class that I created. This validator has a method like:
#Override
public boolean isValid(MyBean value, ConstraintValidatorContext context) {
That's where all the validation logic takes place. When it fails, isValid returns false and I can use that context param to build a validation error message the way I want. In addition, myPostMethod also fails with an automatic (because I do not throw it myself) MethodArgumentNotValidException that I'm going to capture on a global handler in order to render a generic ResponseEntity. It all works as expected. The question is: how do I customize not only the validation error message, but also the whole ConstraintViolationException? I want to provide more data (from my business domain) inside the exception to render in the response body json.

I found the answer:
https://docs.jboss.org/hibernate/validator/5.4/api/org/hibernate/validator/constraintvalidation/HibernateConstraintValidatorContext.html#withDynamicPayload-java.lang.Object-
public boolean isValid(MyBean value, ConstraintValidatorContext constraintValidatorContext) {
HibernateConstraintValidatorContext context = constraintValidatorContext.unwrap(HibernateConstraintValidatorContext.class);
// (...)
context.buildConstraintViolationWithTemplate( "{foo}" )
.withDynamicPayload(anyAdditionalInfo)
.addConstraintViolation();
return false;
}

Let's assume that the additional parameter you wanted to pass is called myParam.
First, declare an accessor for that parameter in your Constraint interface;
public #interface MyConstraint {
String message();
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
String myParam() default "some.value";
}
Then in the ConstraintValidator, you could access these params like:
public class MyValidator implements ConstraintValidator<MyConstraint, String> {
private String myParam;
#Override
public void initialize(OpcoConstraint parameters) {
code = parameters.myParam();
}
#Override
public boolean isValid(String value, ConstraintValidatorContext context) {
HibernateConstraintValidatorContext hibernateContext = context.unwrap(
HibernateConstraintValidatorContext.class
);
// you can pass any object as the payload
hibernateContext.withDynamicPayload(Map.of("myParam", myParam));
}
}
If you catch the ConstraintViolationException from an exception handler and want to access the parameter from the Exception itself:
To retrieve ConstraintViolation (s) out of ConstraintViolationException use:
constraintViolationException.getConstraintViolations();
Then to retrieve the dynamic payload out of a ConstraintViolation:
(Map) ((ConstraintViolationImpl) constraintViolation).getDynamicPayload(Map.class))

Related

Pass custom parameter to ConstraintValidator

I'm working on this springboot application where I need to do some validations on values passed from http call and I'm using class level validation as explained here.
I'm using somethink like this:
#ValidRequest
public class EventRequest {
String date;
}
Response create(#Valid EventRequest request) {
..
}
Response update(Long entityId, #Valid EventRequest request) {
...
}
public class ValidRequestValidator
implements ConstraintValidator<ValidRequest, EventRequest> {
In the class ValidRequestValidator, where I implement the ConstraintValidator interface, I need to check if there is another Event entity in the database that meet some conditions on field date. When I want to create a new entity is simple, I perform a query, but when I need to update I need to exclude the entity I'm currently trying to update.
Is there a way to pass entityId parameter to #ValidRequest custom validator?
I know a way is to add the field entityId to the class EventRequest, but I would like to maintain this separation because entityId is coming from a query parameter.
Thank for your help!
Additional to the field-specific(Single Parameter Constraint) you can implement constraint for the whole method(Cross-Parameter Constraint). This will provide ability to pass all parameters of certain method to validator.
Annotation definition:
Annotation used two validators and can be applied to the Method or Type.
#Constraint(validatedBy = {ValidRequestMethodValidator.class, ValidRequestTypeValidator.class})
#Target({ ElementType.METHOD, ElementType.TYPE })
#Retention(RetentionPolicy.RUNTIME)
public #interface ValidRequest {
String message() default "Request is invalid!";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
ConstraintTarget validationAppliesTo() default ConstraintTarget.IMPLICIT;
}
Constraint Validator which will handle single parameter:
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class ValidRequestTypeValidator implements ConstraintValidator<ValidRequest, EventRequest> {
#Override
public boolean isValid(EventRequest request, ConstraintValidatorContext constraintValidatorContext) {
// logic here
return false;
}
}
Constraint Validator which will handle all parameters of specific method:
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.constraintvalidation.SupportedValidationTarget;
import javax.validation.constraintvalidation.ValidationTarget;
#SupportedValidationTarget(ValidationTarget.PARAMETERS)
public class ValidRequestMethodValidator implements ConstraintValidator<ValidRequest, Object[]> {
#Override
public boolean isValid(Object[] objects, ConstraintValidatorContext constraintValidatorContext) {
Long entityId = null;
EventRequest eventRequest = null;
if (objects[0] instanceof Long) {
entityId = (Long) objects[0];
}
if (objects[0] instanceof EventRequest) {
eventRequest = (EventRequest) objects[0];
}
if (objects[1] instanceof EventRequest) {
eventRequest = (EventRequest) objects[1];
}
//logic here
return false;
}
}
Please note, we have to annotate the beans, which shall be validated, with #org.springframework.validation.annotation.Validated annotation to get method validators to work automatically.
Example of usage:
Mixed usage, #ValidRequest annotation defined on method and single parameter level.
#ValidRequest
public class EventRequest {
public String value;
}
#RestController
#Validated
public class Controller {
Response create(#Valid EventRequest request) {
return new Response();
}
#ValidRequest(validationAppliesTo = ConstraintTarget.PARAMETERS)
Response update(Long entityId, EventRequest request) {
return new Response();
}
}
For create method ValidRequestTypeValidator will be executed.
For update method ValidRequestMethodValidator will be executed.
2. Define annotation only for methods
#RestController
#Validated
public class Controller {
#ValidRequest(validationAppliesTo = ConstraintTarget.PARAMETERS)
Response create(EventRequest request) {
return new Response();
}
#ValidRequest(validationAppliesTo = ConstraintTarget.PARAMETERS)
Response update(Long entityId, EventRequest request) {
return new Response();
}
}
For create method ValidRequestMethodValidator will be executed with one element objects array
For update method ValidRequestMethodValidator will be executed with two elements objects array
3. Define annotation for a single parameter and method at the same time
#ValidRequest
public class EventRequest {
public String value;
}
#RestController
#Validated
public class Controller {
#ValidRequest(validationAppliesTo = ConstraintTarget.PARAMETERS)
Response update(Long entityId, #Valid EventRequest request) {
return new Response();
}
}
First will be executed single parameter validator ValidRequestTypeValidator.
If it will passed validation then second method validator ValidRequestMethodValidator will be executed.
Probably only one method-level validation will be sufficient to handle your issue. I described all variants, just for information maybe will be useful.

How can I instantiate a specific sub-type for a #RequestBody parameter based on the requested URI for a Spring MVC controller method?

Given the following basic domain model:
abstract class BaseData { ... }
class DataA extends BaseData { ... }
class DataB extends BaseData { ... }
I want to write a Spring MVC controller endpoint thus ...
#PostMapping(path="/{typeOfData}", ...)
ResponseEntity<Void> postData(#RequestBody BaseData baseData) { ... }
The required concrete type of baseData can be inferred from the typeOfData in the path.
This allows me to have a single method that can handle multiple URLs with different body payloads. I would have a concrete type for each payload but I don't want to have to create multiple controller methods that all do the same thing (albeit each would do very little).
The challenge that I am facing is how to "inform" the deserialization process so that the correct concrete type is instantiated.
I can think of two ways to do this.
First use a custom HttpMessageConverter ...
#Bean
HttpMessageConverter httpMessageConverter() {
return new MappingJackson2HttpMessageConverter() {
#Override
public Object read(final Type type, final Class<?> contextClass, final HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
// TODO How can I set this dynamically ?
final Type subType = DataA.class;
return super.read(subType, contextClass, inputMessage);
}
};
}
... which gives me the challenge to determine the subType based on the HttpInputMessage. Possibly I could use a Filter to set a custom header earlier when the URL is available to me, or I could use a ThreadLocal also set via a Filter. Neither sounds ideal to me.
My second approach would be to again use a Filter and this time wrap the incoming payload in an outer object which would then provide the type in a way that enables Jackson to do the work via #JsonTypeInfo. At the moment this is probably my preferred approach.
I have investigated HandlerMethodArgumentResolver but if I try to register a custom one it is registered AFTER the RequestResponseBodyMethodProcessor and that class takes priority.
Hmm, so after typing all of that out I had a quick check of something in the RequestResponseBodyMethodProcessor before posting the question and found another avenue to explore, which worked neatly.
Excuse the #Configuration / #RestController / WebMvcConfigurer mash-up and public fields, all for brevity. Here's what worked for me and achieved exactly what I wanted:
#Configuration
#RestController
#RequestMapping("/dummy")
public class DummyController implements WebMvcConfigurer {
#Target(ElementType.PARAMETER)
#Retention(RetentionPolicy.RUNTIME)
#Documented
#interface BaseData {}
public static class AbstractBaseData {}
public static class DataA extends AbstractBaseData {
public String a;
}
public static class DataB extends AbstractBaseData {
public String b;
}
private final MappingJackson2HttpMessageConverter converter;
DummyController(final MappingJackson2HttpMessageConverter converter) {
this.converter = converter;
}
#Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(
new RequestResponseBodyMethodProcessor(Collections.singletonList(converter)) {
#Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(BaseData.class)
&& parameter.getParameterType() == AbstractBaseData.class;
}
#Override
protected <T> Object readWithMessageConverters(
NativeWebRequest webRequest, MethodParameter parameter, Type paramType)
throws IOException, HttpMediaTypeNotSupportedException,
HttpMessageNotReadableException {
final String uri =
webRequest.getNativeRequest(HttpServletRequest.class).getRequestURI();
return super.readWithMessageConverters(
webRequest, parameter, determineActualType(webRequest, uri));
}
private Type determineActualType(NativeWebRequest webRequest, String uri) {
if (uri.endsWith("data-a")) {
return DataA.class;
} else if (uri.endsWith("data-b")) {
return DataB.class;
}
throw new HttpMessageNotReadableException(
"Unable to determine actual type for request URI",
new ServletServerHttpRequest(
webRequest.getNativeRequest(HttpServletRequest.class)));
}
});
}
#PostMapping(
path = "/{type}",
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
ResponseEntity<? extends AbstractBaseData> post(#BaseData AbstractBaseData baseData) {
return ResponseEntity.ok(baseData);
}
}
The key to this is that I stopped using #RequestBody because that is what was preventing me overriding the built-in behaviour. By using #BaseData instead I get a HandlerMethodArgumentResolver that uniquely supports the parameter.
Other than that it was a case of assembling the two objects that already did what I needed, so autowire a MappingJackson2HttpMessageConverter and instantiate a RequestResponseBodyMethodProcessor with that one converter. Then pick the right method to override so that I could control what parameter type was used at a point that I had access to the URI.
Quick test. Given the following payload for both requests ...
{
"a": "A",
"b": "B"
}
POST http://localhost:8081/dummy/data-a
... gives a response of ...
{
"a": "A"
}
POST http://localhost:8081/dummy/data-b
... gives a response of ...
{
"b": "B"
}
In our real-world example this means that we will be able to write one method each that supports the POST / PUT. We need to build the objects and configure the validation possibly - or alternatively if we use OpenAPI 3.0 which we are investigating we could generate the model and validate without writing any further code ... but that's a separate task ;)

Spring: HandlerMethodArgumentResolved not working with custom annotation parameter

I've been searching for hours on the internet, as well as attempting the solutions i've found in order to work with a custom parameter annotation on a controller method.
The idea behind this is that i want to practice how to map requests, responses and all sort of things with custom annotations when working with spring.
So what i want is to create an annotation parameter which should create a Map instance, my interface is coded this way:
#Target(ElementType.PARAMETER)
#Retention(RetentionPolicy.RUNTIME)
#Documented
public #interface SearchCriteria {
String value() default "";
}
The resolver:
public class SearchCriteriaResolver implements HandlerMethodArgumentResolver {
private Logger log = LoggerFactory.getLogger(SearchCriteriaResolver.class);
private Map<String, Object> parameters = new HashMap<>() {{
put("name", "");
put("limit", 10);
}};
#Override
public boolean supportsParameter(MethodParameter methodParameter) {
return methodParameter.hasParameterAnnotation(SearchCriteria.class);
}
#Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
HttpServletRequest request = (HttpServletRequest) nativeWebRequest.getNativeRequest();
log.info("Parameter test: " + request.getParameter("test"));
return this.parameters;
}
}
And the configurer:
#Configuration
#EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
#Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new SearchCriteriaResolver());
}
}
I've found on the internet multiple times that handlers are created this way. So in the controller, i am making use of the annotation like this:
#RestController
#RequestMapping("/series")
public class SeriesController {
private static final Logger log = LoggerFactory.getLogger(SeriesController.class);
#Autowired
SeriesService seriesService;
#GetMapping
public ResponseEntity<List<SeriesBatch>> getSeriesList(#SearchCriteria Map<String, Object> parameters) {
log.info("GET /series/ -> getSeriesList");
log.info(parameters.toString());
List<SeriesBatch> seriesList = this.seriesService.findAll();
return new ResponseEntity<>(seriesList, HttpStatus.OK);
}
...
}
So i've been checking in the logs everytime this endpoint is triggered, but the log on the resolver is not triggered, and the log in the controller method only shows an empty object. I've debugged the application start to see if the resolvers.add is being invoked, and it is, but for some reason i don't know, the logic for this annotation is not being executed.
NOTE: I am learning spring as well as taking back JAVA after a long time, so i would appreciate if an explanation on why it has to be that way on the answer is given.
Refactor your code in a way that the data you stored in a java.util.Map instance before will now be stored in some other object, e.g. an instance of a custom class SearchParams. You could even wrap your map as a member in that class to keep things simple for now:
class SearchParams {
private Map<String, Object> values = new HashMap<>();
public void setValue(String key, Object value) {
this.values.put(key, value);
}
public Object getValue(String key) {
this.values.get(key);
}
public Map<String, Object> list() {
return new HashMap<>(this.values);
}
}
Now change your controller method to accept a SearchParams object instead of Map<String, Object>:
public ResponseEntity<List<SeriesBatch>> getSeriesList(#SearchCriteria SearchParams parameters) { ... }
Last but not least you gotta change your #SearchCriteria annotation implementation, e.g. as follows:
public class SearchCriteriaResolver implements HandlerMethodArgumentResolver {
#Override
public boolean supportsParameter(MethodParameter methodParameter) {
return methodParameter.hasParameterAnnotation(SearchCriteria.class);
}
#Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
// somehow determine search params
// setup + return your new SearchParams object to encapsulate your determined search params
SearchParams searchParams = new SearchParams();
searchParams.add("somekey", "somevalue");
return searchParams;
}
}
Now, plz try this out and let me know if it worked out well ;-)
Detailed explanation:
Have a look at Spring's org.springframework.web.method.support.HandlerMethodArgumentResolverComposite class, especially it's getArgumentResolver(MethodParameter parameter) method. Under the hood, Spring maintains a list of different HandlerMethodArgumentResolver instances and loops over them to find one that matches a given method argument (and later on map the method argument's value to some other object!). One of the registered HandlerMethodArgumentResolvers is of type org.springframework.web.method.annotation.MapMethodProcessor. MapMethodProcessor also matches if the parameter if of type java.util.Map and matches first (see attached screenshot below). That's why your custom HandlerMethodArgumentResolver never got called...
[[https://reversecoding.net/spring-mvc-requestparam-binding-request-parameters/]] shows an example where a java.util.Map is used as a controller method's argument -> search for '7. #RequestParam with Map'
Possible way to configure order / change priority of custom any HandlerMethodArgumentResolver in WebConfig configuration class:
#Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
// add custom resolver to beginning of resolver list
resolvers.add(0, new SearchCriteriaResolver());
}

Validate URL path for several controller methods

Given multiple REST resources to gather order information.
/order/{id}
/order/{id}/positions
/order/{id}/invoice
/order/{id}/shipment
Within the a Srping Boot 2 application it's implemented across multiple controllers, e.g. OrderController, InvoiceController, etc.
Currently every controller uses the OrderRepository to ensure the the order with the given id exists. Otherwise it throws an exception. It's always the same replicated code.
#RestController
public class OrderController {
// ...
#GetMapping("order/{id}")
public Order getCustomer(#PathVariable final Integer id) {
return this.orderRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("order not found"));
}
}
Does the framework provide a callback to write the order id check just once?
I found the AntPathMatcher but it seems not the right way, since it provides just an boolean interface.
This is usually a good case for bean validation. While there is already builtin support for many cases of validation (#Size, #NotNull, ...), you can also write your own custom constraints.
First of all, you need to define an annotation to validate your ID, for example:
#Documented
#Constraint(validatedBy = OrderIdValidator.class)
#Target({PARAMETER})
#Retention(RUNTIME)
public #interface ValidOrderId {
String message() default "Invalid order ID";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Since your order ID is always a parameter for your controller mappings, you could use ElementType.PARAMETER to only allow the annotation for method parameters.
The next step is to add the #Constraint annotation to it and point to a custom validator class (eg. OrderIdValidator):
#Component
public class OrderIdValidator implements ConstraintValidator<ValidOrderId, Integer> {
private OrderRepository repository;
public OrderIdValidator(OrderRepository repository) {
this.repository = repository;
}
#Override
public boolean isValid(Integer id, ConstraintValidatorContext constraintValidatorContext) {
return repository.existsById(id);
}
}
By implementing the isValid method, you can check whether or not the order exists. If it doesn't exist, an exception will be thrown and the message() property of the #ValidOrderId annotation will be used as a message.
The last step is to add the #Validated annotation to all of your controllers, and to add the #ValidOrderId annotation to all order ID parameters, for example:
#Validated // Add this
#RestController
public class OrderController {
#GetMapping("order/{id}")
public Order getCustomer(#PathVariable #ValidOrderId final Integer id) { // Add #ValidOrderId
// Do stuff
}
}
If you prefer to use a different response status for your validations, you could always add a class annotated with the #ControllerAdvice annotation and use the following method:
#ExceptionHandler(ConstraintViolationException.class)
public void handleConstraints(HttpServletResponse response) throws IOException {
response.sendError(HttpStatus.BAD_REQUEST.value());
}

How do I use a custom validator with dropwizard?

I have a REST api written by someone else in which the method that handles the request to a particular url accepts a bunch of parameters that are populated from path parameters.
#POST
#Path("/{classid}/{studentid}/details")
#Consumes(MediaType.MULTIPART_FORM_DATA)
#SuppressWarnings("unchecked")
public Response processFile(#FormDataParam("sourceFile") InputStream aStream, #PathParam("classid") String classId, #PathParam("studentid") String studentId, #Context HttpServletRequest httpRequest) {
// Code to do stuff and return a response
}
The person who wrote this has used DropWizard and I have no previous experience working on it. I have the task of validating the studentId field by comparing it with values in the db. This would be pretty straightforward but I have been told to do it using a custom validator. I am pretty new to writing annotations but after much digging wrote an annotation like this,
#Target(ElementType.PARAMETER)
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Constraint(validatedBy = StudentIdValidator.StudentIdValidation.class)
public #interface StudentIdValidator {
String message() default "{Invalid Id}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
class StudentIdValidation implements ConstraintValidator<StudentIdValidator, String> {
#Override
public void initialize(StudentIdValidator constraintAnnotation) {
System.out.println("Annotation initialize !!!!!!!!!");
}
#Override
public boolean isValid(String value, ConstraintValidatorContext context) {
// TODO Auto-generated method stub
System.out.println("Annotation called");
return false;
}
}
}
After this I added the annotation to the field I wanted to run the validation on like this,
public Response processFile(#FormDataParam("sourceFile") InputStream aStream, #PathParam("classid") String classId, #StudentIdValidator #PathParam("studentid") String studentId, #Context HttpServletRequest httpRequest)
Now the problem is that, when the I run/debug the code...this validator is not being called, also I have no idea how to get the value of studentId inside the studentId validation class. So I dug some more and added this to the application file
class MyApplication extends Application<MyConfiguration> {
........
#Override
public void run(MyConfiguration myConfiguration, Environment currentEnvironment) {
currentEnvironment.jersey().register(StudentIdValidator.class);
}
I am literally at the end of my wits. Any help will be very VERY appreciated. Sorry about the poor formatting.
this is pretty straight forward. I will paste my example here since I had it written up and I am lazy and don't want to take your fun experience away :)
Edit: I think your issue is that you didn't annotate your resource with #Valid
so here we go:
You are on the right track with the validator. These are mine:
public class CustomValidator implements ConstraintValidator<CustomValidation, String> {
#Override
public void initialize(CustomValidation constraintAnnotation) {
}
#Override
public boolean isValid(String value, ConstraintValidatorContext context) {
System.out.println("Validation called");
return false;
}
}
And this is the Annotation:
#Constraint(validatedBy = {CustomValidator.class})
#Target({ElementType.FIELD, ElementType.PARAMETER})
#Retention(value = RetentionPolicy.RUNTIME)
public #interface CustomValidation {
String message() default "Some message";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
The application:
public class Application extends io.dropwizard.Application<Configuration>{
#Override
public void run(Configuration configuration, Environment environment) throws Exception {
MetricRegistry metrics = environment.metrics();
environment.jersey().register(new HelloResource(metrics));
}
public static void main(String[] args) throws Exception {
new Application().run("server", "/home/artur/dev/repo/sandbox/src/main/resources/config/test.yaml");
}
}
And the resource:
#Path("/test")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public class HelloResource {
private MetricRegistry service;
public HelloResource(MetricRegistry service) {
this.service = service;
}
#GET
public String hello() {
Timer timer = service.timer("test");
try(Context t = timer.time()) {
return "Hello World";
}
}
#GET
#Path("/test2")
public void test(#Valid #CustomValidation #QueryParam("arg") String test) {
System.out.println(test);
}
}
Don't mind the metrics, they have nothing to do with it. The important part is that you need to tell DW what you want to have validated.
In the resource, see the test method. I annotate the argument I need with #Valid (tells DW to validate) #CustomValidation (tells DW what validator to use).
This is not actually a Dropwizard feature, but rather a hibernate validator implementation.
The way it works under the hood is that hibernate creates the Validator class on the fly when requested by invoking the constructor. Now this works very fine if you have simple validation (like say comparing a string). If you need dependencies, then it gets slightly more tricky. I have an example for that as well, that you can read up on here:
With dropwizard validation, can I access the DB to insert a record
This example uses guice, but it demonstrates how you can hook your own creation mechanism into validation. That way you can control your validator creation and inject or initialise them with a datasource to access your database.
I hope that answers your questions,
Artur
Custom valdation in drop wizard are same as hibernate custom validators.
Follow the link : hibernate validator-customconstraints

Categories