From e5a672faaa6e0061f9dffc5fcbacbf2082dc2818 Mon Sep 17 00:00:00 2001 From: Valdas Petrulis Date: Fri, 10 Mar 2017 14:59:51 +0200 Subject: [PATCH 1/3] Get process/task variables --- client_interface.go | 5 +++ rest/client_rest.go | 79 ++++++++++++++++++++++++----------- rest/dto/variable_response.go | 37 ++++++++++++++++ 3 files changed, 97 insertions(+), 24 deletions(-) create mode 100644 rest/dto/variable_response.go diff --git a/client_interface.go b/client_interface.go index 14ba72a..156b2af 100644 --- a/client_interface.go +++ b/client_interface.go @@ -3,9 +3,11 @@ package go_camunda_client type CamundaClient interface { StartProcess(processDefinitionKey string, request interface{}) (Process, error) GetProcess(processId string) (Process, error) + GetProcessVariable(processId string, variableName string) (VariableResponse, error) GetNextTask(processId string) (Task, error) GetAllTasks(processId string) ([]Task, error) CompleteTask(taskId string, request interface{}) (error) + GetTaskVariable(taskId string, variableName string) (VariableResponse, error) HandleErrors(errorCallback func(error)) } @@ -20,3 +22,6 @@ type Task interface { GetTaskDefinitionKey() string } +type VariableResponse interface { + GetValue() string +} \ No newline at end of file diff --git a/rest/client_rest.go b/rest/client_rest.go index 6bc7b92..4e5b81d 100644 --- a/rest/client_rest.go +++ b/rest/client_rest.go @@ -11,7 +11,10 @@ import ( "net/http" ) -func Construct(urlRoot string, username string, password string, httpClient http.Client) go_camunda_client.CamundaClient { +func Construct( + urlRoot string, username string, password string, + httpClient http.Client, +) go_camunda_client.CamundaClient { client := new(camundaClientRest) client.urlRoot = urlRoot client.authUsername = username @@ -21,7 +24,9 @@ func Construct(urlRoot string, username string, password string, httpClient http return client } -func (client *camundaClientRest) StartProcess(processDefinitionKey string, request interface{}) (go_camunda_client.Process, error) { +func (client *camundaClientRest) StartProcess(processDefinitionKey string, request interface{}) ( + go_camunda_client.Process, error, +) { var process dto.Process response, err := client.doRequest("POST", "process-definition/key/" + processDefinitionKey + "/start", request) @@ -45,6 +50,12 @@ func (client *camundaClientRest) GetProcess(processId string) (go_camunda_client return process, err } +func (client *camundaClientRest) GetProcessVariable(processId string, variableName string) ( + go_camunda_client.VariableResponse, error, +) { + return doVariableRequest(client, "process-instance/" + processId + "/variables/" + variableName) +} + func (client camundaClientRest) GetNextTask(processId string) (go_camunda_client.Task, error) { tasks, err := client.GetAllTasks(processId) if len(tasks) >= 1 { @@ -69,11 +80,19 @@ func (client camundaClientRest) GetAllTasks(processId string) ([]go_camunda_clie } return tasks, err } + func (client camundaClientRest) CompleteTask(taskId string, request interface{}) (error) { _, err := client.doRequest("POST", "task/" + taskId + "/complete", request) return err } +func (client *camundaClientRest) GetTaskVariable(taskId string, variableName string) ( + go_camunda_client.VariableResponse, + error, +) { + return doVariableRequest(client, "task/" + taskId + "/variables/" + variableName) +} + func (client *camundaClientRest) HandleErrors(errorCallback func(error)) { client.errorCallbacks = append(client.errorCallbacks, errorCallback) } @@ -92,6 +111,28 @@ type camundaClientRest struct { errorCallbacks []func(error) } +func (client *camundaClientRest) constructRequest(method, path string, payload interface{})(*http.Request, error) { + var request *http.Request; + var err error; + url := client.urlRoot + "/" + path + + if payload == nil { + request, err = http.NewRequest(method, url, nil) + } else { + var payloadJson []byte; + payloadJson, err = json.Marshal(payload) + if err != nil { + client.notifyErrorHandlers(err) + return nil, err + } + request, err = http.NewRequest(method, url, bytes.NewBuffer(payloadJson)) + } + + request.Header.Set("Content-Type", "application/json") + request.SetBasicAuth(client.authUsername, client.authPassword) + return request, err +} + func (client *camundaClientRest) doRequest(method, path string, payload interface{}) (*http.Response, error) { request, err := client.constructRequest(method, path, payload) @@ -115,6 +156,18 @@ func (client *camundaClientRest) doRequest(method, path string, payload interfac return response, nil } +func doVariableRequest(client *camundaClientRest, path string) (dto.VariableResponse, error) { + var variableResponse dto.VariableResponse + + response, err := client.doRequest("GET", path + "/?deserializeValue=false", nil) + if err == nil { + err = client.parseResponseJson(response, &variableResponse) + defer response.Body.Close() + } + + return variableResponse, err +} + func (client *camundaClientRest) parseResponseError(response *http.Response) error { contentType := response.Header.Get("Content-Type") if contentType == "application/json" { @@ -141,26 +194,4 @@ func (client *camundaClientRest) parseResponseJson(response *http.Response, dto } return nil -} - -func (client *camundaClientRest) constructRequest(method, path string, payload interface{})(*http.Request, error) { - var request *http.Request; - var err error; - url := client.urlRoot + "/" + path - - if payload == nil { - request, err = http.NewRequest(method, url, nil) - } else { - var payloadJson []byte; - payloadJson, err = json.Marshal(payload) - if err != nil { - client.notifyErrorHandlers(err) - return nil, err - } - request, err = http.NewRequest(method, url, bytes.NewBuffer(payloadJson)) - } - - request.Header.Set("Content-Type", "application/json") - request.SetBasicAuth(client.authUsername, client.authPassword) - return request, err } \ No newline at end of file diff --git a/rest/dto/variable_response.go b/rest/dto/variable_response.go new file mode 100644 index 0000000..5d1cbb0 --- /dev/null +++ b/rest/dto/variable_response.go @@ -0,0 +1,37 @@ +package dto + +import ( + "fmt" + "encoding/json" + "strings" +) + +type VariableResponse struct { + Type string + Value string + ValueFormat string +} + +func (response VariableResponse) GetValue() string { + return response.Value +} + +func (response *VariableResponse) UnmarshalJSON(data []byte) error { + var responseRaw struct{ + Type string `json:"type"` + Value string `json:"value"` + ValueInfo struct{ + SerializationDataFormat string `json:"serializationDataFormat"` + } `json:"valueInfo"` + } + if err := json.Unmarshal(data, &responseRaw); err != nil { + return fmt.Errorf("Failed to parse variable: %s", err) + } + + response.Value = strings.Replace(responseRaw.Value, `\\\"`, `"`, -1) + response.Type = responseRaw.Type + response.ValueFormat = responseRaw.ValueInfo.SerializationDataFormat + return nil +} + + From 04372375eaf77b41b3ddc7b34708e78d47b79a97 Mon Sep 17 00:00:00 2001 From: Valdas Petrulis Date: Mon, 13 Mar 2017 14:14:35 +0200 Subject: [PATCH 2/3] Seperate request factory from transport --- rest/client_rest.go | 112 +++++++++++++++++++++++++------------------- 1 file changed, 63 insertions(+), 49 deletions(-) diff --git a/rest/client_rest.go b/rest/client_rest.go index 4e5b81d..3e5bce3 100644 --- a/rest/client_rest.go +++ b/rest/client_rest.go @@ -1,7 +1,6 @@ package rest import ( - "bytes" "encoding/json" "errors" "fmt" @@ -9,12 +8,12 @@ import ( "github.com/bigbank-as/go_camunda_client/rest/dto" "io/ioutil" "net/http" + "bytes" ) -func Construct( - urlRoot string, username string, password string, - httpClient http.Client, -) go_camunda_client.CamundaClient { +const CLIENT_NAME = "goclient-v0.1" + +func Construct(urlRoot, username, password string, httpClient http.Client) go_camunda_client.CamundaClient { client := new(camundaClientRest) client.urlRoot = urlRoot client.authUsername = username @@ -24,12 +23,17 @@ func Construct( return client } -func (client *camundaClientRest) StartProcess(processDefinitionKey string, request interface{}) ( - go_camunda_client.Process, error, +func (client *camundaClientRest) StartProcess(processDefinitionKey string, requestDto interface{}) ( + go_camunda_client.Process, + error, ) { var process dto.Process - response, err := client.doRequest("POST", "process-definition/key/" + processDefinitionKey + "/start", request) + response, err := client.doRequestJson( + "POST", + "process-definition/key/" + processDefinitionKey + "/start", + requestDto, + ) if err == nil { err = client.parseResponseJson(response, &process) defer response.Body.Close() @@ -41,7 +45,7 @@ func (client *camundaClientRest) StartProcess(processDefinitionKey string, reque func (client *camundaClientRest) GetProcess(processId string) (go_camunda_client.Process, error) { var process dto.Process - response, err := client.doRequest("GET", "process-instance/" + processId, nil) + response, err := client.doRequest("GET", "process-instance/" + processId) if err == nil { err = client.parseResponseJson(response, &process) defer response.Body.Close() @@ -50,10 +54,11 @@ func (client *camundaClientRest) GetProcess(processId string) (go_camunda_client return process, err } -func (client *camundaClientRest) GetProcessVariable(processId string, variableName string) ( - go_camunda_client.VariableResponse, error, +func (client *camundaClientRest) GetProcessVariable(processId, variableName string) ( + go_camunda_client.VariableResponse, + error, ) { - return doVariableRequest(client, "process-instance/" + processId + "/variables/" + variableName) + return client.doRequestVariable("process-instance/" + processId + "/variables/" + variableName) } func (client camundaClientRest) GetNextTask(processId string) (go_camunda_client.Task, error) { @@ -68,7 +73,7 @@ func (client camundaClientRest) GetAllTasks(processId string) ([]go_camunda_clie var dtoTasks []dto.Task var tasks []go_camunda_client.Task - response, err := client.doRequest("GET", "task/?processInstanceId=" + processId, nil) + response, err := client.doRequest("GET", "task/?processInstanceId=" + processId) if err == nil { err = client.parseResponseJson(response, &dtoTasks) defer response.Body.Close() @@ -81,16 +86,16 @@ func (client camundaClientRest) GetAllTasks(processId string) ([]go_camunda_clie return tasks, err } -func (client camundaClientRest) CompleteTask(taskId string, request interface{}) (error) { - _, err := client.doRequest("POST", "task/" + taskId + "/complete", request) +func (client camundaClientRest) CompleteTask(taskId string, requestDto interface{}) (error) { + _, err := client.doRequestJson("POST", "task/" + taskId + "/complete", requestDto) return err } -func (client *camundaClientRest) GetTaskVariable(taskId string, variableName string) ( +func (client *camundaClientRest) GetTaskVariable(taskId, variableName string) ( go_camunda_client.VariableResponse, error, ) { - return doVariableRequest(client, "task/" + taskId + "/variables/" + variableName) + return client.doRequestVariable("task/" + taskId + "/variables/" + variableName) } func (client *camundaClientRest) HandleErrors(errorCallback func(error)) { @@ -111,55 +116,44 @@ type camundaClientRest struct { errorCallbacks []func(error) } -func (client *camundaClientRest) constructRequest(method, path string, payload interface{})(*http.Request, error) { - var request *http.Request; - var err error; - url := client.urlRoot + "/" + path - - if payload == nil { - request, err = http.NewRequest(method, url, nil) - } else { - var payloadJson []byte; - payloadJson, err = json.Marshal(payload) - if err != nil { - client.notifyErrorHandlers(err) - return nil, err - } - request, err = http.NewRequest(method, url, bytes.NewBuffer(payloadJson)) +func (client *camundaClientRest) doRequest(method, path string) ( + *http.Response, + error, +) { + request, err := http.NewRequest(method, client.urlRoot + "/" + path, nil) + if err != nil { + client.notifyErrorHandlers(err) + return nil, err } - request.Header.Set("Content-Type", "application/json") - request.SetBasicAuth(client.authUsername, client.authPassword) - return request, err -} -func (client *camundaClientRest) doRequest(method, path string, payload interface{}) (*http.Response, error) { + return client.transportRequest(request) +} - request, err := client.constructRequest(method, path, payload) +func (client *camundaClientRest) doRequestJson(method, path string, payload interface{}) ( + *http.Response, + error, +) { + payloadJson, err := json.Marshal(payload) if err != nil { client.notifyErrorHandlers(err) return nil, err } - response, err := client.httpClient.Do(request) + request, err := http.NewRequest(method, client.urlRoot + "/" + path, bytes.NewBuffer(payloadJson)) + request.Header.Set("Content-Type", "application/json") if err != nil { client.notifyErrorHandlers(err) - return response, err - } - - if (response.StatusCode < 200 || response.StatusCode >= 300) { - err := client.parseResponseError(response) - client.notifyErrorHandlers(err) - return response, err + return nil, err } - return response, nil + return client.transportRequest(request) } -func doVariableRequest(client *camundaClientRest, path string) (dto.VariableResponse, error) { +func (client *camundaClientRest) doRequestVariable(resoucePath string) (dto.VariableResponse, error) { var variableResponse dto.VariableResponse - response, err := client.doRequest("GET", path + "/?deserializeValue=false", nil) + response, err := client.doRequest("GET", resoucePath+ "/?deserializeValue=false") if err == nil { err = client.parseResponseJson(response, &variableResponse) defer response.Body.Close() @@ -168,6 +162,26 @@ func doVariableRequest(client *camundaClientRest, path string) (dto.VariableResp return variableResponse, err } +func (client *camundaClientRest) transportRequest(request *http.Request) (*http.Response, error) { + request.Header.Set("User-Agent", CLIENT_NAME) + request.Header.Set("Accept", "application/json") + request.SetBasicAuth(client.authUsername, client.authPassword) + + response, err := client.httpClient.Do(request) + if err != nil { + client.notifyErrorHandlers(err) + return response, err + } + + if response.StatusCode < 200 || response.StatusCode >= 300 { + err := client.parseResponseError(response) + client.notifyErrorHandlers(err) + return response, err + } + + return response, nil +} + func (client *camundaClientRest) parseResponseError(response *http.Response) error { contentType := response.Header.Get("Content-Type") if contentType == "application/json" { From bd06ec7ef001d20ed820f5f7cd216294d5119f42 Mon Sep 17 00:00:00 2001 From: Valdas Petrulis Date: Mon, 13 Mar 2017 14:21:56 +0200 Subject: [PATCH 3/3] Isolate DTO variables under interfaces --- rest/dto/{error.go => error_response.go} | 0 rest/dto/process.go | 14 --------- rest/dto/process_response.go | 33 +++++++++++++++++++ rest/dto/task.go | 19 ----------- rest/dto/task_response.go | 40 ++++++++++++++++++++++++ rest/dto/variable_response.go | 14 ++++----- 6 files changed, 80 insertions(+), 40 deletions(-) rename rest/dto/{error.go => error_response.go} (100%) delete mode 100644 rest/dto/process.go create mode 100644 rest/dto/process_response.go delete mode 100644 rest/dto/task.go create mode 100644 rest/dto/task_response.go diff --git a/rest/dto/error.go b/rest/dto/error_response.go similarity index 100% rename from rest/dto/error.go rename to rest/dto/error_response.go diff --git a/rest/dto/process.go b/rest/dto/process.go deleted file mode 100644 index e769e45..0000000 --- a/rest/dto/process.go +++ /dev/null @@ -1,14 +0,0 @@ -package dto - -type Process struct { - JsonId string `json:"id"` - JsonIsEnded bool `json:"ended"` -} - -func (process Process) GetId() string { - return process.JsonId -} - -func (process Process) IsEnded() bool { - return process.JsonIsEnded -} diff --git a/rest/dto/process_response.go b/rest/dto/process_response.go new file mode 100644 index 0000000..4a329e4 --- /dev/null +++ b/rest/dto/process_response.go @@ -0,0 +1,33 @@ +package dto + +import ( + "fmt" + "encoding/json" +) + +type Process struct { + id string + isEnded bool +} + +func (process Process) GetId() string { + return process.id +} + +func (process Process) IsEnded() bool { + return process.isEnded +} + +func (response *Process) UnmarshalJSON(data []byte) error { + var responseRaw struct{ + Id string `json:"id"` + IsEnded bool `json:"ended"` + } + if err := json.Unmarshal(data, &responseRaw); err != nil { + return fmt.Errorf("Failed to parse variable: %s", err) + } + + response.id = responseRaw.Id + response.isEnded = responseRaw.IsEnded + return nil +} diff --git a/rest/dto/task.go b/rest/dto/task.go deleted file mode 100644 index 7453fc3..0000000 --- a/rest/dto/task.go +++ /dev/null @@ -1,19 +0,0 @@ -package dto - -type Task struct { - Id string `json:"id"` - Name string `json:"name"` - TaskDefinitionKey string `json:"taskDefinitionKey"` -} - -func (task Task) GetId() string { - return task.Id -} - -func (task Task) GetName() string { - return task.Name -} - -func (task Task) GetTaskDefinitionKey() string { - return task.TaskDefinitionKey -} \ No newline at end of file diff --git a/rest/dto/task_response.go b/rest/dto/task_response.go new file mode 100644 index 0000000..8c62239 --- /dev/null +++ b/rest/dto/task_response.go @@ -0,0 +1,40 @@ +package dto + +import ( + "fmt" + "encoding/json" +) + +type Task struct { + id string + name string + taskDefinitionKey string +} + +func (task Task) GetId() string { + return task.id +} + +func (task Task) GetName() string { + return task.name +} + +func (task Task) GetTaskDefinitionKey() string { + return task.taskDefinitionKey +} + +func (response *Task) UnmarshalJSON(data []byte) error { + var responseRaw struct{ + Id string `json:"id"` + Name string `json:"name"` + TaskDefinitionKey string `json:"taskDefinitionKey"` + } + if err := json.Unmarshal(data, &responseRaw); err != nil { + return fmt.Errorf("Failed to parse variable: %s", err) + } + + response.id = responseRaw.Id + response.name = responseRaw.Name + response.taskDefinitionKey = responseRaw.TaskDefinitionKey + return nil +} \ No newline at end of file diff --git a/rest/dto/variable_response.go b/rest/dto/variable_response.go index 5d1cbb0..60dd4fb 100644 --- a/rest/dto/variable_response.go +++ b/rest/dto/variable_response.go @@ -7,13 +7,13 @@ import ( ) type VariableResponse struct { - Type string - Value string - ValueFormat string + value string + valueType string + valueFormat string } func (response VariableResponse) GetValue() string { - return response.Value + return response.value } func (response *VariableResponse) UnmarshalJSON(data []byte) error { @@ -28,9 +28,9 @@ func (response *VariableResponse) UnmarshalJSON(data []byte) error { return fmt.Errorf("Failed to parse variable: %s", err) } - response.Value = strings.Replace(responseRaw.Value, `\\\"`, `"`, -1) - response.Type = responseRaw.Type - response.ValueFormat = responseRaw.ValueInfo.SerializationDataFormat + response.value = strings.Replace(responseRaw.Value, `\\\"`, `"`, -1) + response.valueType = responseRaw.Type + response.valueFormat = responseRaw.ValueInfo.SerializationDataFormat return nil }