Validation of input beans is now performed automatically
git-svn-id: https://svn.d4science.research-infrastructures.eu/gcube/trunk/data-catalogue/grsf-publisher-ws@133247 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
parent
f128ca18ab
commit
9bb23c991f
|
@ -3,9 +3,6 @@
|
|||
<wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/>
|
||||
<wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>
|
||||
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
|
||||
<dependent-module archiveName="ckan-util-library-2.0.0-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/ckan-util-library/ckan-util-library">
|
||||
<dependency-type>uses</dependency-type>
|
||||
</dependent-module>
|
||||
<property name="context-root" value="grsf-publisher-ws"/>
|
||||
<property name="java-output-path" value="/grsf-publisher-ws/target/classes"/>
|
||||
</wb-module>
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package org.gcube.data_catalogue.grsf_publish_ws.ex;
|
||||
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.ext.ExceptionMapper;
|
||||
import javax.ws.rs.ext.Provider;
|
||||
|
||||
@Provider
|
||||
/**
|
||||
* Exception thrown when @Valid fail
|
||||
* @author Costantino Perciante at ISTI-CNR
|
||||
*/
|
||||
public class ApplicationException implements ExceptionMapper<Exception> {
|
||||
|
||||
public Response toResponse(Exception e) {
|
||||
return Response
|
||||
.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode())
|
||||
.type(MediaType.APPLICATION_JSON)
|
||||
.entity(e.getMessage())
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package org.gcube.data_catalogue.grsf_publish_ws.ex;
|
||||
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.ConstraintViolationException;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.ext.ExceptionMapper;
|
||||
import javax.ws.rs.ext.Provider;
|
||||
|
||||
@Provider
|
||||
/**
|
||||
* Exception thrown on fail
|
||||
* @author Costantino Perciante at ISTI-CNR
|
||||
*/
|
||||
public class ValidationException implements ExceptionMapper<javax.validation.ValidationException> {
|
||||
|
||||
@Override
|
||||
public Response toResponse(javax.validation.ValidationException e) {
|
||||
final StringBuilder strBuilder = new StringBuilder();
|
||||
for (ConstraintViolation<?> cv : ((ConstraintViolationException) e).getConstraintViolations()) {
|
||||
strBuilder.append(cv.getPropertyPath().toString() + " " + cv.getMessage());
|
||||
}
|
||||
return Response
|
||||
.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode())
|
||||
.type(MediaType.APPLICATION_JSON)
|
||||
.entity(strBuilder.toString())
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
|
@ -52,11 +53,13 @@ public class Common {
|
|||
@JsonProperty("database_sources")
|
||||
@NotNull(message="database_source cannot be null")
|
||||
@Size(min=1, message="database_source cannot be empty")
|
||||
@Valid
|
||||
private List<DatabaseSource> databaseSources;
|
||||
|
||||
@JsonProperty("source_of_information")
|
||||
@NotNull(message="source_of_information cannot be null")
|
||||
@Size(min=1, message="source_of_information cannot be empty")
|
||||
@Valid
|
||||
private List<Resource> sourceOfInformation;
|
||||
|
||||
@JsonProperty("data_owner")
|
||||
|
|
|
@ -7,6 +7,8 @@ import java.util.Map;
|
|||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.ValidationException;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
|
@ -81,7 +83,8 @@ public class GrsfPublisherFisheryService {
|
|||
@Path("publish-product")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response publishFishery(FisheryRecord record){
|
||||
public Response publishFishery(
|
||||
@NotNull(message="record cannot be null") @Valid FisheryRecord record) throws ValidationException{
|
||||
|
||||
// retrieve context and username
|
||||
Caller caller = AuthorizationProvider.instance.get();
|
||||
|
@ -95,18 +98,18 @@ public class GrsfPublisherFisheryService {
|
|||
Status status = Status.INTERNAL_SERVER_ERROR;
|
||||
String id = "";
|
||||
|
||||
// validate the bean
|
||||
logger.debug("Start validating bean...");
|
||||
Response responseAfterValidation = HelperMethods.validateBeanAndResources(record);
|
||||
|
||||
if(responseAfterValidation == null)
|
||||
logger.debug("Bean validation successful");
|
||||
else{
|
||||
|
||||
logger.warn("Bean validation failed");
|
||||
return responseAfterValidation;
|
||||
|
||||
}
|
||||
// // validate the bean
|
||||
// logger.debug("Start validating bean...");
|
||||
// Response responseAfterValidation = HelperMethods.validateBeanAndResources(record);
|
||||
//
|
||||
// if(responseAfterValidation == null)
|
||||
// logger.debug("Bean validation successful");
|
||||
// else{
|
||||
//
|
||||
// logger.warn("Bean validation failed");
|
||||
// return responseAfterValidation;
|
||||
//
|
||||
// }
|
||||
|
||||
try{
|
||||
|
||||
|
@ -217,7 +220,7 @@ public class GrsfPublisherFisheryService {
|
|||
if(HelperMethods.existsLicenseId(record.getLicense()))
|
||||
license = record.getLicense();
|
||||
else throw new Exception("Please check the license id!");
|
||||
|
||||
|
||||
long version = record.getVersion() == null ? 1 : record.getVersion();
|
||||
|
||||
// create the product
|
||||
|
@ -263,12 +266,12 @@ public class GrsfPublisherFisheryService {
|
|||
return Response.status(status).entity(responseBean).build();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@DELETE
|
||||
@Path("delete-product")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response deleteFishery(@Valid DeleteProductBean recordToDelete){
|
||||
public Response deleteFishery(@NotNull(message="missing input value") @Valid DeleteProductBean recordToDelete) throws ValidationException{
|
||||
|
||||
// retrieve context and username
|
||||
Caller caller = AuthorizationProvider.instance.get();
|
||||
|
@ -278,7 +281,7 @@ public class GrsfPublisherFisheryService {
|
|||
ResponseCreationBean responseBean = new ResponseCreationBean();
|
||||
Status status = Status.INTERNAL_SERVER_ERROR;
|
||||
|
||||
// check it is a stock ...
|
||||
// check it is a fishery ...
|
||||
logger.info("Received call to delete product with id " + recordToDelete.getId() + ", checking if it is a fishery");
|
||||
try{
|
||||
|
||||
|
@ -302,7 +305,7 @@ public class GrsfPublisherFisheryService {
|
|||
|
||||
}
|
||||
|
||||
// get extras and check there is the field Assessment distribution area that is mandatory for stock
|
||||
// get extras and check there is the field Fishery Name that is mandatory for fishery
|
||||
if(fisheryInCkan.getExtrasAsHashMap().containsKey("Fishery Name")){
|
||||
|
||||
logger.warn("Ok, this is a fishery, removing it");
|
||||
|
|
|
@ -7,6 +7,8 @@ import java.util.Map;
|
|||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.ValidationException;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
|
@ -81,7 +83,8 @@ public class GrsfPublisherStockService {
|
|||
@Path("publish-product")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response publishStock(StockRecord record){
|
||||
public Response publishStock(
|
||||
@NotNull(message="record cannot be null") @Valid StockRecord record) throws ValidationException{
|
||||
|
||||
// retrieve context and username
|
||||
Caller caller = AuthorizationProvider.instance.get();
|
||||
|
@ -95,18 +98,18 @@ public class GrsfPublisherStockService {
|
|||
Status status = Status.INTERNAL_SERVER_ERROR;
|
||||
String id = "";
|
||||
|
||||
// validate the bean
|
||||
logger.debug("Start validating bean...");
|
||||
Response responseAfterValidation = HelperMethods.validateBeanAndResources(record);
|
||||
|
||||
if(responseAfterValidation == null)
|
||||
logger.debug("Bean validation successful");
|
||||
else{
|
||||
|
||||
logger.warn("Bean validation failed");
|
||||
return responseAfterValidation;
|
||||
|
||||
}
|
||||
// // validate the bean
|
||||
// logger.debug("Start validating bean...");
|
||||
// Response responseAfterValidation = HelperMethods.validateBeanAndResources(record);
|
||||
//
|
||||
// if(responseAfterValidation == null)
|
||||
// logger.debug("Bean validation successful");
|
||||
// else{
|
||||
//
|
||||
// logger.warn("Bean validation failed");
|
||||
// return responseAfterValidation;
|
||||
//
|
||||
// }
|
||||
|
||||
try{
|
||||
|
||||
|
@ -259,7 +262,7 @@ public class GrsfPublisherStockService {
|
|||
@Path("delete-product")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response deleteStock(@Valid DeleteProductBean recordToDelete){
|
||||
public Response deleteStock(@NotNull(message="missing input value") @Valid DeleteProductBean recordToDelete) throws ValidationException{
|
||||
|
||||
// retrieve context and username
|
||||
Caller caller = AuthorizationProvider.instance.get();
|
||||
|
|
|
@ -8,14 +8,8 @@ import java.util.ArrayList;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.Validation;
|
||||
import javax.validation.Validator;
|
||||
import javax.validation.ValidatorFactory;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.gcube.common.scope.api.ScopeProvider;
|
||||
import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.CustomField;
|
||||
|
@ -24,7 +18,6 @@ import org.gcube.data_catalogue.grsf_publish_ws.custom_annotations.Tag;
|
|||
import org.gcube.data_catalogue.grsf_publish_ws.json.input.Common;
|
||||
import org.gcube.data_catalogue.grsf_publish_ws.json.input.DatabaseSource;
|
||||
import org.gcube.data_catalogue.grsf_publish_ws.json.input.Resource;
|
||||
import org.gcube.data_catalogue.grsf_publish_ws.json.output.ResponseCreationBean;
|
||||
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Source;
|
||||
import org.gcube.data_catalogue.grsf_publish_ws.utils.groups.Status;
|
||||
import org.gcube.datacatalogue.ckanutillibrary.DataCatalogue;
|
||||
|
@ -113,7 +106,7 @@ public abstract class HelperMethods {
|
|||
}
|
||||
}
|
||||
while((current = current.getSuperclass())!=null);
|
||||
|
||||
|
||||
// now parse also the Database Sources field
|
||||
List<DatabaseSource> sources = record.getDatabaseSources();
|
||||
for (DatabaseSource databaseSource : sources) {
|
||||
|
@ -359,49 +352,49 @@ public abstract class HelperMethods {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a record along the database_sources and the source_of_information
|
||||
* @param record
|
||||
* @return
|
||||
*/
|
||||
public static Response validateBeanAndResources(Common record){
|
||||
|
||||
ResponseCreationBean responseBean = new ResponseCreationBean();
|
||||
javax.ws.rs.core.Response.Status status = javax.ws.rs.core.Response.Status.BAD_REQUEST;
|
||||
|
||||
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
|
||||
Validator validator = factory.getValidator();
|
||||
|
||||
|
||||
Set<ConstraintViolation<Common>> violations = validator.validate(record);
|
||||
for (ConstraintViolation<Common> constraintViolation : violations) {
|
||||
logger.warn("Violation is about " + constraintViolation.getPropertyPath() + ", message error is " + constraintViolation.getMessage());
|
||||
responseBean.setError(constraintViolation.getMessage());
|
||||
return Response.status(status).entity(responseBean).build();
|
||||
}
|
||||
|
||||
// check database_sources and source_of_information (they are not null nor empty at this point)
|
||||
List<DatabaseSource> databaseSources = record.getDatabaseSources();
|
||||
for (DatabaseSource databaseSource : databaseSources) {
|
||||
Set<ConstraintViolation<DatabaseSource>> violationsDatabaseSourcesBean = validator.validate(databaseSource);
|
||||
for (ConstraintViolation<DatabaseSource> constraintViolation : violationsDatabaseSourcesBean) {
|
||||
logger.warn("Violation is about " + constraintViolation.getPropertyPath() + ", message error is " + constraintViolation.getMessage());
|
||||
responseBean.setError(constraintViolation.getMessage());
|
||||
return Response.status(status).entity(responseBean).build();
|
||||
}
|
||||
}
|
||||
|
||||
List<Resource> sourcesOfInformation = record.getSourceOfInformation();
|
||||
for (Resource sourceOfinformation : sourcesOfInformation) {
|
||||
Set<ConstraintViolation<Resource>> violationsSourceOfinformationsBean = validator.validate(sourceOfinformation);
|
||||
for (ConstraintViolation<Resource> constraintViolation : violationsSourceOfinformationsBean) {
|
||||
logger.warn("Violation is about " + constraintViolation.getPropertyPath() + ", message error is " + constraintViolation.getMessage());
|
||||
responseBean.setError(constraintViolation.getMessage());
|
||||
return Response.status(status).entity(responseBean).build();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// /**
|
||||
// * Validate a record along the database_sources and the source_of_information
|
||||
// * @param record
|
||||
// * @return
|
||||
// */
|
||||
// public static Response validateBeanAndResources(Common record){
|
||||
//
|
||||
// ResponseCreationBean responseBean = new ResponseCreationBean();
|
||||
// javax.ws.rs.core.Response.Status status = javax.ws.rs.core.Response.Status.BAD_REQUEST;
|
||||
//
|
||||
// ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
|
||||
// Validator validator = factory.getValidator();
|
||||
//
|
||||
//
|
||||
// Set<ConstraintViolation<Common>> violations = validator.validate(record);
|
||||
// for (ConstraintViolation<Common> constraintViolation : violations) {
|
||||
// logger.warn("Violation is about " + constraintViolation.getPropertyPath() + ", message error is " + constraintViolation.getMessage());
|
||||
// responseBean.setError(constraintViolation.getMessage());
|
||||
// return Response.status(status).entity(responseBean).build();
|
||||
// }
|
||||
//
|
||||
// // check database_sources and source_of_information (they are not null nor empty at this point)
|
||||
// List<DatabaseSource> databaseSources = record.getDatabaseSources();
|
||||
// for (DatabaseSource databaseSource : databaseSources) {
|
||||
// Set<ConstraintViolation<DatabaseSource>> violationsDatabaseSourcesBean = validator.validate(databaseSource);
|
||||
// for (ConstraintViolation<DatabaseSource> constraintViolation : violationsDatabaseSourcesBean) {
|
||||
// logger.warn("Violation is about " + constraintViolation.getPropertyPath() + ", message error is " + constraintViolation.getMessage());
|
||||
// responseBean.setError(constraintViolation.getMessage());
|
||||
// return Response.status(status).entity(responseBean).build();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// List<Resource> sourcesOfInformation = record.getSourceOfInformation();
|
||||
// for (Resource sourceOfinformation : sourcesOfInformation) {
|
||||
// Set<ConstraintViolation<Resource>> violationsSourceOfinformationsBean = validator.validate(sourceOfinformation);
|
||||
// for (ConstraintViolation<Resource> constraintViolation : violationsSourceOfinformationsBean) {
|
||||
// logger.warn("Violation is about " + constraintViolation.getPropertyPath() + ", message error is " + constraintViolation.getMessage());
|
||||
// responseBean.setError(constraintViolation.getMessage());
|
||||
// return Response.status(status).entity(responseBean).build();
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Retrieve the ResourceBean given the record (extract resources from Database Sources and Source of Information)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<version>1.0.0-SNAPSHOT</version>
|
||||
<description>Data Catalogue Service</description>
|
||||
<local-persistence location='target' />
|
||||
<exclude>/rest/</exclude>
|
||||
<exclude>/rest/stock/hello</exclude>
|
||||
<exclude>/rest/fishery/hello</exclude>
|
||||
</application>
|
|
@ -12,6 +12,10 @@
|
|||
<param-name>jersey.config.server.provider.packages</param-name>
|
||||
<param-value>org.gcube.data_catalogue.grsf_publish_ws.services</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>jersey.config.beanValidation.enableOutputValidationErrorEntity.server</param-name>
|
||||
<param-value>true</param-value>
|
||||
</init-param>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<html>
|
||||
<body>
|
||||
<h2>The social networking web service is up and running!</h2>
|
||||
<h2>The GRSF publisher web service is up and running!</h2>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -24,7 +24,7 @@ public class JJerseyTest extends JerseyTest{
|
|||
//@Override
|
||||
protected Application configure() {
|
||||
forceSet(TestProperties.CONTAINER_PORT, "0");
|
||||
return new ResourceConfig(GrsfPublisherFisheryService.class, GrsfPublisherStockService.class);
|
||||
return new ResourceConfig(GrsfPublisherFisheryService.class, GrsfPublisherStockService.class).property("jersey.config.beanValidation.enableOutputValidationErrorEntity.server", true);
|
||||
}
|
||||
|
||||
//@Test
|
||||
|
|
Loading…
Reference in New Issue