jsr 303 validated all fields in object - json

suppose i hava two view files(jsps) and one class(BudgetControlRegisterDto)
BudgetControlRegisterDto
public class BudgetControlRegisterDto implements Serializable {
#NotNull(message = "{NotNull.java.util.Date}")
private Date demandReceiveDate;
#NotNull(message = "{NotNull.java.util.Date}")
private Date demandOriginalDate;
#NotNull(message = "Start date {NotNull.java.util.Date}")
private Date startDate;
#NotNull(message = "End date {NotNull.java.util.Date}")
private Date endDate;
// setter and getter
}
In one view file i want to validate startDate and endDate
and in other view file i want to validate demandOriginalDate and demandReceiveDate using json ajax. when validation occurs i get validation message for all fields with below code:
controller class's method this is testing code used by both view files(jsps)
#RequestMapping(value = "/addnewdemand.json", method = RequestMethod.POST)
public #ResponseBody BudgetControlRegisterDto addNewDemand(#Valid #ModelAttribute("bcrDto") BudgetControlRegisterDto bcrDto,Errors errors){
log.info("addNewDemand invoked!");
if(errors.hasErrors()) {
log.info("has errors");
bcrDto.setFieldsErrors(errors.getFieldErrors());
return bcrDto;
}
return bcrDto;
}
.js file this is testing code used by both view files(jsps) below code is ajax response code
if(response.fieldsErrors != null) {
html ='<div class="ui-message-error">';
for(var i= 0; i<response.fieldsErrors.length; i++) {
html+='<span>'+response.fieldsErrors[i].defaultMessage+'</span><br/>';
}
html+='</div>';
$("#bcrForm_message").html(html);
}
Question why m i getting validation message of all fields

this is the situation where groups takes place. Here is a good tutorial about them.
The first thing you need to change is to add groups attribute to your #NotNull annotations.
public class BudgetControlRegisterDto implements Serializable {
#NotNull(message = "{NotNull.java.util.Date}",groups={First.class})
private Date demandReceiveDate;
#NotNull(message = "{NotNull.java.util.Date}",groups={First.class})
private Date demandOriginalDate;
#NotNull(message = "Start date {NotNull.java.util.Date}",groups={Second.class})
private Date startDate;
#NotNull(message = "End date {NotNull.java.util.Date}",groups={Second.class})
private Date endDate;
public interface First {};
public interface Second {};
// setter and getter
}
the second one is to change from #Valid to #Validated because #Valid doesn't support validation groups.
controller's method:
#RequestMapping(value = "/addnewdemand.json", method = RequestMethod.POST)
public #ResponseBody BudgetControlRegisterDto addNewDemand(#Validated(BudgetControlRegisterDto.First.class) #ModelAttribute("bcrDto") BudgetControlRegisterDto bcrDto,Errors errors){
log.info("addNewDemand invoked!");
if(errors.hasErrors()) {
log.info("has errors");
bcrDto.setFieldsErrors(errors.getFieldErrors());
return bcrDto;
}
return bcrDto;
}

Related

Hibernate saveOrUpdate session not working

I am new to hibernate and was working on a project where I want to update the expiry date of membership when someone buys the membership. i have written a class implementing the AtributeConverter.
Upon calling the buyMembership method, both print methods are printing the correct date but database is not getting updated. In console, it shows that only select query is running. The update query is being executed. Refer code for referrence
USER_LOGIN Class
#Entity
#Table(name = "login")
public class User_Login {
#Id
#Column(name = "username")
private String username;
#Column(name = "password")
private String password;
#Column(name = "enabled")
private Boolean enabled = false;
#Column(name="start_date")
private LocalDate startDate;
#Column(name="end_date")
private LocalDate expiryDate;
Repository
public void buyMembership(String months,String email) {
Session currentSession = manager.unwrap(Session.class);
User_Login user = currentSession.get(User_Login.class, email);
LocalDate date = user.getExpiryDate();
LocalDate current = LocalDate.now();
if(date.compareTo(current)<0) {
user.setStartDate(current);
LocalDate newExpiryDate = current.plusMonths(Long.parseLong(months));
System.out.println(newExpiryDate);
user.setExpiryDate(newExpiryDate);
user.setStartDate(current);
//currentSession.saveOrUpdate(user);
}
else {
LocalDate newExpiryDate = date.plusMonths(Long.parseLong(months));
System.out.println(newExpiryDate);
user.setExpiryDate(newExpiryDate);
user.setStartDate(current);
System.out.println(user.getExpiryDate());
//currentSession.saveOrUpdate(user);
}
currentSession.update(user);
}
Attribute Converter*
#Converter(autoApply = true)
public class LocalDatePersistenceConverter implements
AttributeConverter<LocalDate, Date> {
#Override
public Date convertToDatabaseColumn(LocalDate attribute) {
if(attribute==null)
return null;
return java.sql.Date.valueOf(attribute);
}
#Override
public LocalDate convertToEntityAttribute(java.sql.Date dbData) {
if(dbData==null)
return null;
return dbData.toLocalDate();
}
}
Actually, it was a silly error. I had just missed marking my buyMembership service as transactional. After that,It worked like a charm...

How to GET data in the JSON format form the DB Repository

I have this JPA Class, where I have 3 columns id, name and date. The Database is already filled with data, where each entry has an id.
#Data
#Entity
#Table(name = "TEST", schema = "TESTSCHEMA")
public class TestDataJpaRecord implements Serializable {
private static final long serialVersionUID = 1L;
TestDataJpaRecord(){
// default constructor
}
public TestDataJpaRecord(
String name,
Date date,
){
this.name = name;
this.date = date;
}
#Id
#Column(name = "ID", nullable = false)
#GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "TEST_SEQUENCE")
#SequenceGenerator(
sequenceName = "TEST_SEQUENCE", allocationSize = 1,
name = "TEST_SEQUENCEx")
private Long id;
#Column(name = "NAME")
private String name;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "DATE")
private Date date;
}
I created a JPA repository for all the data.
public interface TestDataJpaRecordRepository extends JpaRepository<TestDataJpaRecord, Long> {
}
I want to get the data from the DB in a JSON format.
Here is my Rest GET Api. Here I return the data as a string just, but I want to return them as JSON.
#GetMapping(value = "data/{id}")
private ResponseEntity<?> getDataFromTheDB(#PathVariable("id") Long id) {
// get one entry form the DB
TestDataJpaRecord testDataJpaRecord =testDataJpaRecordRepository.findOne(id);
// Here I want to return a JSON instead of a String
return new ResponseEntity<>(testDataJpaRecord.toString(), HttpStatus.OK);
}
Any idea on how I could return the data as JSON and not as a string from the DB?
I would very very much appreciate any suggestion.
If you have Jackson on the classpath which you should if you have used the spring-boot-starter-web then simply:
#GetMapping(value = "data/{id}")
private ResponseEntity<TestDataJpaRecord> getDataFromTheDB(#PathVariable("id") Long id) {
TestDataJpaRecord testDataJpaRecord =testDataJpaRecordRepository.findOne(id);
return new ResponseEntity.ok(testDataJpaRecord);
}
This assumes you have annoted your controller with #RestController rather than #Controller. If not then you can either do that or, annotate your controller method with #ResponseBody.
With Spring Data's web support enabled (which it should be by default with Spring Boot) then you can also simplify as below:
#GetMapping(value = "data/{id}")
private ResponseEntity<TestDataJpaRecord>
getDataFromTheDB(#PathVariable("id") TestDataJpaRecord record) {
return new ResponseEntity.ok(record);
}
See:
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#core.web.basic.domain-class-converter

how to pass date yyyy-mm-dd in spring boot controller request body when default timestamp format set to something else

I have configured my application by setting default timestamp format as yyyy-MM-dd HH:mm:ss z
#Configuration
#EnableWebMvc
public class KukunWebMvcConfigurerAdapter extends WebMvcConfigurerAdapter {
public MappingJackson2HttpMessageConverter jacksonJsonMessageConverter() {
MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper mapper = new ObjectMapper();
// Registering Hibernate5Module to support lazy objects
mapper.registerModule(new Hibernate5Module());
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"));
messageConverter.setObjectMapper(mapper);
return messageConverter;
}
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(jacksonJsonMessageConverter());
super.configureMessageConverters(converters);
}
}
But I am able to pass date field from request body, its giving 400 Bad Request.
Process Entity field:
#Entity
#Table(name = "process")
public class Process{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "process_id")
private Long processId;
#Column(name = "process_name")
#NotNull
private String processname;
#Column(name = "process_date")
#Temporal(TemporalType.DATE)
#DateTimeFormat(pattern = "yyyy-MM-dd")
private Date processDate;
//other fields and setter&getter methods
}
controller method:
#PostMapping
public ResponseEntity<Response> createProcess(
#RequestBody Process process) throws GenericException {
}
request body:
{
"processDate":"2019-03-30"
}
How can I pass date value via request body when default timestamp set via configuration ?
let’s take a look at the #JsonFormat annotation to control the
date format on individual classes instead of globally, for the entire
application:
public class Event {
public String name;
#JsonFormat
(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss")
public Date eventDate;
}

When deserializing List of objects, JSON looks for a unexistent class [duplicate]

This question already has answers here:
Status 400 and Error deserializing List of Objects. No default constructor found
(2 answers)
Closed 4 years ago.
Using Spring I created a microservice that finds all messages in DB for a specific user.
Controller:
#RestController
public class Controller {
#Autowired
private MessageRepository daoMsg;
#RequestMapping(value = "/Mensajes", method = RequestMethod.GET, produces=MediaType.APPLICATION_JSON_VALUE)
public List<MessageObject> enviados (#RequestParam("mail") String mail) {
return daoMsg.findByEmisorOrDestinatario(mail, mail);
}
}
DAO:
public class MessageObject implements Serializable{
private static final long serialVersionUID = 1L;
#Id
private String id;
private String emisor;
private String destinatario;
private String mensaje;
private String tipo;
private LocalDate fecha;
private String id_housing;
public MessageObject() {
}
public MessageObject(String id, String emisor, String destinatario, String tipo, LocalDate fecha, String id_housing) {
this.id = id;
this.emisor = emisor;
this.destinatario = destinatario;
this.tipo = tipo;
this.fecha = fecha;
this.id_housing = id_housing;
}
When calling the microservice from my client app:
Client client = ClientBuilder.newClient();
WebTarget webResource =
client.target("http://localhost:8082").path("Mensajes").queryParam(mail);
Invocation.Builder invocationBuilder =
webResource.request(MediaType.APPLICATION_JSON);
Response respuesta = invocationBuilder.get();
int status = respuesta.getStatus();
System.out.println("el status es "+ status);
MessageObject[] listMessages =
respuesta.readEntity(MessageObject[].class);
stacktrace:
javax.ws.rs.ProcessingException: Error deserializing object from entity
stream.Caused by: javax.json.bind.JsonbException: Can't create instance of
a class: class [LMessages.MessageObject;, No default constructor
found.Caused by: java.lang.NoSuchMethodException:
[LMessages.MessageObject;.<init>()
My client has the same MessageObject DAO as the one in the microservice, in:
Question: why JSON is looking for a default constructor in LMessages.MessageObject if my MessageObject class is in package Messages (not LMessages)
Solved. Problem was i was using .queryparam(mail) without key - value structure, only key. Now using .queryparam ("mail", mail) works.

Element in JSON of type date is being sent as timestamp instead of date

I am converting the json received from database to object User.class using Objectmapper,class structure as follows
#XmlRootElement
public class User {
public User() {
super();
}
#XmlElement
private String username=null;
#XmlElement
private Feedbacks feedbacks=null;
//getter setter....
}
User has an instance of Feedbacks class which in turn has Arraylist< Feedback>
#XmlRootElement
public class Feedbacks {
public Feedbacks() {
}
#XmlElement
private ArrayList<Feedback> FeedbackList=new ArrayList<>();
public ArrayList<Feedback> getFeedbackList() {
return FeedbackList;
}
public void setFeedbackList(ArrayList<Feedback> FeedbackList) {
this.FeedbackList = FeedbackList;
}
}
and
public class Feedback {
private String feedback=null;
//private String timeStamp=null;
/*#JsonDeserialize(using = DateDeserializer.class); */
#JsonFormat(pattern = "MM/dd/yyyy HH:mm")
private Date feedbackDate;
public Feedback (){}
}
Sample json that i retrieve from db is:
{
"userName":"Test",
"feedbacks":{
"feedbackTOList":[
{
"feedback":"Please select appropriate value..1",
"timeStamp":"03/01/2000 14:52"
},
{
"feedback":"Please select appropriate value..2",
"timeStamp":"03/01/2018 13:50"
},
{
"feedback":"Please select appropriate value..3",
"timeStamp":"02/01/2018 10:52"
}
]
}
}
Json to object conversion and sorting the list of feedback based on date:
SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy HH:mm");
mapper = new ObjectMapper();
mapper.setDateFormat(formatter);
userObject= mapper.readValue(jsonPayload, User.class);
Collections.sort(user.getFeedbacks().getFeedbackList(), new
Comparator<Feedback>() {
public int compare(Feedback f1, Feedback f2) {
if (f1.getTimeStamp() == null || f2.getTimeStamp() == null)
return 0;
return (f2.getTimeStamp().compareTo(f1.getTimeStamp()));
}
});
The issue is when angular UI consumes the object from rest service,instead of Date (Wed Aug 01 16:20:00 EDT 2018]) the timestamp value is being sent as timeStamp=1533154800000.
My question is how do i send the string in given format or atleast date object but not timestamp?
So far i tried #JsonFormat(pattern = "MM/dd/yyyy HH:mm"),custom date deserializer but no luck(by referring many other posts on stackoverflow,sites),can some one please let me know what mistake am i making?