I am creating integration testing using spring cloud contract. Everything's working fine from configuration until adding stubs jar to the project. Hence I found that the request not match despite having all params and headers same.
{
"url" : "/my-project/api/checkTransaction/id?id=ASDFGHJKL",
"absoluteUrl" : "http://127.0.0.1:8085/my-project/api/checkTransaction/id?id=ASDFGHJKL",
"method" : "GET",
"clientIp" : "127.0.0.1",
"headers" : {
"Accept" : "application/json",
"X-B3-ParentSpanId" : "6f922af45db72e2e",
"User-Agent" : "Java/1.8.0_111",
"Connection" : "keep-alive",
"Host" : "127.0.0.1:8085",
"X-Span-Name" : "http://my-project/api/checkTransaction/id",
"X-B3-SpanId" : "886d8cfcdeec47ca",
"X-B3-Sampled" : "0",
"X-B3-TraceId" : "6f922af45db72e2e",
"requestKey" : "RANDOM",
"defaultId" : "12345",
"baggage-requestKey" : "RANDOM",
"baggage-defaultId" : "12345",
"Content-Type" : "application/json",
"username" : "589e329c-1cf1-4eb5-b7bb-eaffdd266560"
},
"cookies" : { },
"browserProxyRequest" : false,
"loggedDate" : 1526541502499,
"bodyAsBase64" : "",
"body" : "",
"loggedDateString" : "2018-05-17T07:18:22Z",
"queryParams" : {
"id" : {
"key" : "id",
"values" : [ "ASDFGHJKL" ]
}
}
}
Closest match:
{
"urlPath" : "/api/checkTransaction/id",
"method" : "GET",
"headers" : {
"defaultId" : {
"equalTo" : "12345"
},
"username" : {
"matches" : "[\\p{L}]*"
},
"requestKey" : {
"equalTo" : "RANDOM"
},
"Content-Type" : {
"matches" : "application/json.*"
},
"Accept" : {
"matches" : "application/json.*"
}
},
"queryParameters" : {
"id" : {
"equalTo" : "ASDFGHJKL"
}
}
}
Here's the Test for API
#Test
public void checkId_Contract() throws Exception {
// given:
MockMvcRequestSpecification request = given()
.header("requestKey", "RANDOM")
.header("accept-language", "en")
.header("accept-encoding", "gzip")
.header("Content-Type", "application/json;charset=UTF-8");
// when:
ResponseOptions response = given().spec(request)
.queryParam("id","ASDFGHJKL")
.when().async()
.timeout(10000)
.get("/api/id/ASDFGHJKL/check");
// then:
assertThat(response.statusCode()).isEqualTo(200);
assertThat(response.header("Content-Type")).matches("application/json;charset=UTF-8.*");
// and:
DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
assertThatJson(parsedJson).field("['errors']").isNull();
assertThatJson(parsedJson).field("['message']").isEqualTo("Id not found");
assertThatJson(parsedJson).field("['value']").isNull();
assertThatJson(parsedJson).field("['code']").isEqualTo("ID_NOT_FOUND");
}
Here's the contract that being called by the API
Contract.make {
request {
method 'GET'
url('/api/checkTransaction/id') {
headers {
header 'defaultId' : '12345'
header 'username' : $(anyAlphaUnicode())
header 'requestKey' : 'RANDOM'
contentType('application/json')
accept('application/json')
}
queryParameters {
parameter 'id' : 'ASDFGHJKL'
}
}
}
response {
status 200
async()
fixedDelayMilliseconds(5000)
headers{
contentType('application/json')
}
body '''\
{
"code": "ID_NOT_FOUND",
"message": "ID not found",
"errors": null,
"value": null,
"success": false
}
'''
}
}
even when I delete the username from contract request, still getting the same error.
Do I need to create headers for X-B3-ParentSpanId, etc to make it match?
Your url within the request is wrong, it is missing my-project in it.
It should look like this:
Contract.make {
request {
method 'GET'
url('/my-project/api/checkTransaction/id') {
...
Related
I'm currently learning about Spring Boot and am undertaking a project where users can make posts, view those posts, etc.
A user's post(s) can be viewed via http://localhost:8080/users/{user_id}/posts and http://localhost:8080/users/{user_id}/posts/{post_id}
As a result I have the following UserPostController
#RestController
#RequestMapping("/users")
public class UserPostController {
#Autowired
private UserPostService postService;
#GetMapping("/{user_id}/posts")
public List<Post> retrieveUserPosts(#PathVariable int user_id) {
return postService.retrieveUserPostList(user_id);
}
#GetMapping("/{user_id}/posts/{post_id}")
public EntityModel<Post> retrieveUserPost(#PathVariable int user_id, #PathVariable int post_id) {
return postService.retrieveUserPost(user_id, post_id);
}
#PostMapping("/{user_id}/posts")
public ResponseEntity<Object> createUserPost(#PathVariable int user_id, #Valid #RequestBody Post post) {
return postService.saveUserPost(user_id, post);
}
}
Every request to the links work correctly. For example a GET request to http://localhost:8080/users/1/posts returns [{"id":1,"description":"This is a post"},{"id":2,"description":"This is another post"}], which is the expected action.
However, for some reason I am able to visit http://localhost:8080/posts which then returns a list of all posts:
{
"_embedded" : {
"posts" : [ {
"description" : "This is a post",
"_links" : {
"self" : {
"href" : "http://localhost:8080/posts/1"
},
"post" : {
"href" : "http://localhost:8080/posts/1"
},
"user" : {
"href" : "http://localhost:8080/posts/1/user"
}
}
}, {
"description" : "This another post",
"_links" : {
"self" : {
"href" : "http://localhost:8080/posts/2"
},
"post" : {
"href" : "http://localhost:8080/posts/2"
},
"user" : {
"href" : "http://localhost:8080/posts/2/user"
}
}
}, {
"description" : "This is yet another post",
"_links" : {
"self" : {
"href" : "http://localhost:8080/posts/3"
},
"post" : {
"href" : "http://localhost:8080/posts/3"
},
"user" : {
"href" : "http://localhost:8080/posts/3/user"
}
}
} ]
},
"_links" : {
"self" : {
"href" : "http://localhost:8080/posts"
},
"profile" : {
"href" : "http://localhost:8080/profile/posts"
}
},
"page" : {
"size" : 20,
"totalElements" : 3,
"totalPages" : 1,
"number" : 0
}
}
Through HATEOAS I am able to also see available links of the format http://localhost:8080/posts/{user_id}/user which I have also not created methods for, but they still exist.
Is there a reason why these unwanted routes exist? If so how do I change this?
Thank you :)
I am trying to send PUT request to the Zotero API, but I keep getting an error:
Caused by: org.springframework.web.client.HttpClientErrorException$BadRequest: 400 Bad Request: ['itemType' property not provided]
The JSON being sent is fine, so it is something with my code.
private void handleUpdateItemButton(ActionEvent event) throws IOException {
Properties props = restConnection.getAccessProperties();
ResponseEntity<JsonNode> res = restConnection.getRestTemplate().exchange(this.getItem(props, itemKey), new ParameterizedTypeReference<JsonNode>() {
});
if (res.getStatusCode() == HttpStatus.OK) {
JsonNode jsonNode = res.getBody();
printJSON(jsonNode);
JSONObject jsonObject = convertNodetoObject(jsonNode);
JSONObject jsonData = jsonObject.getJSONObject("data");
//jsonObject.getJSONObject("data").put("title", "This is the new title");
jsonData.put("title", "This is the new title");
ResponseEntity<JsonNode> updatedItem = restConnection.getRestTemplate().exchange(this.updateItem(props, jsonData, itemKey), new ParameterizedTypeReference<JsonNode>() {
});
}
else{
System.out.println("This item cannot be updated");
}
}
The method above then calls the method below
private RequestEntity updateItem(Properties props, JSONObject item, String itemKey) throws JsonProcessingException {
ResponseEntity<JsonNode> res = restConnection.getRestTemplate().exchange(this.getItem(props, itemKey), new ParameterizedTypeReference<JsonNode>() {
});
return RequestEntity
.put(restConnection.getZoteroBaseURL() + "/users/" + props.getProperty("username") + "/items/" + itemKey)
.header("Zotero-API-Version", "3")
.header("Zotero-API-Key", props.getProperty("key"))
.header("If-Unmodified-Since-Version", numberBody.get("version").toString())
.header("Content-Type", "application/json")
.body(item);
}
Not really sure what is wrong. I'd appreciate any help - zoter-dev said that the PUT request should work and it's something with my code. Thanks!
I'd suggest you take a good look at the Zotero Web API documentation.
If you examine the creating an item section you'll find what you need to pass in your API call in order for it to work:
[
{
"itemType" : "book",
"title" : "My Book",
"creators" : [
{
"creatorType":"author",
"firstName" : "Sam",
"lastName" : "McAuthor"
},
{
"creatorType":"editor",
"name" : "John T. Singlefield"
}
],
"tags" : [
{ "tag" : "awesome" },
{ "tag" : "rad", "type" : 1 }
],
"collections" : [
"BCDE3456", "CDEF4567"
],
"relations" : {
"owl:sameAs" : "http://zotero.org/groups/1/items/JKLM6543",
"dc:relation" : "http://zotero.org/groups/1/items/PQRS6789",
"dc:replaces" : "http://zotero.org/users/1/items/BCDE5432"
}
}
]
It's stated that All properties other than itemType, tags, collections, and relations are optional, meaning itemType is mandatory.
You must fill in these four properties, at least, if you want your call to succeed.
If you don't have any data for tags, collections or relations you could just pass empty property values:
{
"itemType" : "note",
"note" : "My sample note",
"tags" : [],
"collections" : [],
"relations" : {}
}
Please find my mapping query below for the filename field.
PUT /articles
{
"settings" : {
"analysis" : {
"analyzer" : {
"filename_search" : {
"tokenizer" : "filename",
"filter" : ["lowercase"]
},
"filename_index" : {
"tokenizer" : "filename",
"filter" : ["lowercase","edge_ngram"]
}
},
"tokenizer" : {
"filename" : {
"pattern" : "[^\\p{L}\\d]+",
"type" : "pattern"
}
},
"filter" : {
"edge_ngram" : {
"side" : "front",
"max_gram" : 50,
"min_gram" : 1,
"type" : "edgeNGram"
}
}
}
},
"mappings" : {
"doc" : {
"properties" : {
"filename" : {
"type" : "text",
"search_analyzer" : "filename_search",
"analyzer" : "filename_index"
}
}
}
}
}
If am trying to query series1333372 doc623258 and am expecting karthik_series1333372_oracle_page_doc623258_v1_en-EU.pdf. But it's giving all the files which is having series1333372, not even checking for doc623258.
Please find my query below
get articles/_search
{
"query" : {
"match" : {
"filename" : "series1333372 doc623258"
}
}
}
I am inserting the following sample documents for testing from Kibana
POST articles/doc/1
{
"filename" : "karthik_series1333372_oracle_page_doc623258_v1_en-EU.pdf"
}
POST articles/doc/2
{
"filename" : "karthik_series1333372_sun_page_doc658_v1_en-EU.pdf"
}
POST articles/doc/3
{
"filename" : "series1333372_oracle_page_doc623_v1_en-US.pdf"
}
POST articles/doc/4
{
"filename" : "Engineering series1333372 valve_page doc6232 v1_en-US.pdf"
}
POST articles/doc/5
{
"filename" : "Machines_series1333372_page_doc62258_v1_en-US.pdf"
}
POST articles/doc/6
{
"filename" : "AIX series1333372 IBM page doc62358 v1_en-EU.pdf"
}
The default operator of match is OR. If you want all your terms to be present change it like this
GET articles/_search
{
"query" : {
"match" : {
"filename" : {
"query": "series1333372 doc623258",
"operator" : "and"
}
}
}
}
We are using haschild query to find the parent documents based on the condition.
We have two types
funnels
pages
funnels sample doc
{
"funnel_id": "12345",
"path": "a -> b -> c"
}
{
"funnel_id": "56789",
"path": "a -> d"
}
** pages sample doc**
{
"_parent": "12345",
"visited_page": "/home"
}
{
"_parent": "12345",
"visited_page": "/cart"
}
{
"_parent": "12345",
"visited_page": "/cart"
}
Condition1:
Find parent doc based child doc "visited_page" value contains "home".
"must" : {
"has_child" : {
"query" : {
"regexp" : {
"url" : {
"value" : ".*home.*",
"flags_value" : 65535
}
}
},
"child_type" : "session_pages"
}
}
It works perfectly.
Condition2
Find parent doc based child doc "visited_page" value does NOT contains "home".
"must_not" : {
"has_child" : {
"query" : {
"regexp" : {
"url" : {
"value" : ".*home.*",
"flags_value" : 65535
}
}
},
"child_type" : "session_pages"
}
}
But this query returned wrong results.
Output of the query
{
"funnel_id": "12345",
"path": "a -> b -> c"
}
{
"funnel_id": "56789",
"path": "a -> d"
}
You can see the parent id(funnel_id:12345) child doc contains visited page with value "home". But that also returns.
Expected Result
{
"funnel_id": "56789",
"path": "a -> d"
}
I believe you are "must_not"ing in the wrong spot
try:
"must" : {
"has_child" : {
"query" : {
"regexp" : {
"url" : {
"must_not": {
"value" : ".*home.*"
},
"flags_value" : 65535
}
}
},
"child_type" : "session_pages"
}
}
How can i get any object id from Hal representation?
Exactly i want to get this from specific user from allUser list. There is example:
{
"_embedded" : {
"users" : [ {
"login" : "user1",
"firstName" : "Bolek",
"lastName" : "Kowal",
"email" : null,
"password" : null,
"gender" : null,
"birthDate" : null,
"_links" : {
"self" : {
"href" : "http://localhost:8080/games-organizer/api/users/1"
},
"user" : {
"href" : "http://localhost:8080/games-organizer/api/users/1"
},
"roles" : {
"href" : "http://localhost:8080/games-organizer/api/users/1/roles"
}
}
}, {
"login" : "user2",
"firstName" : "Lolek",
"lastName" : "Kowalski",
"email" : null,
"password" : null,
"gender" : null,
"birthDate" : null,
"_links" : {
"self" : {
"href" : "http://localhost:8080/games-organizer/api/users/2"
},
"user" : {
"href" : "http://localhost:8080/games-organizer/api/users/2"
},
"roles" : {
"href" : "http://localhost:8080/games-organizer/api/users/2/roles"
}
}
}
Eventually how can i delete specific user using rest spring api and angular/spring? I don't know how can i do this without having id from any user(object).
Update:
I want to use this id, in invoke some method like this:
$scope.$on('deleteUser', function (event, id) {
userService.delete({id: id}).$promise.then(
function () {
// Broadcast the event to refresh the grid.
$rootScope.$broadcast('refreshUserGrid');
// Broadcast the event to display a delete message.
$rootScope.$broadcast('userDeleted');
$scope.clearForm();
},
function () {
// Broadcast the event for a server error.
$rootScope.$broadcast('error');
});
});
I want to delete some record from database in springRestAPI.
Suppose you want to delete details of user2 then you can do this :
For (var i=0;i<allUser.users.length;i++){
if(allUser.users[i].login=="user2"){
allUser.users.splice(i-1,i);
}
}