Add code formatting guidelines
Add 'eclipse' folder containing Eclipse code formatter configuration and instructions how to use it. Update rule for join_wrapped_lines - Set to `false` Resolves #930 Update README Address review comments
This commit is contained in:
committed by
Marius Bogoevici
parent
9632546f03
commit
bd002e4aaf
13
README.adoc
13
README.adoc
@@ -37,6 +37,19 @@ Any question that is not a bug or an issue should be asked on Stack Overflow, us
|
||||
|
||||
We love contributions. Follow this https://github.com/spring-cloud/spring-cloud-commons#contributing[link] for more information on how to contribute.
|
||||
|
||||
=== Code formatting guidelines
|
||||
|
||||
* The directory `eclipse` contains two files that can be used to configure the formatting rules in your IDE: `eclipse-code-formatter.xml` for the majority of the code formatting rules and `eclipse.importorder` to order the import statements.
|
||||
|
||||
* In Eclipse you import these files by navigating `Windows -> Preferences` and then the menu items `Preferences > Java > Code Style > Formatter` and `Preferences > Java > Code Style > Organize Imports` respectively.
|
||||
|
||||
* In `IntelliJ`, install the plugin `Eclipse Code Formatter`.
|
||||
You can find it by searching the "Browse Repositories" under the plugin option within `IntelliJ` (Once installed you will need to reboot Intellij for it to take effect).
|
||||
Then navigate to `Intellij IDEA > Preferences` and select the Eclipse Code Formatter.
|
||||
Select the `eclipse-code-formatter.xml` file for the field `Eclipse Java Formatter config file` and the file `eclipse.importorder` for the field `Import order`.
|
||||
Enable the `Eclipse code formatter` by clicking `Use the Eclipse code formatter` then click the *OK* button.
|
||||
** NOTE: If you configure the `Eclipse Code Formatter` from `File > Other Settings > Default Settings` it will set this policy across all of your Intellij projects.
|
||||
|
||||
== Code of Conduct
|
||||
This project adheres to the Contributor Covenant link:CODE_OF_CONDUCT.adoc[code of conduct]. By participating, you are expected to uphold this code. Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.
|
||||
|
||||
|
||||
397
eclipse/eclipse-code-formatter.xml
Normal file
397
eclipse/eclipse-code-formatter.xml
Normal file
@@ -0,0 +1,397 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<profiles version="12">
|
||||
<profile kind="CodeFormatterProfile" name="Spring Boot Java Conventions" version="12">
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration"
|
||||
value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters"
|
||||
value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="do not insert"/>
|
||||
<setting
|
||||
id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration"
|
||||
value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="49"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations"
|
||||
value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
|
||||
<setting
|
||||
id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return"
|
||||
value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments"
|
||||
value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer"
|
||||
value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration"
|
||||
value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="90"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration"
|
||||
value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments"
|
||||
value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference"
|
||||
value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations"
|
||||
value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header"
|
||||
value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments"
|
||||
value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration"
|
||||
value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.source" value="1.8"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws"
|
||||
value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer"
|
||||
value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw"
|
||||
value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.8"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters"
|
||||
value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer"
|
||||
value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters"
|
||||
value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header"
|
||||
value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
|
||||
<setting
|
||||
id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference"
|
||||
value="do not insert"/>
|
||||
<setting
|
||||
id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression"
|
||||
value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration"
|
||||
value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws"
|
||||
value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments"
|
||||
value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration"
|
||||
value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.8"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration"
|
||||
value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
|
||||
<setting
|
||||
id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header"
|
||||
value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration"
|
||||
value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation"
|
||||
value="do not insert"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
|
||||
</profile>
|
||||
</profiles>
|
||||
7
eclipse/eclipse.importorder
Normal file
7
eclipse/eclipse.importorder
Normal file
@@ -0,0 +1,7 @@
|
||||
#Organize Import Order
|
||||
#Wed Apr 26 12:53:22 EDT 2017
|
||||
4=\#
|
||||
3=org.springframework
|
||||
2=
|
||||
1=javax
|
||||
0=java
|
||||
@@ -57,23 +57,23 @@ public abstract class AbstractBinderTests<B extends AbstractTestBinder<? extends
|
||||
protected B testBinder;
|
||||
|
||||
/**
|
||||
* Subclasses may override this default value to have tests wait longer for a message receive, for example if
|
||||
* running
|
||||
* in an environment that is known to be slow (e.g. travis).
|
||||
* Subclasses may override this default value to have tests wait longer for a message
|
||||
* receive, for example if running in an environment that is known to be slow (e.g.
|
||||
* travis).
|
||||
*/
|
||||
protected double timeoutMultiplier = 1.0D;
|
||||
|
||||
/**
|
||||
* Attempt to receive a message on the given channel,
|
||||
* waiting up to 1s (times the {@link #timeoutMultiplier}).
|
||||
* Attempt to receive a message on the given channel, waiting up to 1s (times the
|
||||
* {@link #timeoutMultiplier}).
|
||||
*/
|
||||
protected Message<?> receive(PollableChannel channel) {
|
||||
return receive(channel, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to receive a message on the given channel,
|
||||
* waiting up to 1s * additionalMultiplier * {@link #timeoutMultiplier}).
|
||||
* Attempt to receive a message on the given channel, waiting up to 1s *
|
||||
* additionalMultiplier * {@link #timeoutMultiplier}).
|
||||
*
|
||||
* Allows accomodating tests which are slower than normal (e.g. retry).
|
||||
*/
|
||||
@@ -170,7 +170,6 @@ public abstract class AbstractBinderTests<B extends AbstractTestBinder<? extends
|
||||
moduleOutputChannel1.send(message1);
|
||||
moduleOutputChannel2.send(message2);
|
||||
|
||||
|
||||
Message<?>[] messages = new Message[2];
|
||||
messages[0] = receive(moduleInputChannel);
|
||||
messages[1] = receive(moduleInputChannel);
|
||||
@@ -211,7 +210,6 @@ public abstract class AbstractBinderTests<B extends AbstractTestBinder<? extends
|
||||
consumerBinding.unbind();
|
||||
}
|
||||
|
||||
|
||||
protected abstract B getBinder() throws Exception;
|
||||
|
||||
protected abstract CP createConsumerProperties();
|
||||
@@ -224,15 +222,14 @@ public abstract class AbstractBinderTests<B extends AbstractTestBinder<? extends
|
||||
return bindingProperties;
|
||||
}
|
||||
|
||||
|
||||
protected BindingProperties createProducerBindingProperties(PP producerProperties) {
|
||||
BindingProperties bindingProperties = new BindingProperties();
|
||||
bindingProperties.setProducer(producerProperties);
|
||||
return bindingProperties;
|
||||
}
|
||||
|
||||
protected DirectChannel createBindableChannel(String channelName, BindingProperties bindingProperties) throws
|
||||
Exception {
|
||||
protected DirectChannel createBindableChannel(String channelName, BindingProperties bindingProperties)
|
||||
throws Exception {
|
||||
BindingServiceProperties bindingServiceProperties = new BindingServiceProperties();
|
||||
bindingServiceProperties.getBindings().put(channelName, bindingProperties);
|
||||
ConfigurableApplicationContext applicationContext = new GenericApplicationContext();
|
||||
@@ -259,7 +256,8 @@ public abstract class AbstractBinderTests<B extends AbstractTestBinder<? extends
|
||||
}
|
||||
|
||||
/**
|
||||
* If appropriate, let the binder middleware settle down a bit while binding/unbinding actually happens.
|
||||
* If appropriate, let the binder middleware settle down a bit while binding/unbinding
|
||||
* actually happens.
|
||||
*/
|
||||
protected void binderBindUnbindLatency() throws InterruptedException {
|
||||
// default none
|
||||
|
||||
@@ -28,24 +28,16 @@ import org.springframework.messaging.MessageChannel;
|
||||
* @author Gary Russell
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public abstract class AbstractTestBinder<C extends AbstractBinder<MessageChannel, CP, PP>, CP extends ConsumerProperties, PP extends ProducerProperties> implements Binder<MessageChannel, CP, PP> {
|
||||
public abstract class AbstractTestBinder<C extends AbstractBinder<MessageChannel, CP, PP>, CP extends ConsumerProperties, PP extends ProducerProperties>
|
||||
implements Binder<MessageChannel, CP, PP> {
|
||||
|
||||
protected Set<String> queues = new HashSet<String>();
|
||||
|
||||
private C binder;
|
||||
|
||||
public void setBinder(C binder) {
|
||||
try {
|
||||
binder.afterPropertiesSet();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException("Failed to initialize binder", e);
|
||||
}
|
||||
this.binder = binder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Binding<MessageChannel> bindConsumer(String name, String group, MessageChannel moduleInputChannel, CP properties) {
|
||||
public Binding<MessageChannel> bindConsumer(String name, String group, MessageChannel moduleInputChannel,
|
||||
CP properties) {
|
||||
queues.add(name);
|
||||
return binder.bindConsumer(name, group, moduleInputChannel, properties);
|
||||
}
|
||||
@@ -66,4 +58,14 @@ public abstract class AbstractTestBinder<C extends AbstractBinder<MessageChannel
|
||||
return this.binder;
|
||||
}
|
||||
|
||||
public void setBinder(C binder) {
|
||||
try {
|
||||
binder.afterPropertiesSet();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException("Failed to initialize binder", e);
|
||||
}
|
||||
this.binder = binder;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,7 +25,8 @@ import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
|
||||
/**
|
||||
* An {@link EnvironmentPostProcessor} that sets some common configuration properties (log config etc.,) for binder tests.
|
||||
* An {@link EnvironmentPostProcessor} that sets some common configuration properties (log
|
||||
* config etc.,) for binder tests.
|
||||
*
|
||||
* @author Ilayaperumal Gopinathan
|
||||
*/
|
||||
|
||||
@@ -25,19 +25,18 @@ import org.springframework.integration.support.utils.IntegrationUtils;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Gary Russell
|
||||
*/
|
||||
public abstract class BinderTestUtils {
|
||||
|
||||
private static final MessageBuilderFactory mbf = new MutableMessageBuilderFactory();
|
||||
|
||||
public static final AbstractApplicationContext MOCK_AC = mock(AbstractApplicationContext.class);
|
||||
|
||||
public static final ConfigurableListableBeanFactory MOCK_BF = mock(ConfigurableListableBeanFactory.class);
|
||||
|
||||
private static final MessageBuilderFactory mbf = new MutableMessageBuilderFactory();
|
||||
|
||||
static {
|
||||
when(MOCK_BF.getBean(IntegrationUtils.INTEGRATION_MESSAGE_BUILDER_FACTORY_BEAN_NAME,
|
||||
MessageBuilderFactory.class)).thenReturn(mbf);
|
||||
|
||||
@@ -44,8 +44,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Mark Fisher
|
||||
* @author Marius Bogoevici
|
||||
*/
|
||||
public abstract class PartitionCapableBinderTests<B extends AbstractTestBinder<? extends
|
||||
AbstractBinder<MessageChannel, CP, PP>, CP, PP>, CP extends ConsumerProperties, PP extends ProducerProperties>
|
||||
public abstract class PartitionCapableBinderTests<B extends AbstractTestBinder<? extends AbstractBinder<MessageChannel, CP, PP>, CP, PP>, CP extends ConsumerProperties, PP extends ProducerProperties>
|
||||
extends AbstractBinderTests<B, CP, PP> {
|
||||
|
||||
protected static final SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.springframework.cloud.stream.binder;
|
||||
|
||||
import org.springframework.messaging.Message;
|
||||
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
*/
|
||||
|
||||
@@ -17,9 +17,8 @@
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
/**
|
||||
* Represents an out-of-band connection to the underlying middleware,
|
||||
* so that tests can check that some messages actually do (or do not)
|
||||
* transit through it.
|
||||
* Represents an out-of-band connection to the underlying middleware, so that tests can
|
||||
* check that some messages actually do (or do not) transit through it.
|
||||
*
|
||||
* @author Eric Bottard
|
||||
*/
|
||||
|
||||
@@ -43,7 +43,6 @@ import org.springframework.util.MimeTypeUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
* @author David Turanski
|
||||
@@ -132,7 +131,6 @@ public class MessageChannelBinderSupportTests {
|
||||
assertThat(reconstructed.get(MessageHeaders.CONTENT_TYPE)).isEqualTo(MimeTypeUtils.APPLICATION_JSON_VALUE);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testContentTypePreservedForNonSCStApp() {
|
||||
Message<String> inbound = MessageBuilder.withPayload("{\"foo\":\"bar\"}")
|
||||
@@ -253,19 +251,6 @@ public class MessageChannelBinderSupportTests {
|
||||
|
||||
}
|
||||
|
||||
public class TestMessageChannelBinder extends AbstractBinder<MessageChannel, ConsumerProperties, ProducerProperties> {
|
||||
|
||||
@Override
|
||||
protected Binding<MessageChannel> doBindConsumer(String name, String group, MessageChannel channel, ConsumerProperties properties) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Binding<MessageChannel> doBindProducer(String name, MessageChannel channel, ProducerProperties properties) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static class TupleRegistrar implements KryoRegistrar {
|
||||
private final TupleKryoRegistrar delegate = new TupleKryoRegistrar();
|
||||
|
||||
@@ -280,4 +265,20 @@ public class MessageChannelBinderSupportTests {
|
||||
}
|
||||
}
|
||||
|
||||
public class TestMessageChannelBinder
|
||||
extends AbstractBinder<MessageChannel, ConsumerProperties, ProducerProperties> {
|
||||
|
||||
@Override
|
||||
protected Binding<MessageChannel> doBindConsumer(String name, String group, MessageChannel channel,
|
||||
ConsumerProperties properties) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Binding<MessageChannel> doBindProducer(String name, MessageChannel channel,
|
||||
ProducerProperties properties) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ import org.springframework.integration.codec.kryo.FileKryoRegistrar;
|
||||
import org.springframework.integration.codec.kryo.KryoRegistrar;
|
||||
import org.springframework.integration.codec.kryo.PojoCodec;
|
||||
|
||||
|
||||
/**
|
||||
* Auto configures {@link PojoCodec} if Kryo is on the class path.
|
||||
* @author David Turanski
|
||||
@@ -53,8 +52,7 @@ public class KryoCodecAutoConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(PojoCodec.class)
|
||||
public PojoCodec codec() {
|
||||
Map<String, KryoRegistrar> kryoRegistrarMap = applicationContext.getBeansOfType(KryoRegistrar
|
||||
.class);
|
||||
Map<String, KryoRegistrar> kryoRegistrarMap = applicationContext.getBeansOfType(KryoRegistrar.class);
|
||||
return new PojoCodec(new ArrayList<>(kryoRegistrarMap.values()), kryoCodecProperties.isReferences());
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Ilayaperumal Gopinathan
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringBootTest(classes = {ContentTypeOutboundSourceTests.TestSource.class})
|
||||
@SpringBootTest(classes = { ContentTypeOutboundSourceTests.TestSource.class })
|
||||
public class ContentTypeOutboundSourceTests {
|
||||
|
||||
@Autowired
|
||||
@@ -54,8 +54,9 @@ public class ContentTypeOutboundSourceTests {
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testMessageHeaderWhenNoExplicitContentTypeOnMessage() throws Exception {
|
||||
testSource.output().send(MessageBuilder.withPayload("{\"message\":\"Hi\"}").build());
|
||||
Message<String> received = (Message<String>) ((TestSupportBinder) binderFactory.getBinder(null, MessageChannel.class))
|
||||
.messageCollector().forChannel(testSource.output()).poll();
|
||||
Message<String> received = (Message<String>) ((TestSupportBinder) binderFactory.getBinder(null,
|
||||
MessageChannel.class))
|
||||
.messageCollector().forChannel(testSource.output()).poll();
|
||||
assertThat(received.getHeaders().get(MessageHeaders.CONTENT_TYPE).toString()).isEqualTo("application/json");
|
||||
assertThat(received).hasFieldOrPropertyWithValue("payload", "{\"message\":\"Hi\"}");
|
||||
}
|
||||
@@ -67,4 +68,3 @@ public class ContentTypeOutboundSourceTests {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,8 +71,9 @@ public class CustomMessageConverterTests {
|
||||
BarConverter.class, DefaultDatatypeChannelMessageConverter.class);
|
||||
testSource.output().send(MessageBuilder.withPayload(new Foo("hi")).build());
|
||||
@SuppressWarnings("unchecked")
|
||||
Message<String> received = (Message<String>) ((TestSupportBinder) binderFactory.getBinder(null, MessageChannel.class))
|
||||
.messageCollector().forChannel(testSource.output()).poll(1, TimeUnit.SECONDS);
|
||||
Message<String> received = (Message<String>) ((TestSupportBinder) binderFactory.getBinder(null,
|
||||
MessageChannel.class))
|
||||
.messageCollector().forChannel(testSource.output()).poll(1, TimeUnit.SECONDS);
|
||||
Assert.assertThat(received, notNullValue());
|
||||
assertThat(received.getHeaders().get(MessageHeaders.CONTENT_TYPE)).isEqualTo(MimeType.valueOf("test/foo"));
|
||||
}
|
||||
@@ -128,7 +129,6 @@ public class CustomMessageConverterTests {
|
||||
super(MimeType.valueOf("test/bar"));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean supports(Class<?> clazz) {
|
||||
return clazz.equals(Bar.class);
|
||||
|
||||
@@ -58,7 +58,8 @@ public class DeserializeJSONToJavaTypeTests {
|
||||
|
||||
@Test
|
||||
public void testMessageDeserialized() throws Exception {
|
||||
testProcessor.input().send(MessageBuilder.withPayload("{\"name\":\"Bar\"}").setHeader("contentType", "application/json").build());
|
||||
testProcessor.input().send(
|
||||
MessageBuilder.withPayload("{\"name\":\"Bar\"}").setHeader("contentType", "application/json").build());
|
||||
@SuppressWarnings("unchecked")
|
||||
Message<?> received = ((TestSupportBinder) binderFactory.getBinder(null, MessageChannel.class))
|
||||
.messageCollector().forChannel(testProcessor.output()).poll(1, TimeUnit.SECONDS);
|
||||
|
||||
@@ -56,7 +56,8 @@ public class ErrorChannelTests {
|
||||
|
||||
@Test
|
||||
public void testErrorChannelBinding() throws Exception {
|
||||
Message<?> message = ((TestSupportBinder) binderFactory.getBinder(null, MessageChannel.class)).messageCollector().forChannel(errorChannel).poll(10, TimeUnit.SECONDS);
|
||||
Message<?> message = ((TestSupportBinder) binderFactory.getBinder(null, MessageChannel.class))
|
||||
.messageCollector().forChannel(errorChannel).poll(10, TimeUnit.SECONDS);
|
||||
Assert.isTrue(message instanceof ErrorMessage, "Message should be an instance of ErrorMessage");
|
||||
Assert.isTrue(message.getPayload() instanceof MessagingException, "Message payload should be an instance" +
|
||||
"of MessagingException");
|
||||
@@ -81,4 +82,3 @@ public class ErrorChannelTests {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,10 +61,9 @@ public class InboundJsonToTupleConversionTest {
|
||||
Message<?> received = ((TestSupportBinder) binderFactory.getBinder(null, MessageChannel.class))
|
||||
.messageCollector().forChannel(testProcessor.output()).poll(1, TimeUnit.SECONDS);
|
||||
assertThat(received).isNotNull();
|
||||
assertThat(received.getPayload()).isEqualTo(TupleBuilder.tuple().of("name","foo"));
|
||||
assertThat(received.getPayload()).isEqualTo(TupleBuilder.tuple().of("name", "foo"));
|
||||
}
|
||||
|
||||
|
||||
@EnableBinding(Processor.class)
|
||||
@EnableAutoConfiguration
|
||||
@PropertySource("classpath:/org/springframework/cloud/stream/config/inboundjsontuple/inbound-json-tuple.properties")
|
||||
|
||||
@@ -21,7 +21,6 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@@ -54,7 +53,8 @@ import static org.junit.Assert.assertNull;
|
||||
* @author Gary Russell
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringBootTest(classes = {MessageChannelConfigurerTests.TestSink.class, MessageChannelConfigurerTests.TestSource.class})
|
||||
@SpringBootTest(classes = { MessageChannelConfigurerTests.TestSink.class,
|
||||
MessageChannelConfigurerTests.TestSource.class })
|
||||
public class MessageChannelConfigurerTests {
|
||||
|
||||
@Autowired
|
||||
@@ -92,12 +92,13 @@ public class MessageChannelConfigurerTests {
|
||||
|
||||
@Test
|
||||
public void testObjectMapperConfig() throws Exception {
|
||||
CompositeMessageConverter converters = (CompositeMessageConverter) messageConverterFactory.getMessageConverterForType(MimeTypeUtils
|
||||
.APPLICATION_JSON);
|
||||
CompositeMessageConverter converters = (CompositeMessageConverter) messageConverterFactory
|
||||
.getMessageConverterForType(MimeTypeUtils.APPLICATION_JSON);
|
||||
for (MessageConverter converter : converters.getConverters()) {
|
||||
DirectFieldAccessor converterAccessor = new DirectFieldAccessor(converter);
|
||||
ObjectMapper objectMapper = (ObjectMapper) converterAccessor.getPropertyValue("objectMapper");
|
||||
// assert that the ObjectMapper used by the converters is compliant with the Boot configuration
|
||||
// assert that the ObjectMapper used by the converters is compliant with the
|
||||
// Boot configuration
|
||||
assertThat(!objectMapper.getSerializationConfig().isEnabled(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS))
|
||||
.withFailMessage("SerializationFeature 'WRITE_DATES_AS_TIMESTAMPS' should be disabled");
|
||||
// assert that the globally set bean is used by the converters
|
||||
|
||||
@@ -61,7 +61,8 @@ public class StreamListenerAnnotatedMethodArgumentsTests {
|
||||
sink.input().send(MessageBuilder.withPayload("{\"foo\":\"barbar" + id + "\"}")
|
||||
.setHeader("contentType", "application/json").setHeader("testHeader", "testValue").build());
|
||||
assertThat(testPojoWithAnnotatedArguments.receivedArguments).hasSize(3);
|
||||
assertThat(testPojoWithAnnotatedArguments.receivedArguments.get(0)).isInstanceOf(StreamListenerTestUtils.FooPojo.class);
|
||||
assertThat(testPojoWithAnnotatedArguments.receivedArguments.get(0))
|
||||
.isInstanceOf(StreamListenerTestUtils.FooPojo.class);
|
||||
assertThat(testPojoWithAnnotatedArguments.receivedArguments.get(0)).hasFieldOrPropertyWithValue("foo",
|
||||
"barbar" + id);
|
||||
assertThat(testPojoWithAnnotatedArguments.receivedArguments.get(1)).isInstanceOf(Map.class);
|
||||
@@ -77,7 +78,7 @@ public class StreamListenerAnnotatedMethodArgumentsTests {
|
||||
public void testInputAnnotationAtMethodParameter() throws Exception {
|
||||
try {
|
||||
SpringApplication.run(TestPojoWithInvalidInputAnnotatedArgument.class, "--server.port=0");
|
||||
fail("Exception expected: "+ INVALID_DECLARATIVE_METHOD_PARAMETERS);
|
||||
fail("Exception expected: " + INVALID_DECLARATIVE_METHOD_PARAMETERS);
|
||||
}
|
||||
catch (BeanCreationException e) {
|
||||
assertThat(e.getCause().getMessage()).contains(INVALID_DECLARATIVE_METHOD_PARAMETERS);
|
||||
|
||||
@@ -73,11 +73,6 @@ public class StreamListenerAnnotationBeanPostProcessorOverrideTest {
|
||||
public static class TestPojoWithAnnotatedArguments {
|
||||
|
||||
List<StreamListenerTestUtils.FooPojo> receivedFoo = new ArrayList<>();
|
||||
|
||||
@StreamListener(value = Sink.INPUT, condition = "foo")
|
||||
public void receive(@Payload StreamListenerTestUtils.FooPojo fooPojo) {
|
||||
this.receivedFoo.add(fooPojo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the default {@link StreamListenerAnnotationBeanPostProcessor}.
|
||||
@@ -86,12 +81,19 @@ public class StreamListenerAnnotationBeanPostProcessorOverrideTest {
|
||||
public static BeanPostProcessor streamListenerAnnotationBeanPostProcessor() {
|
||||
return new StreamListenerAnnotationBeanPostProcessor() {
|
||||
@Override
|
||||
protected StreamListener postProcessAnnotation(StreamListener originalAnnotation, Method annotatedMethod) {
|
||||
Map<String,Object> attributes = new HashMap<>(AnnotationUtils.getAnnotationAttributes(originalAnnotation));
|
||||
protected StreamListener postProcessAnnotation(StreamListener originalAnnotation,
|
||||
Method annotatedMethod) {
|
||||
Map<String, Object> attributes = new HashMap<>(
|
||||
AnnotationUtils.getAnnotationAttributes(originalAnnotation));
|
||||
attributes.put("condition", "headers['type']=='" + originalAnnotation.condition() + "'");
|
||||
return AnnotationUtils.synthesizeAnnotation(attributes, StreamListener.class, annotatedMethod);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@StreamListener(value = Sink.INPUT, condition = "foo")
|
||||
public void receive(@Payload StreamListenerTestUtils.FooPojo fooPojo) {
|
||||
this.receivedFoo.add(fooPojo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,11 +40,40 @@ import org.springframework.messaging.handler.annotation.Payload;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@MessageMapping
|
||||
@Documented
|
||||
@StreamListener
|
||||
@interface EventHandler {
|
||||
/**
|
||||
* The name of the binding target (e.g. channel) that the method subscribes to.
|
||||
* @return the name of the binding target.
|
||||
*/
|
||||
@AliasFor(annotation = StreamListener.class, attribute = "target")
|
||||
String value() default "";
|
||||
|
||||
/**
|
||||
* The name of the binding target (e.g. channel) that the method subscribes to.
|
||||
* @return the name of the binding target.
|
||||
*/
|
||||
@AliasFor(annotation = StreamListener.class, attribute = "target")
|
||||
String target() default "";
|
||||
|
||||
/**
|
||||
* A condition that must be met by all items that are dispatched to this method.
|
||||
* @return a SpEL expression that must evaluate to a {@code boolean} value.
|
||||
*/
|
||||
@AliasFor(annotation = StreamListener.class, attribute = "condition")
|
||||
String condition() default "";
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @author David Turanski
|
||||
*/
|
||||
public class StreamListenerAsMetaAnnotationTests {
|
||||
|
||||
|
||||
@Test
|
||||
public void testCustomAnnotation() {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(TestPojoWithCustomAnnotatedArguments.class,
|
||||
@@ -62,7 +91,7 @@ public class StreamListenerAsMetaAnnotationTests {
|
||||
"barbar" + id);
|
||||
context.close();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testAnnotation() {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(TestPojoWithAnnotatedArguments.class,
|
||||
@@ -80,7 +109,7 @@ public class StreamListenerAsMetaAnnotationTests {
|
||||
"barbar" + id);
|
||||
context.close();
|
||||
}
|
||||
|
||||
|
||||
@EnableBinding(Sink.class)
|
||||
@EnableAutoConfiguration
|
||||
public static class TestPojoWithCustomAnnotatedArguments {
|
||||
@@ -94,7 +123,7 @@ public class StreamListenerAsMetaAnnotationTests {
|
||||
this.receivedFoo.add(fooPojo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@EnableBinding(Sink.class)
|
||||
@EnableAutoConfiguration
|
||||
public static class TestPojoWithAnnotatedArguments {
|
||||
@@ -109,32 +138,3 @@ public class StreamListenerAsMetaAnnotationTests {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@MessageMapping
|
||||
@Documented
|
||||
@StreamListener
|
||||
@interface EventHandler {
|
||||
/**
|
||||
* The name of the binding target (e.g. channel) that the method subscribes to.
|
||||
* @return the name of the binding target.
|
||||
*/
|
||||
@AliasFor(annotation=StreamListener.class, attribute="target")
|
||||
String value() default "";
|
||||
|
||||
/**
|
||||
* The name of the binding target (e.g. channel) that the method subscribes to.
|
||||
* @return the name of the binding target.
|
||||
*/
|
||||
@AliasFor(annotation=StreamListener.class, attribute="target")
|
||||
String target() default "";
|
||||
|
||||
/**
|
||||
* A condition that must be met by all items that are dispatched to this method.
|
||||
* @return a SpEL expression that must evaluate to a {@code boolean} value.
|
||||
*/
|
||||
@AliasFor(annotation=StreamListener.class, attribute="condition")
|
||||
String condition() default "";
|
||||
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@ public class StreamListenerContentTypeConversionTests {
|
||||
public static class TestSinkWithContentTypeConversion {
|
||||
|
||||
List<StreamListenerTestUtils.FooPojo> receivedArguments = new ArrayList<>();
|
||||
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
|
||||
@StreamListener(Sink.INPUT)
|
||||
|
||||
@@ -64,8 +64,8 @@ public class StreamListenerDuplicateMappingTests {
|
||||
context = SpringApplication.run(TestDuplicateMappingFromAbstractMethod.class, "--server.port=0");
|
||||
}
|
||||
catch (BeanCreationException e) {
|
||||
String errorMessage = e.getCause().getMessage().startsWith("Duplicate @StreamListener mapping") ?
|
||||
"Duplicate mapping exception is not expected" : "Test failed with exception";
|
||||
String errorMessage = e.getCause().getMessage().startsWith("Duplicate @StreamListener mapping")
|
||||
? "Duplicate mapping exception is not expected" : "Test failed with exception";
|
||||
fail(errorMessage + ": " + e.getMessage());
|
||||
}
|
||||
finally {
|
||||
@@ -75,6 +75,14 @@ public class StreamListenerDuplicateMappingTests {
|
||||
}
|
||||
}
|
||||
|
||||
public interface GenericSink<T extends Base> {
|
||||
void testMethod(T msg);
|
||||
}
|
||||
|
||||
public interface Base {
|
||||
|
||||
}
|
||||
|
||||
@EnableBinding(Processor.class)
|
||||
@EnableAutoConfiguration
|
||||
public static class TestMultipleMappingsWithReturnValue {
|
||||
@@ -102,14 +110,6 @@ public class StreamListenerDuplicateMappingTests {
|
||||
}
|
||||
}
|
||||
|
||||
public interface GenericSink<T extends Base> {
|
||||
void testMethod(T msg);
|
||||
}
|
||||
|
||||
public interface Base {
|
||||
|
||||
}
|
||||
|
||||
public class TestBase implements Base {
|
||||
|
||||
}
|
||||
|
||||
@@ -79,7 +79,8 @@ public class StreamListenerHandlerMethodTests {
|
||||
|
||||
@Test
|
||||
public void testMethodWithObjectAsMethodArgument() throws Exception {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(TestMethodWithObjectAsMethodArgument.class, "--server.port=0");
|
||||
ConfigurableApplicationContext context = SpringApplication.run(TestMethodWithObjectAsMethodArgument.class,
|
||||
"--server.port=0");
|
||||
Processor processor = context.getBean(Processor.class);
|
||||
String id = UUID.randomUUID().toString();
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
@@ -94,11 +95,13 @@ public class StreamListenerHandlerMethodTests {
|
||||
|
||||
@Test
|
||||
public void testStreamListenerMethodWithTargetBeanFromOutside() throws Exception {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(TestStreamListenerMethodWithTargetBeanFromOutside.class, "--server.port=0");
|
||||
ConfigurableApplicationContext context = SpringApplication
|
||||
.run(TestStreamListenerMethodWithTargetBeanFromOutside.class, "--server.port=0");
|
||||
Sink sink = context.getBean(Sink.class);
|
||||
final String testMessageToSend = "testing";
|
||||
sink.input().send(MessageBuilder.withPayload(testMessageToSend).build());
|
||||
DirectChannel directChannel = (DirectChannel) context.getBean(testMessageToSend.toUpperCase(), MessageChannel.class);
|
||||
DirectChannel directChannel = (DirectChannel) context.getBean(testMessageToSend.toUpperCase(),
|
||||
MessageChannel.class);
|
||||
MessageCollector messageCollector = context.getBean(MessageCollector.class);
|
||||
Message<?> result = messageCollector.forChannel(directChannel).poll(1000, TimeUnit.MILLISECONDS);
|
||||
sink.input().send(MessageBuilder.withPayload(testMessageToSend).build());
|
||||
@@ -159,7 +162,8 @@ public class StreamListenerHandlerMethodTests {
|
||||
}
|
||||
catch (BeanCreationException e) {
|
||||
assertThat(e.getCause()).isInstanceOf(IllegalArgumentException.class);
|
||||
assertThat(e.getCause()).hasMessageContaining(StreamListenerErrorMessages.INVALID_DECLARATIVE_METHOD_PARAMETERS);
|
||||
assertThat(e.getCause())
|
||||
.hasMessageContaining(StreamListenerErrorMessages.INVALID_DECLARATIVE_METHOD_PARAMETERS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,9 +236,11 @@ public class StreamListenerHandlerMethodTests {
|
||||
|
||||
@Test
|
||||
public void testMethodWithMultipleInputParameters() throws Exception {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(TestMethodWithMultipleInputParameters.class, "--server.port=0");
|
||||
ConfigurableApplicationContext context = SpringApplication.run(TestMethodWithMultipleInputParameters.class,
|
||||
"--server.port=0");
|
||||
Processor processor = context.getBean(Processor.class);
|
||||
StreamListenerTestUtils.FooInboundChannel1 inboundChannel2 = context.getBean(StreamListenerTestUtils.FooInboundChannel1.class);
|
||||
StreamListenerTestUtils.FooInboundChannel1 inboundChannel2 = context
|
||||
.getBean(StreamListenerTestUtils.FooInboundChannel1.class);
|
||||
String id = UUID.randomUUID().toString();
|
||||
final CountDownLatch latch = new CountDownLatch(2);
|
||||
((SubscribableChannel) processor.output()).subscribe(new MessageHandler() {
|
||||
@@ -254,10 +260,12 @@ public class StreamListenerHandlerMethodTests {
|
||||
|
||||
@Test
|
||||
public void testMethodWithMultipleOutputParameters() throws Exception {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(TestMethodWithMultipleOutputParameters.class, "--server.port=0");
|
||||
ConfigurableApplicationContext context = SpringApplication.run(TestMethodWithMultipleOutputParameters.class,
|
||||
"--server.port=0");
|
||||
Processor processor = context.getBean(Processor.class);
|
||||
String id = UUID.randomUUID().toString();
|
||||
StreamListenerTestUtils.FooOutboundChannel1 source2 = context.getBean(StreamListenerTestUtils.FooOutboundChannel1.class);
|
||||
StreamListenerTestUtils.FooOutboundChannel1 source2 = context
|
||||
.getBean(StreamListenerTestUtils.FooOutboundChannel1.class);
|
||||
final CountDownLatch latch = new CountDownLatch(2);
|
||||
((SubscribableChannel) processor.output()).subscribe(new MessageHandler() {
|
||||
@Override
|
||||
@@ -281,28 +289,31 @@ public class StreamListenerHandlerMethodTests {
|
||||
context.close();
|
||||
}
|
||||
|
||||
@EnableBinding({Processor.class, StreamListenerTestUtils.FooOutboundChannel1.class})
|
||||
@EnableBinding({ Processor.class, StreamListenerTestUtils.FooOutboundChannel1.class })
|
||||
@EnableAutoConfiguration
|
||||
public static class TestMethodWithMultipleOutputParameters {
|
||||
|
||||
@StreamListener
|
||||
public void receive(@Input(Processor.INPUT) SubscribableChannel input, @Output(Processor.OUTPUT) final MessageChannel output1,
|
||||
public void receive(@Input(Processor.INPUT) SubscribableChannel input,
|
||||
@Output(Processor.OUTPUT) final MessageChannel output1,
|
||||
@Output(StreamListenerTestUtils.FooOutboundChannel1.OUTPUT) final MessageChannel output2) {
|
||||
input.subscribe(new MessageHandler() {
|
||||
@Override
|
||||
public void handleMessage(Message<?> message) throws MessagingException {
|
||||
if (message.getHeaders().get("output").equals("output1")) {
|
||||
output1.send(org.springframework.messaging.support.MessageBuilder.withPayload(message.getPayload().toString().toUpperCase()).build());
|
||||
output1.send(org.springframework.messaging.support.MessageBuilder
|
||||
.withPayload(message.getPayload().toString().toUpperCase()).build());
|
||||
}
|
||||
else if (message.getHeaders().get("output").equals("output2")) {
|
||||
output2.send(org.springframework.messaging.support.MessageBuilder.withPayload(message.getPayload().toString().toLowerCase()).build());
|
||||
output2.send(org.springframework.messaging.support.MessageBuilder
|
||||
.withPayload(message.getPayload().toString().toLowerCase()).build());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@EnableBinding({Sink.class})
|
||||
@EnableBinding({ Sink.class })
|
||||
@EnableAutoConfiguration
|
||||
public static class TestMethodWithoutInput {
|
||||
|
||||
@@ -311,7 +322,7 @@ public class StreamListenerHandlerMethodTests {
|
||||
}
|
||||
}
|
||||
|
||||
@EnableBinding({Processor.class})
|
||||
@EnableBinding({ Processor.class })
|
||||
@EnableAutoConfiguration
|
||||
public static class TestMethodWithObjectAsMethodArgument {
|
||||
|
||||
@@ -340,7 +351,7 @@ public class StreamListenerHandlerMethodTests {
|
||||
}
|
||||
}
|
||||
|
||||
@EnableBinding({Sink.class})
|
||||
@EnableBinding({ Sink.class })
|
||||
@EnableAutoConfiguration
|
||||
public static class TestInvalidInputOnMethod {
|
||||
|
||||
@@ -350,7 +361,7 @@ public class StreamListenerHandlerMethodTests {
|
||||
}
|
||||
}
|
||||
|
||||
@EnableBinding({Sink.class})
|
||||
@EnableBinding({ Sink.class })
|
||||
@EnableAutoConfiguration
|
||||
public static class TestAmbiguousMethodArguments1 {
|
||||
|
||||
@@ -359,27 +370,29 @@ public class StreamListenerHandlerMethodTests {
|
||||
}
|
||||
}
|
||||
|
||||
@EnableBinding({Sink.class})
|
||||
@EnableBinding({ Sink.class })
|
||||
@EnableAutoConfiguration
|
||||
public static class TestAmbiguousMethodArguments2 {
|
||||
|
||||
@StreamListener(Processor.INPUT)
|
||||
public void receive(@Payload StreamListenerTestUtils.FooPojo fooPojo, @Payload StreamListenerTestUtils.BarPojo barPojo) {
|
||||
public void receive(@Payload StreamListenerTestUtils.FooPojo fooPojo,
|
||||
@Payload StreamListenerTestUtils.BarPojo barPojo) {
|
||||
}
|
||||
}
|
||||
|
||||
@EnableBinding({Processor.class, StreamListenerTestUtils.FooOutboundChannel1.class})
|
||||
@EnableBinding({ Processor.class, StreamListenerTestUtils.FooOutboundChannel1.class })
|
||||
@EnableAutoConfiguration
|
||||
public static class TestReturnTypeWithMultipleOutput {
|
||||
|
||||
@StreamListener
|
||||
public String receive(@Input(Processor.INPUT) SubscribableChannel input1, @Output(Processor.OUTPUT) MessageChannel output1,
|
||||
public String receive(@Input(Processor.INPUT) SubscribableChannel input1,
|
||||
@Output(Processor.OUTPUT) MessageChannel output1,
|
||||
@Output(StreamListenerTestUtils.FooOutboundChannel1.OUTPUT) MessageChannel output2) {
|
||||
return "foo";
|
||||
}
|
||||
}
|
||||
|
||||
@EnableBinding({Processor.class, StreamListenerTestUtils.FooOutboundChannel1.class})
|
||||
@EnableBinding({ Processor.class, StreamListenerTestUtils.FooOutboundChannel1.class })
|
||||
@EnableAutoConfiguration
|
||||
public static class TestInvalidReturnTypeWithNoOutput {
|
||||
|
||||
@@ -389,7 +402,7 @@ public class StreamListenerHandlerMethodTests {
|
||||
}
|
||||
}
|
||||
|
||||
@EnableBinding({Processor.class})
|
||||
@EnableBinding({ Processor.class })
|
||||
@EnableAutoConfiguration
|
||||
public static class TestInvalidInputAnnotationWithNoValue {
|
||||
|
||||
@@ -398,7 +411,7 @@ public class StreamListenerHandlerMethodTests {
|
||||
}
|
||||
}
|
||||
|
||||
@EnableBinding({Processor.class})
|
||||
@EnableBinding({ Processor.class })
|
||||
@EnableAutoConfiguration
|
||||
public static class TestInvalidOutputAnnotationWithNoValue {
|
||||
|
||||
@@ -407,7 +420,7 @@ public class StreamListenerHandlerMethodTests {
|
||||
}
|
||||
}
|
||||
|
||||
@EnableBinding({Sink.class})
|
||||
@EnableBinding({ Sink.class })
|
||||
@EnableAutoConfiguration
|
||||
public static class TestMethodInvalidInboundName {
|
||||
|
||||
@@ -416,16 +429,17 @@ public class StreamListenerHandlerMethodTests {
|
||||
}
|
||||
}
|
||||
|
||||
@EnableBinding({Processor.class})
|
||||
@EnableBinding({ Processor.class })
|
||||
@EnableAutoConfiguration
|
||||
public static class TestMethodInvalidOutboundName {
|
||||
|
||||
@StreamListener
|
||||
public void receive(@Input(Processor.INPUT) SubscribableChannel input, @Output("invalid") MessageChannel output) {
|
||||
public void receive(@Input(Processor.INPUT) SubscribableChannel input,
|
||||
@Output("invalid") MessageChannel output) {
|
||||
}
|
||||
}
|
||||
|
||||
@EnableBinding({Sink.class})
|
||||
@EnableBinding({ Sink.class })
|
||||
@EnableAutoConfiguration
|
||||
public static class TestMethodWithInputAsMethodAndParameter {
|
||||
|
||||
@@ -434,39 +448,44 @@ public class StreamListenerHandlerMethodTests {
|
||||
}
|
||||
}
|
||||
|
||||
@EnableBinding({Processor.class, StreamListenerTestUtils.FooOutboundChannel1.class})
|
||||
@EnableBinding({ Processor.class, StreamListenerTestUtils.FooOutboundChannel1.class })
|
||||
@EnableAutoConfiguration
|
||||
public static class TestMethodWithOutputAsMethodAndParameter {
|
||||
|
||||
@StreamListener
|
||||
@Output(StreamListenerTestUtils.FooOutboundChannel1.OUTPUT)
|
||||
public void receive(@Input(Processor.INPUT) SubscribableChannel input, @Output(Processor.OUTPUT) final MessageChannel output1) {
|
||||
public void receive(@Input(Processor.INPUT) SubscribableChannel input,
|
||||
@Output(Processor.OUTPUT) final MessageChannel output1) {
|
||||
input.subscribe(new MessageHandler() {
|
||||
@Override
|
||||
public void handleMessage(Message<?> message) throws MessagingException {
|
||||
output1.send(org.springframework.messaging.support.MessageBuilder.withPayload(message.getPayload().toString().toUpperCase()).build());
|
||||
output1.send(org.springframework.messaging.support.MessageBuilder
|
||||
.withPayload(message.getPayload().toString().toUpperCase()).build());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@EnableBinding({Processor.class, StreamListenerTestUtils.FooInboundChannel1.class})
|
||||
@EnableBinding({ Processor.class, StreamListenerTestUtils.FooInboundChannel1.class })
|
||||
@EnableAutoConfiguration
|
||||
public static class TestMethodWithMultipleInputParameters {
|
||||
|
||||
@StreamListener
|
||||
public void receive(@Input(Processor.INPUT) SubscribableChannel input1, @Input(StreamListenerTestUtils.FooInboundChannel1.INPUT) SubscribableChannel input2,
|
||||
public void receive(@Input(Processor.INPUT) SubscribableChannel input1,
|
||||
@Input(StreamListenerTestUtils.FooInboundChannel1.INPUT) SubscribableChannel input2,
|
||||
final @Output(Processor.OUTPUT) MessageChannel output) {
|
||||
input1.subscribe(new MessageHandler() {
|
||||
@Override
|
||||
public void handleMessage(Message<?> message) throws MessagingException {
|
||||
output.send(org.springframework.messaging.support.MessageBuilder.withPayload(message.getPayload().toString().toUpperCase()).build());
|
||||
output.send(org.springframework.messaging.support.MessageBuilder
|
||||
.withPayload(message.getPayload().toString().toUpperCase()).build());
|
||||
}
|
||||
});
|
||||
input2.subscribe(new MessageHandler() {
|
||||
@Override
|
||||
public void handleMessage(Message<?> message) throws MessagingException {
|
||||
output.send(org.springframework.messaging.support.MessageBuilder.withPayload(message.getPayload().toString().toUpperCase()).build());
|
||||
output.send(org.springframework.messaging.support.MessageBuilder
|
||||
.withPayload(message.getPayload().toString().toUpperCase()).build());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ public class StreamListenerMessageArgumentTests {
|
||||
|
||||
@Parameterized.Parameters
|
||||
public static Collection InputConfigs() {
|
||||
return Arrays.asList(new Class[] {TestPojoWithMessageArgument1.class, TestPojoWithMessageArgument2.class});
|
||||
return Arrays.asList(new Class[] { TestPojoWithMessageArgument1.class, TestPojoWithMessageArgument2.class });
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -52,11 +52,12 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Ilayaperumal Gopinathan
|
||||
*/
|
||||
@RunWith(StreamListenerMethodReturnWithConversionTests.class)
|
||||
@Suite.SuiteClasses({StreamListenerMethodReturnWithConversionTests.TestReturnConversion.class,
|
||||
StreamListenerMethodReturnWithConversionTests.TestReturnNoConversion.class})
|
||||
@Suite.SuiteClasses({ StreamListenerMethodReturnWithConversionTests.TestReturnConversion.class,
|
||||
StreamListenerMethodReturnWithConversionTests.TestReturnNoConversion.class })
|
||||
public class StreamListenerMethodReturnWithConversionTests extends Suite {
|
||||
|
||||
public StreamListenerMethodReturnWithConversionTests(Class<?> klass, RunnerBuilder builder) throws InitializationError {
|
||||
public StreamListenerMethodReturnWithConversionTests(Class<?> klass, RunnerBuilder builder)
|
||||
throws InitializationError {
|
||||
super(klass, builder);
|
||||
}
|
||||
|
||||
@@ -71,7 +72,7 @@ public class StreamListenerMethodReturnWithConversionTests extends Suite {
|
||||
|
||||
@Parameterized.Parameters
|
||||
public static Collection InputConfigs() {
|
||||
return Arrays.asList(new Class[] {TestPojoWithMimeType1.class, TestPojoWithMimeType2.class});
|
||||
return Arrays.asList(new Class[] { TestPojoWithMimeType1.class, TestPojoWithMimeType2.class });
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -87,10 +88,12 @@ public class StreamListenerMethodReturnWithConversionTests extends Suite {
|
||||
TestPojoWithMimeType testPojoWithMimeType = context.getBean(TestPojoWithMimeType.class);
|
||||
assertThat(testPojoWithMimeType.receivedPojos).hasSize(1);
|
||||
assertThat(testPojoWithMimeType.receivedPojos.get(0)).hasFieldOrPropertyWithValue("foo", "barbar" + id);
|
||||
Message<String> message = (Message<String>) collector.forChannel(processor.output()).poll(1, TimeUnit.SECONDS);
|
||||
Message<String> message = (Message<String>) collector.forChannel(processor.output()).poll(1,
|
||||
TimeUnit.SECONDS);
|
||||
assertThat(message).isNotNull();
|
||||
assertThat(message.getPayload()).isEqualTo("{\"bar\":\"barbar" + id + "\"}");
|
||||
assertThat(message.getHeaders().get(MessageHeaders.CONTENT_TYPE, MimeType.class).includes(MimeTypeUtils.APPLICATION_JSON));
|
||||
assertThat(message.getHeaders().get(MessageHeaders.CONTENT_TYPE, MimeType.class)
|
||||
.includes(MimeTypeUtils.APPLICATION_JSON));
|
||||
context.close();
|
||||
}
|
||||
}
|
||||
@@ -106,7 +109,7 @@ public class StreamListenerMethodReturnWithConversionTests extends Suite {
|
||||
|
||||
@Parameterized.Parameters
|
||||
public static Collection InputConfigs() {
|
||||
return Arrays.asList(new Class[] {TestPojoWithMimeType1.class, TestPojoWithMimeType2.class});
|
||||
return Arrays.asList(new Class[] { TestPojoWithMimeType1.class, TestPojoWithMimeType2.class });
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -121,8 +124,9 @@ public class StreamListenerMethodReturnWithConversionTests extends Suite {
|
||||
TestPojoWithMimeType testPojoWithMimeType = context.getBean(TestPojoWithMimeType.class);
|
||||
assertThat(testPojoWithMimeType.receivedPojos).hasSize(1);
|
||||
assertThat(testPojoWithMimeType.receivedPojos.get(0)).hasFieldOrPropertyWithValue("foo", "barbar" + id);
|
||||
Message<StreamListenerTestUtils.BarPojo> message = (Message<StreamListenerTestUtils.BarPojo>) collector.forChannel(processor.output()).poll(1,
|
||||
TimeUnit.SECONDS);
|
||||
Message<StreamListenerTestUtils.BarPojo> message = (Message<StreamListenerTestUtils.BarPojo>) collector
|
||||
.forChannel(processor.output()).poll(1,
|
||||
TimeUnit.SECONDS);
|
||||
assertThat(message).isNotNull();
|
||||
assertThat(message.getPayload().getBar()).isEqualTo("barbar" + id);
|
||||
assertThat(message.getHeaders().get(MessageHeaders.CONTENT_TYPE, MimeType.class) == null);
|
||||
|
||||
@@ -56,7 +56,7 @@ public class StreamListenerMethodWithReturnMessageTests {
|
||||
|
||||
@Parameterized.Parameters
|
||||
public static Collection InputConfigs() {
|
||||
return Arrays.asList(new Class[]{TestPojoWithMessageReturn1.class, TestPojoWithMessageReturn2.class});
|
||||
return Arrays.asList(new Class[] { TestPojoWithMessageReturn1.class, TestPojoWithMessageReturn2.class });
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -56,7 +56,7 @@ public class StreamListenerMethodWithReturnValueTests {
|
||||
|
||||
@Parameterized.Parameters
|
||||
public static Collection InputConfigs() {
|
||||
return Arrays.asList(new Class[]{TestStringProcessor1.class, TestStringProcessor2.class});
|
||||
return Arrays.asList(new Class[] { TestStringProcessor1.class, TestStringProcessor2.class });
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -26,6 +26,24 @@ import org.springframework.messaging.SubscribableChannel;
|
||||
*/
|
||||
public class StreamListenerTestUtils {
|
||||
|
||||
public interface FooInboundChannel1 {
|
||||
|
||||
String INPUT = "foo1-input";
|
||||
|
||||
@Input(FooInboundChannel1.INPUT)
|
||||
SubscribableChannel input();
|
||||
|
||||
}
|
||||
|
||||
public interface FooOutboundChannel1 {
|
||||
|
||||
String OUTPUT = "foo1-output";
|
||||
|
||||
@Output(FooOutboundChannel1.OUTPUT)
|
||||
MessageChannel output();
|
||||
|
||||
}
|
||||
|
||||
public static class FooPojo {
|
||||
|
||||
private String foo;
|
||||
@@ -51,22 +69,4 @@ public class StreamListenerTestUtils {
|
||||
this.bar = bar;
|
||||
}
|
||||
}
|
||||
|
||||
public interface FooInboundChannel1 {
|
||||
|
||||
String INPUT = "foo1-input";
|
||||
|
||||
@Input(FooInboundChannel1.INPUT)
|
||||
SubscribableChannel input();
|
||||
|
||||
}
|
||||
|
||||
public interface FooOutboundChannel1 {
|
||||
|
||||
String OUTPUT = "foo1-output";
|
||||
|
||||
@Output(FooOutboundChannel1.OUTPUT)
|
||||
MessageChannel output();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,13 +73,15 @@ public class StreamListenerWithAnnotatedInputOutputArgsTests {
|
||||
}
|
||||
catch (BeanCreationException e) {
|
||||
assertThat(e.getCause()).isInstanceOf(IllegalArgumentException.class);
|
||||
assertThat(e.getCause()).hasMessageContaining(StreamListenerErrorMessages.INVALID_DECLARATIVE_METHOD_PARAMETERS);
|
||||
assertThat(e.getCause())
|
||||
.hasMessageContaining(StreamListenerErrorMessages.INVALID_DECLARATIVE_METHOD_PARAMETERS);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInputOutputArgsWithParameterOrderChanged() throws Exception {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(TestInputOutputArgsWithParameterOrderChanged.class, "--server.port=0");
|
||||
ConfigurableApplicationContext context = SpringApplication
|
||||
.run(TestInputOutputArgsWithParameterOrderChanged.class, "--server.port=0");
|
||||
sendMessageAndValidate(context);
|
||||
}
|
||||
|
||||
@@ -94,13 +96,13 @@ public class StreamListenerWithAnnotatedInputOutputArgsTests {
|
||||
context.close();
|
||||
}
|
||||
|
||||
|
||||
@EnableBinding(Processor.class)
|
||||
@EnableAutoConfiguration
|
||||
public static class TestInputOutputArgs {
|
||||
|
||||
@StreamListener
|
||||
public void receive(@Input(Processor.INPUT) SubscribableChannel input, @Output(Processor.OUTPUT) final MessageChannel output) {
|
||||
public void receive(@Input(Processor.INPUT) SubscribableChannel input,
|
||||
@Output(Processor.OUTPUT) final MessageChannel output) {
|
||||
input.subscribe(new MessageHandler() {
|
||||
@Override
|
||||
public void handleMessage(Message<?> message) throws MessagingException {
|
||||
@@ -115,7 +117,8 @@ public class StreamListenerWithAnnotatedInputOutputArgsTests {
|
||||
public static class TestInputOutputArgsWithMoreParameters {
|
||||
|
||||
@StreamListener
|
||||
public void receive(@Input(Processor.INPUT) SubscribableChannel input, @Output(Processor.OUTPUT) final MessageChannel output,
|
||||
public void receive(@Input(Processor.INPUT) SubscribableChannel input,
|
||||
@Output(Processor.OUTPUT) final MessageChannel output,
|
||||
String someArg) {
|
||||
input.subscribe(new MessageHandler() {
|
||||
@Override
|
||||
@@ -131,7 +134,8 @@ public class StreamListenerWithAnnotatedInputOutputArgsTests {
|
||||
public static class TestInputOutputArgsWithInvalidBindableTarget {
|
||||
|
||||
@StreamListener
|
||||
public void receive(@Input("invalid") SubscribableChannel input, @Output(Processor.OUTPUT) final MessageChannel output) {
|
||||
public void receive(@Input("invalid") SubscribableChannel input,
|
||||
@Output(Processor.OUTPUT) final MessageChannel output) {
|
||||
input.subscribe(new MessageHandler() {
|
||||
@Override
|
||||
public void handleMessage(Message<?> message) throws MessagingException {
|
||||
@@ -146,7 +150,8 @@ public class StreamListenerWithAnnotatedInputOutputArgsTests {
|
||||
public static class TestInputOutputArgsWithParameterOrderChanged {
|
||||
|
||||
@StreamListener
|
||||
public void receive(@Output(Processor.OUTPUT) final MessageChannel output, @Input("input") SubscribableChannel input) {
|
||||
public void receive(@Output(Processor.OUTPUT) final MessageChannel output,
|
||||
@Input("input") SubscribableChannel input) {
|
||||
input.subscribe(new MessageHandler() {
|
||||
@Override
|
||||
public void handleMessage(Message<?> message) throws MessagingException {
|
||||
|
||||
@@ -75,13 +75,16 @@ public class StreamListenerWithConditionsTest {
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testConditionalFailsWithReturnValue() throws Exception {
|
||||
try {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(TestConditionalOnMethodWithReturnValueFails.class,
|
||||
ConfigurableApplicationContext context = SpringApplication.run(
|
||||
TestConditionalOnMethodWithReturnValueFails.class,
|
||||
"--server.port=0");
|
||||
context.close();
|
||||
fail("Context creation failure expected");
|
||||
} catch (BeanCreationException e) {
|
||||
}
|
||||
catch (BeanCreationException e) {
|
||||
assertThat(e).hasRootCauseInstanceOf(IllegalArgumentException.class);
|
||||
assertThat(e.getCause()).hasMessageContaining(StreamListenerErrorMessages.CONDITION_ON_METHOD_RETURNING_VALUE);
|
||||
assertThat(e.getCause())
|
||||
.hasMessageContaining(StreamListenerErrorMessages.CONDITION_ON_METHOD_RETURNING_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,11 +92,13 @@ public class StreamListenerWithConditionsTest {
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testConditionalFailsWithDeclarativeMethod() throws Exception {
|
||||
try {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(TestConditionalOnDeclarativeMethodFails.class,
|
||||
ConfigurableApplicationContext context = SpringApplication.run(
|
||||
TestConditionalOnDeclarativeMethodFails.class,
|
||||
"--server.port=0");
|
||||
context.close();
|
||||
fail("Context creation failure expected");
|
||||
} catch (BeanCreationException e) {
|
||||
}
|
||||
catch (BeanCreationException e) {
|
||||
assertThat(e).hasRootCauseInstanceOf(IllegalArgumentException.class);
|
||||
assertThat(e.getCause()).hasMessageContaining(StreamListenerErrorMessages.CONDITION_ON_DECLARATIVE_METHOD);
|
||||
}
|
||||
|
||||
@@ -43,8 +43,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @since 1.2
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringBootTest(classes = TextPlainConversionTest.FooProcessor.class,
|
||||
webEnvironment = SpringBootTest.WebEnvironment.NONE)
|
||||
@SpringBootTest(classes = TextPlainConversionTest.FooProcessor.class, webEnvironment = SpringBootTest.WebEnvironment.NONE)
|
||||
public class TextPlainConversionTest {
|
||||
|
||||
@Autowired
|
||||
@@ -83,7 +82,6 @@ public class TextPlainConversionTest {
|
||||
assertThat(received.getPayload()).isEqualTo("Foo{name='Foo{name='Bar'}'}");
|
||||
}
|
||||
|
||||
|
||||
@EnableBinding(Processor.class)
|
||||
@EnableAutoConfiguration
|
||||
@PropertySource("classpath:/org/springframework/cloud/stream/config/textplain/text-plain.properties")
|
||||
|
||||
@@ -44,10 +44,13 @@ public class AggregateApplicationTests {
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testAggregateApplication() throws Exception {
|
||||
ConfigurableApplicationContext context = new AggregateApplicationBuilder(TestSupportBinderAutoConfiguration.class).from(TestSource.class).to(TestProcessor.class).run();
|
||||
TestSupportBinder testSupportBinder = (TestSupportBinder) context.getBean(BinderFactory.class).getBinder(null, MessageChannel.class);
|
||||
ConfigurableApplicationContext context = new AggregateApplicationBuilder(
|
||||
TestSupportBinderAutoConfiguration.class).from(TestSource.class).to(TestProcessor.class).run();
|
||||
TestSupportBinder testSupportBinder = (TestSupportBinder) context.getBean(BinderFactory.class).getBinder(null,
|
||||
MessageChannel.class);
|
||||
MessageChannel processorOutput = testSupportBinder.getChannelForName("output");
|
||||
Message<String> received = (Message<String>) (testSupportBinder.messageCollector().forChannel(processorOutput).poll(5, TimeUnit.SECONDS));
|
||||
Message<String> received = (Message<String>) (testSupportBinder.messageCollector().forChannel(processorOutput)
|
||||
.poll(5, TimeUnit.SECONDS));
|
||||
Assert.assertThat(received, notNullValue());
|
||||
Assert.assertTrue(received.getPayload().endsWith("processed"));
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ public class ApplicationMetrics {
|
||||
private final Date createdTime;
|
||||
|
||||
private String name;
|
||||
|
||||
|
||||
private Collection<Metric<?>> metrics;
|
||||
|
||||
private Map<String, Object> properties;
|
||||
|
||||
@@ -44,6 +44,8 @@ import org.springframework.util.PatternMatchUtils;
|
||||
public class ApplicationMetricsProperties
|
||||
implements ApplicationListener<ContextRefreshedEvent> {
|
||||
|
||||
private final MetricExportProperties metricExportProperties;
|
||||
|
||||
private String prefix = "";
|
||||
|
||||
@Value("${spring.application.name:${vcap.application.name:${spring.config.name:application}}}")
|
||||
@@ -53,17 +55,23 @@ public class ApplicationMetricsProperties
|
||||
|
||||
private String[] properties;
|
||||
|
||||
private final MetricExportProperties metricExportProperties;
|
||||
|
||||
public TriggerProperties getTrigger() {
|
||||
return metricExportProperties.findTrigger(BinderMetricsAutoConfiguration.APPLICATION_METRICS_EXPORTER_TRIGGER_NAME);
|
||||
}
|
||||
/**
|
||||
* List of properties that are going to be appended to each message. This gets
|
||||
* populate by onApplicationEvent, once the context refreshes to avoid overhead of
|
||||
* doing per message basis.
|
||||
*/
|
||||
private Map<String, Object> exportProperties = new HashMap<>();
|
||||
|
||||
public ApplicationMetricsProperties(MetricExportProperties metricExportProperties) {
|
||||
Assert.notNull(metricExportProperties, "'metricsExportProperties' cannot be null");
|
||||
this.metricExportProperties = metricExportProperties;
|
||||
}
|
||||
|
||||
public TriggerProperties getTrigger() {
|
||||
return metricExportProperties
|
||||
.findTrigger(BinderMetricsAutoConfiguration.APPLICATION_METRICS_EXPORTER_TRIGGER_NAME);
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
@@ -91,13 +99,6 @@ public class ApplicationMetricsProperties
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of properties that are going to be appended to each message. This gets
|
||||
* populate by onApplicationEvent, once the context refreshes to avoid overhead of
|
||||
* doing per message basis.
|
||||
*/
|
||||
private Map<String, Object> exportProperties = new HashMap<>();
|
||||
|
||||
public Map<String, Object> getExportProperties() {
|
||||
return exportProperties;
|
||||
}
|
||||
@@ -137,7 +138,7 @@ public class ApplicationMetricsProperties
|
||||
relaxedLoop: for (String relaxedPropertyName : relaxedNames) {
|
||||
if (isMatch(relaxedPropertyName, this.properties, null)) {
|
||||
Object value = source.getProperty(propertyName);
|
||||
String stringValue = ObjectUtils.nullSafeToString(value);
|
||||
String stringValue = ObjectUtils.nullSafeToString(value);
|
||||
Object exportedValue = null;
|
||||
if (value != null) {
|
||||
exportedValue = stringValue.startsWith("#{")
|
||||
|
||||
@@ -40,8 +40,8 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
|
||||
/**
|
||||
* Autoconfiguration registering an {@link Exporter} that publishes application metrics over
|
||||
* the {@link Emitter#applicationMetrics()} channel.
|
||||
* Autoconfiguration registering an {@link Exporter} that publishes application metrics
|
||||
* over the {@link Emitter#applicationMetrics()} channel.
|
||||
*
|
||||
* @author Vinicius Carvalho
|
||||
* @author Marius Bogoevici
|
||||
@@ -56,19 +56,15 @@ import org.springframework.context.annotation.Lazy;
|
||||
+ ".destination")
|
||||
public class BinderMetricsAutoConfiguration {
|
||||
|
||||
public static Log log = LogFactory.getLog(BinderMetricsAutoConfiguration.class);
|
||||
|
||||
public static final String APPLICATION_METRICS_EXPORTER_TRIGGER_NAME = "application";
|
||||
|
||||
@Bean
|
||||
public MetricJsonSerializer metricJsonSerializer() {
|
||||
return new MetricJsonSerializer();
|
||||
}
|
||||
public static Log log = LogFactory.getLog(BinderMetricsAutoConfiguration.class);
|
||||
|
||||
/**
|
||||
* Postprocessor for installing the {@link ApplicationMetricsExporter} as an
|
||||
* exporter under the name {@code application}.
|
||||
* @param endpoint the metrics endpoint (lazy reference to prevent early initialization)
|
||||
* Postprocessor for installing the {@link ApplicationMetricsExporter} as an exporter
|
||||
* under the name {@code application}.
|
||||
* @param endpoint the metrics endpoint (lazy reference to prevent early
|
||||
* initialization)
|
||||
* @param emitter the emitter bound interface
|
||||
* @param properties application metrics properties
|
||||
* @return
|
||||
@@ -101,4 +97,9 @@ public class BinderMetricsAutoConfiguration {
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MetricJsonSerializer metricJsonSerializer() {
|
||||
return new MetricJsonSerializer();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -46,6 +46,12 @@ public class MetricJsonSerializer {
|
||||
|
||||
private static final BlockingQueue<DateFormat> formatters = new LinkedBlockingQueue<DateFormat>();
|
||||
|
||||
private static DateFormat defaultDateFormat() {
|
||||
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
|
||||
df.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
return df;
|
||||
}
|
||||
|
||||
public static class Serializer extends JsonSerializer<Metric<?>> {
|
||||
|
||||
@Override
|
||||
@@ -95,10 +101,4 @@ public class MetricJsonSerializer {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static DateFormat defaultDateFormat() {
|
||||
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
|
||||
df.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
return df;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +101,8 @@ public class ApplicationMetricsExporterTests {
|
||||
.poll(10, TimeUnit.SECONDS);
|
||||
Assert.assertNotNull(message);
|
||||
ObjectMapper mapper = applicationContext.getBean(ObjectMapper.class);
|
||||
ApplicationMetrics applicationMetrics = mapper.readValue((String) message.getPayload(), ApplicationMetrics.class);
|
||||
ApplicationMetrics applicationMetrics = mapper.readValue((String) message.getPayload(),
|
||||
ApplicationMetrics.class);
|
||||
Assert.assertTrue(contains("integration.channel.errorChannel.errorRate.mean",
|
||||
applicationMetrics.getMetrics()));
|
||||
Assert.assertTrue(contains("mem", applicationMetrics.getMetrics()));
|
||||
@@ -171,7 +172,8 @@ public class ApplicationMetricsExporterTests {
|
||||
.poll(10, TimeUnit.SECONDS);
|
||||
Assert.assertNotNull(message);
|
||||
ObjectMapper mapper = applicationContext.getBean(ObjectMapper.class);
|
||||
ApplicationMetrics applicationMetrics = mapper.readValue((String) message.getPayload(), ApplicationMetrics.class);
|
||||
ApplicationMetrics applicationMetrics = mapper.readValue((String) message.getPayload(),
|
||||
ApplicationMetrics.class);
|
||||
Assert.assertFalse(contains("integration.channel.errorChannel.errorRate.mean",
|
||||
applicationMetrics.getMetrics()));
|
||||
Assert.assertTrue(contains("mem", applicationMetrics.getMetrics()));
|
||||
@@ -193,7 +195,8 @@ public class ApplicationMetricsExporterTests {
|
||||
.poll(10, TimeUnit.SECONDS);
|
||||
Assert.assertNotNull(message);
|
||||
ObjectMapper mapper = applicationContext.getBean(ObjectMapper.class);
|
||||
ApplicationMetrics applicationMetrics = mapper.readValue((String) message.getPayload(), ApplicationMetrics.class);
|
||||
ApplicationMetrics applicationMetrics = mapper.readValue((String) message.getPayload(),
|
||||
ApplicationMetrics.class);
|
||||
Assert.assertFalse(contains("mem", applicationMetrics.getMetrics()));
|
||||
Assert.assertTrue(contains("integration.channel.errorChannel.errorRate.mean",
|
||||
applicationMetrics.getMetrics()));
|
||||
@@ -225,7 +228,8 @@ public class ApplicationMetricsExporterTests {
|
||||
.poll(10, TimeUnit.SECONDS);
|
||||
Assert.assertNotNull(message);
|
||||
ObjectMapper mapper = applicationContext.getBean(ObjectMapper.class);
|
||||
ApplicationMetrics applicationMetrics = mapper.readValue((String) message.getPayload(), ApplicationMetrics.class);
|
||||
ApplicationMetrics applicationMetrics = mapper.readValue((String) message.getPayload(),
|
||||
ApplicationMetrics.class);
|
||||
Assert.assertTrue(contains("integration.channel.errorChannel.errorRate.mean",
|
||||
applicationMetrics.getMetrics()));
|
||||
Assertions.assertThat(applicationMetrics.getProperties().get("spring.cloud.application.guid"))
|
||||
@@ -260,13 +264,15 @@ public class ApplicationMetricsExporterTests {
|
||||
.poll(10, TimeUnit.SECONDS);
|
||||
Assert.assertNotNull(message);
|
||||
ObjectMapper mapper = applicationContext.getBean(ObjectMapper.class);
|
||||
ApplicationMetrics applicationMetrics = mapper.readValue((String) message.getPayload(), ApplicationMetrics.class);
|
||||
ApplicationMetrics applicationMetrics = mapper.readValue((String) message.getPayload(),
|
||||
ApplicationMetrics.class);
|
||||
Assert.assertTrue(contains("integration.channel.errorChannel.errorRate.mean",
|
||||
applicationMetrics.getMetrics()));
|
||||
Assertions.assertThat(applicationMetrics.getProperties().get("spring.cloud.application.guid.test.metrics"))
|
||||
.isEqualTo("highPriority");
|
||||
applicationContext.close();
|
||||
} finally {
|
||||
}
|
||||
finally {
|
||||
System.clearProperty("spring.cloud.application.guid.test.metrics");
|
||||
}
|
||||
}
|
||||
@@ -285,7 +291,8 @@ public class ApplicationMetricsExporterTests {
|
||||
.poll(10, TimeUnit.SECONDS);
|
||||
Assert.assertNotNull(message);
|
||||
ObjectMapper mapper = applicationContext.getBean(ObjectMapper.class);
|
||||
ApplicationMetrics applicationMetrics = mapper.readValue((String) message.getPayload(), ApplicationMetrics.class);
|
||||
ApplicationMetrics applicationMetrics = mapper.readValue((String) message.getPayload(),
|
||||
ApplicationMetrics.class);
|
||||
Assert.assertTrue(contains("integration.channel.errorChannel.errorRate.mean",
|
||||
applicationMetrics.getMetrics()));
|
||||
Assert.assertTrue(contains("mem", applicationMetrics.getMetrics()));
|
||||
|
||||
@@ -33,8 +33,10 @@ public class RelaxedPropertiesUtilsTests {
|
||||
RelaxedNames springEnv = new RelaxedNames("SPRING_APPLICATION_NAME");
|
||||
RelaxedNames springDot = new RelaxedNames("spring.application.name");
|
||||
RelaxedNames springCamel = new RelaxedNames("springApplicationName");
|
||||
RelaxedNames contentType = new RelaxedNames("spring.cloud.stream.bindings.applicationMetricsChannel.contentType");
|
||||
RelaxedNames contentTypeEnv = new RelaxedNames("SPRING_CLOUD_STREAM_BINDINGS_APPLICATION-METRICS-CHANNEL_CONTENT-TYPE");
|
||||
RelaxedNames contentType = new RelaxedNames(
|
||||
"spring.cloud.stream.bindings.applicationMetricsChannel.contentType");
|
||||
RelaxedNames contentTypeEnv = new RelaxedNames(
|
||||
"SPRING_CLOUD_STREAM_BINDINGS_APPLICATION-METRICS-CHANNEL_CONTENT-TYPE");
|
||||
RelaxedNames xyz = new RelaxedNames("My.X.Is");
|
||||
RelaxedNames springMetrics = new RelaxedNames("spring.cloud.stream.applicationMetricsChannel");
|
||||
RelaxedNames springMetricsEnv = new RelaxedNames("spring.cloud.stream.application-metrics-channel");
|
||||
|
||||
@@ -21,7 +21,6 @@ import java.util.Date;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -36,17 +35,17 @@ import static org.junit.Assert.assertEquals;
|
||||
public class MetricJsonSerializerTests {
|
||||
|
||||
@Test
|
||||
public void validateAlwaysGMTDateAndFormat() throws Exception {
|
||||
public void validateAlwaysGMTDateAndFormat() throws Exception {
|
||||
Date date = new Date(1493060197188L); // Mon Apr 24 14:56:37 EDT 2017
|
||||
Metric<Number> metric = new Metric<Number>("Hello", 123, date);
|
||||
|
||||
Metric<Number> metric = new Metric<Number>("Hello", 123, date);
|
||||
|
||||
JsonFactory factory = new JsonFactory();
|
||||
StringWriter writer = new StringWriter();
|
||||
StringWriter writer = new StringWriter();
|
||||
JsonGenerator jsonGenerator = factory.createGenerator(writer);
|
||||
Serializer ser = new Serializer();
|
||||
Serializer ser = new Serializer();
|
||||
ser.serialize(metric, jsonGenerator, null);
|
||||
jsonGenerator.flush();
|
||||
|
||||
|
||||
JSONObject json = new JSONObject(writer.toString());
|
||||
String serializedTimestamp = json.getString("timestamp");
|
||||
assertEquals("2017-04-24T18:56:37.188Z", serializedTimestamp);
|
||||
|
||||
@@ -26,8 +26,8 @@ import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
|
||||
/**
|
||||
* A {@link org.springframework.cloud.stream.binding.StreamListenerResultAdapter} from a {@link Flux}
|
||||
* return type to a bound {@link MessageChannel}.
|
||||
* A {@link org.springframework.cloud.stream.binding.StreamListenerResultAdapter} from a
|
||||
* {@link Flux} return type to a bound {@link MessageChannel}.
|
||||
* @author Marius Bogoevici
|
||||
*/
|
||||
public class FluxToMessageChannelResultAdapter
|
||||
|
||||
@@ -53,8 +53,9 @@ public class MessageChannelToFluxSenderParameterAdapter
|
||||
.doOnError(e -> this.log.error("Error during processing: ", e))
|
||||
.retry()
|
||||
.subscribe(
|
||||
result -> bindingTarget.send(result instanceof Message<?> ? (Message<?>) result :
|
||||
MessageBuilder.withPayload(result).build()), e -> sendResult.onError(e),
|
||||
result -> bindingTarget.send(result instanceof Message<?> ? (Message<?>) result
|
||||
: MessageBuilder.withPayload(result).build()),
|
||||
e -> sendResult.onError(e),
|
||||
() -> sendResult.onComplete());
|
||||
return sendResult;
|
||||
};
|
||||
|
||||
@@ -55,8 +55,7 @@ public class MessageChannelToObservableSenderParameterAdapter implements
|
||||
public ObservableSender adapt(MessageChannel bindingTarget, MethodParameter parameter) {
|
||||
return new ObservableSender() {
|
||||
|
||||
private FluxSender fluxSender = MessageChannelToObservableSenderParameterAdapter.this
|
||||
.messageChannelToFluxSenderArgumentAdapter
|
||||
private FluxSender fluxSender = MessageChannelToObservableSenderParameterAdapter.this.messageChannelToFluxSenderArgumentAdapter
|
||||
.adapt(bindingTarget, parameter);
|
||||
|
||||
@Override
|
||||
|
||||
@@ -26,8 +26,8 @@ import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A {@link StreamListenerResultAdapter} from an {@link Observable}
|
||||
* return type to a bound {@link MessageChannel}.
|
||||
* A {@link StreamListenerResultAdapter} from an {@link Observable} return type to a bound
|
||||
* {@link MessageChannel}.
|
||||
*
|
||||
* @author Marius Bogoevici
|
||||
*/
|
||||
|
||||
@@ -71,8 +71,7 @@ public class ReactiveSupportAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(ObservableToMessageChannelResultAdapter.class)
|
||||
public ObservableToMessageChannelResultAdapter
|
||||
observableToMessageChannelResultAdapter(
|
||||
public ObservableToMessageChannelResultAdapter observableToMessageChannelResultAdapter(
|
||||
FluxToMessageChannelResultAdapter fluxToMessageChannelResultAdapter) {
|
||||
return new ObservableToMessageChannelResultAdapter(fluxToMessageChannelResultAdapter);
|
||||
}
|
||||
|
||||
@@ -44,9 +44,21 @@ import static org.springframework.cloud.stream.binding.StreamListenerErrorMessag
|
||||
@SuppressWarnings("unchecked")
|
||||
public class StreamListenerGenericFluxInputOutputArgsWithMessageTests {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static void sendMessageAndValidate(ConfigurableApplicationContext context) throws InterruptedException {
|
||||
Processor processor = context.getBean(Processor.class);
|
||||
String sentPayload = "hello " + UUID.randomUUID().toString();
|
||||
processor.input().send(MessageBuilder.withPayload(sentPayload).setHeader("contentType", "text/plain").build());
|
||||
MessageCollector messageCollector = context.getBean(MessageCollector.class);
|
||||
Message<?> result = messageCollector.forChannel(processor.output()).poll(1000, TimeUnit.MILLISECONDS);
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result.getPayload()).isEqualTo(sentPayload.toUpperCase());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenericFluxInputOutputArgsWithMessage() throws Exception {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(TestGenericStringFluxInputOutputArgsWithMessageImpl1.class, "--server.port=0");
|
||||
ConfigurableApplicationContext context = SpringApplication
|
||||
.run(TestGenericStringFluxInputOutputArgsWithMessageImpl1.class, "--server.port=0");
|
||||
sendMessageAndValidate(context);
|
||||
context.close();
|
||||
}
|
||||
@@ -62,21 +74,12 @@ public class StreamListenerGenericFluxInputOutputArgsWithMessageTests {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static void sendMessageAndValidate(ConfigurableApplicationContext context) throws InterruptedException {
|
||||
Processor processor = context.getBean(Processor.class);
|
||||
String sentPayload = "hello " + UUID.randomUUID().toString();
|
||||
processor.input().send(MessageBuilder.withPayload(sentPayload).setHeader("contentType", "text/plain").build());
|
||||
MessageCollector messageCollector = context.getBean(MessageCollector.class);
|
||||
Message<?> result = messageCollector.forChannel(processor.output()).poll(1000, TimeUnit.MILLISECONDS);
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result.getPayload()).isEqualTo(sentPayload.toUpperCase());
|
||||
public static class TestGenericStringFluxInputOutputArgsWithMessageImpl1
|
||||
extends TestGenericFluxInputOutputArgsWithMessage1<String> {
|
||||
}
|
||||
|
||||
public static class TestGenericStringFluxInputOutputArgsWithMessageImpl1 extends TestGenericFluxInputOutputArgsWithMessage1<String> {
|
||||
}
|
||||
|
||||
public static class TestGenericStringFluxInputOutputArgsWithMessageImpl2 extends TestGenericFluxInputOutputArgsWithMessage2<String> {
|
||||
public static class TestGenericStringFluxInputOutputArgsWithMessageImpl2
|
||||
extends TestGenericFluxInputOutputArgsWithMessage2<String> {
|
||||
}
|
||||
|
||||
@EnableBinding(Processor.class)
|
||||
|
||||
@@ -35,8 +35,8 @@ import org.springframework.messaging.support.MessageBuilder;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Test validating that a fix for <a href="https://github.com/reactor/reactor-core/issues/159"/>
|
||||
* is present.
|
||||
* Test validating that a fix for
|
||||
* <a href="https://github.com/reactor/reactor-core/issues/159"/> is present.
|
||||
*
|
||||
* @author Marius Bogoevici
|
||||
*/
|
||||
|
||||
@@ -56,14 +56,7 @@ public class StreamListenerReactiveInputOutputArgsTests {
|
||||
|
||||
@Parameterized.Parameters
|
||||
public static Collection InputConfigs() {
|
||||
return Arrays.asList(new Class[]{ReactorTestInputOutputArgs.class, RxJava1TestInputOutputArgs.class});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInputOutputArgs() throws Exception {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(this.configClass, "--server.port=0");
|
||||
sendMessageAndValidate(context);
|
||||
context.close();
|
||||
return Arrays.asList(new Class[] { ReactorTestInputOutputArgs.class, RxJava1TestInputOutputArgs.class });
|
||||
}
|
||||
|
||||
private static void sendMessageAndValidate(ConfigurableApplicationContext context) throws InterruptedException {
|
||||
@@ -77,6 +70,13 @@ public class StreamListenerReactiveInputOutputArgsTests {
|
||||
assertThat(result.getPayload()).isEqualTo(sentPayload.toUpperCase());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInputOutputArgs() throws Exception {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(this.configClass, "--server.port=0");
|
||||
sendMessageAndValidate(context);
|
||||
context.close();
|
||||
}
|
||||
|
||||
@EnableBinding(Processor.class)
|
||||
@EnableAutoConfiguration
|
||||
public static class ReactorTestInputOutputArgs {
|
||||
@@ -92,7 +92,8 @@ public class StreamListenerReactiveInputOutputArgsTests {
|
||||
public static class RxJava1TestInputOutputArgs {
|
||||
|
||||
@StreamListener
|
||||
public void receive(@Input(Processor.INPUT) Observable<String> input, @Output(Processor.OUTPUT) ObservableSender output) {
|
||||
public void receive(@Input(Processor.INPUT) Observable<String> input,
|
||||
@Output(Processor.OUTPUT) ObservableSender output) {
|
||||
output.send(input.map(m -> m.toUpperCase()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,14 +56,8 @@ public class StreamListenerReactiveInputOutputArgsWithMessageTests {
|
||||
|
||||
@Parameterized.Parameters
|
||||
public static Collection InputConfigs() {
|
||||
return Arrays.asList(new Class[]{ReactorTestInputOutputArgsWithMessage.class, RxJava1TestInputOutputArgsWithMessage.class});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInputOutputArgs() throws Exception {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(this.configClass, "--server.port=0");
|
||||
sendMessageAndValidate(context);
|
||||
context.close();
|
||||
return Arrays.asList(new Class[] { ReactorTestInputOutputArgsWithMessage.class,
|
||||
RxJava1TestInputOutputArgsWithMessage.class });
|
||||
}
|
||||
|
||||
private static void sendMessageAndValidate(ConfigurableApplicationContext context) throws InterruptedException {
|
||||
@@ -77,6 +71,13 @@ public class StreamListenerReactiveInputOutputArgsWithMessageTests {
|
||||
assertThat(result.getPayload()).isEqualTo(sentPayload.toUpperCase());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInputOutputArgs() throws Exception {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(this.configClass, "--server.port=0");
|
||||
sendMessageAndValidate(context);
|
||||
context.close();
|
||||
}
|
||||
|
||||
@EnableBinding(Processor.class)
|
||||
@EnableAutoConfiguration
|
||||
public static class ReactorTestInputOutputArgsWithMessage {
|
||||
|
||||
@@ -56,19 +56,10 @@ public class StreamListenerReactiveInputOutputArgsWithSenderAndFailureTests {
|
||||
|
||||
@Parameterized.Parameters
|
||||
public static Collection InputConfigs() {
|
||||
return Arrays.asList(new Class[]{TestInputOutputArgsWithFluxSenderAndFailure.class, TestInputOutputArgsWithObservableSenderAndFailure.class});
|
||||
return Arrays.asList(new Class[] { TestInputOutputArgsWithFluxSenderAndFailure.class,
|
||||
TestInputOutputArgsWithObservableSenderAndFailure.class });
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInputOutputArgsWithFluxSenderAndFailure() throws Exception {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(this.configClass, "--server.port=0");
|
||||
sendMessageAndValidate(context);
|
||||
sendFailingMessage(context);
|
||||
sendMessageAndValidate(context);
|
||||
context.close();
|
||||
}
|
||||
|
||||
|
||||
private static void sendMessageAndValidate(ConfigurableApplicationContext context) throws InterruptedException {
|
||||
@SuppressWarnings("unchecked")
|
||||
Processor processor = context.getBean(Processor.class);
|
||||
@@ -86,11 +77,21 @@ public class StreamListenerReactiveInputOutputArgsWithSenderAndFailureTests {
|
||||
processor.input().send(MessageBuilder.withPayload("fail").setHeader("contentType", "text/plain").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInputOutputArgsWithFluxSenderAndFailure() throws Exception {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(this.configClass, "--server.port=0");
|
||||
sendMessageAndValidate(context);
|
||||
sendFailingMessage(context);
|
||||
sendMessageAndValidate(context);
|
||||
context.close();
|
||||
}
|
||||
|
||||
@EnableBinding(Processor.class)
|
||||
@EnableAutoConfiguration
|
||||
public static class TestInputOutputArgsWithFluxSenderAndFailure {
|
||||
@StreamListener
|
||||
public void receive(@Input(Processor.INPUT) Flux<Message<String>> input, @Output(Processor.OUTPUT) FluxSender output) {
|
||||
public void receive(@Input(Processor.INPUT) Flux<Message<String>> input,
|
||||
@Output(Processor.OUTPUT) FluxSender output) {
|
||||
output.send(input
|
||||
.map(m -> m.getPayload().toString())
|
||||
.map(m -> {
|
||||
@@ -109,7 +110,8 @@ public class StreamListenerReactiveInputOutputArgsWithSenderAndFailureTests {
|
||||
@EnableAutoConfiguration
|
||||
public static class TestInputOutputArgsWithObservableSenderAndFailure {
|
||||
@StreamListener
|
||||
public void receive(@Input(Processor.INPUT) Observable<Message<String>> input, @Output(Processor.OUTPUT) ObservableSender output) {
|
||||
public void receive(@Input(Processor.INPUT) Observable<Message<String>> input,
|
||||
@Output(Processor.OUTPUT) ObservableSender output) {
|
||||
output.send(input
|
||||
.map(m -> m.getPayload().toString())
|
||||
.map(m -> {
|
||||
|
||||
@@ -56,7 +56,19 @@ public class StreamListenerReactiveInputOutputArgsWithSenderTests {
|
||||
|
||||
@Parameterized.Parameters
|
||||
public static Collection InputConfigs() {
|
||||
return Arrays.asList(new Class[]{ReactorTestInputOutputArgsWithFluxSender.class, RxJava1TestInputOutputArgsWithObservableSender.class});
|
||||
return Arrays.asList(new Class[] { ReactorTestInputOutputArgsWithFluxSender.class,
|
||||
RxJava1TestInputOutputArgsWithObservableSender.class });
|
||||
}
|
||||
|
||||
private static void sendMessageAndValidate(ConfigurableApplicationContext context) throws InterruptedException {
|
||||
@SuppressWarnings("unchecked")
|
||||
Processor processor = context.getBean(Processor.class);
|
||||
String sentPayload = "hello " + UUID.randomUUID().toString();
|
||||
processor.input().send(MessageBuilder.withPayload(sentPayload).setHeader("contentType", "text/plain").build());
|
||||
MessageCollector messageCollector = context.getBean(MessageCollector.class);
|
||||
Message<?> result = messageCollector.forChannel(processor.output()).poll(1000, TimeUnit.MILLISECONDS);
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result.getPayload()).isEqualTo(sentPayload.toUpperCase());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -70,23 +82,12 @@ public class StreamListenerReactiveInputOutputArgsWithSenderTests {
|
||||
context.close();
|
||||
}
|
||||
|
||||
|
||||
private static void sendMessageAndValidate(ConfigurableApplicationContext context) throws InterruptedException {
|
||||
@SuppressWarnings("unchecked")
|
||||
Processor processor = context.getBean(Processor.class);
|
||||
String sentPayload = "hello " + UUID.randomUUID().toString();
|
||||
processor.input().send(MessageBuilder.withPayload(sentPayload).setHeader("contentType", "text/plain").build());
|
||||
MessageCollector messageCollector = context.getBean(MessageCollector.class);
|
||||
Message<?> result = messageCollector.forChannel(processor.output()).poll(1000, TimeUnit.MILLISECONDS);
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result.getPayload()).isEqualTo(sentPayload.toUpperCase());
|
||||
}
|
||||
|
||||
@EnableBinding(Processor.class)
|
||||
@EnableAutoConfiguration
|
||||
public static class ReactorTestInputOutputArgsWithFluxSender {
|
||||
@StreamListener
|
||||
public void receive(@Input(Processor.INPUT) Flux<Message<String>> input, @Output(Processor.OUTPUT) FluxSender output) {
|
||||
public void receive(@Input(Processor.INPUT) Flux<Message<String>> input,
|
||||
@Output(Processor.OUTPUT) FluxSender output) {
|
||||
output.send(input
|
||||
.map(m -> m.getPayload().toString().toUpperCase())
|
||||
.map(o -> MessageBuilder.withPayload(o).build()));
|
||||
@@ -97,8 +98,8 @@ public class StreamListenerReactiveInputOutputArgsWithSenderTests {
|
||||
@EnableAutoConfiguration
|
||||
public static class RxJava1TestInputOutputArgsWithObservableSender {
|
||||
@StreamListener
|
||||
public void receive(@Input(Processor.INPUT) Observable<Message<?>> input, @Output(Processor.OUTPUT)
|
||||
ObservableSender output) {
|
||||
public void receive(@Input(Processor.INPUT) Observable<Message<?>> input,
|
||||
@Output(Processor.OUTPUT) ObservableSender output) {
|
||||
output.send(input
|
||||
.map(m -> m.getPayload().toString().toUpperCase())
|
||||
.map(o -> MessageBuilder.withPayload(o).build()));
|
||||
|
||||
@@ -49,16 +49,6 @@ public class StreamListenerReactiveMethodTests {
|
||||
}
|
||||
}
|
||||
|
||||
@EnableBinding(Processor.class)
|
||||
@EnableAutoConfiguration
|
||||
public static class ReactorTestInputOutputArgs {
|
||||
|
||||
@StreamListener(Processor.INPUT)
|
||||
public void receive(Flux<String> input, @Output(Processor.OUTPUT) FluxSender output) {
|
||||
output.send(input.map(m -> m.toUpperCase()));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRxJava1InvalidInputValueWithOutputMethodParameters() {
|
||||
try {
|
||||
@@ -70,16 +60,6 @@ public class StreamListenerReactiveMethodTests {
|
||||
}
|
||||
}
|
||||
|
||||
@EnableBinding(Processor.class)
|
||||
@EnableAutoConfiguration
|
||||
public static class RxJava1TestInputOutputArgs {
|
||||
|
||||
@StreamListener(Processor.INPUT)
|
||||
public void receive(Observable<String> input, @Output(Processor.OUTPUT) ObservableSender output) {
|
||||
output.send(input.map(m -> m.toUpperCase()));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMethodReturnTypeWithNoOutboundSpecified() {
|
||||
try {
|
||||
@@ -91,6 +71,26 @@ public class StreamListenerReactiveMethodTests {
|
||||
}
|
||||
}
|
||||
|
||||
@EnableBinding(Processor.class)
|
||||
@EnableAutoConfiguration
|
||||
public static class ReactorTestInputOutputArgs {
|
||||
|
||||
@StreamListener(Processor.INPUT)
|
||||
public void receive(Flux<String> input, @Output(Processor.OUTPUT) FluxSender output) {
|
||||
output.send(input.map(m -> m.toUpperCase()));
|
||||
}
|
||||
}
|
||||
|
||||
@EnableBinding(Processor.class)
|
||||
@EnableAutoConfiguration
|
||||
public static class RxJava1TestInputOutputArgs {
|
||||
|
||||
@StreamListener(Processor.INPUT)
|
||||
public void receive(Observable<String> input, @Output(Processor.OUTPUT) ObservableSender output) {
|
||||
output.send(input.map(m -> m.toUpperCase()));
|
||||
}
|
||||
}
|
||||
|
||||
@EnableBinding(Processor.class)
|
||||
@EnableAutoConfiguration
|
||||
public static class ReactorTestReturn5 {
|
||||
|
||||
@@ -57,17 +57,10 @@ public class StreamListenerReactiveMethodWithReturnTypeTests {
|
||||
|
||||
@Parameterized.Parameters
|
||||
public static Collection InputConfigs() {
|
||||
return Arrays.asList(new Class[]{ReactorTestReturn1.class, ReactorTestReturn2.class, ReactorTestReturn3.class, ReactorTestReturn4.class,
|
||||
RxJava1TestReturn1.class, RxJava1TestReturn2.class, RxJava1TestReturn3.class, RxJava1TestReturn4.class});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReturn() throws Exception {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(this.configClass, "--server.port=0");
|
||||
sendMessageAndValidate(context);
|
||||
sendMessageAndValidate(context);
|
||||
sendMessageAndValidate(context);
|
||||
context.close();
|
||||
return Arrays.asList(new Class[] { ReactorTestReturn1.class, ReactorTestReturn2.class, ReactorTestReturn3.class,
|
||||
ReactorTestReturn4.class,
|
||||
RxJava1TestReturn1.class, RxJava1TestReturn2.class, RxJava1TestReturn3.class,
|
||||
RxJava1TestReturn4.class });
|
||||
}
|
||||
|
||||
private static void sendMessageAndValidate(ConfigurableApplicationContext context) throws InterruptedException {
|
||||
@@ -81,14 +74,21 @@ public class StreamListenerReactiveMethodWithReturnTypeTests {
|
||||
assertThat(result.getPayload()).isEqualTo(sentPayload.toUpperCase());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReturn() throws Exception {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(this.configClass, "--server.port=0");
|
||||
sendMessageAndValidate(context);
|
||||
sendMessageAndValidate(context);
|
||||
sendMessageAndValidate(context);
|
||||
context.close();
|
||||
}
|
||||
|
||||
@EnableBinding(Processor.class)
|
||||
@EnableAutoConfiguration
|
||||
public static class ReactorTestReturn1 {
|
||||
|
||||
@StreamListener
|
||||
public
|
||||
@Output(Processor.OUTPUT)
|
||||
Flux<String> receive(@Input(Processor.INPUT) Flux<String> input) {
|
||||
public @Output(Processor.OUTPUT) Flux<String> receive(@Input(Processor.INPUT) Flux<String> input) {
|
||||
return input.map(m -> m.toUpperCase());
|
||||
}
|
||||
}
|
||||
@@ -131,9 +131,7 @@ public class StreamListenerReactiveMethodWithReturnTypeTests {
|
||||
public static class RxJava1TestReturn1 {
|
||||
|
||||
@StreamListener
|
||||
public
|
||||
@Output(Processor.OUTPUT)
|
||||
Observable<String> receive(@Input(Processor.INPUT) Observable<String> input) {
|
||||
public @Output(Processor.OUTPUT) Observable<String> receive(@Input(Processor.INPUT) Observable<String> input) {
|
||||
return input.map(m -> m.toUpperCase());
|
||||
}
|
||||
}
|
||||
@@ -143,9 +141,7 @@ public class StreamListenerReactiveMethodWithReturnTypeTests {
|
||||
public static class RxJava1TestReturn2 {
|
||||
|
||||
@StreamListener(Processor.INPUT)
|
||||
public
|
||||
@Output(Processor.OUTPUT)
|
||||
Observable<String> receive(Observable<String> input) {
|
||||
public @Output(Processor.OUTPUT) Observable<String> receive(Observable<String> input) {
|
||||
return input.map(m -> m.toUpperCase());
|
||||
}
|
||||
}
|
||||
@@ -155,9 +151,7 @@ public class StreamListenerReactiveMethodWithReturnTypeTests {
|
||||
public static class RxJava1TestReturn3 {
|
||||
|
||||
@StreamListener(Processor.INPUT)
|
||||
public
|
||||
@SendTo(Processor.OUTPUT)
|
||||
Observable<String> receive(Observable<String> input) {
|
||||
public @SendTo(Processor.OUTPUT) Observable<String> receive(Observable<String> input) {
|
||||
return input.map(m -> m.toUpperCase());
|
||||
}
|
||||
}
|
||||
@@ -167,9 +161,7 @@ public class StreamListenerReactiveMethodWithReturnTypeTests {
|
||||
public static class RxJava1TestReturn4 {
|
||||
|
||||
@StreamListener
|
||||
public
|
||||
@SendTo(Processor.OUTPUT)
|
||||
Observable<String> receive(@Input(Processor.INPUT) Observable<String> input) {
|
||||
public @SendTo(Processor.OUTPUT) Observable<String> receive(@Input(Processor.INPUT) Observable<String> input) {
|
||||
return input.map(m -> m.toUpperCase());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,20 +57,11 @@ public class StreamListenerReactiveReturnWithFailureTests {
|
||||
|
||||
@Parameterized.Parameters
|
||||
public static Collection InputConfigs() {
|
||||
return Arrays.asList(new Class[] {ReactorTestReturnWithFailure1.class, ReactorTestReturnWithFailure2.class,
|
||||
ReactorTestReturnWithFailure3.class, ReactorTestReturnWithFailure4.class, RxJava1TestReturnWithFailure1.class,
|
||||
RxJava1TestReturnWithFailure2.class, RxJava1TestReturnWithFailure3.class, RxJava1TestReturnWithFailure4.class});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReturnWithFailure() throws Exception {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(this.configClass, "--server.port=0");
|
||||
sendMessageAndValidate(context);
|
||||
sendFailingMessage(context);
|
||||
sendMessageAndValidate(context);
|
||||
sendFailingMessage(context);
|
||||
sendMessageAndValidate(context);
|
||||
context.close();
|
||||
return Arrays.asList(new Class[] { ReactorTestReturnWithFailure1.class, ReactorTestReturnWithFailure2.class,
|
||||
ReactorTestReturnWithFailure3.class, ReactorTestReturnWithFailure4.class,
|
||||
RxJava1TestReturnWithFailure1.class,
|
||||
RxJava1TestReturnWithFailure2.class, RxJava1TestReturnWithFailure3.class,
|
||||
RxJava1TestReturnWithFailure4.class });
|
||||
}
|
||||
|
||||
private static void sendMessageAndValidate(ConfigurableApplicationContext context) throws InterruptedException {
|
||||
@@ -90,14 +81,23 @@ public class StreamListenerReactiveReturnWithFailureTests {
|
||||
processor.input().send(MessageBuilder.withPayload("fail").setHeader("contentType", "text/plain").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReturnWithFailure() throws Exception {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(this.configClass, "--server.port=0");
|
||||
sendMessageAndValidate(context);
|
||||
sendFailingMessage(context);
|
||||
sendMessageAndValidate(context);
|
||||
sendFailingMessage(context);
|
||||
sendMessageAndValidate(context);
|
||||
context.close();
|
||||
}
|
||||
|
||||
@EnableBinding(Processor.class)
|
||||
@EnableAutoConfiguration
|
||||
public static class ReactorTestReturnWithFailure1 {
|
||||
|
||||
@StreamListener
|
||||
public
|
||||
@Output(Processor.OUTPUT)
|
||||
Flux<String> receive(@Input(Processor.INPUT) Flux<String> input) {
|
||||
public @Output(Processor.OUTPUT) Flux<String> receive(@Input(Processor.INPUT) Flux<String> input) {
|
||||
return input.map(m -> {
|
||||
if (!m.equals("fail")) {
|
||||
return m.toUpperCase();
|
||||
@@ -114,9 +114,7 @@ public class StreamListenerReactiveReturnWithFailureTests {
|
||||
public static class ReactorTestReturnWithFailure2 {
|
||||
|
||||
@StreamListener(Processor.INPUT)
|
||||
public
|
||||
@Output(Processor.OUTPUT)
|
||||
Flux<String> receive(Flux<String> input) {
|
||||
public @Output(Processor.OUTPUT) Flux<String> receive(Flux<String> input) {
|
||||
return input.map(m -> {
|
||||
if (!m.equals("fail")) {
|
||||
return m.toUpperCase();
|
||||
@@ -133,9 +131,7 @@ public class StreamListenerReactiveReturnWithFailureTests {
|
||||
public static class ReactorTestReturnWithFailure3 {
|
||||
|
||||
@StreamListener(Processor.INPUT)
|
||||
public
|
||||
@SendTo(Processor.OUTPUT)
|
||||
Flux<String> receive(Flux<String> input) {
|
||||
public @SendTo(Processor.OUTPUT) Flux<String> receive(Flux<String> input) {
|
||||
return input.map(m -> {
|
||||
if (!m.equals("fail")) {
|
||||
return m.toUpperCase();
|
||||
@@ -152,9 +148,7 @@ public class StreamListenerReactiveReturnWithFailureTests {
|
||||
public static class ReactorTestReturnWithFailure4 {
|
||||
|
||||
@StreamListener
|
||||
public
|
||||
@SendTo(Processor.OUTPUT)
|
||||
Flux<String> receive(@Input(Processor.INPUT) Flux<String> input) {
|
||||
public @SendTo(Processor.OUTPUT) Flux<String> receive(@Input(Processor.INPUT) Flux<String> input) {
|
||||
return input.map(m -> {
|
||||
if (!m.equals("fail")) {
|
||||
return m.toUpperCase();
|
||||
@@ -171,9 +165,7 @@ public class StreamListenerReactiveReturnWithFailureTests {
|
||||
public static class RxJava1TestReturnWithFailure1 {
|
||||
|
||||
@StreamListener
|
||||
public
|
||||
@Output(Processor.OUTPUT)
|
||||
Observable<String> receive(@Input(Processor.INPUT) Observable<String> input) {
|
||||
public @Output(Processor.OUTPUT) Observable<String> receive(@Input(Processor.INPUT) Observable<String> input) {
|
||||
return input.map(m -> {
|
||||
if (!m.equals("fail")) {
|
||||
return m.toUpperCase();
|
||||
@@ -190,9 +182,7 @@ public class StreamListenerReactiveReturnWithFailureTests {
|
||||
public static class RxJava1TestReturnWithFailure2 {
|
||||
|
||||
@StreamListener
|
||||
public
|
||||
@SendTo(Processor.OUTPUT)
|
||||
Observable<String> receive(@Input(Processor.INPUT) Observable<String> input) {
|
||||
public @SendTo(Processor.OUTPUT) Observable<String> receive(@Input(Processor.INPUT) Observable<String> input) {
|
||||
return input.map(m -> {
|
||||
if (!m.equals("fail")) {
|
||||
return m.toUpperCase();
|
||||
@@ -209,9 +199,7 @@ public class StreamListenerReactiveReturnWithFailureTests {
|
||||
public static class RxJava1TestReturnWithFailure3 {
|
||||
|
||||
@StreamListener(Processor.INPUT)
|
||||
public
|
||||
@SendTo(Processor.OUTPUT)
|
||||
Observable<String> receive(Observable<String> input) {
|
||||
public @SendTo(Processor.OUTPUT) Observable<String> receive(Observable<String> input) {
|
||||
return input.map(m -> {
|
||||
if (!m.equals("fail")) {
|
||||
return m.toUpperCase();
|
||||
@@ -228,9 +216,7 @@ public class StreamListenerReactiveReturnWithFailureTests {
|
||||
public static class RxJava1TestReturnWithFailure4 {
|
||||
|
||||
@StreamListener(Processor.INPUT)
|
||||
public
|
||||
@Output(Processor.OUTPUT)
|
||||
Observable<String> receive(Observable<String> input) {
|
||||
public @Output(Processor.OUTPUT) Observable<String> receive(Observable<String> input) {
|
||||
return input.map(m -> {
|
||||
if (!m.equals("fail")) {
|
||||
return m.toUpperCase();
|
||||
|
||||
@@ -57,16 +57,11 @@ public class StreamListenerReactiveReturnWithMessageTests {
|
||||
|
||||
@Parameterized.Parameters
|
||||
public static Collection InputConfigs() {
|
||||
return Arrays.asList(new Class[] {ReactorTestReturnWithMessage1.class, ReactorTestReturnWithMessage2.class,
|
||||
ReactorTestReturnWithMessage3.class, ReactorTestReturnWithMessage4.class, RxJava1TestReturnWithMessage1.class,
|
||||
RxJava1TestReturnWithMessage2.class, RxJava1TestReturnWithMessage3.class, RxJava1TestReturnWithMessage4.class});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReturnWithMessage() throws Exception {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(this.configClass, "--server.port=0");
|
||||
sendMessageAndValidate(context);
|
||||
context.close();
|
||||
return Arrays.asList(new Class[] { ReactorTestReturnWithMessage1.class, ReactorTestReturnWithMessage2.class,
|
||||
ReactorTestReturnWithMessage3.class, ReactorTestReturnWithMessage4.class,
|
||||
RxJava1TestReturnWithMessage1.class,
|
||||
RxJava1TestReturnWithMessage2.class, RxJava1TestReturnWithMessage3.class,
|
||||
RxJava1TestReturnWithMessage4.class });
|
||||
}
|
||||
|
||||
private static void sendMessageAndValidate(ConfigurableApplicationContext context) throws InterruptedException {
|
||||
@@ -80,14 +75,19 @@ public class StreamListenerReactiveReturnWithMessageTests {
|
||||
assertThat(result.getPayload()).isEqualTo(sentPayload.toUpperCase());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReturnWithMessage() throws Exception {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(this.configClass, "--server.port=0");
|
||||
sendMessageAndValidate(context);
|
||||
context.close();
|
||||
}
|
||||
|
||||
@EnableBinding(Processor.class)
|
||||
@EnableAutoConfiguration
|
||||
public static class ReactorTestReturnWithMessage1 {
|
||||
|
||||
@StreamListener
|
||||
public
|
||||
@Output(Processor.OUTPUT)
|
||||
Flux<String> receive(@Input(Processor.INPUT) Flux<Message<String>> input) {
|
||||
public @Output(Processor.OUTPUT) Flux<String> receive(@Input(Processor.INPUT) Flux<Message<String>> input) {
|
||||
return input.map(m -> m.getPayload().toUpperCase());
|
||||
}
|
||||
}
|
||||
@@ -97,9 +97,7 @@ public class StreamListenerReactiveReturnWithMessageTests {
|
||||
public static class ReactorTestReturnWithMessage2 {
|
||||
|
||||
@StreamListener(Processor.INPUT)
|
||||
public
|
||||
@Output(Processor.OUTPUT)
|
||||
Flux<String> receive(Flux<Message<String>> input) {
|
||||
public @Output(Processor.OUTPUT) Flux<String> receive(Flux<Message<String>> input) {
|
||||
return input.map(m -> m.getPayload().toUpperCase());
|
||||
}
|
||||
}
|
||||
@@ -109,22 +107,17 @@ public class StreamListenerReactiveReturnWithMessageTests {
|
||||
public static class ReactorTestReturnWithMessage3 {
|
||||
|
||||
@StreamListener(Processor.INPUT)
|
||||
public
|
||||
@SendTo(Processor.OUTPUT)
|
||||
Flux<String> receive(Flux<Message<String>> input) {
|
||||
public @SendTo(Processor.OUTPUT) Flux<String> receive(Flux<Message<String>> input) {
|
||||
return input.map(m -> m.getPayload().toUpperCase());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@EnableBinding(Processor.class)
|
||||
@EnableAutoConfiguration
|
||||
public static class ReactorTestReturnWithMessage4 {
|
||||
|
||||
@StreamListener
|
||||
public
|
||||
@SendTo(Processor.OUTPUT)
|
||||
Flux<String> receive(@Input(Processor.INPUT) Flux<Message<String>> input) {
|
||||
public @SendTo(Processor.OUTPUT) Flux<String> receive(@Input(Processor.INPUT) Flux<Message<String>> input) {
|
||||
return input.map(m -> m.getPayload().toUpperCase());
|
||||
}
|
||||
}
|
||||
@@ -134,9 +127,8 @@ public class StreamListenerReactiveReturnWithMessageTests {
|
||||
public static class RxJava1TestReturnWithMessage1 {
|
||||
|
||||
@StreamListener
|
||||
public
|
||||
@Output(Processor.OUTPUT)
|
||||
Observable<String> receive(@Input(Processor.INPUT) Observable<Message<String>> input) {
|
||||
public @Output(Processor.OUTPUT) Observable<String> receive(
|
||||
@Input(Processor.INPUT) Observable<Message<String>> input) {
|
||||
return input.map(m -> m.getPayload().toUpperCase());
|
||||
}
|
||||
}
|
||||
@@ -146,9 +138,8 @@ public class StreamListenerReactiveReturnWithMessageTests {
|
||||
public static class RxJava1TestReturnWithMessage2 {
|
||||
|
||||
@StreamListener
|
||||
public
|
||||
@SendTo(Processor.OUTPUT)
|
||||
Observable<String> receive(@Input(Processor.INPUT) Observable<Message<String>> input) {
|
||||
public @SendTo(Processor.OUTPUT) Observable<String> receive(
|
||||
@Input(Processor.INPUT) Observable<Message<String>> input) {
|
||||
return input.map(m -> m.getPayload().toUpperCase());
|
||||
}
|
||||
}
|
||||
@@ -158,9 +149,7 @@ public class StreamListenerReactiveReturnWithMessageTests {
|
||||
public static class RxJava1TestReturnWithMessage3 {
|
||||
|
||||
@StreamListener(Processor.INPUT)
|
||||
public
|
||||
@Output(Processor.OUTPUT)
|
||||
Observable<String> receive(Observable<Message<String>> input) {
|
||||
public @Output(Processor.OUTPUT) Observable<String> receive(Observable<Message<String>> input) {
|
||||
return input.map(m -> m.getPayload().toUpperCase());
|
||||
}
|
||||
}
|
||||
@@ -170,9 +159,7 @@ public class StreamListenerReactiveReturnWithMessageTests {
|
||||
public static class RxJava1TestReturnWithMessage4 {
|
||||
|
||||
@StreamListener(Processor.INPUT)
|
||||
public
|
||||
@SendTo(Processor.OUTPUT)
|
||||
Observable<String> receive(Observable<Message<String>> input) {
|
||||
public @SendTo(Processor.OUTPUT) Observable<String> receive(Observable<Message<String>> input) {
|
||||
return input.map(m -> m.getPayload().toUpperCase());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,9 +56,9 @@ public class StreamListenerReactiveReturnWithPojoTests {
|
||||
|
||||
@Parameterized.Parameters
|
||||
public static Collection InputConfigs() {
|
||||
return Arrays.asList(new Class[] {ReactorTestReturnWithPojo1.class, ReactorTestReturnWithPojo2.class,
|
||||
return Arrays.asList(new Class[] { ReactorTestReturnWithPojo1.class, ReactorTestReturnWithPojo2.class,
|
||||
ReactorTestReturnWithPojo3.class, ReactorTestReturnWithPojo4.class, RxJava1TestReturnWithPojo1.class,
|
||||
RxJava1TestReturnWithPojo2.class, RxJava1TestReturnWithPojo3.class, RxJava1TestReturnWithPojo4.class});
|
||||
RxJava1TestReturnWithPojo2.class, RxJava1TestReturnWithPojo3.class, RxJava1TestReturnWithPojo4.class });
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -81,9 +81,7 @@ public class StreamListenerReactiveReturnWithPojoTests {
|
||||
public static class ReactorTestReturnWithPojo1 {
|
||||
|
||||
@StreamListener
|
||||
public
|
||||
@Output(Processor.OUTPUT)
|
||||
Flux<BarPojo> receive(@Input(Processor.INPUT) Flux<FooPojo> input) {
|
||||
public @Output(Processor.OUTPUT) Flux<BarPojo> receive(@Input(Processor.INPUT) Flux<FooPojo> input) {
|
||||
return input.map(m -> new BarPojo(m.getMessage()));
|
||||
}
|
||||
}
|
||||
@@ -93,9 +91,7 @@ public class StreamListenerReactiveReturnWithPojoTests {
|
||||
public static class ReactorTestReturnWithPojo2 {
|
||||
|
||||
@StreamListener(Processor.INPUT)
|
||||
public
|
||||
@Output(Processor.OUTPUT)
|
||||
Flux<BarPojo> receive(Flux<FooPojo> input) {
|
||||
public @Output(Processor.OUTPUT) Flux<BarPojo> receive(Flux<FooPojo> input) {
|
||||
return input.map(m -> new BarPojo(m.getMessage()));
|
||||
}
|
||||
}
|
||||
@@ -105,9 +101,7 @@ public class StreamListenerReactiveReturnWithPojoTests {
|
||||
public static class ReactorTestReturnWithPojo3 {
|
||||
|
||||
@StreamListener(Processor.INPUT)
|
||||
public
|
||||
@SendTo(Processor.OUTPUT)
|
||||
Flux<BarPojo> receive(Flux<FooPojo> input) {
|
||||
public @SendTo(Processor.OUTPUT) Flux<BarPojo> receive(Flux<FooPojo> input) {
|
||||
return input.map(m -> new BarPojo(m.getMessage()));
|
||||
}
|
||||
}
|
||||
@@ -117,9 +111,7 @@ public class StreamListenerReactiveReturnWithPojoTests {
|
||||
public static class ReactorTestReturnWithPojo4 {
|
||||
|
||||
@StreamListener
|
||||
public
|
||||
@SendTo(Processor.OUTPUT)
|
||||
Flux<BarPojo> receive(@Input(Processor.INPUT) Flux<FooPojo> input) {
|
||||
public @SendTo(Processor.OUTPUT) Flux<BarPojo> receive(@Input(Processor.INPUT) Flux<FooPojo> input) {
|
||||
return input.map(m -> new BarPojo(m.getMessage()));
|
||||
}
|
||||
}
|
||||
@@ -129,9 +121,8 @@ public class StreamListenerReactiveReturnWithPojoTests {
|
||||
public static class RxJava1TestReturnWithPojo1 {
|
||||
|
||||
@StreamListener
|
||||
public
|
||||
@Output(Processor.OUTPUT)
|
||||
Observable<BarPojo> receive(@Input(Processor.INPUT) Observable<FooPojo> input) {
|
||||
public @Output(Processor.OUTPUT) Observable<BarPojo> receive(
|
||||
@Input(Processor.INPUT) Observable<FooPojo> input) {
|
||||
return input.map(m -> new BarPojo(m.getMessage()));
|
||||
}
|
||||
}
|
||||
@@ -141,9 +132,8 @@ public class StreamListenerReactiveReturnWithPojoTests {
|
||||
public static class RxJava1TestReturnWithPojo2 {
|
||||
|
||||
@StreamListener
|
||||
public
|
||||
@SendTo(Processor.OUTPUT)
|
||||
Observable<BarPojo> receive(@Input(Processor.INPUT) Observable<FooPojo> input) {
|
||||
public @SendTo(Processor.OUTPUT) Observable<BarPojo> receive(
|
||||
@Input(Processor.INPUT) Observable<FooPojo> input) {
|
||||
return input.map(m -> new BarPojo(m.getMessage()));
|
||||
}
|
||||
}
|
||||
@@ -153,9 +143,7 @@ public class StreamListenerReactiveReturnWithPojoTests {
|
||||
public static class RxJava1TestReturnWithPojo3 {
|
||||
|
||||
@StreamListener(Processor.INPUT)
|
||||
public
|
||||
@Output(Processor.OUTPUT)
|
||||
Observable<BarPojo> receive(Observable<FooPojo> input) {
|
||||
public @Output(Processor.OUTPUT) Observable<BarPojo> receive(Observable<FooPojo> input) {
|
||||
return input.map(m -> new BarPojo(m.getMessage()));
|
||||
}
|
||||
}
|
||||
@@ -165,9 +153,7 @@ public class StreamListenerReactiveReturnWithPojoTests {
|
||||
public static class RxJava1TestReturnWithPojo4 {
|
||||
|
||||
@StreamListener(Processor.INPUT)
|
||||
public
|
||||
@SendTo(Processor.OUTPUT)
|
||||
Observable<BarPojo> receive(Observable<FooPojo> input) {
|
||||
public @SendTo(Processor.OUTPUT) Observable<BarPojo> receive(Observable<FooPojo> input) {
|
||||
return input.map(m -> new BarPojo(m.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,9 +45,21 @@ import static org.springframework.cloud.stream.binding.StreamListenerErrorMessag
|
||||
*/
|
||||
public class StreamListenerWildCardFluxInputOutputArgsWithMessageTests {
|
||||
|
||||
private static void sendMessageAndValidate(ConfigurableApplicationContext context) throws InterruptedException {
|
||||
@SuppressWarnings("unchecked")
|
||||
Processor processor = context.getBean(Processor.class);
|
||||
String sentPayload = "hello " + UUID.randomUUID().toString();
|
||||
processor.input().send(MessageBuilder.withPayload(sentPayload).setHeader("contentType", "text/plain").build());
|
||||
MessageCollector messageCollector = context.getBean(MessageCollector.class);
|
||||
Message<?> result = messageCollector.forChannel(processor.output()).poll(1000, TimeUnit.MILLISECONDS);
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result.getPayload()).isEqualTo(sentPayload.toUpperCase());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWildCardFluxInputOutputArgsWithMessage() throws Exception {
|
||||
ConfigurableApplicationContext context = SpringApplication.run(TestWildCardFluxInputOutputArgsWithMessage1.class, "--server.port=0");
|
||||
ConfigurableApplicationContext context = SpringApplication
|
||||
.run(TestWildCardFluxInputOutputArgsWithMessage1.class, "--server.port=0");
|
||||
sendMessageAndValidate(context);
|
||||
context.close();
|
||||
}
|
||||
@@ -74,17 +86,6 @@ public class StreamListenerWildCardFluxInputOutputArgsWithMessageTests {
|
||||
}
|
||||
}
|
||||
|
||||
private static void sendMessageAndValidate(ConfigurableApplicationContext context) throws InterruptedException {
|
||||
@SuppressWarnings("unchecked")
|
||||
Processor processor = context.getBean(Processor.class);
|
||||
String sentPayload = "hello " + UUID.randomUUID().toString();
|
||||
processor.input().send(MessageBuilder.withPayload(sentPayload).setHeader("contentType", "text/plain").build());
|
||||
MessageCollector messageCollector = context.getBean(MessageCollector.class);
|
||||
Message<?> result = messageCollector.forChannel(processor.output()).poll(1000, TimeUnit.MILLISECONDS);
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result.getPayload()).isEqualTo(sentPayload.toUpperCase());
|
||||
}
|
||||
|
||||
@EnableBinding(Processor.class)
|
||||
@EnableAutoConfiguration
|
||||
public static class TestWildCardFluxInputOutputArgsWithMessage1 {
|
||||
|
||||
@@ -28,11 +28,13 @@ import org.springframework.cloud.stream.messaging.Processor;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* Annotation that identifies the class as RxJava processor module. The class that has {@link EnableRxJavaProcessor}
|
||||
* annotated is expected to provide a bean that implements {@link RxJavaProcessor}.
|
||||
* Annotation that identifies the class as RxJava processor module. The class that has
|
||||
* {@link EnableRxJavaProcessor} annotated is expected to provide a bean that implements
|
||||
* {@link RxJavaProcessor}.
|
||||
*
|
||||
* @author Ilayaperumal Gopinathan
|
||||
* @deprecated in favor of {@link org.springframework.cloud.stream.annotation.StreamListener} with reactive types
|
||||
* @deprecated in favor of
|
||||
* {@link org.springframework.cloud.stream.annotation.StreamListener} with reactive types
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
||||
@@ -23,7 +23,8 @@ import rx.Observable;
|
||||
*
|
||||
* @author Mark Pollack
|
||||
* @author Ilayaperumal Gopinathan
|
||||
* @deprecated in favor of {@link org.springframework.cloud.stream.annotation.StreamListener} with reactive types
|
||||
* @deprecated in favor of
|
||||
* {@link org.springframework.cloud.stream.annotation.StreamListener} with reactive types
|
||||
*/
|
||||
@Deprecated
|
||||
public interface RxJavaProcessor<I, O> {
|
||||
|
||||
@@ -34,34 +34,39 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Adapts the item at a time delivery of a {@link org.springframework.messaging.MessageHandler}
|
||||
* by delegating processing to a {@link Observable}.
|
||||
* Adapts the item at a time delivery of a
|
||||
* {@link org.springframework.messaging.MessageHandler} by delegating processing to a
|
||||
* {@link Observable}.
|
||||
* <p/>
|
||||
* The outputStream of the processor is used to create a message and send it to the output channel. If the
|
||||
* input channel and output channel are connected to the {@link org.springframework.cloud.stream.binder.Binder},
|
||||
* then data delivered to the input stream via a call to onNext is invoked on the dispatcher thread of the binder
|
||||
* and sending a message to the output channel will involve IO operations on the binder.
|
||||
* The outputStream of the processor is used to create a message and send it to the output
|
||||
* channel. If the input channel and output channel are connected to the
|
||||
* {@link org.springframework.cloud.stream.binder.Binder}, then data delivered to the
|
||||
* input stream via a call to onNext is invoked on the dispatcher thread of the binder and
|
||||
* sending a message to the output channel will involve IO operations on the binder.
|
||||
* <p/>
|
||||
* The implementation uses a SerializedSubject. This has the advantage that the state of the Observabale
|
||||
* can be shared across all the incoming dispatcher threads that are invoking onNext. It has the disadvantage
|
||||
* that processing and sending to the output channel will execute serially on one of the dispatcher threads.
|
||||
* The implementation uses a SerializedSubject. This has the advantage that the state of
|
||||
* the Observabale can be shared across all the incoming dispatcher threads that are
|
||||
* invoking onNext. It has the disadvantage that processing and sending to the output
|
||||
* channel will execute serially on one of the dispatcher threads.
|
||||
* <p/>
|
||||
* The use of this handler makes for a very natural first experience when processing data. For example given
|
||||
* the stream <code></code>http | rxjava-processor | log</code> where the <code>rxjava-processor</code> does a
|
||||
* <code>buffer(5)</code> and then produces a single value. Sending 10 messages to the http source will
|
||||
* result in 2 messages in the log, no matter how many dispatcher threads are used.
|
||||
* The use of this handler makes for a very natural first experience when processing data.
|
||||
* For example given the stream <code></code>http | rxjava-processor | log</code> where
|
||||
* the <code>rxjava-processor</code> does a <code>buffer(5)</code> and then produces a
|
||||
* single value. Sending 10 messages to the http source will result in 2 messages in the
|
||||
* log, no matter how many dispatcher threads are used.
|
||||
* <p/>
|
||||
* You can modify what thread the outputStream subscriber, which does the send to the output channel,
|
||||
* will use by explicitly calling <code>observeOn</code> before returning the outputStream from your processor.
|
||||
* You can modify what thread the outputStream subscriber, which does the send to the
|
||||
* output channel, will use by explicitly calling <code>observeOn</code> before returning
|
||||
* the outputStream from your processor.
|
||||
* <p/>
|
||||
|
||||
*
|
||||
* All error handling is the responsibility of the processor implementation.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
* @author Ilayaperumal Gopinathan
|
||||
* @author Marius Bogoevici
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@Deprecated
|
||||
public class SubjectMessageHandler extends AbstractMessageProducingHandler implements SmartLifecycle {
|
||||
|
||||
@@ -76,7 +81,7 @@ public class SubjectMessageHandler extends AbstractMessageProducingHandler imple
|
||||
|
||||
private volatile boolean running;
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public SubjectMessageHandler(RxJavaProcessor processor) {
|
||||
Assert.notNull(processor, "RxJava processor must not be null.");
|
||||
this.processor = processor;
|
||||
|
||||
@@ -48,17 +48,18 @@ public class SchemaServerConfiguration {
|
||||
return new BeanFactoryPostProcessor() {
|
||||
|
||||
@Override
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws
|
||||
BeansException {
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
||||
if (beanFactory instanceof BeanDefinitionRegistry) {
|
||||
EntityScanPackages.register((BeanDefinitionRegistry) beanFactory, Collections.singletonList(Schema.class.getPackage().getName()));
|
||||
EntityScanPackages.register((BeanDefinitionRegistry) beanFactory,
|
||||
Collections.singletonList(Schema.class.getPackage().getName()));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ServerController serverController(SchemaRepository repository, SchemaServerProperties schemeServerProperties) {
|
||||
public ServerController serverController(SchemaRepository repository,
|
||||
SchemaServerProperties schemeServerProperties) {
|
||||
return new ServerController(repository, schemaValidators(), schemeServerProperties);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package org.springframework.cloud.stream.schema.server.config;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package org.springframework.cloud.stream.schema.server.controllers;
|
||||
|
||||
import java.util.List;
|
||||
@@ -134,10 +133,12 @@ public class ServerController {
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET, produces = "application/json", path = "/{subject}/{format}")
|
||||
public ResponseEntity<List<Schema>> findBySubjectAndVersion(@PathVariable("subject") String subject, @PathVariable("format") String format) {
|
||||
public ResponseEntity<List<Schema>> findBySubjectAndVersion(@PathVariable("subject") String subject,
|
||||
@PathVariable("format") String format) {
|
||||
List<Schema> schemas = repository.findBySubjectAndFormatOrderByVersion(subject, format);
|
||||
if (schemas == null || schemas.size() == 0) {
|
||||
throw new SchemaNotFoundException(String.format("No schemas found for subject %s and format %s", subject, format));
|
||||
throw new SchemaNotFoundException(
|
||||
String.format("No schemas found for subject %s and format %s", subject, format));
|
||||
}
|
||||
return new ResponseEntity<List<Schema>>(schemas, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@@ -14,12 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package org.springframework.cloud.stream.schema.server.model;
|
||||
|
||||
/**
|
||||
* @author Vinicius Carvalho
|
||||
*/
|
||||
public enum Compatibility {
|
||||
BACKWARD, FORWARD, FULL, INCOMPATIBLE;
|
||||
BACKWARD,
|
||||
FORWARD,
|
||||
FULL,
|
||||
INCOMPATIBLE;
|
||||
}
|
||||
|
||||
@@ -207,7 +207,8 @@ public class SchemaRegistryServerAvroTests {
|
||||
ResponseEntity<Schema> response1 = client.postForEntity("http://localhost:8990/",
|
||||
schema1, Schema.class);
|
||||
Assert.assertTrue(response1.getStatusCode().is2xxSuccessful());
|
||||
Assert.assertEquals(HttpStatus.OK, client.getForEntity("http://localhost:8990/test/avro/v1", Schema.class).getStatusCode());
|
||||
Assert.assertEquals(HttpStatus.OK,
|
||||
client.getForEntity("http://localhost:8990/test/avro/v1", Schema.class).getStatusCode());
|
||||
client.getForEntity("http://localhost:8990/test/avro/1", Schema.class);
|
||||
Schema schema2 = new Schema();
|
||||
schema2.setFormat("avro");
|
||||
@@ -216,7 +217,8 @@ public class SchemaRegistryServerAvroTests {
|
||||
ResponseEntity<Schema> response2 = client.postForEntity("http://localhost:8990/",
|
||||
schema2, Schema.class);
|
||||
Assert.assertTrue(response2.getStatusCode().is2xxSuccessful());
|
||||
Assert.assertEquals(HttpStatus.OK, client.getForEntity("http://localhost:8990/test/avro/v2", Schema.class).getStatusCode());
|
||||
Assert.assertEquals(HttpStatus.OK,
|
||||
client.getForEntity("http://localhost:8990/test/avro/v2", Schema.class).getStatusCode());
|
||||
schemaServerProperties.setAllowSchemaDeletion(true);
|
||||
client.delete("http://localhost:8990/test");
|
||||
ResponseEntity<Schema> response4 = client
|
||||
@@ -236,7 +238,8 @@ public class SchemaRegistryServerAvroTests {
|
||||
ResponseEntity<Schema> response1 = client.postForEntity("http://localhost:8990/",
|
||||
schema, Schema.class);
|
||||
Assert.assertTrue(response1.getStatusCode().is2xxSuccessful());
|
||||
ResponseEntity<Object> deleteBySubjectFormatVersion = client.exchange("http://localhost:8990/test/avro/v1", HttpMethod.DELETE,
|
||||
ResponseEntity<Object> deleteBySubjectFormatVersion = client.exchange("http://localhost:8990/test/avro/v1",
|
||||
HttpMethod.DELETE,
|
||||
null, Object.class);
|
||||
assertThat(deleteBySubjectFormatVersion.getStatusCode()).isEqualTo(HttpStatus.METHOD_NOT_ALLOWED);
|
||||
ResponseEntity<Object> deleteBySubject = client.exchange("http://localhost:8990/test", HttpMethod.DELETE,
|
||||
@@ -266,8 +269,9 @@ public class SchemaRegistryServerAvroTests {
|
||||
v2, Schema.class);
|
||||
Assert.assertTrue(response2.getStatusCode().is2xxSuccessful());
|
||||
|
||||
ResponseEntity<List<Schema>> schemaResponse = client.exchange("http://localhost:8990/test/avro", HttpMethod.GET, null, new ParameterizedTypeReference<List<Schema>>() {
|
||||
});
|
||||
ResponseEntity<List<Schema>> schemaResponse = client.exchange("http://localhost:8990/test/avro", HttpMethod.GET,
|
||||
null, new ParameterizedTypeReference<List<Schema>>() {
|
||||
});
|
||||
|
||||
Assert.assertTrue(schemaResponse.getStatusCode().is2xxSuccessful());
|
||||
Assert.assertEquals(2, schemaResponse.getBody().size());
|
||||
|
||||
@@ -30,7 +30,8 @@ public class EntityScanningTests {
|
||||
|
||||
@Test
|
||||
public void testApplicationWithEmbeddedSchemaRegistryServerOutsideOfRootPackage() throws Exception {
|
||||
final ConfigurableApplicationContext context = SpringApplication.run(CustomApplicationEmbeddingSchemaServer.class, "--server.port=0");
|
||||
final ConfigurableApplicationContext context = SpringApplication
|
||||
.run(CustomApplicationEmbeddingSchemaServer.class, "--server.port=0");
|
||||
context.close();
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,8 @@ public class EntityScanningTestsWithEntityScan {
|
||||
|
||||
@Test
|
||||
public void testApplicationWithEmbeddedSchemaRegistryServerOutsideOfRootPackage() throws Exception {
|
||||
final ConfigurableApplicationContext context = SpringApplication.run(CustomApplicationEmbeddingSchemaServer.class, "--server.port=0");
|
||||
final ConfigurableApplicationContext context = SpringApplication
|
||||
.run(CustomApplicationEmbeddingSchemaServer.class, "--server.port=0");
|
||||
context.close();
|
||||
}
|
||||
|
||||
|
||||
@@ -21,13 +21,14 @@ import org.apache.avro.Schema;
|
||||
/**
|
||||
* Stores a {@link Schema} together with its String representation.
|
||||
*
|
||||
* Helps to avoid unnecessary parsing of schema textual representation,
|
||||
* as well as calls to {@link org.apache.avro.Schema} toString method which is very
|
||||
* expensive due the utilization of {@link com.fasterxml.jackson.databind.ObjectMapper}
|
||||
* to output a JSON representation of the schema.
|
||||
* Helps to avoid unnecessary parsing of schema textual representation, as well as calls
|
||||
* to {@link org.apache.avro.Schema} toString method which is very expensive due the
|
||||
* utilization of {@link com.fasterxml.jackson.databind.ObjectMapper} to output a JSON
|
||||
* representation of the schema.
|
||||
*
|
||||
* Once a schema is found for any Class, be it a POJO or a {@link org.apache.avro.generic.GenericContainer},
|
||||
* both textual representation as well as the {@link org.apache.avro.Schema} will be stored within this class.
|
||||
* Once a schema is found for any Class, be it a POJO or a
|
||||
* {@link org.apache.avro.generic.GenericContainer}, both textual representation as well
|
||||
* as the {@link org.apache.avro.Schema} will be stored within this class.
|
||||
*
|
||||
* @author Vinicius Carvalho
|
||||
*
|
||||
@@ -40,7 +41,7 @@ public class ParsedSchema {
|
||||
|
||||
private SchemaRegistrationResponse registration;
|
||||
|
||||
public ParsedSchema(Schema schema){
|
||||
public ParsedSchema(Schema schema) {
|
||||
this.schema = schema;
|
||||
this.representation = schema.toString();
|
||||
}
|
||||
|
||||
@@ -45,12 +45,12 @@ import org.springframework.messaging.converter.MessageConversionException;
|
||||
import org.springframework.util.MimeType;
|
||||
|
||||
/**
|
||||
* Base class for Apache Avro {@link org.springframework.messaging.converter.MessageConverter} implementations.
|
||||
* Base class for Apache Avro
|
||||
* {@link org.springframework.messaging.converter.MessageConverter} implementations.
|
||||
* @author Marius Bogoevici
|
||||
*/
|
||||
public abstract class AbstractAvroMessageConverter extends AbstractMessageConverter {
|
||||
|
||||
|
||||
protected AbstractAvroMessageConverter(MimeType supportedMimeType) {
|
||||
super(supportedMimeType);
|
||||
}
|
||||
|
||||
@@ -38,19 +38,17 @@ import org.springframework.util.ObjectUtils;
|
||||
@ConditionalOnClass(name = "org.apache.avro.Schema")
|
||||
@ConditionalOnProperty(value = "spring.cloud.stream.schemaRegistryClient.enabled", matchIfMissing = true)
|
||||
@ConditionalOnBean(type = "org.springframework.cloud.stream.schema.client.SchemaRegistryClient")
|
||||
@EnableConfigurationProperties({AvroMessageConverterProperties.class})
|
||||
@EnableConfigurationProperties({ AvroMessageConverterProperties.class })
|
||||
public class AvroMessageConverterAutoConfiguration {
|
||||
|
||||
@Autowired
|
||||
private AvroMessageConverterProperties avroMessageConverterProperties;
|
||||
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(AvroSchemaRegistryClientMessageConverter.class)
|
||||
public AvroSchemaRegistryClientMessageConverter avroSchemaMessageConverter(
|
||||
SchemaRegistryClient schemaRegistryClient) {
|
||||
AvroSchemaRegistryClientMessageConverter
|
||||
avroSchemaRegistryClientMessageConverter = new AvroSchemaRegistryClientMessageConverter(
|
||||
AvroSchemaRegistryClientMessageConverter avroSchemaRegistryClientMessageConverter = new AvroSchemaRegistryClientMessageConverter(
|
||||
schemaRegistryClient);
|
||||
avroSchemaRegistryClientMessageConverter.setDynamicSchemaGenerationEnabled(
|
||||
this.avroMessageConverterProperties.isDynamicSchemaGenerationEnabled());
|
||||
@@ -70,7 +68,7 @@ public class AvroMessageConverterAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public CacheManager cacheManager(){
|
||||
public CacheManager cacheManager() {
|
||||
return new ConcurrentMapCacheManager();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,14 +27,11 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.MimeType;
|
||||
|
||||
/**
|
||||
* A {@link org.springframework.messaging.converter.MessageConverter}
|
||||
* using Apache Avro.
|
||||
* The schema for serializing and deserializing will be automatically inferred
|
||||
* from the class for {@link org.apache.avro.specific.SpecificRecord} and regular
|
||||
* classes, unless a specific schema is set, case in which that schema will be used
|
||||
* instead.
|
||||
* For converting to {@link org.apache.avro.generic.GenericRecord} targets,
|
||||
* a schema must be set.s
|
||||
* A {@link org.springframework.messaging.converter.MessageConverter} using Apache Avro.
|
||||
* The schema for serializing and deserializing will be automatically inferred from the
|
||||
* class for {@link org.apache.avro.specific.SpecificRecord} and regular classes, unless a
|
||||
* specific schema is set, case in which that schema will be used instead. For converting
|
||||
* to {@link org.apache.avro.generic.GenericRecord} targets, a schema must be set.s
|
||||
* @author Marius Bogoevici
|
||||
*/
|
||||
|
||||
@@ -43,24 +40,24 @@ public class AvroSchemaMessageConverter extends AbstractAvroMessageConverter {
|
||||
private Schema schema;
|
||||
|
||||
/**
|
||||
* Create a {@link AvroSchemaMessageConverter}.
|
||||
* Uses the default {@link MimeType} of {@code "application/avro"}.
|
||||
* Create a {@link AvroSchemaMessageConverter}. Uses the default {@link MimeType} of
|
||||
* {@code "application/avro"}.
|
||||
*/
|
||||
public AvroSchemaMessageConverter() {
|
||||
super(new MimeType("application", "avro"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link AvroSchemaMessageConverter}.
|
||||
* The converter will be used for the provided {@link MimeType}.
|
||||
* Create a {@link AvroSchemaMessageConverter}. The converter will be used for the
|
||||
* provided {@link MimeType}.
|
||||
*/
|
||||
public AvroSchemaMessageConverter(MimeType supportedMimeType) {
|
||||
super(supportedMimeType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link AvroSchemaMessageConverter}.
|
||||
* The converter will be used for the provided {@link MimeType}s.
|
||||
* Create a {@link AvroSchemaMessageConverter}. The converter will be used for the
|
||||
* provided {@link MimeType}s.
|
||||
* @param supportedMimeTypes the mime types supported by this converter
|
||||
*/
|
||||
public AvroSchemaMessageConverter(Collection<MimeType> supportedMimeTypes) {
|
||||
|
||||
@@ -110,13 +110,15 @@ public class AvroSchemaRegistryClientMessageConverter extends AbstractAvroMessag
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance, configuring it with {@link SchemaRegistryClient} and {@link CacheManager}.
|
||||
* Creates a new instance, configuring it with {@link SchemaRegistryClient} and
|
||||
* {@link CacheManager}.
|
||||
* @param schemaRegistryClient the {@link SchemaRegistryClient} used to interact with
|
||||
* the schema registry server.
|
||||
* @param cacheManager instance of {@link CacheManager} to cache parsed schemas. If caching
|
||||
* is not required use {@link NoOpCacheManager}
|
||||
* @param cacheManager instance of {@link CacheManager} to cache parsed schemas. If
|
||||
* caching is not required use {@link NoOpCacheManager}
|
||||
*/
|
||||
public AvroSchemaRegistryClientMessageConverter(SchemaRegistryClient schemaRegistryClient, CacheManager cacheManager) {
|
||||
public AvroSchemaRegistryClientMessageConverter(SchemaRegistryClient schemaRegistryClient,
|
||||
CacheManager cacheManager) {
|
||||
super(Arrays.asList(new MimeType("application", "*+avro")));
|
||||
Assert.notNull(schemaRegistryClient, "cannot be null");
|
||||
Assert.notNull(cacheManager, "'cacheManager' cannot be null");
|
||||
@@ -194,7 +196,7 @@ public class AvroSchemaRegistryClientMessageConverter extends AbstractAvroMessag
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.cacheManager instanceof NoOpCacheManager){
|
||||
if (this.cacheManager instanceof NoOpCacheManager) {
|
||||
logger.warn("Schema caching is effectively disabled "
|
||||
+ "since configured cache manager is a NoOpCacheManager. If this was not "
|
||||
+ "the intention, please provide the appropriate instance of CacheManager "
|
||||
@@ -337,7 +339,6 @@ public class AvroSchemaRegistryClientMessageConverter extends AbstractAvroMessag
|
||||
return schema;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated as of release 1.0.4. Please use the constructor to inject CacheManager
|
||||
*/
|
||||
|
||||
@@ -46,9 +46,9 @@ public class CachingRegistryClient implements SchemaRegistryClient {
|
||||
|
||||
@Override
|
||||
public SchemaRegistrationResponse register(String subject, String format, String schema) {
|
||||
SchemaRegistrationResponse response = delegate.register(subject,format,schema);
|
||||
cacheManager.getCache(ID_CACHE).put(response.getSchemaReference(),schema);
|
||||
cacheManager.getCache(REF_CACHE).put(response.getId(),schema);
|
||||
SchemaRegistrationResponse response = delegate.register(subject, format, schema);
|
||||
cacheManager.getCache(ID_CACHE).put(response.getSchemaReference(), schema);
|
||||
cacheManager.getCache(REF_CACHE).put(response.getId(), schema);
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ import org.springframework.web.client.RestTemplate;
|
||||
*/
|
||||
public class DefaultSchemaRegistryClient implements SchemaRegistryClient {
|
||||
|
||||
|
||||
private RestTemplate template;
|
||||
|
||||
private String endpoint = "http://localhost:8990";
|
||||
@@ -69,7 +68,8 @@ public class DefaultSchemaRegistryClient implements SchemaRegistryClient {
|
||||
ResponseEntity<Map> responseEntity = this.template.getForEntity(
|
||||
this.endpoint + "/" + schemaReference.getSubject() + "/" + schemaReference
|
||||
.getFormat() + "/v" + schemaReference
|
||||
.getVersion(), Map.class);
|
||||
.getVersion(),
|
||||
Map.class);
|
||||
if (!responseEntity.getStatusCode().is2xxSuccessful()) {
|
||||
throw new RuntimeException("Failed to fetch schema: " + responseEntity.toString());
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ import org.springframework.context.annotation.Import;
|
||||
/**
|
||||
* @author Marius Bogoevici
|
||||
*/
|
||||
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
|
||||
@Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Inherited
|
||||
|
||||
@@ -26,16 +26,19 @@ import org.springframework.cloud.stream.schema.SchemaRegistrationResponse;
|
||||
public interface SchemaRegistryClient {
|
||||
|
||||
/**
|
||||
* Registers a schema with the remote repository returning the unique identifier associated with this schema.
|
||||
* Registers a schema with the remote repository returning the unique identifier
|
||||
* associated with this schema.
|
||||
* @param subject the full name of the schema
|
||||
* @param schema
|
||||
* @return a {@link SchemaRegistrationResponse} representing the result of the operation
|
||||
* @return a {@link SchemaRegistrationResponse} representing the result of the
|
||||
* operation
|
||||
*/
|
||||
SchemaRegistrationResponse register(String subject, String format, String schema);
|
||||
|
||||
/**
|
||||
* Retrieves a schema by its reference (subject and version).
|
||||
* @param schemaReference a {@link SchemaReference} used to identify the target schema.
|
||||
* @param schemaReference a {@link SchemaReference} used to identify the target
|
||||
* schema.
|
||||
* @return
|
||||
*/
|
||||
String fetch(SchemaReference schemaReference);
|
||||
|
||||
@@ -44,7 +44,8 @@ public class SchemaRegistryClientConfiguration {
|
||||
defaultSchemaRegistryClient.setEndpoint(schemaRegistryClientProperties.getEndpoint());
|
||||
}
|
||||
|
||||
SchemaRegistryClient client = (schemaRegistryClientProperties.isCached()) ? new CachingRegistryClient(defaultSchemaRegistryClient) : defaultSchemaRegistryClient;
|
||||
SchemaRegistryClient client = (schemaRegistryClientProperties.isCached())
|
||||
? new CachingRegistryClient(defaultSchemaRegistryClient) : defaultSchemaRegistryClient;
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
@@ -53,12 +53,12 @@ public class AvroMessageConverterSerializationTests {
|
||||
Pattern versionedSchema = Pattern.compile(
|
||||
"application/" + "vnd" + "\\.([\\p{Alnum}\\$\\.]+)\\.v(\\p{Digit}+)\\+avro");
|
||||
|
||||
private ConfigurableApplicationContext schemaRegistryServerContext;
|
||||
Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private ConfigurableApplicationContext schemaRegistryServerContext;
|
||||
|
||||
@Before
|
||||
public void setup(){
|
||||
public void setup() {
|
||||
schemaRegistryServerContext = SpringApplication.run(
|
||||
SchemaRegistryServerApplication.class);
|
||||
}
|
||||
@@ -72,9 +72,10 @@ public class AvroMessageConverterSerializationTests {
|
||||
public void sourceWriteSameVersion() throws Exception {
|
||||
User specificRecord = new User();
|
||||
specificRecord.setName("joe");
|
||||
Schema v1 = new Schema.Parser().parse(AvroMessageConverterSerializationTests.class.getClassLoader().getResourceAsStream("schemas/user.avsc"));
|
||||
Schema v1 = new Schema.Parser().parse(
|
||||
AvroMessageConverterSerializationTests.class.getClassLoader().getResourceAsStream("schemas/user.avsc"));
|
||||
GenericRecord genericRecord = new GenericData.Record(v1);
|
||||
genericRecord.put("name","joe");
|
||||
genericRecord.put("name", "joe");
|
||||
SchemaRegistryClient client = new DefaultSchemaRegistryClient();
|
||||
AvroSchemaRegistryClientMessageConverter converter = new AvroSchemaRegistryClientMessageConverter(client);
|
||||
converter.setDynamicSchemaGenerationEnabled(false);
|
||||
@@ -82,13 +83,19 @@ public class AvroMessageConverterSerializationTests {
|
||||
converter.setCacheManager(new ConcurrentMapCacheManager());
|
||||
converter.afterPropertiesSet();
|
||||
|
||||
Message specificMessage = converter.toMessage(specificRecord,new MutableMessageHeaders(Collections.<String,Object>emptyMap()), MimeTypeUtils.parseMimeType("application/*+avro"));
|
||||
SchemaReference specificRef = extractSchemaReference( MimeTypeUtils.parseMimeType(specificMessage.getHeaders().get("contentType").toString()));
|
||||
Message specificMessage = converter.toMessage(specificRecord,
|
||||
new MutableMessageHeaders(Collections.<String, Object>emptyMap()),
|
||||
MimeTypeUtils.parseMimeType("application/*+avro"));
|
||||
SchemaReference specificRef = extractSchemaReference(
|
||||
MimeTypeUtils.parseMimeType(specificMessage.getHeaders().get("contentType").toString()));
|
||||
|
||||
Message genericMessage = converter.toMessage(genericRecord,new MutableMessageHeaders(Collections.<String,Object>emptyMap()), MimeTypeUtils.parseMimeType("application/*+avro"));
|
||||
SchemaReference genericRef = extractSchemaReference( MimeTypeUtils.parseMimeType(genericMessage.getHeaders().get("contentType").toString()));
|
||||
Message genericMessage = converter.toMessage(genericRecord,
|
||||
new MutableMessageHeaders(Collections.<String, Object>emptyMap()),
|
||||
MimeTypeUtils.parseMimeType("application/*+avro"));
|
||||
SchemaReference genericRef = extractSchemaReference(
|
||||
MimeTypeUtils.parseMimeType(genericMessage.getHeaders().get("contentType").toString()));
|
||||
|
||||
Assert.assertEquals(genericRef,specificRef);
|
||||
Assert.assertEquals(genericRef, specificRef);
|
||||
Assert.assertEquals(1, genericRef.getVersion());
|
||||
}
|
||||
|
||||
@@ -98,7 +105,8 @@ public class AvroMessageConverterSerializationTests {
|
||||
if (schemaMatcher.find()) {
|
||||
String subject = schemaMatcher.group(1);
|
||||
Integer version = Integer.parseInt(schemaMatcher.group(2));
|
||||
schemaReference = new SchemaReference(subject, version, AvroSchemaRegistryClientMessageConverter.AVRO_FORMAT);
|
||||
schemaReference = new SchemaReference(subject, version,
|
||||
AvroSchemaRegistryClientMessageConverter.AVRO_FORMAT);
|
||||
}
|
||||
return schemaReference;
|
||||
}
|
||||
|
||||
@@ -68,7 +68,6 @@ public class AvroSchemaMessageConverterTests {
|
||||
Message<?> outboundMessage = sourceMessageCollector.forChannel(source.output()).poll(1000,
|
||||
TimeUnit.MILLISECONDS);
|
||||
|
||||
|
||||
ConfigurableApplicationContext barSourceContext = SpringApplication.run(AvroSourceApplication.class,
|
||||
"--server.port=0",
|
||||
"--spring.jmx.enabled=false",
|
||||
@@ -87,7 +86,6 @@ public class AvroSchemaMessageConverterTests {
|
||||
|
||||
assertThat(barOutboundMessage).isNotNull();
|
||||
|
||||
|
||||
User2 secondUser2OutboundPojo = new User2();
|
||||
secondUser2OutboundPojo.setFavoriteColor("foo" + UUID.randomUUID().toString());
|
||||
secondUser2OutboundPojo.setFavoritePlace("foo" + UUID.randomUUID().toString());
|
||||
@@ -96,7 +94,6 @@ public class AvroSchemaMessageConverterTests {
|
||||
Message<?> secondBarOutboundMessage = sourceMessageCollector.forChannel(source.output()).poll(1000,
|
||||
TimeUnit.MILLISECONDS);
|
||||
|
||||
|
||||
ConfigurableApplicationContext sinkContext = SpringApplication.run(AvroSinkApplication.class,
|
||||
"--server.port=0",
|
||||
"--spring.jmx.enabled=false",
|
||||
@@ -139,7 +136,6 @@ public class AvroSchemaMessageConverterTests {
|
||||
Message<?> outboundMessage = sourceMessageCollector.forChannel(source.output()).poll(1000,
|
||||
TimeUnit.MILLISECONDS);
|
||||
|
||||
|
||||
ConfigurableApplicationContext barSourceContext = SpringApplication.run(AvroSourceApplication.class,
|
||||
"--server.port=0",
|
||||
"--spring.jmx.enabled=false",
|
||||
@@ -157,7 +153,6 @@ public class AvroSchemaMessageConverterTests {
|
||||
|
||||
assertThat(barOutboundMessage).isNotNull();
|
||||
|
||||
|
||||
User2 secondUser2OutboundPojo = new User2();
|
||||
secondUser2OutboundPojo.setFavoriteColor("foo" + UUID.randomUUID().toString());
|
||||
secondUser2OutboundPojo.setFavoritePlace("foo" + UUID.randomUUID().toString());
|
||||
@@ -166,7 +161,6 @@ public class AvroSchemaMessageConverterTests {
|
||||
Message<?> secondBarOutboundMessage = sourceMessageCollector.forChannel(source.output()).poll(1000,
|
||||
TimeUnit.MILLISECONDS);
|
||||
|
||||
|
||||
ConfigurableApplicationContext sinkContext = SpringApplication.run(AvroSinkApplication.class,
|
||||
"--server.port=0",
|
||||
"--spring.jmx.enabled=false",
|
||||
@@ -192,19 +186,18 @@ public class AvroSchemaMessageConverterTests {
|
||||
sourceContext.close();
|
||||
}
|
||||
|
||||
|
||||
@EnableBinding(Source.class)
|
||||
@EnableAutoConfiguration
|
||||
@ConfigurationProperties
|
||||
public static class AvroSourceApplication {
|
||||
|
||||
private Resource schemaLocation;
|
||||
|
||||
@Bean
|
||||
public SchemaRegistryClient schemaRegistryClient() {
|
||||
return stubSchemaRegistryClient;
|
||||
}
|
||||
|
||||
private Resource schemaLocation;
|
||||
|
||||
public void setSchemaLocation(Resource schemaLocation) {
|
||||
this.schemaLocation = schemaLocation;
|
||||
}
|
||||
@@ -227,13 +220,13 @@ public class AvroSchemaMessageConverterTests {
|
||||
|
||||
public List<User1> receivedUsers = new ArrayList<>();
|
||||
|
||||
private Resource schemaLocation;
|
||||
|
||||
@StreamListener(Sink.INPUT)
|
||||
public void listen(User1 user) {
|
||||
receivedUsers.add(user);
|
||||
}
|
||||
|
||||
private Resource schemaLocation;
|
||||
|
||||
public void setSchemaLocation(Resource schemaLocation) {
|
||||
this.schemaLocation = schemaLocation;
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.support.MessageBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Marius Bogoevici
|
||||
* @author Oleg Zhurakousky
|
||||
@@ -72,7 +73,6 @@ public class AvroSchemaRegistryClientMessageConverterTests {
|
||||
Message<?> outboundMessage = sourceMessageCollector.forChannel(source.output()).poll(1000,
|
||||
TimeUnit.MILLISECONDS);
|
||||
|
||||
|
||||
ConfigurableApplicationContext barSourceContext = SpringApplication.run(AvroSourceApplication.class,
|
||||
"--server.port=0",
|
||||
"--spring.jmx.enabled=false",
|
||||
@@ -89,7 +89,6 @@ public class AvroSchemaRegistryClientMessageConverterTests {
|
||||
|
||||
assertThat(barOutboundMessage).isNotNull();
|
||||
|
||||
|
||||
User2 secondBarOutboundPojo = new User2();
|
||||
secondBarOutboundPojo.setFavoriteColor("foo" + UUID.randomUUID().toString());
|
||||
secondBarOutboundPojo.setName("foo" + UUID.randomUUID().toString());
|
||||
@@ -97,7 +96,6 @@ public class AvroSchemaRegistryClientMessageConverterTests {
|
||||
Message<?> secondBarOutboundMessage = sourceMessageCollector.forChannel(source.output()).poll(1000,
|
||||
TimeUnit.MILLISECONDS);
|
||||
|
||||
|
||||
ConfigurableApplicationContext sinkContext = SpringApplication.run(AvroSinkApplication.class,
|
||||
"--server.port=0", "--spring.jmx.enabled=false");
|
||||
Sink sink = sinkContext.getBean(Sink.class);
|
||||
@@ -116,7 +114,6 @@ public class AvroSchemaRegistryClientMessageConverterTests {
|
||||
assertThat(receivedPojos.get(1).getName()).isEqualTo(firstOutboundUser2.getName());
|
||||
assertThat(receivedPojos.get(1).getFavoritePlace()).isEqualTo("Boston");
|
||||
|
||||
|
||||
assertThat(receivedPojos.get(2)).isNotSameAs(secondBarOutboundPojo);
|
||||
assertThat(receivedPojos.get(2).getFavoriteColor()).isEqualTo(secondBarOutboundPojo.getFavoriteColor());
|
||||
assertThat(receivedPojos.get(2).getName()).isEqualTo(secondBarOutboundPojo.getName());
|
||||
@@ -128,6 +125,16 @@ public class AvroSchemaRegistryClientMessageConverterTests {
|
||||
schemaRegistryServerContext.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoCacheConfiguration() {
|
||||
ConfigurableApplicationContext sourceContext = SpringApplication.run(NoCacheConfiguration.class,
|
||||
"--spring.main.web-environment=false");
|
||||
AvroSchemaRegistryClientMessageConverter converter = sourceContext
|
||||
.getBean(AvroSchemaRegistryClientMessageConverter.class);
|
||||
DirectFieldAccessor accessor = new DirectFieldAccessor(converter);
|
||||
assertThat(accessor.getPropertyValue("cacheManager")).isInstanceOf(NoOpCacheManager.class);
|
||||
}
|
||||
|
||||
@EnableBinding(Source.class)
|
||||
@EnableAutoConfiguration
|
||||
@EnableSchemaRegistryClient
|
||||
@@ -149,14 +156,6 @@ public class AvroSchemaRegistryClientMessageConverterTests {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoCacheConfiguration (){
|
||||
ConfigurableApplicationContext sourceContext = SpringApplication.run(NoCacheConfiguration.class, "--spring.main.web-environment=false");
|
||||
AvroSchemaRegistryClientMessageConverter converter = sourceContext.getBean(AvroSchemaRegistryClientMessageConverter.class);
|
||||
DirectFieldAccessor accessor = new DirectFieldAccessor(converter);
|
||||
assertThat(accessor.getPropertyValue("cacheManager")).isInstanceOf(NoOpCacheManager.class);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class NoCacheConfiguration {
|
||||
@SuppressWarnings("deprecation")
|
||||
|
||||
@@ -62,7 +62,6 @@ public class AvroStubSchemaRegistryClientMessageConverterTests {
|
||||
Message<?> outboundMessage = sourceMessageCollector.forChannel(source.output()).poll(1000,
|
||||
TimeUnit.MILLISECONDS);
|
||||
|
||||
|
||||
ConfigurableApplicationContext barSourceContext = SpringApplication.run(AvroSourceApplication.class,
|
||||
"--server.port=0",
|
||||
"--spring.jmx.enabled=false",
|
||||
@@ -79,7 +78,6 @@ public class AvroStubSchemaRegistryClientMessageConverterTests {
|
||||
|
||||
assertThat(barOutboundMessage).isNotNull();
|
||||
|
||||
|
||||
User2 secondBarOutboundPojo = new User2();
|
||||
secondBarOutboundPojo.setFavoriteColor("foo" + UUID.randomUUID().toString());
|
||||
secondBarOutboundPojo.setName("foo" + UUID.randomUUID().toString());
|
||||
@@ -87,7 +85,6 @@ public class AvroStubSchemaRegistryClientMessageConverterTests {
|
||||
Message<?> secondBarOutboundMessage = sourceMessageCollector.forChannel(source.output()).poll(1000,
|
||||
TimeUnit.MILLISECONDS);
|
||||
|
||||
|
||||
ConfigurableApplicationContext sinkContext = SpringApplication.run(AvroSinkApplication.class,
|
||||
"--server.port=0", "--spring.jmx.enabled=false");
|
||||
Sink sink = sinkContext.getBean(Sink.class);
|
||||
@@ -106,7 +103,6 @@ public class AvroStubSchemaRegistryClientMessageConverterTests {
|
||||
assertThat(receivedPojos.get(1).getName()).isEqualTo(firstOutboundUser2.getName());
|
||||
assertThat(receivedPojos.get(1).getFavoritePlace()).isEqualTo("Boston");
|
||||
|
||||
|
||||
assertThat(receivedPojos.get(2)).isNotSameAs(secondBarOutboundPojo);
|
||||
assertThat(receivedPojos.get(2).getFavoriteColor()).isEqualTo(secondBarOutboundPojo.getFavoriteColor());
|
||||
assertThat(receivedPojos.get(2).getName()).isEqualTo(secondBarOutboundPojo.getName());
|
||||
|
||||
@@ -42,12 +42,12 @@ public abstract class AbstractExternalResourceTestSupport<R> implements TestRule
|
||||
|
||||
public static final String SCS_EXTERNAL_SERVERS_REQUIRED = "SCS_EXTERNAL_SERVERS_REQUIRED";
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
protected R resource;
|
||||
|
||||
private String resourceDescription;
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
protected AbstractExternalResourceTestSupport(String resourceDescription) {
|
||||
Assert.hasText(resourceDescription, "resourceDescription is required");
|
||||
this.resourceDescription = resourceDescription;
|
||||
|
||||
@@ -22,8 +22,8 @@ import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
|
||||
/**
|
||||
* Maintains a map between (output) channels and messages received (in FIFO order). To be injected in tests that
|
||||
* can then run assertions on the enqueued messages.
|
||||
* Maintains a map between (output) channels and messages received (in FIFO order). To be
|
||||
* injected in tests that can then run assertions on the enqueued messages.
|
||||
*
|
||||
* @author Eric Bottard
|
||||
*/
|
||||
|
||||
@@ -25,7 +25,8 @@ import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
|
||||
/**
|
||||
* An {@link EnvironmentPostProcessor} that sets some configuration properties for {@link TestSupportBinder}.
|
||||
* An {@link EnvironmentPostProcessor} that sets some configuration properties for
|
||||
* {@link TestSupportBinder}.
|
||||
*
|
||||
* @author Ilayaperumal Gopinathan
|
||||
*/
|
||||
|
||||
@@ -36,9 +36,12 @@ import org.springframework.messaging.SubscribableChannel;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A minimal binder that<ul>
|
||||
* <li>does nothing about binding consumers, leaving the channel as-is, so that a test author can interact with it directly,</li>
|
||||
* <li>registers a queue channel on the producer side, so that it is easy to assert what is received.</li>
|
||||
* A minimal binder that
|
||||
* <ul>
|
||||
* <li>does nothing about binding consumers, leaving the channel as-is, so that a test
|
||||
* author can interact with it directly,</li>
|
||||
* <li>registers a queue channel on the producer side, so that it is easy to assert what
|
||||
* is received.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Eric Bottard
|
||||
@@ -53,12 +56,14 @@ public class TestSupportBinder implements Binder<MessageChannel, ConsumerPropert
|
||||
private final ConcurrentMap<String, MessageChannel> messageChannels = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public Binding<MessageChannel> bindConsumer(String name, String group, MessageChannel inboundBindTarget, ConsumerProperties properties) {
|
||||
public Binding<MessageChannel> bindConsumer(String name, String group, MessageChannel inboundBindTarget,
|
||||
ConsumerProperties properties) {
|
||||
return new TestBinding(inboundBindTarget, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a single subscriber to the channel, that enqueues messages for later retrieval and assertion in tests.
|
||||
* Registers a single subscriber to the channel, that enqueues messages for later
|
||||
* retrieval and assertion in tests.
|
||||
*/
|
||||
@Override
|
||||
public Binding<MessageChannel> bindProducer(String name, MessageChannel outboundBindTarget,
|
||||
@@ -99,7 +104,8 @@ public class TestSupportBinder implements Binder<MessageChannel, ConsumerPropert
|
||||
}
|
||||
|
||||
private void unregister(MessageChannel channel) {
|
||||
Assert.notNull(results.remove(channel), "Trying to unregister a mapping for an unknown channel [" + channel + "]");
|
||||
Assert.notNull(results.remove(channel),
|
||||
"Trying to unregister a mapping for an unknown channel [" + channel + "]");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -27,12 +27,12 @@ import org.springframework.core.Ordered;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
|
||||
/**
|
||||
* Installs the {@link TestSupportBinder} and exposes {@link TestSupportBinder.MessageCollectorImpl} to be injected in
|
||||
* tests.
|
||||
* Installs the {@link TestSupportBinder} and exposes
|
||||
* {@link TestSupportBinder.MessageCollectorImpl} to be injected in tests.
|
||||
*
|
||||
* Note that this auto-configuration has higher priority than regular binder configuration, so adding
|
||||
* this on the classpath in test scope is sufficient to have support kick in and replace all binders
|
||||
* with the test binder.
|
||||
* Note that this auto-configuration has higher priority than regular binder
|
||||
* configuration, so adding this on the classpath in test scope is sufficient to have
|
||||
* support kick in and replace all binders with the test binder.
|
||||
*
|
||||
* @author Eric Bottard
|
||||
* @author Marius Bogoevici
|
||||
@@ -47,7 +47,8 @@ public class TestSupportBinderAutoConfiguration {
|
||||
public BinderFactory binderFactory() {
|
||||
return new BinderFactory() {
|
||||
@Override
|
||||
public <T> Binder<T, ? extends ConsumerProperties, ? extends ProducerProperties> getBinder(String configurationName, Class<? extends T> bindableType) {
|
||||
public <T> Binder<T, ? extends ConsumerProperties, ? extends ProducerProperties> getBinder(
|
||||
String configurationName, Class<? extends T> bindableType) {
|
||||
return (Binder<T, ? extends ConsumerProperties, ? extends ProducerProperties>) messageChannelBinder;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -33,7 +33,9 @@ import org.springframework.messaging.Message;
|
||||
/**
|
||||
* A Hamcrest Matcher meant to be used in conjunction with {@link TestSupportBinder}.
|
||||
*
|
||||
* <p>Expected usage is of the form (with appropriate static imports):
|
||||
* <p>
|
||||
* Expected usage is of the form (with appropriate static imports):
|
||||
*
|
||||
* <pre>
|
||||
* public class TransformProcessorApplicationTests {
|
||||
*
|
||||
@@ -51,7 +53,8 @@ import org.springframework.messaging.Message;
|
||||
* assertThat(messageCollector.forChannel(processor.output()), receivesPayloadThat(is("hellofoo")).within(10));
|
||||
* }
|
||||
*
|
||||
* }</pre>
|
||||
* }
|
||||
* </pre>
|
||||
* </p>
|
||||
*
|
||||
* @author Eric Bottard
|
||||
@@ -62,12 +65,12 @@ public class MessageQueueMatcher<T> extends BaseMatcher<BlockingQueue<Message<?>
|
||||
|
||||
private final long timeout;
|
||||
|
||||
private final TimeUnit unit;
|
||||
|
||||
private Extractor<Message<?>, T> extractor;
|
||||
|
||||
private Map<BlockingQueue<Message<?>>, T> actuallyReceived = new HashMap<>();
|
||||
|
||||
private final TimeUnit unit;
|
||||
|
||||
public MessageQueueMatcher(Matcher<T> delegate, long timeout, TimeUnit unit, Extractor<Message<?>, T> extractor) {
|
||||
this.delegate = delegate;
|
||||
this.timeout = timeout;
|
||||
@@ -75,6 +78,28 @@ public class MessageQueueMatcher<T> extends BaseMatcher<BlockingQueue<Message<?>
|
||||
this.extractor = extractor;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public static <P> MessageQueueMatcher<P> receivesMessageThat(Matcher<Message<P>> messageMatcher) {
|
||||
return new MessageQueueMatcher(messageMatcher, 5, TimeUnit.SECONDS,
|
||||
new Extractor<Message<P>, Message<P>>("a message that ") {
|
||||
@Override
|
||||
public Message<P> apply(Message<P> m) {
|
||||
return m;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public static <P> MessageQueueMatcher<P> receivesPayloadThat(Matcher<P> payloadMatcher) {
|
||||
return new MessageQueueMatcher(payloadMatcher, 5, TimeUnit.SECONDS,
|
||||
new Extractor<Message<P>, P>("a message whose payload ") {
|
||||
@Override
|
||||
public P apply(Message<P> m) {
|
||||
return m.getPayload();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Object item) {
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -129,28 +154,9 @@ public class MessageQueueMatcher<T> extends BaseMatcher<BlockingQueue<Message<?>
|
||||
description.appendText("Channel to receive ").appendDescriptionOf(extractor).appendDescriptionOf(delegate);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public static <P> MessageQueueMatcher<P> receivesMessageThat(Matcher<Message<P>> messageMatcher) {
|
||||
return new MessageQueueMatcher(messageMatcher, 5, TimeUnit.SECONDS, new Extractor<Message<P>, Message<P>>("a message that ") {
|
||||
@Override
|
||||
public Message<P> apply(Message<P> m) {
|
||||
return m;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public static <P> MessageQueueMatcher<P> receivesPayloadThat(Matcher<P> payloadMatcher) {
|
||||
return new MessageQueueMatcher(payloadMatcher, 5, TimeUnit.SECONDS, new Extractor<Message<P>, P>("a message whose payload ") {
|
||||
@Override
|
||||
public P apply(Message<P> m) {
|
||||
return m.getPayload();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* A transformation to be applied to a received message before asserting, <i>e.g.</i> to only inspect the payload.
|
||||
* A transformation to be applied to a received message before asserting, <i>e.g.</i>
|
||||
* to only inspect the payload.
|
||||
*/
|
||||
public static abstract class Extractor<R, T> implements Function<R, T>, SelfDescribing {
|
||||
|
||||
@@ -166,6 +172,4 @@ public class MessageQueueMatcher<T> extends BaseMatcher<BlockingQueue<Message<?>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Marius Bogoevici
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringBootTest(classes = AggregateWithBeanTest.ChainedProcessors.class, properties = {"server.port=-1"})
|
||||
@SpringBootTest(classes = AggregateWithBeanTest.ChainedProcessors.class, properties = { "server.port=-1" })
|
||||
public class AggregateWithBeanTest {
|
||||
|
||||
@Autowired
|
||||
|
||||
@@ -43,8 +43,9 @@ public class AggregateWithMainTest {
|
||||
@Test
|
||||
public void testAggregateApplication() throws InterruptedException {
|
||||
// emulate a main method
|
||||
ConfigurableApplicationContext context = new AggregateApplicationBuilder(TestSupportBinderAutoConfiguration.class).from(UppercaseProcessor.class)
|
||||
.namespace("upper").to(SuffixProcessor.class).namespace("suffix").run();
|
||||
ConfigurableApplicationContext context = new AggregateApplicationBuilder(
|
||||
TestSupportBinderAutoConfiguration.class).from(UppercaseProcessor.class)
|
||||
.namespace("upper").to(SuffixProcessor.class).namespace("suffix").run();
|
||||
|
||||
AggregateApplication aggregateAccessor = context.getBean(AggregateApplication.class);
|
||||
MessageCollector messageCollector = context.getBean(MessageCollector.class);
|
||||
@@ -61,7 +62,6 @@ public class AggregateWithMainTest {
|
||||
@EnableBinding(Processor.class)
|
||||
public static class UppercaseProcessor {
|
||||
|
||||
|
||||
@Autowired
|
||||
Processor processor;
|
||||
|
||||
|
||||
@@ -36,11 +36,12 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration test that validates that {@link org.springframework.cloud.stream.test.binder.TestSupportBinder} applies
|
||||
* Integration test that validates that
|
||||
* {@link org.springframework.cloud.stream.test.binder.TestSupportBinder} applies
|
||||
* correctly.
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringBootTest(classes = ExampleTest.MyProcessor.class, properties = {"server.port=-1"})
|
||||
@SpringBootTest(classes = ExampleTest.MyProcessor.class, properties = { "server.port=-1" })
|
||||
@DirtiesContext
|
||||
public class ExampleTest {
|
||||
|
||||
@@ -63,7 +64,6 @@ public class ExampleTest {
|
||||
assertThat(received.getPayload()).isEqualTo("hello world");
|
||||
}
|
||||
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableBinding(Processor.class)
|
||||
public static class MyProcessor {
|
||||
|
||||
@@ -17,15 +17,16 @@
|
||||
package org.springframework.cloud.stream.aggregate;
|
||||
|
||||
/**
|
||||
* Handle to an aggregate application, providing access to the underlying
|
||||
* components of the aggregate (e.g. bindable instances).
|
||||
* Handle to an aggregate application, providing access to the underlying components of
|
||||
* the aggregate (e.g. bindable instances).
|
||||
*
|
||||
* @author Marius Bogoevici
|
||||
*/
|
||||
public interface AggregateApplication {
|
||||
|
||||
/**
|
||||
* Retrieves the bindable proxy instance (e.g. {@link org.springframework.cloud.stream.messaging.Processor},
|
||||
* Retrieves the bindable proxy instance (e.g.
|
||||
* {@link org.springframework.cloud.stream.messaging.Processor},
|
||||
* {@link org.springframework.cloud.stream.messaging.Source},
|
||||
* {@link org.springframework.cloud.stream.messaging.Sink} or custom interface) from
|
||||
* the given namespace.
|
||||
|
||||
@@ -61,7 +61,7 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
@EnableBinding
|
||||
public class AggregateApplicationBuilder implements AggregateApplication, ApplicationContextAware,
|
||||
SmartInitializingSingleton {
|
||||
SmartInitializingSingleton {
|
||||
|
||||
private static final String CHILD_CONTEXT_SUFFIX = ".spring.cloud.stream.context";
|
||||
|
||||
@@ -84,11 +84,11 @@ public class AggregateApplicationBuilder implements AggregateApplication, Applic
|
||||
private boolean webEnvironment = true;
|
||||
|
||||
public AggregateApplicationBuilder(String... args) {
|
||||
this(new Object[]{ParentConfiguration.class}, args);
|
||||
this(new Object[] { ParentConfiguration.class }, args);
|
||||
}
|
||||
|
||||
public AggregateApplicationBuilder(Object source, String... args) {
|
||||
this(new Object[]{source}, args);
|
||||
this(new Object[] { source }, args);
|
||||
}
|
||||
|
||||
public AggregateApplicationBuilder(Object[] sources, String[] args) {
|
||||
@@ -108,7 +108,7 @@ public class AggregateApplicationBuilder implements AggregateApplication, Applic
|
||||
}
|
||||
|
||||
public AggregateApplicationBuilder parent(Object source, String... args) {
|
||||
return parent(new Object[]{source}, args);
|
||||
return parent(new Object[] { source }, args);
|
||||
}
|
||||
|
||||
public AggregateApplicationBuilder parent(Object[] sources, String[] args) {
|
||||
@@ -194,16 +194,18 @@ public class AggregateApplicationBuilder implements AggregateApplication, Applic
|
||||
Class<?> appToEmbed = appConfigurer.getApp();
|
||||
// Always update namespace before preparing SharedChannelRegistry
|
||||
if (appConfigurer.namespace == null) {
|
||||
appConfigurer.namespace = AggregateApplicationUtils.getDefaultNamespace(appConfigurer.getApp().getName(), i);
|
||||
appConfigurer.namespace = AggregateApplicationUtils
|
||||
.getDefaultNamespace(appConfigurer.getApp().getName(), i);
|
||||
}
|
||||
appsToEmbed.put(appToEmbed, appConfigurer.namespace);
|
||||
appConfigurers.put(appConfigurer, appConfigurer.namespace);
|
||||
}
|
||||
if (this.parentContext == null) {
|
||||
if (Boolean.TRUE.equals(this.webEnvironment)) {
|
||||
this.addParentSources(new Object[]{EmbeddedServletContainerAutoConfiguration.class});
|
||||
this.addParentSources(new Object[] { EmbeddedServletContainerAutoConfiguration.class });
|
||||
}
|
||||
this.parentContext = AggregateApplicationUtils.createParentContext(this.parentSources.toArray(new Object[0]),
|
||||
this.parentContext = AggregateApplicationUtils.createParentContext(
|
||||
this.parentSources.toArray(new Object[0]),
|
||||
this.parentArgs.toArray(new String[0]), selfContained(), this.webEnvironment, this.headless);
|
||||
}
|
||||
else {
|
||||
@@ -216,7 +218,8 @@ public class AggregateApplicationBuilder implements AggregateApplication, Applic
|
||||
new SharedChannelRegistry(sharedBindingTargetRegistry));
|
||||
}
|
||||
}
|
||||
SharedBindingTargetRegistry sharedBindingTargetRegistry = this.parentContext.getBean(SharedBindingTargetRegistry.class);
|
||||
SharedBindingTargetRegistry sharedBindingTargetRegistry = this.parentContext
|
||||
.getBean(SharedBindingTargetRegistry.class);
|
||||
AggregateApplicationUtils.prepareSharedBindingTargetRegistry(sharedBindingTargetRegistry, appsToEmbed);
|
||||
PropertySources propertySources = this.parentContext.getEnvironment()
|
||||
.getPropertySources();
|
||||
@@ -291,6 +294,36 @@ public class AggregateApplicationBuilder implements AggregateApplication, Applic
|
||||
return new ChildContextBuilder(AggregateApplicationUtils.embedApp(parentContext, namespace, app));
|
||||
}
|
||||
|
||||
private static class ChildContextHolder {
|
||||
|
||||
private final ConfigurableApplicationContext childContext;
|
||||
|
||||
ChildContextHolder(ConfigurableApplicationContext childContext) {
|
||||
Assert.notNull(childContext, "cannot be null");
|
||||
this.childContext = childContext;
|
||||
}
|
||||
|
||||
public ConfigurableApplicationContext getChildContext() {
|
||||
return childContext;
|
||||
}
|
||||
}
|
||||
|
||||
@ImportAutoConfiguration({ ChannelBindingAutoConfiguration.class, EndpointAutoConfiguration.class })
|
||||
@EnableBinding
|
||||
public static class ParentConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(SharedBindingTargetRegistry.class)
|
||||
public SharedBindingTargetRegistry sharedBindingTargetRegistry() {
|
||||
return new SharedBindingTargetRegistry();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(SharedChannelRegistry.class)
|
||||
public SharedChannelRegistry sharedChannelRegistry(SharedBindingTargetRegistry sharedBindingTargetRegistry) {
|
||||
return new SharedChannelRegistry(sharedBindingTargetRegistry);
|
||||
}
|
||||
}
|
||||
|
||||
public class SourceConfigurer extends AppConfigurer<SourceConfigurer> {
|
||||
|
||||
public SourceConfigurer(Class<?> app) {
|
||||
@@ -382,7 +415,7 @@ public class AggregateApplicationBuilder implements AggregateApplication, Applic
|
||||
void embed() {
|
||||
final ConfigurableApplicationContext childContext = childContext(this.app,
|
||||
AggregateApplicationBuilder.this.parentContext, this.namespace).args(this.args).config(this.names)
|
||||
.profiles(this.profiles).run();
|
||||
.profiles(this.profiles).run();
|
||||
// Register bindable proxies as beans so they can be queried for later
|
||||
Map<String, BindableProxyFactory> bindableProxies = BeanFactoryUtils
|
||||
.beansOfTypeIncludingAncestors(childContext.getBeanFactory(), BindableProxyFactory.class);
|
||||
@@ -402,7 +435,8 @@ public class AggregateApplicationBuilder implements AggregateApplication, Applic
|
||||
if (BeanFactoryUtils.beansOfTypeIncludingAncestors(AggregateApplicationBuilder.this.parentContext,
|
||||
IntegrationMBeanExporter.class).size() > 0) {
|
||||
BeanFactoryUtils
|
||||
.beanOfTypeIncludingAncestors(AggregateApplicationBuilder.this.parentContext, MetricsEndpoint.class)
|
||||
.beanOfTypeIncludingAncestors(AggregateApplicationBuilder.this.parentContext,
|
||||
MetricsEndpoint.class)
|
||||
.registerPublicMetrics(
|
||||
new MetricReaderPublicMetrics(new NamespaceAwareSpringIntegrationMetricReader(
|
||||
this.namespace, childContext.getBean(IntegrationMBeanExporter.class))));
|
||||
@@ -413,7 +447,6 @@ public class AggregateApplicationBuilder implements AggregateApplication, Applic
|
||||
return applicationBuilder;
|
||||
}
|
||||
|
||||
|
||||
public String[] getArgs() {
|
||||
return this.args;
|
||||
}
|
||||
@@ -467,34 +500,4 @@ public class AggregateApplicationBuilder implements AggregateApplication, Applic
|
||||
|
||||
}
|
||||
|
||||
private static class ChildContextHolder {
|
||||
|
||||
private final ConfigurableApplicationContext childContext;
|
||||
|
||||
ChildContextHolder(ConfigurableApplicationContext childContext) {
|
||||
Assert.notNull(childContext, "cannot be null");
|
||||
this.childContext = childContext;
|
||||
}
|
||||
|
||||
public ConfigurableApplicationContext getChildContext() {
|
||||
return childContext;
|
||||
}
|
||||
}
|
||||
|
||||
@ImportAutoConfiguration({ChannelBindingAutoConfiguration.class, EndpointAutoConfiguration.class})
|
||||
@EnableBinding
|
||||
public static class ParentConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(SharedBindingTargetRegistry.class)
|
||||
public SharedBindingTargetRegistry sharedBindingTargetRegistry() {
|
||||
return new SharedBindingTargetRegistry();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(SharedChannelRegistry.class)
|
||||
public SharedChannelRegistry sharedChannelRegistry(SharedBindingTargetRegistry sharedBindingTargetRegistry) {
|
||||
return new SharedChannelRegistry(sharedBindingTargetRegistry);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,11 +27,13 @@ import org.springframework.integration.support.management.Statistics;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A customized version of {@link org.springframework.boot.actuate.metrics.integration.SpringIntegrationMetricReader} that
|
||||
* provides support for customizing channels with a namespace prefix.
|
||||
* A customized version of
|
||||
* {@link org.springframework.boot.actuate.metrics.integration.SpringIntegrationMetricReader}
|
||||
* that provides support for customizing channels with a namespace prefix.
|
||||
*
|
||||
* @author Marius Bogoevici
|
||||
* @see org.springframework.boot.actuate.metrics.integration.SpringIntegrationMetricReader for original implementation
|
||||
* @see org.springframework.boot.actuate.metrics.integration.SpringIntegrationMetricReader
|
||||
* for original implementation
|
||||
*/
|
||||
public class NamespaceAwareSpringIntegrationMetricReader implements MetricReader {
|
||||
|
||||
@@ -101,4 +103,3 @@ public class NamespaceAwareSpringIntegrationMetricReader implements MetricReader
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -26,13 +26,13 @@ import java.lang.annotation.Target;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
|
||||
/**
|
||||
* Indicates an instance of an interface containing methods returning bound
|
||||
* inputs and outputs.
|
||||
* Indicates an instance of an interface containing methods returning bound inputs and
|
||||
* outputs.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Marius Bogoevici
|
||||
* @deprecated As of 1.1 for being redundant (beans qualified by it are already
|
||||
* uniquely identified by their type)
|
||||
* @deprecated As of 1.1 for being redundant (beans qualified by it are already uniquely
|
||||
* identified by their type)
|
||||
*/
|
||||
|
||||
@Qualifier
|
||||
|
||||
@@ -34,7 +34,7 @@ import org.springframework.beans.factory.annotation.Qualifier;
|
||||
|
||||
@Qualifier
|
||||
@Target({ ElementType.FIELD, ElementType.METHOD,
|
||||
ElementType.ANNOTATION_TYPE, ElementType.PARAMETER })
|
||||
ElementType.ANNOTATION_TYPE, ElementType.PARAMETER })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
|
||||
@@ -141,7 +141,7 @@ public @interface StreamListener {
|
||||
* @return the name of the binding target.
|
||||
*/
|
||||
@AliasFor("value")
|
||||
String target() default "";
|
||||
String target() default "";
|
||||
|
||||
/**
|
||||
* A condition that must be met by all items that are dispatched to this method.
|
||||
|
||||
@@ -68,12 +68,12 @@ public abstract class AbstractBinder<T, C extends ConsumerProperties, P extends
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final StringConvertingContentTypeResolver contentTypeResolver = new StringConvertingContentTypeResolver();
|
||||
|
||||
private volatile AbstractApplicationContext applicationContext;
|
||||
|
||||
private volatile Codec codec;
|
||||
|
||||
private final StringConvertingContentTypeResolver contentTypeResolver = new StringConvertingContentTypeResolver();
|
||||
|
||||
private volatile EvaluationContext evaluationContext;
|
||||
|
||||
private volatile Map<String, Class<?>> payloadTypeCache = new ConcurrentHashMap<>();
|
||||
@@ -82,7 +82,7 @@ public abstract class AbstractBinder<T, C extends ConsumerProperties, P extends
|
||||
* For binder implementations that support a prefix, apply the prefix to the name.
|
||||
*
|
||||
* @param prefix the prefix.
|
||||
* @param name the name.
|
||||
* @param name the name.
|
||||
*/
|
||||
public static String applyPrefix(String prefix, String name) {
|
||||
return prefix + name;
|
||||
@@ -98,16 +98,16 @@ public abstract class AbstractBinder<T, C extends ConsumerProperties, P extends
|
||||
return name + ".dlq";
|
||||
}
|
||||
|
||||
protected AbstractApplicationContext getApplicationContext() {
|
||||
return this.applicationContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
|
||||
this.applicationContext = (AbstractApplicationContext) applicationContext;
|
||||
}
|
||||
|
||||
protected AbstractApplicationContext getApplicationContext() {
|
||||
return this.applicationContext;
|
||||
}
|
||||
|
||||
protected ConfigurableListableBeanFactory getBeanFactory() {
|
||||
return this.applicationContext.getBeanFactory();
|
||||
}
|
||||
@@ -157,7 +157,7 @@ public abstract class AbstractBinder<T, C extends ConsumerProperties, P extends
|
||||
/**
|
||||
* Construct a name comprised of the name and group.
|
||||
*
|
||||
* @param name the name.
|
||||
* @param name the name.
|
||||
* @param group the group.
|
||||
* @return the constructed name.
|
||||
*/
|
||||
@@ -243,7 +243,8 @@ public abstract class AbstractBinder<T, C extends ConsumerProperties, P extends
|
||||
return new String(bytes, "UTF-8");
|
||||
}
|
||||
catch (UnsupportedEncodingException e) {
|
||||
String errorMessage = "unable to deserialize [java.lang.String]. Encoding not supported. " + e.getMessage();
|
||||
String errorMessage = "unable to deserialize [java.lang.String]. Encoding not supported. "
|
||||
+ e.getMessage();
|
||||
logger.error(errorMessage);
|
||||
throw new SerializationFailedException(errorMessage, e);
|
||||
}
|
||||
@@ -258,9 +259,10 @@ public abstract class AbstractBinder<T, C extends ConsumerProperties, P extends
|
||||
this.payloadTypeCache.put(className, targetType);
|
||||
}
|
||||
return this.codec.decode(bytes, targetType);
|
||||
}// catch all exceptions that could occur during de-serialization
|
||||
} // catch all exceptions that could occur during de-serialization
|
||||
catch (Exception e) {
|
||||
String errorMessage = "Unable to deserialize [" + className + "] using the contentType [" + contentType + "] " + e.getMessage();
|
||||
String errorMessage = "Unable to deserialize [" + className + "] using the contentType [" + contentType
|
||||
+ "] " + e.getMessage();
|
||||
logger.error(errorMessage);
|
||||
throw new SerializationFailedException(errorMessage, e);
|
||||
}
|
||||
|
||||
@@ -39,15 +39,16 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.MimeType;
|
||||
|
||||
/**
|
||||
* {@link AbstractBinder} that serves as base class for {@link MessageChannel}
|
||||
* binders. Implementors must implement the following methods:
|
||||
* {@link AbstractBinder} that serves as base class for {@link MessageChannel} binders.
|
||||
* Implementors must implement the following methods:
|
||||
* <ul>
|
||||
* <li>{@link #createProducerMessageHandler(ProducerDestination, ProducerProperties)} </li>
|
||||
* <li>{@link #createConsumerEndpoint(ConsumerDestination, String, ConsumerProperties)} </li>
|
||||
* <li>{@link #createProducerMessageHandler(ProducerDestination, ProducerProperties)}</li>
|
||||
* <li>{@link #createConsumerEndpoint(ConsumerDestination, String, ConsumerProperties)}
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* @param <C> the consumer properties type
|
||||
* @param <P> the producer properties type
|
||||
* @param <C> the consumer properties type
|
||||
* @param <P> the producer properties type
|
||||
* @author Marius Bogoevici
|
||||
* @author Ilayaperumal Gopinathan
|
||||
* @author Soby Chacko
|
||||
@@ -59,9 +60,13 @@ public abstract class AbstractMessageChannelBinder<C extends ConsumerProperties,
|
||||
protected static final ExpressionParser EXPRESSION_PARSER = new SpelExpressionParser();
|
||||
|
||||
/**
|
||||
* Indicates whether the implementation and the message broker have
|
||||
* native support for message headers. If false, headers will be
|
||||
* embedded in the message payloads.
|
||||
* {@link ProvisioningProvider} delegated by the downstream binder implementations.
|
||||
*/
|
||||
protected final PP provisioningProvider;
|
||||
|
||||
/**
|
||||
* Indicates whether the implementation and the message broker have native support for
|
||||
* message headers. If false, headers will be embedded in the message payloads.
|
||||
*/
|
||||
private final boolean supportsHeadersNatively;
|
||||
|
||||
@@ -71,13 +76,8 @@ public abstract class AbstractMessageChannelBinder<C extends ConsumerProperties,
|
||||
*/
|
||||
private final String[] headersToEmbed;
|
||||
|
||||
/**
|
||||
* {@link ProvisioningProvider} delegated by the downstream binder implementations.
|
||||
*/
|
||||
protected final PP provisioningProvider;
|
||||
|
||||
public AbstractMessageChannelBinder(boolean supportsHeadersNatively, String[] headersToEmbed,
|
||||
PP provisioningProvider) {
|
||||
PP provisioningProvider) {
|
||||
this.supportsHeadersNatively = supportsHeadersNatively;
|
||||
this.headersToEmbed = headersToEmbed == null ? new String[0] : headersToEmbed;
|
||||
this.provisioningProvider = provisioningProvider;
|
||||
@@ -86,14 +86,15 @@ public abstract class AbstractMessageChannelBinder<C extends ConsumerProperties,
|
||||
/**
|
||||
* Binds an outbound channel to a given destination. The implementation delegates to
|
||||
* {@link ProvisioningProvider#provisionProducerDestination(String, ProducerProperties)}
|
||||
* and {@link #createProducerMessageHandler(ProducerDestination, ProducerProperties)} for
|
||||
* handling the middleware specific logic. If the returned producer message handler is an
|
||||
* {@link InitializingBean} then {@link InitializingBean#afterPropertiesSet()} will be
|
||||
* called on it. Similarly, if the returned producer message handler e ndpoint is a
|
||||
* {@link Lifecycle}, then {@link Lifecycle#start()} will be called on it.
|
||||
* and {@link #createProducerMessageHandler(ProducerDestination, ProducerProperties)}
|
||||
* for handling the middleware specific logic. If the returned producer message
|
||||
* handler is an {@link InitializingBean} then
|
||||
* {@link InitializingBean#afterPropertiesSet()} will be called on it. Similarly, if
|
||||
* the returned producer message handler e ndpoint is a {@link Lifecycle}, then
|
||||
* {@link Lifecycle#start()} will be called on it.
|
||||
*
|
||||
* @param destination the name of the destination
|
||||
* @param outputChannel the channel to be bound
|
||||
* @param destination the name of the destination
|
||||
* @param outputChannel the channel to be bound
|
||||
* @param producerProperties the {@link ProducerProperties} of the binding
|
||||
* @return the Binding for the channel
|
||||
* @throws BinderException on internal errors during binding
|
||||
@@ -106,7 +107,8 @@ public abstract class AbstractMessageChannelBinder<C extends ConsumerProperties,
|
||||
final MessageHandler producerMessageHandler;
|
||||
final ProducerDestination producerDestination;
|
||||
try {
|
||||
producerDestination = this.provisioningProvider.provisionProducerDestination(destination, producerProperties);
|
||||
producerDestination = this.provisioningProvider.provisionProducerDestination(destination,
|
||||
producerProperties);
|
||||
producerMessageHandler = createProducerMessageHandler(producerDestination, producerProperties);
|
||||
if (producerMessageHandler instanceof InitializingBean) {
|
||||
((InitializingBean) producerMessageHandler).afterPropertiesSet();
|
||||
@@ -128,7 +130,8 @@ public abstract class AbstractMessageChannelBinder<C extends ConsumerProperties,
|
||||
}
|
||||
((SubscribableChannel) outputChannel).subscribe(
|
||||
new SendingHandler(producerMessageHandler, !this.supportsHeadersNatively && HeaderMode.embeddedHeaders
|
||||
.equals(producerProperties.getHeaderMode()), this.headersToEmbed, producerProperties.isUseNativeEncoding()));
|
||||
.equals(producerProperties.getHeaderMode()), this.headersToEmbed,
|
||||
producerProperties.isUseNativeEncoding()));
|
||||
|
||||
return new DefaultBinding<MessageChannel>(destination, null, outputChannel,
|
||||
producerMessageHandler instanceof Lifecycle ? (Lifecycle) producerMessageHandler : null) {
|
||||
@@ -139,8 +142,10 @@ public abstract class AbstractMessageChannelBinder<C extends ConsumerProperties,
|
||||
if (producerMessageHandler instanceof DisposableBean) {
|
||||
((DisposableBean) producerMessageHandler).destroy();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
AbstractMessageChannelBinder.this.logger.error("Exception thrown while unbinding " + this.toString(), e);
|
||||
}
|
||||
catch (Exception e) {
|
||||
AbstractMessageChannelBinder.this.logger
|
||||
.error("Exception thrown while unbinding " + this.toString(), e);
|
||||
}
|
||||
afterUnbindProducer(producerDestination, producerProperties);
|
||||
}
|
||||
@@ -148,31 +153,32 @@ public abstract class AbstractMessageChannelBinder<C extends ConsumerProperties,
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link MessageHandler} with the ability to send data to the
|
||||
* target middleware. If the returned instance is also a {@link Lifecycle},
|
||||
* it will be stopped automatically by the binder.
|
||||
* Creates a {@link MessageHandler} with the ability to send data to the target
|
||||
* middleware. If the returned instance is also a {@link Lifecycle}, it will be
|
||||
* stopped automatically by the binder.
|
||||
* <p>
|
||||
* In order to be fully compliant, the {@link MessageHandler} of the binder
|
||||
* must observe the following headers:
|
||||
* In order to be fully compliant, the {@link MessageHandler} of the binder must
|
||||
* observe the following headers:
|
||||
* <ul>
|
||||
* <li>{@link BinderHeaders#PARTITION_HEADER} - indicates the target
|
||||
* partition where the message must be sent</li>
|
||||
* <li>{@link BinderHeaders#PARTITION_HEADER} - indicates the target partition where
|
||||
* the message must be sent</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
*
|
||||
* @param destination the name of the target destination
|
||||
* @param destination the name of the target destination
|
||||
* @param producerProperties the producer properties
|
||||
* @return the message handler for sending data to the target middleware
|
||||
* @throws Exception
|
||||
*/
|
||||
protected abstract MessageHandler createProducerMessageHandler(ProducerDestination destination, P producerProperties)
|
||||
protected abstract MessageHandler createProducerMessageHandler(ProducerDestination destination,
|
||||
P producerProperties)
|
||||
throws Exception;
|
||||
|
||||
/**
|
||||
* Invoked after the unbinding of a producer. Subclasses may override this to provide
|
||||
* their own logic for dealing with unbinding.
|
||||
*
|
||||
* @param destination the bound destination
|
||||
* @param destination the bound destination
|
||||
* @param producerProperties the producer properties
|
||||
*/
|
||||
protected void afterUnbindProducer(ProducerDestination destination, P producerProperties) {
|
||||
@@ -181,16 +187,17 @@ public abstract class AbstractMessageChannelBinder<C extends ConsumerProperties,
|
||||
/**
|
||||
* Binds an inbound channel to a given destination. The implementation delegates to
|
||||
* {@link ProvisioningProvider#provisionConsumerDestination(String, String, ConsumerProperties)}
|
||||
* and {@link #createConsumerEndpoint(ConsumerDestination, String, ConsumerProperties)}
|
||||
* and
|
||||
* {@link #createConsumerEndpoint(ConsumerDestination, String, ConsumerProperties)}
|
||||
* for handling middleware-specific logic. If the returned consumer endpoint is an
|
||||
* {@link InitializingBean} then {@link InitializingBean#afterPropertiesSet()} will be
|
||||
* called on it. Similarly, if the returned consumer endpoint is a {@link Lifecycle},
|
||||
* then {@link Lifecycle#start()} will be called on it.
|
||||
*
|
||||
* @param name the name of the destination
|
||||
* @param group the consumer group
|
||||
* @param name the name of the destination
|
||||
* @param group the consumer group
|
||||
* @param inputChannel the channel to be bound
|
||||
* @param properties the {@link ConsumerProperties} of the binding
|
||||
* @param properties the {@link ConsumerProperties} of the binding
|
||||
* @return the Binding for the channel
|
||||
* @throws BinderException on internal errors during binding
|
||||
*/
|
||||
@@ -199,7 +206,8 @@ public abstract class AbstractMessageChannelBinder<C extends ConsumerProperties,
|
||||
final C properties) throws BinderException {
|
||||
MessageProducer consumerEndpoint = null;
|
||||
try {
|
||||
final ConsumerDestination destination = this.provisioningProvider.provisionConsumerDestination(name, group, properties);
|
||||
final ConsumerDestination destination = this.provisioningProvider.provisionConsumerDestination(name, group,
|
||||
properties);
|
||||
final boolean extractEmbeddedHeaders = HeaderMode.embeddedHeaders.equals(
|
||||
properties.getHeaderMode()) && !this.supportsHeadersNatively;
|
||||
ReceivingHandler rh = new ReceivingHandler(extractEmbeddedHeaders);
|
||||
@@ -256,9 +264,9 @@ public abstract class AbstractMessageChannelBinder<C extends ConsumerProperties,
|
||||
* Creates {@link MessageProducer} that receives data from the consumer destination.
|
||||
* will be started and stopped by the binder.
|
||||
*
|
||||
* @param group the consumer group
|
||||
* @param group the consumer group
|
||||
* @param destination reference to the consumer destination
|
||||
* @param properties the consumer properties
|
||||
* @param properties the consumer properties
|
||||
* @return the consumer endpoint.
|
||||
*/
|
||||
protected abstract MessageProducer createConsumerEndpoint(ConsumerDestination destination, String group,
|
||||
@@ -268,8 +276,8 @@ public abstract class AbstractMessageChannelBinder<C extends ConsumerProperties,
|
||||
* Invoked after the unbinding of a consumer. The binder implementation can override
|
||||
* this method to provide their own logic (e.g. for cleaning up destinations).
|
||||
*
|
||||
* @param destination the consumer destination
|
||||
* @param group the consumer group
|
||||
* @param destination the consumer destination
|
||||
* @param group the consumer group
|
||||
* @param consumerProperties the consumer properties
|
||||
*/
|
||||
protected void afterUnbindConsumer(ConsumerDestination destination, String group, C consumerProperties) {
|
||||
@@ -299,7 +307,8 @@ public abstract class AbstractMessageChannelBinder<C extends ConsumerProperties,
|
||||
catch (Exception e) {
|
||||
AbstractMessageChannelBinder.this.logger.error(
|
||||
EmbeddedHeaderUtils.decodeExceptionMessage(
|
||||
requestMessage), e);
|
||||
requestMessage),
|
||||
e);
|
||||
messageValues = new MessageValues(requestMessage);
|
||||
}
|
||||
messageValues = deserializePayloadIfNecessary(messageValues);
|
||||
@@ -338,8 +347,8 @@ public abstract class AbstractMessageChannelBinder<C extends ConsumerProperties,
|
||||
|
||||
@Override
|
||||
protected void handleMessageInternal(Message<?> message) throws Exception {
|
||||
Message<?> messageToSend = (this.useNativeEncoding) ?
|
||||
message : serializeAndEmbedHeadersIfApplicable(message);
|
||||
Message<?> messageToSend = (this.useNativeEncoding) ? message
|
||||
: serializeAndEmbedHeadersIfApplicable(message);
|
||||
this.delegate.handleMessage(messageToSend);
|
||||
}
|
||||
|
||||
@@ -348,7 +357,8 @@ public abstract class AbstractMessageChannelBinder<C extends ConsumerProperties,
|
||||
byte[] payload;
|
||||
if (this.embedHeaders) {
|
||||
Object contentType = transformed.get(MessageHeaders.CONTENT_TYPE);
|
||||
// transform content type headers to String, so that they can be properly embedded in JSON
|
||||
// transform content type headers to String, so that they can be properly
|
||||
// embedded in JSON
|
||||
if (contentType instanceof MimeType) {
|
||||
transformed.put(MessageHeaders.CONTENT_TYPE, contentType.toString());
|
||||
}
|
||||
|
||||
@@ -16,10 +16,8 @@
|
||||
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
|
||||
/**
|
||||
* Exception thrown to indicate a binder error (most
|
||||
* likely a configuration error).
|
||||
* Exception thrown to indicate a binder error (most likely a configuration error).
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @author Marius Bogoevici
|
||||
|
||||
@@ -19,7 +19,6 @@ package org.springframework.cloud.stream.binder;
|
||||
import org.springframework.integration.IntegrationMessageHeaderAccessor;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
|
||||
|
||||
/**
|
||||
* Spring Integration message headers for Spring Cloud Stream.
|
||||
* @author Gary Russell
|
||||
@@ -27,34 +26,15 @@ import org.springframework.messaging.MessageHeaders;
|
||||
*/
|
||||
public final class BinderHeaders {
|
||||
|
||||
private static final String PREFIX = "scst_";
|
||||
|
||||
/**
|
||||
* Indicates the original content type of a message that has been
|
||||
* transformed in a native transport format.
|
||||
* Indicates the original content type of a message that has been transformed in a
|
||||
* native transport format.
|
||||
*/
|
||||
public static final String BINDER_ORIGINAL_CONTENT_TYPE = "originalContentType";
|
||||
|
||||
/**
|
||||
* Indicates the target partition of an outbound message.
|
||||
* Binders must observe this value when sending data on the transport.
|
||||
* This header is internally set by the framework when partitioning is
|
||||
* configured.
|
||||
* It may be overridden by {@link BinderHeaders#PARTITION_OVERRIDE} if set
|
||||
* by the user.
|
||||
*/
|
||||
public static final String PARTITION_HEADER = PREFIX + "partition";
|
||||
|
||||
/**
|
||||
* Indicates the target partition of an outbound message.
|
||||
* Overrides any partition selected by the binder.
|
||||
* This header takes precedence over {@link BinderHeaders#PARTITION_HEADER}.
|
||||
*/
|
||||
public static final String PARTITION_OVERRIDE = PREFIX + "partitionOverride";
|
||||
|
||||
/**
|
||||
* The headers that will be propagated, by default, by binder implementations
|
||||
* that have no inherent header support (by embedding the headers in the payload).
|
||||
* The headers that will be propagated, by default, by binder implementations that
|
||||
* have no inherent header support (by embedding the headers in the payload).
|
||||
*/
|
||||
public static final String[] STANDARD_HEADERS = new String[] {
|
||||
IntegrationMessageHeaderAccessor.CORRELATION_ID,
|
||||
@@ -64,6 +44,23 @@ public final class BinderHeaders {
|
||||
BINDER_ORIGINAL_CONTENT_TYPE
|
||||
};
|
||||
|
||||
private static final String PREFIX = "scst_";
|
||||
|
||||
/**
|
||||
* Indicates the target partition of an outbound message. Binders must observe this
|
||||
* value when sending data on the transport. This header is internally set by the
|
||||
* framework when partitioning is configured. It may be overridden by
|
||||
* {@link BinderHeaders#PARTITION_OVERRIDE} if set by the user.
|
||||
*/
|
||||
public static final String PARTITION_HEADER = PREFIX + "partition";
|
||||
|
||||
/**
|
||||
* Indicates the target partition of an outbound message. Overrides any partition
|
||||
* selected by the binder. This header takes precedence over
|
||||
* {@link BinderHeaders#PARTITION_HEADER}.
|
||||
*/
|
||||
public static final String PARTITION_OVERRIDE = PREFIX + "partitionOverride";
|
||||
|
||||
private BinderHeaders() {
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user