I am trying to use Jersey to get JSON request from the user to create vendor
#POST
#Produces({APPLICATION_JSON})
#Consumes({APPLICATION_JSON})
#Path("create")
public Response create(VendorTO vendorTO) throws Exception {
But before it converts in vendorTO object I want to validate it with javax.validation
I have added constraints in my pojo like this
{#JsonSerialize(include=Inclusion.NON_NULL)
public class VendorTO {
#NotNull
private Integer userId;
#Size(min = 2)
private String vendorName;
private String address1;
private String address2;
private String city;
private String state;
private String country;
private String email;
private String phone;
}
but it doesnt seems to be working. Can anyone help ?
You need to tell the framework that the parameter should be #Validated:
#POST
#Produces({APPLICATION_JSON})
#Consumes({APPLICATION_JSON})
#Path("create")
public Response create(#Valid VendorTO vendorTO) {
// ...
}
At this point, it appears Jersey does not support JSR 303 natively. You might have to write some ResourceFilters and handle the validation manually.
Related
I need a custom validator in Spring Boot(version 2.7.x). My User class is defined as:
class User{
private String email;
private String phone;
private String name;
private String address;
private String city;
private String country;
private String postalCode;
//getters and setters
}
I'm trying to validate the following requirements:
Either phone or email or a combination of (name+address+city+country+postalCode) is mandatory
If (name+address+city+country+postalCode) is present, they should be not null.
Please help with your suggestions as to how do I go about in implementing it.
you can use JSR-303 valiation implementation that hibernate-validator
and it is conventient to use annotation for valiate which
is in package javax.validation.constraints
here is code sample that
you can use #NotNull annotation above Field that mark the field should be not null
entity
class User{
private String email;
private String phone;
private String name;
#NotNull(message = "address should be not null")
private String address;
private String city;
private String country;
private String postalCode;
//getters and setters
}
validatorUtil
#Slf4j
public class ValidatorUtil {
static Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
public static <T> Set<ConstraintViolation<T>> validateOne(T t , Class<?>... group) {
Set<ConstraintViolation<T>> validateResult = validator.validate(t,group);
return validateResult;
}
}
valiatorTest
#Slf4j
public class ValiatorTest {
#Test
public void vailator(){
User accountInfo = new User();
Set<ConstraintViolation<User>> constraintViolations = ValidatorUtil.validateOne(accountInfo);
Assertions.assertTrue(CollectionUtil.isNotEmpty(constraintViolations));
}
}
if you build project with maven ,add hibernate-validator dependency to pom
<properties>
<hibernate.validator.version>6.0.14.Final</hibernate.validator.version>
</properties>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>${hibernate.validator.version}</version>
</dependency>
if you want learn more , please accroding to this article Which #NotNull Java annotation should I use?!
So I'm trying to fix Fortify Vulnerability Issue for content-sniffing, and this needs to use StringEscapeUtils.escapeHtml4 for all attributes of the DTO.
My problem is that the DTO is not a simple object, but rather having nested objects as its attributes:
Root DTO:
public class ServiceOrderListDTO implements Serializable {
private String count;
private String next;
private String previous;
private List<ServiceOrderDetailDTO> results;
}
public class ServiceOrderDetailDTO implements Serializable {
private static final long serialVersionUID = -819641011600662396L;
#JsonProperty("order_code")
private String orderCode;
#JsonProperty("service_number")
private String serviceNumber;
#JsonProperty("customer_name")
private String customerName;
#JsonProperty("customer_brn")
private String customerBrn;
private CustomerDTO[] customer;
#JsonProperty("order_details")
private OrderDetailsDTO orderDetails;
#JsonProperty("site_a_address")
private String siteAAddress;
#JsonProperty("site_b_address")
private String siteBAddress;
#JsonProperty("dff_service_order_id")
private String dffServiceOrderID;
#JsonProperty("dff_response")
private DffResponse dffResponse;
private MilestonesDTO milestones;
private AppointmentsDTO appointments;
}
So I need to Iterate through all the child objects and apply the escapehtml4 function one by one.
However I got feedback that this may lead to performance issue. Is there a way that the escapeHtml4 be applied in the DTO as a whole?
I've been going through SO also but no viable solution so far.
Cross-Site Scripting/Content Sniffing vulnerability detected through static scan for API while returning response
What is the standard object design for accepting a POST request from a client, saving the record to the database, and then returning a response back to the client? I'm working with the Spring framework.
Should I be sending back the entity and hiding properties that aren't necessary for the response?
#RestController
public class SomeController {
private final SomeService service;
#PostMapping(value = "/post/new", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<SomeEntity> post(#RequestBody final SomeEntity someEntity) {
SomeEntity savedEntity = service.save(someEntity);
return ResponseEntity.ok(savedEntity);
}
}
#Entity
#Table(name = "posts")
public class SomeEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "title")
private String title;
#Column(name = "body")
#JsonIgnore
private String body;
#JsonIgnore
#Column(name = "deleted_ind")
private boolean deleted;
#JsonIgnore
#Column(name = "author")
private String author;
#Column(name = "created_at")
private LocalDateTime createdAt;
}
or would I accept some sort of POST request object that I convert to an entity, then re-assemble the entity into a response?
#JsonIgnoreProperties(ignoreUnknown = true)
public class SomePostRequestResource {
private String title;
private String body;
private String createdAt;
}
#RequiredArgsConstructor
#RestController
public class SomeController {
private final SomeService service;
private final SomeResourceAssembler resourceAssembler;
#PostMapping(value = "/post/new", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<SomePostRequestResource> post(
#RequestBody final SomePostRequestResource someResource
) {
SomeEntity savedEntity = service.convertToEntityAndSave(someResource);
SomePostRequestResource response = resourceAssembler.toResource(savedEntity);
return ResponseEntity.ok(response);
}
}
But then maybe I only want to send back the createdAt, would I hide the other properties in the SomePostRequestResource, or do I need another object to represent the response, which only has the property I want to send back?
I would also appreciate any book or article suggestions related to desigining objects for use with a RESTful API. I have seen articles concerning how to design and name the endpoints, but not so many concerning how to design the objects on the backend.
I would recommend you create a DTO class for the incoming/outgoing data containing the filed that are set/viewable by the client like:
public class SomeEntityIncomingDto {
private String title;
....
}
public class SomeEntityOutgoingDto {
private Long id;
private String title;
....
}
On the other hand, You won't need to map your persistence entities to DTOs and vice versa manually, you can use a library like ModelMapper or MapStruct that handles the conversion automatically.
I have a field called password which can be received by endpoint. But it cannot be sent back in response or persisted in Database
The class is as follows -
public class ShortURL {
#Pattern(regexp="^(https?|ftp|file)://[-a-zA-Z0-9+&##/%?=~_|!:,.;]*[-a-zA-Z0-9+&##/%=~_|]")
private String url;
#Size(min=8,max=16)
#Transient
private String password = null;
private boolean isPasswordProtected = false;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isPasswordProtected() {
return isPasswordProtected;
}
public void setPasswordProtected(boolean isPasswordProtected) {
this.isPasswordProtected = isPasswordProtected;
}
public ShortURL(
#Pattern(regexp = "^(https?|ftp|file)://[-a-zA-Z0-9+&##/%?=~_|!:,.;]*[-a-zA-Z0-9+&##/%=~_|]") String url,
#Size(min = 8, max = 16) String password, boolean isPasswordProtected) {
super();
this.url = url;
this.password = password;
this.isPasswordProtected = isPasswordProtected;
}
#Transient works properly. But adding the #JsonIgnore after #Transient causes problems -
Type definition error: [simple type, class java.lang.String];
nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException:
No fallback setter/field defined for creator property 'password'"
How do I achieve my intentions?
Depends on your Jackson version.
Before version 1.9, you could add #JsonIgnore to the getter of password and add #JsonProperty to the setter of the password field.
Recent versions of Jackson provide READ_ONLY and WRITE_ONLY annotation arguments for #JsonProperty, something like this:
#JsonProperty(access = Access.READ_ONLY)
private String password;
Yes you can use #JsonIgnore to let jackson ignore it during sending the user response but. There are certain best practices you should follow.
Never expose the Entities directly to the endpoint instead its better to have a wrapper i.e DTO that translates your entity to the required response.
For eg. in your case
public class ShortURL {
#Pattern(regexp="^(https?|ftp|file)://[-a-zA-Z0-9+&##/%?=~_|!:,.;]*[-a-zA-Z0-9+&##/%=~_|]")
private String url;
#Size(min=8,max=16)
private String password;
private boolean isPasswordProtected;
}
//here is the dto in which you can create a parameterised constructor and
accordingly invoke it based on the fields you want to set.
public class ShortURLDTO {
private String url;
public ShortURLDTO(String url){
this.url=url
}
}
I am using Chrome postman client for rest calls, here I am sending 15 form parameters like fname, last name.. so on, and also two files as file type.
I am submitting my request POST method, body type is form data selected and content type header is empty.
In the server side, I am consume this as method
#RequestMapping(value = "/create"
method = RequestMethod.POST,
consumes = {"multipart/form-data"},
produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public ResponseEntity<ResponseTO> create( #ModelAttribute RequestTO updateTripRequestTO, HttpServletRequest request);
public class RequestTO implements Serializable {
private UUID id private Date createdate;
private String createdby;
private String updatedby;
private Date updateddate;
private String visibility;
private String name;
private MultipartFile tripimage;
public class RequestTO implements Serializable {
private UUID id private Date createdate;
private String createdby;
private String updatedby;
private Date updateddate;
private String visibility;
private String name;
private MultipartFile tripimage;
( and Set and get Methods)
When I debug the TO, its giving comma separated values in TO.
If I give fname is "Test", lname "Ltest" in the postman, when I debug the TO its coming fname as "Test,Test" and lname as "Ltest,Ltest " for all form fields. Can some suggest me why like this and any solution please.