Atul Sureka
Atul Sureka

Reputation: 3312

Custom validation with RESTful APIs

I am newbie in Java world (came from .Net background). I created a RESTful service using Jersey framework. it has couple of methods. Following is the sample code snippet for Customer service. There are couple more services in my code.

@Path("/CustomerService")
public interface ICustomerService {

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @Path("/getCustomerInfo")
    Response query(String constraints);

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @Path("/getCustomerDetails")
    Response fetchDetails(String customerID);

}

I have some validation logic which I would like to perform at each API which is exposed to the client. I C# world we can define own validation logic. Something like following, This can be applied at method or controller level.

[MyValdationLogic()]

What is the equivalent in Java? How can I write code which can be applied at multiple places over the method.

Also I do not want to allow admin to play with that configuration. I found there is something called as filters but this gets configured in config file. admin can disable it.

Upvotes: 2

Views: 885

Answers (1)

Vikas Sachdeva
Vikas Sachdeva

Reputation: 5803

You can create a Validator class and use that Validator class on your bean for validation. Although, the process is bit lengthy.

Following is one example of doing this -

Jersey Resource

@POST
@Path("/addEmp")
@Produces("text/plain")
public String doOrder(@BeanParam final @Valid Employee emp) {

    // Some implementation here
}

Sample Bean - Suppose, I want to apply validation on address i.e. either address or city or postcode must be there.

@Address
public final class Employee {

    @FormDataParam("id")
    private String id;

    @FormDataParam("address")
    private String address;

    @FormDataParam("city")
    private String city;

    @FormDataParam("postcode")
    private String postcode;

        // Other member variables

        // Getters and setters

}

Address Annotation - Define custom Address Annotation

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RUNTIME)
@Constraint(validatedBy = AddressValidator.class)
@Documented
public @interface Address {

    String message() default "Address required";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

Validator Class - Here is the validator class contains actual validation logic -

public class AddressValidator implements ConstraintValidator<Address, Employee> {

    @Override
    public boolean isValid(Employee emp, ConstraintValidatorContext constraintValidatorContext) {

    // Check for at least one value
    if((emp.getAddress() != null && !emp.getAddress().equals("") ||
            (emp.getCity() != null && !emp.getCity().equals("")) ||
            (emp.getPostcode() != null && !emp.getPostcode().equals("")))) {
        return true;
    }

    return false;
    }
    public void initialize(Address emp) {
          ...
    }
}

By this way, you can create reusable Validator class. Instead of taking Employee directly in this Validator class, you can take Object class or some parent class and then change the logic accordingly.

You can check more details in bean-validation

Upvotes: 3

Related Questions