I'm currently working on my homework about client and server topic:
I created a class called VehileRequest.java which will take three variables (year, make, model) from Client.java and pass them to Server.java then the Server will get information from VehicleRespone.java and display the information about price, miles vv...
As I understand, the program didn't recognize the request that pass to the respond file.
I got stuck at passing the Request to Response so that the Response will understand. Any help please. thank you
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.ObjectMapper;
public class VehicleResponse {
private VehicleRequest request;
private int milesOnVehicle;
private int price;
private int numberOfSeats;
private int numberOfDoors;
private String[] options;
#JsonIgnore
private static final ObjectMapper objectMapper = new ObjectMapper();
public static String toJSON(VehicleResponse vehicle) throws Exception {
return objectMapper.writeValueAsString(vehicle);
}
public static VehicleResponse fromJSON(String input) throws Exception{
return objectMapper.readValue(input, VehicleResponse.class);
}
protected VehicleResponse() {}
public VehicleResponse(VehicleRequest request, int milesOnVehicle,int price, int numberOfSeats, int numberOfDoors,String[] options) {
this.request=request;
this.milesOnVehicle=milesOnVehicle;
this.price=price;
this.numberOfSeats=numberOfSeats;
this.numberOfDoors=numberOfDoors;
this.options=options;
}
#Override
public String toString() {
return String.format(
"Vehicle request:[miles=%d, price=%d, number of seats=%d,number of doors=%d, option='%s']",
milesOnVehicle,price,numberOfSeats,numberOfDoors,options);
}
public VehicleRequest getRequest() {return request;}
public int getMilesOnVehicle(){return milesOnVehicle;};
public int getPrice(){return price;}
public int getNumberOfDoors() {return numberOfDoors;}
public int getNumberOfSeats() {return numberOfSeats;}
public String[] getOptions() {return options;}
public void setRequest(VehicleRequest request) {
this.request = request;
}
public void setMilesOnVehicle(int milesOnVehicle) {
this.milesOnVehicle = milesOnVehicle;
}
public void setPrice(int price) {
this.price = price;
}
public void setNumberOfSeats(int numberOfSeats) {
this.numberOfSeats = numberOfSeats;
}
public void setNumberOfDoors(int numberOfDoors) {
this.numberOfDoors = numberOfDoors;
}
public void setOptions(String[] options) {
this.options = options;
}
}
Here is the VehicleRequest file
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.ObjectMapper;
public class VehicleRequest {
private int year;
private String make;
private String model;
#JsonIgnore
private static final ObjectMapper objectMapper = new ObjectMapper();
public static String toJSON(VehicleRequest vehicle) throws Exception {
return objectMapper.writeValueAsString(vehicle);
}
public static VehicleRequest fromJSON(String input) throws Exception{
return objectMapper.readValue(input, VehicleRequest.class);
}
protected VehicleRequest() {}
public VehicleRequest(int year, String make, String model) {
this.year = year;
this.make =make;
this.model=model;
}
#Override
public String toString() {
return String.format(
"Vehicle: [year=%d, make='%s', model='%s']",
year,make,model);
}
public int getYear() {
return year;
}
public String getMake(){return make;}
public String getModel(){return model;}
public void setYear(int year) {
this.year = year;
}
public void setMake(String make){
this.make=make;
}
public void setModel(String model){
this.model=model;
}
}
Here is the Server
public class Server {
private ServerSocket serverSocket;
private Socket clientSocket;
private PrintWriter out;
private BufferedReader in;
public void start(int port) throws Exception {
serverSocket = new ServerSocket(port);
clientSocket = serverSocket.accept();
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
VehicleRequest request = VehicleRequest.fromJSON(inputLine);
VehicleResponse response = new VehicleResponse(request,10000,12000,5,4, null);
out.println(VehicleResponse.toJSON(response));
}
}
public void stop() throws IOException {
in.close();
out.close();
clientSocket.close();
serverSocket.close();
}
public static void main(String[] args) {
Server server = new Server();
try {
server.start(4444);
server.stop();
} catch(Exception e) {
e.printStackTrace();
}
}
}
Here is the client
public class Client {
private Socket clientSocket;
private PrintWriter out;
private BufferedReader in;
public void startConnection(String ip, int port) throws IOException {
clientSocket = new Socket(ip, port);
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
}
public VehicleRequest sendRequest() throws Exception {
out.println(VehicleRequest.toJSON(new VehicleRequest(2008,"Honda","Civic")));
return VehicleRequest.fromJSON(in.readLine());
}
public void stopConnection() throws IOException {
in.close();
out.close();
clientSocket.close();
}
public static void main(String[] args) {
Client client = new Client();
try {
client.startConnection("127.0.0.1", 4444);
System.out.println(client.sendRequest().toString());
client.stopConnection();
} catch(Exception e) {
e.printStackTrace();
}
}
}
I got the result was
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "request" (class edu.sdccd.cisc191.template.VehicleRequest), not marked as ignorable (3 known properties: "model", "year", "make"])
at [Source: (String)"{"request":{"year":2008,"make":"Honda","model":"Civic"},"milesOnVehicle":10000,"price":12000,"numberOfSeats":5,"numberOfDoors":4,"options":null}"; line: 1, column: 13] (through reference chain: edu.sdccd.cisc191.template.VehicleRequest["request"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:61)
at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:855)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1212)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1604)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1582)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:299)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:156)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4482)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3434)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3402)
at edu.sdccd.cisc191.template.VehicleRequest.fromJSON(VehicleRequest.java:17)
at edu.sdccd.cisc191.template.Client.sendRequest(Client.java:32)
at edu.sdccd.cisc191.template.Client.main(Client.java:44)
}
In the line VehicleRequest.fromJSON(in.readLine()); you are trying to parse whatever it is the input, which seems to be:
{
"request":{
"year":2008,
"make":"Honda",
"model":"Civic"
},
"milesOnVehicle":10000,
"price":12000,
"numberOfSeats":5,
"numberOfDoors":4,
"options":null
}
However, you are expecting this to be parseable to VehicleRequest which is not possible because it contains only 3 parameters and not all that. Either you parse this as VehicleResponse as follows:
VehicleResponse.fromJSON(in.readLine());
Or you change the input to be something that can be parsed to VehicleRequest:
{
"year":2008,
"make":"Honda",
"model":"Civic"
}
If I am understanding your code correctly you are trying to make communication between Client and Server. In that case, you will need to change your Client code:
public class Client {
private Socket clientSocket;
private PrintWriter out;
private BufferedReader in;
public void startConnection(String ip, int port) throws IOException {
clientSocket = new Socket(ip, port);
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
}
public VehicleResponse sendRequest() throws Exception {
out.println(VehicleRequest.toJSON(new VehicleRequest(2008,"Honda","Civic")));
return VehicleResponse.fromJSON(in.readLine());
}
public void stopConnection() throws IOException {
in.close();
out.close();
clientSocket.close();
}
public static void main(String[] args) {
Client client = new Client();
try {
client.startConnection("127.0.0.1", 4444);
System.out.println(client.sendRequest().toString());
client.stopConnection();
} catch(Exception e) {
e.printStackTrace();
}
}
}
Although João Dias already solved your lapse by fixing the response-type, I would like to share some practical advice on JSON-conversion especially when implementing web-API facades like your Client / Server classes:
pure-functions with parameters make code more testable: send(request)
content-conversion (from/into formats, like JSON) is a (cross-cutting) separate concern: inject a reusable component like ObjectMapper into client and server (representation layer) to make your request/response classes format-independent
The resulting code might appeal to you as
more readable
easier to comprehend and debug
less coupled
easier to maintain and extend
Request to response: send as pure function
Usually the responsibility of a client is to send multiple different requests. So parameterize your send method.
Design issues
Before: No parameter but static hard-coded request. Thus not testable.
public VehicleRequest sendRequest() throws Exception {
out.println(VehicleRequest.toJSON(new VehicleRequest(2008,"Honda","Civic")));
return VehicleRequest.fromJSON(in.readLine());
}
Note: the method signature ...Request sendRequest() can be read like "output = produceInput()". This style of designing methods or functions is called pure function: it usually converts an input to a new output - it produces something, like a response.
Design issues:
Here no input can be given. The returned product or answer could be expected to be always the same. Wouldn't you like to ask different questions or send different requests. So that the expected answer depends on the given request.
Improve
After: Added parameter to make testable with different requests. Method name simplified.
public VehicleResponse send(VehicleRequest request) throws Exception {
out.println(VehicleRequest.toJSON(request));
return VehicleResponse.fromJSON(in.readLine());
}
This can be called in your main or in a test like response = client.send(new VehicleRequest(2008,"Honda","Civic")).
Object representation: JSON-conversion as separate-concern
There are some basic representation formats like String that are tightly coupled to each class. In Java this concern is inherited from Object class's methods toString() and for some wrapper-classes like Integer.valueOf(String s).
However more complex representations, especially REST- or HTTP-related like JSON, XML, HTML, but also binary formats are usually treated by a design principle called Separation of Concerns. Especially in web-applications (like your simplified client-server architecture) this leads to separate layers (best-practice):
Representation layer (concern of UI, Web, Communication) .. e.g. your Client / Server classes and Jackson's ObjectMapper handling JSON-conversion
Business layer (concern of Logic) .. e.g. your Vehicle.. classes
Persistence layer (concern of Storage, Database, etc.)
See these separate concerns illustrated as layers, e.g. in Wikipedia Multi-tier Architecture or in Robert C. Martin's Clean Architecture.
Design issues
The external dependency Jackson is duplicated part of your DTO-classes like ..Request and ..Response. So both depend on Jackson and JSON-format.
Before: Concern of representation layer is mixed into DTO-classes, which might change along with Business layer. Now they need to change with each format, the client can support, too (strong-coupling and 2 reasons to change).
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.ObjectMapper;
// ..
#JsonIgnore
private static final ObjectMapper objectMapper = new ObjectMapper();
// duplicated code, implemented similarly for both classes
public static String toJSON(VehicleRe.. vehicle) throws Exception {
return objectMapper.writeValueAsString(vehicle);
}
public static VehicleRe.. fromJSON(String input) throws Exception{
return objectMapper.readValue(input, VehicleRe.. .class);
}
Note: You could move this cross-cutting (used by many classes) concern into the client. This way, your (entity) classes stay independent from the format/mapping-framework and the client can be easily extended to support other formats (like XML) in the future.
Improve
After: In REST formats are concern of the representation layer. The client is responsible of content-negotiation and conversion.
class Client {
private final ObjectMapper mapper;
// Mapper can be injected as dependency, configurable from ouside
public Client(ObjectMapper mapper) {
this.mapper = mapper;
// optional remaining initialization, could add ip, port, etc.
}
public VehicleResponse send(VehicleRequest vehicle) throws Exception {
String request = objectMapper.writeValueAsString(vehicle); // to <textual-format>
out.println(request); // request as String (now JSON, future XML)
String response = in.readLine(); // request as String (now JSON, future XML)
return objectMapper.readValue(response); // from <textual-format>
}
}
This way you can in your main-method simply create a special XML-capable client by configuring like
Client xmlClient = new Client(new XmlMapper()) or use as-is (with JSON as content-exchange format): Client client = new Client(new ObjectMapper()).
For your CS-course and homework this might be too much and over-engineering.
However in "real code", as seen in professional web-frameworks like Spring, this is good or best-practice and contributes to extensible and maintainable software, see SOLID .
On my flink script I have a stream that I'm getting from one kafka topic, manipulate it and sending it back to kafka using the sink.
public static void main(String[] args) throws Exception {
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setParallelism(1);
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
Properties p = new Properties();
p.setProperty("bootstrap.servers", servers_ip_list);
p.setProperty("gropu.id", "Flink");
FlinkKafkaConsumer<Event_N> kafkaData_N =
new FlinkKafkaConsumer("CorID_0", new Ev_Des_Sch_N(), p);
WatermarkStrategy<Event_N> wmStrategy =
WatermarkStrategy
.<Event_N>forMonotonousTimestamps()
.withIdleness(Duration.ofMinutes(1))
.withTimestampAssigner((Event, timestamp) -> {
return Event.get_Time();
});
DataStream<Event_N> stream_N = env.addSource(
kafkaData_N.assignTimestampsAndWatermarks(wmStrategy));
The part above is working fine no problems at all, the part below instead is where I'm getting the issue.
String ProducerTopic = "CorID_0_f1";
DataStream<Stream_Blocker_Pojo.block> box_stream_p= stream_N
.keyBy((Event_N CorrID) -> CorrID.get_CorrID())
.map(new Stream_Blocker_Pojo());
FlinkKafkaProducer<Stream_Blocker_Pojo.block> myProducer = new FlinkKafkaProducer<>(
ProducerTopic,
new ObjSerializationSchema(ProducerTopic),
p,
FlinkKafkaProducer.Semantic.EXACTLY_ONCE); // fault-tolerance
box_stream_p.addSink(myProducer);
No errors everything works fine, this is the Stream_Blocker_Pojo where I'm mapping a stream manipulating it and sending out a new one.(I have simplify my code, just keeping 4 variables and removing all the math and data processing).
public class Stream_Blocker_Pojo extends RichMapFunction<Event_N, Stream_Blocker_Pojo.block>
{
public class block {
public Double block_id;
public Double block_var2 ;
public Double block_var3;
public Double block_var4;}
private transient ValueState<block> state_a;
#Override
public void open(Configuration parameters) throws Exception {
state_a = getRuntimeContext().getState(new ValueStateDescriptor<>("BoxState_a", block.class));
}
public block map(Event_N input) throws Exception {
p1.Stream_Blocker_Pojo.block current_a = state_a.value();
if (current_a == null) {
current_a = new p1.Stream_Blocker_Pojo.block();
current_a.block_id = 0.0;
current_a.block_var2 = 0.0;
current_a.block_var3 = 0.0;
current_a.block_var4 = 0.0;}
current_a.block_id = input.f_num_id;
current_a.block_var2 = input.f_num_2;
current_a.block_var3 = input.f_num_3;
current_a.tblock_var4 = input.f_num_4;
state_a.update(current_a);
return new block();
};
}
This is the implementation of the Kafka Serialization schema.
public class ObjSerializationSchema implements KafkaSerializationSchema<Stream_Blocker_Pojo.block>{
private String topic;
private ObjectMapper mapper;
public ObjSerializationSchema(String topic) {
super();
this.topic = topic;
}
#Override
public ProducerRecord<byte[], byte[]> serialize(Stream_Blocker_Pojo.block obj, Long timestamp) {
byte[] b = null;
if (mapper == null) {
mapper = new ObjectMapper();
}
try {
b= mapper.writeValueAsBytes(obj);
} catch (JsonProcessingException e) {
}
return new ProducerRecord<byte[], byte[]>(topic, b);
}
}
When I open the messages that i sent from my Flink script using kafka, I find that all the variables are "null"
CorrID b'{"block_id":null,"block_var1":null,"block_var2":null,"block_var3":null,"block_var4":null}
It looks like I'm sending out an empty obj with no values. But I'm struggling to understand what I'm doing wrong. I think that the problem could be into my implementation of the Stream_Blocker_Pojo or maybe into the ObjSerializationSchema, Any help would be really appreciated. Thanks
There are two probable issues here:
Are You sure the variable You are passing of type block doesn't have null fields? You may want to debug that part to be sure.
The reason may also be in ObjectMapper, You should have getters and setters available for Your block otherwise Jackson may not be able to access them.
I'm currently new to the Spring Boot Java framework and I'm building a simple application. When my service starts, I want to be able to read a raw file from a URL, parse that data, and upload it into my mongodb database of atlas. So far this is what I have:
#Service
public class CoronaVirusDataService {
private List<LocationStats> allConfirmedStats = new ArrayList<>();
MongoOperations mongoOperations;
#PostConstruct // run this method as soon as the application runs
#Scheduled(cron = "* * 1 * * *") // execute this method every day
public void fetchVirusData() {
List<LocationStats> newStats = new ArrayList<>(); // to hold the stats of each state
HttpClient client = HttpClient.newHttpClient();
// creating a new http request
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(ConstantsUtil.VIRUS_CONFIRMED_DATA_URL))
.build();
// get a response by having the client send the request
try {
HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString());
// parse the body of the request from csv format to readable format
StringReader csvBodyReader = new StringReader(httpResponse.body());
Iterable<CSVRecord> records = CSVFormat.DEFAULT.withFirstRecordAsHeader().parse(csvBodyReader);
for (CSVRecord record: records) {
// create a model with the parsed data
LocationStats stats = new LocationStats();
stats.setState(record.get("Province/State"));
stats.setCountry(record.get("Country/Region"));
// the latest day
int latestCases = Integer.parseInt(record.get(record.size() - 1));
int prevDayCases = Integer.parseInt(record.get(record.size() - 2));
stats.setLatestTotalCases(latestCases);
stats.setDiffFromPreviousDay(prevDayCases);
mongoOperations.save(LocationStats);
// add to new stats
newStats.add(stats);
}
// assign to class array -> we use this array to display the data
this.allConfirmedStats = newStats;
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
So the main issue with this is the data is not saving to the mongoDB once I call mongoOperations.save(). Also, I've learned that it is bad practice to maintain some type of state in a Service. What is the best practice for this? Will inserting the data into MongoDB take care of that since we are not managing state.
Here is my model class that I want to save to mongodb
#Document(collection = "LocationStats")
public class LocationStats {
/** Location model to show corona virus statistics in each state*/
#Id
private String state;
private String country;
private int latestTotalCases;
private int diffFromPreviousDay;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public int getLatestTotalCases() {
return latestTotalCases;
}
public void setLatestTotalCases(int latestTotalCases) {
this.latestTotalCases = latestTotalCases;
}
public int getDiffFromPreviousDay() {
return diffFromPreviousDay;
}
public void setDiffFromPreviousDay(int diffFromPreviousDay) {
this.diffFromPreviousDay = diffFromPreviousDay;
}
#Override
public String toString() {
return "LocationStats{" +
"state='" + state + '\'' +
", country='" + country + '\'' +
", latestTotalCases=" + latestTotalCases +
'}';
}
}
once I have my models saved into mongoDB, I want to read from the database and get all the data from each collection and display it on the webpage. I'm thinking I'd fetch that data within the controller class and pass it to the frontend, is this good practice? here is my controller class.
#Controller
public class HomeController {
/** Controller class to generate/render the html UI */
#Autowired
CoronaVirusDataService coronaVirusDataService;
#Autowired
MongoOperations mongoOperations;
#GetMapping("/") // map this to the root template
public String home(Model model) {
List<LocationStats> allStats = coronaVirusDataService.getAllConfirmedStats();
// instead of above getter method, have a method call that fetches all data from mongoDB and return it as a List<LocationStats>
// get the total confirmed cases
int totalConfirmedCases = allStats.stream().mapToInt(LocationStats::getLatestTotalCases).sum();
int totalNewCases = allStats.stream().mapToInt(LocationStats::getDiffFromPreviousDay).sum();
// send the models to the view
model.addAttribute("locationStats", allStats);
model.addAttribute("totalReportedCases", totalConfirmedCases);
model.addAttribute("totalNewCases", totalNewCases);
return "home";
}
}
I created app for getting info from upwork.com. I use java lib and Upwork OAuth 1.0. The problem is local request to API works fine, but when I do deploy to Google Cloud, my code does not work. I get ({"error":{"code":"503","message":"Exception: IOException"}}).
I create UpworkAuthClient for return OAuthClient and next it is used for requests in JobClient.
run() {
UpworkAuthClient upworkClient = new UpworkAuthClient();
upworkClient.setTokenWithSecret("USER TOKEN", "USER SECRET");
OAuthClient client = upworkClient.getOAuthClient();
//set query
JobQuery jobQuery = new JobQuery();
jobQuery.setQuery("query");
List<JobQuery> jobQueries = new ArrayList<>();
jobQueries.add(jobQuery);
// Get request of job
JobClient jobClient = new JobClient(client, jobQuery);
List<Job> result = jobClient.getJob();
}
public class UpworkAuthClient {
public static final String CONSUMERKEY = "UPWORK KEY";
public static final String CONSUMERSECRET = "UPWORK SECRET";
public static final String OAYTРCALLBACK = "https://my-app.com/main";
OAuthClient client ;
public UpworkAuthClient() {
Properties keys = new Properties();
keys.setProperty("consumerKey", CONSUMERKEY);
keys.setProperty("consumerSecret", CONSUMERSECRET);
Config config = new Config(keys);
client = new OAuthClient(config);
}
public void setTokenWithSecret (String token, String secret){
client.setTokenWithSecret(token, secret);
}
public OAuthClient getOAuthClient() {
return client;
}
public String getAuthorizationUrl() {
return this.client.getAuthorizationUrl(OAYTРCALLBACK);
}
}
public class JobClient {
private JobQuery jobQuery;
private Search jobs;
public JobClient(OAuthClient oAuthClient, JobQuery jobQuery) {
jobs = new Search(oAuthClient);
this.jobQuery = jobQuery;
}
public List<Job> getJob() throws JSONException {
JSONObject job = jobs.find(jobQuery.getQueryParam());
jobList = parseResponse(job);
return jobList;
}
}
Local dev server works fine, I get resilts on local machine, but in Cloud not.
I will be glad to any ideas, thanks!
{"error":{"code":"503","message":"Exception: IOException"}}
doesn't seem like a response return by Upwork API. Could you please provide the full response including the returned headers? So, we will take a more precise look into it.
I am trying to send my tests to testrail from selenium but im not using an assert to end the test, i just want it to pass if it runs to completion? Is this possible? Also is there any examples of how this working in the code? I currently have:
public class login_errors extends ConditionsWebDriverFactory {
public static String TEST_RUN_ID = "R1713";
public static String TESTRAIL_USERNAME = "f2009#hotmail.com";
public static String TESTRAIL_PASSWORD = "Password100";
public static String RAILS_ENGINE_URL = "https://testdec.testrail.com/";
public static final int TEST_CASE_PASSED_STATUS = 1;
public static final int TEST_CASE_FAILED_STATUS = 5;
#Test
public void login_errors() throws IOException, APIException {
Header header = new Header();
header.guest_select_login();
Pages.Login login = new Pages.Login();
login.login_with_empty_fields();
login.login_with_invalid_email();
login.email_or_password_incorrect();
login.login_open_and_close();
login_errors.addResultForTestCase("T65013",TEST_CASE_PASSED_STATUS," ");
}
public static void addResultForTestCase(String testCaseId, int status,
String error) throws IOException, APIException {
String testRunId = TEST_RUN_ID;
APIClient client = new APIClient(RAILS_ENGINE_URL);
client.setUser(TESTRAIL_USERNAME);
client.setPassword(TESTRAIL_PASSWORD);
Map data = new HashMap();
data.put("status_id", status);
data.put("comment", "Test Executed - Status updated automatically from Selenium test automation.");
client.sendPost("add_result_for_case/"+testRunId+"/"+testCaseId+"",data );
}
}
I am getting a 401 status from this code.
Simply place the addResultForTestCase method at the end of the run. Ensure the Test CASE is used rather than the run id. You are currently using the incorrect ID