I'm trying to make a Client Library with WebClient from Spring WebFlux.
Server return responses like this JSON:
{
"result": [
{
"parent": "",
"made_sla": "true",
"watch_list": "",
"upon_reject": "cancel",
"sys_updated_on": "2016-01-19 04:52:04",
"approval_history": "",
"number": "PRB0000050",
"sys_updated_by": "glide.maint",
"opened_by": {
"link": "https://instance.service-now.com/api/now/table/sys_user/glide.maint",
"value": "glide.maint"
},
"user_input": "",
"sys_created_on": "2016-01-19 04:51:19",
"sys_domain": {
"link": "https://instance.service-now.com/api/now/table/sys_user_group/global",
"value": "global"
},
"state": "4",
"sys_created_by": "glide.maint",
"knowledge": "false",
"order": "",
"closed_at": "2016-01-19 04:52:04",
"cmdb_ci": {
"link": "https://instance.service-now.com/api/now/table/cmdb_ci/55b35562c0a8010e01cff22378e0aea9",
"value": "55b35562c0a8010e01cff22378e0aea9"
},
"delivery_plan": "",
"impact": "3",
"active": "false",
"work_notes_list": "",
"business_service": "",
"priority": "4",
"sys_domain_path": "/",
"time_worked": "",
"expected_start": "",
"rejection_goto": "",
"opened_at": "2016-01-19 04:49:47",
"business_duration": "1970-01-01 00:00:00",
"group_list": "",
"work_end": "",
"approval_set": "",
"wf_activity": "",
"work_notes": "",
"short_description": "Switch occasionally drops connections",
"correlation_display": "",
"delivery_task": "",
"work_start": "",
"assignment_group": "",
"additional_assignee_list": "",
"description": "Switch occasionally drops connections",
"calendar_duration": "1970-01-01 00:02:17",
"close_notes": "updated firmware",
"sys_class_name": "problem",
"closed_by": "",
"follow_up": "",
"sys_id": "04ce72c9c0a8016600b5b7f75ac67b5b",
"contact_type": "phone",
"urgency": "3",
"company": "",
"reassignment_count": "",
"activity_due": "",
"assigned_to": "",
"comments": "",
"approval": "not requested",
"sla_due": "",
"comments_and_work_notes": "",
"due_date": "",
"sys_mod_count": "1",
"sys_tags": "",
"escalation": "0",
"upon_approval": "proceed",
"correlation_id": "",
"location": ""
},
{
"parent": "",
"made_sla": "true",
"watch_list": "",
"upon_reject": "cancel",
"sys_updated_on": "2016-01-19 04:52:04",
"approval_history": "",
"number": "PRB0000050",
"sys_updated_by": "glide.maint",
"opened_by": {
"link": "https://instance.service-now.com/api/now/table/sys_user/glide.maint",
"value": "glide.maint"
},
"user_input": "",
"sys_created_on": "2016-01-19 04:51:19",
"sys_domain": {
"link": "https://instance.service-now.com/api/now/table/sys_user_group/global",
"value": "global"
},
"state": "4",
"sys_created_by": "glide.maint",
"knowledge": "false",
"order": "",
"closed_at": "2016-01-19 04:52:04",
"cmdb_ci": {
"link": "https://instance.service-now.com/api/now/table/cmdb_ci/55b35562c0a8010e01cff22378e0aea9",
"value": "55b35562c0a8010e01cff22378e0aea9"
},
"delivery_plan": "",
"impact": "3",
"active": "false",
"work_notes_list": "",
"business_service": "",
"priority": "4",
"sys_domain_path": "/",
"time_worked": "",
"expected_start": "",
"rejection_goto": "",
"opened_at": "2016-01-19 04:49:47",
"business_duration": "1970-01-01 00:00:00",
"group_list": "",
"work_end": "",
"approval_set": "",
"wf_activity": "",
"work_notes": "",
"short_description": "Switch occasionally drops connections",
"correlation_display": "",
"delivery_task": "",
"work_start": "",
"assignment_group": "",
"additional_assignee_list": "",
"description": "Switch occasionally drops connections",
"calendar_duration": "1970-01-01 00:02:17",
"close_notes": "updated firmware",
"sys_class_name": "problem",
"closed_by": "",
"follow_up": "",
"sys_id": "04ce72c9c0a8016600b5b7f75ac67b5b",
"contact_type": "phone",
"urgency": "3",
"company": "",
"reassignment_count": "",
"activity_due": "",
"assigned_to": "",
"comments": "",
"approval": "not requested",
"sla_due": "",
"comments_and_work_notes": "",
"due_date": "",
"sys_mod_count": "1",
"sys_tags": "",
"escalation": "0",
"upon_approval": "proceed",
"correlation_id": "",
"location": ""
},
{
"parent": "",
"made_sla": "true",
"watch_list": "",
"upon_reject": "cancel",
"sys_updated_on": "2016-01-19 04:52:04",
"approval_history": "",
"number": "PRB0000050",
"sys_updated_by": "glide.maint",
"opened_by": {
"link": "https://instance.service-now.com/api/now/table/sys_user/glide.maint",
"value": "glide.maint"
},
"user_input": "",
"sys_created_on": "2016-01-19 04:51:19",
"sys_domain": {
"link": "https://instance.service-now.com/api/now/table/sys_user_group/global",
"value": "global"
},
"state": "4",
"sys_created_by": "glide.maint",
"knowledge": "false",
"order": "",
"closed_at": "2016-01-19 04:52:04",
"cmdb_ci": {
"link": "https://instance.service-now.com/api/now/table/cmdb_ci/55b35562c0a8010e01cff22378e0aea9",
"value": "55b35562c0a8010e01cff22378e0aea9"
},
"delivery_plan": "",
"impact": "3",
"active": "false",
"work_notes_list": "",
"business_service": "",
"priority": "4",
"sys_domain_path": "/",
"time_worked": "",
"expected_start": "",
"rejection_goto": "",
"opened_at": "2016-01-19 04:49:47",
"business_duration": "1970-01-01 00:00:00",
"group_list": "",
"work_end": "",
"approval_set": "",
"wf_activity": "",
"work_notes": "",
"short_description": "Switch occasionally drops connections",
"correlation_display": "",
"delivery_task": "",
"work_start": "",
"assignment_group": "",
"additional_assignee_list": "",
"description": "Switch occasionally drops connections",
"calendar_duration": "1970-01-01 00:02:17",
"close_notes": "updated firmware",
"sys_class_name": "problem",
"closed_by": "",
"follow_up": "",
"sys_id": "04ce72c9c0a8016600b5b7f75ac67b5b",
"contact_type": "phone",
"urgency": "3",
"company": "",
"reassignment_count": "",
"activity_due": "",
"assigned_to": "",
"comments": "",
"approval": "not requested",
"sla_due": "",
"comments_and_work_notes": "",
"due_date": "",
"sys_mod_count": "1",
"sys_tags": "",
"escalation": "0",
"upon_approval": "proceed",
"correlation_id": "",
"location": ""
}
]
}
result field contains array of elements, and that elements can be different depending from API consumed.
For more info about that API is Table API from ServiceNow Product.
As you can see on documentation, API path is something like this: GET /now/table/{tableName}, where tableName could be different values and result elements tipology will depend from table fetched.
So the response elements inside result field can be formed with different name or different quantity of attributes. Basically it's a database exposed through HTTP, so every table could be formed with different number of columns.
My GET Implementation:
public Mono<Result> get(){
return client.get()
.uri(uriBuilder -> uriBuilder
.path(this.tablePath)
.queryParam("active", "true")
.queryParam("state", "1")
.build())
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(Result.class);
}
POJOs
@Data
public class ProjectTask {
private String project;
}
@Data
public class Result <T> {
List<T> result;
}
Simple Usage to get the error:
List<ProjectTask> projectTasks = Objects.requireNonNull(
client.table("pm_project_task")
.get().block())
.getResult();
for (ProjectTask task : projectTasks){
System.out.println("========PROJECT=============== "+task.getProject());
}
My runtime error at line for (ProjectTask task : projectTasks){
java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to my.namespace.api.services.servicenow.model.ProjectTask
Response Needs:
- Result POJO has to use Generic Type to manage different response elements type.
- If first point cannot be accomplished try to give a solution to fetch that API with a reusable GET implementation for different table types.
- I don't want to return a List from my client, my idea is that this library only return Mono or Flux objects.