Hibernate custom constraint validator, how to set propertyPath explicitly? - java

my custom class is implemented via:
#RequiredIfSet.List({
#RequiredIfSet(field = "isFillingOutForSomeoneElse", dependentField = "reporterName", message = "may not be null"),
})
When I loop through my ConstraintViolations and whip it to the frontend via a DTO and ajax, I have getMessage() and getPropertyPath() in a little String[].
Works fine for everything, but propertyPath isn't set by this, as its not ON the field, its a list, how can i set it, or grab the field name to send back? Has been driving me crazy, have tried a few work around, also for note, heres where I loop:
public static <T> EntityValidationDTO GetEntityValidationDTO(Set<ConstraintViolation<T>> cv){
List<String[]> invalidFields = new ArrayList<String[]>();
Iterator<ConstraintViolation<T>> iterator = cv.iterator();
while(iterator.hasNext()) {
ConstraintViolation<T> i = iterator.next();
String message = i.getMessage();
String property = i.getPropertyPath().toString();
invalidFields.add(new String[] { property, message });
}
EntityValidationDTO EVDTO = new EntityValidationDTO();
EVDTO.setStatus("fail");
EVDTO.setInvalidFields(invalidFields);
return EVDTO;
}

Related

DynamoDB updating list from Java fails

I have next table:
#DynamoDBTable(tableName = "Table")
#Getter
#Setter
public class Table {
#DynamoDBHashKey
private String id;
#DynamoDBAttribute
private List<String> list;
}
I need to add values to list from Java. I tried next approach:
UpdateItemRequest request = new UpdateItemRequest()
.withTableName("Table")
.withKey(Collections.singletonMap("id", new AttributeValue().withS("123")))
.withUpdateExpression("SET #ri = list_append(:vals, #ri)")
.withExpressionAttributeNames(Collections.singletonMap("#ri","list"))
.withExpressionAttributeValues(Collections.singletonMap(":vals",
new AttributeValue().withSS("1","2","3")));
dynamoDB.updateItem(request);
But it fails without providing exact reason:
Unable to unmarshall exception response with the unmarshallers provided
I got two questions:
What is wrong with my request ?
Why I get unmarshall exception and how to fix it to get real reason ?
P.S. Other update requests work fine e.g. I can update id with same approach without problem.
Updated:
I've found a way to update values from Java
UpdateItemRequest request = new UpdateItemRequest()
.withTableName("Table")
.withKey(Collections.singletonMap("id", new AttributeValue().withS("123")))
.withUpdateExpression("SET #ri = list_append(:vals, #ri)")
.withExpressionAttributeNames(Collections.singletonMap("#ri","list"))
.withExpressionAttributeValues(Collections.singletonMap(":vals",
new AttributeValue().withL(new AttributeValue().withS("1"),AttributeValue().withS("2"),AttributeValue().withS("3"))));
dynamoDB.updateItem(request);
But it only allows to add one by one values in list, but I need to add several.
private void updateList(String id, String field, List<AttributeValue> values) {
UpdateItemRequest request = new UpdateItemRequest()
.withTableName("Table")
.withKey(Collections.singletonMap("id", new AttributeValue().withS(id)))
.withUpdateExpression("SET #field = list_append(:values, #field)")
.withExpressionAttributeNames(Collections.singletonMap("#field", field))
.withExpressionAttributeValues(Collections.singletonMap(":values",
new AttributeValue().withL(values)));
dynamoDB.updateItem(request);
}
And use next method to convert to list of AttributeValue
private List<AttributeValue> buildAttributeValuesList(List<String> values) {
return values
.stream()
.map(it -> new AttributeValue().withS(it))
.collect(Collectors.toList());
}

How to save JSONdata into a set?

I have a data set. It is of the form
{
"name1": 123
"name2": 234
"name3": 345
.
.
.
}
Now, I am using a #RestController to read this through PostMan. I have a class test.java.
I have a function,
public void testController(#RequestBody String request)
I'm running this through a local host with the help of #RequestMapping. I need to save the above data set one by one in an object. The object is as follows.
public class OperatorClass implements Comparable<OperatorClass>{
private String name;
private ArrayList<String> id = new ArrayList<>();
OperatorClass(String name, String id)
{
add_id(id);
add_name(name);
}
I am trying to save this data in the following way, which by the way I have figured out is wrong.
try {
JSONObject array = new JSONObject(request);
Iterator<String> stringIterator1 = array.keys();
stringIterator1.next();
ArrayList<String> arrayList = new ArrayList<>();
OperatorClass oco = new OperatorClass(array.keys().,array.get(array.keys().toString()).toString());
System.out.println(oco.get_Name());
System.out.println(oco.get_Id());
} catch (Exception e) {
e.printStackTrace();
}
I know it is wrong because array.keys() gives all the name1, name2, name3 data. What I want to know is how to get just name 1 for this. And how to get it's following ID, to insert into a particular object.I was trying to save the object into a set of operator class.
Ok. I have got an answer to this problem. We use
String temp = stringIterator1.next();
And instead of
OperatorClass oco = new OperatorClass(array.keys().,array.get(array.keys().toString()).toString());
We use,
OperatorClass oco = new OperatorClass(temp, array.get(temp).toString);
Just remember that using string iterator will probably not display the values in the order of the data set, due to hash mapping.

Gson converter factory retrofit2. Different types in serialization/deserialization

I'm working with wordpress post metas and rest api, i've exposed to rest a meta field called "picture_collection" wich store data as an array of integers where every number represents the ID of an attachment.
I've then modified the response when interrogating the api to give me a list of links instead of the attachment ids, like this:
function get_pic_coll ($object, $field_name, $request) {
include_once dirname(__FILE__) . '/attach_coll.php';
$pic_coll = get_post_meta ($object['id'], $field_name, true);
$json_coll = array();
if($pic_coll != null || !empty($pic_coll)){
foreach ($pic_coll as $pic){
$media_id = $pic;
$link_med = wp_get_attachment_image_src($media_id, 'medium');
$link_full = wp_get_attachment_image_src($media_id, 'full');
$medium_size = $link_med[0];
$full_size = $link_full[0];
$obj = new attach_coll($media_id, $medium_size, $full_size);
$element = $obj->return_coll_object();
$json_coll[] = $element;
}
return $json_coll;
}
}
while the attach_coll object is:
class attach_coll{
public function __construct($media_id, $medium_url, $orig_url){
$this->attach_id = $media_id;
$this->medium_size_pic = $medium_url;
$this->full_size_pic = $orig_url;
}
private $attach_id;
private $medium_size_pic;
private $full_size_pic;
public function get_media_id(){
return $this->attach_id;
}
public function get_medium_pic(){
return $this->medium_size_pic;
}
public function get_orig_pic(){
return $this->full_size_pic;
}
public function return_coll_object(){
$ret_coll = array(
"ID" => $this->get_media_id(),
"medium" => $this->get_medium_pic(),
"full" => $this->get_orig_pic()
);
return $ret_coll;
}
}
Java side the things goes like this:
1)the user make a picture and upload her, he receive in exchange the ID of the attachment that is stored inside an Integers ArrayList.
2)when he has done the program update the post_meta passing to the api the entire list.
3)the program receive the response as a json containing the whole post with my custom field, it looks like this:
{...
"id":"someValue",
"title":"myTitle",
"pic_collection":[ {'ID':'picID','mediumSizePic':'someUrl', 'FullSizePic':'SomeOtherUrl},{...}],
The php code works well as i see from the ResponseBody the json i was expecting, the problem is that i'm getting an error 'gson expected a Integer and found an Object' that is logical because the pojo is defined like:
#SerializedName("pic_collection")
private List<Integer> idList = new ArrayList<Integer>();
public void setList(List<Integer> list){
this.idList=list;
}
I tried to change my list to:
List<PicCollection> picList = new ArrayList<PicCollection>();
public class PicCollection{
#SerializedName("ID")
private int picId;
#SerializedName("medium_size")
private String medSizeUrl;
#SerializedName("full_size")
private String fullSizeUrl;
Getters and Setters
}
But that just complicated everything up and didn't resolved the problem as i'm still having a the same gson error 'ID expecting an int but found an object' and no links returned at all.
A glimpse on the code to set the id's:
iterator=idList.iterator;
while(iterator.hasNext()){
FotoCollection fc = new FotoCollection();
fc.ID = iterator.next
What can i do to resove the problem? I need a custom converter?
I just created 2 objects:
One for the request and one for the response.

How to avoid interference of HttpServletRequest.getReader and getParameterValues?

In my application I have to extract parameters of a request and put into a collection in the order of their appearance in the querystring.
For example, if the sender makes following request,
http://myapp.com/myrequest?param3=value3&param2=value2&param1=value1 ,
I need to generate a collection, in which the elements are placed in this order: param3, param2, param1.
To achieve this, I first extract the names of the parameters using the method getParameterNames shown below.
private List<String> getParameterNames(HttpServletRequest aRequest)
throws IOException {
final List<String> parameterNames = new LinkedList<>();
final BufferedReader reader = aRequest.getReader();
final String queryString = IOUtils.toString(reader);
final String[] parameterValuePairs = queryString.split("&");
for (String parameterValuePair : parameterValuePairs) {
final String[] nameValueArray = parameterValuePair.split("=");
parameterNames.add(nameValueArray[0]);
}
return parameterNames;
}
The problem: After invokation of this method, aRequest.getParameterValue(...) returns null for ever parameter name.
If I do it otherwise - first save the parameter map, and then invoke getParameterNames, then its result is null.
final Map<String,String[]> parameterMap = aRequest.getParameterMap();
final List<String> parameterNames = getParameterNames(aRequest);
I tried following things:
Make sure that reader.close() is not invoked in getParameterNames (elsewhere I read that this may cause problems).
Invoke reader.reset().
None of this helped.
How can I get a list of parameter-value pairs from a HttpServletRequest, which is sorted by parameter's appearance in the querystring?
With the first approach you don't need to use Reader to get the parameters. Instead do:
final List<String> parameterNames = new LinkedList<>();
final String queryString = query.getQueryString(); // get query string from query itself
// rest of your code stays unchanged
The reason it didn't work is because data from a request input stream can be read only once.
Or, if I am wrong and that is not the case, you can save parameters and their values into a LinkedHashMap:
final LinkedHashMap<String, String> parameterValues = new LinkedHashMap<>();
final BufferedReader reader = aRequest.getReader();
final String queryString = IOUtils.toString(reader);
final String[] parameterValuePairs = queryString.split("&");
for (String parameterValuePair : parameterValuePairs) {
final String[] nameValueArray = parameterValuePair.split("=");
parameterValues.put(nameValueArray[0], nameValueArray[1]);
}
Now parameterValues is a map with entries sorted by the order of appearance.

REST - How to pass an array of long in parameter with Jersey?

I am trying to pass an array of long with Jersey :
In the client side i have trying something like that :
#GET
#Consume("text/plain")
#Produces("application/xml)
Response getAllAgentsById(#params("listOfId") List<Long> listOfId);
Is there a way to realize something like that?
Thanks in advance!
If you want to stick to "application/xml" format and avoid JSON format, you should wrap this data into a JAXB annotated object, so that Jersey can use the built-in MessageBodyWriter / MessageBodyReader.
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public ListOfIds{
private List<Long> ids;
public ListOfIds() {}
public ListOfIds(List<Long> ids) {
this.ids= ids;
}
public List<Long> getIds() {
return ids;
}
}
On the client side (using Jersey client)
// get your list of Long
List<Long> list = computeListOfIds();
// wrap it in your object
ListOfIds idList = new ListOfIds(list);
Builder builder = webResource.path("/agentsIds/").type("application/xml").accept("application/xml");
ClientResponse response = builder.post(ClientResponse.class, idList);
If you just need to pass array of long its possible without any problem. But I will probably pass the long as comma delimited string. (123,233,2344,232) and then split the string and convert in to long.
If not, I suggest you use Json Serialization. If you are using java client, then google gson is a good option. In client side, I will encode my list:
List<Long> test = new ArrayList<Long>();
for (long i = 0; i < 10; i++) {
test.add(i);
}
String s = new Gson().toJson(test);
And pass this string as post param. In the server side, I will decode like this.
Type collectionType = new TypeToken<List<Long>>() {
} // end new
.getType();
List<Long> longList = new Gson().fromJson(longString,
collectionType);

Categories

Resources