operaton-bpm-client 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +134 -0
- data/lib/operaton/bpm/client/backoff/backoff_strategy.rb +20 -0
- data/lib/operaton/bpm/client/backoff/error_aware_backoff_strategy.rb +22 -0
- data/lib/operaton/bpm/client/backoff/exponential_backoff_strategy.rb +38 -0
- data/lib/operaton/bpm/client/backoff/exponential_error_backoff_strategy.rb +38 -0
- data/lib/operaton/bpm/client/exceptions.rb +74 -0
- data/lib/operaton/bpm/client/external_task_client.rb +20 -0
- data/lib/operaton/bpm/client/external_task_client_builder.rb +18 -0
- data/lib/operaton/bpm/client/impl/engine_client.rb +132 -0
- data/lib/operaton/bpm/client/impl/engine_client_exception.rb +25 -0
- data/lib/operaton/bpm/client/impl/engine_client_logger.rb +54 -0
- data/lib/operaton/bpm/client/impl/engine_rest_exception_dto.rb +28 -0
- data/lib/operaton/bpm/client/impl/external_task_client_builder_impl.rb +349 -0
- data/lib/operaton/bpm/client/impl/external_task_client_impl.rb +41 -0
- data/lib/operaton/bpm/client/impl/external_task_client_logger.rb +236 -0
- data/lib/operaton/bpm/client/impl/object_mapper.rb +44 -0
- data/lib/operaton/bpm/client/impl/permanent_url_resolver.rb +22 -0
- data/lib/operaton/bpm/client/impl/request_dto.rb +24 -0
- data/lib/operaton/bpm/client/impl/request_executor.rb +143 -0
- data/lib/operaton/bpm/client/interceptor/auth/basic_auth_provider.rb +42 -0
- data/lib/operaton/bpm/client/interceptor/client_request_context.rb +16 -0
- data/lib/operaton/bpm/client/interceptor/client_request_interceptor.rb +18 -0
- data/lib/operaton/bpm/client/interceptor/impl/client_request_context_impl.rb +28 -0
- data/lib/operaton/bpm/client/interceptor/impl/request_interceptor_handler.rb +43 -0
- data/lib/operaton/bpm/client/spi/data_format.rb +32 -0
- data/lib/operaton/bpm/client/spi/data_format_configurator.rb +31 -0
- data/lib/operaton/bpm/client/spi/data_format_provider.rb +31 -0
- data/lib/operaton/bpm/client/task/external_task.rb +22 -0
- data/lib/operaton/bpm/client/task/external_task_handler.rb +28 -0
- data/lib/operaton/bpm/client/task/external_task_service.rb +18 -0
- data/lib/operaton/bpm/client/task/impl/dto/bpmn_error_request_dto.rb +35 -0
- data/lib/operaton/bpm/client/task/impl/dto/complete_request_dto.rb +33 -0
- data/lib/operaton/bpm/client/task/impl/dto/extend_lock_request_dto.rb +29 -0
- data/lib/operaton/bpm/client/task/impl/dto/failure_request_dto.rb +43 -0
- data/lib/operaton/bpm/client/task/impl/dto/lock_request_dto.rb +29 -0
- data/lib/operaton/bpm/client/task/impl/dto/set_variables_request_dto.rb +29 -0
- data/lib/operaton/bpm/client/task/impl/external_task_impl.rb +128 -0
- data/lib/operaton/bpm/client/task/impl/external_task_service_impl.rb +90 -0
- data/lib/operaton/bpm/client/task/ordering_config.rb +78 -0
- data/lib/operaton/bpm/client/task/sorting_dto.rb +29 -0
- data/lib/operaton/bpm/client/topic/impl/dto/fetch_and_lock_request_dto.rb +47 -0
- data/lib/operaton/bpm/client/topic/impl/dto/fetch_and_lock_response_dto.rb +32 -0
- data/lib/operaton/bpm/client/topic/impl/dto/topic_request_dto.rb +70 -0
- data/lib/operaton/bpm/client/topic/impl/topic_subscription_builder_impl.rb +164 -0
- data/lib/operaton/bpm/client/topic/impl/topic_subscription_impl.rb +76 -0
- data/lib/operaton/bpm/client/topic/impl/topic_subscription_manager.rb +222 -0
- data/lib/operaton/bpm/client/topic/impl/topic_subscription_manager_logger.rb +52 -0
- data/lib/operaton/bpm/client/topic/topic_subscription.rb +20 -0
- data/lib/operaton/bpm/client/topic/topic_subscription_builder.rb +22 -0
- data/lib/operaton/bpm/client/url_resolver.rb +15 -0
- data/lib/operaton/bpm/client/variable/client_values.rb +33 -0
- data/lib/operaton/bpm/client/variable/impl/abstract_typed_value_mapper.rb +59 -0
- data/lib/operaton/bpm/client/variable/impl/default_value_mappers.rb +71 -0
- data/lib/operaton/bpm/client/variable/impl/format/json/json_data_format.rb +82 -0
- data/lib/operaton/bpm/client/variable/impl/format/json/json_data_format_provider.rb +34 -0
- data/lib/operaton/bpm/client/variable/impl/mapper/boolean_value_mapper.rb +35 -0
- data/lib/operaton/bpm/client/variable/impl/mapper/byte_array_value_mapper.rb +53 -0
- data/lib/operaton/bpm/client/variable/impl/mapper/date_value_mapper.rb +61 -0
- data/lib/operaton/bpm/client/variable/impl/mapper/double_value_mapper.rb +36 -0
- data/lib/operaton/bpm/client/variable/impl/mapper/file_value_mapper.rb +73 -0
- data/lib/operaton/bpm/client/variable/impl/mapper/integer_value_mapper.rb +36 -0
- data/lib/operaton/bpm/client/variable/impl/mapper/json_value_mapper.rb +35 -0
- data/lib/operaton/bpm/client/variable/impl/mapper/long_value_mapper.rb +36 -0
- data/lib/operaton/bpm/client/variable/impl/mapper/null_value_mapper.rb +45 -0
- data/lib/operaton/bpm/client/variable/impl/mapper/number_value_mapper.rb +25 -0
- data/lib/operaton/bpm/client/variable/impl/mapper/object_value_mapper.rb +151 -0
- data/lib/operaton/bpm/client/variable/impl/mapper/primitive_value_mapper.rb +44 -0
- data/lib/operaton/bpm/client/variable/impl/mapper/short_value_mapper.rb +36 -0
- data/lib/operaton/bpm/client/variable/impl/mapper/string_value_mapper.rb +35 -0
- data/lib/operaton/bpm/client/variable/impl/mapper/xml_value_mapper.rb +35 -0
- data/lib/operaton/bpm/client/variable/impl/type/json_type_impl.rb +24 -0
- data/lib/operaton/bpm/client/variable/impl/type/xml_type_impl.rb +24 -0
- data/lib/operaton/bpm/client/variable/impl/typed_value_field.rb +36 -0
- data/lib/operaton/bpm/client/variable/impl/typed_values.rb +100 -0
- data/lib/operaton/bpm/client/variable/impl/value/deferred_file_value_impl.rb +57 -0
- data/lib/operaton/bpm/client/variable/impl/value/json_value_impl.rb +26 -0
- data/lib/operaton/bpm/client/variable/impl/value/xml_value_impl.rb +26 -0
- data/lib/operaton/bpm/client/variable/impl/value_mapper.rb +42 -0
- data/lib/operaton/bpm/client/variable/impl/value_mappers.rb +26 -0
- data/lib/operaton/bpm/client/variable/impl/variable_value.rb +55 -0
- data/lib/operaton/bpm/client/variable/value/deferred_file_value.rb +19 -0
- data/lib/operaton/bpm/client/variable/value/json_value.rb +16 -0
- data/lib/operaton/bpm/client/variable/value/xml_value.rb +16 -0
- data/lib/operaton/bpm/client/version.rb +9 -0
- data/lib/operaton/bpm/client.rb +121 -0
- data/lib/operaton/bpm/engine/variable/typed_value.rb +153 -0
- data/lib/operaton/bpm/engine/variable/value_type.rb +126 -0
- data/lib/operaton/bpm/engine/variable/variable_map.rb +72 -0
- data/lib/operaton/bpm/engine/variable/variables.rb +197 -0
- data/lib/operaton-bpm-client.rb +3 -0
- metadata +188 -0
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "socket"
|
|
4
|
+
require "securerandom"
|
|
5
|
+
|
|
6
|
+
require_relative "../external_task_client_builder"
|
|
7
|
+
require_relative "external_task_client_logger"
|
|
8
|
+
require_relative "external_task_client_impl"
|
|
9
|
+
require_relative "permanent_url_resolver"
|
|
10
|
+
require_relative "object_mapper"
|
|
11
|
+
require_relative "engine_client"
|
|
12
|
+
require_relative "request_executor"
|
|
13
|
+
require_relative "../backoff/exponential_backoff_strategy"
|
|
14
|
+
require_relative "../interceptor/impl/request_interceptor_handler"
|
|
15
|
+
require_relative "../task/ordering_config"
|
|
16
|
+
require_relative "../topic/impl/topic_subscription_manager"
|
|
17
|
+
require_relative "../spi/data_format_provider"
|
|
18
|
+
require_relative "../spi/data_format_configurator"
|
|
19
|
+
require_relative "../variable/client_values"
|
|
20
|
+
require_relative "../variable/impl/default_value_mappers"
|
|
21
|
+
require_relative "../variable/impl/typed_values"
|
|
22
|
+
require_relative "../variable/impl/mapper/boolean_value_mapper"
|
|
23
|
+
require_relative "../variable/impl/mapper/byte_array_value_mapper"
|
|
24
|
+
require_relative "../variable/impl/mapper/date_value_mapper"
|
|
25
|
+
require_relative "../variable/impl/mapper/double_value_mapper"
|
|
26
|
+
require_relative "../variable/impl/mapper/file_value_mapper"
|
|
27
|
+
require_relative "../variable/impl/mapper/integer_value_mapper"
|
|
28
|
+
require_relative "../variable/impl/mapper/json_value_mapper"
|
|
29
|
+
require_relative "../variable/impl/mapper/long_value_mapper"
|
|
30
|
+
require_relative "../variable/impl/mapper/null_value_mapper"
|
|
31
|
+
require_relative "../variable/impl/mapper/object_value_mapper"
|
|
32
|
+
require_relative "../variable/impl/mapper/short_value_mapper"
|
|
33
|
+
require_relative "../variable/impl/mapper/string_value_mapper"
|
|
34
|
+
require_relative "../variable/impl/mapper/xml_value_mapper"
|
|
35
|
+
require_relative "../variable/impl/format/json/json_data_format_provider"
|
|
36
|
+
|
|
37
|
+
module Operaton
|
|
38
|
+
module Bpm
|
|
39
|
+
module Client
|
|
40
|
+
module Impl
|
|
41
|
+
# Mirrors org.operaton.bpm.client.impl.ExternalTaskClientBuilderImpl
|
|
42
|
+
class ExternalTaskClientBuilderImpl
|
|
43
|
+
include ExternalTaskClientBuilder
|
|
44
|
+
|
|
45
|
+
attr_reader :object_mapper, :value_mappers, :typed_values, :engine_client
|
|
46
|
+
|
|
47
|
+
def initialize
|
|
48
|
+
# default values
|
|
49
|
+
@worker_id = nil
|
|
50
|
+
@max_tasks = 10
|
|
51
|
+
@use_priority = true
|
|
52
|
+
@ordering_config = Task::OrderingConfig.empty
|
|
53
|
+
@async_response_timeout = nil
|
|
54
|
+
@lock_duration = 20_000
|
|
55
|
+
@default_serialization_format = Engine::Variable::Variables::SerializationDataFormats::JSON
|
|
56
|
+
@date_format = ObjectMapper::DEFAULT_DATE_FORMAT
|
|
57
|
+
@interceptors = []
|
|
58
|
+
@is_auto_fetching_enabled = true
|
|
59
|
+
@backoff_strategy = Backoff::ExponentialBackoffStrategy.new
|
|
60
|
+
@is_backoff_strategy_disabled = false
|
|
61
|
+
@http_customizer = nil
|
|
62
|
+
@url_resolver = PermanentUrlResolver.new(nil)
|
|
63
|
+
@object_mapper = nil
|
|
64
|
+
@value_mappers = nil
|
|
65
|
+
@typed_values = nil
|
|
66
|
+
@engine_client = nil
|
|
67
|
+
@topic_subscription_manager = nil
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def base_url(base_url)
|
|
71
|
+
@url_resolver = PermanentUrlResolver.new(base_url)
|
|
72
|
+
self
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def url_resolver(url_resolver)
|
|
76
|
+
@url_resolver = url_resolver
|
|
77
|
+
self
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def worker_id(worker_id)
|
|
81
|
+
@worker_id = worker_id
|
|
82
|
+
self
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def add_interceptor(interceptor)
|
|
86
|
+
@interceptors << interceptor
|
|
87
|
+
self
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def max_tasks(max_tasks)
|
|
91
|
+
@max_tasks = max_tasks
|
|
92
|
+
self
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def use_priority(use_priority)
|
|
96
|
+
@use_priority = use_priority
|
|
97
|
+
self
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def use_create_time(use_create_time)
|
|
101
|
+
if use_create_time
|
|
102
|
+
@ordering_config.configure_field(Task::OrderingConfig::SortingField::CREATE_TIME)
|
|
103
|
+
@ordering_config.configure_direction_on_last_field(Task::OrderingConfig::Direction::DESC)
|
|
104
|
+
end
|
|
105
|
+
self
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def order_by_create_time
|
|
109
|
+
@ordering_config.configure_field(Task::OrderingConfig::SortingField::CREATE_TIME)
|
|
110
|
+
self
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def asc
|
|
114
|
+
@ordering_config.configure_direction_on_last_field(Task::OrderingConfig::Direction::ASC)
|
|
115
|
+
self
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def desc
|
|
119
|
+
@ordering_config.configure_direction_on_last_field(Task::OrderingConfig::Direction::DESC)
|
|
120
|
+
self
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def async_response_timeout(async_response_timeout)
|
|
124
|
+
@async_response_timeout = async_response_timeout
|
|
125
|
+
self
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def lock_duration(lock_duration)
|
|
129
|
+
@lock_duration = lock_duration
|
|
130
|
+
self
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def disable_auto_fetching
|
|
134
|
+
@is_auto_fetching_enabled = false
|
|
135
|
+
self
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def backoff_strategy(backoff_strategy)
|
|
139
|
+
@backoff_strategy = backoff_strategy
|
|
140
|
+
self
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def disable_backoff_strategy
|
|
144
|
+
@is_backoff_strategy_disabled = true
|
|
145
|
+
self
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def default_serialization_format(default_serialization_format)
|
|
149
|
+
@default_serialization_format = default_serialization_format
|
|
150
|
+
self
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# A Ruby strftime pattern (default "%Y-%m-%dT%H:%M:%S.%L%z", the
|
|
154
|
+
# equivalent of the Java client's "yyyy-MM-dd'T'HH:mm:ss.SSSZ").
|
|
155
|
+
def date_format(date_format)
|
|
156
|
+
@date_format = date_format
|
|
157
|
+
self
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# Accepts a block invoked with the Net::HTTP instance of every request.
|
|
161
|
+
def customize_http_client(customizer = nil, &block)
|
|
162
|
+
@http_customizer = customizer || block
|
|
163
|
+
self
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def build
|
|
167
|
+
raise logger.max_tasks_not_greater_than_zero_exception(@max_tasks) if @max_tasks <= 0
|
|
168
|
+
|
|
169
|
+
if !@async_response_timeout.nil? && @async_response_timeout <= 0
|
|
170
|
+
raise logger.async_response_timeout_not_greater_than_zero_exception(@async_response_timeout)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
raise logger.lock_duration_is_not_greater_than_zero_exception(@lock_duration) if @lock_duration <= 0
|
|
174
|
+
|
|
175
|
+
raise logger.base_url_null_exception if @url_resolver.nil? || get_base_url.nil? || get_base_url.empty?
|
|
176
|
+
|
|
177
|
+
check_interceptors
|
|
178
|
+
@ordering_config.validate_ordering_properties
|
|
179
|
+
|
|
180
|
+
init_base_url
|
|
181
|
+
init_worker_id
|
|
182
|
+
init_object_mapper
|
|
183
|
+
init_engine_client
|
|
184
|
+
init_variable_mappers
|
|
185
|
+
init_topic_subscription_manager
|
|
186
|
+
|
|
187
|
+
ExternalTaskClientImpl.new(@topic_subscription_manager)
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def get_base_url # rubocop:disable Naming/AccessorMethodName
|
|
191
|
+
@url_resolver.base_url
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def get_default_serialization_format # rubocop:disable Naming/AccessorMethodName
|
|
195
|
+
@default_serialization_format
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def get_date_format # rubocop:disable Naming/AccessorMethodName
|
|
199
|
+
@date_format
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
protected
|
|
203
|
+
|
|
204
|
+
def init_base_url
|
|
205
|
+
@url_resolver.base_url = sanitize_url(@url_resolver.base_url) if @url_resolver.is_a?(PermanentUrlResolver)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def sanitize_url(url)
|
|
209
|
+
url.strip.sub(%r{/+\z}, "")
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def init_worker_id
|
|
213
|
+
return unless @worker_id.nil?
|
|
214
|
+
|
|
215
|
+
hostname = check_hostname
|
|
216
|
+
@worker_id = "#{hostname}#{SecureRandom.uuid}"
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def check_interceptors
|
|
220
|
+
@interceptors.each do |interceptor|
|
|
221
|
+
raise logger.interceptor_null_exception if interceptor.nil?
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def init_object_mapper
|
|
226
|
+
@object_mapper = ObjectMapper.new(@date_format)
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def init_engine_client
|
|
230
|
+
request_interceptor_handler = Interceptor::Impl::RequestInterceptorHandler.new(@interceptors)
|
|
231
|
+
request_executor = RequestExecutor.new(
|
|
232
|
+
@object_mapper,
|
|
233
|
+
interceptor_handler: request_interceptor_handler,
|
|
234
|
+
http_customizer: @http_customizer,
|
|
235
|
+
read_timeout: compute_read_timeout
|
|
236
|
+
)
|
|
237
|
+
@engine_client = EngineClient.new(@worker_id, @max_tasks, @async_response_timeout, @url_resolver,
|
|
238
|
+
request_executor, @use_priority, @ordering_config)
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def init_variable_mappers
|
|
242
|
+
@value_mappers = Variable::Impl::DefaultValueMappers.new(@default_serialization_format)
|
|
243
|
+
|
|
244
|
+
@value_mappers.add_mapper(Variable::Impl::Mapper::NullValueMapper.new)
|
|
245
|
+
@value_mappers.add_mapper(Variable::Impl::Mapper::BooleanValueMapper.new)
|
|
246
|
+
@value_mappers.add_mapper(Variable::Impl::Mapper::StringValueMapper.new)
|
|
247
|
+
@value_mappers.add_mapper(Variable::Impl::Mapper::DateValueMapper.new(@date_format))
|
|
248
|
+
@value_mappers.add_mapper(Variable::Impl::Mapper::ByteArrayValueMapper.new)
|
|
249
|
+
|
|
250
|
+
# number mappers
|
|
251
|
+
@value_mappers.add_mapper(Variable::Impl::Mapper::IntegerValueMapper.new)
|
|
252
|
+
@value_mappers.add_mapper(Variable::Impl::Mapper::LongValueMapper.new)
|
|
253
|
+
@value_mappers.add_mapper(Variable::Impl::Mapper::ShortValueMapper.new)
|
|
254
|
+
@value_mappers.add_mapper(Variable::Impl::Mapper::DoubleValueMapper.new)
|
|
255
|
+
|
|
256
|
+
# object
|
|
257
|
+
lookup_data_formats.each do |key, format|
|
|
258
|
+
@value_mappers.add_mapper(Variable::Impl::Mapper::ObjectValueMapper.new(key, format))
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
# json/xml
|
|
262
|
+
@value_mappers.add_mapper(Variable::Impl::Mapper::JsonValueMapper.new)
|
|
263
|
+
@value_mappers.add_mapper(Variable::Impl::Mapper::XmlValueMapper.new)
|
|
264
|
+
|
|
265
|
+
# file
|
|
266
|
+
@value_mappers.add_mapper(Variable::Impl::Mapper::FileValueMapper.new(@engine_client))
|
|
267
|
+
|
|
268
|
+
@typed_values = Variable::Impl::TypedValues.new(@value_mappers)
|
|
269
|
+
@engine_client.typed_values = @typed_values
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def init_topic_subscription_manager
|
|
273
|
+
@topic_subscription_manager = Topic::Impl::TopicSubscriptionManager.new(
|
|
274
|
+
@engine_client, @typed_values, @lock_duration
|
|
275
|
+
)
|
|
276
|
+
@topic_subscription_manager.backoff_strategy = @backoff_strategy
|
|
277
|
+
@topic_subscription_manager.disable_backoff_strategy if @is_backoff_strategy_disabled
|
|
278
|
+
@topic_subscription_manager.start if auto_fetching_enabled?
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
def lookup_data_formats
|
|
282
|
+
data_formats = {}
|
|
283
|
+
lookup_custom_data_formats(data_formats)
|
|
284
|
+
apply_configurators(data_formats)
|
|
285
|
+
data_formats
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
def lookup_custom_data_formats(data_formats)
|
|
289
|
+
Spi::DataFormatProvider.providers.each do |provider|
|
|
290
|
+
logger.log_data_format_provider(provider)
|
|
291
|
+
lookup_provider(data_formats, provider)
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def lookup_provider(data_formats, provider)
|
|
296
|
+
data_format_name = provider.data_format_name
|
|
297
|
+
raise logger.multiple_providers_for_dataformat(data_format_name) if data_formats.key?(data_format_name)
|
|
298
|
+
|
|
299
|
+
data_format_instance = provider.create_instance
|
|
300
|
+
data_formats[data_format_name] = data_format_instance
|
|
301
|
+
logger.log_data_format(data_format_instance)
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def apply_configurators(data_formats)
|
|
305
|
+
Spi::DataFormatConfigurator.configurators.each do |configurator|
|
|
306
|
+
logger.log_data_format_configurator(configurator)
|
|
307
|
+
apply_configurator(data_formats, configurator)
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
def apply_configurator(data_formats, configurator)
|
|
312
|
+
data_formats.each_value do |data_format|
|
|
313
|
+
configurator.configure(data_format) if data_format.is_a?(configurator.data_format_class)
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
def check_hostname
|
|
318
|
+
hostname = get_hostname
|
|
319
|
+
raise logger.cannot_get_hostname_exception(nil) if hostname.nil? || hostname.empty?
|
|
320
|
+
|
|
321
|
+
hostname
|
|
322
|
+
rescue StandardError => e
|
|
323
|
+
raise logger.cannot_get_hostname_exception(e)
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
def get_hostname # rubocop:disable Naming/AccessorMethodName
|
|
327
|
+
Socket.gethostname
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
def auto_fetching_enabled?
|
|
331
|
+
@is_auto_fetching_enabled
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
def compute_read_timeout
|
|
335
|
+
if @async_response_timeout
|
|
336
|
+
(@async_response_timeout / 1000.0) + 30
|
|
337
|
+
else
|
|
338
|
+
60
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
def logger
|
|
343
|
+
ExternalTaskClientLogger.client_logger
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
end
|
|
349
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../topic/impl/topic_subscription_builder_impl"
|
|
4
|
+
|
|
5
|
+
module Operaton
|
|
6
|
+
module Bpm
|
|
7
|
+
module Client
|
|
8
|
+
module Impl
|
|
9
|
+
# Mirrors org.operaton.bpm.client.impl.ExternalTaskClientImpl
|
|
10
|
+
class ExternalTaskClientImpl
|
|
11
|
+
attr_reader :topic_subscription_manager
|
|
12
|
+
|
|
13
|
+
def initialize(topic_subscription_manager)
|
|
14
|
+
@topic_subscription_manager = topic_subscription_manager
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Creates a fluent builder to create and configure a topic subscription.
|
|
18
|
+
def subscribe(topic_name)
|
|
19
|
+
Topic::Impl::TopicSubscriptionBuilderImpl.new(topic_name, topic_subscription_manager)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Stops continuous fetching and locking of tasks.
|
|
23
|
+
def stop
|
|
24
|
+
topic_subscription_manager.stop
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Starts continuous fetching and locking of tasks.
|
|
28
|
+
def start
|
|
29
|
+
topic_subscription_manager.start
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# True while the client is actively fetching tasks.
|
|
33
|
+
def active?
|
|
34
|
+
topic_subscription_manager.running?
|
|
35
|
+
end
|
|
36
|
+
alias is_active? active?
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "logger"
|
|
4
|
+
require_relative "../exceptions"
|
|
5
|
+
|
|
6
|
+
module Operaton
|
|
7
|
+
module Bpm
|
|
8
|
+
module Client
|
|
9
|
+
class << self
|
|
10
|
+
# Library-wide logger, mirroring the "org.operaton.bpm.client" SLF4J logger.
|
|
11
|
+
attr_writer :logger
|
|
12
|
+
|
|
13
|
+
def logger
|
|
14
|
+
@logger ||= Logger.new($stderr, progname: "org.operaton.bpm.client")
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
module Impl
|
|
19
|
+
# Mirrors org.operaton.bpm.client.impl.ExternalTaskClientLogger
|
|
20
|
+
class ExternalTaskClientLogger
|
|
21
|
+
PROJECT_CODE = "TASK/CLIENT"
|
|
22
|
+
|
|
23
|
+
def self.client_logger
|
|
24
|
+
@client_logger ||= new("01")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def self.engine_client_logger
|
|
28
|
+
@engine_client_logger ||= EngineClientLogger.new("02")
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def self.topic_subscription_manager_logger
|
|
32
|
+
@topic_subscription_manager_logger ||= Topic::Impl::TopicSubscriptionManagerLogger.new("03")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def initialize(component_id)
|
|
36
|
+
@component_id = component_id
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def exception_message(id, message_template, *args)
|
|
40
|
+
"#{PROJECT_CODE}-#{@component_id}#{id} #{format_template(message_template, *args)}"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def format_template(template, *args)
|
|
44
|
+
args.reduce(template) { |msg, arg| msg.sub("{}", arg.to_s) }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def log_error(id, message_template, error = nil, *args)
|
|
48
|
+
msg = exception_message(id, message_template, *args)
|
|
49
|
+
msg += " : #{error.class}: #{error.message}" if error
|
|
50
|
+
Client.logger.error(msg)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def log_info(id, message_template, *args)
|
|
54
|
+
Client.logger.info(exception_message(id, message_template, *args))
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def log_debug(id, message_template, *args)
|
|
58
|
+
Client.logger.debug(exception_message(id, message_template, *args))
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def base_url_null_exception
|
|
62
|
+
ExternalTaskClientException.new(exception_message(
|
|
63
|
+
"001", "Base URL cannot be null or an empty string"))
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def cannot_get_hostname_exception(cause)
|
|
67
|
+
ExternalTaskClientException.new(exception_message("002", "Cannot get hostname"), cause)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def double_direction_config_exception
|
|
71
|
+
ExternalTaskClientException.new(
|
|
72
|
+
"Invalid query: can specify only one direction desc() or asc() for an ordering constraint")
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def unspecified_order_by_method_exception
|
|
76
|
+
ExternalTaskClientException.new(
|
|
77
|
+
"Invalid query: You should call any of the orderBy methods first before specifying a direction")
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def missing_direction_exception
|
|
81
|
+
ExternalTaskClientException.new(
|
|
82
|
+
"Invalid query: call asc() or desc() after using orderByXX()")
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def topic_name_null_exception
|
|
86
|
+
ExternalTaskClientException.new(exception_message(
|
|
87
|
+
"003", "Topic name cannot be null"))
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def lock_duration_is_not_greater_than_zero_exception(lock_duration)
|
|
91
|
+
ExternalTaskClientException.new(exception_message(
|
|
92
|
+
"004", "Lock duration must be greater than 0, but was '{}'", lock_duration))
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def external_task_handler_null_exception
|
|
96
|
+
ExternalTaskClientException.new(exception_message(
|
|
97
|
+
"005", "External task handler cannot be null"))
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def topic_name_already_subscribed_exception(topic_name)
|
|
101
|
+
ExternalTaskClientException.new(exception_message(
|
|
102
|
+
"006", "Topic name '{}' has already been subscribed", topic_name))
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Mirrors handledEngineClientException: maps EngineClientException
|
|
106
|
+
# causes to the public exception hierarchy.
|
|
107
|
+
def handled_engine_client_exception(action_name, error)
|
|
108
|
+
caused = error.cause
|
|
109
|
+
|
|
110
|
+
if caused.is_a?(RestException)
|
|
111
|
+
message = caused.message
|
|
112
|
+
status = caused.http_status_code
|
|
113
|
+
|
|
114
|
+
return case status
|
|
115
|
+
when 400 then BadRequestException.new(create_message("007", action_name, message), caused)
|
|
116
|
+
when 404 then NotFoundException.new(create_message("008", action_name, message), caused)
|
|
117
|
+
when 500 then EngineException.new(create_message("009", action_name, message), caused)
|
|
118
|
+
else
|
|
119
|
+
UnknownHttpErrorException.new(exception_message(
|
|
120
|
+
"031", "Exception while {}: The request failed with status code {} and message: \"{}\"",
|
|
121
|
+
action_name, status, message), caused)
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
if io_error?(caused)
|
|
126
|
+
return ConnectionLostException.new(exception_message(
|
|
127
|
+
"010", "Exception while {}: Connection could not be established with message: \"{}\"",
|
|
128
|
+
action_name, caused.message), caused)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
ExternalTaskClientException.new(exception_message(
|
|
132
|
+
"011", "Exception while {}: ", action_name), error)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def create_message(id, action_name, message)
|
|
136
|
+
exception_message(id, "Exception while {}: {}", action_name, message)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def basic_auth_credentials_null_exception
|
|
140
|
+
ExternalTaskClientException.new(exception_message(
|
|
141
|
+
"012", "Basic authentication credentials (username, password) cannot be null"))
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def interceptor_null_exception
|
|
145
|
+
ExternalTaskClientException.new(exception_message(
|
|
146
|
+
"013", "Interceptor cannot be null"))
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def max_tasks_not_greater_than_zero_exception(max_tasks)
|
|
150
|
+
ExternalTaskClientException.new(exception_message(
|
|
151
|
+
"014", "Maximum amount of fetched tasks must be greater than zero, but was '{}'", max_tasks))
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def async_response_timeout_not_greater_than_zero_exception(async_response_timeout)
|
|
155
|
+
ExternalTaskClientException.new(exception_message(
|
|
156
|
+
"015", "Asynchronous response timeout must be greater than zero, but was '{}'", async_response_timeout))
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def value_mapper_exception_while_parsing_date(date, error)
|
|
160
|
+
ValueMapperException.new(exception_message(
|
|
161
|
+
"018", "Exception while mapping value: Cannot parse date '{}'", date), error)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def value_mapper_exception_due_to_no_object_type_name
|
|
165
|
+
ValueMapperException.new(exception_message(
|
|
166
|
+
"019", "Exception while mapping value: " \
|
|
167
|
+
"Cannot write serialized value for variable: no 'objectTypeName' provided for non-null value."))
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def value_mapper_exception_while_serializing_object(error)
|
|
171
|
+
ValueMapperException.new(exception_message(
|
|
172
|
+
"020", "Exception while mapping value: Cannot serialize object in variable."), error)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def value_mapper_exception_while_deserializing_object(error)
|
|
176
|
+
ValueMapperException.new(exception_message(
|
|
177
|
+
"021", "Exception while mapping value: Cannot deserialize object in variable."), error)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def value_mapper_exception_while_serializing_abstract_value(name)
|
|
181
|
+
ValueMapperException.new(exception_message(
|
|
182
|
+
"022", "Cannot serialize value of abstract type '{}'", name))
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def value_mapper_exception_due_to_serializer_not_found_for_typed_value(typed_value)
|
|
186
|
+
ValueMapperException.new(exception_message(
|
|
187
|
+
"023", "Cannot find serializer for value '{}'", typed_value))
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def value_mapper_exception_due_to_serializer_not_found_for_typed_value_field(value)
|
|
191
|
+
ValueMapperException.new(exception_message(
|
|
192
|
+
"024", "Cannot find serializer for value '{}'", value))
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def cannot_serialize_variable(variable_name, error)
|
|
196
|
+
ValueMapperException.new(exception_message(
|
|
197
|
+
"025", "Cannot serialize variable '{}'", variable_name), error)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def log_data_format_provider(provider)
|
|
201
|
+
log_info("026", "Discovered data format provider: {}[name = {}]",
|
|
202
|
+
provider.class.name, provider.data_format_name)
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def log_data_format(data_format)
|
|
206
|
+
log_info("025", "Discovered data format: {}[name = {}]", data_format.class.name, data_format.name)
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def log_data_format_configurator(configurator)
|
|
210
|
+
log_info("027", "Discovered data format configurator: {}[dataformat = {}]",
|
|
211
|
+
configurator.class.name, configurator.data_format_class.name)
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def multiple_providers_for_dataformat(data_format_name)
|
|
215
|
+
ExternalTaskClientException.new(exception_message(
|
|
216
|
+
"028", "Multiple providers found for dataformat '{}'", data_format_name))
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def pass_null_value_parameter(parameter_name)
|
|
220
|
+
ExternalTaskClientException.new(exception_message(
|
|
221
|
+
"030", "Null value is not allowed as '{}'", parameter_name))
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
private
|
|
225
|
+
|
|
226
|
+
def io_error?(error)
|
|
227
|
+
error.is_a?(IOError) || error.is_a?(SystemCallError) || error.is_a?(SocketError) ||
|
|
228
|
+
error.is_a?(Timeout::Error) || error.is_a?(OpenSSL::SSL::SSLError)
|
|
229
|
+
rescue NameError
|
|
230
|
+
error.is_a?(IOError) || error.is_a?(SystemCallError)
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require "time"
|
|
5
|
+
|
|
6
|
+
module Operaton
|
|
7
|
+
module Bpm
|
|
8
|
+
module Client
|
|
9
|
+
module Impl
|
|
10
|
+
# Stands in for the configured Jackson ObjectMapper: JSON encoding and
|
|
11
|
+
# decoding plus date handling with the client's configured date format.
|
|
12
|
+
#
|
|
13
|
+
# The date format is a Ruby strftime pattern. The default corresponds to
|
|
14
|
+
# the Java client's "yyyy-MM-dd'T'HH:mm:ss.SSSZ".
|
|
15
|
+
class ObjectMapper
|
|
16
|
+
DEFAULT_DATE_FORMAT = "%Y-%m-%dT%H:%M:%S.%L%z"
|
|
17
|
+
|
|
18
|
+
attr_reader :date_format
|
|
19
|
+
|
|
20
|
+
def initialize(date_format = DEFAULT_DATE_FORMAT)
|
|
21
|
+
@date_format = date_format
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def write_value_as_string(value)
|
|
25
|
+
JSON.generate(value)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def read_value(json_string)
|
|
29
|
+
JSON.parse(json_string)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def format_date(time)
|
|
33
|
+
time = time.to_time if !time.is_a?(Time) && time.respond_to?(:to_time)
|
|
34
|
+
time.strftime(date_format)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def parse_date(string)
|
|
38
|
+
Time.strptime(string, date_format)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../url_resolver"
|
|
4
|
+
|
|
5
|
+
module Operaton
|
|
6
|
+
module Bpm
|
|
7
|
+
module Client
|
|
8
|
+
module Impl
|
|
9
|
+
# Mirrors org.operaton.bpm.client.impl.PermanentUrlResolver
|
|
10
|
+
class PermanentUrlResolver
|
|
11
|
+
include UrlResolver
|
|
12
|
+
|
|
13
|
+
attr_accessor :base_url
|
|
14
|
+
|
|
15
|
+
def initialize(base_url)
|
|
16
|
+
@base_url = base_url
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|