I tried to get product from API with some parameters. I used WooCommerce API Java Wrapper. REST API with OAuth 1.0. Simple getAll method return list of one page (10 products). To get all i must set how much products must be in one page and use offset. To get third page must send this parameters: "per_page=10&offset=20". I test with query in get&post programm - all work. In Java, when i added parameters - i got error (401)- "Invalid signature - the provided signature did not match".
I changed WooCommerceAPI class:
private static final String API_URL_FORMAT = "%s/wp-json/wc/v2/%s";
private static final String API_URL_ONE_ENTITY_FORMAT = "%s/wp-json/wc/v2/%s/%d";
private HttpClient client;
private OAuthConfig config;
public List getAll(String endpointBase) {
String url = String.format(API_URL_FORMAT, config.getUrl(), endpointBase) + "?per_page=10&offset=20";
String signature = OAuthSignature.getAsQueryString(config, url, HttpMethod.GET);
String securedUrl = String.format("%s&%s", url, signature);
System.out.println("url="+url);
System.out.println("securedUrl="+securedUrl);
return client.getAll(securedUrl);
}
But I have got the same error.
I've just released a new version of wc-api-java library (version 1.2) and now you can use the method getAll with params argument where you can put additional request parameters. For example:
// Get all with request parameters
Map<String, String> params = new HashMap<>();
params.put("per_page","100");
params.put("offset","0");
List products = wooCommerce.getAll(EndpointBaseType.PRODUCTS.getValue(), params);
System.out.println(products.size());
As you noticed, you changed URL_SECURED_FORMAT from "%s?%s" to "%s&%s", as soon as you added query params. But problem is that signature is generated based on all query params, not only oauth_*, and your params offset and per_page are ignored while generating signature (as soon as lib author did not expect additional params).
Think that you need to modify this lib to support signature based on all params.
Related
I am sending some get query to an API that returns a 400 Bad request when I send empty query parameters.
However, I do not know in advance which optional query parameters will be empty.
Apart from testing each optional parameter for emptyness, is there a simpler approach to dynamically remove empty parameters ?
Currently I am doing:
private URI getApiUrl(QueryParametersObject qpo) {
String url = configBundle.getPropertyStr("some.api.url");
UriComponentsBuilder builder = UriComponentsBuilder
.fromHttpUrl(url)
.queryParam("mandatoryParam1", qpo.getMandatoryParam1()) // MANDATORY
.queryParam("mandatoryParam2", qpo.getMandatoryParam2()); // MANDATORY
if (!qpo.getOptionalParam1().isEmpty())
builder.queryParam("optionalParam1", qpo.getOptionalParam1());
if (!qpo.getOptionalParam2().isEmpty())
builder.queryParam("optionalParam2", qpo.getOptionalParam2());
if (!qpo.getOptionalParam3().isEmpty())
builder.queryParam("optionalParam3", qpo.getOptionalParam3());
return builder.build().encode().toUri();
}
It can become quite cumbersome when the number of optional query parameters grows.
A way to do this is to use a newer version of spring-web, like 5.3.4, in which the class UriComponentsBuilder gets a new method UriBuilder queryParamIfPresent(String name, Optional<?> value) that you can use like this:
private URI getApiUrl(QueryParametersObject qpo) {
String url = configBundle.getPropertyStr("some.api.url");
UriComponentsBuilder builder = UriComponentsBuilder
.fromHttpUrl(url)
.queryParam("mandatoryParam1", qpo.getMandatoryParam1()) // MANDATORY
.queryParam("mandatoryParam2", qpo.getMandatoryParam2()) // MANDATORY
.queryParamIfPresent("optionalParam1", Optional.of(qpo.getOptionalParam1()))
.queryParamIfPresent("optionalParam2", Optional.of(qpo.getOptionalParam2()))
.queryParamIfPresent("optionalParam3", Optional.of(qpo.getOptionalParam3()));
return builder.build().encode().toUri();
}
Further enhancing the accepted answer by #l0r3nz4cc10
Optional.ofNullable would be a better approach !!!
private URI getApiUrl(QueryParametersObject qpo) {
String url = configBundle.getPropertyStr("some.api.url");
UriComponentsBuilder builder = UriComponentsBuilder
.fromHttpUrl(url)
.queryParam("mandatoryParam1", qpo.getMandatoryParam1()) // MANDATORY
.queryParam("mandatoryParam2", qpo.getMandatoryParam2()) // MANDATORY
.queryParamIfPresent("optionalParam1", Optional.ofNullable(qpo.getOptionalParam1()))
.queryParamIfPresent("optionalParam2", Optional.ofNullable(qpo.getOptionalParam2()))
.queryParamIfPresent("optionalParam3", Optional.ofNullable(qpo.getOptionalParam3()));
return builder.build().encode().toUri();
I am trying to automate twitter API. when tried to print "js.get("text") using
System.out.println(js.get("text")); I am getting error as
"The method println(boolean) is ambiguous for the type PrintStream"
I downloaded jars and passed in Build path as well "scribejava-apis-2.5.3" and "scribejava-core-4.2.0"
Below code is not allowing me use println for ------>js.get("text")
public class Basicfunc {
String Consumerkeys= "**************";
String Consumersecretkeys="*******************";
String Token="*******************";
String Tokensecret="***************************";
#Test
public void getLatestTweet(){
RestAssured.baseURI = "https://api.twitter.com/1.1/statuses";
Response res = given().auth().oauth(Consumerkeys, Consumersecretkeys, Token, Tokensecret).
queryParam("count","1").
when().get("/home_timeline.json").then().extract().response();
String response = res.asString();
System.out.println(response);
JsonPath js = new JsonPath(response);
System.out.println(js.get("text"));
}
}
Use System.out.println(js.getString("text")); instead of System.out.println(js.get("text"));, because get returns any primitive value.
I think your problem is that your twitter response is actually a list.
Try to use System.out.println(js.getList()[0].get("text")); and be aware that you are only using the first [0] entry and ignoring the rest.
Here is a part of my code for index or update document. I want to get a specific field value 'documentID' which is in '_source'.Here 'json' is JSONObject of document model.
String jsonForUpdate = json.toString();
String uuid = UUID.randomUUID().toString();
json.put("documentID", uuid);
String jsonForIndex = json.toString();
IndexRequest indexRequest = new IndexRequest(indexName, typeName, documentModel.getId());
indexRequest.source(jsonForIndex);
UpdateResponse updateResponse = elasticsearchTemplate.getClient().prepareUpdate(indexName, typeName , documentModel.getId()).setDoc(jsonForUpdate).setUpsert(indexRequest).setFields("documentID").get();
I tried this code to get value for document field.
updateResponse.getGetResult().getFields().get("documentID").getValue().toString();
But it didnt work for me during updating the document.works fine during indexing the document.
If you look at: https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update.html
you can see the following parameter that can be passed on update:
_source
Allows to control if and how the updated source should be returned in the response. By default the updated source is not returned. See source filtering for details.
This mean that in your prepareUpdate you can use the setFetchSource(true) method, although this will bring the full document.
Update:
For version 2.3.3 you can still use:
/**
* Explicitly specify the fields that will be returned. By default, nothing is returned.
*/
public UpdateRequestBuilder setFields(String... fields) {
request.fields(fields);
return this;
}
Elasticsearch doc: https://www.elastic.co/guide/en/elasticsearch/reference/2.3/docs-update.html
The method is available on the UpdateRequestBuilder, which is the class of the object returned by your prepareUpdate.
The following code produces a string that has question marks as the display name when I insert an Iranian address(?????, ???????). However if I put the same url into my browser, it returns Tehran, Iran instead of question marks. I know that it has something to do with encoding but how do I get the English text as the browser returns in my java application?
String rawAddress = "Tehran";
String address = URLEncoder.encode(rawAddress, "utf-8");
String geocodeURL = "http://nominatim.openstreetmap.org/search?format=json&limit=1&polygon=0&addressdetails=0&email=myemail#gmail.com&languagecodes=en&q=";
String formattedUrl = geocodeURL + address;
URL theGeocodeUrl = new URL(formattedUrl);
System.out.println("HERE " +theGeocodeUrl.toString());
InputStream is = theGeocodeUrl.openStream();
final ObjectMapper mapper = new ObjectMapper();
final List<Object> dealData = mapper.readValue(is, List.class);
System.out.println(dealData.get(0).toString());
I tried the following code but it produced this: تهران, �ايران‎ for the display name which should be Tehran, Iran.
System.out.println(new String(dealData.get(0).toString().getBytes("UTF-8")));
Use "accept-language" in the URL parameter for Nominatim to specify the preferred language of Nominatim's results, overriding whatever default the HTTP header may set. From the documentation:
accept-language= <browser language string>
Preferred language order for showing search results, overrides the
value specified in the "Accept-Language" HTTP header. Either uses
standard rfc2616 accept-language string or a simple comma separated
list of language codes.
I'm using a Jersey (v 1.17.1) client to communicate with a remote server that I don't have under my control (so I can't see the incomming requests).
I like to issue a POST request with JSON data, that has a structure similar to this example:
{"customer":"Someone",
"date":"2013-09-12",
"items":[{
"sequenceNo":1,
"name":"foo",
"quantity":2,
"price":42,
"tax":{"percent":7,"name":"vat 7%"}
},
{
"sequenceNo":2,
"name":"bar",
"quantity":5,
"price":23,
"tax":{"percent":7,"name":"vat 7%"}
}
]
}
That's my code:
final Client c = Client.create();
final WebResource service = c.resource(SERVER);
final Form form = new Form();
form.add("customer", "Someone");
form.add("date", "2013-09-12");
form.add("items", XXX); // how do I do that?
final ClientResponse response = service.path("aPath").queryParam("param", "value").cookie(new Cookie("token", token))
.type(MediaType.APPLICATION_JSON)
.post(ClientResponse.class, form);
final String raw = response.getEntity(String.class);
System.out.println("Response " + raw);
I tried several approaches (like nesting another Form object), but I always get the same result: The server returns 400 - Bad Request ("The request sent by the client was syntactically incorrect (Bad Request).") I assume because the mandatory parameter items isn't sent correctly.
Does somebody know how I nest JSON data like described? I think it is a common case, but I found no examples in the web.
Form is essentially a Map that limits your values to Strings. What you need is a simple Map (e.g. a HashMap). Every nested element will also be a map. So you will have something like this.
Map<String, Object> data = new HashMap<String, Object>();
data.put("customer", "Someone");
data.put("date", "2013-09-12");
Map<String, Object> item1 = new HashMap<String, Object>();
item1.put("sequenceNo", 2);
item1.put("name", "foo");
data.put("items", Arrays.asList(item1));
This way you can do as much nesting as you need.
Alternatively you can create a few classes that represent your data structures. Jersey will know how to serialize it.
class Item {
String name;
int sequenceNo;
// getters & setters
}
class Data {
String customer;
String date;
List<Item> items;
// getters & setters
}