Spring mvc error while binding date param - json

I'm having a weird problem with a Spring MVC.
I have a Controller method that accepts 2 date parameters as request parameters startDate and endDate.
If I use a simple url with the 2 params like so :
http://localhost/myapp/videos?startDate=2013-05-10&endDate=2013-06-01.json
I get this error message :
[#|2013-05-27T17:39:01.711+0200|INFO|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=24;_ThreadName=Thread-2;|38386 [http-thread-pool-8080(5)] DEBUG org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver - Resolving exception from handler [public java.util.List<Video> com.ufasoli.Videos.programs(com.ufasoli.filtering.SearchParams)]: org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'searchParams' on field 'endDate': rejected value [2013-06-01.json]; codes [typeMismatch.searchParams.endDate,typeMismatch.endDate,typeMismatch.java.util.Date,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [searchParams.endDate,endDate]; arguments []; default message [endDate]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'endDate'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type java.lang.String to type #org.springframework.format.annotation.DateTimeFormat java.util.Date for value '2013-06-01.json'; nested exception is java.lang.IllegalArgumentException: Invalid format: "2013-06-01.json" is malformed at ".json"]
|#]
But as soon as I remove the .json like so :
http://localhost/myapp/videos?startDate=2013-05-10&endDate=2013-06-01
it all works fine...
This looks like a bug to me as the databinder should not take the url extension into account when binding the data to the controller or is this normal behavior?
Below is the controller method causing the problem :
#RequestMapping(value = "/videos/",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
public List<Videos> videos( SearchParams searchParams) {
return videosRepository.videos(searchParams);
}
Here is my SearchParams class :
public class SearchParams extends BaseSearchParams implements Serializable{
private static final long serialVersionUID = 1L;
#DateTimeFormat(iso = ISO.DATE, pattern = "yyyy-MM-dd")
private Date startDate;
#DateTimeFormat(iso = ISO.DATE, pattern = "yyyy-MM-dd")
private Date endDate;
//Setters/Getters
}
I'm using Spring MVC 3.2.1.RELEASE
Any insight?
Thanks in advance

I think that the 'url extension' (if any) should be part of the path and belongs therefore before the query: http://localhost/myapp/videos.json?startDate=2013-05-10&endDate=2013-06-01.

Related

LocalDateTime of type format problem in thymeleaf

I'm studying JavaWeb now,but not enough experience to solve the problem.
I use MySql 8.0+, "mysql-connector-java" version by maven impot is 8.0.12,JDBC connect MySql Driver use "com.mysql.cj.jdbc.Driver";DataBase table date time field type is " datetime",the field can be read successful by invoked set in JavaBean attribute "orderDate",then let attribute "orderDate" through 'HttpSession session' to set in session.
When JavaBean attribute type is " java.sql.Timestamp ", from session read variable values,the thymeleaf format work is fine;
There is the source code:
<td th:text="${#dates.format(orderBean.getOrderDate(),'yyyy-MM-dd HH:mm:ss')}"></td>
But when JavaBean attribute type is " java.time.LocalDateTime ",the "orderBean.java" part source code:
public class OrderBean {
....
private LocalDateTime orderDate;
.....
public LocalDateTime getOrderDate() {
return orderDate;
}
public void setOrderDate(LocalDateTime orderDate) {
this.orderDate = orderDate;
}
}
There is a method to set orderBean to HttpSeesion part source code:
public String checkout(HttpSession session){
........
OrderBean orderBean = new OrderBean();
LocalDateTime localDateTime = LocalDateTime.now();
orderBean.setOrderDate(localDateTime);
session.setAttribute("orderBean",orderBean);
........
return "cart/cart";
}
There is the cart.html source code:
<td th:text="${#temporals.format(orderBean.getOrderDate(),'yyyy-MM-dd HH:mm:ss')}"></td>
from session read variable values,the thymeleaf format not in effect,throw the erro:
org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating OGNL expression: "#temporals.format(orderBean.getOrderDate(),'yyyy-MM-dd HH:mm:ss')" (template: "order/order" - line 48, col 19)
at org.thymeleaf.standard.expression.OGNLVariableExpressionEvaluator.evaluate(OGNLVariableExpressionEvaluator.java:191)
at org.thymeleaf.standard.expression.OGNLVariableExpressionEvaluator.evaluate(OGNLVariableExpressionEvaluator.java:95)
at org.thymeleaf.standard.expression.VariableExpression.executeVariableExpression(VariableExpression.java:166)
at org.thymeleaf.standard.expression.SimpleExpression.executeSimple(SimpleExpression.java:66)
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:109)
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:138)
at org.thymeleaf.standard.processor.AbstractStandardExpressionAttributeTagProcessor.doProcess(AbstractStandardExpressionAttributeTagProcessor.java:144)
at org.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess(AbstractAttributeTagProcessor.java:74)
at org.thymeleaf.processor.element.AbstractElementTagProcessor.process(AbstractElementTagProcessor.java:95)
at org.thymeleaf.util.ProcessorConfigurationUtils$ElementTagProcessorWrapper.process(ProcessorConfigurationUtils.java:633)
at org.thymeleaf.engine.ProcessorTemplateHandler.handleOpenElement(ProcessorTemplateHandler.java:1314)
at org.thymeleaf.engine.OpenElementTag.beHandled(OpenElementTag.java:205)
at org.thymeleaf.engine.Model.process(Model.java:282)
at org.thymeleaf.engine.Model.process(Model.java:290)
at org.thymeleaf.engine.IteratedGatheringModelProcessable.processIterationModel(IteratedGatheringModelProcessable.java:367)
at org.thymeleaf.engine.IteratedGatheringModelProcessable.process(IteratedGatheringModelProcessable.java:221)
at org.thymeleaf.engine.ProcessorTemplateHandler.handleCloseElement(ProcessorTemplateHandler.java:1640)
at org.thymeleaf.engine.CloseElementTag.beHandled(CloseElementTag.java:139)
at org.thymeleaf.engine.TemplateModel.process(TemplateModel.java:136)
I try to solve it ,but i search in google,they write code like the same that.But the different is that they use SpringMVC, through "model.setAttribute()" method ,
model.addAttribute("localDate", LocalDate.now());
then through thymeleaf expression:
<p th:text="${#temporals.format(localDateTime, 'dd-MM-yyyy HH:mm')}"></p>
In addition,i also import dependency in maven artifactId "thymeleaf-extras-java8time ";
I just use javax-Servlet-api ,without spring,springMVC stc...,I'm devastated that I don't know how to solve it.
I hope someone can help me....

LocalDate serialization does not work with spring boot - (#jsonformat dos not work )

I am trying to parse JSON as local date, I tried multiple options including #jsonFormat but I am still getting the below exception - (I am using spring boot rest controller for accepting this request)
public class Student {
private long rollNumber;
private String firstName;
private String lastName;
#JsonDeserialize(using = LocalDateDeserializer.class)
#JsonSerialize(using = LocalDateSerializer.class)
#JsonFormat(shape=JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy")
private LocalDate dob;
private Gender gender;
private Grade grade;
}
json :
[{
"rollNumber":"1",
"firstName":"abc",
"lastName":"ere",
"dob":"08-06-1993",
"gender":"MALE",
"grade":"TENTH"
}]
org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.time.LocalDate` from String \"08-06-1993\": Failed to deserialize java.time.LocalDate: (java.time.format.DateTimeParseException) Text '08-06-1993' could not be parsed at index 0; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.time.LocalDate` from String \"08-06-1993\": Failed to deserialize java.time.LocalDate: (java.time.format.DateTimeParseException) Text '08-06-1993' could not be parsed at index 0\n at [Source: (PushbackInputStream); line: 5, column: 7] (through reference chain: java.util.ArrayList[0]->com.example.application.restApp.model.Student[\"dob\"])\r\n\tat org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:389)\r\n\tat org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:342)\r\n\tat org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:185)\r\n\tat
JSON can not deserialize the time from string. Change date type and format as below.
#JsonFormat
(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss")
public Date dob;
I figured out the issue, seems like when we don't have a no args constructor even having #jsonFormat does not seem to work. I was using Lombok and I missed adding a no args constructor , after adding that the issue resolved.
Thanks everyone for the help.
Interestingly spring boot does not throw error stating no args constructor is not present and tries to do the default implementation.

Can not convert JSON to domain object with spring restTemplate

Actually I try to invoke a get request with the restTemplate in Spring. Debbuging my application clearly shows that the JSON is downloaded but the automatic mapping does not work. My List of domain object includes only 0 values and null values.
When I invoke the get request from the browser, I get the following response as JSON (I copied here the first two record out of the 3 192):
[{"OrderId":77862,"DateAdded":"2016-04-30T02:25:40.263","OrderItemCorpusId":"HUBW","OrderItemCorpusOriginalId":null,"OrderItemCurrency":"HUF","OrderItemExchangeRate":1.00000,"OrderItemOriginalLocation":"HU","OrderItemBuyLocation":"HU","OrderItemPrice":1337.80314,"OrderItemDiscountId":0,"OrderItemDiscountValue":"","DocumentId":25140,"Title":"Romana Gold 10. kötet","PublisherOriginalName":"Harlequin Kiadó","ISBN":"9789634073369"},{"OrderId":77864,"DateAdded":"2016-04-30T15:49:22.61","OrderItemCorpusId":"HUBW","OrderItemCorpusOriginalId":null,"OrderItemCurrency":"HUF","OrderItemExchangeRate":1.00000,"OrderItemOriginalLocation":"HU","OrderItemBuyLocation":"HU","OrderItemPrice":2748.03149,"OrderItemDiscountId":0,"OrderItemDiscountValue":"","DocumentId":25252,"Title":"Az eltűnt lány","PublisherOriginalName":"Harlequin Kiadó","ISBN":"9789634072423"}]
My POJO domain object which should keep the converted data from JSON:
#JsonIgnoreProperties(ignoreUnknown = true)
public class BandWTransaction {
private long OrderId;
private Date DateAdded;
private String OrderItemCurrency;
private double OrderItemExchangeRate;
private String OrderItemBuyLocation;
private double OrderItemPrice;
private String OrderItemDiscountValue;
private long DocumentId;
private String Title;
private String PublisherOriginalName;
private String ISBN;
//getters and setters
Finally the code snippet I use for the rest get request:
String startDate = new SimpleDateFormat("yyyy-MM-dd").format(start.getTime());
String endDate = new SimpleDateFormat("yyyy-MM-dd").format(end.getTime());
UriComponents uri = UriComponentsBuilder.newInstance().scheme("http").host("www.bookandwalk.hu")
.path("/api/AdminTransactionList").queryParam("password", "XXX")
.queryParam("begindate", startDate).queryParam("enddate", endDate).queryParam("corpusid", "HUBW")
.build().encode();
LOG.log(Level.INFO, "{0} were called as a rest call", uri.toString());
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.set("User-Agent", "Anything");
HttpEntity<String> entity = new HttpEntity<String>(headers);
ResponseEntity<List<BandWTransaction>> transResponse = restTemplate.exchange(uri.toString(), HttpMethod.GET,
entity, new ParameterizedTypeReference<List<BandWTransaction>>() {
});
List<BandWTransaction> transactions = transResponse.getBody();
When I debug the app I realized that the transactions list includes objects with full of null and 0 values. More precisely, there is no and objcet within the list having other values as 0 and null in the properties.
I have also checked that spring boot automatically registered in the restTemplate.messageConverters ArrayList 9 HttpMessageConverter. The 7th element of this ArrayList is the org.springframework.http.converter.json.MappingJackson2HttpMessageConverter which supports the application/json and application/+json media types.
Any idea is appreciated to solve this problem as I am newbie in spring and in JSON mapping in general.
It seems you have a naming convention issue due to your field variables starts with a uppercase. When Jackson finds a pair getTitle/setTitleasumes that the name of this variable is title (starting with lowercase). Of course, if you change the capitalization of your variables, json properties and java variables has different names, so mapping still fails. The best solution is change your names to meet Java conventions, and use Jackson annotations to define your mappings.
#JsonProperty(value="OrderId")
private int orderId;
#JsonProperty(value="DateAdded")
private Date dateAdded;
Hope it helps.
I can suggest you to write a test and check how fasterxml ObjectMapper read a json and unmarshall json to your object:
ObjectMapper objectMapper = new ObjectMapper();
String somestring = objectMapper.readValue("somestring", String.class);
just replace String with your class and "somestring" with your json. So you check if there is problem with it.
And try to use #JsonPropery cause all this capital letters fields start with looks messy:
#JsonIgnoreProperties(ignoreUnknown = true)
public class BandWTransaction {
#JsonProperty("OrderId")
private long OrderId;
[...]
With this stuff I read json correct. You can come in from other side remove ignoring unknown properties:
#JsonIgnoreProperties(ignoreUnknown = true) //remove it and run test
public class BandWTransaction {
and you get :
(11 known properties: "dateAdded", "orderItemExchangeRate",
"documentId", "orderItemPrice", "orderId", "orderItemBuyLocation",
"orderItemDiscountValue", "orderItemCurrency", "isbn", "title",
"publisherOriginalName"])
So problem in variables naming and you can fix it with #JsonProperty

How to use Spring Data CouchBase 'findAll(Iterable<ID>)' Method?

I'm trying to use Spring-Data-Couchbase.
I want to get List from findAll(Iterable) method.
I set view 'all' to my Production View.
But, I meet the exception.
How Can I use findAll(Iterable) method?
Below is a Sample Code and exception.
Document Class:
#Document
public class User {
#Id
private String id;
private String userSeq;
}
Repository Class :
public interface UserRepository extends CouchbaseRepository<User, String> {
}
Service Class:
//List<String> get the Same result & exception.
Set<String> friendSet = new HashSet<String>();
friendSet.add("User8");
friendSet.add("User6");
userRepository.findAll(friendSet)
Exception:
Caused by: java.util.concurrent.ExecutionException: OperationException: SERVER: bad_request Reason: invalid UTF-8 JSON: {{error,{2,"lexical error: invalid char in json text.\n"}},
"[User8, User6]"}
at com.couchbase.client.internal.HttpFuture.waitForAndCheckOperation(HttpFuture.java:98)
at com.couchbase.client.internal.HttpFuture.get(HttpFuture.java:82)
at com.couchbase.client.internal.HttpFuture.get(HttpFuture.java:72)
at com.couchbase.client.CouchbaseClient.query(CouchbaseClient.java:778)
... 66 more
Caused by: OperationException: SERVER: bad_request Reason: invalid UTF-8 JSON: {{error,{2,"lexical error: invalid char in json text.\n"}},
"[User8, User6]"}
at com.couchbase.client.protocol.views.NoDocsOperationImpl.parseError(NoDocsOperationImpl.java:110)
at com.couchbase.client.protocol.views.ViewOperationImpl.handleResponse(ViewOperationImpl.java:68)
at com.couchbase.client.http.HttpResponseCallback.completed(HttpResponseCallback.java:103)
at com.couchbase.client.http.HttpResponseCallback.completed(HttpResponseCallback.java:51)
at org.apache.http.concurrent.BasicFuture.completed(BasicFuture.java:115)
at org.apache.http.nio.protocol.HttpAsyncRequester$RequestExecutionCallback.completed(HttpAsyncRequester.java:376)
at org.apache.http.concurrent.BasicFuture.completed(BasicFuture.java:115)
at org.apache.http.nio.protocol.BasicAsyncClientExchangeHandler.responseCompleted(BasicAsyncClientExchangeHandler.java:179)
at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.processResponse(HttpAsyncRequestExecutor.java:349)
at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.inputReady(HttpAsyncRequestExecutor.java:236)
at org.apache.http.impl.nio.DefaultNHttpClientConnection.consumeInput(DefaultNHttpClientConnection.java:267)
at org.apache.http.impl.nio.DefaultHttpClientIODispatch.onInputReady(DefaultHttpClientIODispatch.java:165)
at org.apache.http.impl.nio.DefaultHttpClientIODispatch.onInputReady(DefaultHttpClientIODispatch.java:51)
at org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:113)
at org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:159)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:338)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:316)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:277)
at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:105)
at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:584)
... 1 more
You have to quote the id:s before you call findAll(...).
Set<String> friendSet = new HashSet<String>();
friendSet.add("\"User8\"");
friendSet.add("\"User6\"");
If the id:s aren't quoted the keys parameter sent to the Couchbase server will look something like [User8, User6] which isn't valid JSON, hence the exception. Pretty surprising behaviour...

asp web api json serialization returns private properties

I have a Web api controller class
and i call a method on a proxy class generated from a WSDL from the web api controller,
and i return an object of type defined in the WSDL proxy class.
but the xml/json returned contains the private members of the proxy class
the private members are
private string companyField;
private string soldBPField;
private string fromDateField;
private string toDateField;
private long succStatusField;
and the xml returned is :
<companyField>700</companyField>
<soldBPField>999000353</soldBPField>
<fromDateField>01-01-2012</fromDateField>
<toDateField>01-01-2013</toDateField>
the json returned is also similar
I changed the xml formatter in the global.asax as follows:
var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
xml.UseXmlSerializer = true;
this changed the XML returned to:
<company>700</company>
<soldBP>999000353</soldBP>
<fromDateField>01-01-2012</fromDate>
<toDate>01-01-2013</toDate>
but the json returned still contains the name of the private variables
can any one help me with this
Are your types marked as [Serializable]? Serializable means that the serializer should serialize all fields - private or public. Try to remove Serializable or else use this line to stop the JSON formatter from recognizing the attribute:
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new DefaultContractResolver();