Convert JSON to JAVA Object through play.data.Form - java

I have no idea what to do with this problem.
I have a JSON object to assist in value input through POST (using Play Framework) that structures like this:
{
"start_absolute": 1403185486254,
"end_absolute": 1403185486254,
"metrics": [
{
"name": "parts",
"tags": [
{
"key":"machine",
"value":"10"
}
],
"sampling":
{
"value": 1,
"unit": "minutes"
}
}
]
}
And in server side i try to process the info like this:
Form<QueryForm> queryForm = Form.form(QueryForm.class).bindFromRequest();
if (queryForm.hasErrors()) {
return badRequest(queryForm.errorsAsJson());
}
QueryForm queryInfo = queryForm.get();
the classes used to define the JSON object in java
public class QueryForm {
private Date start_absolute;
private Date end_absolute;
private List<MetricForm> metrics= Lists.newArrayList();
public Date getStart_absolute() {
return start_absolute;
}
public void setStart_absolute(long start_absolute) {
this.start_absolute = new Date(start_absolute);
}
public Date getEnd_absolute() {
return end_absolute;
}
public void setEnd_absolute(long end_absolute) {
this.end_absolute =new Date(end_absolute);
}
public List<MetricForm> getMetrics() {
return metrics;
}
public void setMetrics(List<MetricForm> metrics) {
this.metrics = metrics;
}
#Override
public String toString() {
return "QueryForm[start_absolute="+start_absolute+", end_absolute="+end_absolute+", metrics="+metrics+"]";
}
.
public class MetricForm {
private String name;
private List<Tag> tags= Lists.newArrayList();
private RelativeTimeForm sampling= new RelativeTimeForm(1,"milliseconds");
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Tag> getTags() {
return tags;
}
public void setTags(List<Tag> tags) {
this.tags.addAll(tags);
}
public RelativeTimeForm getSampling() {
return sampling;
}
public void setSampling(int val, String unit) {
this.sampling.setUnit(unit);
this.sampling.setVal(val);
}
#Override
public String toString() {
return "MetricForm[name="+name+", tags="+tags+",sampling="+sampling+"]";
}
.
public class Tag {
private String key;
private String value;
public Tag(String key, String value) {
this.key = key;
this.value = value;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
#Override
public String toString() {
return String.format(
"Tag[key=%s, value='%s']",
key, value
);
}
}
.
public class RelativeTimeForm {
private int value;
private String unit;
public RelativeTimeForm (int val, String unit){
this.setValue(val);
this.setUnit(unit);
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public String getUnit() {
return unit;
}
public void setUnit(String unit) {
this.unit = unit;
}
#Override
public String toString() {
return "RelativeTimeForm[value="+value+", unit="+unit+"]";
}
I'm not experienced working with play.data.Form but in previous ocasions with simpler objects (Using primitive data types and String) this worked fine but when i tried to POST to the play application (Header: Content-Type = application/json; charset=utf-8) it occurs an Internal Server Error:
play.api.Application$$anon$1: Execution exception [[InvalidPropertyException:
Invalid property 'metrics[0].tags[0]' of bean class [model.QueryForm]: Illegal
attempt to get property 'tags' threw exception; nested exception is
org.springframework.beans.NullValueInNestedPathException: Invalid property
'metrics[0].tags' of bean class [model.QueryForm]: Could not instatiate property
path:
java.lang:InstatiationException: [model.Tag]
Any one can help with this? I canĀ“t figure out what to do. Is it to complex of an object to convert from JSON? Do i need to add some JSON Annotations (not currently using them)?
I have no clue how to fix this
UPDATE: I narrowed it down to the Tag class. for some reason i'm not able to instatiate Tag through JSON. I even tried setting a single Tag instance in the same level as the dates and it gives the same error (It work for Sampling)
RESOLVED:
Spring binding exception when a form is submitted
The answer is in the post above. I have to set an empty construtor in Tag class for it to work.
public Tag(){
}

The exception means, that one or more attributes aren't instantiated.
private List<MetricForm> metrics = new ...;
private List<Tag> tags = new ...;
private RelativeTimeForm sampling = new ...;
should do it.
In the case you get problems to read in your time values: Instead of using Date type directly to read in, I would use long to read in the time values and then (internally) convert them to Date objects.

Related

Selma - Bad custom field to field mapping

I have a project that uses Mapstrcut, i want to replace it by Selma, so in the below example i mapped AttachmentRequest to Attachment
public class Attachment {
private SocialReason socialReason;
public SocialReason getSocialReason() { return socialReason; }
public Attachment socialReason(SocialReason socialReason) { this.socialReason = socialReason; return this; }
}
public class SocialReason {
private String value;
public String getValue() { return value; }
public SocialReason value(String value) { this.value = value; return this; }
}
public class AttachmentRequest {
private String socialReason;
public String getSocialReason() { return socialReason; }
public AttachmentRequest socialReason(String socialReason) { this.socialReason = socialReason; return this; }
}
I tried with the bellow code, but i have this error
Bad custom field to field mapping: field out.getSocialReason().value
from destination bean Attachment has no setter !
--> Fix #Field({"socialreason","socialreason.value"})
#Mapper(withIgnoreMissing = IgnoreMissing.ALL)
public interface AttachmentCommandMapper {
#Maps(withCustomFields = { #Field({ "socialReason", "socialReason.value" }) })
Attachment attachmentRequestToAttachment(AttachmentRequest attachmentRequest);
}
Is setters required in the class for the mapping in Selma, because in mapstruct doesn't require setters.

How to write JUnit testcase for a Class

I am a fresher and I need to know how to write JUnit test cases for this class. Can anyone help me out?
package com.jpmc.cb.creos.util.grid;
public class GridHelper {
public static List<GridFilter> getGridFilters(String jsonFilters)throws JsonParseException, JsonMappingException, IOException
{
List<GridFilter> filters = new ArrayList<GridFilter>();
GridFilter filter[] = new ObjectMapper().readValue(jsonFilters,
GridFilter[].class);
for (int i = 0; i < filter.length; i++) {
filters.add(filter[i]);
}
return filters;
}
}
This is the GridFilter Class:
package com.jpmc.cb.creos.util.grid;
public class GridFilter {
private String property;
private String value;
private String operator;
public GridFilter() {}
public GridFilter(String property, String operator, String value)
{
this.property = property;
this.value = value;
this.operator = operator;
}
public String getProperty() {
return property;
}
public void setProperty(String property) {
this.property = property;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getOperator() {
return operator;
}
public void setOperator(String operator) {
this.operator = operator;
}
}
Here are some ideas for what to test. Write test methods for (at least) the following cases:
a well formed json with 2 filters should return a list with two filters with matching values
a well formed json with no filters should return an empty list
a malformed json should raise a JsonParseException
other bad data to raise the other exception types
How to write the test cases? Not clear what you're asking. But here's an example:
#Test
public void empty_json_gives_empty_list() throws Exception {
assertEquals(Collections.emptyList(), GridHelper.getGridFilters("[]"));
}

enum does not provide expected result

I have defined an enum in a class A
public class A{
public static final String CANDY = "yelow candy";
public static final String CAKE = "cookie";
public enum Yummy{
CANDY, CAKE;
}
}
In another package,
public class C {
Yummy[] yummies = A.Yummy.values();
for (Yummy yum : yummies){
String yumString = yum.toString();
System.out.println("yum =" + yumString);
}
}
I get CANDY and CAKE as a result, not "yelow candy" and "cookie".
What does I need to change to get the "yelow candy" and "cookie ?
You've defined an enum "A.Yummy" and also two strings, "A.Candy" and "A.CAKE".
They aren't linked at all.
You will want to delete the strings and add something like https://stackoverflow.com/a/13291109/1041364
public enum Yummy {
CANDY("yelow candy"),
CAKE("cookie");
private String description;
private Yummy(String description) {
this.description= description;
}
public String toString() {
return this.description;
}
}
Try the following:
public enum Yummy{
CANDY ("yellow candy"), CAKE ("cookie");
private String name;
private Yummy(String name) {
this.name = name;
}
public String toString() {
return this.name;
}
}
Additional values for enums should be hold in properties. You have to provide constructor to set up those properties.
public enum Yummy {
CANDY("yelow candy"), CAKE("cookie");
private String value;
private Yummy(String value) {
this.value = value;
}
};
And then in code you can use CANDY.value or override toString() method.
Try this:
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
for (Yummy yum : Yummy.values()) {
System.out.printf("%s, %s\n", yum, yum.getValue());
}
}
}
enum Yummy {
CANDY("yelow candy"),
CAKE("cookie");
private String value;
private Yummy(String value) {
this.value = value;
}
public String getValue() {
return this.value;
}
}

Robospice Cached Object is Always null

For some reason pulling a cached object back from the cache in Robospice is always null. Is there something I'm doing wrong?
getSpiceManager().execute(cardRequest, Card.class.getName(),
DurationInMillis.ONE_DAY, new CardRequestListener());
Is how it's executed. The spice manager is created as follows:
mSpiceManager = new SpiceManager(JacksonGoogleHttpClientSpiceService.class);
And the card class is as follows:
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"iosThumbHighRes",
"iosThumb",
"iosLargeHiRes",
"iosLargeHighRes",
"iosLarge"
})
public class Card {
#JsonProperty("iosThumbHighRes")
private String iosThumbHighRes;
#JsonProperty("iosThumb")
private String iosThumb;
#JsonProperty("iosLargeHiRes")
private String iosLargeHiRes;
#JsonProperty("iosLargeHighRes")
private String iosLargeHighRes;
#JsonProperty("iosLarge")
private String iosLarge;
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
#JsonProperty("iosThumbHighRes")
public String getIosThumbHighRes() {
return iosThumbHighRes;
}
#JsonProperty("iosThumbHighRes")
public void setIosThumbHighRes(String iosThumbHighRes) {
this.iosThumbHighRes = iosThumbHighRes;
}
#JsonProperty("iosThumb")
public String getIosThumb() {
return iosThumb;
}
#JsonProperty("iosThumb")
public void setIosThumb(String iosThumb) {
this.iosThumb = iosThumb;
}
#JsonProperty("iosLargeHiRes")
public String getIosLargeHiRes() {
return iosLargeHiRes;
}
#JsonProperty("iosLargeHiRes")
public void setIosLargeHiRes(String iosLargeHiRes) {
this.iosLargeHiRes = iosLargeHiRes;
}
#JsonProperty("iosLargeHighRes")
public String getIosLargeHighRes() {
return iosLargeHighRes;
}
#JsonProperty("iosLargeHighRes")
public void setIosLargeHighRes(String iosLargeHighRes) {
this.iosLargeHighRes = iosLargeHighRes;
}
#JsonProperty("iosLarge")
public String getIosLarge() {
return iosLarge;
}
#JsonProperty("iosLarge")
public void setIosLarge(String iosLarge) {
this.iosLarge = iosLarge;
}
#Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
#Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
#Override
public boolean equals(Object other) {
return EqualsBuilder.reflectionEquals(this, other);
}
#JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
#JsonAnySetter
public void setAdditionalProperties(String name, Object value) {
this.additionalProperties.put(name, value);
}
}
Is there something else I need to set?
Thanks, Graeme
The Google Http Client uses the #Key annotation. You are using Jackson annotation which is not supported by Googe Http Java Client, as it provides an abstraction layer over all serialisation solutions (gson/jackson).

How do i create a string enum types without overriding toString method to be used in Mule Studio?

I'm working with Mule Studio in this, and I actually was wondering the possibility to add the drop down list with a "custom" string name. The case applies for MIME Types (ContentTypes) names. (i.e: text/css, text/javascript, and so)
Made an structure like this:
public enum HttpContentType {
TEXT_PLAIN
{
public String toString() {
return "text/plain";
}
},
TEXT_CSS
{
public String toString() {
return "text/css";
}
},
TEXT_JS
{
public String toString() {
return "text/javascript";
}
},
TEXT_XML
{
public String toString() {
return "text/xml";
}
},
};
To then be used like this as a Configurable attribute:
/**
* Connection Content Types
*/
#Configurable
#Placement(order=1,group="Configuration",tab="HTTP Configuration")
private HttpContentType contentType;
But of course that when reading that from the Mule Studio it will be a Drop Down list with names such as: TEXT_CSS, TEXT_XML, TEXT_JAVASCRIPT ( http://puu.sh/3vLbd.png ) and so instead of text/css, text/xml, text/javascript.
How can i achieve this result?
A far better way to achieve this would be to provide a field in your enum, and provide an appropriate constructor:
public enum HttpContentType {
TEXT_PLAIN("text/plain"),
TEXT_CSS("text/css");
private String value;
HttpContentType(String value) {
this.value = value;
}
public String toString() {
return this.value;
}
public static HttpContentType getByValue(String value){
for (final HttpContentType element : EnumSet.allOf(HttpContentType.class)) {
if (element.toString().equals(value)) {
return element;
}
}
return null;
}
}
One option is to provide a different method to get the MIME string.
public interface IMimeTypeProvider {
public String toMimeType();
}
public enum HttpContentType implements IMimeTypeProvider {
TEXT_PLAIN
{
public String toMimeType() {
return "text/plain";
}
},
...
public String toMimeType() {
return "text/plain";
}
}
You might also consider adding a toDisplayString() method. The enumerator name is not necessarily a good display name, even in a single locale.
public enum HttpContentType {
TEXT_PLAIN("text/plain"), TEXT_CSS("text/css");
private String code;
HttpContentType(String code) {
this.code = code;
}
public String toString() {
return code;
}
public static HttpContentType getEnum(String code) {
if (code.equals("text/plain")) {
return TEXT_PLAIN;
} else if (code.equals("text/css")) {
return TEXT_CSS;
} else {
return null;
}
}
}

Categories

Resources