From 03dd474d4d80778dfe35ffe479c12966859056cb Mon Sep 17 00:00:00 2001 From: antonbabak Date: Mon, 18 Dec 2023 15:33:28 +0100 Subject: [PATCH 1/3] Add EditorConfig and Refactoring --- .editorconfig | 333 ++++++++++++++++++ .../builders/PrebidServerResponseBuilder.java | 21 +- .../cache/handlers/GetCacheHandler.java | 2 +- .../cache/handlers/PostCacheHandler.java | 25 +- .../prebid/cache/metrics/MetricsRecorder.java | 6 +- .../org/prebid/cache/model/ErrorResponse.java | 2 - .../java/org/prebid/cache/model/Payload.java | 6 +- .../prebid/cache/model/PayloadTransfer.java | 2 - .../prebid/cache/model/PayloadWrapper.java | 2 - .../org/prebid/cache/model/RequestObject.java | 12 +- .../prebid/cache/model/ResponseObject.java | 10 +- .../redis/RedisConfigurationValidator.java | 2 - .../builders/PayloadWrapperResponseTests.java | 50 +-- .../PrebidServerResponseBuilderTests.java | 42 +-- .../cache/handlers/CacheHandlerTests.java | 31 +- .../cache/handlers/GetCacheHandlerTests.java | 53 ++- .../cache/handlers/PostCacheHandlerTests.java | 155 ++++---- .../prebid/cache/model/ContractModelTest.java | 13 +- .../cache/models/PayloadTransferTest.java | 1 - .../cache/models/PayloadWrapperTests.java | 33 +- ...eactiveTestAerospikeRepositoryContext.java | 4 +- .../ReactiveTestRedisRepositoryContext.java | 13 +- 22 files changed, 551 insertions(+), 267 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..90601a8 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,333 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +max_line_length = 120 +tab_width = 4 +ij_continuation_indent_size = 8 +ij_formatter_off_tag = @formatter:off +ij_formatter_on_tag = @formatter:on +ij_formatter_tags_enabled = false +ij_smart_tabs = false +ij_visual_guides = none +ij_wrap_on_typing = false + +[*.java] +ij_java_align_consecutive_assignments = false +ij_java_align_consecutive_variable_declarations = false +ij_java_align_group_field_declarations = false +ij_java_align_multiline_annotation_parameters = false +ij_java_align_multiline_array_initializer_expression = false +ij_java_align_multiline_assignment = false +ij_java_align_multiline_binary_operation = false +ij_java_align_multiline_chained_methods = false +ij_java_align_multiline_extends_list = false +ij_java_align_multiline_for = true +ij_java_align_multiline_method_parentheses = false +ij_java_align_multiline_parameters = true +ij_java_align_multiline_parameters_in_calls = false +ij_java_align_multiline_parenthesized_expression = false +ij_java_align_multiline_records = true +ij_java_align_multiline_resources = true +ij_java_align_multiline_ternary_operation = false +ij_java_align_multiline_text_blocks = false +ij_java_align_multiline_throws_list = false +ij_java_align_subsequent_simple_methods = false +ij_java_align_throws_keyword = false +ij_java_annotation_parameter_wrap = off +ij_java_array_initializer_new_line_after_left_brace = false +ij_java_array_initializer_right_brace_on_new_line = false +ij_java_array_initializer_wrap = off +ij_java_assert_statement_colon_on_next_line = false +ij_java_assert_statement_wrap = off +ij_java_assignment_wrap = off +ij_java_binary_operation_sign_on_next_line = false +ij_java_binary_operation_wrap = off +ij_java_blank_lines_after_anonymous_class_header = 0 +ij_java_blank_lines_after_class_header = 0 +ij_java_blank_lines_after_imports = 1 +ij_java_blank_lines_after_package = 1 +ij_java_blank_lines_around_class = 1 +ij_java_blank_lines_around_field = 0 +ij_java_blank_lines_around_field_in_interface = 0 +ij_java_blank_lines_around_initializer = 1 +ij_java_blank_lines_around_method = 1 +ij_java_blank_lines_around_method_in_interface = 1 +ij_java_blank_lines_before_class_end = 0 +ij_java_blank_lines_before_imports = 1 +ij_java_blank_lines_before_method_body = 0 +ij_java_blank_lines_before_package = 0 +ij_java_block_brace_style = end_of_line +ij_java_block_comment_at_first_column = true +ij_java_builder_methods = none +ij_java_call_parameters_new_line_after_left_paren = false +ij_java_call_parameters_right_paren_on_new_line = false +ij_java_call_parameters_wrap = off +ij_java_case_statement_on_separate_line = true +ij_java_catch_on_new_line = false +ij_java_class_annotation_wrap = split_into_lines +ij_java_class_brace_style = end_of_line +ij_java_class_count_to_use_import_on_demand = 999 +ij_java_class_names_in_javadoc = 1 +ij_java_do_not_indent_top_level_class_members = false +ij_java_do_not_wrap_after_single_annotation = false +ij_java_do_while_brace_force = never +ij_java_doc_add_blank_line_after_description = true +ij_java_doc_add_blank_line_after_param_comments = false +ij_java_doc_add_blank_line_after_return = false +ij_java_doc_add_p_tag_on_empty_lines = true +ij_java_doc_align_exception_comments = true +ij_java_doc_align_param_comments = true +ij_java_doc_do_not_wrap_if_one_line = false +ij_java_doc_enable_formatting = true +ij_java_doc_enable_leading_asterisks = true +ij_java_doc_indent_on_continuation = false +ij_java_doc_keep_empty_lines = true +ij_java_doc_keep_empty_parameter_tag = true +ij_java_doc_keep_empty_return_tag = true +ij_java_doc_keep_empty_throws_tag = true +ij_java_doc_keep_invalid_tags = true +ij_java_doc_param_description_on_new_line = false +ij_java_doc_preserve_line_breaks = false +ij_java_doc_use_throws_not_exception_tag = true +ij_java_else_on_new_line = false +ij_java_enum_constants_wrap = off +ij_java_extends_keyword_wrap = off +ij_java_extends_list_wrap = off +ij_java_field_annotation_wrap = split_into_lines +ij_java_finally_on_new_line = false +ij_java_for_brace_force = never +ij_java_for_statement_new_line_after_left_paren = false +ij_java_for_statement_right_paren_on_new_line = false +ij_java_for_statement_wrap = off +ij_java_generate_final_locals = false +ij_java_generate_final_parameters = false +ij_java_if_brace_force = never +ij_java_imports_layout = *,|,javax.**,java.**,|,$* +ij_java_indent_case_from_switch = true +ij_java_insert_inner_class_imports = false +ij_java_insert_override_annotation = true +ij_java_keep_blank_lines_before_right_brace = 2 +ij_java_keep_blank_lines_between_package_declaration_and_header = 2 +ij_java_keep_blank_lines_in_code = 2 +ij_java_keep_blank_lines_in_declarations = 2 +ij_java_keep_builder_methods_indents = false +ij_java_keep_control_statement_in_one_line = true +ij_java_keep_first_column_comment = true +ij_java_keep_indents_on_empty_lines = false +ij_java_keep_line_breaks = true +ij_java_keep_multiple_expressions_in_one_line = false +ij_java_keep_simple_blocks_in_one_line = false +ij_java_keep_simple_classes_in_one_line = false +ij_java_keep_simple_lambdas_in_one_line = false +ij_java_keep_simple_methods_in_one_line = false +ij_java_label_indent_absolute = false +ij_java_label_indent_size = 0 +ij_java_lambda_brace_style = end_of_line +ij_java_layout_static_imports_separately = true +ij_java_line_comment_add_space = false +ij_java_line_comment_at_first_column = true +ij_java_method_annotation_wrap = split_into_lines +ij_java_method_brace_style = end_of_line +ij_java_method_call_chain_wrap = off +ij_java_method_parameters_new_line_after_left_paren = false +ij_java_method_parameters_right_paren_on_new_line = false +ij_java_method_parameters_wrap = off +ij_java_modifier_list_wrap = false +ij_java_names_count_to_use_import_on_demand = 999 +ij_java_new_line_after_lparen_in_record_header = false +ij_java_packages_to_use_import_on_demand = java.awt.*,javax.swing.* +ij_java_parameter_annotation_wrap = off +ij_java_parentheses_expression_new_line_after_left_paren = false +ij_java_parentheses_expression_right_paren_on_new_line = false +ij_java_place_assignment_sign_on_next_line = false +ij_java_prefer_longer_names = true +ij_java_prefer_parameters_wrap = false +ij_java_record_components_wrap = normal +ij_java_repeat_synchronized = true +ij_java_replace_instanceof_and_cast = false +ij_java_replace_null_check = true +ij_java_replace_sum_lambda_with_method_ref = true +ij_java_resource_list_new_line_after_left_paren = false +ij_java_resource_list_right_paren_on_new_line = false +ij_java_resource_list_wrap = off +ij_java_rparen_on_new_line_in_record_header = false +ij_java_space_after_closing_angle_bracket_in_type_argument = false +ij_java_space_after_colon = true +ij_java_space_after_comma = true +ij_java_space_after_comma_in_type_arguments = true +ij_java_space_after_for_semicolon = true +ij_java_space_after_quest = true +ij_java_space_after_type_cast = true +ij_java_space_before_annotation_array_initializer_left_brace = false +ij_java_space_before_annotation_parameter_list = false +ij_java_space_before_array_initializer_left_brace = false +ij_java_space_before_catch_keyword = true +ij_java_space_before_catch_left_brace = true +ij_java_space_before_catch_parentheses = true +ij_java_space_before_class_left_brace = true +ij_java_space_before_colon = true +ij_java_space_before_colon_in_foreach = true +ij_java_space_before_comma = false +ij_java_space_before_do_left_brace = true +ij_java_space_before_else_keyword = true +ij_java_space_before_else_left_brace = true +ij_java_space_before_finally_keyword = true +ij_java_space_before_finally_left_brace = true +ij_java_space_before_for_left_brace = true +ij_java_space_before_for_parentheses = true +ij_java_space_before_for_semicolon = false +ij_java_space_before_if_left_brace = true +ij_java_space_before_if_parentheses = true +ij_java_space_before_method_call_parentheses = false +ij_java_space_before_method_left_brace = true +ij_java_space_before_method_parentheses = false +ij_java_space_before_opening_angle_bracket_in_type_parameter = false +ij_java_space_before_quest = true +ij_java_space_before_switch_left_brace = true +ij_java_space_before_switch_parentheses = true +ij_java_space_before_synchronized_left_brace = true +ij_java_space_before_synchronized_parentheses = true +ij_java_space_before_try_left_brace = true +ij_java_space_before_try_parentheses = true +ij_java_space_before_type_parameter_list = false +ij_java_space_before_while_keyword = true +ij_java_space_before_while_left_brace = true +ij_java_space_before_while_parentheses = true +ij_java_space_inside_one_line_enum_braces = false +ij_java_space_within_empty_array_initializer_braces = false +ij_java_space_within_empty_method_call_parentheses = false +ij_java_space_within_empty_method_parentheses = false +ij_java_spaces_around_additive_operators = true +ij_java_spaces_around_assignment_operators = true +ij_java_spaces_around_bitwise_operators = true +ij_java_spaces_around_equality_operators = true +ij_java_spaces_around_lambda_arrow = true +ij_java_spaces_around_logical_operators = true +ij_java_spaces_around_method_ref_dbl_colon = false +ij_java_spaces_around_multiplicative_operators = true +ij_java_spaces_around_relational_operators = true +ij_java_spaces_around_shift_operators = true +ij_java_spaces_around_type_bounds_in_type_parameters = true +ij_java_spaces_around_unary_operator = false +ij_java_spaces_within_angle_brackets = false +ij_java_spaces_within_annotation_parentheses = false +ij_java_spaces_within_array_initializer_braces = false +ij_java_spaces_within_braces = false +ij_java_spaces_within_brackets = false +ij_java_spaces_within_cast_parentheses = false +ij_java_spaces_within_catch_parentheses = false +ij_java_spaces_within_for_parentheses = false +ij_java_spaces_within_if_parentheses = false +ij_java_spaces_within_method_call_parentheses = false +ij_java_spaces_within_method_parentheses = false +ij_java_spaces_within_parentheses = false +ij_java_spaces_within_record_header = false +ij_java_spaces_within_switch_parentheses = false +ij_java_spaces_within_synchronized_parentheses = false +ij_java_spaces_within_try_parentheses = false +ij_java_spaces_within_while_parentheses = false +ij_java_special_else_if_treatment = true +ij_java_subclass_name_suffix = Impl +ij_java_ternary_operation_signs_on_next_line = false +ij_java_ternary_operation_wrap = off +ij_java_test_name_suffix = Test +ij_java_throws_keyword_wrap = off +ij_java_throws_list_wrap = off +ij_java_use_external_annotations = false +ij_java_use_fq_class_names = false +ij_java_use_relative_indents = false +ij_java_use_single_class_imports = true +ij_java_variable_annotation_wrap = off +ij_java_visibility = public +ij_java_while_brace_force = never +ij_java_while_on_new_line = false +ij_java_wrap_comments = false +ij_java_wrap_first_method_in_call_chain = false +ij_java_wrap_long_lines = false + +[.editorconfig] +ij_editorconfig_align_group_field_declarations = false +ij_editorconfig_space_after_colon = false +ij_editorconfig_space_after_comma = true +ij_editorconfig_space_before_colon = false +ij_editorconfig_space_before_comma = false +ij_editorconfig_spaces_around_assignment_operators = true + +[{*.ant,*.fxml,*.jhm,*.jnlp,*.jrxml,*.pom,*.rng,*.tld,*.wadl,*.wsdd,*.wsdl,*.xjb,*.xml,*.xsd,*.xsl,*.xslt,*.xul}] +ij_xml_align_attributes = true +ij_xml_align_text = false +ij_xml_attribute_wrap = normal +ij_xml_block_comment_at_first_column = true +ij_xml_keep_blank_lines = 2 +ij_xml_keep_indents_on_empty_lines = false +ij_xml_keep_line_breaks = true +ij_xml_keep_line_breaks_in_text = true +ij_xml_keep_whitespaces = false +ij_xml_keep_whitespaces_around_cdata = preserve +ij_xml_keep_whitespaces_inside_cdata = false +ij_xml_line_comment_at_first_column = true +ij_xml_space_after_tag_name = false +ij_xml_space_around_equals_in_attribute = false +ij_xml_space_inside_empty_tag = false +ij_xml_text_wrap = normal +ij_xml_use_custom_settings = false + +[{*.bash,*.sh,*.zsh}] +indent_size = 2 +tab_width = 2 +ij_shell_binary_ops_start_line = false +ij_shell_keep_column_alignment_padding = false +ij_shell_minify_program = false +ij_shell_redirect_followed_by_space = false +ij_shell_switch_cases_indented = false +ij_shell_use_unix_line_separator = true + +[{*.har,*.jsb2,*.jsb3,*.json,.babelrc,.eslintrc,.stylelintrc,bowerrc,jest.config}] +indent_size = 2 +ij_json_keep_blank_lines_in_code = 0 +ij_json_keep_indents_on_empty_lines = false +ij_json_keep_line_breaks = true +ij_json_space_after_colon = true +ij_json_space_after_comma = true +ij_json_space_before_colon = false +ij_json_space_before_comma = false +ij_json_spaces_within_braces = false +ij_json_spaces_within_brackets = false +ij_json_wrap_long_lines = false + +[{*.markdown,*.md}] +ij_markdown_force_one_space_after_blockquote_symbol = true +ij_markdown_force_one_space_after_header_symbol = true +ij_markdown_force_one_space_after_list_bullet = true +ij_markdown_force_one_space_between_words = true +ij_markdown_keep_indents_on_empty_lines = false +ij_markdown_max_lines_around_block_elements = 1 +ij_markdown_max_lines_around_header = 1 +ij_markdown_max_lines_between_paragraphs = 1 +ij_markdown_min_lines_around_block_elements = 1 +ij_markdown_min_lines_around_header = 1 +ij_markdown_min_lines_between_paragraphs = 1 + +[{*.properties,spring.handlers,spring.schemas}] +ij_properties_align_group_field_declarations = false +ij_properties_keep_blank_lines = false +ij_properties_key_value_delimiter = equals +ij_properties_spaces_around_key_value_delimiter = false + +[{*.yaml,*.yml}] +indent_size = 2 +ij_yaml_align_values_properties = do_not_align +ij_yaml_autoinsert_sequence_marker = true +ij_yaml_block_mapping_on_new_line = false +ij_yaml_indent_sequence_value = true +ij_yaml_keep_indents_on_empty_lines = false +ij_yaml_keep_line_breaks = true +ij_yaml_sequence_on_new_line = false +ij_yaml_space_before_colon = false +ij_yaml_spaces_within_braces = true +ij_yaml_spaces_within_brackets = true diff --git a/src/main/java/org/prebid/cache/builders/PrebidServerResponseBuilder.java b/src/main/java/org/prebid/cache/builders/PrebidServerResponseBuilder.java index b5eb190..ef12862 100644 --- a/src/main/java/org/prebid/cache/builders/PrebidServerResponseBuilder.java +++ b/src/main/java/org/prebid/cache/builders/PrebidServerResponseBuilder.java @@ -20,7 +20,7 @@ import java.util.Date; import java.util.function.Predicate; -import static org.springframework.web.reactive.function.BodyInserters.fromObject; +import static org.springframework.web.reactive.function.BodyInserters.fromValue; import static org.springframework.web.reactive.function.server.ServerResponse.status; @Component @@ -38,13 +38,13 @@ public PrebidServerResponseBuilder(final ApiConfig apiConfig) { public Mono createResponseMono(final ServerRequest request, final MediaType mediaType, final PayloadWrapper wrapper) { - return ok(request, mediaType).body(fromObject(wrapper.getPayload().getValue())); + return ok(request, mediaType).body(fromValue(wrapper.getPayload().getValue())); } public Mono createResponseMono(final ServerRequest request, final MediaType mediaType, final ResponseObject response) { - return ok(request, mediaType).body(fromObject(response)); + return ok(request, mediaType).body(fromValue(response)); } private ServerResponse.BodyBuilder ok(final ServerRequest request, final MediaType mediaType) { @@ -63,13 +63,14 @@ public Mono error(final Mono monoError, return monoError.transform(ThrowableTranslator::translate) .flatMap(translation -> addHeaders(status(translation.getHttpStatus()), request) - .body(Mono.just(new ErrorResponse( - translation.getHttpStatus().getReasonPhrase(), - translation.getHttpStatus().value(), - apiConfig.getPath(), - translation.getErrorMessage(), - new Date() - )), + .body(Mono.just( + ErrorResponse.builder() + .error(translation.getHttpStatus().getReasonPhrase()) + .status(translation.getHttpStatus().value()) + .path(apiConfig.getPath()) + .message(translation.getErrorMessage()) + .timestamp(new Date()) + .build()), ErrorResponse.class) ); } diff --git a/src/main/java/org/prebid/cache/handlers/GetCacheHandler.java b/src/main/java/org/prebid/cache/handlers/GetCacheHandler.java index 1dbd74a..e6c873e 100644 --- a/src/main/java/org/prebid/cache/handlers/GetCacheHandler.java +++ b/src/main/java/org/prebid/cache/handlers/GetCacheHandler.java @@ -119,7 +119,7 @@ private Mono processProxyRequest(final ServerRequest request, return webClient.get() .uri(uriBuilder -> uriBuilder.queryParam(ID_KEY, idKeyParam).build()) .headers(httpHeaders -> httpHeaders.addAll(request.headers().asHttpHeaders())) - .exchange() + .exchangeToMono(Mono::just) .transform(CircuitBreakerOperator.of(circuitBreaker)) .timeout(Duration.ofMillis(config.getTimeoutMs())) .subscribeOn(Schedulers.parallel()) diff --git a/src/main/java/org/prebid/cache/handlers/PostCacheHandler.java b/src/main/java/org/prebid/cache/handlers/PostCacheHandler.java index 26740ae..ce008e0 100644 --- a/src/main/java/org/prebid/cache/handlers/PostCacheHandler.java +++ b/src/main/java/org/prebid/cache/handlers/PostCacheHandler.java @@ -110,7 +110,7 @@ public Mono save(final ServerRequest request) { .map(payloadWrapperToMapTransformer) .collectList() .transform(this::validateErrorResult) - .map(ResponseObject::new) + .map(ResponseObject::of) .flatMap(response -> { if (response.getResponses().isEmpty()) { return ErrorHandler.createNoElementsFound(); @@ -123,15 +123,14 @@ public Mono save(final ServerRequest request) { } private Function payloadWrapperTransformer(Supplier currentDateProvider) { - return transfer -> - new PayloadWrapper( - RandomUUID.extractUUID(transfer), - transfer.getPrefix(), - new Payload(transfer.getType(), transfer.getKey(), transfer.valueAsString()), - transfer.getExpiry(), - currentDateProvider.get(), - RandomUUID.isExternalUUID(transfer) - ); + return transfer -> PayloadWrapper.builder() + .id(RandomUUID.extractUUID(transfer)) + .prefix(transfer.getPrefix()) + .payload(Payload.of(transfer.getType(), transfer.getKey(), transfer.valueAsString())) + .expiry(transfer.getExpiry()) + .lastModified(currentDateProvider.get()) + .isExternalId(RandomUUID.isExternalUUID(transfer)) + .build(); } private void validateUUID(final PayloadWrapper payload, final SynchronousSink sink) { @@ -172,13 +171,13 @@ private void sendRequestToSecondaryPrebidCacheHosts(List payload for (PayloadWrapper payloadWrapper : payloadWrappers) { payloadTransfers.add(wrapperToTransfer(payloadWrapper)); } - RequestObject requestObject = new RequestObject(payloadTransfers); + webClients.forEach((ip, webClient) -> webClient.post() .uri(uriBuilder -> uriBuilder.path(config.getSecondaryCachePath()) .queryParam("secondaryCache", "yes").build()) .contentType(MediaType.APPLICATION_JSON) - .syncBody(requestObject) - .exchange() + .bodyValue(RequestObject.of(payloadTransfers)) + .exchangeToMono(Mono::just) .transform(CircuitBreakerOperator.of(circuitBreaker)) .doOnError(throwable -> { metricsRecorder.getSecondaryCacheWriteError().increment(); diff --git a/src/main/java/org/prebid/cache/metrics/MetricsRecorder.java b/src/main/java/org/prebid/cache/metrics/MetricsRecorder.java index 6a158f0..02eac81 100644 --- a/src/main/java/org/prebid/cache/metrics/MetricsRecorder.java +++ b/src/main/java/org/prebid/cache/metrics/MetricsRecorder.java @@ -35,7 +35,7 @@ public enum MeasurementTag { PROXY_FAILURE("pbc.proxy.failure"); @Getter - private String tag; + private final String tag; MeasurementTag(final String tag) { this.tag = tag; @@ -43,8 +43,8 @@ public enum MeasurementTag { } public class MetricsRecorderTimer { - private Timer timer; - private Timer.Sample sample; + private final Timer timer; + private final Timer.Sample sample; MetricsRecorderTimer(String measurementTag) { timer = meterRegistry.timer(measurementTag); diff --git a/src/main/java/org/prebid/cache/model/ErrorResponse.java b/src/main/java/org/prebid/cache/model/ErrorResponse.java index 2000e78..0f7878b 100644 --- a/src/main/java/org/prebid/cache/model/ErrorResponse.java +++ b/src/main/java/org/prebid/cache/model/ErrorResponse.java @@ -1,14 +1,12 @@ package org.prebid.cache.model; import lombok.Builder; -import lombok.RequiredArgsConstructor; import lombok.Value; import java.util.Date; @Value @Builder -@RequiredArgsConstructor public class ErrorResponse { String error; int status; diff --git a/src/main/java/org/prebid/cache/model/Payload.java b/src/main/java/org/prebid/cache/model/Payload.java index 566b341..4331b40 100644 --- a/src/main/java/org/prebid/cache/model/Payload.java +++ b/src/main/java/org/prebid/cache/model/Payload.java @@ -1,12 +1,8 @@ package org.prebid.cache.model; -import lombok.Builder; -import lombok.RequiredArgsConstructor; import lombok.Value; -@Value -@Builder -@RequiredArgsConstructor +@Value(staticConstructor = "of") public class Payload { String type; String key; diff --git a/src/main/java/org/prebid/cache/model/PayloadTransfer.java b/src/main/java/org/prebid/cache/model/PayloadTransfer.java index 409e7a4..1ba0d0a 100644 --- a/src/main/java/org/prebid/cache/model/PayloadTransfer.java +++ b/src/main/java/org/prebid/cache/model/PayloadTransfer.java @@ -2,13 +2,11 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import lombok.Builder; -import lombok.RequiredArgsConstructor; import lombok.Value; import org.prebid.cache.helpers.Json; @Value @Builder(toBuilder = true) -@RequiredArgsConstructor @JsonIgnoreProperties(ignoreUnknown = true) public class PayloadTransfer { String type; diff --git a/src/main/java/org/prebid/cache/model/PayloadWrapper.java b/src/main/java/org/prebid/cache/model/PayloadWrapper.java index 9ad286d..c5288e1 100644 --- a/src/main/java/org/prebid/cache/model/PayloadWrapper.java +++ b/src/main/java/org/prebid/cache/model/PayloadWrapper.java @@ -1,7 +1,6 @@ package org.prebid.cache.model; import lombok.Builder; -import lombok.RequiredArgsConstructor; import lombok.Value; import org.prebid.cache.exceptions.PayloadWrapperPropertyException; @@ -9,7 +8,6 @@ @Value @Builder -@RequiredArgsConstructor public class PayloadWrapper { String id; String prefix; diff --git a/src/main/java/org/prebid/cache/model/RequestObject.java b/src/main/java/org/prebid/cache/model/RequestObject.java index 5c8f3da..c73e9aa 100644 --- a/src/main/java/org/prebid/cache/model/RequestObject.java +++ b/src/main/java/org/prebid/cache/model/RequestObject.java @@ -1,18 +1,10 @@ package org.prebid.cache.model; -import lombok.Builder; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.Singular; import lombok.Value; import java.util.List; -@Value -@Builder -@RequiredArgsConstructor +@Value(staticConstructor = "of") public class RequestObject { - @NonNull - @Singular - private List puts; + List puts; } diff --git a/src/main/java/org/prebid/cache/model/ResponseObject.java b/src/main/java/org/prebid/cache/model/ResponseObject.java index 3808fbe..2145f9c 100644 --- a/src/main/java/org/prebid/cache/model/ResponseObject.java +++ b/src/main/java/org/prebid/cache/model/ResponseObject.java @@ -1,19 +1,11 @@ package org.prebid.cache.model; -import lombok.Builder; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.Singular; import lombok.Value; import java.util.List; import java.util.Map; -@Value -@Builder -@RequiredArgsConstructor +@Value(staticConstructor = "of") public class ResponseObject { - @NonNull - @Singular List> responses; } diff --git a/src/main/java/org/prebid/cache/repository/redis/RedisConfigurationValidator.java b/src/main/java/org/prebid/cache/repository/redis/RedisConfigurationValidator.java index 18f66ce..bba991d 100644 --- a/src/main/java/org/prebid/cache/repository/redis/RedisConfigurationValidator.java +++ b/src/main/java/org/prebid/cache/repository/redis/RedisConfigurationValidator.java @@ -58,9 +58,7 @@ private static ValidationResult validateClusterConfiguration(Environment environ @Value(staticConstructor = "of") private static class ValidationResult { - boolean defined; - boolean valid; } } diff --git a/src/test/java/org/prebid/cache/builders/PayloadWrapperResponseTests.java b/src/test/java/org/prebid/cache/builders/PayloadWrapperResponseTests.java index 5e220e4..b6dbe3b 100644 --- a/src/test/java/org/prebid/cache/builders/PayloadWrapperResponseTests.java +++ b/src/test/java/org/prebid/cache/builders/PayloadWrapperResponseTests.java @@ -1,9 +1,8 @@ package org.prebid.cache.builders; +import org.junit.jupiter.api.BeforeAll; import org.prebid.cache.model.Payload; import org.prebid.cache.model.PayloadWrapper; -import lombok.val; -import org.junit.jupiter.api.BeforeAll; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.MediaType; @@ -14,8 +13,21 @@ import static org.springframework.http.MediaType.APPLICATION_XML; @SpringBootTest -public abstract class PayloadWrapperResponseTests -{ +public abstract class PayloadWrapperResponseTests { + static final String XML_RESPONSE = """ + + + + + ]]> + + + """; + static final String JSON_RESPONSE = """ + { + "creativeCode" : "" + }"""; + static PayloadWrapper jsonPayloadWrapper; static PayloadWrapper jsonUTF8PayloadWrapper; static PayloadWrapper xmlPayloadWrapper; @@ -37,22 +49,6 @@ static boolean isJsonUTF8(MediaType mediaType) { return mediaType.equals(APPLICATION_JSON_UTF8); } - private static String xmlResponse() { - return "\n" + - "\n" + - " \n" + - " \n" + - " ]]>\n" + - "\n" + - "\n"; - } - - private static String jsonResponse() { - return "{\n" + - " \"creativeCode\" : \"\"\n" + - "}"; - } - private static PayloadWrapper createJsonPayloadWrapper() { return createPayloadWrapper(APPLICATION_JSON); } @@ -66,12 +62,18 @@ private static PayloadWrapper createXmlPayloadWrapper() { private static PayloadWrapper createPayloadWrapper(MediaType mediaType) { String payloadValue = null; if (isJson(mediaType) || isJsonUTF8(mediaType)) { - payloadValue = jsonResponse(); + payloadValue = JSON_RESPONSE; } else if (isXml(mediaType)) { - payloadValue = xmlResponse(); + payloadValue = XML_RESPONSE; } - final var payload = new Payload("json", "1234567890", payloadValue); - return new PayloadWrapper("","prefix", payload, 200L, new Date(), false); + return PayloadWrapper.builder() + .id("") + .prefix("prefix") + .payload(Payload.of("json", "1234567890", payloadValue)) + .expiry(200L) + .lastModified(new Date()) + .isExternalId(false) + .build(); } } diff --git a/src/test/java/org/prebid/cache/builders/PrebidServerResponseBuilderTests.java b/src/test/java/org/prebid/cache/builders/PrebidServerResponseBuilderTests.java index 804cda7..c95475d 100644 --- a/src/test/java/org/prebid/cache/builders/PrebidServerResponseBuilderTests.java +++ b/src/test/java/org/prebid/cache/builders/PrebidServerResponseBuilderTests.java @@ -35,14 +35,13 @@ @ExtendWith(SpringExtension.class) @ContextConfiguration(classes={PrebidServerResponseBuilder.class, ApiConfig.class}) @SpringBootTest -class PrebidServerResponseBuilderTests extends PayloadWrapperResponseTests -{ +class PrebidServerResponseBuilderTests extends PayloadWrapperResponseTests { + @Autowired PrebidServerResponseBuilder builder; private Mono createResponseMono(final ServerRequest request, - final MediaType mediaType) - { + final MediaType mediaType) { if (isJson(mediaType)) { return builder.createResponseMono(request, mediaType, jsonPayloadWrapper); } else if (isJsonUTF8(mediaType)) { @@ -78,7 +77,7 @@ private void verifyServerResponse(MediaType mediaType) { } private void verifyErrorResponse(HttpStatus status) { - final var request = MockServerRequest.builder().build(); + final MockServerRequest request = MockServerRequest.builder().build(); final Consumer> consumer = signal -> assertEquals(status.value(), signal.get().statusCode().value()); @@ -122,8 +121,7 @@ void verifyJsonServerResponse() { void verifyRepoError() { verifyErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR); } @SpringBootTest - public abstract static class PayloadTests - { + public abstract static class PayloadTests { protected static PayloadWrapper jsonPayloadWrapper; protected static PayloadWrapper jsonUTF8PayloadWrapper; protected static PayloadWrapper xmlPayloadWrapper; @@ -147,22 +145,6 @@ protected static boolean isJsonUTF8(MediaType mediaType) { return mediaType.equals(APPLICATION_JSON_UTF8); } - private static String xmlResponse() { - return "\n" + - "\n" + - " \n" + - " \n" + - " ]]>\n" + - "\n" + - "\n"; - } - - private static String jsonResponse() { - return "{\n" + - " \"creativeCode\" : \"\"\n" + - "}"; - } - private static PayloadWrapper createJsonPayloadWrapper() { return createPayloadWrapper(APPLICATION_JSON); } @@ -178,13 +160,19 @@ private static PayloadWrapper createXmlPayloadWrapper() { private static PayloadWrapper createPayloadWrapper(MediaType mediaType) { String payloadValue = null; if (isJson(mediaType) || isJsonUTF8(mediaType)) { - payloadValue = jsonResponse(); + payloadValue = JSON_RESPONSE; } else if (isXml(mediaType)) { - payloadValue = xmlResponse(); + payloadValue = XML_RESPONSE; } - final var payload = new Payload("json", "1234567890", payloadValue); - return new PayloadWrapper("", "prefix", payload, 200L, new Date(), false); + return PayloadWrapper.builder() + .id("") + .prefix("prefix") + .payload(Payload.of("json", "1234567890", payloadValue)) + .expiry(200L) + .lastModified(new Date()) + .isExternalId(false) + .build(); } } } diff --git a/src/test/java/org/prebid/cache/handlers/CacheHandlerTests.java b/src/test/java/org/prebid/cache/handlers/CacheHandlerTests.java index d92b3de..49c6b69 100644 --- a/src/test/java/org/prebid/cache/handlers/CacheHandlerTests.java +++ b/src/test/java/org/prebid/cache/handlers/CacheHandlerTests.java @@ -2,28 +2,43 @@ import org.prebid.cache.exceptions.RequestParsingException; import org.prebid.cache.exceptions.RepositoryException; +import org.prebid.cache.model.Payload; +import org.prebid.cache.model.PayloadTransfer; +import org.prebid.cache.model.PayloadWrapper; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +import java.util.Date; import java.util.function.Consumer; import static org.junit.jupiter.api.Assertions.assertTrue; abstract class CacheHandlerTests { - void verifyRepositoryError(CacheHandler handler) { - final Consumer consumer = (t) -> { - assertTrue(t instanceof RepositoryException); - }; + static final PayloadTransfer PAYLOAD_TRANSFER = PayloadTransfer.builder() + .type("json") + .key("2be04ba5-8f9b-4a1e-8100-d573c40312f8") + .value("") + .expiry(1800L) + .prefix("prebid_") + .build(); + + static final PayloadWrapper PAYLOAD_WRAPPER = PayloadWrapper.builder() + .id("2be04ba5-8f9b-4a1e-8100-d573c40312f8") + .prefix("prebid_") + .payload(Payload.of("json", "2be04ba5-8f9b-4a1e-8100-d573c40312f8", "")) + .expiry(1800L) + .lastModified(new Date(100)) + .isExternalId(true) + .build(); + void verifyRepositoryError(CacheHandler handler) { + final Consumer consumer = t -> assertTrue(t instanceof RepositoryException); verifyResultTest(consumer, handler); } void verifyJacksonError(CacheHandler handler) { - final Consumer consumer = (t) -> { - assertTrue(t instanceof RequestParsingException); - }; - + final Consumer consumer = t -> assertTrue(t instanceof RequestParsingException); verifyResultTest(consumer, handler); } diff --git a/src/test/java/org/prebid/cache/handlers/GetCacheHandlerTests.java b/src/test/java/org/prebid/cache/handlers/GetCacheHandlerTests.java index 4573da7..566ee64 100644 --- a/src/test/java/org/prebid/cache/handlers/GetCacheHandlerTests.java +++ b/src/test/java/org/prebid/cache/handlers/GetCacheHandlerTests.java @@ -10,7 +10,6 @@ import org.prebid.cache.config.CircuitBreakerPropertyConfiguration; import org.prebid.cache.metrics.MetricsRecorder; import org.prebid.cache.metrics.MetricsRecorderTest; -import org.prebid.cache.model.Payload; import org.prebid.cache.model.PayloadWrapper; import org.prebid.cache.repository.CacheConfig; import org.prebid.cache.repository.ReactiveRepository; @@ -31,7 +30,6 @@ import reactor.core.publisher.Signal; import reactor.test.StepVerifier; -import java.util.Date; import java.util.function.Consumer; import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; @@ -42,7 +40,6 @@ import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; import static com.github.tomakehurst.wiremock.client.WireMock.verify; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.BDDMockito.given; import static org.springframework.http.HttpHeaders.CONTENT_TYPE; @@ -112,11 +109,13 @@ void testVerifyError() { verifyRepositoryError(handler); } + private static Consumer assertNotFoundStatusCode() { + return response -> assertEquals(response.statusCode().value(), 404); + } + @Test void testVerifyFetch() { - final var payload = new Payload("json", "2be04ba5-8f9b-4a1e-8100-d573c40312f8", ""); - final var payloadWrapper = new PayloadWrapper("12", "prebid_", payload, 1800L, new Date(), true); - given(repository.findById("prebid_a8db2208-d085-444c-9721-c1161d7f09ce")).willReturn(Mono.just(payloadWrapper)); + given(repository.findById("prebid_a8db2208-d085-444c-9721-c1161d7f09ce")).willReturn(Mono.just(PAYLOAD_WRAPPER)); final var requestMono = MockServerRequest.builder() .method(HttpMethod.GET) @@ -127,21 +126,21 @@ void testVerifyFetch() { responseMono.doOnEach(assertSignalStatusCode(200)).subscribe(); StepVerifier.create(responseMono) - .expectSubscription() - .expectNextMatches(t -> true) - .expectComplete() - .verify(); + .expectSubscription() + .expectNextMatches(t -> true) + .expectComplete() + .verify(); } @Test void testVerifyFetchWithCacheHostParam() { serverMock.stubFor(get(urlPathEqualTo("/cache")) - .willReturn(aResponse().withHeader(HttpHeaders.CONTENT_TYPE, "application/json;charset=utf-8") - .withBody("{\"uuid\":\"2be04ba5-8f9b-4a1e-8100-d573c40312f8\"}"))); + .willReturn(aResponse().withHeader(HttpHeaders.CONTENT_TYPE, "application/json;charset=utf-8") + .withBody("{\"uuid\":\"2be04ba5-8f9b-4a1e-8100-d573c40312f8\"}"))); final var requestMono = MockServerRequest.builder() - .method(HttpMethod.GET) - .header(CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE) + .method(HttpMethod.GET) + .header(CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .queryParam("uuid", "a8db2208-d085-444c-9721-c1161d7f09ce") .queryParam("ch", "localhost:8080") .build(); @@ -156,8 +155,8 @@ void testVerifyFetchWithCacheHostParam() { .verify(); verify(getRequestedFor(urlPathEqualTo("/cache")) - .withQueryParam("uuid", equalTo("a8db2208-d085-444c-9721-c1161d7f09ce")) - .withHeader(HttpHeaders.CONTENT_TYPE, equalToIgnoreCase(MediaType.APPLICATION_JSON_UTF8_VALUE)) + .withQueryParam("uuid", equalTo("a8db2208-d085-444c-9721-c1161d7f09ce")) + .withHeader(HttpHeaders.CONTENT_TYPE, equalToIgnoreCase(MediaType.APPLICATION_JSON_VALUE)) ); } @@ -173,7 +172,7 @@ void testVerifyFailForNotFoundResourceWithCacheHostParam() { responseMono.doOnEach(assertSignalStatusCode(404)).subscribe(); StepVerifier.create(responseMono) - .consumeNextWith(assertStatusCode(404)) + .consumeNextWith(assertNotFoundStatusCode()) .expectComplete() .verify(); } @@ -187,8 +186,8 @@ void testVerifyFetchReturnsBadRequestWhenResponseStatusIsNotOk() { .withBody("{\"uuid\":\"2be04ba5-8f9b-4a1e-8100-d573c40312f8\"}"))); final var requestMono = MockServerRequest.builder() - .method(HttpMethod.GET) - .header(CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE) + .method(HttpMethod.GET) + .header(CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .queryParam("uuid", "a8db2208-d085-444c-9721-c1161d7f09ce") .queryParam("ch", "localhost:8080") .build(); @@ -197,21 +196,17 @@ void testVerifyFetchReturnsBadRequestWhenResponseStatusIsNotOk() { responseMono.doOnEach(assertSignalStatusCode(400)).subscribe(); StepVerifier.create(responseMono) - .expectSubscription() - .expectNextMatches(t -> true) - .expectComplete() - .verify(); + .expectSubscription() + .expectNextMatches(t -> true) + .expectComplete() + .verify(); verify(getRequestedFor(urlPathEqualTo("/cache")) - .withQueryParam("uuid", equalTo("a8db2208-d085-444c-9721-c1161d7f09ce")) - .withHeader(HttpHeaders.CONTENT_TYPE, equalToIgnoreCase(MediaType.APPLICATION_JSON_UTF8_VALUE)) + .withQueryParam("uuid", equalTo("a8db2208-d085-444c-9721-c1161d7f09ce")) + .withHeader(HttpHeaders.CONTENT_TYPE, equalToIgnoreCase(MediaType.APPLICATION_JSON_VALUE)) ); } - private static Consumer assertStatusCode(int statusCode) { - return response -> assertEquals(response.statusCode().value(), statusCode); - } - private static Consumer> assertSignalStatusCode(int statusCode) { return signal -> { assertTrue(signal.isOnComplete()); diff --git a/src/test/java/org/prebid/cache/handlers/PostCacheHandlerTests.java b/src/test/java/org/prebid/cache/handlers/PostCacheHandlerTests.java index b74055c..c335d82 100644 --- a/src/test/java/org/prebid/cache/handlers/PostCacheHandlerTests.java +++ b/src/test/java/org/prebid/cache/handlers/PostCacheHandlerTests.java @@ -1,7 +1,7 @@ package org.prebid.cache.handlers; import com.github.tomakehurst.wiremock.WireMockServer; -import com.google.common.collect.ImmutableList; +import com.github.tomakehurst.wiremock.matching.RequestPatternBuilder; import io.github.resilience4j.circuitbreaker.CircuitBreaker; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -13,8 +13,6 @@ import org.prebid.cache.helpers.CurrentDateProvider; import org.prebid.cache.metrics.MetricsRecorder; import org.prebid.cache.metrics.MetricsRecorderTest; -import org.prebid.cache.model.Payload; -import org.prebid.cache.model.PayloadTransfer; import org.prebid.cache.model.PayloadWrapper; import org.prebid.cache.model.RequestObject; import org.prebid.cache.repository.CacheConfig; @@ -116,69 +114,59 @@ public void teardown() { @Test void testVerifySave() { - final var payloadInner = new Payload("json", "2be04ba5-8f9b-4a1e-8100-d573c40312f8", ""); - final var payloadWrapper = new PayloadWrapper("2be04ba5-8f9b-4a1e-8100-d573c40312f8", "prebid_", payloadInner - , 1800L, new Date(100), true); given(currentDateProvider.get()).willReturn(new Date(100)); - given(repository.save(payloadWrapper)).willReturn(Mono.just(payloadWrapper)); + given(repository.save(PAYLOAD_WRAPPER)).willReturn(Mono.just(PAYLOAD_WRAPPER)); - final var handler = new PostCacheHandler(repository, cacheConfig, metricsRecorder, builder, - currentDateProvider, webClientCircuitBreaker, samplingRate); + final PostCacheHandler handler = new PostCacheHandler(repository, cacheConfig, metricsRecorder, builder, + currentDateProvider, webClientCircuitBreaker, samplingRate); - final var payload = new PayloadTransfer("json", "2be04ba5-8f9b-4a1e-8100-d573c40312f8", "", 1800L, null, - "prebid_"); - final var request = Mono.just(new RequestObject(ImmutableList.of(payload))); - final var requestMono = MockServerRequest.builder() - .method(HttpMethod.POST) - .header(CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE) - .body(request); + final Mono request = Mono.just(RequestObject.of(Collections.singletonList(PAYLOAD_TRANSFER))); + final MockServerRequest requestMono = MockServerRequest.builder() + .method(HttpMethod.POST) + .header(CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE) + .body(request); - final var responseMono = handler.save(requestMono); + final Mono responseMono = handler.save(requestMono); final Consumer consumer = - serverResponse -> assertEquals(200, serverResponse.statusCode().value()); + serverResponse -> assertEquals(200, serverResponse.statusCode().value()); StepVerifier.create(responseMono) - .consumeNextWith(consumer) - .expectComplete() - .verify(); + .consumeNextWith(consumer) + .expectComplete() + .verify(); } @Test void testSecondaryCacheSuccess() { - final var payloadInner = new Payload("json", "2be04ba5-8f9b-4a1e-8100-d573c40312f8", ""); - final var payloadWrapper = new PayloadWrapper("2be04ba5-8f9b-4a1e-8100-d573c40312f8", "prebid_", payloadInner - , 1800L, new Date(100), true); given(currentDateProvider.get()).willReturn(new Date(100)); - given(repository.save(payloadWrapper)).willReturn(Mono.just(payloadWrapper)); + given(repository.save(PAYLOAD_WRAPPER)).willReturn(Mono.just(PAYLOAD_WRAPPER)); serverMock.stubFor(post(urlPathEqualTo("/cache")) - .willReturn(aResponse().withBody("{\"responses\":[{\"uuid\":\"2be04ba5-8f9b-4a1e-8100-d573c40312f8\"}]}"))); + .willReturn(aResponse().withBody("{\"responses\":[{\"uuid\":\"2be04ba5-8f9b-4a1e-8100-d573c40312f8\"}]}"))); - final var handler = new PostCacheHandler(repository, cacheConfig, metricsRecorder, builder, - currentDateProvider, webClientCircuitBreaker, samplingRate); + final PostCacheHandler handler = new PostCacheHandler(repository, cacheConfig, metricsRecorder, builder, + currentDateProvider, webClientCircuitBreaker, samplingRate); - final var payload = new PayloadTransfer("json", "2be04ba5-8f9b-4a1e-8100-d573c40312f8", "", 1800L, null, - "prebid_"); - final var request = Mono.just(new RequestObject(ImmutableList.of(payload))); - final var requestMono = MockServerRequest.builder() - .method(HttpMethod.POST) - .header(CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE) - .body(request); + final Mono request = Mono.just(RequestObject.of(Collections.singletonList(PAYLOAD_TRANSFER))); + final MockServerRequest requestMono = MockServerRequest.builder() + .method(HttpMethod.POST) + .header(CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE) + .body(request); - final var responseMono = handler.save(requestMono); + final Mono responseMono = handler.save(requestMono); final Consumer consumer = - serverResponse -> assertEquals(200, serverResponse.statusCode().value()); + serverResponse -> assertEquals(200, serverResponse.statusCode().value()); StepVerifier.create(responseMono) - .consumeNextWith(consumer) - .expectComplete() - .verify(); + .consumeNextWith(consumer) + .expectComplete() + .verify(); - final var requestPatternBuilder = postRequestedFor(urlPathEqualTo("/cache")) - .withQueryParam("secondaryCache", equalTo("yes")) - .withHeader(HttpHeaders.CONTENT_TYPE, equalToIgnoreCase("application/json")); + final RequestPatternBuilder requestPatternBuilder = postRequestedFor(urlPathEqualTo("/cache")) + .withQueryParam("secondaryCache", equalTo("yes")) + .withHeader(HttpHeaders.CONTENT_TYPE, equalToIgnoreCase("application/json")); awaitAndVerify(requestPatternBuilder, 5000); } @@ -186,66 +174,61 @@ void testSecondaryCacheSuccess() { @Test void testExternalUUIDInvalid() { //given - final var cacheConfigLocal = new CacheConfig(cacheConfig.getPrefix(), cacheConfig.getExpirySec(), - cacheConfig.getTimeoutMs(), - cacheConfig.getMinExpiry(), cacheConfig.getMaxExpiry(), - false, Collections.emptyList(), cacheConfig.getSecondaryCachePath(), 100, 100, "example.com", "http"); - final var handler = new PostCacheHandler(repository, cacheConfigLocal, metricsRecorder, builder, - currentDateProvider, webClientCircuitBreaker, samplingRate); - - final var payload = new PayloadTransfer("json", "2be04ba5-8f9b-4a1e-8100-d573c40312f8", "", 1800L, null, - "prebid_"); - final var request = Mono.just(new RequestObject(ImmutableList.of(payload))); - final var requestMono = MockServerRequest.builder() - .method(HttpMethod.POST) - .header(CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE) - .body(request); - - final var responseMono = handler.save(requestMono); + final CacheConfig cacheConfigLocal = new CacheConfig(cacheConfig.getPrefix(), cacheConfig.getExpirySec(), + cacheConfig.getTimeoutMs(), + cacheConfig.getMinExpiry(), cacheConfig.getMaxExpiry(), + false, Collections.emptyList(), cacheConfig.getSecondaryCachePath(), 100, 100, "example.com", "http"); + final PostCacheHandler handler = new PostCacheHandler(repository, cacheConfigLocal, metricsRecorder, builder, + currentDateProvider, webClientCircuitBreaker, samplingRate); + + final Mono request = Mono.just(RequestObject.of(Collections.singletonList(PAYLOAD_TRANSFER))); + final MockServerRequest requestMono = MockServerRequest.builder() + .method(HttpMethod.POST) + .header(CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE) + .body(request); + + final Mono responseMono = handler.save(requestMono); final Consumer consumer = - serverResponse -> assertEquals(400, serverResponse.statusCode().value()); + serverResponse -> assertEquals(400, serverResponse.statusCode().value()); StepVerifier.create(responseMono) - .consumeNextWith(consumer) - .expectComplete() - .verify(); + .consumeNextWith(consumer) + .expectComplete() + .verify(); } @Test void testUUIDDuplication() { - final var payloadInner = new Payload("json", "2be04ba5-8f9b-4a1e-8100-d573c40312f8", ""); - final var payloadWrapper = new PayloadWrapper("2be04ba5-8f9b-4a1e-8100-d573c40312f8", "prebid_", payloadInner - , 1800L, new Date(100), true); given(currentDateProvider.get()).willReturn(new Date(100)); - given(repository.save(payloadWrapper)).willReturn(Mono.just(payloadWrapper)).willReturn(Mono.error(new DuplicateKeyException(""))); + given(repository.save(PAYLOAD_WRAPPER)) + .willReturn(Mono.just(PAYLOAD_WRAPPER)) + .willReturn(Mono.error(new DuplicateKeyException(""))); - final var cacheConfigLocal = new CacheConfig(cacheConfig.getPrefix(), cacheConfig.getExpirySec(), - cacheConfig.getTimeoutMs(), - 5, cacheConfig.getMaxExpiry(), cacheConfig.isAllowExternalUUID(), - Collections.emptyList(), cacheConfig.getSecondaryCachePath(), 100, 100, "example.com", "http"); - final var handler = new PostCacheHandler(repository, cacheConfigLocal, metricsRecorder, builder, - currentDateProvider, webClientCircuitBreaker, samplingRate); + final CacheConfig cacheConfigLocal = new CacheConfig(cacheConfig.getPrefix(), cacheConfig.getExpirySec(), + cacheConfig.getTimeoutMs(), + 5, cacheConfig.getMaxExpiry(), cacheConfig.isAllowExternalUUID(), + Collections.emptyList(), cacheConfig.getSecondaryCachePath(), 100, 100, "example.com", "http"); + final PostCacheHandler handler = new PostCacheHandler(repository, cacheConfigLocal, metricsRecorder, builder, + currentDateProvider, webClientCircuitBreaker, samplingRate); - final var payload = new PayloadTransfer("json", "2be04ba5-8f9b-4a1e-8100-d573c40312f8", "", 1800L, null, - "prebid_"); - final var request = Mono.just(new RequestObject(ImmutableList.of(payload))); - final var requestMono = MockServerRequest.builder() - .method(HttpMethod.POST) - .header(CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE) - .body(request); + final Mono request = Mono.just(RequestObject.of(Collections.singletonList(PAYLOAD_TRANSFER))); + final MockServerRequest requestMono = MockServerRequest.builder() + .method(HttpMethod.POST) + .header(CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE) + .body(request); - final var responseMono = handler.save(requestMono); + final Mono responseMono = handler.save(requestMono); final Consumer consumer = - serverResponse -> assertEquals(200, serverResponse.statusCode().value()); + serverResponse -> assertEquals(200, serverResponse.statusCode().value()); StepVerifier.create(responseMono) - .consumeNextWith(consumer) - .expectComplete() - .verify(); + .consumeNextWith(consumer) + .expectComplete() + .verify(); - final var responseMonoSecond = handler.save(requestMono); + final Mono responseMonoSecond = handler.save(requestMono); final Consumer consumerSecond = serverResponse -> assertEquals(400, serverResponse.statusCode().value()); diff --git a/src/test/java/org/prebid/cache/model/ContractModelTest.java b/src/test/java/org/prebid/cache/model/ContractModelTest.java index e93275c..4d8012e 100644 --- a/src/test/java/org/prebid/cache/model/ContractModelTest.java +++ b/src/test/java/org/prebid/cache/model/ContractModelTest.java @@ -4,6 +4,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.reflections.Reflections; +import org.reflections.scanners.Scanners; import org.reflections.scanners.SubTypesScanner; import org.reflections.util.ConfigurationBuilder; import org.reflections.util.FilterBuilder; @@ -19,18 +20,14 @@ void verifyEqualsAndHashCode(Class clazz) { } static Iterable> modelClassProvider() { - Reflections reflections = new Reflections( - new ConfigurationBuilder().setScanners( - new SubTypesScanner(false) - ) + new ConfigurationBuilder().setScanners(Scanners.SubTypes.filterResultsBy(s -> true)) .setUrls(forPackage("org.prebid.cache", staticClassLoader())) .filterInputsBy(new FilterBuilder() - .include("org\\.prebid\\.cache\\.model\\..*\\.class") - .exclude("org\\.prebid\\.cache\\.model\\..*(Builder|Test)\\.class") - ) + .includePattern("org\\.prebid\\.cache\\.model\\..*\\.class") + .excludePattern("org\\.prebid\\.cache\\.model\\..*(Builder|Test)\\.class")) ); return reflections.getSubTypesOf(Object.class); } -} \ No newline at end of file +} diff --git a/src/test/java/org/prebid/cache/models/PayloadTransferTest.java b/src/test/java/org/prebid/cache/models/PayloadTransferTest.java index f1b050d..0c82ad0 100644 --- a/src/test/java/org/prebid/cache/models/PayloadTransferTest.java +++ b/src/test/java/org/prebid/cache/models/PayloadTransferTest.java @@ -1,7 +1,6 @@ package org.prebid.cache.models; import lombok.Builder; -import lombok.val; import org.junit.jupiter.api.Test; import org.prebid.cache.model.PayloadTransfer; diff --git a/src/test/java/org/prebid/cache/models/PayloadWrapperTests.java b/src/test/java/org/prebid/cache/models/PayloadWrapperTests.java index cfbd496..c650924 100644 --- a/src/test/java/org/prebid/cache/models/PayloadWrapperTests.java +++ b/src/test/java/org/prebid/cache/models/PayloadWrapperTests.java @@ -1,39 +1,38 @@ package org.prebid.cache.models; +import org.junit.jupiter.api.Test; import org.prebid.cache.exceptions.PayloadWrapperPropertyException; import org.prebid.cache.helpers.Json; import org.prebid.cache.model.PayloadWrapper; -import lombok.val; -import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; -@SuppressWarnings("FieldCanBeLocal") class PayloadWrapperTests { - private static String jsonWithExpiry = "{\n" + - " \"id\": \"2be04ba5-8f9b-4a1e-8100-d573c40312f8\",\n" + - " \"prefix\": \"prebid_\",\n" + - " \"payload\": {\n" + - " \"type\": \"json\",\n" + - " \"value\": \"{\\r\\n \\\"creativeCode\\\" : \\\"\\\"\\r\\n}\",\n" + - " \"key\": \"2be04ba5-8f9b-4a1e-8100-d573c40312f8\"\n" + - " },\n" + - " \"expiry\": 1800,\n" + - " \"lastModified\": \"Dec 9, 2017 11:24:44 AM\",\n" + - " \"success\": true\n" + - "}"; + private static final String JSON_WITH_EXPIRY = """ + { + "id": "2be04ba5-8f9b-4a1e-8100-d573c40312f8", + "prefix": "prebid_", + "payload": { + "type": "json", + "value": "{\\r\\n \\"creativeCode\\" : \\"\\"\\r\\n}", + "key": "2be04ba5-8f9b-4a1e-8100-d573c40312f8" + }, + "expiry": 1800, + "lastModified": "Dec 9, 2017 11:24:44 AM", + "success": true + }"""; @Test void testExpiry() { - final var wrapper = Json.createPayloadFromJson(jsonWithExpiry, PayloadWrapper.class); + final PayloadWrapper wrapper = Json.createPayloadFromJson(JSON_WITH_EXPIRY, PayloadWrapper.class); assertEquals(1800L, wrapper.getExpiry().longValue()); } @Test void testGetNormalizedId() throws PayloadWrapperPropertyException { - final var wrapper = Json.createPayloadFromJson(jsonWithExpiry, PayloadWrapper.class); + final PayloadWrapper wrapper = Json.createPayloadFromJson(JSON_WITH_EXPIRY, PayloadWrapper.class); assertEquals("prebid_2be04ba5-8f9b-4a1e-8100-d573c40312f8", wrapper.getNormalizedId()); } diff --git a/src/test/java/org/prebid/cache/repository/ReactiveTestAerospikeRepositoryContext.java b/src/test/java/org/prebid/cache/repository/ReactiveTestAerospikeRepositoryContext.java index d43fb5f..e234737 100644 --- a/src/test/java/org/prebid/cache/repository/ReactiveTestAerospikeRepositoryContext.java +++ b/src/test/java/org/prebid/cache/repository/ReactiveTestAerospikeRepositoryContext.java @@ -8,6 +8,7 @@ import com.aerospike.client.policy.Policy; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; +import org.prebid.cache.model.PayloadWrapper; import org.prebid.cache.repository.aerospike.AerospikePropertyConfiguration; import org.prebid.cache.repository.aerospike.AerospikeRepositoryImpl; import org.springframework.context.annotation.Bean; @@ -15,12 +16,11 @@ import org.springframework.context.annotation.Primary; @Configuration - public class ReactiveTestAerospikeRepositoryContext { @Bean @Primary - public ReactiveRepository createRepository() { + public ReactiveRepository createRepository() { return new AerospikeRepositoryImpl(aerospikePropertyConfiguration(), client(), eventLoops(), readPolicy()); } diff --git a/src/test/java/org/prebid/cache/repository/ReactiveTestRedisRepositoryContext.java b/src/test/java/org/prebid/cache/repository/ReactiveTestRedisRepositoryContext.java index 44b7c55..faaffff 100644 --- a/src/test/java/org/prebid/cache/repository/ReactiveTestRedisRepositoryContext.java +++ b/src/test/java/org/prebid/cache/repository/ReactiveTestRedisRepositoryContext.java @@ -4,6 +4,7 @@ import io.lettuce.core.RedisURI; import io.lettuce.core.api.StatefulRedisConnection; import io.lettuce.core.api.reactive.RedisStringReactiveCommands; +import org.prebid.cache.model.PayloadWrapper; import org.prebid.cache.repository.redis.RedisRepositoryImpl; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -13,8 +14,8 @@ public class ReactiveTestRedisRepositoryContext { @Bean @Primary - public ReactiveRepository createRepository() { - return new RedisRepositoryImpl(reactiveCommands()); + public ReactiveRepository createRepository(RedisStringReactiveCommands reactiveCommands) { + return new RedisRepositoryImpl(reactiveCommands); } @Bean @@ -23,12 +24,12 @@ RedisClient client() { } @Bean - StatefulRedisConnection connection() { - return client().connect(); + StatefulRedisConnection connection(RedisClient redisClient) { + return redisClient.connect(); } @Bean - RedisStringReactiveCommands reactiveCommands() { - return connection().reactive(); + RedisStringReactiveCommands reactiveCommands(StatefulRedisConnection connection) { + return connection.reactive(); } } From ff3cd12f6f6f99e3ff03879bc62a62d661011e7a Mon Sep 17 00:00:00 2001 From: antonbabak Date: Mon, 18 Dec 2023 17:29:43 +0100 Subject: [PATCH 2/3] Revert some changes --- .../java/org/prebid/cache/handlers/GetCacheHandler.java | 2 +- .../java/org/prebid/cache/handlers/PostCacheHandler.java | 2 +- .../org/prebid/cache/handlers/GetCacheHandlerTests.java | 8 ++++---- .../repository/ReactiveTestRedisRepositoryContext.java | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/prebid/cache/handlers/GetCacheHandler.java b/src/main/java/org/prebid/cache/handlers/GetCacheHandler.java index e6c873e..1dbd74a 100644 --- a/src/main/java/org/prebid/cache/handlers/GetCacheHandler.java +++ b/src/main/java/org/prebid/cache/handlers/GetCacheHandler.java @@ -119,7 +119,7 @@ private Mono processProxyRequest(final ServerRequest request, return webClient.get() .uri(uriBuilder -> uriBuilder.queryParam(ID_KEY, idKeyParam).build()) .headers(httpHeaders -> httpHeaders.addAll(request.headers().asHttpHeaders())) - .exchangeToMono(Mono::just) + .exchange() .transform(CircuitBreakerOperator.of(circuitBreaker)) .timeout(Duration.ofMillis(config.getTimeoutMs())) .subscribeOn(Schedulers.parallel()) diff --git a/src/main/java/org/prebid/cache/handlers/PostCacheHandler.java b/src/main/java/org/prebid/cache/handlers/PostCacheHandler.java index ce008e0..dbcf97e 100644 --- a/src/main/java/org/prebid/cache/handlers/PostCacheHandler.java +++ b/src/main/java/org/prebid/cache/handlers/PostCacheHandler.java @@ -177,7 +177,7 @@ private void sendRequestToSecondaryPrebidCacheHosts(List payload .queryParam("secondaryCache", "yes").build()) .contentType(MediaType.APPLICATION_JSON) .bodyValue(RequestObject.of(payloadTransfers)) - .exchangeToMono(Mono::just) + .exchange() .transform(CircuitBreakerOperator.of(circuitBreaker)) .doOnError(throwable -> { metricsRecorder.getSecondaryCacheWriteError().increment(); diff --git a/src/test/java/org/prebid/cache/handlers/GetCacheHandlerTests.java b/src/test/java/org/prebid/cache/handlers/GetCacheHandlerTests.java index 566ee64..66025bc 100644 --- a/src/test/java/org/prebid/cache/handlers/GetCacheHandlerTests.java +++ b/src/test/java/org/prebid/cache/handlers/GetCacheHandlerTests.java @@ -140,7 +140,7 @@ void testVerifyFetchWithCacheHostParam() { final var requestMono = MockServerRequest.builder() .method(HttpMethod.GET) - .header(CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .header(CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE) .queryParam("uuid", "a8db2208-d085-444c-9721-c1161d7f09ce") .queryParam("ch", "localhost:8080") .build(); @@ -156,7 +156,7 @@ void testVerifyFetchWithCacheHostParam() { verify(getRequestedFor(urlPathEqualTo("/cache")) .withQueryParam("uuid", equalTo("a8db2208-d085-444c-9721-c1161d7f09ce")) - .withHeader(HttpHeaders.CONTENT_TYPE, equalToIgnoreCase(MediaType.APPLICATION_JSON_VALUE)) + .withHeader(HttpHeaders.CONTENT_TYPE, equalToIgnoreCase(MediaType.APPLICATION_JSON_UTF8_VALUE)) ); } @@ -187,7 +187,7 @@ void testVerifyFetchReturnsBadRequestWhenResponseStatusIsNotOk() { final var requestMono = MockServerRequest.builder() .method(HttpMethod.GET) - .header(CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .header(CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE) .queryParam("uuid", "a8db2208-d085-444c-9721-c1161d7f09ce") .queryParam("ch", "localhost:8080") .build(); @@ -203,7 +203,7 @@ void testVerifyFetchReturnsBadRequestWhenResponseStatusIsNotOk() { verify(getRequestedFor(urlPathEqualTo("/cache")) .withQueryParam("uuid", equalTo("a8db2208-d085-444c-9721-c1161d7f09ce")) - .withHeader(HttpHeaders.CONTENT_TYPE, equalToIgnoreCase(MediaType.APPLICATION_JSON_VALUE)) + .withHeader(HttpHeaders.CONTENT_TYPE, equalToIgnoreCase(MediaType.APPLICATION_JSON_UTF8_VALUE)) ); } diff --git a/src/test/java/org/prebid/cache/repository/ReactiveTestRedisRepositoryContext.java b/src/test/java/org/prebid/cache/repository/ReactiveTestRedisRepositoryContext.java index faaffff..31c3d6b 100644 --- a/src/test/java/org/prebid/cache/repository/ReactiveTestRedisRepositoryContext.java +++ b/src/test/java/org/prebid/cache/repository/ReactiveTestRedisRepositoryContext.java @@ -24,12 +24,12 @@ RedisClient client() { } @Bean - StatefulRedisConnection connection(RedisClient redisClient) { - return redisClient.connect(); + StatefulRedisConnection connection() { + return client().connect(); } @Bean - RedisStringReactiveCommands reactiveCommands(StatefulRedisConnection connection) { - return connection.reactive(); + RedisStringReactiveCommands reactiveCommands() { + return connection().reactive(); } } From f27e13e620d4a96470239ba2d686714762bfabb7 Mon Sep 17 00:00:00 2001 From: antonbabak Date: Tue, 27 Feb 2024 16:06:39 +0100 Subject: [PATCH 3/3] Fix conflicts --- .../cache/builders/PayloadWrapperResponseTests.java | 2 +- .../org/prebid/cache/handlers/CacheHandlerTests.java | 1 - .../prebid/cache/handlers/GetCacheHandlerTests.java | 4 +--- .../prebid/cache/handlers/PostCacheHandlerTests.java | 12 ++---------- 4 files changed, 4 insertions(+), 15 deletions(-) diff --git a/src/test/java/org/prebid/cache/builders/PayloadWrapperResponseTests.java b/src/test/java/org/prebid/cache/builders/PayloadWrapperResponseTests.java index 2530ed9..bf0ebf2 100644 --- a/src/test/java/org/prebid/cache/builders/PayloadWrapperResponseTests.java +++ b/src/test/java/org/prebid/cache/builders/PayloadWrapperResponseTests.java @@ -26,6 +26,7 @@ public abstract class PayloadWrapperResponseTests { { "creativeCode" : "" }"""; + static PayloadWrapper jsonPayloadWrapper; static PayloadWrapper jsonUTF8PayloadWrapper; static PayloadWrapper xmlPayloadWrapper; @@ -71,7 +72,6 @@ private static PayloadWrapper createPayloadWrapper(MediaType mediaType) { .prefix("prefix") .payload(payload) .expiry(200L) - .lastModified(new Date()) .isExternalId(false) .build(); } diff --git a/src/test/java/org/prebid/cache/handlers/CacheHandlerTests.java b/src/test/java/org/prebid/cache/handlers/CacheHandlerTests.java index 49c6b69..a484356 100644 --- a/src/test/java/org/prebid/cache/handlers/CacheHandlerTests.java +++ b/src/test/java/org/prebid/cache/handlers/CacheHandlerTests.java @@ -28,7 +28,6 @@ abstract class CacheHandlerTests { .prefix("prebid_") .payload(Payload.of("json", "2be04ba5-8f9b-4a1e-8100-d573c40312f8", "")) .expiry(1800L) - .lastModified(new Date(100)) .isExternalId(true) .build(); diff --git a/src/test/java/org/prebid/cache/handlers/GetCacheHandlerTests.java b/src/test/java/org/prebid/cache/handlers/GetCacheHandlerTests.java index 2484fd6..66025bc 100644 --- a/src/test/java/org/prebid/cache/handlers/GetCacheHandlerTests.java +++ b/src/test/java/org/prebid/cache/handlers/GetCacheHandlerTests.java @@ -115,9 +115,7 @@ private static Consumer assertNotFoundStatusCode() { @Test void testVerifyFetch() { - final var payload = new Payload("json", "2be04ba5-8f9b-4a1e-8100-d573c40312f8", ""); - final var payloadWrapper = new PayloadWrapper("12", "prebid_", payload, 1800L, true); - given(repository.findById("prebid_a8db2208-d085-444c-9721-c1161d7f09ce")).willReturn(Mono.just(payloadWrapper)); + given(repository.findById("prebid_a8db2208-d085-444c-9721-c1161d7f09ce")).willReturn(Mono.just(PAYLOAD_WRAPPER)); final var requestMono = MockServerRequest.builder() .method(HttpMethod.GET) diff --git a/src/test/java/org/prebid/cache/handlers/PostCacheHandlerTests.java b/src/test/java/org/prebid/cache/handlers/PostCacheHandlerTests.java index 83b0b91..52a8d41 100644 --- a/src/test/java/org/prebid/cache/handlers/PostCacheHandlerTests.java +++ b/src/test/java/org/prebid/cache/handlers/PostCacheHandlerTests.java @@ -12,6 +12,7 @@ import org.prebid.cache.exceptions.DuplicateKeyException; import org.prebid.cache.metrics.MetricsRecorder; import org.prebid.cache.metrics.MetricsRecorderTest; +import org.prebid.cache.model.Payload; import org.prebid.cache.model.PayloadWrapper; import org.prebid.cache.model.RequestObject; import org.prebid.cache.repository.CacheConfig; @@ -111,11 +112,8 @@ public void teardown() { @Test void testVerifySave() { - final var payloadInner = new Payload("json", "2be04ba5-8f9b-4a1e-8100-d573c40312f8", ""); - final var payloadWrapper = new PayloadWrapper("2be04ba5-8f9b-4a1e-8100-d573c40312f8", "prebid_", payloadInner - , 1800L, true); given(currentDateProvider.get()).willReturn(new Date(100)); - given(repository.save(PAYLOAD_WRAPPER)).willReturn(Mono.just(payloadWrapper)); + given(repository.save(PAYLOAD_WRAPPER)).willReturn(Mono.just(PAYLOAD_WRAPPER)); final PostCacheHandler handler = new PostCacheHandler(repository, cacheConfig, metricsRecorder, builder, webClientCircuitBreaker, samplingRate); @@ -139,9 +137,6 @@ void testVerifySave() { @Test void testSecondaryCacheSuccess() { - final var payloadInner = new Payload("json", "2be04ba5-8f9b-4a1e-8100-d573c40312f8", ""); - final var payloadWrapper = new PayloadWrapper("2be04ba5-8f9b-4a1e-8100-d573c40312f8", "prebid_", payloadInner - , 1800L, true); given(currentDateProvider.get()).willReturn(new Date(100)); given(repository.save(PAYLOAD_WRAPPER)).willReturn(Mono.just(PAYLOAD_WRAPPER)); @@ -203,9 +198,6 @@ void testExternalUUIDInvalid() { @Test void testUUIDDuplication() { - final var payloadInner = new Payload("json", "2be04ba5-8f9b-4a1e-8100-d573c40312f8", ""); - final var payloadWrapper = new PayloadWrapper("2be04ba5-8f9b-4a1e-8100-d573c40312f8", "prebid_", payloadInner - , 1800L, true); given(currentDateProvider.get()).willReturn(new Date(100)); given(repository.save(PAYLOAD_WRAPPER)) .willReturn(Mono.just(PAYLOAD_WRAPPER))