I have a member function that will retrieve all membershipId of a member(one member might have multiples of membershipId).After retrieve all membershipId using List,it will call the url like this.
This is my service:
RestRequest request = RestRequest.newBuilder()
.url("/membership/" + membershipId + "/outlet")
.get();
This is my controller:
#RequestMapping(value = "/favouriteStores", method = RequestMethod.GET)
public Object FavouriteStores(ModelMap modelMap,HttpSession session)throws Exception {
String memberId = "5677a7075e3f1b998fc7483b";
List<Membership> membershipList= memberService.getMembershipByMemberId(memberId);
List<String> membershipIds = membershipList.stream().map(m->m.getId()).collect(Collectors.toList());
String membershipId = membershipIds.toString();
Set<Outlet> outletSet = membershipService.getOutletByMembershipId(membershipId);
My problem is it will transform the whole membershipId in one url like this
"membership/[12345, 54321]/outlet"
It should be two url like "membership/[12345]/outlet" and "membership/[54321]/outlet"
I know we can use foreach to do that in controller,but i don't know how.Thanks for any helps.
Try map method of Stream instead :
You can achieve this using map method of Stream.
Set<Outlet> outletSet = membershipIds.stream()
.map(membershipService::getOutletByMembershipId)
.collect(Collectors.toSet());
Even you can combine your previous stream operations and omit creation of intermediate list objects :
String memberId = "5677a7075e3f1b998fc7483b";
Set<Outlet> outletSet = memberService.getMembershipByMemberId(memberId)
.stream()
.map(Membership::getId)
.map(membershipService::getOutletByMembershipId)
.collect(Collectors.toSet())
Related
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());
}
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.
I'm trying to get param values passed to a Java Servlet but the string returned is not correct. I'm storing the values in a Map and checking if the key exists.
Map params;
params = request.getParameterMap();
String id = params.get("id").toString();
String data = params.get("data").toString();
System.out.println("streaming" + data + " with id of " + id);
Yet if I call this servlet via http://localhost:8080/Serv/stream/data?data=hereisdata&id=you my output looks like this:
streaming[Ljava.lang.String;#5e2091d3 with id of [Ljava.lang.String;#36314ab8
What am I missing?
EDIT: as the suggested answers are not working, I'm including the entire class as I'm likely messing something up within the class:
import java.util.*;
import javax.servlet.http.HttpServletRequest;
import Engine.Streamer;
public class AnalyzerController {
private Map params;
private String pathInfo;
private HttpServletRequest request;
public AnalyzerController(HttpServletRequest request)
{
this.params = request.getParameterMap();
this.pathInfo = request.getPathInfo();
}
public void processRequest()
{
System.out.println("procing with " + pathInfo);
switch(pathInfo){
case "/stream/data":
if(params.containsKey("id") && params.containsKey("data")) processStream();
break;
}
}
private void processStream()
{
System.out.println("we are told to stream");
String data = request.getParameter("data");
String id = request.getParameter("id");
Streamer stream = new Streamer();
stream.streamInput(data, "Analyzer", id);
}
}
This line specifically is throwing the NPE: String data = request.getParameter("data");
If you look at the docs of the Request#getParameterMap(), it returns a Map of the type Map<String, String[]>. Therefore, you need to take out the first element from the value String[] array returned from the map.
String id = params.get("id")[0];
Ofcourse, you can avoid all this and directly get the parameters from the request objects using the Request#getParameter() method.
String id = request.getParameter("id");
Edit: Looking at your class code, it seems that the instance variable request is not initialized. Initialize that in the constructor like this:
public AnalyzerController(HttpServletRequest request)
{
this.request = request; // Initialize your instance variable request which is used in the other methods.
this.params = request.getParameterMap();
this.pathInfo = request.getPathInfo();
}
You can get the required parameters instead of the whole map
String id = request.getParameter("id");
String data = request.getParameter("data");
Try something like this.
String data = ((String)params.get("data"));
Or directly from the Request.
String data = request.getParameter("data");
You can use request object plus it's method for to get data usinggetParameter() of you can use getParameterValues() if multiple data are from page.
String id = request.getParameter("id")
String data = request.getParameter("data")
why are you using Map ?
Any special need of it or any reason ?
or you can use like this :
String id = params.get("id")[0];
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¶m2=value2¶m1=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.
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);