Utility library for REST services
Library is compatible with Java 11+
Import library in your project:
<dependency>
<groupId>com.mjamsek.rest</groupId>
<artifactId>rest-utils</artifactId>
<version>${rest-utils-lib.version}</version>
</dependency>
Library provides validating service.
import javax.inject.Inject;
import com.mjamsek.rest.factories.ValidatorFactory;
import com.mjamsek.rest.services.Validator;
class Sample {
@Inject
private Validator validator;
public void init() {
// Get new instance in non-CDI context
this.validator = ValidatorFactory.getNewInstance();
}
public void sample() {
// Asserts object is not null
validator.assertNotNull(request.field);
// Asserts string is not null or empty (spaces are trimmed)
validator.assertNotBlank(request.field);
// Asserts string matches regex pattern
validator.assertRegex(request.field, regexp);
// Asserts string matches email pattern (compliant with RFC 5322)
validator.assertEmail(request.field);
// Asserts that value is not after second argument
validator.assertNotAfter(new Date(), request.getExpirationDate());
// Asserts that value is not before second argument
validator.assertNotBefore(new Date(), request.getStartDate());
}
}
All of these methods throw ValidationException if assertion fails. More in exceptions.
Library also provides overloaded methods to provide additional information to user.
Service for localizing messages from java properties file.
Translations are expected to be in classpath:/i18n/translations[_en_US].properties
.
import javax.inject.Inject;
import com.mjamsek.rest.factories.LocalizatorFactory;
import com.mjamsek.rest.services.Localizator;
class Sample {
@Inject
private Localizator localizator;
public void init() {
// Get new instance in non-CDI context
this.localizator = LocalizatorFactory.getNewInstance();
}
public void sample() {
// If translation_en_US.properties contains
// code.error=Error!
String message = localizator.getTranslation("code.error", new Locale("en", "US"));
// then message == "Error!"
// It is also possible to pass params for
// parameterized messages like:
// code.error=Error occurred at line {}
String message = localizator.getTranslation("code.error", new Locale("en", "US"), 2);
// then message == "Error occurred at line 2"
}
}
Library provides additional statuses:
- 422 (validation failed)
int status = Rest.HttpStatus.VALIDATION_FAILED;
- 424 (validation failed)
int status = Rest.HttpStatus.FAILED_DEPENDENCY;
It also provides additional header fields:
- X-Service-Name
String header = Rest.HttpHeaders.X_SERVICE_NAME;
- X-Service-Version
String header = Rest.HttpHeaders.X_SERVICE_VERSION;
- X-Service-Env
String header = Rest.HttpHeaders.X_SERVICE_END;
- X-Powered-By
String header = Rest.HttpHeaders.X_POWERED_BY;
- X-Request-Id
String header = Rest.HttpHeaders.X_REQUEST_ID;
- X-Total-Count
String header = Rest.HttpHeaders.X_TOTAL_COUNT;
- X-Limit
String header = Rest.HttpHeaders.X_LIMIT;
- X-Offset
String header = Rest.HttpHeaders.X_OFFSET;
- Content-Disposition
String header = Rest.HttpHeaders.CONTENT_DISPOSITION;
- Authorization
String header = Rest.HttpHeaders.AUTHORIZATION;
- X-Content-Type-Options
String header = Rest.HttpHeaders.X_CONTENT_TYPE_OPTIONS;
- X-XSS-Protection
String header = Rest.HttpHeaders.X_XSS_PROTECTION;
- X-Frame-Options
String header = Rest.HttpHeaders.X_FRAME_OPTIONS;
- Strict-Transport-Security
String header = Rest.HttpHeaders.STRICT_TRANSPORT_SECURITY;
- Content-Security-Policy
String header = Rest.HttpHeaders.CONTENT_SECURITY_POLICY;
- Access-Control-Allow-Origin
String header = Rest.HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN;
- Access-Control-Expose-Headers
String header = Rest.HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS;
- Access-Control-Allow-Credentials
String header = Rest.HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS;
- Access-Control-Allow-Methods
String header = Rest.HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS;
- Access-Control-Allow-Headers
String header = Rest.HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS;
- Timing-Allow-Origin
String header = Rest.HttpHeaders.TIMING_ALLOW_ORIGIN;
Generic base exception. All other exceptions inherit from it.
Thrown when call to other service fails. Returns code 503.
Validation exception uses self-enclosing data (ExceptionResponse
), so there is no need to map its data. To provide better message to users, simply provide exception mapper:
import com.mjamsek.rest.exceptions.ValidationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
@Provider
public class ValidationExceptionMapper implements ExceptionMapper<ValidationException> {
@Override
public Response toResponse(ValidationException e) {
return e.getResponse().createResponse();
}
}
Error when receiveing bad data from user. Returns 400.
Return 401 or 403, if user lacks proper permissions.
Thrown when requested entity does not exist and returns 404. It also provides an overloaded constructor to easily describe to user what is missing.
You can also provide your own implementation of ExceptionResponse
:
import com.mjamsek.rest.exceptions.RestException;
import com.mjamsek.rest.exceptions.dto.ExceptionResponse;
import javax.ws.rs.core.Response;
class Sample {
public void sample() {
MyException myExc = new MyException()
.setStatus(500)
.setMessage("Server error")
.setCode("error.server")
.setEntity("Person")
.setField("lastName")
.setMoreInfo("see more at: https://google.com");
throw new RestException("code.error")
.replaceResponse(myExc);
}
public static class MyException extends ExceptionResponse {
private String additionalField;
@Override
public Response createResponse() {
return Response.status(this.status).entity(this).build();
}
public String getAdditionalField() {
return this.additionalField;
}
public void setAdditionalField(String additionalField) {
this.additionalField = additionalField;
}
}
}
Changes can be viewed on releases page on GitHub.
MIT