I have Created two java classes TestA.java,TestB.java using restAssured where each of the class reads json from TestA.json and testB.json and post a request to endpoint uri.TestA.java returns a json response having tag "customerID" which will be input for one of the tags of TestB.json and when ever I post a request using "TestB.java" customerID has to be picked from TestB.json .How do my code look like?Any ideas?
My code :
TestA.java
String requestBody = generateString("CreateCustomer.json");
RestAssured.baseURI = "https://localhost:8080";
Response res = given().contentType(ContentType.JSON)
.header("Content-Type", "application/json").header("checkXML", "N").body(requestBody).when()
.post("/restservices/customerHierarchy/customers").then().assertThat()
.statusCode(201).and().body("transactionDetails.statusMessage", equalTo("Success")).and().log().all()
.extract().response();
//converts response to string
String respose = res.asString();
JsonPath jsonRes = new JsonPath(respose);
CustomerID = jsonRes.getString("customerNodeDetails.customerId");
TestA.java response
{
"customerNodeDetails": {
"customerId": "81263"
},
Now i want to pass this customerID as input in testB.json or testB.java which is dynamic.
TestB.json
"hierarchyNodeDetails": {
"**customerId**":"",
"accountNumber": "",
"startDate": "",
}
Both TestA.java and TestB.java looks almost same except the post uri
Thanks in Advance
It depends on how you are distributing your classes:
If you want to write the tests for A and B in a single class. Declare a local variable of type Response/String and then store the customer ID in that variable. The scope of the variable will be live in all TestNG methods. You can set the customer ID for the B.json from the local variable.
public class Test{
String _cust_id;
#Test
public void test_A(){
// ceremony for getting customer id
_cust_id = jsonRes.getString("customerNodeDetails.customerId");
}
#Test
public void test_B(){
// write value of customer id using the variable _cust_id
}}
You can try this approach, but would suggest separating the data part to a dataProvider class.
If you want to have separate classes for A and B, use ITestContext to pass values from one class to the other.
public class A{
#Test
public void test1(ITestContext context){
context.setAttribute("key", "value");
}
}
public class B{
#Test
public void test2(ITestContext context){
String _attribute = context.getAttribute(key);
}
}
The elegant way could be, use a dataProvider for class B test where you perform the ceremony of getting the customerID from class A Tests.
public class DataB{
#DataProvider
public static Object[][] _test_data_for_b(){
// get the customerID
// create the json for class B
// return the json required for class B test
// All these could be achieved as everything has a common scope
}}
public class B{
#Test(dataProvider = "_test_data_for_b", dataProviderClass = DataB.class)
public void test_B(String _obj){
// perform the testing
}}
Related
I am trying to check if the response from the API GET method is Null. The response is like
{
"#odata.context": "https://dev.com/data/$metadata#Customers",
"value": []
}
I need to check if the value array is null or not and do the necessary steps below is what I tried
public class deserializeData
{
public String #odata_context {get;set;} // in json: #odata.context
public List<Value> value {get;set;}
}
public class getDataFromExternalSystem{
public string getDataFrom(){
.......
Http http1 = new Http();
HttpRequest req1 = new HttpRequest();
req1.setEndpoint(endPoint);
req1.setMethod('GET');
req1.setHeader('Authorization','Bearer '+atoken);
HttpResponse res1 = http1.send(req1);
System.debug('Response Body=========' + res1.getBody());
deserializeData dsData = (deserializeData)JSON.deserialize(res1.getbody(),deserializeData.class);
if(dsData.value.size = null) {
......
}
else{
......
}}
But I get below error like
#odata_context is not a legal identifier in Apex. # is used to introduce annotations.
If you're using JSON2Apex, which appears to be the case, you'll need to change the name of the property to something legal for Apex (like odata_context), and make the corresponding change in the parser method. E.g., where JSON2Apex generates
if (text == '#odata.context') {
#odata_context = parser.getText();
you'll need to replace that identifier with the new one you choose.
I have a JAX-RS method that returns me a List with DO's. Unfortunetly when I go to the path which is mapped by the method i get only an empty json list like:
[{}, {}, {}]
My resource method looks like this:
#GET
#Produces("application/json")
public List<ModelDO> getModels() {
List<ModelDo> models = modelRepo.findAllModelsWithName("Name");
return models;
}
I'm 100% sure the objects exists and the list isn't empty, because I have checked it in the debugger.
The ModelDO class is a simple POJO:
public class ModelDO {
private int id;
private String name;
//public getters
}
What should I do to get an non empty json response?
PS. When I'm returning a single object I get the same problem -> {}
EDIT:
modelRepo:
public List<ModelDO> findAllModelsWithName(String name){
return new JPAQueryFactory(entityManager).selectFrom(modelEntity)
.where(modelEntity.name.eq(name))
.fetch();
}
ModelRepo.class is #Injected into my Resoure class
The reason was that my Model object did not have field setters, only getters.
First off my question is very similar to below however I'm not sure if the answers are applicable to my specific problem or whether I just need clarification about how to approach it:
Convert LinkedHashMap<String,String> to an object in Java
I am using struts2 json rest plugin to convert a json array into a java array. The array is sent through an ajax post request and the java receives this data. However instead of being the object type I expect it is received as a LinkedHashmap. Which is identical to the json request in structure.
[
{advance_Or_Premium=10000, available=true},
{advance_Or_Premium=10000, available=true},
{advance_Or_Premium=10000, available=true}
]
The data is all present and correct but just in the wrong type. Ideally I want to send the data in my object type or if this is not possible convert the LinkedHashMap from a list of keys and values into the object array. Here is the class I am using, incoming data is received in the create() method:
#Namespace(value = "/rest")
public class OptionRequestAction extends MadeAbstractAction implements ModelDriven<ArrayList<OptionRequestRest>>
{
private String id;
ArrayList<OptionRequestRest> model = new ArrayList<OptionRequestRest>();
public HttpHeaders create()
{
// TODO - need to use model here but it's a LinkedHashmap
return new DefaultHttpHeaders("create");
}
public String getId()
{
return this.id;
}
public ArrayList<OptionRequestRest> getModel()
{
return this.model;
}
public ArrayList<OptionRequestRest> getOptionRequests()
{
#SuppressWarnings("unchecked")
ArrayList<OptionRequestRest> lReturn = (ArrayList<OptionRequestRest>) this.getSession().get("optionRequest");
return lReturn;
}
// Handles /option-request GET requests
public HttpHeaders index()
{
this.model = this.getOptionRequests();
return new DefaultHttpHeaders("index").lastModified(new Date());
}
public void setId(String pId)
{
this.id = pId;
}
public void setModel(ArrayList<OptionRequestRest> pModel)
{
this.model = pModel;
}
// Handles /option-request/{id} GET requests
public HttpHeaders show()
{
this.model = this.getOptionRequests();
return new DefaultHttpHeaders("show").lastModified(new Date());
}
}
One of the things which is confusing me is that this code works fine and returns the correct object type if the model is not an array. Please let me know if my question is not clear enough and needs additional information. Thanks.
I am using JAX-RS (CXF) with JaxB and Jackson to provide a REST-API.
Unfortunately, none of the found results helps me with following (simple) problem:
I implemented following method:
#POST
#Path(ApiStatics.ARMY_CREATE_ARMY)
public com.empires.web.dto.Army createArmy(#FormParam("locationid") long locationId, #FormParam("name") String name, #FormParam("troops") ArmyTroops troops) {
and here are is my model class:
#XmlRootElement
#XmlSeeAlso(ArmyTroop.class)
public class ArmyTroops {
public ArmyTroops() {
}
public ArmyTroops(List<ArmyTroop> troops) {
this.troops = troops;
}
#XmlElement(name = "troops")
private List<ArmyTroop> troops = new ArrayList<ArmyTroop>();
public List<ArmyTroop> getTroops() {
return troops;
}
public void setTroops(List<ArmyTroop> troops) {
this.troops = troops;
}
}
ArmyTroop
#XmlRootElement(name = "troops")
public class ArmyTroop {
#XmlElement
private long troopId;
#XmlElement
private String amount;
public long getTroopId() {
return troopId;
}
public void setTroopId(long troopId) {
this.troopId = troopId;
}
public String getAmount() {
return amount;
}
public void setAmount(String amount) {
this.amount = amount;
}
}
My json that i send looks like this:
locationid 1
name asdasd
troops {"troops":[{"troopId":4,"amount":"5"},{"troopId":6,"amount":"5"}]}
Unfortunately, the object gets not transformed. Instead I receive this error:
InjectionUtils #reportServerError - Parameter Class com.empires.web.dto.in.ArmyTroops has no constructor with single String parameter, static valueOf(String) or fromString(String) methods
If I provide the constructor with a single string parameter, I get passed the whole json string for "troops" as mentioned above.
Any ideas why JaxB does not work at this point?
You are passing all your parameters with #Form annotation.
But the Form part of the http message must be an xml data structure.
Your 3 parameters don't have a main xml datastructure so it wont work.
In short, form params are send as body.
Cxf use the MultivaluedMap to send params (cxf have an xml model for this structure).
As you can see it is not fit for parameters that can't be trivally serialized.
Here me solution would be to drop the #FormParam to avoid the problem:
1) Use #PathParam #CookieParam to send yours first 2 parameters, and the 'no tag' (body) only for the army compositions.
2) Define an uber object that take all parameters and can be serialized as xml datastructure and use the 'no tag' (body) sending.
3) Use soap, with cxf it is really easy to gets both Rest and Soap.
I am having a deserialization problem using the GSON library.
The following is the JSON code which I try to deserialize
{"response": {
"#service": "CreateUser",
"#response-code": "100",
"#timestamp": "2010-11-27T15:52:43-08:00",
"#version": "1.0",
"error-message": "",
"responseData": {
"user-guid": "023804207971199"
}
}}
I create the following classes
public class GsonContainer {
private GsonResponse mResponse;
public GsonContainer() { }
//get & set methods
}
public class GsonResponse {
private String mService;
private String mResponseCode;
private String mTimeStamp;
private String mVersion;
private String mErrorMessage;
private GsonResponseCreateUser mResponseData;
public GsonResponse(){
}
//gets and sets method
}
public class GsonResponseCreateUser {
private String mUserGuid;
public GsonResponseCreateUser(){
}
//get and set methods
}
After calling the GSON library the data is null. Any ideas what is wrong with the classes?
Thx in advance for your help ... I assume it's something trivial ....
#user523392 said:
the member variables have to match exactly what is given in the JSON response
This is not the case.
There are a few options for specifying how Java field names map to JSON element names.
One solution that would work for the case in the original question above is to annotate the Java class members with the #SerializedName to very explicitly declare what JSON element name it maps to.
// output: [MyObject: element=value1, elementTwo=value2]
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.SerializedName;
public class Foo
{
static String jsonInput =
"{" +
"\"element\":\"value1\"," +
"\"#element-two\":\"value2\"" +
"}";
public static void main(String[] args)
{
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
MyObject object = gson.fromJson(jsonInput, MyObject.class);
System.out.println(object);
}
}
class MyObject
{
String element;
#SerializedName("#element-two")
String elementTwo;
#Override
public String toString()
{
return String.format(
"[MyObject: element=%s, elementTwo=%s]",
element, elementTwo);
}
}
Another approach is to create a custom FieldNamingStrategy to specify how Java member names are translated to JSON element names. This example would apply the same name mapping to all Java member names. This approach would not work for the original example above, because not all of the JSON element names follow the same naming pattern -- they don't all start with '#' and some use camel case naming instead of separating name parts with '-'. An instance of this FieldNamingStrategy would be used when building the Gson instance (gsonBuilder.setFieldNamingStrategy(new MyFieldNamingStrategy());).
class MyFieldNamingStrategy implements FieldNamingStrategy
{
// Translates the field name into its JSON field name representation.
#Override
public String translateName(Field field)
{
String name = field.getName();
StringBuilder translation = new StringBuilder();
translation.append('#');
for (int i = 0, length = name.length(); i < length; i++)
{
char c = name.charAt(i);
if (Character.isUpperCase(c))
{
translation.append('-');
c = Character.toLowerCase(c);
}
translation.append(c);
}
return translation.toString();
}
}
Another approach to manage how Java field names map to JSON element names is to specify a FieldNamingPolicy when building the Gson instance, e.g., gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES);. This also would not work with the original example, however, since it applies the same name mapping policy to all situations.
The JSON response above cannot be deserialized by GSON because of the special characters # and -. GSON is based on reflections and the member variables have to match exactly what is given in the JSON response.