Consuming REST Service in Spring - spring

I'm frightfully new to Spring and Java but I'm trying to consume some code for some rule validations in Easy Rules but I can't quite figure it out.
#RequestMapping(method = {RequestMethod.GET}, value = "author/field", produces= MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody ResponseEntity<Enum> getField(#RequestParam(value="field", required=true) String field){
Enum enum = mongoService.findByField(field);
if(enum == null){
return new ResponseEntity<Enum>(HttpStatus.NO_CONTENT);
}else{
return new ResponseEntity<Enum>(enum,HttpStatus.OK);
}
}
So I'm trying something like:
import com.mongoservice.Enum
import com.mongoservice.Enums
RestTemplate restTemplate = new RestTemplate();
String uri = "http://localhost:9000";
//This is my confusion
List<Enums> response = restTemplate.getForObject(uri +
"/author/field?={field}", Enum.class,"a").getEnums();
String value = response.getValue().toString().trim();
//this is the record i'm checking against that is pulling a specific string value and what i'm expecting
String record = "a";
return (value == record);
The JSON data I'm trying to pull back is modeled like this but I need to validate to make sure that record equals one of the values from enums[] json array
{
"field": "a",
"descriptor": "blah",
"enums": [
{
"value": "h",
"description": "blah"
},
{
"value": "e",
"description": "blah"
},
{
"value": "l",
"description": "blah"
},
{
"value": "p",
"description": "blah"
}
]
}

What is the problem that you are seeing is it just not matching? If so it could be because you are using == instead of String.equals. Try modifying your code to:
return record.equals(value);
See Java String.equals versus == for more.

Can you change String uri = "http://localhost:9000"
and missed the path variable name field it should be like author/field?field={field} as per your controller description.

Related

JGraphT: How to use JSONImporter to Import my DirectedMultigraph with Labeled Edges

I have created a custom edge class as defined here. The only change I made was a No Arg constructor in order to get the import code below to run. I have successfully generated a DirectedMultigraph via the JSONExporter class and now want to take that exported JSON and re-import it via the JSONImporter class.
I'm having trouble doing this and retaining my edge labels due to my limited understanding of how to build the EdgeProvider required for my JSONImporter constructor.
This is the JSON I'm trying to import:
{
"edges": [
{
"id": "{shipmentNumber:12345}",
"source": "DEHAM",
"target": "USNYC"
}
],
"nodes": [
{
"id": "DEHAM"
},
{
"id": "USNYC"
}
],
"creator": "JGraphT JSON Exporter",
"version": "1"
}
This is the code that I have so far:
Graph<String, RelationshipEdge> graph = new DirectedMultigraph<>(SupplierUtil.createStringSupplier(), SupplierUtil.createSupplier(RelationshipEdge.class), false);
VertexProvider<String> vertexProvider = (label, attributes) -> label;
EdgeProvider<String, RelationshipEdge> edgeProvider =
(from, to, label, attributes) -> graph.getEdgeSupplier().get();
JSONImporter<String, RelationshipEdge> importer = new JSONImporter<>(vertexProvider, edgeProvider);
importer.importGraph(graph, new StringReader([inputJSON]);
I know the problem is the EdgeProvider assignment because I don't know how to pass the argument constructor for the RelationshipEdge class which is where the actual label is set. If I could figure out how to call the argument constructor of the RelationshipEdge class then I think that would solve my problem.
FYI, this is my JSONExporter Code:
ComponentNameProvider<String> vertexIdProvider = name -> name;
ComponentNameProvider<RelationshipEdge> edgeLabelProvider = component -> component.getLabel();
ComponentAttributeProvider<String> vertexAttributeProvider = component -> new HashMap<>();
ComponentAttributeProvider<RelationshipEdge> edgeAttributeProvider = component -> new HashMap<>();
GraphExporter<String, RelationshipEdge> jsonExporter = new JSONExporter<>(vertexIdProvider, vertexAttributeProvider, edgeLabelProvider, edgeAttributeProvider);
StringWriter writer = new StringWriter();
jsonExporter.exportGraph(graph, writer);
System.out.println(writer.toString());
The following JSON is exported (with the label/id missing):
{
"creator": "JGraphT JSON Exporter",
"version": "1",
"nodes": [
{
"id": "DEHAM"
},
{
"id": "USNYC"
}
],
"edges": [
{
"source": "DEHAM",
"target": "USNYC"
}
]
}
Since your graph is using the SupplierUtil factory methods, the graph importer will use no-arg constructors as it visits/parses the json file, iterates over all the nodes/edges in the file and creates instances for them. In order to set your node/edge attributes during import you need to provide appropriate Vertex/Edge Attribute Consumers to the importer. Additionally, your node/edge classes need methods to access/modify their attributes:
JSONImporter<String, RelationshipEdge> importer = new JSONImporter<>(vertexProvider, edgeProvider);
importer.addEdgeAttributeConsumer((edgeField, value) -> {
// edgeField: Pair<Edge, String> / Edge instance, field name
// value: instance of org.jgrapht.nio.Attribute / getValue(); getType();
RelationshipEdge = edgeField.getFirst();
e.setLabel(value.getValue()); // Note that since you only have one field I am not finding the
// correct setter. I don't like reflection so I would probably
// add a 'setField(name, value)' method to my edge/node implementation.
});
To persist your graph, the idea is the same. But in this case you need Vertex/Edge AttributeProviders (You added them but they always returned empty maps):
GraphExporter<String, RelationshipEdge> jsonExporter = new JSONExporter<>();
exporter.setEdgeAttributeProvider(e -> {
Map<String, Attribute> attribs = new HashMap<>();
attribs.put("label", new DefaultAttribute<String>(e.getLabel(), AttributeType.STRING));
return attribs;
});

How to remove unwanted keys from rest-assured response object and assert remaining object data with constant variable having json string using java

In rest-assured test cases I am getting response as mentioned, where I want to remove keys such as "updated_at", "deleted_at", "created_at" and "notice" and then assert this response object with expected json string constant which contains 'settings'
{
"notice": "The Settings are updated successfully.",
"settings": {
"push_notification": {
"enabled": true,
"credentials": [{
"key": "value"
}],
"service_name": "API Testing"
},
"created_at": "2019-05-04T14:52:32.773Z",
"deleted_at": "false",
"updated_at": "2019-05-07T11:23:22.781Z"
}
}
For given response the expected json string is...
public static String SETTING_EXPECTED = "{\"push_notification\": {\"enabled\": true, \"credentials\": [{\"key\": \"value\"}], \"service_name\": \"API Testing\"}}"
Please help me with creating a common method using java which can be reuse for response assertions in all the test cases.
To delete keys from response you can use below code I am using jayway jsonpath library, you need to pass Json Response and field name jsonPath, in case your it will be "$.settings.created_at" :
public String deleteFieldNameFromResponse(String jsonResponse, String fieldToDelete)
throws ParseException, FileNotFoundException, IOException {
Object obj = null;
JSONParser parser = new JSONParser();
JsonPath jsonPath = null;
DocumentContext docCtx = null;
obj = parser.parse(jsonResponse);
docCtx = JsonPath.parse(obj);
docCtx.delete(fieldToDelete);
jsonPath = JsonPath.compile("$");
return docCtx.read(jsonPath).toString();
}

Spring ModelAndView to RestController json response

I have a legacy spring code where they use ModelAndView and they add the objects to it as below.
ModelAndView result = new ModelAndView();
result.addObject("folders", folders);
return result;
for the above i am getting response as
{
"folders": [
{
"recordCount": 0,
"folderContentType": "Reports",
"folderId": 34,
},
{
"recordCount": 2,
"folderContentType": "SharedReports",
"folderId": 88,
}
]
}
I have changed these to use Spring's RestController with a POJO backing the results returned from DB.
#GetMapping("/folders")
public List<Folder> getAllFolders() {
return Service.findAllFolders(1,2);
}
This returns a JSON as below
[
{
"folderId": 359056,
"folderName": "BE Shared Report Inbox",
"folderDescription": "BE Shared Report Inbox",
},
{
"folderId": 359057,
"folderName": "BE Shared Spec Inbox",
}]
How could i return this as exactly as my legacy code response. I know i can convert the List to Map and display. But, is there any equivalent
way.
Thanks.
You can put your result into a map.
#GetMapping("/folders")
public List<Folder> getAllFolders() {
return Service.findAllFolders(1,2);
}
Change to:
#GetMapping("/folders")
public Map<String,List<Folder>> getAllFolders() {
Map<String,List<Folder>> map = new HashMap<>();
map.put("folders",Service.findAllFolders(1,2));
return map;
}

Passing multiple parameters to web API GET method

I have created a WEB API using MySQL Database. The API works as expected for now. I sent a meter serial number and a date time parameter and then GET the expected result. Below is my controller
public MDCEntities medEntitites = new MDCEntities();
public HttpResponseMessage GetByMsn(string msn, DateTime dt)
{
try
{
var before = dt.AddMinutes(-5);
var after = dt.AddMinutes(5);
var result = medEntitites.tj_xhqd
.Where(m =>
m.zdjh == msn &&
m.sjsj >= before &&
m.sjsj <= after).Select(m => new { MSN = m.zdjh, DateTime = m.sjsj, Signal_Strength = m.xhqd }).Distinct();
return Request.CreateResponse(HttpStatusCode.Found, result);
}
catch (Exception ex)
{
return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
}
}
Below is my WebApiConfig file
config.Routes.MapHttpRoute(
name: "GetByMsn",
routeTemplate: "api/{controller}/{action}/{msn}/{dt}",
defaults: null,
constraints: new { msn = #"^[0-9]+$" , dt = #"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$" }
);
The URL is http://localhost:14909/api/meters/GetByMsn/002999000171/2017-10-10T10:08:20
The response I GET is
[{
"MSN": "002999000171",
"DateTime": "2017-10-10T10:04:39",
"Signal_Strength": "20"
},
{
"MSN": "002999000171",
"DateTime": "2017-10-10T10:06:35",
"Signal_Strength": "19"
},
{
"MSN": "002999000171",
"DateTime": "2017-10-10T10:08:31",
"Signal_Strength": "20"
},
{
"MSN": "002999000171",
"DateTime": "2017-10-10T10:10:27",
"Signal_Strength": "20"
},
{
"MSN": "002999000171",
"DateTime": "2017-10-10T10:12:23",
"Signal_Strength": "20"
}]
This all scenario works when a single serial number is passed. But at client side there would be more than one different serial numbers. For this I had to make my method to work both for one and more than one serial numbers provided the date time will be the same for all.
One solution is to create a new method a pass the multiple serial number strings, but this will not help because the number of serial numbers are dynamic i.e. they may be one, two to 100's. So setting a hard coded method won't be a solution.
I have searched for it but most of the times I have found the static method again and again. But this solution looks some what helpful but again I don't know whether it will work or not.
Any help would be highly appreciated.
You can pass a custom model to an action method, but I suggest not using the GET for you task because GET does not have a body.
Instead, use the SEARCH verb and put the list of serials number and the date inside a custom model in the body.
public class MeterSearchModel
{
public List<string> Serials {get;set;}
public DateTime Date {get;set;}
}
In .NET Core 2 your controller would have something like -
[AcceptVerbs("SEARCH")]
public async Task<IActionResult> Search([FromBody] MeterSearchModel model)
{
//..perform search
}

How do i send JsonObject with nested values as Post request in REST assured

I am using rest assured -https://code.google.com/p/rest-assured/wiki/Usage
My JsonObject looks like this
{
"id": "12",
"employeeInfo": null,
"employerInfo": null,
"checkDate": 1395093997218,
"netAmount": {
"amount": 70,
"currency": "USD"
},
"moneyDistributionLineItems": [
{
"mAmount": 100,
"employeeBankAccountId": "BankAccount 1"
}
],
}
how can i send this as part of parameters using REST-assured POST?
I have tried
given().param("key1", "value1").param("key2", "value2").when().post("/somewhere").then().
body(containsString("OK"));
but that is not scalable for HUGE objects with nested values. Is there a better approach?
You just send the JSON document in the body. For example if you have your JSON document in a String called myJson then you can just do like this:
String myJson = ..
given().contentType(JSON).body(myJson).when().post("/somewhere"). ..
You can also use a POJO, input stream and byte[] instead of a String.
URL file = Resources.getResource("PublishFlag_False_Req.json");
String myJson = Resources.toString(file, Charsets.UTF_8);
Response responsedata = given().header("Authorization", AuthorizationValue)
.header("X-App-Client-Id", XappClintIDvalue)
.contentType("application/vnd.api+json")
.body(myJson)
.with()
.when()
.post(dataPostUrl);

Resources