Issue while mapping my json to model fields attribute value set 0 - java

while mapping json with my object, my attribute set default value to zero, here is my field attribute
in my ModelDTO
private int ExcessRqstType;
public int getExcessRqstType() {
return ExcessRqstType;
}
public void setExcessRqstType(int excessRqstType) {
ExcessRqstType = excessRqstType;
}
Here is my json
{
"ExcessRqstType": 2,
"balance": 100000,
"ExcessFor": 1020
}
In output it gives me '0'
System.out.println(objModel.getExcessRqstType());
"ExcessRqstType" value in my json is '2' but when it mapped i get '0'.
I am stuck in this issue.

Issue resolve, this issue because of case sensitivity, I change "ExcessRqstType" to "excessRqstType" in my DTO as well as in model, also changed in json request object
private int excessRqstType;
public int getExcessRqstType() {
return excessRqstType;
}
public void setExcessRqstType(int excessRqstType) {
excessRqstType = excessRqstType;
}

Related

How to use AsmVisitorWrapper to visit an array inside an annotation and merge its content with another array

(repository with an example of what I'm trying to do is here)
It's my first time using ByteBuddy and I've found myself struggling to merge the contents of two #RequestMapping annotations.
Something like this:
#Validated
#RequestMapping(
path = "/somePrefix",
produces = {"application/text", "application/xml"},
consumes = {"application/text", "application/xml"},
params = {"exampleParam1", "exampleParam2"},
headers = {"key=val", "nokey=val"}
)
public interface ExampleInterface {
#RequestMapping(value = {"/someEndpoint"}, method = {RequestMethod.POST}, produces = {"application/json"}, consumes = {"application/json"})
ResponseEntity<String> someEndpointMethod(String value);
}
And pretending to having this:
public interface ExampleInterface {
#RequestMapping(
value = {"/somePrefix/someEndpoint"},
method = {RequestMethod.POST},
produces = {"application/text", ,application/xml","application/json"},
consumes = {"application/text", "application/xml","application/json"},
params = {"exampleParam1", "exampleParam2"},
headers = {"key=val", "nokey=val"}
)
ResponseEntity<String> someEndpointMethod(String value);
}
I've seen that editing the values can be done replacing the value when the method annotation object is visited, for example:
[...]
#Override
public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
if (Type.getDescriptor(RequestMapping.class).equals(descriptor)) {
return new AnnotationVisitor(Opcodes.ASM9, super.visitAnnotation(descriptor, visible)) {
#Override
public AnnotationVisitor visitArray(String name) {
if ("produces".equals(name)) {
return new AnnotationVisitor(Opcodes.ASM9, super.visitArray(name)) {
#Override
public void visit(String name, Object value) {
// I'd like to receive an array as value, so I can provide one with all values merged
boolean tryToMerge = false;
if (tryToMerge) {
//I cannot return array with everything
Object[] newValue = new Object[]{value};
value = Arrays.copyOf(newValue, newValue.length + originalAnnotation.produces().length);
System.arraycopy(originalAnnotation.produces(), 0, value, newValue.length, originalAnnotation.produces().length);
} else {
//I can only replace a single value
value = originalAnnotation.produces()[0];
}
// How to set an array in produces?
super.visit(name, value);
}
};
} else {
return super.visitArray(name);
}
}
};
} else {
return super.visitAnnotation(descriptor, visible);
}
}
[...]
However, I'm receiving the array values one per one via visit() and I cannot just return an array with the two values I want to merge (["application/text", "application/xml"]) because it's expecting an String object. I can substitute the value that I'm receiving but I cannot add more.
Besides that, the headers and params arrays are not being visited, which seems logical because no values are on those arrays. However, I'm not sure how I should visit those fields in the #RequestMapping on the method so I can insert the values picked from the class one.
What I am missing here?
Thanks in advance.
In such a case, you can override the onEnd() method of AnnotationVisitor. When invoked, you know that all values are processed and you can invoke super.onValue() from there before delegating to super.onEnd(). If you know the replacements beforehand, you can also simply leave the onValue method empty to drop all existing values and then repopulate the array in the end.

creating a POJO containing only some elements from the response

I'm trying to read from a JSON response using a pojo. The response has many attributes but I only need few, I created the POJO with only those attributes, but when I'm trying to read it. it fails to parse it.
JSON response:
[
{
"attr_1":1,
"attr_2":2,
"attr_3":3,
"attr_4":4,
"attr_5":5,
},
{
"attr_1":10,
"attr_2":20,
"attr_3":30,
"attr_4":40,
"attr_5":50,
}
]
my POJO:
#JsonIgnoreProperties(ignoreUnknown = true)
public class MyPOJO {
#JsonProperty("attr_2")
private int attr_2;
#JsonProperty("attr_4")
private int attr_4;
public int getattr_2() { return attr_2; }
public void setattr_2(int attr_2) { this.attr_2 = attr_2;}
public int getattr_4() { return attr_4; }
public void setattr_4(int attr_4) { this.attr_4 = attr_4;}
}
I only need attr_2 and attr_4, and not the others.
this is how I'm trying to read the response:
MyPOJO[] arr = response.readEntity(MyPOJO[].class);
but it fails at this step. do we really need to have all the attributes in my POJO as there are many and I need few attributes, don't want to have redundant code?
I was able to solve the issue. I created an empty constructor and it worked. previously I had a constructor with the two needed attributes only.

Getter is used to add value in dynamoDB

I have an attribute called Attribute which is Set in dynamoDB(not mandatory), all the values for the attributes will be sent through an api which will be added into dynamoDB. I am using
#DynamoDBAttribute(attributename = Attribute)
private set<String> Attribute
public Set<String> getAttribute() {
if(CollectionUtils.isNullOrEmpty(Attribute)) {
return ImmutableSet.of(DEFAULT_ATTRIBUTE);
} else {
return ImmutableSet.copyOf(Attribute);
}
}
public void setAttribute(final Set<String> Attribute) {
if (CollectionUtils.isNullOrEmpty(Attribute)) {
this.categories = ImmutableSet.of();
} else {
this.categories = ImmutableSet.copyOf(Attribute);
}
}
I am expecting my dynamoDB table to have an empty set when we don't pass in an attribute value in the request we use, but instead of that, it is saving DEFAULT_ATTRIBUTE as the value of the field Attribute.
My DynamoDBMapperConfig.Savebehavior has default UPDATE, but I see that while saving a new value all the Savebehavior works the same.
If anyone knows the issue please help me with this, I have been trying to debug this from a long time. I want to know why the value in getAttribute is getting stored as the Attribute value?
Try this instead:
private set<String> Attribute
#DynamoDBTyped(DynamoDBMapperFieldModel.DynamoDBAttributeType.SS)
public Set<String> getAttribute() {
return Attribute;
}
public void setAttribute(final Set<String> Attribute) {
this.Attribute = Attribute;
}
DynamoDBMapper will handle the String Set for you. You just need to use the right annotation.
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBMapper.DataTypes.html

JAX-RS/JAXB JSON to POJO - Ignore fields in JSON that don't exist in the POJO

I am working on an API that needs to be able to handle JSON payloads on PUT/POST that may be supersets of the known POJO.
For example:
#XmlRootElement
public FruitCounter
{
int numberOfApples;
int numberOfOranges;
public int getNumberOfApples()
{
return this.numberOfApples();
}
public int setNumberOfApples(int numberOfApples)
{
this.numberOfApples = numberOfApples;
}
public int getNumberOfOranges()
{
return this.numberOfOranges();
}
public int setNumberOfOranges(int numberOfOranges)
{
this.numberOfOranges = numberOfOranges;
}
}
Would produce JSON along the following lines when a GET is performed:
{
numberOfApples: 4,
numberOfOranges: 7
}
We need to be able to handle a JSON payload like the following, to update the counts for apples and oranges but do nothing for pears.
{
numberOfApples: 9,
numberOfOranges: 19,
numberOfPears: 21
}
Is there any clean way to do this?
Add #JsonIgnoreProperties(ignoreUnknown = true) on top of your class
#JsonIgnoreProperties(ignoreUnknown = true)
#XmlRootElement
public FruitCounter
{
int numberOfApples;
int numberOfOranges;
public int getNumberOfApples()
{
return this.numberOfApples();
}
public int setNumberOfApples(int numberOfApples)
{
this.numberOfApples = numberOfApples;
}
public int getNumberOfOranges()
{
return this.numberOfOranges();
}
public int setNumberOfOranges(int numberOfOranges)
{
this.numberOfOranges = numberOfOranges;
}
}
Also check this question which seems to be the same problem.

Error in deserializing body of reply message for a web service operation

Error is obviously after the remote procedure/method has been executed. It's most likely that the remote service is sending back the incorrect data or so I think. I have tried increasing the readQuote in Web.Config, that didn't help.
Response Class
When this property (MultiSMSPostedList) is set, the value is NULL. As soon as the code comes out of get, the exception is thrown.
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "2.0.50727.5485")]
[System.SerializableAttribute()]
//[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.SoapTypeAttribute(Namespace="urn")]
public partial class MessagingServices_SendMultiSMSResult : object, System.ComponentModel.INotifyPropertyChanged {
private int sMSCountField;
private MessagingServices_SendMultiSMS_SendSuccess[] multiSMSPostedListField;
private MessagingServices_SendMultiSMS_SendFailed[] multiSMSRejectedListField;
/// <remarks/>
public int SMSCount {
get {
return this.sMSCountField;
}
set {
this.sMSCountField = value;
this.RaisePropertyChanged("SMSCount");
}
}
/// <remarks/>
[System.Xml.Serialization.SoapElementAttribute(IsNullable=true)]
public MessagingServices_SendMultiSMS_SendSuccess[] MultiSMSPostedList {
get {
return this.multiSMSPostedListField;
}
set {
this.multiSMSPostedListField = value;
this.RaisePropertyChanged("MultiSMSPostedList");
}
}
/// <remarks/>
[System.Xml.Serialization.SoapElementAttribute(IsNullable=true)]
public MessagingServices_SendMultiSMS_SendFailed[] MultiSMSRejectedList {
get {
return this.multiSMSRejectedListField;
}
set {
this.multiSMSRejectedListField = value;
this.RaisePropertyChanged("MultiSMSRejectedList");
}
}
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName) {
System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
if ((propertyChanged != null)) {
propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
}
Exception
The exception text is below, it clear that exception is caused when system tries to convert variable to array.
http://justpaste.it/sms-exception
More information
Further digging shows that the remote service is returning the correct number of values, if not the format.
This property MultiSMSPostedList makes call to below class based on the number of values passed to the original procedure/method. (i.e. if I pass two phone numbers and two text messages, the properties inside MessagingServices_SendMultiSMS_SendSuccess are initialized twice, indicating remote server returned an array)
Property class
public partial class MessagingServices_SendMultiSMS_SendSuccess : object, System.ComponentModel.INotifyPropertyChanged {
private string gRecipientNameField;
private string gRecipientMSISDNwithCCField;
private int gOutMsgIDField;
/// <remarks/>
[System.Xml.Serialization.SoapElementAttribute(IsNullable=true)]
public string gRecipientName {
get {
return this.gRecipientNameField;
}
set {
this.gRecipientNameField = value;
this.RaisePropertyChanged("gRecipientName");
}
}
/// <remarks/>
[System.Xml.Serialization.SoapElementAttribute(IsNullable=true)]
public string gRecipientMSISDNwithCC {
get {
return this.gRecipientMSISDNwithCCField;
}
set {
this.gRecipientMSISDNwithCCField = value;
this.RaisePropertyChanged("gRecipientMSISDNwithCC");
}
}
/// <remarks/>
public int gOutMsgID {
get {
return this.gOutMsgIDField;
}
set {
this.gOutMsgIDField = value;
this.RaisePropertyChanged("gOutMsgID");
}
}
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName) {
System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
if ((propertyChanged != null)) {
propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
}
I am sure, visual studio is not able to generate the class correctly based on the WSDL data, I may need to make some changes to reference.cs file. I am not an expert on the subject, so not really sure what and where should I make the change?
Could be useful
Remote service is java based, axis web service.
MORE INFO: Changes made to reference.cs
I made below changes to Response Class and it's working without any exception. Since it's a variable instead of array, I get only first response and all the other response values are lost.
private MessagingServices_SendMultiSMS_SendSuccess[] multiSMSPostedListField;
private MessagingServices_SendMultiSMS_SendFailed[] multiSMSRejectedListField;
I am not sure where exactly in the reference.cs I can find the location, where remote call is made/ends, may be making some changes there could help. Any suggestions?

Categories

Resources