I need help. How can I trap the exception whenever the date field is left blank when a user forgot to input a birthDate. I used Validator interface to handle it. And I want Java to print on the browser when birthdate field is empty a message FootballPlayer birth date is required. What happens is that when the birthdate field is empty it prints out the Exception and the error message I created. It prints like this:
Failed to convert property value of type java.lang.String to required type java.util.Date for property birthDate; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [java.util.Date] for property birthDate: no matching editors or conversion strategy found
FootballPlayer birth date is required.
I only want to print FootballPlayer birth date is required.. How can I do this?
Im completely new to java and programming. Please help.
FootballPlayerValidator.java:
if (footballPlayer.getBirthDate() == null || footballPlayer.getBirthDate().equals(null)) {
try {
errors.rejectValue("birthDate", null, null, "FootballPlayer birth date is required.");
} catch (Exception ex) {
ex.printStackTrace();
}
}
FootballPlayerController.java:
#RequestMapping (value = "/add", method = RequestMethod.POST)
public String saveFootballPlayer (#ModelAttribute ("footballPlayer") FootballPlayer footballPlayer,
BindingResult result, Model model, HttpSession session) {
System.out.println("Saving footballPlayer");
footballPlayerValidator.validate(footballPlayer, result);
if (result.hasErrors())
return "addFootballPlayer";
saveFootballPlayer(footballPlayer);
return "successfullySaved";
}
In my setter and getter I declared birthdate as Date and also in my database.
FootballPlayer.java:
private Date birthDate;
public Date getBirthDate() {
return birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
try this :
#NotNull
public Date getBirthDate() {
return birthDate;
}
EDIT :
sorry I don't see that you don't use validation-api.
Since you are using java.util.Date for the date object you need to ask spring to convert the string value from the jsp to a Date object; here is a tutorial on how to do it
Later, you need to set the validation (which is what you are looking for); there is a sample for it here.
Related
I have a service defined as follows.
public String getData(#QueryParam("date") Date date)
I'm trying to pass a java.util.Date to it from my client (which is jaxrs:client of CXF, not a generic HTTP client or browser).
My service receives the date as Thu Mar 01 22:33:10 IST 2012 in the HTTP URL. Since CXF won't be able to create a Date object using this String, my client receives a 404 error.
I tried using a ParameterHandler on the service side, but I still can't parse it successfully because I'm not expecting the date in any specific format.
As per this post, passing a Date is supposed to work out of the box, but I can't seem to get the basic case working. Am I required to do anything in order to successfully pass a Date object from my client to service? Appreciate any help.
Thanks
The problem is that JAX-RS dictates that parameter unbundling be done in one of two ways:
The parameter bean has a public constructor that accepts a String
The parameter bean has a static valueOf(String) method.
In your case, the Date is being unbundled via its Date(String) constructor, which cannot handle the input format your client is sending. You have a couple options available to remedy this:
Option 1
Get your client to change the format of the date before they send it. This is the ideal, but probably the hardest to accomplish!
Option 2
Handle the crazy date format. The options for this are:
Change your method signature to accept a string. Attempt to construct a Date object out of that and if that fails, use your own custom SimpleDateFormat class to parse it.
static final DateFormat CRAZY_FORMAT = new SimpleDateFormat("");
public String getData(#QueryParam("date") String dateString) {
final Date date;
try {
date = new Date(dateString); // yes, I know this is a deprecated method
} catch(Exception e) {
date = CRAZY_FORMAT.parse(dateString);
}
}
Define your own parameter class that does the logic mentioned above. Give it a string constructor or static valueOf(String) method that invokes the logic. And an additional method to get the Date when all is said and done.
public class DateParameter implements Serializable {
public static DateParameter valueOf(String dateString) {
try {
date = new Date(dateString); // yes, I know this is a deprecated method
} catch(Exception e) {
date = CRAZY_FORMAT.parse(dateString);
}
}
private Date date;
// Constructor, Getters, Setters
}
public String getData(#QueryParam("date") DateParameter dateParam) {
final Date date = dateParam.getDate();
}
Or finally, you can register a parameter handler for dates. Where its logic is simply the same as mentioned for the other options above. Note that you need to be using at least CXF 2.5.3 in order to have your parameter handler evaluated before it tries the default unbundling logic.
public class DateHandler implements ParameterHandler<Date> {
public Map fromString(String s) {
final Date date;
try {
date = new Date(dateString); // yes, I know this is a deprecated method
} catch(Exception e) {
date = CRAZY_FORMAT.parse(dateString);
}
}
}
Percepiton's answer was very useful, but ParameterHandler has been deprecated in Apache-cxf 3.0, see the Apache-cxf 3.0 Migration Guide:
CXF JAX-RS ParameterHandler has been dropped, please use JAX-RS 2.0 ParamConverterProvider.
So I add an example with the ParamConverterProvider :
public class DateParameterConverterProvider implements ParamConverterProvider {
#Override
public <T> ParamConverter<T> getConverter(Class<T> type, Type type1, Annotation[] antns) {
if (Date.class.equals(type)) {
#SuppressWarnings("unchecked")
ParamConverter<T> paramConverter = (ParamConverter<T>) new DateParameterConverter();
return paramConverter;
}
return null;
}
}
public class DateParameterConverter implements ParamConverter<Date> {
public static final String format = "yyyy-MM-dd"; // set the format to whatever you need
#Override
public Date fromString(String string) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
try {
return simpleDateFormat.parse(string);
} catch (ParseException ex) {
throw new WebApplicationException(ex);
}
}
#Override
public String toString(Date t) {
return new SimpleDateFormat(format).format(t);
}
}
The #SuppressWarnings is required to suppress an "unchecked or unsafe operations" warning during compilation. See How do I address unchecked cast warnings for more details.
The ParamConverterProvider can be registred as provider. Here is how I did it:
<jaxrs:server id="myService" address="/rest">
<jaxrs:serviceBeans>
...
</jaxrs:serviceBeans>
<jaxrs:providers>
<ref bean="dateParameterConverterProvider" />
</jaxrs:providers>
</jaxrs:server>
<bean id="dateParameterConverterProvider" class="myPackage.DateParameterConverterProvider"/>
See Apache-cxf JAX-RS : Services Configuration for more information.
Using a custom DateParam class seems the safest option. You can then base your method signatures on that and implement the ugly conversion logic inside the valueOf() method or the class constructor. It is also more self-documenting than using plain strings
As #Perception suggests in option two, you can handle the date. But you should use following:
private Date getDateFromString(String dateString) {
try {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
Date date = df.parse(dateString);
return date;
} catch (ParseException e) {
//WebApplicationException ...("Date format should be yyyy-MM-dd'T'HH:mm:ss", Status.BAD_REQUEST);
}
}
You call it from within the resource as
Date date = getDateFromString(dateString);//dateString is query param.
I have to make a web service call and send many attributes while calling. One of the attribute is birthDate which is of type java.util.Date. I want birthDate to have value of this form "1960-10-25T00:00:00".
#GetMapping("/someSearch")
public PolicySearchResponseResource searchSomething(#RequestParam String firstName,
#RequestParam String lastName, #RequestParam Date birthDate) {
//call web service here and send birthDate in this form 1960-10-25T00:00:00...
}
When I send 1960-10-25T00:00:00 in request param, it is not recieving it and throwing error. Only this form "Oct 25 1960" is accepted. How to handle this?
Try this:
#RequestParam(value="paramName") #DateTimeFormat(pattern="MMddyyyy") Date paramName
So in your case it will be:
#GetMapping("/someSearch")
public PolicySearchResponseResource searchSomething(#RequestParam String firstName,
#RequestParam String lastName, #RequestParam(value="birthDate") #DateTimeFormat(pattern="yyyy-MM-dd'T'HH:mm:ss") Date birthDate) {
}
I am writing a Spring boot application linked to MySQL, in one of my packages:
com.Employee.DataManagement.salaries
I misspelled a property's name:
#Column(name = "from_date")
java.sql.Date fromeDate
As you can see, there is an extra "e" in the name. But I didn't realize it at that time and run the main java file(the one with annotation #SpringBootApplication) for a few times. Then I removed the extra "e" and the property becomes this:
#Column(name = "from_date")
java.sql.Date fromDate
Setter and Getter looks like this:
public Date getFromeDate() {
return fromDate;
}
public void setFromeDate(Date fromDate) {
this.fromDate = fromDate;
}
However, when I run the java file again, the old property name won't go away. The are some screenshot:
When I use GET and get the response, the from date in JSON always display as the previous name.
When I want to POST new data into the database, the example given by Swagger is like this:
But in the RequestBody I can ignore the misspell property and only use the correct one, write like this:
{
"embeddedKeyId": {
"employee": {
"emp_no": 123123
},
"fromDate": "2012-10-27",
},
"salary": 450,
"toDate": "2333-08-09"
}
But the output will still display as the old property name.
I searched through the project to see if I forgot to change some property name, but I got nothing.
Lastly, here is the screenshot of the salaries table in database
The answer is cited from varren's answer
Change setter and getter from:
public Date getFromeDate() {
return fromDate;
}
public void setFromeDate(Date fromDate) {
this.fromDate = fromDate;
}
To:
public Date getFromDate() {
return fromDate;
}
public void setFromDate(Date fromDate) {
this.fromDate = fromDate;
}
Without "e".
I have to get two dates in a request parameter lets say "from=jan 1 2016" and "to= feb 1 2016". "from" should always come before "to".
My controller methods return Map in response if "from" is before "to", but if "to=jan 1 2016" value comes before "from=feb 1 2016", how do I handle the response to send a message?
The proper way would be to throw an exception if anything happens that shouldn't happen. If you're using Java 8 time API (or something like Joda time), you can easily achieve this by using isBefore():
if (to.isBefore(from)) {
// Write your own exception class
throw new InvalidParameterException("To cannot be before from");
}
Now you can use #ExceptionHandler to do anything you want if an exception is thrown. For example:
#ExceptionHandler(InvalidParameterException.class)
#ResponseBody
#ResponseStatus(value = HttpStatus.BAD_REQUEST)
public ErrorMessageDTO handleInvalidParameter(InvalidParameterException ex) {
// Write your own DTO to return an exception
return new ErrorMessageDTO(ex.getMessage());
}
If you want to use dates as request parameters, you might want to use a Formatter<LocalDate> to properly do this:
#Component
public class LocalDateStringFormatter implements Formatter<LocalDate> {
// Or use a custom formatter with a custom pattern
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE;
#Override
public LocalDate parse(String isoDateString, Locale locale) throws ParseException {
return LocalDate.parse(text, FORMATTER);
}
#Override
public String print(LocalDate date, Locale locale) {
retun date.format(FORMATTER);
}
}
This way you can map #RequestParams of type LocalDate.
I have problem on processing input request parameter (of course it's type String) to java.util.Date. I thought that following code added to my bean might solve this problem, but I was wrong:
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public void setDate(String dateString) {
try {
date = DateFormat.getDateInstance().parse(dateString);
} catch (ParseException e) {
date = new Date();
}
}
It throws an exception after submiting form:
javax.servlet.ServletException: BeanUtils.populate
org.apache.struts.util.RequestUtils.populate(RequestUtils.java:469)
org.apache.struts.action.RequestProcessor.processPopulate(RequestProcessor.java:818)
java.lang.IllegalArgumentException: Cannot invoke com.epam.testapp.model.News.setDate - argument type mismatch
org.apache.commons.beanutils.PropertyUtilsBean.invokeMethod(PropertyUtilsBean.java:1778)
org.apache.commons.beanutils.PropertyUtilsBean.setSimpleProperty(PropertyUtilsBean.java:1759)
org.apache.commons.beanutils.PropertyUtilsBean.setNestedProperty(PropertyUtilsBean.java:1648)
org.apache.commons.beanutils.PropertyUtilsBean.setProperty(PropertyUtilsBean.java:1677)
Is this fundamental of struts 1 form that this code won't work because of mismatch of returning getter and accepting setter parameter types? How can I solve this problem ? I don't want at all to make method named like setStringDate(String stringDate(){...} and think on every page which method should I call :(
Date object cannot be a property in struts as date format can vary (depending on specification). Some may have dd-MM-yyyy, dd-MMMM-yy, etc.
I would suggest having a property:
private String date;
public String getDate() { return date; }
public void setDate(String date) { this.date = date; }
And in your action, convert the date string into Date object.
As per my knowledge I think , overloaded methods don't work very well in form beans .Try naming the two methods differently, and I think you'll have better luck.