Merge branch 'polish' of https://github.com/philwebb/spring-cloud-netflix into philwebb-polish

Conflicts:
	spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignClient.java
	spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/feign/FeignClientScan.java
	spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/zuul/filters/route/RibbonRoutingFilter.java
	spring-cloud-netflix-turbine-amqp/src/test/java/org/springframework/cloud/netflix/turbine/amqp/AggregatorTest.java
This commit is contained in:
Spencer Gibb
2015-01-15 11:04:47 -07:00
168 changed files with 7237 additions and 4434 deletions

View File

@@ -1,44 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-docs</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-build</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<relativePath/>
<relativePath />
</parent>
<artifactId>spring-cloud-netflix-docs</artifactId>
<packaging>pom</packaging>
<name>Spring Cloud Netflix Docs</name>
<description>Spring Cloud Docs</description>
<properties>
<docs.main>spring-cloud-netflix</docs.main>
<docs.main>spring-cloud-netflix</docs.main>
<main.basedir>${basedir}/..</main.basedir>
</properties>
<profiles>
<profiles>
<profile>
<id>docs</id>
<build>
<plugins>
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<inherited>false</inherited>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<inherited>false</inherited>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<inherited>false</inherited>
</plugin>
</plugins>
</build>
<build>
<plugins>
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<inherited>false</inherited>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<inherited>false</inherited>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<inherited>false</inherited>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</profiles>
</project>

View File

@@ -0,0 +1,295 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="12">
<profile kind="CodeFormatterProfile" name="Spring Cloud 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="8"/>
<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="0"/>
<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="false"/>
<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="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="true"/>
<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="0"/>
<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="90"/>
<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>

View File

@@ -0,0 +1,389 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.codeComplete.argumentPrefixes=
org.eclipse.jdt.core.codeComplete.argumentSuffixes=
org.eclipse.jdt.core.codeComplete.fieldPrefixes=
org.eclipse.jdt.core.codeComplete.fieldSuffixes=
org.eclipse.jdt.core.codeComplete.localPrefixes=
org.eclipse.jdt.core.codeComplete.localSuffixes=
org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.doc.comment.support=enabled
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
org.eclipse.jdt.core.compiler.problem.deadCode=warning
org.eclipse.jdt.core.compiler.problem.deprecation=warning
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=default
org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag
org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
org.eclipse.jdt.core.compiler.problem.nullReference=ignore
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
org.eclipse.jdt.core.compiler.problem.unusedImport=warning
org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
org.eclipse.jdt.core.compiler.source=1.6
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_assignment=0
org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
org.eclipse.jdt.core.formatter.blank_lines_after_package=1
org.eclipse.jdt.core.formatter.blank_lines_before_field=0
org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
org.eclipse.jdt.core.formatter.blank_lines_before_method=1
org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
org.eclipse.jdt.core.formatter.blank_lines_before_package=0
org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
org.eclipse.jdt.core.formatter.comment.format_block_comments=true
org.eclipse.jdt.core.formatter.comment.format_header=false
org.eclipse.jdt.core.formatter.comment.format_html=true
org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
org.eclipse.jdt.core.formatter.comment.format_line_comments=true
org.eclipse.jdt.core.formatter.comment.format_source_code=false
org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
org.eclipse.jdt.core.formatter.comment.indent_root_tags=false
org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=do not insert
org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
org.eclipse.jdt.core.formatter.comment.line_length=90
org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
org.eclipse.jdt.core.formatter.compact_else_if=true
org.eclipse.jdt.core.formatter.continuation_indentation=2
org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_empty_lines=false
org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
org.eclipse.jdt.core.formatter.indentation.size=8
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=insert
org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.join_lines_in_comments=true
org.eclipse.jdt.core.formatter.join_wrapped_lines=true
org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
org.eclipse.jdt.core.formatter.lineSplit=90
org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
org.eclipse.jdt.core.formatter.tabulation.char=tab
org.eclipse.jdt.core.formatter.tabulation.size=4
org.eclipse.jdt.core.formatter.use_on_off_tags=false
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true

File diff suppressed because one or more lines are too long

576
pom.xml
View File

@@ -1,295 +1,299 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Spring Cloud Netflix</name>
<description>Spring Cloud Netflix</description>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-build</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<relativePath/>
<!-- lookup parent from repository -->
</parent>
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-build</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<relativePath />
</parent>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Spring Cloud Netflix</name>
<description>Spring Cloud Netflix</description>
<scm>
<url>https://github.com/spring-cloud/spring-cloud-netflix</url>
<connection>scm:git:git://github.com/spring-cloud/spring-cloud-netflix.git</connection>
<developerConnection>scm:git:ssh://git@github.com/spring-cloud/spring-cloud-netflix.git</developerConnection>
<tag>HEAD</tag>
</scm>
<modules>
<module>spring-cloud-netflix-core</module>
<module>spring-cloud-netflix-hystrix-dashboard</module>
<module>spring-cloud-netflix-hystrix-amqp</module>
<module>spring-cloud-netflix-eureka-server</module>
<module>spring-cloud-netflix-turbine</module>
<module>spring-cloud-netflix-turbine-amqp</module>
<module>spring-cloud-netflix-sidecar</module>
<module>docs</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-core</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-eureka-server</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-hystrix-dashboard</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-hystrix-amqp</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-turbine</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-turbine-amqp</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-zuul-server</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.netflix.archaius</groupId>
<artifactId>archaius-core</artifactId>
<version>${archaius.version}</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.netflix.eureka</groupId>
<artifactId>eureka-client</artifactId>
<version>${eureka.version}</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.netflix.eureka</groupId>
<artifactId>eureka-core</artifactId>
<version>${eureka.version}</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
<exclusion>
<artifactId>log4j</artifactId>
<groupId>log4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-core</artifactId>
<version>${feign.version}</version>
</dependency>
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-ribbon</artifactId>
<version>${feign.version}</version>
<exclusions>
<exclusion>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-loadbalancer</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-slf4j</artifactId>
<version>${feign.version}</version>
</dependency>-->
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-core</artifactId>
<version>${hystrix.version}</version>
</dependency>
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-metrics-event-stream</artifactId>
<version>${hystrix.version}</version>
</dependency>
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-javanica</artifactId>
<version>${hystrix.version}</version>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon</artifactId>
<version>${ribbon.version}</version>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-core</artifactId>
<version>${ribbon.version}</version>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-httpclient</artifactId>
<version>${ribbon.version}</version>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-eureka</artifactId>
<version>${ribbon.version}</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.netflix.rxjava</groupId>
<artifactId>rxjava-core</artifactId>
<version>${netflix.rxjava.version}</version>
</dependency>
<dependency>
<groupId>com.netflix.zuul</groupId>
<artifactId>zuul-core</artifactId>
<version>${zuul.version}</version>
<exclusions>
<exclusion>
<artifactId>groovy-all</artifactId>
<groupId>org.codehaus.groovy</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-java-dsl</artifactId>
<version>${spring-integration-dsl.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.12.6</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
<version>1.13</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-core</artifactId>
<version>1.13</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.13</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>1.13</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>d3js</artifactId>
<version>3.4.11</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
</dependencies>
</dependencyManagement>
<properties>
<archaius.version>0.6.3</archaius.version>
<eureka.version>1.1.145</eureka.version>
<feign.version>6.1.3</feign.version>
<hystrix.version>1.4.0-RC5</hystrix.version>
<ribbon.version>2.0-RC13</ribbon.version>
<zuul.version>1.0.28</zuul.version>
<netflix.rxjava.version>0.20.7</netflix.rxjava.version>
<java.version>1.7</java.version>
<spring-integration-dsl.version>1.0.0.RELEASE</spring-integration-dsl.version>
<cloud-connectors.version>1.1.1.BUILD-SNAPSHOT</cloud-connectors.version>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<main.basedir>${basedir}</main.basedir>
<archaius.version>0.6.3</archaius.version>
<eureka.version>1.1.145</eureka.version>
<feign.version>6.1.3</feign.version>
<hystrix.version>1.4.0-RC5</hystrix.version>
<ribbon.version>2.0-RC13</ribbon.version>
<zuul.version>1.0.28</zuul.version>
<netflix.rxjava.version>0.20.7</netflix.rxjava.version>
<java.version>1.7</java.version>
<spring-integration-dsl.version>1.0.0.RELEASE</spring-integration-dsl.version>
<cloud-connectors.version>1.1.1.BUILD-SNAPSHOT</cloud-connectors.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<configuration>
<useProjectReferences>false</useProjectReferences>
<additionalConfig>
<file>
<name>.settings/org.eclipse.jdt.ui.prefs</name>
<location>${main.basedir}/eclipse/org.eclipse.jdt.ui.prefs</location>
</file>
<file>
<name>.settings/org.eclipse.jdt.core.prefs</name>
<location>${main.basedir}/eclipse/org.eclipse.jdt.core.prefs</location>
</file>
</additionalConfig>
</configuration>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-core</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-eureka-server</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-hystrix-dashboard</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-hystrix-amqp</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-turbine</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-turbine-amqp</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-zuul-server</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.netflix.archaius</groupId>
<artifactId>archaius-core</artifactId>
<version>${archaius.version}</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.netflix.eureka</groupId>
<artifactId>eureka-client</artifactId>
<version>${eureka.version}</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.netflix.eureka</groupId>
<artifactId>eureka-core</artifactId>
<version>${eureka.version}</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
<exclusion>
<artifactId>log4j</artifactId>
<groupId>log4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-core</artifactId>
<version>${feign.version}</version>
</dependency>
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-ribbon</artifactId>
<version>${feign.version}</version>
<exclusions>
<exclusion>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-loadbalancer</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--<dependency> <groupId>com.netflix.feign</groupId> <artifactId>feign-slf4j</artifactId>
<version>${feign.version}</version> </dependency> -->
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-core</artifactId>
<version>${hystrix.version}</version>
</dependency>
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-metrics-event-stream</artifactId>
<version>${hystrix.version}</version>
</dependency>
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-javanica</artifactId>
<version>${hystrix.version}</version>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon</artifactId>
<version>${ribbon.version}</version>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-core</artifactId>
<version>${ribbon.version}</version>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-httpclient</artifactId>
<version>${ribbon.version}</version>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-eureka</artifactId>
<version>${ribbon.version}</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.netflix.rxjava</groupId>
<artifactId>rxjava-core</artifactId>
<version>${netflix.rxjava.version}</version>
</dependency>
<dependency>
<groupId>com.netflix.zuul</groupId>
<artifactId>zuul-core</artifactId>
<version>${zuul.version}</version>
<exclusions>
<exclusion>
<artifactId>groovy-all</artifactId>
<groupId>org.codehaus.groovy</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-java-dsl</artifactId>
<version>${spring-integration-dsl.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.12.6</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
<version>1.13</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-core</artifactId>
<version>1.13</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.13</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>1.13</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>d3js</artifactId>
<version>3.4.11</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
</dependencies>
</dependencyManagement>
<modules>
<module>spring-cloud-netflix-core</module>
<module>spring-cloud-netflix-hystrix-dashboard</module>
<module>spring-cloud-netflix-hystrix-amqp</module>
<module>spring-cloud-netflix-eureka-server</module>
<module>spring-cloud-netflix-turbine</module>
<module>spring-cloud-netflix-turbine-amqp</module>
<module>spring-cloud-netflix-sidecar</module>
<module>docs</module>
</modules>
</project>

View File

@@ -2,19 +2,19 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-netflix-core</artifactId>
<packaging>jar</packaging>
<name>Spring Cloud Netflix Core</name>
<description>Spring Cloud Netflix Core</description>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>spring-cloud-netflix-core</artifactId>
<packaging>jar</packaging>
<name>Spring Cloud Netflix Core</name>
<description>Spring Cloud Netflix Core</description>
<properties>
<main.basedir>${basedir}/..</main.basedir>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
@@ -24,11 +24,11 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
@@ -68,10 +68,8 @@
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-ribbon</artifactId>
<optional>true</optional>
<optional>true</optional>
</dependency>
<!--<dependency> <groupId>com.netflix.feign</groupId> <artifactId>feign-slf4j</artifactId>
</dependency> -->
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-core</artifactId>
@@ -87,11 +85,11 @@
<artifactId>hystrix-javanica</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-core</artifactId>
@@ -102,27 +100,27 @@
<artifactId>ribbon-eureka</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-httpclient</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.netflix.zuul</groupId>
<artifactId>zuul-core</artifactId>
<optional>true</optional>
<exclusions>
<exclusion>
<artifactId>groovy-all</artifactId>
<groupId>org.codehaus.groovy</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.netflix.rxjava</groupId>
<artifactId>rxjava-core</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-httpclient</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.netflix.zuul</groupId>
<artifactId>zuul-core</artifactId>
<optional>true</optional>
<exclusions>
<exclusion>
<artifactId>groovy-all</artifactId>
<groupId>org.codehaus.groovy</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.netflix.rxjava</groupId>
<artifactId>rxjava-core</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
@@ -139,11 +137,9 @@
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -1,8 +1,26 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix;
/**
* @author Spencer Gibb
*/
public interface Constants {
String HYSTRIX_STREAM_NAME = "spring.cloud.hystrix.stream";
}

View File

@@ -1,12 +1,20 @@
package org.springframework.cloud.netflix.archaius;
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static com.netflix.config.ConfigurationBasedDeploymentContext.DEPLOYMENT_APPLICATION_ID_PROPERTY;
import static com.netflix.config.ConfigurationManager.APPLICATION_PROPERTIES;
import static com.netflix.config.ConfigurationManager.DISABLE_DEFAULT_ENV_CONFIG;
import static com.netflix.config.ConfigurationManager.DISABLE_DEFAULT_SYS_CONFIG;
import static com.netflix.config.ConfigurationManager.ENV_CONFIG_NAME;
import static com.netflix.config.ConfigurationManager.SYS_CONFIG_NAME;
import static com.netflix.config.ConfigurationManager.URL_CONFIG_NAME;
package org.springframework.cloud.netflix.archaius;
import java.lang.reflect.Field;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -31,6 +39,14 @@ import com.netflix.config.ConfigurationManager;
import com.netflix.config.DynamicPropertyFactory;
import com.netflix.config.DynamicURLConfiguration;
import static com.netflix.config.ConfigurationBasedDeploymentContext.DEPLOYMENT_APPLICATION_ID_PROPERTY;
import static com.netflix.config.ConfigurationManager.APPLICATION_PROPERTIES;
import static com.netflix.config.ConfigurationManager.DISABLE_DEFAULT_ENV_CONFIG;
import static com.netflix.config.ConfigurationManager.DISABLE_DEFAULT_SYS_CONFIG;
import static com.netflix.config.ConfigurationManager.ENV_CONFIG_NAME;
import static com.netflix.config.ConfigurationManager.SYS_CONFIG_NAME;
import static com.netflix.config.ConfigurationManager.URL_CONFIG_NAME;
/**
* @author Spencer Gibb
*/
@@ -40,6 +56,7 @@ public class ArchaiusAutoConfiguration {
private static final Logger logger = LoggerFactory
.getLogger(ArchaiusAutoConfiguration.class);
private static final AtomicBoolean initialized = new AtomicBoolean(false);
@Autowired
@@ -57,7 +74,7 @@ public class ArchaiusAutoConfiguration {
@Bean
public ConfigurableEnvironmentConfiguration configurableEnvironmentConfiguration() {
ConfigurableEnvironmentConfiguration envConfig = new ConfigurableEnvironmentConfiguration(
env);
this.env);
configureArchaius(envConfig);
return envConfig;
}
@@ -74,7 +91,7 @@ public class ArchaiusAutoConfiguration {
@SuppressWarnings("deprecation")
protected void configureArchaius(ConfigurableEnvironmentConfiguration envConfig) {
if (initialized.compareAndSet(false, true)) {
String appName = env.getProperty("spring.application.name");
String appName = this.env.getProperty("spring.application.name");
if (appName == null) {
appName = "application";
logger.warn("No spring.application.name found, defaulting to 'application'");
@@ -101,8 +118,8 @@ public class ArchaiusAutoConfiguration {
try {
config.addConfiguration(defaultURLConfig, URL_CONFIG_NAME);
}
catch (Throwable e) {
logger.error("Cannot create config from " + defaultURLConfig, e);
catch (Throwable ex) {
logger.error("Cannot create config from " + defaultURLConfig, ex);
}
// TODO: sys/env above urls?

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.archaius;
import org.apache.commons.configuration.AbstractConfiguration;
@@ -23,15 +24,16 @@ import com.netflix.config.ConfigurationManager;
/**
* @author Dave Syer
*
*/
public class ArchaiusDelegatingProxyUtils {
public static String APPLICATION_CONTEXT = ApplicationContext.class.getName();
public static <T> T getNamedInstance(Class<T> type, String name) {
ApplicationContext context = (ApplicationContext) ConfigurationManager.getConfigInstance().getProperty(APPLICATION_CONTEXT);
return context!=null && context.containsBean(name) ? context.getBean(name, type) : null;
ApplicationContext context = (ApplicationContext) ConfigurationManager
.getConfigInstance().getProperty(APPLICATION_CONTEXT);
return context != null && context.containsBean(name) ? context
.getBean(name, type) : null;
}
public static <T> T getInstanceWithPrefix(Class<T> type, String prefix) {
@@ -41,7 +43,7 @@ public class ArchaiusDelegatingProxyUtils {
public static void addApplicationContext(ConfigurableApplicationContext context) {
AbstractConfiguration config = ConfigurationManager.getConfigInstance();
config .clearProperty(APPLICATION_CONTEXT);
config.clearProperty(APPLICATION_CONTEXT);
config.setProperty(APPLICATION_CONTEXT, context);
}

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.archaius;
import java.util.Iterator;
@@ -30,7 +31,6 @@ import com.netflix.config.ConfigurationManager;
/**
* @author Dave Syer
*
*/
public class ArchaiusEndpoint extends AbstractEndpoint<Map<String, Object>> {

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.archaius;
import java.util.ArrayList;
@@ -18,73 +34,69 @@ import org.springframework.core.env.StandardEnvironment;
* @author Spencer Gibb
*/
public class ConfigurableEnvironmentConfiguration extends AbstractConfiguration {
ConfigurableEnvironment environment;
public ConfigurableEnvironmentConfiguration(ConfigurableEnvironment environment) {
this.environment = environment;
}
private final ConfigurableEnvironment environment;
@Override
protected void addPropertyDirect(String key, Object value) {
public ConfigurableEnvironmentConfiguration(ConfigurableEnvironment environment) {
this.environment = environment;
}
}
@Override
protected void addPropertyDirect(String key, Object value) {
@Override
public boolean isEmpty() {
return !getKeys().hasNext(); //TODO: find a better way to do this
}
}
@Override
public boolean containsKey(String key) {
return environment.containsProperty(key);
}
@Override
public boolean isEmpty() {
return !getKeys().hasNext(); // TODO: find a better way to do this
}
@Override
public Object getProperty(String key) {
return environment.getProperty(key);
}
@Override
public boolean containsKey(String key) {
return this.environment.containsProperty(key);
}
@Override
public Iterator<String> getKeys() {
List<String> result = new ArrayList<>();
for (Map.Entry<String, PropertySource<?>> entry : getPropertySources().entrySet()) {
PropertySource<?> source = entry.getValue();
if (source instanceof EnumerablePropertySource) {
EnumerablePropertySource<?> enumerable = (EnumerablePropertySource<?>) source;
for (String name : enumerable.getPropertyNames()) {
result.add(name);
}
}
}
return result.iterator();
}
@Override
public Object getProperty(String key) {
return this.environment.getProperty(key);
}
private Map<String, PropertySource<?>> getPropertySources() {
Map<String, PropertySource<?>> map = new LinkedHashMap<>();
MutablePropertySources sources;
if (this.environment != null
&& this.environment instanceof ConfigurableEnvironment) {
sources = this.environment.getPropertySources();
}
else {
sources = new StandardEnvironment().getPropertySources();
}
for (PropertySource<?> source : sources) {
extract("", map, source);
}
return map;
}
@Override
public Iterator<String> getKeys() {
List<String> result = new ArrayList<>();
for (Map.Entry<String, PropertySource<?>> entry : getPropertySources().entrySet()) {
PropertySource<?> source = entry.getValue();
if (source instanceof EnumerablePropertySource) {
EnumerablePropertySource<?> enumerable = (EnumerablePropertySource<?>) source;
for (String name : enumerable.getPropertyNames()) {
result.add(name);
}
}
}
return result.iterator();
}
private void extract(String root, Map<String, PropertySource<?>> map,
PropertySource<?> source) {
if (source instanceof CompositePropertySource) {
for (PropertySource<?> nest : ((CompositePropertySource) source).getPropertySources()) {
extract(source.getName() + ":", map, nest);
}
}
else {
map.put(root + source.getName(), source);
}
}
private Map<String, PropertySource<?>> getPropertySources() {
Map<String, PropertySource<?>> map = new LinkedHashMap<>();
MutablePropertySources sources = (this.environment != null ? this.environment
.getPropertySources() : new StandardEnvironment().getPropertySources());
for (PropertySource<?> source : sources) {
extract("", map, source);
}
return map;
}
private void extract(String root, Map<String, PropertySource<?>> map,
PropertySource<?> source) {
if (source instanceof CompositePropertySource) {
for (PropertySource<?> nest : ((CompositePropertySource) source)
.getPropertySources()) {
extract(source.getName() + ":", map, nest);
}
}
else {
map.put(root + source.getName(), source);
}
}
}

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.config;
import lombok.extern.slf4j.Slf4j;
@@ -37,9 +38,8 @@ import com.netflix.discovery.DiscoveryClient;
/**
* Bootstrap configuration for a config client that wants to lookup the config server via
* discovery.
*
* @author Dave Syer
*
* @author Dave Syer
*/
@ConditionalOnClass({ DiscoveryClient.class, ConfigServicePropertySourceLocator.class })
@ConditionalOnExpression("${spring.cloud.config.discovery.enabled:false}")
@@ -65,27 +65,27 @@ public class DiscoveryClientConfigServiceBootstrapConfiguration implements
log.info("Environment is not ConfigurableEnvironment so cannot look up configserver");
return;
}
InstanceInfo server = client.getNextServerFromEureka(config.getDiscovery()
.getServiceId(), false);
InstanceInfo server = this.client.getNextServerFromEureka(this.config
.getDiscovery().getServiceId(), false);
String url = server.getHomePageUrl();
if (server.getMetadata().containsKey("password")) {
String user = server.getMetadata().get("user");
user = user == null ? "user" : user;
config.setUsername(user);
this.config.setUsername(user);
String password = server.getMetadata().get("password");
config.setPassword(password);
this.config.setPassword(password);
}
if (server.getMetadata().containsKey("configPath")) {
String path = server.getMetadata().get("configPath");
if (url.endsWith("/") && path.startsWith("/")) {
url = url.substring(0, url.length()-1);
url = url.substring(0, url.length() - 1);
}
url = url + path;
}
config.setUri(url);
this.config.setUri(url);
}
catch (Exception e) {
log.warn("Could not locate configserver via discovery", e);
catch (Exception ex) {
log.warn("Could not locate configserver via discovery", ex);
}
}

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.config;
import javax.annotation.PostConstruct;
@@ -29,29 +30,30 @@ import com.netflix.discovery.DiscoveryClient;
/**
* Extra configuration for config server if it happens to be a Eureka instance.
* @author Dave Syer
*
* @author Dave Syer
*/
@Configuration
@EnableConfigurationProperties
@ConditionalOnClass({EurekaInstanceConfigBean.class, DiscoveryClient.class, ConfigServerProperties.class})
@ConditionalOnClass({ EurekaInstanceConfigBean.class, DiscoveryClient.class,
ConfigServerProperties.class })
public class EurekaClientConfigServerAutoConfiguration {
@Autowired(required=false)
@Autowired(required = false)
private EurekaInstanceConfigBean instance;
@Autowired(required=false)
@Autowired(required = false)
private ConfigServerProperties server;
@PostConstruct
public void init() {
if (instance==null || server==null) {
if (this.instance == null || this.server == null) {
return;
}
String prefix = server.getPrefix();
String prefix = this.server.getPrefix();
if (StringUtils.hasText(prefix)) {
instance.getMetadataMap().put("configPath", prefix);
this.instance.getMetadataMap().put("configPath", prefix);
}
}
}

View File

@@ -1,5 +1,25 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.endpoint;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.actuate.endpoint.Endpoint;
@@ -11,66 +31,63 @@ import org.springframework.web.context.ServletContextAware;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.ServletWrappingController;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* TODO: move to spring-boot?
* User: spencergibb
* Date: 4/24/14
* Time: 9:13 PM
*/
public abstract class ServletWrappingEndpoint implements InitializingBean,
ApplicationContextAware, ServletContextAware, MvcEndpoint {
ApplicationContextAware, ServletContextAware, MvcEndpoint {
protected String path;
protected boolean sensitive;
protected boolean enabled = true;
// TODO: move to spring-boot?
protected final ServletWrappingController controller = new ServletWrappingController();
protected String path;
@Override
public void afterPropertiesSet() throws Exception {
this.controller.afterPropertiesSet();
}
protected boolean sensitive;
@Override
public void setServletContext(ServletContext servletContext) {
this.controller.setServletContext(servletContext);
}
protected boolean enabled = true;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.controller.setApplicationContext(applicationContext);
}
protected final ServletWrappingController controller = new ServletWrappingController();
protected ServletWrappingEndpoint(Class<?> servletClass, String servletName, String path,
boolean sensitive, boolean enabled) {
controller.setServletClass(servletClass);
controller.setServletName(servletName);
this.path = path;
this.sensitive = sensitive;
this.enabled = enabled;
}
@Override
public void afterPropertiesSet() throws Exception {
this.controller.afterPropertiesSet();
}
@RequestMapping("**")
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response) throws Exception {
return this.controller.handleRequest(request, response);
}
@Override
public void setServletContext(ServletContext servletContext) {
this.controller.setServletContext(servletContext);
}
@Override
public String getPath() {
return path;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.controller.setApplicationContext(applicationContext);
}
@Override
public boolean isSensitive() {
return sensitive;
}
protected ServletWrappingEndpoint(Class<?> servletClass, String servletName,
String path, boolean sensitive, boolean enabled) {
this.controller.setServletClass(servletClass);
this.controller.setServletName(servletName);
this.path = path;
this.sensitive = sensitive;
this.enabled = enabled;
}
@RequestMapping("**")
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response)
throws Exception {
return this.controller.handleRequest(request, response);
}
@Override
public String getPath() {
return this.path;
}
@Override
public boolean isSensitive() {
return this.sensitive;
}
@Override
public Class<? extends Endpoint<?>> getEndpointType() {
return null;
}
@Override
public Class<? extends Endpoint<?>> getEndpointType() {
return null;
}
}

View File

@@ -13,8 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.eureka;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.cloud.client.discovery.DiscoveryHeartbeatEvent;
import org.springframework.context.ApplicationContext;
import com.netflix.appinfo.DataCenterInfo;
import com.netflix.appinfo.DataCenterInfo.Name;
import com.netflix.appinfo.InstanceInfo;
@@ -23,17 +32,15 @@ import com.netflix.discovery.converters.Converters.ApplicationsConverter;
import com.netflix.discovery.converters.Converters.InstanceInfoConverter;
import com.netflix.discovery.shared.Applications;
import com.thoughtworks.xstream.MarshallingStrategy;
import com.thoughtworks.xstream.converters.*;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.ConverterLookup;
import com.thoughtworks.xstream.converters.DataHolder;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.core.TreeMarshallingStrategy;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.mapper.Mapper;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.cloud.client.discovery.DiscoveryHeartbeatEvent;
import org.springframework.context.ApplicationContext;
/**
* A special purpose wrapper for an XStream TreeMarshallingStrategy that is aware of the
@@ -44,13 +51,13 @@ import org.springframework.context.ApplicationContext;
* is useful when not running Eureka in bare EC2 VMs, so the EC2 metadata is not available
* for uniquely identifying the InstanceInfo (the default is to just use the hostname, but
* that isn't very useful when sitting behind a proxy).
*
* @author Dave Syer
*
* @author Dave Syer
*/
public class DataCenterAwareMarshallingStrategy implements MarshallingStrategy {
private TreeMarshallingStrategy delegate = new TreeMarshallingStrategy();
private ApplicationContext context;
public DataCenterAwareMarshallingStrategy(ApplicationContext context) {
@@ -60,15 +67,17 @@ public class DataCenterAwareMarshallingStrategy implements MarshallingStrategy {
@Override
public Object unmarshal(Object root, HierarchicalStreamReader reader,
DataHolder dataHolder, ConverterLookup converterLookup, Mapper mapper) {
ConverterLookup wrapped = new DataCenterAwareConverterLookup(converterLookup, context);
return delegate.unmarshal(root, reader, dataHolder, wrapped, mapper);
ConverterLookup wrapped = new DataCenterAwareConverterLookup(converterLookup,
this.context);
return this.delegate.unmarshal(root, reader, dataHolder, wrapped, mapper);
}
@Override
public void marshal(HierarchicalStreamWriter writer, Object obj,
ConverterLookup converterLookup, Mapper mapper, DataHolder dataHolder) {
ConverterLookup wrapped = new DataCenterAwareConverterLookup(converterLookup, context);
delegate.marshal(writer, obj, wrapped, mapper, dataHolder);
ConverterLookup wrapped = new DataCenterAwareConverterLookup(converterLookup,
this.context);
this.delegate.marshal(writer, obj, wrapped, mapper, dataHolder);
}
public static class InstanceIdDataCenterInfo implements DataCenterInfo,
@@ -87,7 +96,7 @@ public class DataCenterAwareMarshallingStrategy implements MarshallingStrategy {
@Override
public String getId() {
return instanceId;
return this.instanceId;
}
}
@@ -95,20 +104,23 @@ public class DataCenterAwareMarshallingStrategy implements MarshallingStrategy {
private static class DataCenterAwareConverterLookup implements ConverterLookup {
private ConverterLookup delegate;
private ApplicationContext context;
public DataCenterAwareConverterLookup(ConverterLookup delegate, ApplicationContext context) {
public DataCenterAwareConverterLookup(ConverterLookup delegate,
ApplicationContext context) {
this.delegate = delegate;
this.context = context;
}
@Override
public Converter lookupConverterForType(@SuppressWarnings("rawtypes") Class type) {
Converter converter = delegate.lookupConverterForType(type);
Converter converter = this.delegate.lookupConverterForType(type);
if (InstanceInfo.class == type) {
return new DataCenterAwareConverter();
} else if (Applications.class == type) {
return new PublishingApplicationsConverter(context);
}
else if (Applications.class == type) {
return new PublishingApplicationsConverter(this.context);
}
return converter;
}
@@ -124,7 +136,8 @@ public class DataCenterAwareMarshallingStrategy implements MarshallingStrategy {
}
@Override
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext unmarshallingContext) {
public Object unmarshal(HierarchicalStreamReader reader,
UnmarshallingContext unmarshallingContext) {
Object obj = super.unmarshal(reader, unmarshallingContext);
ProxyFactory factory = new ProxyFactory(obj);
@@ -135,6 +148,7 @@ public class DataCenterAwareMarshallingStrategy implements MarshallingStrategy {
@Slf4j
private static class SetVersionInterceptor implements MethodInterceptor {
private ApplicationContext context;
public SetVersionInterceptor(ApplicationContext context) {
@@ -147,14 +161,16 @@ public class DataCenterAwareMarshallingStrategy implements MarshallingStrategy {
if ("setVersion".equals(invocation.getMethod().getName())) {
Long version = Long.class.cast(invocation.getArguments()[0]);
log.debug("Applications.setVersion() called with version: " + version);
context.publishEvent(new DiscoveryHeartbeatEvent(invocation.getThis(), version));
this.context.publishEvent(new DiscoveryHeartbeatEvent(invocation
.getThis(), version));
}
return ret;
}
}
private static class DataCenterAwareConverter extends InstanceInfoConverter {
@Override
public void marshal(Object source, HierarchicalStreamWriter writer,
MarshallingContext context) {

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.eureka;
import org.springframework.beans.factory.annotation.Autowired;
@@ -11,16 +27,17 @@ import com.netflix.discovery.EurekaClientConfig;
*/
public class DiscoveryManagerInitializer {
@Autowired
private EurekaClientConfig clientConfig;
@Autowired
private EurekaClientConfig clientConfig;
@Autowired
private EurekaInstanceConfig instanceConfig;
@Autowired
private EurekaInstanceConfig instanceConfig;
public synchronized void init() {
if (DiscoveryManager.getInstance().getDiscoveryClient() == null) {
DiscoveryManager.getInstance().initComponent(this.instanceConfig,
this.clientConfig);
}
}
public synchronized void init() {
if (DiscoveryManager.getInstance().getDiscoveryClient() == null) {
DiscoveryManager.getInstance().initComponent(instanceConfig, clientConfig);
}
}
}

View File

@@ -1,9 +1,21 @@
package org.springframework.cloud.netflix.eureka;
/**
* @author Spencer Gibb
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.eureka;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
@@ -19,9 +31,9 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
* it is Eureka you want. All it does is turn on discovery and let the autoconfiguration
* find the eureka classes if they are available (i.e. you need Eureka on the classpath as
* well).
*
* @author Dave Syer
*
* @author Dave Syer
* @author Spencer Gibb
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@@ -29,4 +41,5 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@Inherited
@EnableDiscoveryClient
public @interface EnableEurekaClient {
}

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.eureka;
import javax.annotation.PostConstruct;
@@ -33,7 +34,6 @@ import com.netflix.discovery.converters.XmlXStream;
/**
* @author Dave Syer
*
*/
@Configuration
@EnableConfigurationProperties
@@ -47,9 +47,9 @@ public class EurekaClientAutoConfiguration {
@PostConstruct
public void init() {
XmlXStream.getInstance().setMarshallingStrategy(
new DataCenterAwareMarshallingStrategy(context));
new DataCenterAwareMarshallingStrategy(this.context));
JsonXStream.getInstance().setMarshallingStrategy(
new DataCenterAwareMarshallingStrategy(context));
new DataCenterAwareMarshallingStrategy(this.context));
}
@Bean
@@ -64,5 +64,4 @@ public class EurekaClientAutoConfiguration {
return new EurekaInstanceConfigBean();
}
}

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.eureka;
import java.util.ArrayList;
@@ -29,18 +30,18 @@ import com.netflix.discovery.EurekaClientConfig;
/**
* @author Dave Syer
*
*/
@Data
@ConfigurationProperties("eureka.client")
public class EurekaClientConfigBean implements EurekaClientConfig {
public static final String DEFAULT_URL = "http://localhost:8761" + EurekaServerConfigBean.DEFAULT_PREFIX + "/";
public static final String DEFAULT_URL = "http://localhost:8761"
+ EurekaServerConfigBean.DEFAULT_PREFIX + "/";
public static final String DEFAULT_ZONE = "defaultZone";
private static final int MINUTES = 60;
private boolean enabled = true;
private int registryFetchIntervalSeconds = 30;
@@ -55,9 +56,9 @@ public class EurekaClientConfigBean implements EurekaClientConfig {
private String proxyHost;
private String proxyUserName;
private String proxyUserName;
private String proxyPassword;
private String proxyPassword;
private int eurekaServerReadTimeoutSeconds = 8;
@@ -83,16 +84,15 @@ public class EurekaClientConfigBean implements EurekaClientConfig {
private int heartbeatExecutorThreadPoolSize = 2;
private int heartbeatExecutorExponentialBackOffBound = 10;
private int heartbeatExecutorExponentialBackOffBound = 10;
private int cacheRefreshExecutorThreadPoolSize = 2;
private int cacheRefreshExecutorExponentialBackOffBound = 10;
private int cacheRefreshExecutorExponentialBackOffBound = 10;
private Map<String,String> serviceUrl = new HashMap<String, String>();
private Map<String, String> serviceUrl = new HashMap<String, String>();
{
serviceUrl.put(DEFAULT_ZONE, DEFAULT_URL);
this.serviceUrl.put(DEFAULT_ZONE, DEFAULT_URL);
}
private boolean gZipContent = true;
@@ -117,43 +117,43 @@ public class EurekaClientConfigBean implements EurekaClientConfig {
@Override
public boolean shouldGZipContent() {
return gZipContent;
return this.gZipContent;
}
@Override
public boolean shouldUseDnsForFetchingServiceUrls() {
return useDnsForFetchingServiceUrls;
return this.useDnsForFetchingServiceUrls;
}
@Override
public boolean shouldRegisterWithEureka() {
return registerWithEureka;
return this.registerWithEureka;
}
@Override
public boolean shouldPreferSameZoneEureka() {
return preferSameZoneEureka;
return this.preferSameZoneEureka;
}
@Override
public boolean shouldLogDeltaDiff() {
return logDeltaDiff;
return this.logDeltaDiff;
}
@Override
public boolean shouldDisableDelta() {
return disableDelta;
return this.disableDelta;
}
@Override
public String fetchRegistryForRemoteRegions() {
return fetchRemoteRegionsRegistry;
return this.fetchRemoteRegionsRegistry;
}
@Override
public String[] getAvailabilityZones(String region) {
String value = availabilityZones.get(region);
if (value==null) {
String value = this.availabilityZones.get(region);
if (value == null) {
value = DEFAULT_ZONE;
}
return value.split(",");
@@ -161,25 +161,25 @@ public class EurekaClientConfigBean implements EurekaClientConfig {
@Override
public List<String> getEurekaServerServiceUrls(String myZone) {
String serviceUrls = serviceUrl.get(myZone);
if (serviceUrls == null || serviceUrls.isEmpty()) {
serviceUrls = serviceUrl.get(DEFAULT_ZONE);
}
if (serviceUrls != null) {
return Arrays.asList(serviceUrls.split(","));
}
String serviceUrls = this.serviceUrl.get(myZone);
if (serviceUrls == null || serviceUrls.isEmpty()) {
serviceUrls = this.serviceUrl.get(DEFAULT_ZONE);
}
if (serviceUrls != null) {
return Arrays.asList(serviceUrls.split(","));
}
return new ArrayList<>();
return new ArrayList<>();
}
@Override
public boolean shouldFilterOnlyUpInstances() {
return filterOnlyUpInstances;
return this.filterOnlyUpInstances;
}
@Override
public boolean shouldFetchRegistry() {
return fetchRegistry;
return this.fetchRegistry;
}
}

View File

@@ -1,20 +1,40 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.eureka;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import com.google.common.base.Function;
import com.google.common.base.Predicates;
import com.google.common.collect.Lists;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.shared.Application;
import com.netflix.discovery.shared.Applications;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.List;
import static com.google.common.collect.Iterables.*;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform;
/**
* @author Spencer Gibb
@@ -24,10 +44,10 @@ public class EurekaDiscoveryClient implements DiscoveryClient {
public static final String DESCRIPTION = "Spring Cloud Eureka Discovery Client";
@Autowired
private EurekaInstanceConfigBean config;
private EurekaInstanceConfigBean config;
@Autowired
private com.netflix.discovery.DiscoveryClient discovery;
@Autowired
private com.netflix.discovery.DiscoveryClient discovery;
@Override
public String description() {
@@ -35,96 +55,104 @@ public class EurekaDiscoveryClient implements DiscoveryClient {
}
@Override
public ServiceInstance getLocalServiceInstance() {
return new ServiceInstance() {
@Override
public String getServiceId() {
return config.getAppname();
}
public ServiceInstance getLocalServiceInstance() {
return new ServiceInstance() {
@Override
public String getServiceId() {
return EurekaDiscoveryClient.this.config.getAppname();
}
@Override
public String getHost() {
return config.getHostname();
}
@Override
public String getHost() {
return EurekaDiscoveryClient.this.config.getHostname();
}
@Override
public int getPort() {
return config.getNonSecurePort();
}
};
}
@Override
public int getPort() {
return EurekaDiscoveryClient.this.config.getNonSecurePort();
}
};
}
@Override
public List<ServiceInstance> getInstances(String serviceId) {
List<InstanceInfo> infos = discovery.getInstancesByVipAddress(serviceId, false);
Iterable<ServiceInstance> instances = transform(infos, new Function<InstanceInfo, ServiceInstance>() {
@Nullable
@Override
public ServiceInstance apply(@Nullable InstanceInfo info) {
return new EurekaServiceInstance(info);
}
});
return Lists.newArrayList(instances);
}
@Override
public List<ServiceInstance> getInstances(String serviceId) {
List<InstanceInfo> infos = this.discovery.getInstancesByVipAddress(serviceId,
false);
Iterable<ServiceInstance> instances = transform(infos,
new Function<InstanceInfo, ServiceInstance>() {
@Nullable
@Override
public ServiceInstance apply(@Nullable InstanceInfo info) {
return new EurekaServiceInstance(info);
}
});
return Lists.newArrayList(instances);
}
static class EurekaServiceInstance implements ServiceInstance {
InstanceInfo instance;
static class EurekaServiceInstance implements ServiceInstance {
InstanceInfo instance;
EurekaServiceInstance(InstanceInfo instance) {
this.instance = instance;
}
EurekaServiceInstance(InstanceInfo instance) {
this.instance = instance;
}
@Override
public String getServiceId() {
return instance.getAppName();
}
@Override
public String getServiceId() {
return this.instance.getAppName();
}
@Override
public String getHost() {
return instance.getHostName();
}
@Override
public String getHost() {
return this.instance.getHostName();
}
@Override
public int getPort() {
return instance.getPort();
}
}
@Override
public int getPort() {
return this.instance.getPort();
}
}
@Override
public List<String> getServices() {
Applications applications = discovery.getApplications();
if (applications == null) {
return Collections.emptyList();
}
return Lists.newArrayList(filter(transform(applications.getRegisteredApplications(), new Function<Application, String>() {
@Nullable
@Override
public String apply(@Nullable Application app) {
if (app.getInstances().isEmpty()) {
return null;
}
return app.getName().toLowerCase();
}
}), Predicates.notNull()));
}
@Override
public List<String> getServices() {
Applications applications = this.discovery.getApplications();
if (applications == null) {
return Collections.emptyList();
}
return Lists.newArrayList(filter(
transform(applications.getRegisteredApplications(),
new Function<Application, String>() {
@Nullable
@Override
public String apply(@Nullable Application app) {
if (app.getInstances().isEmpty()) {
return null;
}
return app.getName().toLowerCase();
}
}), Predicates.notNull()));
}
@Override
public List<ServiceInstance> getAllInstances() {
Applications applications = this.discovery.getApplications();
if (applications == null) {
return Collections.emptyList();
}
Iterable<ServiceInstance> instances = transform(
concat(transform(applications.getRegisteredApplications(),
new Function<Application, List<InstanceInfo>>() {
@Override
public List<InstanceInfo> apply(@Nullable Application app) {
return app.getInstances();
}
})), new Function<InstanceInfo, ServiceInstance>() {
@Nullable
@Override
public ServiceInstance apply(@Nullable InstanceInfo info) {
return new EurekaServiceInstance(info);
}
});
return Lists.newArrayList(instances);
}
@Override
public List<ServiceInstance> getAllInstances() {
Applications applications = discovery.getApplications();
if (applications == null) {
return Collections.emptyList();
}
Iterable<ServiceInstance> instances = transform(concat(transform(applications.getRegisteredApplications(), new Function<Application, List<InstanceInfo>>() {
public List<InstanceInfo> apply(@Nullable Application app) {
return app.getInstances();
}
})), new Function<InstanceInfo, ServiceInstance>() {
@Nullable
@Override
public ServiceInstance apply(@Nullable InstanceInfo info) {
return new EurekaServiceInstance(info);
}
});
return Lists.newArrayList(instances);
}
}

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.eureka;
import java.lang.reflect.Field;
@@ -55,7 +56,6 @@ import com.netflix.discovery.shared.EurekaJerseyClient;
/**
* @author Dave Syer
*
*/
@Configuration
@EnableConfigurationProperties
@@ -84,7 +84,8 @@ public class EurekaDiscoveryClientConfiguration implements SmartLifecycle, Order
@PreDestroy
public void close() {
closeDiscoveryClientJersey();
logger.info("Removing application {} from eureka", instanceConfig.getAppname());
logger.info("Removing application {} from eureka",
this.instanceConfig.getAppname());
DiscoveryManager.getInstance().shutdownComponent();
}
@@ -103,8 +104,8 @@ public class EurekaDiscoveryClientConfiguration implements SmartLifecycle, Order
jerseyClient.destroyResources();
}
}
catch (Exception e) {
logger.error("Error closing DiscoveryClient.jerseyClient", e);
catch (Exception ex) {
logger.error("Error closing DiscoveryClient.jerseyClient", ex);
}
}
}
@@ -112,25 +113,27 @@ public class EurekaDiscoveryClientConfiguration implements SmartLifecycle, Order
@Override
public void start() {
// only set the port if the nonSecurePort is 0 and this.port != 0
if (port.get() != 0 && instanceConfig.getNonSecurePort() == 0) {
instanceConfig.setNonSecurePort(port.get());
if (this.port.get() != 0 && this.instanceConfig.getNonSecurePort() == 0) {
this.instanceConfig.setNonSecurePort(this.port.get());
}
// only initialize if nonSecurePort is greater than 0 and it isn't already running
// because of containerPortInitializer below
if (!running.get() && instanceConfig.getNonSecurePort() > 0) {
if (!this.running.get() && this.instanceConfig.getNonSecurePort() > 0) {
discoveryManagerIntitializer().init();
logger.info("Registering application {} with eureka with status {}",
instanceConfig.getAppname(), instanceConfig.getInitialStatus());
this.instanceConfig.getAppname(),
this.instanceConfig.getInitialStatus());
ApplicationInfoManager.getInstance().setInstanceStatus(
instanceConfig.getInitialStatus());
this.instanceConfig.getInitialStatus());
if (healthCheckHandler != null) {
if (this.healthCheckHandler != null) {
DiscoveryManager.getInstance().getDiscoveryClient()
.registerHealthCheck(healthCheckHandler);
.registerHealthCheck(this.healthCheckHandler);
}
context.publishEvent(new InstanceRegisteredEvent<>(this, instanceConfig));
running.set(true);
this.context.publishEvent(new InstanceRegisteredEvent<>(this,
this.instanceConfig));
this.running.set(true);
}
}
@@ -138,15 +141,15 @@ public class EurekaDiscoveryClientConfiguration implements SmartLifecycle, Order
public void stop() {
logger.info(
"Unregistering application {} with eureka with status OUT_OF_SERVICE",
instanceConfig.getAppname());
this.instanceConfig.getAppname());
ApplicationInfoManager.getInstance().setInstanceStatus(
InstanceStatus.OUT_OF_SERVICE);
running.set(false);
this.running.set(false);
}
@Override
public boolean isRunning() {
return running.get();
return this.running.get();
}
@Override
@@ -166,7 +169,7 @@ public class EurekaDiscoveryClientConfiguration implements SmartLifecycle, Order
@Override
public int getOrder() {
return order;
return this.order;
}
@Bean
@@ -214,4 +217,5 @@ public class EurekaDiscoveryClientConfiguration implements SmartLifecycle, Order
return new EurekaHealthIndicator(eurekaDiscoveryClient, metrics, config);
}
}
}

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.eureka;
import java.util.Collections;
@@ -24,27 +25,26 @@ import org.springframework.boot.actuate.health.Health.Builder;
import org.springframework.boot.actuate.health.Status;
import org.springframework.boot.actuate.metrics.Metric;
import org.springframework.boot.actuate.metrics.reader.MetricReader;
import org.springframework.cloud.client.discovery.DiscoveryHealthIndicator;
import com.netflix.appinfo.EurekaInstanceConfig;
import com.netflix.discovery.DiscoveryClient;
import com.netflix.discovery.shared.Application;
import com.netflix.discovery.shared.Applications;
import org.springframework.cloud.client.discovery.DiscoveryHealthIndicator;
/**
* @author Dave Syer
*
*/
public class EurekaHealthIndicator implements DiscoveryHealthIndicator {
private EurekaInstanceConfig instanceConfig;
private final DiscoveryClient discovery;
private MetricReader metrics;
private final MetricReader metrics;
private final EurekaInstanceConfig instanceConfig;
private int failCount = 0;
private DiscoveryClient discovery;
public EurekaHealthIndicator(DiscoveryClient discovery, MetricReader metrics,
EurekaInstanceConfig instanceConfig) {
super();
@@ -67,28 +67,29 @@ public class EurekaHealthIndicator implements DiscoveryHealthIndicator {
}
private Status getStatus(Builder builder) {
Status status = new Status(discovery.getInstanceRemoteStatus().toString(),
Status status = new Status(this.discovery.getInstanceRemoteStatus().toString(),
"Remote status from Eureka server");
@SuppressWarnings("unchecked")
Metric<Number> value = (Metric<Number>) metrics
Metric<Number> value = (Metric<Number>) this.metrics
.findOne("counter.servo.discoveryclient_failed");
if (value != null) {
int renewalPeriod = instanceConfig.getLeaseRenewalIntervalInSeconds();
int renewalPeriod = this.instanceConfig.getLeaseRenewalIntervalInSeconds();
int latest = value.getValue().intValue();
builder.withDetail("failCount", latest);
builder.withDetail("renewalPeriod", renewalPeriod);
if (failCount < latest) {
if (this.failCount < latest) {
status = new Status("UP", "Eureka discovery client is reporting failures");
failCount = latest;
} else {
status = new Status("UP", "No new failures in Eureka discovery client");
this.failCount = latest;
}
else {
status = new Status("UP", "No new failures in Eureka discovery client");
}
}
return status;
}
private Map<String, Object> getApplications() {
Applications applications = discovery.getApplications();
Applications applications = this.discovery.getApplications();
if (applications == null) {
return Collections.emptyMap();
}

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.eureka;
import java.net.InetAddress;
@@ -37,104 +38,109 @@ import com.netflix.appinfo.UniqueIdentifier;
/**
* @author Dave Syer
*
*/
@Data
@ConfigurationProperties("eureka.instance")
public class EurekaInstanceConfigBean implements EurekaInstanceConfig {
private static final Log logger = LogFactory.getLog(EurekaInstanceConfigBean.class);
@Getter(AccessLevel.PRIVATE) @Setter(AccessLevel.PRIVATE)
@Getter(AccessLevel.PRIVATE)
@Setter(AccessLevel.PRIVATE)
private String[] hostInfo = initHostInfo();
@Value("${spring.application.name:unknown}")
private String appname = "unknown";
private String appname = "unknown";
private String appGroupName;
private boolean instanceEnabledOnit;
private String appGroupName;
private boolean instanceEnabledOnit;
@Value("${server.port:${SERVER_PORT:${PORT:8080}}}")
private int nonSecurePort = 80;
private int nonSecurePort = 80;
private int securePort = 443;
private int securePort = 443;
private boolean nonSecurePortEnabled = true;
private boolean nonSecurePortEnabled = true;
private boolean securePortEnabled;
private boolean securePortEnabled;
private int leaseRenewalIntervalInSeconds = 30;
private int leaseRenewalIntervalInSeconds = 30;
private int leaseExpirationDurationInSeconds = 90;
private int leaseExpirationDurationInSeconds = 90;
@Value("${spring.application.name:unknown}")
private String virtualHostName;
private String virtualHostName;
private String secureVirtualHostName;
private String secureVirtualHostName;
private String aSGName;
private String aSGName;
private Map<String, String> metadataMap = new HashMap<>();
private Map<String, String> metadataMap = new HashMap<>();
private DataCenterInfo dataCenterInfo = new IdentifyingDataCenterInfo();
private DataCenterInfo dataCenterInfo = new IdentifyingDataCenterInfo();
private String ipAddress = hostInfo[0];
private String ipAddress = this.hostInfo[0];
private String statusPageUrlPath = "/info";
private String statusPageUrlPath = "/info";
private String statusPageUrl;
private String statusPageUrl;
private String homePageUrlPath = "/";
private String homePageUrlPath = "/";
private String homePageUrl;
private String homePageUrl;
private String healthCheckUrlPath = "/health";
private String healthCheckUrlPath = "/health";
private String healthCheckUrl;
private String healthCheckUrl;
private String secureHealthCheckUrl;
private String secureHealthCheckUrl;
private String namespace = "eureka";
private String namespace = "eureka";
private String hostname = this.hostInfo[1];
private String hostname = hostInfo[1];
private boolean preferIpAddress = false;
private InstanceStatus initialStatus = InstanceStatus.UP;
private InstanceStatus initialStatus = InstanceStatus.UP;
public String getHostname() {
return preferIpAddress ? ipAddress : hostname;
return this.preferIpAddress ? this.ipAddress : this.hostname;
}
@Override
public boolean getSecurePortEnabled() {
return securePortEnabled;
return this.securePortEnabled;
}
private String[] initHostInfo() {
String[] info = new String[2];
try {
info[0] = InetAddress.getLocalHost().getHostAddress();
info[1] = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
logger.error("Cannot get host info", e);
}
return info ;
info[1] = InetAddress.getLocalHost().getHostName();
}
catch (UnknownHostException ex) {
logger.error("Cannot get host info", ex);
}
return info;
}
@Override
public String getHostName(boolean refresh) {
return preferIpAddress ? ipAddress : hostname;
return this.preferIpAddress ? this.ipAddress : this.hostname;
}
private final class IdentifyingDataCenterInfo implements DataCenterInfo, UniqueIdentifier {
@Getter @Setter
private Name name = Name.MyOwn;
private final class IdentifyingDataCenterInfo implements DataCenterInfo,
UniqueIdentifier {
@Getter
@Setter
private Name name = Name.MyOwn;
@Override
public String getId() {
String instanceId = metadataMap.get("instanceId");
String instanceId = EurekaInstanceConfigBean.this.metadataMap
.get("instanceId");
if (instanceId != null) {
String old = getHostname();
String id = old.endsWith(instanceId) ? old : old + ":" + instanceId;
@@ -142,7 +148,7 @@ public class EurekaInstanceConfigBean implements EurekaInstanceConfig {
}
return getHostname();
}
}
}

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.eureka;
import java.util.Collections;
@@ -20,15 +21,14 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.springframework.boot.context.properties.ConfigurationProperties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import com.netflix.eureka.EurekaServerConfig;
/**
* @author Dave Syer
*
*/
@Data
@ConfigurationProperties("eureka.server")
@@ -46,11 +46,7 @@ public class EurekaServerConfigBean implements EurekaServerConfig {
private int eIPBindingRetryIntervalMs = 5 * MINUTES;
private boolean enableSelfPreservation = true;
@Override
public boolean shouldEnableSelfPreservation() {
return enableSelfPreservation;
}
private boolean enableSelfPreservation = true;
private double renewalPercentThreshold = 0.85;
@@ -88,11 +84,7 @@ public class EurekaServerConfigBean implements EurekaServerConfig {
private long responseCacheUpdateIntervalMs = 30 * 1000;
private boolean disableDelta;
@Override
public boolean shouldDisableDelta() {
return disableDelta;
}
private boolean disableDelta;
private long maxIdleThreadInMinutesAgeForStatusReplication = 10;
@@ -102,11 +94,7 @@ public class EurekaServerConfigBean implements EurekaServerConfig {
private int maxElementsInStatusReplicationPool = 10000;
private boolean syncWhenTimestampDiffers = true;
@Override
public boolean shouldSyncWhenTimestampDiffers() {
return syncWhenTimestampDiffers;
}
private boolean syncWhenTimestampDiffers = true;
private int registrySyncRetries = 5;
@@ -120,17 +108,9 @@ public class EurekaServerConfigBean implements EurekaServerConfig {
private int maxTimeForReplication = 30000;
private boolean primeAwsReplicaConnections = true;
@Override
public boolean shouldPrimeAwsReplicaConnections() {
return primeAwsReplicaConnections;
}
private boolean primeAwsReplicaConnections = true;
private boolean disableDeltaForRemoteRegions;
@Override
public boolean shouldDisableDeltaForRemoteRegions() {
return disableDeltaForRemoteRegions;
}
private boolean disableDeltaForRemoteRegions;
private int remoteRegionConnectTimeoutMs = 1000;
@@ -142,26 +122,13 @@ public class EurekaServerConfigBean implements EurekaServerConfig {
private int remoteRegionConnectionIdleTimeoutSeconds = 30;
private boolean gZipContentFromRemoteRegion = true;
@Override
public boolean shouldGZipContentFromRemoteRegion() {
return gZipContentFromRemoteRegion;
}
private boolean gZipContentFromRemoteRegion = true;
private Map<String, String> remoteRegionUrlsWithName = new HashMap<String, String>();
private String[] remoteRegionUrls;
private String[] remoteRegionUrls;
private Map<String, Set<String>> remoteRegionAppWhitelist;
@Override
public Set<String> getRemoteRegionAppWhitelist(String regionName) {
if (null == regionName) {
regionName = "global";
} else {
regionName = regionName.trim().toLowerCase();
}
return remoteRegionAppWhitelist.get(regionName);
}
private int remoteRegionRegistryFetchInterval = 30;
@@ -170,34 +137,72 @@ public class EurekaServerConfigBean implements EurekaServerConfig {
private String remoteRegionTrustStorePassword = "changeit";
private boolean disableTransparentFallbackToOtherRegion;
private boolean batchReplication;
private boolean rateLimiterEnabled = false;
private boolean rateLimiterThrottleStandardClients = false;
private Set<String> rateLimiterPrivilegedClients = Collections.emptySet();
private int rateLimiterBurstSize = 10;
private int rateLimiterRegistryFetchAverageRate = 500;
private int rateLimiterFullFetchAverageRate = 100;
private boolean logIdentityHeaders = true;
@Override
public boolean disableTransparentFallbackToOtherRegion() {
return disableTransparentFallbackToOtherRegion;
public boolean shouldEnableSelfPreservation() {
return this.enableSelfPreservation;
}
private boolean batchReplication;
@Override
public boolean shouldDisableDelta() {
return this.disableDelta;
}
@Override
public boolean shouldSyncWhenTimestampDiffers() {
return this.syncWhenTimestampDiffers;
}
@Override
public boolean shouldPrimeAwsReplicaConnections() {
return this.primeAwsReplicaConnections;
}
@Override
public boolean shouldDisableDeltaForRemoteRegions() {
return this.disableDeltaForRemoteRegions;
}
@Override
public boolean shouldGZipContentFromRemoteRegion() {
return this.gZipContentFromRemoteRegion;
}
@Override
public Set<String> getRemoteRegionAppWhitelist(String regionName) {
return this.remoteRegionAppWhitelist.get(regionName == null ? "global"
: regionName.trim().toLowerCase());
}
@Override
public boolean disableTransparentFallbackToOtherRegion() {
return this.disableTransparentFallbackToOtherRegion;
}
@Override
public boolean shouldBatchReplication() {
return batchReplication;
return this.batchReplication;
}
private boolean logIdentityHeaders = true;
@Override
public boolean shouldLogIdentityHeaders() {
return this.logIdentityHeaders;
}
@Override
public boolean shouldLogIdentityHeaders() {
return logIdentityHeaders;
}
private boolean rateLimiterEnabled = false;
private boolean rateLimiterThrottleStandardClients = false;
private Set<String> rateLimiterPrivilegedClients = Collections.emptySet();
private int rateLimiterBurstSize = 10;
private int rateLimiterRegistryFetchAverageRate = 500;
private int rateLimiterFullFetchAverageRate = 100;
}

View File

@@ -1,20 +1,36 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.feign;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration;
import org.springframework.cloud.netflix.feign.ribbon.FeignRibbonClient;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.netflix.loadbalancer.ILoadBalancer;
import feign.Client;
import feign.Contract;
import feign.Feign;
import feign.Logger;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.cloud.netflix.feign.ribbon.FeignRibbonClient;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration;
import com.netflix.loadbalancer.ILoadBalancer;
/**
* @author Spencer Gibb
* @author Julien Roy
@@ -23,13 +39,14 @@ import com.netflix.loadbalancer.ILoadBalancer;
@ConditionalOnClass(Feign.class)
@AutoConfigureAfter(ArchaiusAutoConfiguration.class)
public class FeignAutoConfiguration {
@Bean
SpringDecoder feignDecoder() {
public SpringDecoder feignDecoder() {
return new SpringDecoder();
}
@Bean
SpringEncoder feignEncoder() {
public SpringEncoder feignEncoder() {
return new SpringEncoder();
}
@@ -52,4 +69,5 @@ public class FeignAutoConfiguration {
return new FeignRibbonClient(factory);
}
}
}

View File

@@ -1,6 +1,26 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.feign;
import java.lang.annotation.*;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation for interfaces declaring that a REST client with that interface should be
@@ -11,6 +31,7 @@ import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FeignClient {
/**
* @return serviceId if loadbalance is true, url otherwise There is no need to prefix
* serviceId with http://.
@@ -22,4 +43,5 @@ public @interface FeignClient {
* available).
*/
boolean loadbalance() default true;
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.feign;
import lombok.Data;
@@ -6,34 +22,37 @@ import lombok.EqualsAndHashCode;
import org.springframework.beans.factory.FactoryBean;
/**
* @author Spencer Gibb
*/
* @author Spencer Gibb
*/
@Data
@EqualsAndHashCode(callSuper=false)
@EqualsAndHashCode(callSuper = false)
class FeignClientFactoryBean extends FeignConfiguration implements FactoryBean<Object> {
private boolean loadbalance;
private Class<?> type;
private String schemeName;
@Override
public Object getObject() throws Exception {
if (!schemeName.startsWith("http")) {
schemeName = "http://"+schemeName;
if (!this.schemeName.startsWith("http")) {
this.schemeName = "http://" + this.schemeName;
}
if (loadbalance) {
return loadBalance(type, schemeName);
if (this.loadbalance) {
return loadBalance(this.type, this.schemeName);
}
return feign().target(type, schemeName);
return feign().target(this.type, this.schemeName);
}
@Override
public Class<?> getObjectType() {
return type;
return this.type;
}
@Override
public boolean isSingleton() {
return true;
}
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.feign;
import java.lang.annotation.Documented;
@@ -14,7 +30,8 @@ import org.springframework.context.annotation.Import;
* {@link org.springframework.context.annotation.Configuration
* <code>@Configuration</code>} classes.
*
* @author Artem Bilan
* @author Spencer Gibb
* @author Dave Syer
* @since 1.0
*/
@Retention(RetentionPolicy.RUNTIME)
@@ -27,7 +44,6 @@ public @interface FeignClientScan {
* Alias for the {@link #basePackages()} attribute. Allows for more concise annotation
* declarations e.g.: {@code @ComponentScan("org.my.pkg")} instead of
* {@code @ComponentScan(basePackages="org.my.pkg")}.
*
* @return the array of 'basePackages'.
*/
String[] value() default {};
@@ -55,4 +71,4 @@ public @interface FeignClientScan {
*/
Class<?>[] basePackageClasses() default {};
}
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.feign;
import java.lang.annotation.Annotation;
@@ -24,10 +40,11 @@ import org.springframework.util.StringUtils;
/**
* @author Spencer Gibb
* patterned after Spring Integration IntegrationComponentScanRegistrar
*/
public class FeignClientScanRegistrar extends FeignConfiguration
implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, BeanClassLoaderAware {
public class FeignClientScanRegistrar extends FeignConfiguration implements
ImportBeanDefinitionRegistrar, ResourceLoaderAware, BeanClassLoaderAware {
// patterned after Spring Integration IntegrationComponentScanRegistrar
private ResourceLoader resourceLoader;
@@ -47,22 +64,25 @@ public class FeignClientScanRegistrar extends FeignConfiguration
}
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
Set<String> basePackages = getBasePackages(importingClassMetadata);
ClassPathScanningCandidateComponentProvider scanner = getScanner();
scanner.addIncludeFilter(new AnnotationTypeFilter(FeignClient.class));
scanner.setResourceLoader(resourceLoader);
scanner.setResourceLoader(this.resourceLoader);
for (String basePackage : basePackages) {
Set<BeanDefinition> candidateComponents = scanner.findCandidateComponents(basePackage);
Set<BeanDefinition> candidateComponents = scanner
.findCandidateComponents(basePackage);
for (BeanDefinition candidateComponent : candidateComponents) {
if (candidateComponent instanceof AnnotatedBeanDefinition) {
//verify annotated class is an interface
// verify annotated class is an interface
AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition) candidateComponent;
AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
Assert.isTrue(annotationMetadata.isInterface(), "@FeignClient can only be specified on an interface");
Assert.isTrue(annotationMetadata.isInterface(),
"@FeignClient can only be specified on an interface");
BeanDefinitionHolder holder = createBeanDefinition(annotationMetadata);
BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
@@ -72,42 +92,50 @@ public class FeignClientScanRegistrar extends FeignConfiguration
}
public BeanDefinitionHolder createBeanDefinition(AnnotationMetadata annotationMetadata) {
Map<String, Object> attributes = annotationMetadata.getAnnotationAttributes(FeignClient.class.getCanonicalName());
Map<String, Object> attributes = annotationMetadata
.getAnnotationAttributes(FeignClient.class.getCanonicalName());
String className = annotationMetadata.getClassName();
BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(FeignClientFactoryBean.class);
BeanDefinitionBuilder definition = BeanDefinitionBuilder
.genericBeanDefinition(FeignClientFactoryBean.class);
definition.addPropertyValue("loadbalance", attributes.get("loadbalance"));
definition.addPropertyValue("type", className);
definition.addPropertyValue("schemeName", attributes.get("value"));
String beanName = StringUtils.uncapitalize(className.substring(className.lastIndexOf(".") + 1));
String beanName = StringUtils.uncapitalize(className.substring(className
.lastIndexOf(".") + 1));
return new BeanDefinitionHolder(definition.getBeanDefinition(), beanName);
}
protected ClassPathScanningCandidateComponentProvider getScanner() {
return new ClassPathScanningCandidateComponentProvider(false) {
@Override
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
if (beanDefinition.getMetadata().isIndependent()) {
// TODO until SPR-11711 will be resolved
if (beanDefinition.getMetadata().isInterface() &&
beanDefinition.getMetadata().getInterfaceNames().length == 1 &&
Annotation.class.getName().equals(beanDefinition.getMetadata().getInterfaceNames()[0])) {
try {
Class<?> target = ClassUtils.forName(beanDefinition.getMetadata().getClassName(), classLoader);
return !target.isAnnotation();
}
catch (Exception e) {
logger.error("Could not load target class: " + beanDefinition.getMetadata().getClassName(), e);
}
@Override
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
if (beanDefinition.getMetadata().isIndependent()) {
// TODO until SPR-11711 will be resolved
if (beanDefinition.getMetadata().isInterface()
&& beanDefinition.getMetadata().getInterfaceNames().length == 1
&& Annotation.class.getName().equals(
beanDefinition.getMetadata().getInterfaceNames()[0])) {
try {
Class<?> target = ClassUtils.forName(beanDefinition
.getMetadata().getClassName(),
FeignClientScanRegistrar.this.classLoader);
return !target.isAnnotation();
}
catch (Exception ex) {
this.logger.error("Could not load target class: "
+ beanDefinition.getMetadata().getClassName(), ex);
}
return true;
}
return false;
return true;
}
};
return false;
}
};
}
protected Set<String> getBasePackages(AnnotationMetadata importingClassMetadata) {
@@ -130,7 +158,8 @@ public class FeignClientScanRegistrar extends FeignConfiguration
}
if (basePackages.isEmpty()) {
basePackages.add(ClassUtils.getPackageName(importingClassMetadata.getClassName()));
basePackages.add(ClassUtils.getPackageName(importingClassMetadata
.getClassName()));
}
return basePackages;
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.feign;
import org.springframework.beans.factory.annotation.Autowired;
@@ -20,20 +36,21 @@ import feign.ribbon.LoadBalancingTarget;
*/
@Configuration
public class FeignConfiguration {
@Autowired
ConfigurableEnvironmentConfiguration envConfig; //FIXME: howto enforce this?
@Autowired
Decoder decoder;
@Autowired
ConfigurableEnvironmentConfiguration envConfig; // FIXME: howto enforce this?
@Autowired
Encoder encoder;
@Autowired
Decoder decoder;
@Autowired
Logger logger;
@Autowired
Encoder encoder;
@Autowired
Contract contract;
@Autowired
Logger logger;
@Autowired
Contract contract;
@Autowired(required = false)
Logger.Level logLevel;
@@ -47,40 +64,43 @@ public class FeignConfiguration {
@Autowired(required = false)
Request.Options options;
@Autowired(required = false)
Client ribbonClient;
@Autowired(required = false)
Client ribbonClient;
protected Feign.Builder feign() {
protected Feign.Builder feign() {
Feign.Builder builder = Feign.builder()
//required values
.logger(logger)
.encoder(encoder)
.decoder(decoder)
.contract(contract);
// required values
.logger(this.logger).encoder(this.encoder).decoder(this.decoder)
.contract(this.contract);
//optional values
if (logLevel != null)
builder.logLevel(logLevel);
if (retryer != null)
builder.retryer(retryer);
if (errorDecoder != null)
builder.errorDecoder(errorDecoder);
if (options != null)
builder.options(options);
// optional values
if (this.logLevel != null) {
builder.logLevel(this.logLevel);
}
if (this.retryer != null) {
builder.retryer(this.retryer);
}
if (this.errorDecoder != null) {
builder.errorDecoder(this.errorDecoder);
}
if (this.options != null) {
builder.options(this.options);
}
return builder;
}
}
protected <T> T loadBalance(Class<T> type, String schemeName) {
return loadBalance(feign(), type, schemeName);
}
protected <T> T loadBalance(Class<T> type, String schemeName) {
return loadBalance(feign(), type, schemeName);
}
protected <T> T loadBalance(Feign.Builder builder, Class<T> type, String schemeName) {
if(ribbonClient != null) {
return builder.client(ribbonClient).target(type, schemeName);
} else {
return builder.target(LoadBalancingTarget.create(type, schemeName));
}
}
protected <T> T loadBalance(Feign.Builder builder, Class<T> type, String schemeName) {
if (this.ribbonClient != null) {
return builder.client(this.ribbonClient).target(type, schemeName);
}
else {
return builder.target(LoadBalancingTarget.create(type, schemeName));
}
}
}

View File

@@ -1,20 +1,38 @@
package org.springframework.cloud.netflix.feign;
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.springframework.http.HttpHeaders;
package org.springframework.cloud.netflix.feign;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import org.springframework.http.HttpHeaders;
/**
* @author Spencer Gibb
*/
public class FeignUtils {
static HttpHeaders getHttpHeaders(Map<String, Collection<String>> headers) {
HttpHeaders httpHeaders = new HttpHeaders();
for (Map.Entry<String, Collection<String>> entry : headers.entrySet()) {
httpHeaders.put(entry.getKey(), new ArrayList<>(entry.getValue()));
}
return httpHeaders;
}
static HttpHeaders getHttpHeaders(Map<String, Collection<String>> headers) {
HttpHeaders httpHeaders = new HttpHeaders();
for (Map.Entry<String, Collection<String>> entry : headers.entrySet()) {
httpHeaders.put(entry.getKey(), new ArrayList<>(entry.getValue()));
}
return httpHeaders;
}
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.feign;
import java.io.IOException;
@@ -5,6 +21,8 @@ import java.io.InputStream;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import javax.inject.Provider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
import org.springframework.http.HttpHeaders;
@@ -17,8 +35,6 @@ import feign.Response;
import feign.codec.DecodeException;
import feign.codec.Decoder;
import javax.inject.Provider;
import static org.springframework.cloud.netflix.feign.FeignUtils.getHttpHeaders;
/**
@@ -26,25 +42,28 @@ import static org.springframework.cloud.netflix.feign.FeignUtils.getHttpHeaders;
*/
public class SpringDecoder implements Decoder {
@Autowired
Provider<HttpMessageConverters> messageConverters;
@Autowired
Provider<HttpMessageConverters> messageConverters;
public SpringDecoder() {
}
@Override
public Object decode(final Response response, Type type) throws IOException, FeignException {
public Object decode(final Response response, Type type) throws IOException,
FeignException {
if (type instanceof Class || type instanceof ParameterizedType) {
@SuppressWarnings({ "unchecked", "rawtypes" })
HttpMessageConverterExtractor<?> extractor = new HttpMessageConverterExtractor(
type, messageConverters.get().getConverters());
@SuppressWarnings({ "unchecked", "rawtypes" })
HttpMessageConverterExtractor<?> extractor = new HttpMessageConverterExtractor(
type, this.messageConverters.get().getConverters());
return extractor.extractData(new FeignResponseAdapter(response));
}
throw new DecodeException("type is not an instance of Class or ParameterizedType: " + type);
return extractor.extractData(new FeignResponseAdapter(response));
}
throw new DecodeException(
"type is not an instance of Class or ParameterizedType: " + type);
}
private class FeignResponseAdapter implements ClientHttpResponse {
private class FeignResponseAdapter implements ClientHttpResponse {
private final Response response;
private FeignResponseAdapter(Response response) {
@@ -53,38 +72,39 @@ public class SpringDecoder implements Decoder {
@Override
public HttpStatus getStatusCode() throws IOException {
return HttpStatus.valueOf(response.status());
return HttpStatus.valueOf(this.response.status());
}
@Override
public int getRawStatusCode() throws IOException {
return response.status();
return this.response.status();
}
@Override
public String getStatusText() throws IOException {
return response.reason();
return this.response.reason();
}
@Override
public void close() {
try {
response.body().close();
this.response.body().close();
}
catch (IOException e) {
e.printStackTrace();
catch (IOException ex) {
ex.printStackTrace();
}
}
@Override
public InputStream getBody() throws IOException {
return response.body().asInputStream();
return this.response.body().asInputStream();
}
@Override
public HttpHeaders getHeaders() {
return getHttpHeaders(response.headers());
return getHttpHeaders(this.response.headers());
}
}
}

View File

@@ -1,10 +1,27 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.feign;
import com.google.common.base.Charsets;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collection;
import feign.RequestTemplate;
import feign.codec.EncodeException;
import feign.codec.Encoder;
import javax.inject.Provider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -15,11 +32,11 @@ import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import javax.inject.Provider;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collection;
import com.google.common.base.Charsets;
import feign.RequestTemplate;
import feign.codec.EncodeException;
import feign.codec.Encoder;
import static org.springframework.cloud.netflix.feign.FeignUtils.getHttpHeaders;
@@ -27,13 +44,11 @@ import static org.springframework.cloud.netflix.feign.FeignUtils.getHttpHeaders;
* @author Spencer Gibb
*/
public class SpringEncoder implements Encoder {
private static final Logger logger = LoggerFactory.getLogger(SpringEncoder.class);
@Autowired
Provider<HttpMessageConverters> messageConverters;
public SpringEncoder() {
}
@Autowired
Provider<HttpMessageConverters> messageConverters;
@Override
public void encode(Object requestBody, RequestTemplate request)
@@ -49,7 +64,8 @@ public class SpringEncoder implements Encoder {
requestContentType = MediaType.valueOf(type);
}
for (HttpMessageConverter<?> messageConverter : messageConverters.get().getConverters()) {
for (HttpMessageConverter<?> messageConverter : this.messageConverters.get()
.getConverters()) {
if (messageConverter.canWrite(requestType, requestContentType)) {
if (logger.isDebugEnabled()) {
if (requestContentType != null) {
@@ -70,16 +86,16 @@ public class SpringEncoder implements Encoder {
HttpMessageConverter<Object> copy = (HttpMessageConverter<Object>) messageConverter;
copy.write(requestBody, requestContentType, outputMessage);
}
catch (IOException e) {
throw new EncodeException("Error converting request body", e);
catch (IOException ex) {
throw new EncodeException("Error converting request body", ex);
}
request.body(outputMessage.getOutputStream().toByteArray(),
Charsets.UTF_8); // TODO: set charset
return;
}
}
String message = "Could not write request: no suitable HttpMessageConverter found for request type ["
+ requestType.getName() + "]";
String message = "Could not write request: no suitable HttpMessageConverter "
+ "found for request type [" + requestType.getName() + "]";
if (requestContentType != null) {
message += " and content type [" + requestContentType + "]";
}
@@ -88,8 +104,10 @@ public class SpringEncoder implements Encoder {
}
private class FeignOutputMessage implements HttpOutputMessage {
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
RequestTemplate request;
private final RequestTemplate request;
private FeignOutputMessage(RequestTemplate request) {
this.request = request;
@@ -97,16 +115,18 @@ public class SpringEncoder implements Encoder {
@Override
public OutputStream getBody() throws IOException {
return outputStream;
return this.outputStream;
}
@Override
public HttpHeaders getHeaders() {
return getHttpHeaders(request.headers());
return getHttpHeaders(this.request.headers());
}
public ByteArrayOutputStream getOutputStream() {
return outputStream;
return this.outputStream;
}
}
}

View File

@@ -1,7 +1,20 @@
package org.springframework.cloud.netflix.feign;
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static feign.Util.checkState;
import static feign.Util.emptyToNull;
package org.springframework.cloud.netflix.feign;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
@@ -12,128 +25,155 @@ import java.util.Map;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import feign.Contract;
import feign.MethodMetadata;
import org.springframework.web.bind.annotation.RequestParam;
import static feign.Util.checkState;
import static feign.Util.emptyToNull;
/**
* @author Spencer Gibb
*/
public class SpringMvcContract extends Contract.BaseContract {
static final String ACCEPT = "Accept";
static final String CONTENT_TYPE = "Content-Type";
@Override
protected void processAnnotationOnMethod(MethodMetadata data, Annotation methodAnnotation, Method method) {
RequestMapping mapping = RequestMapping.class.cast(methodAnnotation);
if (mapping != null) {
//HTTP Method
checkOne(method, mapping.method(), "method");
data.template().method(mapping.method()[0].name());
private static final String ACCEPT = "Accept";
//path
checkOne(method, mapping.value(), "value");
private static final String CONTENT_TYPE = "Content-Type";
String methodAnnotationValue = mapping.value()[0];
String pathValue = emptyToNull(methodAnnotationValue);
checkState(pathValue != null, "value was empty on method %s", method.getName());
if (!methodAnnotationValue.startsWith("/") && !data.template().toString().endsWith("/")) {
methodAnnotationValue = "/" + methodAnnotationValue;
}
data.template().append(methodAnnotationValue);
@Override
protected void processAnnotationOnMethod(MethodMetadata data,
Annotation methodAnnotation, Method method) {
RequestMapping mapping = RequestMapping.class.cast(methodAnnotation);
if (mapping != null) {
// HTTP Method
checkOne(method, mapping.method(), "method");
data.template().method(mapping.method()[0].name());
//produces
checkAtMostOne(method, mapping.produces(), "produces");
String[] serverProduces = mapping.produces();
String clientAccepts = serverProduces.length == 0 ? null: emptyToNull(serverProduces[0]);
if (clientAccepts != null) {
data.template().header(ACCEPT, clientAccepts);
}
// path
checkOne(method, mapping.value(), "value");
//consumes
checkAtMostOne(method, mapping.consumes(), "consumes");
String[] serverConsumes = mapping.consumes();
String clientProduces = serverConsumes.length == 0 ? null: emptyToNull(serverConsumes[0]);
if (clientProduces != null) {
data.template().header(CONTENT_TYPE, clientProduces);
}
String methodAnnotationValue = mapping.value()[0];
String pathValue = emptyToNull(methodAnnotationValue);
checkState(pathValue != null, "value was empty on method %s",
method.getName());
if (!methodAnnotationValue.startsWith("/")
&& !data.template().toString().endsWith("/")) {
methodAnnotationValue = "/" + methodAnnotationValue;
}
data.template().append(methodAnnotationValue);
//headers
//TODO: only supports one header value per key
if (mapping.headers() != null && mapping.headers().length > 0)
for (String header : mapping.headers()) {
int colon = header.indexOf(':');
data.template().header(header.substring(0, colon), header.substring(colon + 2));
}
}
}
// produces
checkAtMostOne(method, mapping.produces(), "produces");
String[] serverProduces = mapping.produces();
String clientAccepts = serverProduces.length == 0 ? null
: emptyToNull(serverProduces[0]);
if (clientAccepts != null) {
data.template().header(ACCEPT, clientAccepts);
}
private void checkAtMostOne(Method method, Object[] values, String fieldName) {
checkState(values != null && (values.length == 0 || values.length == 1),
"Method %s can only contain at most 1 %s field. Found: %s", method.getName(), fieldName,
values == null ? null : Arrays.asList(values));
}
// consumes
checkAtMostOne(method, mapping.consumes(), "consumes");
String[] serverConsumes = mapping.consumes();
String clientProduces = serverConsumes.length == 0 ? null
: emptyToNull(serverConsumes[0]);
if (clientProduces != null) {
data.template().header(CONTENT_TYPE, clientProduces);
}
private void checkOne(Method method, Object[] values, String fieldName) {
checkState(values != null && values.length == 1,
"Method %s can only contain 1 %s field. Found: %s", method.getName(), fieldName,
values == null ? null : Arrays.asList(values));
}
// headers
// TODO: only supports one header value per key
if (mapping.headers() != null && mapping.headers().length > 0) {
for (String header : mapping.headers()) {
int colon = header.indexOf(':');
data.template().header(header.substring(0, colon),
header.substring(colon + 2));
}
}
}
}
@Override
protected boolean processAnnotationsOnParameter(MethodMetadata data, Annotation[] annotations, int paramIndex) {
boolean isHttpAnnotation = false;
//TODO: support spring parameter annotations?
for (Annotation parameterAnnotation : annotations) {
Class<? extends Annotation> annotationType = parameterAnnotation.annotationType();
if (annotationType == PathVariable.class) {
String name = PathVariable.class.cast(parameterAnnotation).value();
checkState(emptyToNull(name) != null, "PathVariable annotation was empty on param %s.", paramIndex);
nameParam(data, name, paramIndex);
isHttpAnnotation = true;
String varName = '{' + name + '}';
if (data.template().url().indexOf(varName) == -1 &&
!searchMapValues(data.template().queries(), varName) &&
!searchMapValues(data.template().headers(), varName)) {
data.formParams().add(name);
}
} else if (annotationType == RequestParam.class) {
String name = RequestParam.class.cast(parameterAnnotation).value();
checkState(emptyToNull(name) != null, "QueryParam.value() was empty on parameter %s", paramIndex);
Collection<String> query = addTemplatedParam(data.template().queries().get(name), name);
data.template().query(name, query);
nameParam(data, name, paramIndex);
isHttpAnnotation = true;
} else if (annotationType == RequestHeader.class) {
String name = RequestHeader.class.cast(parameterAnnotation).value();
checkState(emptyToNull(name) != null, "HeaderParam.value() was empty on parameter %s", paramIndex);
Collection<String> header = addTemplatedParam(data.template().headers().get(name), name);
data.template().header(name, header);
nameParam(data, name, paramIndex);
isHttpAnnotation = true;
}/* else if (annotationType == FormParam.class) {
String name = FormParam.class.cast(parameterAnnotation).value();
checkState(emptyToNull(name) != null, "FormParam.value() was empty on parameter %s", paramIndex);
data.formParams().add(name);
nameParam(data, name, paramIndex);
isHttpAnnotation = true;
}*/
private void checkAtMostOne(Method method, Object[] values, String fieldName) {
checkState(values != null && (values.length == 0 || values.length == 1),
"Method %s can only contain at most 1 %s field. Found: %s",
method.getName(), fieldName,
values == null ? null : Arrays.asList(values));
}
}
return isHttpAnnotation;
}
private void checkOne(Method method, Object[] values, String fieldName) {
checkState(values != null && values.length == 1,
"Method %s can only contain 1 %s field. Found: %s", method.getName(),
fieldName, values == null ? null : Arrays.asList(values));
}
private <K, V> boolean searchMapValues(Map<K, Collection<V>> map, V search) {
Collection<Collection<V>> values = map.values();
if (values == null)
return false;
@Override
protected boolean processAnnotationsOnParameter(MethodMetadata data,
Annotation[] annotations, int paramIndex) {
boolean isHttpAnnotation = false;
// TODO: support spring parameter annotations?
for (Annotation parameterAnnotation : annotations) {
Class<? extends Annotation> annotationType = parameterAnnotation
.annotationType();
if (annotationType == PathVariable.class) {
String name = PathVariable.class.cast(parameterAnnotation).value();
checkState(emptyToNull(name) != null,
"PathVariable annotation was empty on param %s.", paramIndex);
nameParam(data, name, paramIndex);
isHttpAnnotation = true;
String varName = '{' + name + '}';
if (data.template().url().indexOf(varName) == -1
&& !searchMapValues(data.template().queries(), varName)
&& !searchMapValues(data.template().headers(), varName)) {
data.formParams().add(name);
}
}
else if (annotationType == RequestParam.class) {
String name = RequestParam.class.cast(parameterAnnotation).value();
checkState(emptyToNull(name) != null,
"QueryParam.value() was empty on parameter %s", paramIndex);
Collection<String> query = addTemplatedParam(data.template().queries()
.get(name), name);
data.template().query(name, query);
nameParam(data, name, paramIndex);
isHttpAnnotation = true;
}
else if (annotationType == RequestHeader.class) {
String name = RequestHeader.class.cast(parameterAnnotation).value();
checkState(emptyToNull(name) != null,
"HeaderParam.value() was empty on parameter %s", paramIndex);
Collection<String> header = addTemplatedParam(data.template().headers()
.get(name), name);
data.template().header(name, header);
nameParam(data, name, paramIndex);
isHttpAnnotation = true;
}
for (Collection<V> entry : values) {
if (entry.contains(search))
return true;
}
// TODO
/*
* else if (annotationType == FormParam.class) { String name =
* FormParam.class.cast(parameterAnnotation).value();
* checkState(emptyToNull(name) != null,
* "FormParam.value() was empty on parameter %s", paramIndex);
* data.formParams().add(name); nameParam(data, name, paramIndex);
* isHttpAnnotation = true; }
*/
}
return isHttpAnnotation;
}
private <K, V> boolean searchMapValues(Map<K, Collection<V>> map, V search) {
Collection<Collection<V>> values = map.values();
if (values == null) {
return false;
}
for (Collection<V> entry : values) {
if (entry.contains(search)) {
return true;
}
}
return false;
}
return false;
}
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.feign.ribbon;
import java.io.IOException;
@@ -25,18 +41,9 @@ import feign.Response;
*/
public class FeignRibbonClient implements Client {
private Client defaultClient = new Default(
new Lazy<SSLSocketFactory>() {
@Override
public SSLSocketFactory get() {
return (SSLSocketFactory) SSLSocketFactory.getDefault();
}
}, new Lazy<HostnameVerifier>() {
@Override
public HostnameVerifier get() {
return HttpsURLConnection.getDefaultHostnameVerifier();
}
});
private Client defaultClient = new Default(new LazySSLSocketFactory(),
new LazyHostnameVerifier());
private SpringClientFactory factory;
public FeignRibbonClient(SpringClientFactory factory) {
@@ -44,30 +51,51 @@ public class FeignRibbonClient implements Client {
}
@Override
public Response execute(Request request, Request.Options options) throws IOException {
try {
public Response execute(Request request, Request.Options options) throws IOException {
try {
URI asUri = URI.create(request.url());
String clientName = asUri.getHost();
URI uriWithoutSchemeAndPort = URI.create(request.url().replace(
asUri.getScheme() + "://" + asUri.getHost(), ""));
RibbonLoadBalancer.RibbonRequest ribbonRequest = new RibbonLoadBalancer.RibbonRequest(
request, uriWithoutSchemeAndPort);
return lbClient(clientName).executeWithLoadBalancer(ribbonRequest)
.toResponse();
}
catch (ClientException ex) {
if (ex.getCause() instanceof IOException) {
throw IOException.class.cast(ex.getCause());
}
throw Throwables.propagate(ex);
}
}
URI asUri = URI.create(request.url());
String clientName = asUri.getHost();
URI uriWithoutSchemeAndPort = URI.create(request.url().replace(asUri.getScheme() + "://" + asUri.getHost(), ""));
RibbonLoadBalancer.RibbonRequest ribbonRequest = new RibbonLoadBalancer.RibbonRequest(request, uriWithoutSchemeAndPort);
return lbClient(clientName).executeWithLoadBalancer(ribbonRequest).toResponse();
private RibbonLoadBalancer lbClient(String clientName) {
IClientConfig config = this.factory.getClientConfig(clientName);
ILoadBalancer lb = this.factory.getLoadBalancer(clientName);
return new RibbonLoadBalancer(this.defaultClient, lb, config);
}
} catch (ClientException e) {
if (e.getCause() instanceof IOException) {
throw IOException.class.cast(e.getCause());
}
throw Throwables.propagate(e);
}
}
public void setDefaultClient(Client defaultClient) {
this.defaultClient = defaultClient;
}
private RibbonLoadBalancer lbClient(String clientName) {
IClientConfig config = factory.getClientConfig(clientName);
ILoadBalancer lb = factory.getLoadBalancer(clientName);
return new RibbonLoadBalancer(defaultClient, lb, config);
}
private static class LazySSLSocketFactory implements Lazy<SSLSocketFactory> {
@Override
public SSLSocketFactory get() {
return (SSLSocketFactory) SSLSocketFactory.getDefault();
}
}
private static class LazyHostnameVerifier implements Lazy<HostnameVerifier> {
@Override
public HostnameVerifier get() {
return HttpsURLConnection.getDefaultHostnameVerifier();
}
}
public void setDefaultClient(Client defaultClient) {
this.defaultClient = defaultClient;
}
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.feign.ribbon;
import java.io.IOException;
@@ -20,115 +36,129 @@ import feign.Request;
import feign.RequestTemplate;
import feign.Response;
public class RibbonLoadBalancer extends AbstractLoadBalancerAwareClient<RibbonLoadBalancer.RibbonRequest, RibbonLoadBalancer.RibbonResponse> {
public class RibbonLoadBalancer
extends
AbstractLoadBalancerAwareClient<RibbonLoadBalancer.RibbonRequest, RibbonLoadBalancer.RibbonResponse> {
private final Client delegate;
private final int connectTimeout;
private final int readTimeout;
private final IClientConfig clientConfig;
private final Client delegate;
public RibbonLoadBalancer(Client delegate, ILoadBalancer lb, IClientConfig clientConfig) {
super(lb, clientConfig);
this.setRetryHandler(RetryHandler.DEFAULT);
this.clientConfig = clientConfig;
this.delegate = delegate;
connectTimeout = clientConfig.get(CommonClientConfigKey.ConnectTimeout);
readTimeout = clientConfig.get(CommonClientConfigKey.ReadTimeout);
}
private final int connectTimeout;
@Override
public RibbonResponse execute(RibbonRequest request, IClientConfig configOverride) throws IOException {
Request.Options options;
if (configOverride != null) {
options = new Request.Options(configOverride.get(CommonClientConfigKey.ConnectTimeout, connectTimeout), (configOverride.get(CommonClientConfigKey.ReadTimeout, readTimeout)));
} else {
options = new Request.Options(connectTimeout, readTimeout);
}
Response response = delegate.execute(request.toRequest(), options);
return new RibbonResponse(request.getUri(), response);
}
private final int readTimeout;
@Override
public RequestSpecificRetryHandler getRequestSpecificRetryHandler(
RibbonRequest request, IClientConfig requestConfig) {
if (clientConfig.get(CommonClientConfigKey.OkToRetryOnAllOperations, false)) {
return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(), requestConfig);
}
if (!request.toRequest().method().equals("GET")) {
return new RequestSpecificRetryHandler(true, false, this.getRetryHandler(), requestConfig);
} else {
return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(), requestConfig);
}
}
private final IClientConfig clientConfig;
static class RibbonRequest extends ClientRequest implements Cloneable {
public RibbonLoadBalancer(Client delegate, ILoadBalancer lb,
IClientConfig clientConfig) {
super(lb, clientConfig);
this.setRetryHandler(RetryHandler.DEFAULT);
this.clientConfig = clientConfig;
this.delegate = delegate;
this.connectTimeout = clientConfig.get(CommonClientConfigKey.ConnectTimeout);
this.readTimeout = clientConfig.get(CommonClientConfigKey.ReadTimeout);
}
private final Request request;
@Override
public RibbonResponse execute(RibbonRequest request, IClientConfig configOverride)
throws IOException {
Request.Options options;
if (configOverride != null) {
options = new Request.Options(configOverride.get(
CommonClientConfigKey.ConnectTimeout, this.connectTimeout),
(configOverride.get(CommonClientConfigKey.ReadTimeout,
this.readTimeout)));
}
else {
options = new Request.Options(this.connectTimeout, this.readTimeout);
}
Response response = this.delegate.execute(request.toRequest(), options);
return new RibbonResponse(request.getUri(), response);
}
RibbonRequest(Request request, URI uri) {
this.request = request;
setUri(uri);
}
@Override
public RequestSpecificRetryHandler getRequestSpecificRetryHandler(
RibbonRequest request, IClientConfig requestConfig) {
if (this.clientConfig.get(CommonClientConfigKey.OkToRetryOnAllOperations, false)) {
return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(),
requestConfig);
}
if (!request.toRequest().method().equals("GET")) {
return new RequestSpecificRetryHandler(true, false, this.getRetryHandler(),
requestConfig);
}
else {
return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(),
requestConfig);
}
}
Request toRequest() {
return new RequestTemplate()
.method(request.method())
.append(getUri().toASCIIString())
.headers(request.headers())
.body(request.body(), request.charset())
.request();
}
static class RibbonRequest extends ClientRequest implements Cloneable {
public Object clone() {
return new RibbonRequest(request, getUri());
}
}
private final Request request;
static class RibbonResponse implements IResponse {
RibbonRequest(Request request, URI uri) {
this.request = request;
setUri(uri);
}
private final URI uri;
private final Response response;
Request toRequest() {
return new RequestTemplate().method(this.request.method())
.append(getUri().toASCIIString()).headers(this.request.headers())
.body(this.request.body(), this.request.charset()).request();
}
RibbonResponse(URI uri, Response response) {
this.uri = uri;
this.response = response;
}
@Override
public Object clone() {
return new RibbonRequest(this.request, getUri());
}
}
@Override
public Object getPayload() throws ClientException {
return response.body();
}
static class RibbonResponse implements IResponse {
@Override
public boolean hasPayload() {
return response.body() != null;
}
private final URI uri;
private final Response response;
@Override
public boolean isSuccess() {
return response.status() == 200;
}
RibbonResponse(URI uri, Response response) {
this.uri = uri;
this.response = response;
}
@Override
public URI getRequestedURI() {
return uri;
}
@Override
public Object getPayload() throws ClientException {
return this.response.body();
}
@Override
public Map<String, Collection<String>> getHeaders() {
return response.headers();
}
@Override
public boolean hasPayload() {
return this.response.body() != null;
}
Response toResponse() {
return response;
}
@Override
public boolean isSuccess() {
return this.response.status() == 200;
}
@Override
public void close() throws IOException {
if (response != null && response.body() != null) {
response.body().close();
}
}
@Override
public URI getRequestedURI() {
return this.uri;
}
}
}
@Override
public Map<String, Collection<String>> getHeaders() {
return this.response.headers();
}
Response toResponse() {
return this.response;
}
@Override
public void close() throws IOException {
if (this.response != null && this.response.body() != null) {
this.response.body().close();
}
}
}
}

View File

@@ -1,9 +1,21 @@
package org.springframework.cloud.netflix.hystrix;
/**
* @author Spencer Gibb
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.hystrix;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
@@ -19,9 +31,9 @@ import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
* you want. All it does is turn on circuit breakers and let the autoconfiguration find
* the Hystrix classes if they are available (i.e. you need Hystrix on the classpath as
* well).
*
* @author Dave Syer
*
* @author Dave Syer
* @author Spencer Gibb
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@@ -29,4 +41,5 @@ import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
@Inherited
@EnableCircuitBreaker
public @interface EnableHystrix {
}

View File

@@ -27,7 +27,8 @@ import org.springframework.context.annotation.Configuration;
import com.netflix.hystrix.Hystrix;
/**
* Auto configuration for Hystrix
* Auto configuration for Hystrix.
*
* @author Christian Dupuis
*/
@Configuration

View File

@@ -64,7 +64,7 @@ public class HystrixCircuitBreakerConfiguration {
@Configuration
@ConditionalOnProperty(value = "hystrix.stream.endpoint.enabled", matchIfMissing = true)
@ConditionalOnWebApplication
@ConditionalOnClass({Endpoint.class, HystrixMetricsStreamServlet.class})
@ConditionalOnClass({ Endpoint.class, HystrixMetricsStreamServlet.class })
protected static class HystrixWebConfiguration {
@Bean
@@ -75,13 +75,13 @@ public class HystrixCircuitBreakerConfiguration {
}
@Configuration
@ConditionalOnClass({HystrixMetricsPoller.class, GaugeService.class})
@ConditionalOnClass({ HystrixMetricsPoller.class, GaugeService.class })
protected static class HystrixMetricsPollerConfiguration implements SmartLifecycle {
private static Log logger = LogFactory
.getLog(HystrixMetricsPollerConfiguration.class);
@Autowired(required=false)
@Autowired(required = false)
private GaugeService gauges;
private ObjectMapper mapper = new ObjectMapper();
@@ -93,7 +93,7 @@ public class HystrixCircuitBreakerConfiguration {
@Override
public void start() {
if (gauges==null) {
if (this.gauges == null) {
return;
}
MetricsAsJsonPollerListener listener = new MetricsAsJsonPollerListener() {
@@ -101,20 +101,21 @@ public class HystrixCircuitBreakerConfiguration {
public void handleJsonMetric(String json) {
try {
@SuppressWarnings("unchecked")
Map<String, Object> map = mapper.readValue(json, Map.class);
Map<String, Object> map = HystrixMetricsPollerConfiguration.this.mapper
.readValue(json, Map.class);
if (map != null && map.containsKey("type")) {
addMetrics(map, "hystrix.");
}
}
catch (IOException e) {
catch (IOException ex) {
// ignore
}
}
};
poller = new HystrixMetricsPoller(listener, 2000);
this.poller = new HystrixMetricsPoller(listener, 2000);
// start polling and it will write directly to the listener
poller.start();
this.poller.start();
logger.info("Starting poller");
}
@@ -130,10 +131,10 @@ public class HystrixCircuitBreakerConfiguration {
String prefix = prefixBuilder.toString();
for (String key : map.keySet()) {
Object value = map.get(key);
if (!reserved.contains(key)) {
if (!this.reserved.contains(key)) {
if (value instanceof Number) {
String name = prefix + "." + key;
gauges.submit(name, ((Number) value).doubleValue());
this.gauges.submit(name, ((Number) value).doubleValue());
}
else if (value instanceof Map) {
@SuppressWarnings("unchecked")
@@ -146,14 +147,14 @@ public class HystrixCircuitBreakerConfiguration {
@Override
public void stop() {
if (poller != null) {
poller.shutdown();
if (this.poller != null) {
this.poller.shutdown();
}
}
@Override
public boolean isRunning() {
return poller != null ? poller.isRunning() : false;
return this.poller != null ? this.poller.isRunning() : false;
}
@Override
@@ -168,8 +169,8 @@ public class HystrixCircuitBreakerConfiguration {
@Override
public void stop(Runnable callback) {
if (poller != null) {
poller.shutdown();
if (this.poller != null) {
this.poller.shutdown();
}
callback.run();
}
@@ -189,4 +190,5 @@ public class HystrixCircuitBreakerConfiguration {
}
}
}

View File

@@ -28,34 +28,37 @@ import com.netflix.hystrix.HystrixCircuitBreaker;
import com.netflix.hystrix.HystrixCommandMetrics;
/**
* A {@link HealthIndicator} implementation for Hystrix circuit breakers.
* A {@link HealthIndicator} implementation for Hystrix circuit breakers.
* <p>
* This default implementation will set the system to <code>OUT_OF_SERVICE</code> and
* include all open circuits by name.
*
* This default implementation will set the system to <code>OUT_OF_SERVICE</code> and
* include all open circuits by name.
*
* @author Christian Dupuis
*/
public class HystrixHealthIndicator extends AbstractHealthIndicator {
/** Status code for open circuits */
private static final Status CIRCUIT_OPEN = new Status("CIRCUIT_OPEN");
private static final Status CIRCUIT_OPEN = new Status("CIRCUIT_OPEN");
@Override
protected void doHealthCheck(Builder builder) throws Exception {
List<String> openCircuitBreakers = new ArrayList<String>();
// Collect all open circuit breakers from Hystrix
for (HystrixCommandMetrics metrics : HystrixCommandMetrics.getInstances()) {
HystrixCircuitBreaker circuitBreaker = HystrixCircuitBreaker.Factory.getInstance(metrics.getCommandKey());
HystrixCircuitBreaker circuitBreaker = HystrixCircuitBreaker.Factory
.getInstance(metrics.getCommandKey());
if (circuitBreaker.isOpen()) {
openCircuitBreakers.add(metrics.getCommandGroup().name() + "::" + metrics.getCommandKey().name());
openCircuitBreakers.add(metrics.getCommandGroup().name() + "::"
+ metrics.getCommandKey().name());
}
}
// If there is at least one open circuit report OUT_OF_SERVICE adding the command group
// If there is at least one open circuit report OUT_OF_SERVICE adding the command
// group
// and key name
if (openCircuitBreakers.size() > 0) {
builder.status(CIRCUIT_OPEN).withDetail("openCircuitBreakers", openCircuitBreakers);
builder.status(CIRCUIT_OPEN).withDetail("openCircuitBreakers",
openCircuitBreakers);
}
else {
builder.up();

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.hystrix;
import org.springframework.cloud.netflix.endpoint.ServletWrappingEndpoint;
@@ -24,7 +25,9 @@ import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServl
*/
public class HystrixStreamEndpoint extends ServletWrappingEndpoint {
public HystrixStreamEndpoint() {
super(HystrixMetricsStreamServlet.class, "hystrixStream", "/hystrix.stream", false, true);
}
public HystrixStreamEndpoint() {
super(HystrixMetricsStreamServlet.class, "hystrixStream", "/hystrix.stream",
false, true);
}
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.ribbon;
import java.util.ArrayList;
@@ -17,27 +33,28 @@ import org.springframework.web.client.RestTemplate;
import com.netflix.client.IClient;
/**
* Auto configuration for Ribbon (client side load balancing)
* Auto configuration for Ribbon (client side load balancing).
*
* @author Spencer Gibb
* @author Dave Syer
*/
@Configuration
@ConditionalOnClass({IClient.class, RestTemplate.class})
@ConditionalOnClass({ IClient.class, RestTemplate.class })
@RibbonClients
@AutoConfigureAfter(EurekaClientAutoConfiguration.class)
public class RibbonAutoConfiguration {
@Autowired(required=false)
private List<RibbonClientSpecification> configurations = new ArrayList<>();
@Autowired(required = false)
private List<RibbonClientSpecification> configurations = new ArrayList<>();
@Bean
public SpringClientFactory springClientFactory() {
SpringClientFactory factory = new SpringClientFactory();
factory.setConfigurations(configurations);
public SpringClientFactory springClientFactory() {
SpringClientFactory factory = new SpringClientFactory();
factory.setConfigurations(this.configurations);
return factory;
}
}
@Bean
@Bean
@ConditionalOnMissingBean(RestTemplate.class)
public RestTemplate restTemplate(RibbonInterceptor ribbonInterceptor) {
RestTemplate restTemplate = new RestTemplate();

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.ribbon;
import java.lang.annotation.Documented;
@@ -26,7 +27,6 @@ import org.springframework.context.annotation.Import;
/**
* @author Dave Syer
*
*/
@Configuration
@Import(RibbonClientConfigurationRegistrar.class)
@@ -34,7 +34,11 @@ import org.springframework.context.annotation.Import;
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RibbonClient {
String value() default "";
String name() default "";
Class<?>[] configuration() default {};
}

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.ribbon;
import org.springframework.beans.factory.annotation.Value;
@@ -36,7 +37,6 @@ import com.netflix.servo.monitor.Monitors;
/**
* @author Dave Syer
*
*/
@SuppressWarnings("deprecation")
@Configuration
@@ -51,12 +51,12 @@ public class RibbonClientConfiguration {
// TODO: maybe re-instate autowired load balancers: identified by name they could be
// associated with ribbon clients
@Bean
@ConditionalOnMissingBean
public IClientConfig ribbonClientConfig() {
DefaultClientConfigImpl config = new DefaultClientConfigImpl();
config.loadProperties(name);
config.loadProperties(this.name);
return config;
}
@@ -65,20 +65,21 @@ public class RibbonClientConfiguration {
public RestClient ribbonRestClient(IClientConfig config, ILoadBalancer loadBalancer) {
RestClient client = new RestClient(config);
client.setLoadBalancer(loadBalancer);
Monitors.registerObject("Client_" + name, client);
Monitors.registerObject("Client_" + this.name, client);
return client;
}
@Bean
@ConditionalOnMissingBean
//TODO: move to ribbon.eureka package
public ILoadBalancer ribbonLoadBalancer(IClientConfig config, ServerListFilter<Server> filter) {
// TODO: move to ribbon.eureka package
public ILoadBalancer ribbonLoadBalancer(IClientConfig config,
ServerListFilter<Server> filter) {
ZoneAwareLoadBalancer<Server> balancer = new ZoneAwareLoadBalancer<>(config);
wrapServerList(balancer);
balancer.setFilter(filter);
return balancer;
}
@Bean
@ConditionalOnMissingBean
public ServerListFilter<Server> ribbonServerListFilter(IClientConfig config) {
@@ -86,10 +87,11 @@ public class RibbonClientConfiguration {
filter.initWithNiwsConfig(config);
return filter;
}
@Bean
@ConditionalOnMissingBean
public RibbonLoadBalancerContext ribbonLoadBalancerContext(ILoadBalancer loadBalancer, IClientConfig config) {
public RibbonLoadBalancerContext ribbonLoadBalancerContext(
ILoadBalancer loadBalancer, IClientConfig config) {
return new RibbonLoadBalancerContext(loadBalancer, config);
}
@@ -104,7 +106,7 @@ public class RibbonClientConfiguration {
// metadata *is* available.
// @see com.netflix.appinfo.AmazonInfo.Builder
dynamic.setServerListImpl(new DomainExtractingServerList(list, dynamic
.getClientConfig(), approximateZoneFromHostname));
.getClientConfig(), this.approximateZoneFromHostname));
}
}
}

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.ribbon;
import java.util.Map;
@@ -26,7 +27,6 @@ import org.springframework.util.StringUtils;
/**
* @author Dave Syer
*
*/
public class RibbonClientConfigurationRegistrar implements ImportBeanDefinitionRegistrar {
@@ -56,7 +56,7 @@ public class RibbonClientConfigurationRegistrar implements ImportBeanDefinitionR
}
private String getClientName(Map<String, Object> client) {
if (client==null) {
if (client == null) {
return null;
}
String value = (String) client.get("value");
@@ -67,7 +67,8 @@ public class RibbonClientConfigurationRegistrar implements ImportBeanDefinitionR
if (value != null && StringUtils.hasText(value)) {
return value;
}
throw new IllegalStateException("Either 'name' or 'value' must be provided in @RibbonClient");
throw new IllegalStateException(
"Either 'name' or 'value' must be provided in @RibbonClient");
}
private void registerClientConfiguration(BeanDefinitionRegistry registry,

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.ribbon;
import lombok.AllArgsConstructor;
@@ -20,13 +21,13 @@ import lombok.Data;
/**
* @author Dave Syer
*
*/
@Data
@AllArgsConstructor
public class RibbonClientSpecification {
private String name;
private Class<?>[] configuration;
}

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.ribbon;
import java.lang.annotation.Documented;
@@ -27,9 +28,8 @@ import org.springframework.context.annotation.Import;
/**
* Convenience annotation that allows user to combine multiple <code>@RibbonClient</code>
* annotations on a single class (including in Java 7).
*
* @author Dave Syer
*
* @author Dave Syer
*/
@Configuration
@Retention(RetentionPolicy.RUNTIME)

View File

@@ -1,5 +1,24 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.ribbon;
import java.io.IOException;
import java.net.URI;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerRequest;
@@ -9,36 +28,52 @@ import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.support.HttpRequestWrapper;
import java.io.IOException;
import java.net.URI;
/**
* @author Spencer Gibb
*/
public class RibbonInterceptor implements ClientHttpRequestInterceptor {
private LoadBalancerClient loadBalancer;
private LoadBalancerClient loadBalancer;
public RibbonInterceptor(LoadBalancerClient loadBalancer) {
this.loadBalancer = loadBalancer;
}
public RibbonInterceptor(LoadBalancerClient loadBalancer) {
this.loadBalancer = loadBalancer;
}
@Override
public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,
final ClientHttpRequestExecution execution) throws IOException {
final URI originalUri = request.getURI();
String serviceName = originalUri.getHost();
return this.loadBalancer.execute(serviceName,
new LoadBalancerRequest<ClientHttpResponse>() {
@Override
public ClientHttpResponse apply(final ServiceInstance instance)
throws Exception {
HttpRequest serviceRequest = new ServiceRequestWrapper(request,
instance);
return execution.execute(serviceRequest, body);
}
});
}
private class ServiceRequestWrapper extends HttpRequestWrapper {
private final ServiceInstance instance;
public ServiceRequestWrapper(HttpRequest request, ServiceInstance instance) {
super(request);
this.instance = instance;
}
@Override
public URI getURI() {
URI uri = RibbonInterceptor.this.loadBalancer.reconstructURI(this.instance,
getRequest().getURI());
return uri;
}
}
@Override
public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws IOException {
final URI originalUri = request.getURI();
String serviceName = originalUri.getHost();
return loadBalancer.execute(serviceName, new LoadBalancerRequest<ClientHttpResponse>() {
@Override
public ClientHttpResponse apply(final ServiceInstance instance) throws Exception {
HttpRequestWrapper wrapper = new HttpRequestWrapper(request) {
@Override
public URI getURI() {
URI uri = loadBalancer.reconstructURI(instance, originalUri);
return uri;
}
};
return execution.execute(wrapper, body);
}
});
}
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.ribbon;
import java.net.URI;
@@ -19,72 +35,75 @@ import com.netflix.servo.monitor.Stopwatch;
*/
public class RibbonLoadBalancerClient implements LoadBalancerClient {
private SpringClientFactory clientFactory;
private SpringClientFactory clientFactory;
public RibbonLoadBalancerClient(SpringClientFactory clientFactory) {
this.clientFactory = clientFactory;
}
@Override
public URI reconstructURI(ServiceInstance instance, URI original) {
String serviceId = instance.getServiceId();
RibbonLoadBalancerContext context = clientFactory.getLoadBalancerContext(serviceId);
Server server = new Server(instance.getHost(), instance.getPort());
return context.reconstructURIWithServer(server, original);
}
@Override
public URI reconstructURI(ServiceInstance instance, URI original) {
String serviceId = instance.getServiceId();
RibbonLoadBalancerContext context = this.clientFactory
.getLoadBalancerContext(serviceId);
Server server = new Server(instance.getHost(), instance.getPort());
return context.reconstructURIWithServer(server, original);
}
@Override
@Override
public ServiceInstance choose(String serviceId) {
return new RibbonServer(serviceId, getServer(serviceId));
}
@Override
public <T> T execute(String serviceId, LoadBalancerRequest<T> request) {
ILoadBalancer loadBalancer = getLoadBalancer(serviceId);
RibbonLoadBalancerContext context = clientFactory.getLoadBalancerContext(serviceId);
Server server = getServer(serviceId, loadBalancer);
RibbonServer ribbonServer = new RibbonServer(serviceId, server);
@Override
public <T> T execute(String serviceId, LoadBalancerRequest<T> request) {
ILoadBalancer loadBalancer = getLoadBalancer(serviceId);
RibbonLoadBalancerContext context = this.clientFactory
.getLoadBalancerContext(serviceId);
Server server = getServer(serviceId, loadBalancer);
RibbonServer ribbonServer = new RibbonServer(serviceId, server);
ServerStats serverStats = context.getServerStats(server);
context.noteOpenConnection(serverStats);
Stopwatch tracer = context.getExecuteTracer().start();
ServerStats serverStats = context.getServerStats(server);
context.noteOpenConnection(serverStats);
Stopwatch tracer = context.getExecuteTracer().start();
try {
try {
T returnVal = request.apply(ribbonServer);
recordStats(context, tracer, serverStats, returnVal, null);
return returnVal;
}
catch (Exception ex) {
recordStats(context, tracer, serverStats, null, ex);
Throwables.propagate(ex);
}
return null;
}
T returnVal = request.apply(ribbonServer);
recordStats(context, tracer, serverStats, returnVal, null);
return returnVal;
} catch (Exception e) {
recordStats(context, tracer, serverStats, null, e);
Throwables.propagate(e);
}
return null;
}
private void recordStats(RibbonLoadBalancerContext context, Stopwatch tracer,
ServerStats serverStats, Object entity, Throwable exception) {
tracer.stop();
long duration = tracer.getDuration(TimeUnit.MILLISECONDS);
context.noteRequestCompletion(serverStats, entity, exception, duration, null/* errorHandler */);
}
private void recordStats(RibbonLoadBalancerContext context, Stopwatch tracer, ServerStats serverStats, Object entity, Throwable exception) {
tracer.stop();
long duration = tracer.getDuration(TimeUnit.MILLISECONDS);
context.noteRequestCompletion(serverStats, entity, exception, duration, null/*errorHandler*/);
}
protected Server getServer(String serviceId) {
return getServer(serviceId, getLoadBalancer(serviceId));
}
protected Server getServer(String serviceId) {
return getServer(serviceId, getLoadBalancer(serviceId));
}
protected Server getServer(String serviceId, ILoadBalancer loadBalancer) {
Server server = loadBalancer.chooseServer("default");
if (server == null) {
throw new IllegalStateException(
"Unable to locate ILoadBalancer for service: " + serviceId);
}
return server;
}
protected Server getServer(String serviceId, ILoadBalancer loadBalancer) {
Server server = loadBalancer.chooseServer("default");
if (server == null) {
throw new IllegalStateException(
"Unable to locate ILoadBalancer for service: " + serviceId);
}
return server;
}
protected ILoadBalancer getLoadBalancer(String serviceId) {
return this.clientFactory.getLoadBalancer(serviceId);
}
protected ILoadBalancer getLoadBalancer(String serviceId) {
return clientFactory.getLoadBalancer(serviceId);
}
protected static class RibbonServer implements ServiceInstance {
protected static class RibbonServer implements ServiceInstance {
protected String serviceId;
protected Server server;
@@ -95,17 +114,19 @@ public class RibbonLoadBalancerClient implements LoadBalancerClient {
@Override
public String getServiceId() {
return serviceId;
return this.serviceId;
}
@Override
public String getHost() {
return server.getHost();
return this.server.getHost();
}
@Override
public int getPort() {
return server.getPort();
return this.server.getPort();
}
}
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.ribbon;
import com.netflix.client.RetryHandler;
@@ -11,35 +27,39 @@ import com.netflix.servo.monitor.Timer;
* @author Spencer Gibb
*/
public class RibbonLoadBalancerContext extends LoadBalancerContext {
public RibbonLoadBalancerContext(ILoadBalancer lb) {
super(lb);
}
public RibbonLoadBalancerContext(ILoadBalancer lb) {
super(lb);
}
public RibbonLoadBalancerContext(ILoadBalancer lb, IClientConfig clientConfig) {
super(lb, clientConfig);
}
public RibbonLoadBalancerContext(ILoadBalancer lb, IClientConfig clientConfig) {
super(lb, clientConfig);
}
public RibbonLoadBalancerContext(ILoadBalancer lb, IClientConfig clientConfig, RetryHandler handler) {
super(lb, clientConfig, handler);
}
public RibbonLoadBalancerContext(ILoadBalancer lb, IClientConfig clientConfig,
RetryHandler handler) {
super(lb, clientConfig, handler);
}
@Override
public void noteOpenConnection(ServerStats serverStats) {
super.noteOpenConnection(serverStats);
}
@Override
public void noteOpenConnection(ServerStats serverStats) {
super.noteOpenConnection(serverStats);
}
@Override
public Timer getExecuteTracer() {
return super.getExecuteTracer();
}
@Override
public Timer getExecuteTracer() {
return super.getExecuteTracer();
}
@Override
public void noteRequestCompletion(ServerStats stats, Object response, Throwable e, long responseTime) {
super.noteRequestCompletion(stats, response, e, responseTime);
}
@Override
public void noteRequestCompletion(ServerStats stats, Object response, Throwable e,
long responseTime) {
super.noteRequestCompletion(stats, response, e, responseTime);
}
@Override
public void noteRequestCompletion(ServerStats stats, Object response, Throwable e,
long responseTime, RetryHandler errorHandler) {
super.noteRequestCompletion(stats, response, e, responseTime, errorHandler);
}
@Override
public void noteRequestCompletion(ServerStats stats, Object response, Throwable e, long responseTime, RetryHandler errorHandler) {
super.noteRequestCompletion(stats, response, e, responseTime, errorHandler);
}
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.ribbon;
import java.util.Collection;
@@ -27,18 +43,22 @@ import com.netflix.loadbalancer.ILoadBalancer;
* creates a Spring ApplicationContext per client name, and extracts the beans that it
* needs from there.
*
* @author Spencer Gibb
* @author Dave Syer
*/
public class SpringClientFactory implements DisposableBean, ApplicationContextAware {
private Map<String, AnnotationConfigApplicationContext> contexts = new ConcurrentHashMap<>();
private Map<String, RibbonClientSpecification> configurations = new ConcurrentHashMap<>();
private ApplicationContext parent;
@Override
public void setApplicationContext(ApplicationContext parent) throws BeansException {
this.parent = parent;
}
public void setConfigurations(List<RibbonClientSpecification> configurations) {
for (RibbonClientSpecification client : configurations) {
this.configurations.put(client.getName(), client);
@@ -47,8 +67,8 @@ public class SpringClientFactory implements DisposableBean, ApplicationContextAw
@Override
public void destroy() {
Collection<AnnotationConfigApplicationContext> values = contexts.values();
contexts.clear();
Collection<AnnotationConfigApplicationContext> values = this.contexts.values();
this.contexts.clear();
for (AnnotationConfigApplicationContext context : values) {
context.close();
}
@@ -56,7 +76,6 @@ public class SpringClientFactory implements DisposableBean, ApplicationContextAw
/**
* Get the rest client associated with the name.
*
* @throws RuntimeException if any error occurs
*/
public <C extends IClient<?, ?>> C getClient(String name, Class<C> clientClass) {
@@ -65,7 +84,6 @@ public class SpringClientFactory implements DisposableBean, ApplicationContextAw
/**
* Get the load balancer associated with the name.
*
* @throws RuntimeException if any error occurs
*/
public ILoadBalancer getLoadBalancer(String name) {
@@ -74,7 +92,6 @@ public class SpringClientFactory implements DisposableBean, ApplicationContextAw
/**
* Get the client config associated with the name.
*
* @throws RuntimeException if any error occurs
*/
public IClientConfig getClientConfig(String name) {
@@ -83,7 +100,6 @@ public class SpringClientFactory implements DisposableBean, ApplicationContextAw
/**
* Get the load balancer context associated with the name.
*
* @throws RuntimeException if any error occurs
*/
public RibbonLoadBalancerContext getLoadBalancerContext(String serviceId) {
@@ -91,28 +107,30 @@ public class SpringClientFactory implements DisposableBean, ApplicationContextAw
}
private AnnotationConfigApplicationContext getContext(String name) {
if (!contexts.containsKey(name)) {
synchronized (contexts) {
if (!contexts.containsKey(name)) {
contexts.put(name, createContext(name));
if (!this.contexts.containsKey(name)) {
synchronized (this.contexts) {
if (!this.contexts.containsKey(name)) {
this.contexts.put(name, createContext(name));
}
}
}
return contexts.get(name);
return this.contexts.get(name);
}
private AnnotationConfigApplicationContext createContext(String name) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
if (configurations.containsKey(name)) {
for (Class<?> configuration : configurations.get(name).getConfiguration()) {
if (this.configurations.containsKey(name)) {
for (Class<?> configuration : this.configurations.get(name)
.getConfiguration()) {
context.register(configuration);
}
}
for (Entry<String, RibbonClientSpecification> entry : configurations.entrySet()) {
for (Entry<String, RibbonClientSpecification> entry : this.configurations
.entrySet()) {
if (entry.getKey().startsWith("default.")) {
for (Class<?> configuration : entry.getValue().getConfiguration()) {
context.register(configuration);
}
}
}
}
context.register(PropertyPlaceholderAutoConfiguration.class,
@@ -123,9 +141,9 @@ public class SpringClientFactory implements DisposableBean, ApplicationContextAw
new MapPropertySource("ribbon",
Collections.<String, Object> singletonMap(
"ribbon.client.name", name)));
if (parent != null) {
if (this.parent != null) {
// Uses Environment from parent as well as beans
context.setParent(parent);
context.setParent(this.parent);
}
context.refresh();
return context;
@@ -151,7 +169,8 @@ public class SpringClientFactory implements DisposableBean, ApplicationContextAw
result = BeanUtils.instantiate(clazz);
}
}
catch (Throwable e) { // NOPMD
catch (Throwable ex) {
// NOPMD
}
}
context.getAutowireCapableBeanFactory().autowireBean(result);

View File

@@ -13,111 +13,117 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.ribbon.eureka;
import java.util.ArrayList;
import java.util.List;
import com.netflix.client.config.CommonClientConfigKey;
import com.netflix.client.config.IClientConfig;
import lombok.Getter;
import lombok.Setter;
import org.springframework.util.StringUtils;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.client.config.CommonClientConfigKey;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import com.netflix.niws.loadbalancer.DiscoveryEnabledServer;
/**
* @author Dave Syer
*
*/
public class DomainExtractingServerList implements ServerList<Server> {
private ServerList<Server> list;
private IClientConfig clientConfig;
private ServerList<Server> list;
private IClientConfig clientConfig;
private boolean approximateZoneFromHostname;
public DomainExtractingServerList(ServerList<Server> list, IClientConfig clientConfig, boolean approximateZoneFromHostname) {
this.list = list;
this.clientConfig = clientConfig;
public DomainExtractingServerList(ServerList<Server> list,
IClientConfig clientConfig, boolean approximateZoneFromHostname) {
this.list = list;
this.clientConfig = clientConfig;
this.approximateZoneFromHostname = approximateZoneFromHostname;
}
@Override
public List<Server> getInitialListOfServers() {
List<Server> servers = setZones(list.getInitialListOfServers());
return servers;
}
@Override
public List<Server> getInitialListOfServers() {
List<Server> servers = setZones(this.list.getInitialListOfServers());
return servers;
}
@Override
public List<Server> getUpdatedListOfServers() {
List<Server> servers = setZones(list.getUpdatedListOfServers());
return servers;
}
@Override
public List<Server> getUpdatedListOfServers() {
List<Server> servers = setZones(this.list.getUpdatedListOfServers());
return servers;
}
private List<Server> setZones(List<Server> servers) {
List<Server> result = new ArrayList<>();
boolean isSecure = clientConfig.getPropertyAsBoolean(CommonClientConfigKey.IsSecure, Boolean.TRUE);
boolean shouldUseIpAddr = clientConfig.getPropertyAsBoolean(CommonClientConfigKey.UseIPAddrForServer, Boolean.FALSE);
for (Server server : servers) {
if (server instanceof DiscoveryEnabledServer) {
result.add(new DomainExtractingServer((DiscoveryEnabledServer) server,
isSecure, shouldUseIpAddr, approximateZoneFromHostname));
}
else {
result.add(server);
}
}
return result;
}
private List<Server> setZones(List<Server> servers) {
List<Server> result = new ArrayList<>();
boolean isSecure = this.clientConfig.getPropertyAsBoolean(
CommonClientConfigKey.IsSecure, Boolean.TRUE);
boolean shouldUseIpAddr = this.clientConfig.getPropertyAsBoolean(
CommonClientConfigKey.UseIPAddrForServer, Boolean.FALSE);
for (Server server : servers) {
if (server instanceof DiscoveryEnabledServer) {
result.add(new DomainExtractingServer((DiscoveryEnabledServer) server,
isSecure, shouldUseIpAddr, this.approximateZoneFromHostname));
}
else {
result.add(server);
}
}
return result;
}
}
class DomainExtractingServer extends DiscoveryEnabledServer {
@Getter
@Setter
private String id;
@Getter
@Setter
private String id;
public DomainExtractingServer(DiscoveryEnabledServer server, boolean useSecurePort, boolean useIpAddr, boolean approximateZoneFromHostname) {
//host and port are set in super()
super(server.getInstanceInfo(), useSecurePort, useIpAddr);
public DomainExtractingServer(DiscoveryEnabledServer server, boolean useSecurePort,
boolean useIpAddr, boolean approximateZoneFromHostname) {
// host and port are set in super()
super(server.getInstanceInfo(), useSecurePort, useIpAddr);
if (approximateZoneFromHostname) {
setZone(extractApproximateZone(server));
} else {
}
else {
setZone(server.getZone());
}
setId(extractId(server));
setId(extractId(server));
setAlive(server.isAlive());
setReadyToServe(server.isReadyToServe());
}
}
private String extractId(Server server) {
if (server instanceof DiscoveryEnabledServer) {
DiscoveryEnabledServer enabled = (DiscoveryEnabledServer) server;
InstanceInfo instance = enabled.getInstanceInfo();
if (instance.getMetadata().containsKey("instanceId")) {
return instance.getMetadata().get("instanceId");
}
}
return super.getId();
}
private String extractId(Server server) {
if (server instanceof DiscoveryEnabledServer) {
DiscoveryEnabledServer enabled = (DiscoveryEnabledServer) server;
InstanceInfo instance = enabled.getInstanceInfo();
if (instance.getMetadata().containsKey("instanceId")) {
return instance.getMetadata().get("instanceId");
}
}
return super.getId();
}
private String extractApproximateZone(Server server) {
String host = server.getHost();
if (!host.contains(".")) {
return host;
}
String[] split = StringUtils.split(host, ".");
StringBuilder builder = new StringBuilder(split[1]);
for (int i = 2; i < split.length; i++) {
builder.append(".").append(split[i]);
}
return builder.toString();
}
private String extractApproximateZone(Server server) {
String host = server.getHost();
if (!host.contains(".")) {
return host;
}
String[] split = StringUtils.split(host, ".");
StringBuilder builder = new StringBuilder(split[1]);
for (int i = 2; i < split.length; i++) {
builder.append(".").append(split[i]);
}
return builder.toString();
}
}

View File

@@ -1,10 +1,20 @@
package org.springframework.cloud.netflix.ribbon.eureka;
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static com.netflix.client.config.CommonClientConfigKey.DeploymentContextBasedVipAddresses;
import static com.netflix.client.config.CommonClientConfigKey.EnableZoneAffinity;
import static com.netflix.client.config.CommonClientConfigKey.NFLoadBalancerRuleClassName;
import static com.netflix.client.config.CommonClientConfigKey.NIWSServerListClassName;
import static com.netflix.client.config.CommonClientConfigKey.NIWSServerListFilterClassName;
package org.springframework.cloud.netflix.ribbon.eureka;
import javax.annotation.PostConstruct;
@@ -20,11 +30,17 @@ import com.netflix.discovery.EurekaClientConfig;
import com.netflix.loadbalancer.ZoneAvoidanceRule;
import com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList;
import static com.netflix.client.config.CommonClientConfigKey.DeploymentContextBasedVipAddresses;
import static com.netflix.client.config.CommonClientConfigKey.EnableZoneAffinity;
import static com.netflix.client.config.CommonClientConfigKey.NFLoadBalancerRuleClassName;
import static com.netflix.client.config.CommonClientConfigKey.NIWSServerListClassName;
import static com.netflix.client.config.CommonClientConfigKey.NIWSServerListFilterClassName;
/**
* Preprocessor that configures defaults for eureka-discovered ribbon clients. Such as:
* <code>@zone</code>, NIWSServerListClassName, DeploymentContextBasedVipAddresses,
* NFLoadBalancerRuleClassName, NIWSServerListFilterClassName and more
*
*
* @author Spencer Gibb
* @author Dave Syer
*/
@@ -35,6 +51,7 @@ public class EurekaRibbonClientConfiguration {
private String serviceId = "client";
protected static final String VALUE_NOT_SET = "__not__set__";
protected static final String DEFAULT_NAMESPACE = "ribbon";
@Autowired(required = false)
@@ -51,9 +68,10 @@ public class EurekaRibbonClientConfiguration {
@PostConstruct
public void preprocess() {
if (clientConfig != null
if (this.clientConfig != null
&& ConfigurationManager.getDeploymentContext().getValue(ContextKey.zone) == null) {
String[] zones = clientConfig.getAvailabilityZones(clientConfig.getRegion());
String[] zones = this.clientConfig.getAvailabilityZones(this.clientConfig
.getRegion());
String zone = zones != null && zones.length > 0 ? zones[0] : null;
if (zone != null) {
// You can set this with archaius.deployment.* (maybe requires
@@ -63,15 +81,15 @@ public class EurekaRibbonClientConfiguration {
}
}
// TODO: should this look more like hibernate spring boot props?
setProp(serviceId, NIWSServerListClassName.key(),
setProp(this.serviceId, NIWSServerListClassName.key(),
DiscoveryEnabledNIWSServerList.class.getName());
// FIXME: what should this be?
setProp(serviceId, DeploymentContextBasedVipAddresses.key(), serviceId);
setProp(serviceId, NFLoadBalancerRuleClassName.key(),
setProp(this.serviceId, DeploymentContextBasedVipAddresses.key(), this.serviceId);
setProp(this.serviceId, NFLoadBalancerRuleClassName.key(),
ZoneAvoidanceRule.class.getName());
setProp(serviceId, NIWSServerListFilterClassName.key(),
setProp(this.serviceId, NIWSServerListFilterClassName.key(),
ZonePreferenceServerListFilter.class.getName());
setProp(serviceId, EnableZoneAffinity.key(), "true");
setProp(this.serviceId, EnableZoneAffinity.key(), "true");
}
protected void setProp(String serviceId, String suffix, String value) {

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.ribbon.eureka;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
@@ -29,7 +30,6 @@ import com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList;
/**
* @author Dave Syer
*
*/
@Configuration
@EnableConfigurationProperties
@@ -39,4 +39,5 @@ import com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList;
@AutoConfigureAfter(RibbonAutoConfiguration.class)
@RibbonClients(defaultConfiguration = EurekaRibbonClientConfiguration.class)
public class RibbonEurekaAutoConfiguration {
}

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.ribbon.eureka;
import java.util.ArrayList;
@@ -30,32 +31,33 @@ import com.netflix.loadbalancer.ZoneAffinityServerListFilter;
/**
* A filter that actively prefers the local zone (as defined by the deployment context, or
* the Eureka instance metadata).
*
* @author Dave Syer
*
* TODO: move out of ribbon.eureka package since it has nothing specific to eureka
* @author Dave Syer
*/
@Data
@EqualsAndHashCode(callSuper=false)
@EqualsAndHashCode(callSuper = false)
public class ZonePreferenceServerListFilter extends ZoneAffinityServerListFilter<Server> {
// TODO: move out of ribbon.eureka package since it has nothing specific to eureka
private String zone;
@Override
public void initWithNiwsConfig(IClientConfig niwsClientConfig) {
super.initWithNiwsConfig(niwsClientConfig);
if (ConfigurationManager.getDeploymentContext() != null) {
zone = ConfigurationManager.getDeploymentContext().getValue(ContextKey.zone);
this.zone = ConfigurationManager.getDeploymentContext().getValue(
ContextKey.zone);
}
}
@Override
public List<Server> getFilteredListOfServers(List<Server> servers) {
List<Server> output = super.getFilteredListOfServers(servers);
if (zone != null && output.size() == servers.size()) {
if (this.zone != null && output.size() == servers.size()) {
List<Server> local = new ArrayList<Server>();
for (Server server : output) {
if (zone.equalsIgnoreCase(server.getZone())) {
if (this.zone.equalsIgnoreCase(server.getZone())) {
local.add(server);
}
}

View File

@@ -22,6 +22,7 @@ import java.util.List;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.boot.actuate.metrics.Metric;
import org.springframework.boot.actuate.metrics.reader.MetricReader;
@@ -38,7 +39,7 @@ import com.netflix.servo.publish.PollScheduler;
/**
* {@link MetricReader} implementation that registers a {@link MetricObserver} with the
* Netflix Servo library and exposes Servo metrics to the <code>/metric</code> endpoint.
*
*
* @author Dave Syer
* @author Christian Dupuis
*/
@@ -88,11 +89,13 @@ public class ServoMetricCollector implements DisposableBean {
.append(config.getName()).toString().toLowerCase();
if (servoMetric.hasNumberValue()) {
metrics.set(new Metric<Number>(key, servoMetric.getNumberValue(),
new Date(servoMetric.getTimestamp())));
this.metrics.set(new Metric<Number>(key,
servoMetric.getNumberValue(), new Date(servoMetric
.getTimestamp())));
}
}
}
}
}

View File

@@ -31,8 +31,8 @@ import org.springframework.context.annotation.Configuration;
import com.netflix.servo.monitor.Monitors;
/**
* Auto configuration to configure Servo support.
*
* Auto configuration to configure Servo support.
*
* @author Dave Syer
* @author Christian Dupuis
*/
@@ -40,12 +40,13 @@ import com.netflix.servo.monitor.Monitors;
@ConditionalOnClass({ Monitors.class, MetricReader.class })
@ConditionalOnBean(MetricReader.class)
@AutoConfigureBefore(EndpointAutoConfiguration.class)
@AutoConfigureAfter({MetricRepositoryAutoConfiguration.class})
@AutoConfigureAfter({ MetricRepositoryAutoConfiguration.class })
public class ServoMetricsAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public ServoMetricCollector servoMetricCollector(MetricWriter metrics) {
return new ServoMetricCollector(metrics);
}
}

View File

@@ -1,21 +1,37 @@
package org.springframework.cloud.netflix.zuul;
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Import;
package org.springframework.cloud.netflix.zuul;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Import;
/**
* Sets up a Zuul server endpoint and installs some reverse proxy filters in it, so it can
* forward requests to backend servers. The backends can be registered manually through
* configuration or via Eureka.
*
*
* @see EnableZuulServer for how to get a Zuul server without any proxying
*
*
* @author Spencer Gibb
* @author Dave Syer
*/
@@ -25,4 +41,5 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Import(ZuulProxyConfiguration.class)
public @interface EnableZuulProxy {
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.zuul;
import java.lang.annotation.Documented;
@@ -12,9 +28,9 @@ import org.springframework.context.annotation.Import;
* Set up the application to act as a generic Zuul server without any built-in reverse
* proxy features. The routes into the Zuul server can be configured through
* {@link ZuulProperties} (by default there are none).
*
*
* @see EnableZuulProxy to see how to get reverse proxy out of the box
*
*
* @author Spencer Gibb
*/
@Target(ElementType.TYPE)
@@ -22,4 +38,5 @@ import org.springframework.context.annotation.Import;
@Documented
@Import(ZuulConfiguration.class)
public @interface EnableZuulServer {
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.zuul;
import java.util.Collection;
@@ -41,12 +57,12 @@ public class ProxyRouteLocator implements RouteLocator {
}
public void addRoute(String path, String location) {
staticRoutes.put(path, new ZuulRoute(path, location));
this.staticRoutes.put(path, new ZuulRoute(path, location));
resetRoutes();
}
public void addRoute(ZuulRoute route) {
staticRoutes.put(route.getPath(), route);
this.staticRoutes.put(route.getPath(), route);
resetRoutes();
}
@@ -56,34 +72,30 @@ public class ProxyRouteLocator implements RouteLocator {
}
public Map<String, String> getRoutes() {
if (routes.get() == null) {
routes.set(locateRoutes());
if (this.routes.get() == null) {
this.routes.set(locateRoutes());
}
Map<String, String> values = new LinkedHashMap<>();
for (String key : routes.get().keySet()) {
for (String key : this.routes.get().keySet()) {
String url = key;
values.put(url, routes.get().get(key).getLocation());
values.put(url, this.routes.get().get(key).getLocation());
}
return values;
}
public ProxyRouteSpec getMatchingRoute(String path) {
String location = null;
String targetPath = null;
String id = null;
String prefix = properties.getPrefix();
for (Entry<String, ZuulRoute> entry : routes.get().entrySet()) {
String prefix = this.properties.getPrefix();
for (Entry<String, ZuulRoute> entry : this.routes.get().entrySet()) {
String pattern = entry.getKey();
if (pathMatcher.match(pattern, path)) {
if (this.pathMatcher.match(pattern, path)) {
ZuulRoute route = entry.getValue();
id = route.getId();
location = route.getLocation();
targetPath = path;
if (path.startsWith(prefix) && properties.isStripPrefix()) {
if (path.startsWith(prefix) && this.properties.isStripPrefix()) {
targetPath = path.substring(prefix.length());
}
if (route.isStripPrefix()) {
@@ -97,68 +109,57 @@ public class ProxyRouteLocator implements RouteLocator {
break;
}
}
return location == null ? null : new ProxyRouteSpec(id, targetPath, location,
prefix);
return (location == null ? null : new ProxyRouteSpec(id, targetPath, location,
prefix));
}
public void resetRoutes() {
routes.set(locateRoutes());
this.routes.set(locateRoutes());
}
protected LinkedHashMap<String, ZuulRoute> locateRoutes() {
LinkedHashMap<String, ZuulRoute> routesMap = new LinkedHashMap<>();
addConfiguredRoutes(routesMap);
routesMap.putAll(staticRoutes);
if (discovery != null) {
routesMap.putAll(this.staticRoutes);
if (this.discovery != null) {
// Add routes for discovery services by default
List<String> services = discovery.getServices();
List<String> services = this.discovery.getServices();
for (String serviceId : services) {
// Ignore specifically ignored services and those that were manually
// configured
String key = "/" + serviceId + "/**";
if (!properties.getIgnoredServices().contains(serviceId)
if (!this.properties.getIgnoredServices().contains(serviceId)
&& !routesMap.containsKey(key)) {
routesMap.put(key, new ZuulRoute(key, serviceId));
}
}
}
if (routesMap.get(DEFAULT_ROUTE) != null) {
ZuulRoute defaultRoute = routesMap.get(DEFAULT_ROUTE);
// Move the defaultServiceId to the end
routesMap.remove(DEFAULT_ROUTE);
routesMap.put(DEFAULT_ROUTE, defaultRoute);
}
LinkedHashMap<String, ZuulRoute> values = new LinkedHashMap<>();
for (Entry<String, ZuulRoute> entry : routesMap.entrySet()) {
String path = entry.getKey();
// Prepend with slash if not already present.
if (!path.startsWith("/")) {
path = "/" + path;
}
if (StringUtils.hasText(properties.getPrefix())) {
path = properties.getPrefix() + path;
if (StringUtils.hasText(this.properties.getPrefix())) {
path = this.properties.getPrefix() + path;
if (!path.startsWith("/")) {
path = "/" + path;
}
}
values.put(path, entry.getValue());
}
return values;
}
protected void addConfiguredRoutes(Map<String, ZuulRoute> routes) {
Map<String, ZuulRoute> routeEntries = properties.getRoutes();
Map<String, ZuulRoute> routeEntries = this.properties.getRoutes();
for (ZuulRoute entry : routeEntries.values()) {
String route = entry.getPath();
if (routes.containsKey(route)) {
@@ -171,23 +172,22 @@ public class ProxyRouteLocator implements RouteLocator {
public String getTargetPath(String matchingRoute, String requestURI) {
String path = getRoutes().get(matchingRoute);
if (path == null) {
path = requestURI;
}
else {
}
return path;
return (path != null ? path : requestURI);
}
@Data
@AllArgsConstructor
public static class ProxyRouteSpec {
private String id;
private String path;
private String location;
private String prefix;
}
}

View File

@@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.zuul;
import java.util.Collection;
/**
* @author Dave Syer
*
*/
public interface RouteLocator {

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.zuul;
import java.util.Map;
@@ -16,7 +32,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
/**
* Endpoint to display and reset the zuul proxy routes
*
*
* @author Spencer Gibb
* @author Dave Syer
*/
@@ -24,6 +40,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
public class RoutesEndpoint implements MvcEndpoint, ApplicationEventPublisherAware {
private ProxyRouteLocator routes;
private ApplicationEventPublisher publisher;
@Override
@@ -40,7 +57,7 @@ public class RoutesEndpoint implements MvcEndpoint, ApplicationEventPublisherAwa
@ResponseBody
@ManagedOperation
public Map<String, String> reset() {
publisher.publishEvent(new RoutesRefreshedEvent(routes));
this.publisher.publishEvent(new RoutesRefreshedEvent(this.routes));
return getRoutes();
}
@@ -48,7 +65,7 @@ public class RoutesEndpoint implements MvcEndpoint, ApplicationEventPublisherAwa
@ResponseBody
@ManagedAttribute
public Map<String, String> getRoutes() {
return routes.getRoutes();
return this.routes.getRoutes();
}
@Override

View File

@@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.zuul;
import org.springframework.context.ApplicationEvent;
/**
* @author Dave Syer
*
*/
@SuppressWarnings("serial")
public class RoutesRefreshedEvent extends ApplicationEvent {
@@ -32,7 +32,7 @@ public class RoutesRefreshedEvent extends ApplicationEvent {
}
public RouteLocator getLocator() {
return locator;
return this.locator;
}
}

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.zuul;
import java.util.Collection;
@@ -22,7 +23,6 @@ import org.springframework.cloud.netflix.zuul.ZuulProperties.ZuulRoute;
/**
* @author Dave Syer
*
*/
public class SimpleRouteLocator implements RouteLocator {
@@ -35,7 +35,7 @@ public class SimpleRouteLocator implements RouteLocator {
@Override
public Collection<String> getRoutePaths() {
Collection<String> paths = new LinkedHashSet<String>();
for (ZuulRoute route : properties.getRoutes().values()) {
for (ZuulRoute route : this.properties.getRoutes().values()) {
paths.add(route.getPath());
}
return paths;

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.zuul;
import java.util.Map;
@@ -34,7 +50,7 @@ public class ZuulConfiguration {
@Bean
public RouteLocator routeLocator() {
return new SimpleRouteLocator(zuulProperties);
return new SimpleRouteLocator(this.zuulProperties);
}
@Bean
@@ -47,40 +63,13 @@ public class ZuulConfiguration {
return new ZuulHandlerMapping(routes, zuulController());
}
@Configuration
protected static class ZuulFilterConfiguration {
@Autowired
private Map<String, ZuulFilter> filters;
@Bean
public ZuulFilterInitializer zuulFilterInitializer() {
return new ZuulFilterInitializer(filters);
}
}
@Bean
public ApplicationListener<ApplicationEvent> zuulRefreshRoutesListener() {
return new ZuulRefreshListener();
}
private static class ZuulRefreshListener implements
ApplicationListener<ApplicationEvent> {
@Autowired
private ZuulHandlerMapping zuulHandlerMapping;
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ContextRefreshedEvent
|| event instanceof RefreshScopeRefreshedEvent)
zuulHandlerMapping.registerHandlers();
}
}
// pre filters
@Bean
public FormBodyWrapperFilter formBodyWrapperFilter() {
return new FormBodyWrapperFilter();
@@ -97,6 +86,7 @@ public class ZuulConfiguration {
}
// post filters
@Bean
public SendResponseFilter sendResponseFilter() {
return new SendResponseFilter();
@@ -107,4 +97,33 @@ public class ZuulConfiguration {
return new SendErrorFilter();
}
@Configuration
protected static class ZuulFilterConfiguration {
@Autowired
private Map<String, ZuulFilter> filters;
@Bean
public ZuulFilterInitializer zuulFilterInitializer() {
return new ZuulFilterInitializer(this.filters);
}
}
private static class ZuulRefreshListener implements
ApplicationListener<ApplicationEvent> {
@Autowired
private ZuulHandlerMapping zuulHandlerMapping;
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ContextRefreshedEvent
|| event instanceof RefreshScopeRefreshedEvent) {
this.zuulHandlerMapping.registerHandlers();
}
}
}
}

View File

@@ -1,31 +1,51 @@
package org.springframework.cloud.netflix.zuul;
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.http.ZuulServlet;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.ServletWrappingController;
package org.springframework.cloud.netflix.zuul;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.ServletWrappingController;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.http.ZuulServlet;
/**
* @author Spencer Gibb
*/
public class ZuulController extends ServletWrappingController {
public ZuulController() {
setServletClass(ZuulServlet.class);
setServletName("zuul");
setSupportedMethods((String[])null); // Allow all
}
public ZuulController() {
setServletClass(ZuulServlet.class);
setServletName("zuul");
setSupportedMethods((String[]) null); // Allow all
}
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception {
try {
return super.handleRequestInternal(request, response);
}
finally {
// @see com.netflix.zuul.context.ContextLifecycleFilter.doFilter
RequestContext.getCurrentContext().unset();
}
}
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
try {
return super.handleRequestInternal(request, response);
} finally {
// @see com.netflix.zuul.context.ContextLifecycleFilter.doFilter
RequestContext.getCurrentContext().unset();
}
}
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.zuul;
import java.lang.reflect.Field;
@@ -17,43 +33,44 @@ import com.netflix.zuul.monitoring.MonitoringHelper;
/**
* @author Spencer Gibb
*
* TODO: .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
*
* TODO: .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
*/
public class ZuulFilterInitializer implements ServletContextListener {
private static final Logger LOGGER = LoggerFactory.getLogger(ZuulFilterInitializer.class);
private static final Logger LOGGER = LoggerFactory
.getLogger(ZuulFilterInitializer.class);
private Map<String, ZuulFilter> filters;
private Map<String, ZuulFilter> filters;
public ZuulFilterInitializer(Map<String, ZuulFilter> filters) {
this.filters = filters;
}
@Override
public void contextInitialized(ServletContextEvent sce) {
public void contextInitialized(ServletContextEvent sce) {
LOGGER.info("Starting filter initializer context listener");
LOGGER.info("Starting filter initializer context listener");
//FIXME: mocks monitoring infrastructure as we don't need it for this simple app
MonitoringHelper.initMocks();
// FIXME: mocks monitoring infrastructure as we don't need it for this simple app
MonitoringHelper.initMocks();
FilterRegistry registry = FilterRegistry.instance();
FilterRegistry registry = FilterRegistry.instance();
for (Map.Entry<String, ZuulFilter> entry : filters.entrySet()) {
registry.put(entry.getKey(), entry.getValue());
}
}
for (Map.Entry<String, ZuulFilter> entry : this.filters.entrySet()) {
registry.put(entry.getKey(), entry.getValue());
}
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
LOGGER.info("Stopping filter initializer context listener");
FilterRegistry registry = FilterRegistry.instance();
for (Map.Entry<String, ZuulFilter> entry : filters.entrySet()) {
registry.remove(entry.getKey());
}
clearLoaderCache();
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
LOGGER.info("Stopping filter initializer context listener");
FilterRegistry registry = FilterRegistry.instance();
for (Map.Entry<String, ZuulFilter> entry : this.filters.entrySet()) {
registry.remove(entry.getKey());
}
clearLoaderCache();
}
private void clearLoaderCache() {
FilterLoader instance = FilterLoader.getInstance();
@@ -64,24 +81,17 @@ public class ZuulFilterInitializer implements ServletContextListener {
cache.clear();
}
/*private void initGroovyFilterManager() {
//TODO: support groovy filters loaded from filesystem in proxy
FilterLoader.getInstance().setCompiler(new GroovyCompiler());
final String scriptRoot = props.getFilterRoot();
LOGGER.info("Using file system script: " + scriptRoot);
try {
FilterFileManager.setFilenameFilter(new GroovyFileFilter());
FilterFileManager.init(5,
scriptRoot + "/pre",
scriptRoot + "/route",
scriptRoot + "/post"
);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}*/
/*
* private void initGroovyFilterManager() {
*
* //TODO: support groovy filters loaded from filesystem in proxy
* FilterLoader.getInstance().setCompiler(new GroovyCompiler());
*
* final String scriptRoot = props.getFilterRoot();
* LOGGER.info("Using file system script: " + scriptRoot);
*
* try { FilterFileManager.setFilenameFilter(new GroovyFileFilter());
* FilterFileManager.init(5, scriptRoot + "/pre", scriptRoot + "/route", scriptRoot +
* "/post" ); } catch (Exception e) { throw new RuntimeException(e); } }
*/
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.zuul;
import java.util.Collection;
@@ -7,15 +23,15 @@ import org.springframework.web.servlet.handler.AbstractUrlHandlerMapping;
/**
* MVC HandlerMapping that maps incoming request paths to remote services.
*
*
* @author Spencer Gibb
* @author Dave Syer
*/
public class ZuulHandlerMapping extends AbstractUrlHandlerMapping {
private RouteLocator routeLocator;
private final RouteLocator routeLocator;
private ZuulController zuul;
private final ZuulController zuul;
@Autowired
public ZuulHandlerMapping(RouteLocator routeLocator, ZuulController zuul) {
@@ -25,13 +41,13 @@ public class ZuulHandlerMapping extends AbstractUrlHandlerMapping {
}
protected void registerHandlers() {
Collection<String> routes = routeLocator.getRoutePaths();
Collection<String> routes = this.routeLocator.getRoutePaths();
if (routes.isEmpty()) {
logger.warn("No routes found from ProxyRouteLocator");
this.logger.warn("No routes found from ProxyRouteLocator");
}
else {
for (String url : routes) {
registerHandler(url, zuul);
registerHandler(url, this.zuul);
}
}
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.zuul;
import java.util.ArrayList;
@@ -22,10 +38,15 @@ import org.springframework.util.StringUtils;
@Data
@ConfigurationProperties("zuul")
public class ZuulProperties {
private String prefix = "";
private boolean stripPrefix = true;
private Map<String, ZuulRoute> routes = new LinkedHashMap<String, ZuulRoute>();
private boolean addProxyHeaders = true;
private List<String> ignoredServices = new ArrayList<String>();
@PostConstruct
@@ -48,10 +69,15 @@ public class ZuulProperties {
@AllArgsConstructor
@NoArgsConstructor
public static class ZuulRoute {
private String id;
private String path;
private String serviceId;
private String url;
private boolean stripPrefix = true;
public ZuulRoute(String text) {
@@ -78,19 +104,19 @@ public class ZuulProperties {
}
public String getLocation() {
if (StringUtils.hasText(url)) {
return url;
if (StringUtils.hasText(this.url)) {
return this.url;
}
return serviceId;
return this.serviceId;
}
public void setLocation(String location) {
if (location != null
&& (location.startsWith("http:") || location.startsWith("https:"))) {
url = location;
this.url = location;
}
else {
serviceId = location;
this.serviceId = location;
}
}
@@ -99,6 +125,7 @@ public class ZuulProperties {
path = path.replace("/*", "").replace("*", "");
return path;
}
}
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.zuul;
import java.util.concurrent.atomic.AtomicReference;
@@ -42,44 +58,31 @@ public class ZuulProxyConfiguration extends ZuulConfiguration {
@Bean
@Override
public ProxyRouteLocator routeLocator() {
return new ProxyRouteLocator(discovery, zuulProperties);
}
@Configuration
@ConditionalOnClass(Endpoint.class)
protected static class RoutesEndpointConfuguration {
@Autowired
private ProxyRouteLocator routeLocator;
@Bean
// @RefreshScope
public RoutesEndpoint zuulEndpoint() {
return new RoutesEndpoint(routeLocator);
}
return new ProxyRouteLocator(this.discovery, this.zuulProperties);
}
// pre filters
@Bean
public PreDecorationFilter preDecorationFilter() {
return new PreDecorationFilter(routeLocator(), zuulProperties);
return new PreDecorationFilter(routeLocator(), this.zuulProperties);
}
// route filters
@Bean
public RibbonRoutingFilter ribbonRoutingFilter() {
ProxyRequestHelper helper = new ProxyRequestHelper();
if (traces != null) {
helper.setTraces(traces);
if (this.traces != null) {
helper.setTraces(this.traces);
}
RibbonRoutingFilter filter = new RibbonRoutingFilter(helper, clientFactory);
RibbonRoutingFilter filter = new RibbonRoutingFilter(helper, this.clientFactory);
return filter;
}
@Bean
public SimpleHostRoutingFilter simpleHostRoutingFilter() {
ProxyRequestHelper helper = new ProxyRequestHelper();
if (traces != null) {
helper.setTraces(traces);
if (this.traces != null) {
helper.setTraces(this.traces);
}
return new SimpleHostRoutingFilter(helper);
}
@@ -90,6 +93,21 @@ public class ZuulProxyConfiguration extends ZuulConfiguration {
return new ZuulRefreshListener();
}
@Configuration
@ConditionalOnClass(Endpoint.class)
protected static class RoutesEndpointConfuguration {
@Autowired
private ProxyRouteLocator routeLocator;
@Bean
// @RefreshScope
public RoutesEndpoint zuulEndpoint() {
return new RoutesEndpoint(this.routeLocator);
}
}
private static class ZuulRefreshListener implements
ApplicationListener<ApplicationEvent> {
@@ -110,9 +128,9 @@ public class ZuulProxyConfiguration extends ZuulConfiguration {
}
else if (event instanceof DiscoveryHeartbeatEvent) {
DiscoveryHeartbeatEvent e = (DiscoveryHeartbeatEvent) event;
if (latestHeartbeat.get() == null
|| !latestHeartbeat.get().equals(e.getValue())) {
latestHeartbeat.set(e.getValue());
if (this.latestHeartbeat.get() == null
|| !this.latestHeartbeat.get().equals(e.getValue())) {
this.latestHeartbeat.set(e.getValue());
reset();
}
}
@@ -120,8 +138,8 @@ public class ZuulProxyConfiguration extends ZuulConfiguration {
}
private void reset() {
routeLocator.resetRoutes();
zuulHandlerMapping.registerHandlers();
this.routeLocator.resetRoutes();
this.zuulHandlerMapping.registerHandlers();
}
}

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.zuul.filters;
import java.io.IOException;
@@ -39,7 +40,6 @@ import com.netflix.zuul.util.HTTPRequestUtils;
/**
* @author Dave Syer
*
*/
public class ProxyRequestHelper {
@@ -59,15 +59,12 @@ public class ProxyRequestHelper {
public MultiValueMap<String, String> buildZuulRequestQueryParams(
HttpServletRequest request) {
Map<String, List<String>> map = HTTPRequestUtils.getInstance().getQueryParams();
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
if (map == null)
if (map == null) {
return params;
}
for (String key : map.keySet()) {
for (String value : map.get(key)) {
params.add(key, value);
}
@@ -77,41 +74,34 @@ public class ProxyRequestHelper {
public MultiValueMap<String, String> buildZuulRequestHeaders(
HttpServletRequest request) {
RequestContext context = RequestContext.getCurrentContext();
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
Enumeration<?> headerNames = request.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String name = (String) headerNames.nextElement();
String value = request.getHeader(name);
if (isIncludedHeader(name))
if (isIncludedHeader(name)) {
headers.set(name, value);
}
}
}
Map<String, String> zuulRequestHeaders = context.getZuulRequestHeaders();
for (String header : zuulRequestHeaders.keySet()) {
headers.set(header, zuulRequestHeaders.get(header));
}
headers.set("accept-encoding", "deflate, gzip");
return headers;
}
public void setResponse(int status, InputStream entity,
MultiValueMap<String, String> headers) throws IOException {
RequestContext context = RequestContext.getCurrentContext();
RequestContext.getCurrentContext().setResponseStatusCode(status);
if (entity != null) {
RequestContext.getCurrentContext().setResponseDataStream(entity);
}
boolean isOriginResponseGzipped = false;
if (headers.containsKey(CONTENT_ENCODING)) {
Collection<String> collection = headers.get(CONTENT_ENCODING);
for (String header : collection) {
@@ -122,22 +112,19 @@ public class ProxyRequestHelper {
}
}
context.setResponseGZipped(isOriginResponseGzipped);
for (Entry<String, List<String>> header : headers.entrySet()) {
RequestContext ctx = RequestContext.getCurrentContext();
String name = header.getKey();
for (String value : header.getValue()) {
ctx.addOriginResponseHeader(name, value);
if (name.equalsIgnoreCase("content-length"))
if (name.equalsIgnoreCase("content-length")) {
ctx.setOriginContentLength(value);
}
if (isIncludedHeader(name)) {
ctx.addZuulResponseHeader(name, value);
}
}
}
}
public void addIgnoredHeaders(String... names) {
@@ -177,10 +164,8 @@ public class ProxyRequestHelper {
public Map<String, Object> debug(String verb, String uri,
MultiValueMap<String, String> headers, MultiValueMap<String, String> params,
InputStream requestEntity) throws IOException {
Map<String, Object> info = new LinkedHashMap<String, Object>();
if (traces != null) {
if (this.traces != null) {
RequestContext context = RequestContext.getCurrentContext();
StringBuilder query = new StringBuilder();
for (String param : params.keySet()) {
@@ -196,7 +181,6 @@ public class ProxyRequestHelper {
info.put("query", query.toString());
info.put("remote", true);
info.put("proxy", context.get("proxy"));
Map<String, Object> trace = new LinkedHashMap<String, Object>();
Map<String, Object> input = new LinkedHashMap<String, Object>();
trace.put("request", input);
@@ -209,14 +193,13 @@ public class ProxyRequestHelper {
}
input.put(entry.getKey(), value);
}
RequestContext ctx = RequestContext.getCurrentContext();
if (!ctx.isChunkedRequestBody()) {
if (requestEntity != null) {
debugRequestEntity(info, ctx.getRequest().getInputStream());
}
}
traces.add(info);
this.traces.add(info);
return info;
}
return info;
@@ -224,7 +207,7 @@ public class ProxyRequestHelper {
public void appendDebug(Map<String, Object> info, int status,
MultiValueMap<String, String> headers) {
if (traces != null) {
if (this.traces != null) {
@SuppressWarnings("unchecked")
Map<String, Object> trace = (Map<String, Object>) info.get("headers");
Map<String, Object> output = new LinkedHashMap<String, Object>();
@@ -249,4 +232,4 @@ public class ProxyRequestHelper {
}
}
}
}

View File

@@ -1,12 +1,30 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.zuul.filters.post;
import javax.servlet.RequestDispatcher;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import com.google.common.base.Throwables;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import javax.servlet.RequestDispatcher;
/**
* @author Spencer Gibb
@@ -14,53 +32,57 @@ import javax.servlet.RequestDispatcher;
@Slf4j
public class SendErrorFilter extends ZuulFilter {
protected static final String SEND_ERROR_FILTER_RAN = "sendErrorFilter.ran";
protected static final String SEND_ERROR_FILTER_RAN = "sendErrorFilter.ran";
@Value("${error.path:/error}")
private String errorPath;
@Value("${error.path:/error}")
private String errorPath;
@Override
public String filterType() {
return "post";
}
@Override
public String filterType() {
return "post";
}
@Override
public int filterOrder() {
return 0;
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
RequestContext ctx = RequestContext.getCurrentContext();
//only forward to errorPath if it hasn't been forwarded to already
return ctx.containsKey("error.status_code") && !ctx.getBoolean(SEND_ERROR_FILTER_RAN, false);
}
@Override
public boolean shouldFilter() {
RequestContext ctx = RequestContext.getCurrentContext();
// only forward to errorPath if it hasn't been forwarded to already
return ctx.containsKey("error.status_code")
&& !ctx.getBoolean(SEND_ERROR_FILTER_RAN, false);
}
@Override
public Object run() {
try {
RequestContext ctx = RequestContext.getCurrentContext();
int statusCode = (Integer)ctx.get("error.status_code");
if (ctx.containsKey("error.exception")) {
Object e = ctx.get("error.exception");
log.warn("Error during filtering", Throwable.class.cast(e));
ctx.getRequest().setAttribute("javax.servlet.error.exception", e);
}
ctx.getRequest().setAttribute("javax.servlet.error.status_code", statusCode);
RequestDispatcher dispatcher = ctx.getRequest().getRequestDispatcher(errorPath);
@Override
public Object run() {
try {
RequestContext ctx = RequestContext.getCurrentContext();
int statusCode = (Integer) ctx.get("error.status_code");
if (ctx.containsKey("error.exception")) {
Object e = ctx.get("error.exception");
log.warn("Error during filtering", Throwable.class.cast(e));
ctx.getRequest().setAttribute("javax.servlet.error.exception", e);
}
ctx.getRequest().setAttribute("javax.servlet.error.status_code", statusCode);
RequestDispatcher dispatcher = ctx.getRequest().getRequestDispatcher(
this.errorPath);
if (dispatcher != null) {
ctx.set(SEND_ERROR_FILTER_RAN, true);
if (!ctx.getResponse().isCommitted()) {
dispatcher.forward(ctx.getRequest(), ctx.getResponse());
}
if (!ctx.getResponse().isCommitted()) {
dispatcher.forward(ctx.getRequest(), ctx.getResponse());
}
}
} catch (Exception e) {
Throwables.propagate(e);
}
return null;
}
}
catch (Exception ex) {
Throwables.propagate(ex);
}
return null;
}
public void setErrorPath(String errorPath) {
this.errorPath = errorPath;
}
public void setErrorPath(String errorPath) {
this.errorPath = errorPath;
}
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.zuul.filters.post;
import java.io.ByteArrayInputStream;
@@ -19,17 +35,20 @@ import com.netflix.zuul.constants.ZuulConstants;
import com.netflix.zuul.constants.ZuulHeaders;
import com.netflix.zuul.context.RequestContext;
/**
* @author Spencer Gibb
*/
public class SendResponseFilter extends ZuulFilter {
static DynamicBooleanProperty INCLUDE_DEBUG_HEADER = DynamicPropertyFactory
private static DynamicBooleanProperty INCLUDE_DEBUG_HEADER = DynamicPropertyFactory
.getInstance().getBooleanProperty(ZuulConstants.ZUUL_INCLUDE_DEBUG_HEADER,
false);
static DynamicIntProperty INITIAL_STREAM_BUFFER_SIZE = DynamicPropertyFactory
private static DynamicIntProperty INITIAL_STREAM_BUFFER_SIZE = DynamicPropertyFactory
.getInstance().getIntProperty(ZuulConstants.ZUUL_INITIAL_STREAM_BUFFER_SIZE,
1024);
static DynamicBooleanProperty SET_CONTENT_LENGTH = DynamicPropertyFactory
private static DynamicBooleanProperty SET_CONTENT_LENGTH = DynamicPropertyFactory
.getInstance().getBooleanProperty(ZuulConstants.ZUUL_SET_CONTENT_LENGTH,
false);
@@ -43,33 +62,33 @@ public class SendResponseFilter extends ZuulFilter {
return 1000;
}
@Override
public boolean shouldFilter() {
return !RequestContext.getCurrentContext().getZuulResponseHeaders().isEmpty()
|| RequestContext.getCurrentContext().getResponseDataStream() != null
|| RequestContext.getCurrentContext().getResponseBody() != null;
}
@Override
public Object run() {
try {
addResponseHeaders();
writeResponse();
}
catch (Exception e) {
Throwables.propagate(e);
catch (Exception ex) {
Throwables.propagate(ex);
}
return null;
}
void writeResponse() throws Exception {
private void writeResponse() throws Exception {
RequestContext context = RequestContext.getCurrentContext();
// there is no body to send
if (context.getResponseBody() == null && context.getResponseDataStream() == null)
if (context.getResponseBody() == null && context.getResponseDataStream() == null) {
return;
}
HttpServletResponse servletResponse = context.getResponse();
servletResponse.setCharacterEncoding("UTF-8");
OutputStream outStream = servletResponse.getOutputStream();
InputStream is = null;
try {
@@ -78,13 +97,12 @@ public class SendResponseFilter extends ZuulFilter {
writeResponse(new ByteArrayInputStream(body.getBytes()), outStream);
return;
}
boolean isGzipRequested = false;
final String requestEncoding = context.getRequest().getHeader(
ZuulHeaders.ACCEPT_ENCODING);
if (requestEncoding != null && requestEncoding.equals("gzip"))
if (requestEncoding != null && requestEncoding.equals("gzip")) {
isGzipRequested = true;
}
is = context.getResponseDataStream();
InputStream inputStream = is;
if (is != null) {
@@ -93,36 +111,34 @@ public class SendResponseFilter extends ZuulFilter {
// decompress stream
// before sending to client
// else, stream gzip directly to client
if (context.getResponseGZipped() && !isGzipRequested)
if (context.getResponseGZipped() && !isGzipRequested) {
try {
inputStream = new GZIPInputStream(is);
}
catch (java.util.zip.ZipException e) {
System.out
.println("gzip expected but not received assuming unencoded response"
+ RequestContext.getCurrentContext()
.getRequest().getRequestURL()
.toString());
catch (java.util.zip.ZipException ex) {
System.out.println("gzip expected but not "
+ "received assuming unencoded response"
+ RequestContext.getCurrentContext().getRequest()
.getRequestURL().toString());
inputStream = is;
}
else if (context.getResponseGZipped() && isGzipRequested)
}
else if (context.getResponseGZipped() && isGzipRequested) {
servletResponse.setHeader(ZuulHeaders.CONTENT_ENCODING, "gzip");
}
writeResponse(inputStream, outStream);
}
}
}
finally {
try {
if (is != null)
if (is != null) {
is.close();
}
outStream.flush();
outStream.close();
}
catch (IOException e) {
catch (IOException ex) {
}
}
}
@@ -131,19 +147,18 @@ public class SendResponseFilter extends ZuulFilter {
byte[] bytes = new byte[INITIAL_STREAM_BUFFER_SIZE.get()];
int bytesRead = -1;
while ((bytesRead = zin.read(bytes)) != -1) {
// TODO
// if (Debug.debugRequest() && !Debug.debugRequestHeadersOnly()) {
// Debug.addRequestDebug("OUTBOUND: < " + new String(bytes, 0, bytesRead));
// }
try {
out.write(bytes, 0, bytesRead);
out.flush();
}
catch (IOException e) {
catch (IOException ex) {
// ignore
e.printStackTrace();
ex.printStackTrace();
}
// doubles buffer size if previous read filled it
if (bytesRead == bytes.length) {
bytes = new byte[bytes.length * 2];
@@ -155,7 +170,6 @@ public class SendResponseFilter extends ZuulFilter {
RequestContext context = RequestContext.getCurrentContext();
HttpServletResponse servletResponse = context.getResponse();
List<Pair<String, String>> zuulResponseHeaders = context.getZuulResponseHeaders();
@SuppressWarnings("unchecked")
List<String> rd = (List<String>) RequestContext.getCurrentContext().get(
"routingDebug");
@@ -164,25 +178,24 @@ public class SendResponseFilter extends ZuulFilter {
for (String it : rd) {
debugHeader.append("[[[" + it + "]]]");
}
if (INCLUDE_DEBUG_HEADER.get())
if (INCLUDE_DEBUG_HEADER.get()) {
servletResponse.addHeader("X-Zuul-Debug-Header", debugHeader.toString());
}
}
if (zuulResponseHeaders != null) {
for (Pair<String, String> it : zuulResponseHeaders) {
servletResponse.addHeader(it.first(), it.second());
}
}
RequestContext ctx = RequestContext.getCurrentContext();
Integer contentLength = ctx.getOriginContentLength();
// Only inserts Content-Length if origin provides it and origin response is not
// gzipped
if (SET_CONTENT_LENGTH.get()) {
if (contentLength != null && !ctx.getResponseGZipped())
if (contentLength != null && !ctx.getResponseGZipped()) {
servletResponse.setContentLength(contentLength);
}
}
}
}
}

View File

@@ -1,5 +1,23 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.zuul.filters.pre;
import javax.servlet.http.HttpServletRequest;
import com.netflix.config.DynamicBooleanProperty;
import com.netflix.config.DynamicPropertyFactory;
import com.netflix.config.DynamicStringProperty;
@@ -7,42 +25,42 @@ import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.constants.ZuulConstants;
import com.netflix.zuul.context.RequestContext;
import javax.servlet.http.HttpServletRequest;
/**
* @author Spencer Gibb
*/
public class DebugFilter extends ZuulFilter {
static final DynamicBooleanProperty routingDebug = DynamicPropertyFactory.getInstance()
.getBooleanProperty(ZuulConstants.ZUUL_DEBUG_REQUEST, false);
static final DynamicStringProperty debugParameter = DynamicPropertyFactory.getInstance()
.getStringProperty(ZuulConstants.ZUUL_DEBUG_PARAMETER, "debug");
private static final DynamicBooleanProperty ROUTING_DEBUG = DynamicPropertyFactory
.getInstance().getBooleanProperty(ZuulConstants.ZUUL_DEBUG_REQUEST, false);
@Override
public String filterType() {
return "pre";
}
private static final DynamicStringProperty DEBUG_PARAMETER = DynamicPropertyFactory
.getInstance().getStringProperty(ZuulConstants.ZUUL_DEBUG_PARAMETER, "debug");
@Override
public int filterOrder() {
return 1;
}
@Override
public String filterType() {
return "pre";
}
public boolean shouldFilter() {
HttpServletRequest request = RequestContext.getCurrentContext().getRequest();
if ("true".equals(request.getParameter(debugParameter.get())))
return true;
@Override
public int filterOrder() {
return 1;
}
return routingDebug.get();
}
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
ctx.setDebugRouting(true);
ctx.setDebugRequest(true);
return null;
}
@Override
public boolean shouldFilter() {
HttpServletRequest request = RequestContext.getCurrentContext().getRequest();
if ("true".equals(request.getParameter(DEBUG_PARAMETER.get()))) {
return true;
}
return ROUTING_DEBUG.get();
}
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
ctx.setDebugRouting(true);
ctx.setDebugRequest(true);
return null;
}
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.zuul.filters.pre;
import java.io.IOException;
@@ -23,13 +39,14 @@ import com.netflix.zuul.http.ServletInputStreamWrapper;
* @author Spencer Gibb
*/
public class FormBodyWrapperFilter extends ZuulFilter {
protected Field requestField = null;
private Field requestField;
public FormBodyWrapperFilter() {
requestField = ReflectionUtils.findField(HttpServletRequestWrapper.class, "req",
HttpServletRequest.class);
Assert.notNull(requestField, "HttpServletRequestWrapper.req field not found");
requestField.setAccessible(true);
this.requestField = ReflectionUtils.findField(HttpServletRequestWrapper.class,
"req", HttpServletRequest.class);
Assert.notNull(this.requestField, "HttpServletRequestWrapper.req field not found");
this.requestField.setAccessible(true);
}
@Override
@@ -47,16 +64,16 @@ public class FormBodyWrapperFilter extends ZuulFilter {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
String contentType = request.getContentType();
//Don't use this filter on GET method
if(contentType == null) {
// Don't use this filter on GET method
if (contentType == null) {
return false;
}
//Only use this filter for MediaType : application/x-www-form-urlencoded
// Only use this filter for MediaType : application/x-www-form-urlencoded
try {
return MediaType.APPLICATION_FORM_URLENCODED.includes(MediaType.valueOf(contentType));
} catch (InvalidMediaTypeException imte) {
return MediaType.APPLICATION_FORM_URLENCODED.includes(MediaType
.valueOf(contentType));
}
catch (InvalidMediaTypeException ex) {
return false;
}
}
@@ -67,11 +84,12 @@ public class FormBodyWrapperFilter extends ZuulFilter {
HttpServletRequest request = ctx.getRequest();
if (request instanceof HttpServletRequestWrapper) {
try {
HttpServletRequest wrapped = (HttpServletRequest) requestField.get(request);
requestField.set(request, new FormBodyRequestWrapper(wrapped));
HttpServletRequest wrapped = (HttpServletRequest) this.requestField
.get(request);
this.requestField.set(request, new FormBodyRequestWrapper(wrapped));
}
catch (IllegalAccessException e) {
Throwables.propagate(e);
catch (IllegalAccessException ex) {
Throwables.propagate(ex);
}
}
else {
@@ -83,6 +101,7 @@ public class FormBodyWrapperFilter extends ZuulFilter {
private class FormBodyRequestWrapper extends HttpServletRequestWrapper {
private HttpServletRequest request;
private byte[] contentData;
public FormBodyRequestWrapper(HttpServletRequest request) {
@@ -92,28 +111,29 @@ public class FormBodyWrapperFilter extends ZuulFilter {
@Override
public int getContentLength() {
if (contentData == null) {
contentData = buildContentData();
if (this.contentData == null) {
this.contentData = buildContentData();
}
return contentData.length;
return this.contentData.length;
}
@Override
public ServletInputStream getInputStream() throws IOException {
if (RequestContext.getCurrentContext().isChunkedRequestBody()) {
return request.getInputStream();
return this.request.getInputStream();
}
else {
if (contentData == null) {
contentData = buildContentData();
if (this.contentData == null) {
this.contentData = buildContentData();
}
return new ServletInputStreamWrapper(contentData);
return new ServletInputStreamWrapper(this.contentData);
}
}
private byte[] buildContentData() {
StringBuilder builder = new StringBuilder();
for (Entry<String, String[]> entry : request.getParameterMap().entrySet()) {
for (Entry<String, String[]> entry : this.request.getParameterMap()
.entrySet()) {
for (String value : entry.getValue()) {
if (builder.length() != 0) {
builder.append("&");
@@ -125,4 +145,5 @@ public class FormBodyWrapperFilter extends ZuulFilter {
}
}
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.zuul.filters.pre;
import java.net.MalformedURLException;
@@ -16,6 +32,7 @@ import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
public class PreDecorationFilter extends ZuulFilter {
private static Logger LOG = LoggerFactory.getLogger(PreDecorationFilter.class);
private ProxyRouteLocator routeLocator;
@@ -45,20 +62,13 @@ public class PreDecorationFilter extends ZuulFilter {
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
final String requestURI = ctx.getRequest().getRequestURI();
ProxyRouteSpec route = routeLocator.getMatchingRoute(requestURI);
ProxyRouteSpec route = this.routeLocator.getMatchingRoute(requestURI);
if (route != null) {
String location = route.getLocation();
if (location != null) {
ctx.put("requestURI", route.getPath());
ctx.put("proxy", route.getId());
if (location.startsWith("http:") || location.startsWith("https:")) {
ctx.setRouteHost(getUrl(location));
ctx.addOriginResponseHeader("X-Zuul-Service", location);
@@ -69,8 +79,7 @@ public class PreDecorationFilter extends ZuulFilter {
ctx.setRouteHost(null);
ctx.addOriginResponseHeader("X-Zuul-ServiceId", location);
}
if (properties.isAddProxyHeaders()) {
if (this.properties.isAddProxyHeaders()) {
ctx.addZuulRequestHeader(
"X-Forwarded-Host",
ctx.getRequest().getServerName() + ":"
@@ -92,8 +101,8 @@ public class PreDecorationFilter extends ZuulFilter {
try {
return new URL(target);
}
catch (MalformedURLException e) {
throw new IllegalStateException("Target URL is malformed", e);
catch (MalformedURLException ex) {
throw new IllegalStateException("Target URL is malformed", ex);
}
}
}

View File

@@ -1,130 +1,161 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.zuul.filters.pre;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Collection;
import javax.servlet.AsyncContext;
import javax.servlet.DispatcherType;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
import com.google.common.base.Throwables;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.http.HttpServletRequestWrapper;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Collection;
/**
* @author Spencer Gibb
*/
public class Servlet30WrapperFilter extends ZuulFilter {
protected Field requestField = null;
public Servlet30WrapperFilter() {
requestField = ReflectionUtils.findField(HttpServletRequestWrapper.class, "req",
HttpServletRequest.class);
Assert.notNull(requestField, "HttpServletRequestWrapper.req field not found");
requestField.setAccessible(true);
}
protected Field requestField = null;
@Override
public String filterType() {
return "pre";
}
public Servlet30WrapperFilter() {
this.requestField = ReflectionUtils.findField(HttpServletRequestWrapper.class,
"req", HttpServletRequest.class);
Assert.notNull(this.requestField, "HttpServletRequestWrapper.req field not found");
this.requestField.setAccessible(true);
}
@Override
public int filterOrder() {
return 0;
}
@Override
public String filterType() {
return "pre";
}
@Override
public boolean shouldFilter() {
return true; //TODO: only if in servlet 3.0 env
}
@Override
public int filterOrder() {
return 0;
}
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
if (request instanceof HttpServletRequestWrapper) {
try {
request = (HttpServletRequest) requestField.get(request);
} catch (IllegalAccessException e) {
Throwables.propagate(e);
}
}
ctx.setRequest(new Servlet30RequestWrapper(request));
//ctx.setResponse(new HttpServletResponseWrapper(ctx.getResponse()));
return null;
}
@Override
public boolean shouldFilter() {
return true; // TODO: only if in servlet 3.0 env
}
private class Servlet30RequestWrapper extends HttpServletRequestWrapper {
private HttpServletRequest request;
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
if (request instanceof HttpServletRequestWrapper) {
try {
request = (HttpServletRequest) this.requestField.get(request);
}
catch (IllegalAccessException ex) {
Throwables.propagate(ex);
}
}
ctx.setRequest(new Servlet30RequestWrapper(request));
// ctx.setResponse(new HttpServletResponseWrapper(ctx.getResponse()));
return null;
}
Servlet30RequestWrapper(HttpServletRequest request) {
super(request);
this.request = request;
}
private class Servlet30RequestWrapper extends HttpServletRequestWrapper {
private HttpServletRequest request;
@Override
public boolean authenticate(HttpServletResponse response) throws IOException, ServletException {
return request.authenticate(response);
}
Servlet30RequestWrapper(HttpServletRequest request) {
super(request);
this.request = request;
}
@Override
public void login(String username, String password) throws ServletException {
request.login(username, password);
}
@Override
public boolean authenticate(HttpServletResponse response) throws IOException,
ServletException {
return this.request.authenticate(response);
}
@Override
public void logout() throws ServletException {
request.logout();
}
@Override
public void login(String username, String password) throws ServletException {
this.request.login(username, password);
}
@Override
public Collection<Part> getParts() throws IOException, IllegalStateException, ServletException {
return request.getParts();
}
@Override
public void logout() throws ServletException {
this.request.logout();
}
@Override
public Part getPart(String name) throws IOException, IllegalStateException, ServletException {
return request.getPart(name);
}
@Override
public Collection<Part> getParts() throws IOException, IllegalStateException,
ServletException {
return this.request.getParts();
}
@Override
public ServletContext getServletContext() {
return request.getServletContext();
}
@Override
public Part getPart(String name) throws IOException, IllegalStateException,
ServletException {
return this.request.getPart(name);
}
@Override
public AsyncContext startAsync() {
return request.startAsync();
}
@Override
public ServletContext getServletContext() {
return this.request.getServletContext();
}
@Override
public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) {
return request.startAsync(servletRequest, servletResponse);
}
@Override
public AsyncContext startAsync() {
return this.request.startAsync();
}
@Override
public boolean isAsyncStarted() {
return request.isAsyncStarted();
}
@Override
public AsyncContext startAsync(ServletRequest servletRequest,
ServletResponse servletResponse) {
return this.request.startAsync(servletRequest, servletResponse);
}
@Override
public boolean isAsyncSupported() {
return request.isAsyncSupported();
}
@Override
public boolean isAsyncStarted() {
return this.request.isAsyncStarted();
}
@Override
public AsyncContext getAsyncContext() {
return request.getAsyncContext();
}
@Override
public boolean isAsyncSupported() {
return this.request.isAsyncSupported();
}
@Override
public AsyncContext getAsyncContext() {
return this.request.getAsyncContext();
}
@Override
public DispatcherType getDispatcherType() {
return this.request.getDispatcherType();
}
}
@Override
public DispatcherType getDispatcherType() {
return request.getDispatcherType();
}
}
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.zuul.filters.route;
import java.io.InputStream;
@@ -11,10 +27,12 @@ import com.netflix.client.http.HttpRequest;
import com.netflix.client.http.HttpRequest.Builder;
import com.netflix.client.http.HttpRequest.Verb;
import com.netflix.client.http.HttpResponse;
import com.netflix.config.DynamicIntProperty;
import com.netflix.config.DynamicPropertyFactory;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandProperties;
import com.netflix.hystrix.HystrixCommandProperties.ExecutionIsolationStrategy;
import com.netflix.niws.client.http.RestClient;
import com.netflix.zuul.constants.ZuulConstants;
import com.netflix.zuul.context.RequestContext;
@@ -22,87 +40,83 @@ import com.netflix.zuul.context.RequestContext;
/**
* Hystrix wrapper around Eureka Ribbon command
*
* see original https://github.com/Netflix/zuul/blob/master/zuul-netflix/src/main/java/com/netflix/zuul/dependency/ribbon/hystrix/RibbonCommand.java
* see original
* https://github.com/Netflix/zuul/blob/master/zuul-netflix/src/main/java/com/
* netflix/zuul/dependency/ribbon/hystrix/RibbonCommand.java
*/
public class RibbonCommand extends HystrixCommand<HttpResponse> {
private RestClient restClient;
private Verb verb;
private URI uri;
private MultivaluedMap<String, String> headers;
private MultivaluedMap<String, String> params;
private InputStream requestEntity;
private RestClient restClient;
public RibbonCommand(RestClient restClient,
Verb verb,
String uri,
MultivaluedMap<String, String> headers,
MultivaluedMap<String, String> params,
InputStream requestEntity) throws URISyntaxException {
this("default", restClient, verb, uri, headers, params, requestEntity);
}
private Verb verb;
public RibbonCommand(String commandKey,
RestClient restClient,
Verb verb,
String uri,
MultivaluedMap<String, String> headers,
MultivaluedMap<String, String> params,
InputStream requestEntity) throws URISyntaxException {
private URI uri;
super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(commandKey)).andCommandPropertiesDefaults(
// we want to default to semaphore-isolation since this wraps
// 2 others commands that are already thread isolated
HystrixCommandProperties.Setter().withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE)
.withExecutionIsolationSemaphoreMaxConcurrentRequests(DynamicPropertyFactory.getInstance().
getIntProperty(ZuulConstants.ZUUL_EUREKA + commandKey + ".semaphore.maxSemaphores", 100).get())));
private MultivaluedMap<String, String> headers;
this.restClient = restClient;
this.verb = verb;
this.uri = new URI(uri);
this.headers = headers;
this.params = params;
this.requestEntity = requestEntity;
}
private MultivaluedMap<String, String> params;
@Override
protected HttpResponse run() throws Exception {
try {
return forward();
} catch (Exception e) {
throw e;
}
}
private InputStream requestEntity;
private HttpResponse forward() throws Exception {
public RibbonCommand(RestClient restClient, Verb verb, String uri,
MultivaluedMap<String, String> headers,
MultivaluedMap<String, String> params, InputStream requestEntity)
throws URISyntaxException {
this("default", restClient, verb, uri, headers, params, requestEntity);
}
RequestContext context = RequestContext.getCurrentContext();
public RibbonCommand(String commandKey, RestClient restClient, Verb verb, String uri,
MultivaluedMap<String, String> headers,
MultivaluedMap<String, String> params, InputStream requestEntity)
throws URISyntaxException {
super(getSetter(commandKey));
this.restClient = restClient;
this.verb = verb;
this.uri = new URI(uri);
this.headers = headers;
this.params = params;
this.requestEntity = requestEntity;
}
Builder builder = HttpRequest.newBuilder().
verb(verb).
uri(uri).
entity(requestEntity);
private static HystrixCommand.Setter getSetter(String commandKey) {
// we want to default to semaphore-isolation since this wraps
// 2 others commands that are already thread isolated
String name = ZuulConstants.ZUUL_EUREKA + commandKey + ".semaphore.maxSemaphores";
DynamicIntProperty value = DynamicPropertyFactory.getInstance().getIntProperty(
name, 100);
HystrixCommandProperties.Setter setter = HystrixCommandProperties.Setter()
.withExecutionIsolationStrategy(ExecutionIsolationStrategy.SEMAPHORE)
.withExecutionIsolationSemaphoreMaxConcurrentRequests(value.get());
return Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(commandKey))
.andCommandPropertiesDefaults(setter);
}
for (String name : headers.keySet()) {
List<String> values = headers.get(name);
for (String value : values) {
builder.header(name, value);
}
}
@Override
protected HttpResponse run() throws Exception {
return forward();
}
for (String name : params.keySet()) {
List<String> values = params.get(name);
for (String value : values) {
builder.queryParams(name, value);
}
}
private HttpResponse forward() throws Exception {
RequestContext context = RequestContext.getCurrentContext();
Builder builder = HttpRequest.newBuilder().verb(this.verb).uri(this.uri)
.entity(this.requestEntity);
for (String name : this.headers.keySet()) {
List<String> values = this.headers.get(name);
for (String value : values) {
builder.header(name, value);
}
}
for (String name : this.params.keySet()) {
List<String> values = this.params.get(name);
for (String value : values) {
builder.queryParams(name, value);
}
}
HttpRequest httpClientRequest = builder.build();
HttpResponse response = this.restClient
.executeWithLoadBalancer(httpClientRequest);
context.set("ribbonResponse", response);
return response;
}
HttpRequest httpClientRequest = builder.build();
HttpResponse response = restClient.executeWithLoadBalancer(httpClientRequest);
context.set("ribbonResponse", response);
return response;
}
}
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.zuul.filters.route;
import java.io.IOException;
@@ -59,25 +75,28 @@ public class RibbonRoutingFilter extends ZuulFilter {
return 10;
}
@Override
public boolean shouldFilter() {
RequestContext ctx = RequestContext.getCurrentContext();
return (ctx.getRouteHost() == null && ctx.get("serviceId") != null && ctx
.sendZuulResponse());
}
@Override
public Object run() {
RequestContext context = RequestContext.getCurrentContext();
HttpServletRequest request = context.getRequest();
MultiValueMap<String, String> headers = helper.buildZuulRequestHeaders(request);
MultiValueMap<String, String> params = helper
MultiValueMap<String, String> headers = this.helper
.buildZuulRequestHeaders(request);
MultiValueMap<String, String> params = this.helper
.buildZuulRequestQueryParams(request);
Verb verb = getVerb(request);
InputStream requestEntity = getRequestBody(request);
String serviceId = (String) context.get("serviceId");
RestClient restClient = clientFactory.getClient(serviceId, RestClient.class);
RestClient restClient = this.clientFactory.getClient(serviceId, RestClient.class);
String uri = request.getRequestURI();
if (context.get("requestURI") != null) {
@@ -92,9 +111,9 @@ public class RibbonRoutingFilter extends ZuulFilter {
setResponse(response);
return response;
}
catch (Exception e) {
catch (Exception ex) {
context.set("error.status_code", HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
context.set("error.exception", e);
context.set("error.exception", ex);
}
return null;
}
@@ -102,29 +121,27 @@ public class RibbonRoutingFilter extends ZuulFilter {
private HttpResponse forward(RestClient restClient, Verb verb, String uri,
MultiValueMap<String, String> headers, MultiValueMap<String, String> params,
InputStream requestEntity) throws Exception {
Map<String, Object> info = helper.debug(verb.verb(), uri, headers, params,
Map<String, Object> info = this.helper.debug(verb.verb(), uri, headers, params,
requestEntity);
RibbonCommand command = new RibbonCommand(restClient, verb, uri,
convertHeaders(headers), convertHeaders(params), requestEntity);
try {
HttpResponse response = command.execute();
helper.appendDebug(info, response.getStatus(),
this.helper.appendDebug(info, response.getStatus(),
revertHeaders(response.getHeaders()));
return response;
}
catch (HystrixRuntimeException e) {
catch (HystrixRuntimeException ex) {
info.put("status", "500");
if (e.getFallbackException() != null
&& e.getFallbackException().getCause() != null
&& e.getFallbackException().getCause() instanceof ClientException) {
ClientException ex = (ClientException) e.getFallbackException()
if (ex.getFallbackException() != null
&& ex.getFallbackException().getCause() != null
&& ex.getFallbackException().getCause() instanceof ClientException) {
ClientException cause = (ClientException) ex.getFallbackException()
.getCause();
throw new ZuulException(ex, "Forwarding error", 500, ex.getErrorType()
.toString());
throw new ZuulException(cause, "Forwarding error", 500, cause
.getErrorType().toString());
}
throw new ZuulException(e, "Forwarding error", 500, e.getFailureType()
throw new ZuulException(ex, "Forwarding error", 500, ex.getFailureType()
.toString());
}
@@ -161,10 +178,9 @@ public class RibbonRoutingFilter extends ZuulFilter {
requestEntity = request.getInputStream();
}
}
catch (IOException e) {
LOG.error("Error during getRequestBody", e);
catch (IOException ex) {
LOG.error("Error during getRequestBody", ex);
}
return requestEntity;
}
@@ -185,7 +201,7 @@ public class RibbonRoutingFilter extends ZuulFilter {
}
private void setResponse(HttpResponse resp) throws ClientException, IOException {
helper.setResponse(resp.getStatus(),
this.helper.setResponse(resp.getStatus(),
!resp.hasEntity() ? null : resp.getInputStream(),
revertHeaders(resp.getHeaders()));
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.zuul.filters.route;
import java.io.IOException;
@@ -78,6 +94,7 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
private static final DynamicIntProperty SOCKET_TIMEOUT = DynamicPropertyFactory
.getInstance().getIntProperty(ZuulConstants.ZUUL_HOST_SOCKET_TIMEOUT_MILLIS,
10000);
private static final DynamicIntProperty CONNECTION_TIMEOUT = DynamicPropertyFactory
.getInstance().getIntProperty(ZuulConstants.ZUUL_HOST_CONNECT_TIMEOUT_MILLIS,
2000);
@@ -85,7 +102,8 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
private static final AtomicReference<HttpClient> CLIENT = new AtomicReference<HttpClient>(
newClient());
private static final Timer CONNECTION_MANAGER_TIMER = new Timer("SimpleHostRoutingFilter.CONNECTION_MANAGER_TIMER", true);
private static final Timer CONNECTION_MANAGER_TIMER = new Timer(
"SimpleHostRoutingFilter.CONNECTION_MANAGER_TIMER", true);
// cleans expired connections at an interval
static {
@@ -96,38 +114,18 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
public void run() {
try {
final HttpClient hc = CLIENT.get();
if (hc == null)
if (hc == null) {
return;
}
hc.getConnectionManager().closeExpiredConnections();
}
catch (Throwable t) {
LOG.error("error closing expired connections", t);
catch (Throwable ex) {
LOG.error("error closing expired connections", ex);
}
}
}, 30000, 5000);
}
private static final ClientConnectionManager newConnectionManager() throws Exception {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", sf, 443));
registry.register(new Scheme("https", sf, 8443));
ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(registry);
cm.setMaxTotal(Integer.parseInt(System.getProperty("zuul.max.host.connections",
"200")));
cm.setDefaultMaxPerRoute(Integer.parseInt(System.getProperty(
"zuul.max.host.connections", "20")));
return cm;
}
private ProxyRequestHelper helper;
public SimpleHostRoutingFilter() {
@@ -153,71 +151,19 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
return 100;
}
@Override
public boolean shouldFilter() {
return RequestContext.getCurrentContext().getRouteHost() != null
&& RequestContext.getCurrentContext().sendZuulResponse();
}
private static final void loadClient() {
final HttpClient oldClient = CLIENT.get();
CLIENT.set(newClient());
if (oldClient != null) {
CONNECTION_MANAGER_TIMER.schedule(new TimerTask() {
@Override
public void run() {
try {
oldClient.getConnectionManager().shutdown();
}
catch (Throwable t) {
LOG.error("error shutting down old connection manager", t);
}
}
}, 30000);
}
}
private static final HttpClient newClient() {
// I could statically cache the connection manager but we will probably want to
// make some of its properties
// dynamic in the near future also
try {
DefaultHttpClient httpclient = new DefaultHttpClient(newConnectionManager());
HttpParams httpParams = httpclient.getParams();
httpParams.setIntParameter(CoreConnectionPNames.SO_TIMEOUT,
SOCKET_TIMEOUT.get());
httpParams.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,
CONNECTION_TIMEOUT.get());
httpclient.setHttpRequestRetryHandler(new DefaultHttpRequestRetryHandler(0,
false));
httpParams.setParameter(ClientPNames.COOKIE_POLICY,
org.apache.http.client.params.CookiePolicy.IGNORE_COOKIES);
httpclient.setRedirectStrategy(new org.apache.http.client.RedirectStrategy() {
@Override
public boolean isRedirected(HttpRequest httpRequest,
HttpResponse httpResponse, HttpContext httpContext) {
return false;
}
@Override
public org.apache.http.client.methods.HttpUriRequest getRedirect(
HttpRequest httpRequest, HttpResponse httpResponse,
HttpContext httpContext) {
return null;
}
});
return httpclient;
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public Object run() {
RequestContext context = RequestContext.getCurrentContext();
HttpServletRequest request = context.getRequest();
MultiValueMap<String, String> headers = helper.buildZuulRequestHeaders(request);
MultiValueMap<String, String> params = helper
MultiValueMap<String, String> headers = this.helper
.buildZuulRequestHeaders(request);
MultiValueMap<String, String> params = this.helper
.buildZuulRequestQueryParams(request);
String verb = getVerb(request);
InputStream requestEntity = getRequestBody(request);
@@ -233,9 +179,9 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
params, requestEntity);
setResponse(response);
}
catch (Exception e) {
catch (Exception ex) {
context.set("error.status_code", HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
context.set("error.exception", e);
context.set("error.exception", ex);
}
return null;
}
@@ -244,16 +190,12 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
HttpServletRequest request, MultiValueMap<String, String> headers,
MultiValueMap<String, String> params, InputStream requestEntity)
throws Exception {
Map<String, Object> info = helper
.debug(verb, uri, headers, params, requestEntity);
Map<String, Object> info = this.helper.debug(verb, uri, headers, params,
requestEntity);
URL host = RequestContext.getCurrentContext().getRouteHost();
HttpHost httpHost = getHttpHost(host);
uri = StringUtils.cleanPath(host.getPath() + uri);
HttpRequest httpRequest;
switch (verb.toUpperCase()) {
case "POST":
HttpPost httpPost = new HttpPost(uri + getQueryString());
@@ -271,13 +213,12 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
httpRequest = new BasicHttpRequest(verb, uri + getQueryString());
LOG.debug(uri + getQueryString());
}
try {
httpRequest.setHeaders(convertHeaders(headers));
LOG.debug(httpHost.getHostName() + " " + httpHost.getPort() + " "
+ httpHost.getSchemeName());
HttpResponse zuulResponse = forwardRequest(httpclient, httpHost, httpRequest);
helper.appendDebug(info, zuulResponse.getStatusLine().getStatusCode(),
this.helper.appendDebug(info, zuulResponse.getStatusLine().getStatusCode(),
revertHeaders(zuulResponse.getAllHeaders()));
return zuulResponse;
}
@@ -287,7 +228,6 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
// immediate deallocation of all system resources
// httpclient.getConnectionManager().shutdown();
}
}
private MultiValueMap<String, String> revertHeaders(Header[] headers) {
@@ -334,7 +274,7 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
try {
requestEntity = request.getInputStream();
}
catch (IOException e) {
catch (IOException ex) {
// no requestBody is ok.
}
return requestEntity;
@@ -346,47 +286,123 @@ public class SimpleHostRoutingFilter extends ZuulFilter {
}
private void setResponse(HttpResponse response) throws IOException {
helper.setResponse(response.getStatusLine().getStatusCode(),
this.helper.setResponse(response.getStatusLine().getStatusCode(),
response.getEntity() == null ? null : response.getEntity().getContent(),
revertHeaders(response.getAllHeaders()));
}
private static ClientConnectionManager newConnectionManager() throws Exception {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", sf, 443));
registry.register(new Scheme("https", sf, 8443));
ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(registry);
cm.setMaxTotal(Integer.parseInt(System.getProperty("zuul.max.host.connections",
"200")));
cm.setDefaultMaxPerRoute(Integer.parseInt(System.getProperty(
"zuul.max.host.connections", "20")));
return cm;
}
private static void loadClient() {
final HttpClient oldClient = CLIENT.get();
CLIENT.set(newClient());
if (oldClient != null) {
CONNECTION_MANAGER_TIMER.schedule(new TimerTask() {
@Override
public void run() {
try {
oldClient.getConnectionManager().shutdown();
}
catch (Throwable ex) {
LOG.error("error shutting down old connection manager", ex);
}
}
}, 30000);
}
}
private static HttpClient newClient() {
// I could statically cache the connection manager but we will probably want to
// make some of its properties
// dynamic in the near future also
try {
DefaultHttpClient httpclient = new DefaultHttpClient(newConnectionManager());
HttpParams httpParams = httpclient.getParams();
httpParams.setIntParameter(CoreConnectionPNames.SO_TIMEOUT,
SOCKET_TIMEOUT.get());
httpParams.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,
CONNECTION_TIMEOUT.get());
httpclient.setHttpRequestRetryHandler(new DefaultHttpRequestRetryHandler(0,
false));
httpParams.setParameter(ClientPNames.COOKIE_POLICY,
org.apache.http.client.params.CookiePolicy.IGNORE_COOKIES);
httpclient.setRedirectStrategy(new org.apache.http.client.RedirectStrategy() {
@Override
public boolean isRedirected(HttpRequest httpRequest,
HttpResponse httpResponse, HttpContext httpContext) {
return false;
}
@Override
public org.apache.http.client.methods.HttpUriRequest getRedirect(
HttpRequest httpRequest, HttpResponse httpResponse,
HttpContext httpContext) {
return null;
}
});
return httpclient;
}
catch (Exception ex) {
throw new RuntimeException(ex);
}
}
public static class MySSLSocketFactory extends SSLSocketFactory {
SSLContext sslContext = SSLContext.getInstance("TLS");
public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException,
KeyManagementException, KeyStoreException, UnrecoverableKeyException {
super(truststore);
TrustManager tm = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
};
TrustManager[] tms = new TrustManager[1];
tms[0] = tm;
sslContext.init(null, tms, null);
this.sslContext.init(null, tms, null);
}
@Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose)
throws IOException, UnknownHostException {
return sslContext.getSocketFactory().createSocket(socket, host, port,
return this.sslContext.getSocketFactory().createSocket(socket, host, port,
autoClose);
}
@Override
public Socket createSocket() throws IOException {
return sslContext.getSocketFactory().createSocket();
return this.sslContext.getSocketFactory().createSocket();
}
}
}
}

View File

@@ -29,7 +29,8 @@ import org.springframework.cloud.netflix.zuul.SimpleZuulServerApplicationTests;
* @author Dave Syer
*/
@RunWith(Suite.class)
@SuiteClasses({ SimpleZuulServerApplicationTests.class, SampleZuulProxyApplicationTests.class })
@SuiteClasses({ SimpleZuulServerApplicationTests.class,
SampleZuulProxyApplicationTests.class })
@Ignore
public class AdhocTestSuite {

View File

@@ -13,34 +13,36 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.archaius;
import static org.junit.Assert.assertNotNull;
package org.springframework.cloud.netflix.archaius;
import org.apache.commons.configuration.AbstractConfiguration;
import org.junit.After;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import static org.junit.Assert.assertNotNull;
/**
* @author Dave Syer
*
*/
public class ArchaiusAutoConfigurationTests {
private AnnotationConfigApplicationContext context;
@After
public void close() {
if (context!=null) {
context.close();
if (this.context != null) {
this.context.close();
}
}
@Test
public void configurationCreated() {
context = new AnnotationConfigApplicationContext(ArchaiusAutoConfiguration.class);
AbstractConfiguration config = context.getBean(ConfigurableEnvironmentConfiguration.class);
this.context = new AnnotationConfigApplicationContext(
ArchaiusAutoConfiguration.class);
AbstractConfiguration config = this.context
.getBean(ConfigurableEnvironmentConfiguration.class);
assertNotNull(config.getString("java.io.tmpdir"));
}

View File

@@ -13,10 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.archaius;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
package org.springframework.cloud.netflix.archaius;
import java.util.Map;
@@ -26,9 +24,11 @@ import org.springframework.core.env.StandardEnvironment;
import com.netflix.config.ConcurrentCompositeConfiguration;
import com.netflix.config.ConfigurationManager;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* @author Dave Syer
*
*/
public class ArchaiusEndpointTests {
@@ -37,17 +37,19 @@ public class ArchaiusEndpointTests {
@Test
public void detectsPropertiesWhenSet() {
ConfigurationManager.getConfigInstance().setProperty("foo", "bar");
assertTrue(endpoint.invoke().containsKey("foo"));
assertTrue(this.endpoint.invoke().containsKey("foo"));
}
@Test
public void doesNotIncludeSpringEnvironment() {
ConcurrentCompositeConfiguration composite = new ConcurrentCompositeConfiguration(ConfigurationManager.getConfigInstance());
ConfigurableEnvironmentConfiguration config = new ConfigurableEnvironmentConfiguration(new StandardEnvironment());
ConcurrentCompositeConfiguration composite = new ConcurrentCompositeConfiguration(
ConfigurationManager.getConfigInstance());
ConfigurableEnvironmentConfiguration config = new ConfigurableEnvironmentConfiguration(
new StandardEnvironment());
assertTrue(config.containsKey("user.dir"));
composite.addConfiguration(config);
ConfigurationManager.getConfigInstance().setProperty("foo", "bar");
Map<String, Object> map = endpoint.invoke();
Map<String, Object> map = this.endpoint.invoke();
assertTrue(map.containsKey("foo"));
assertFalse(map.containsKey("user.dir"));
}

View File

@@ -13,9 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.config;
import static org.junit.Assert.assertEquals;
package org.springframework.cloud.netflix.config;
import org.junit.After;
import org.junit.Test;
@@ -28,9 +27,11 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.DiscoveryClient;
import static org.junit.Assert.assertEquals;
import static org.mockito.BDDMockito.given;
/**
* @author Dave Syer
*
*/
public class DiscoveryClientConfigServiceBootstrapConfigurationTests {
@@ -43,41 +44,45 @@ public class DiscoveryClientConfigServiceBootstrapConfigurationTests {
@After
public void close() {
if (context != null) {
context.close();
if (this.context != null) {
this.context.close();
}
}
@Test
public void offByDefault() throws Exception {
context = new AnnotationConfigApplicationContext(
this.context = new AnnotationConfigApplicationContext(
DiscoveryClientConfigServiceBootstrapConfiguration.class);
assertEquals(0, context.getBeanNamesForType(DiscoveryClient.class).length);
assertEquals(0, this.context.getBeanNamesForType(DiscoveryClient.class).length);
assertEquals(
0,
context.getBeanNamesForType(DiscoveryClientConfigServiceBootstrapConfiguration.class).length);
this.context
.getBeanNamesForType(DiscoveryClientConfigServiceBootstrapConfiguration.class).length);
}
@Test
public void onWhenRequested() throws Exception {
Mockito.when(client.getNextServerFromEureka("CONFIGSERVER", false)).thenReturn(
info);
given(this.client.getNextServerFromEureka("CONFIGSERVER", false)).willReturn(
this.info);
setup("spring.cloud.config.discovery.enabled=true");
assertEquals(
1,
context.getBeanNamesForType(DiscoveryClientConfigServiceBootstrapConfiguration.class).length);
Mockito.verify(client).getNextServerFromEureka("CONFIGSERVER", false);
ConfigClientProperties locator = context.getBean(ConfigClientProperties.class);
this.context
.getBeanNamesForType(DiscoveryClientConfigServiceBootstrapConfiguration.class).length);
Mockito.verify(this.client).getNextServerFromEureka("CONFIGSERVER", false);
ConfigClientProperties locator = this.context
.getBean(ConfigClientProperties.class);
assertEquals("http://foo:7001/", locator.getUri());
}
@Test
public void setsPasssword() throws Exception {
info.getMetadata().put("password", "bar");
Mockito.when(client.getNextServerFromEureka("CONFIGSERVER", false)).thenReturn(
info);
this.info.getMetadata().put("password", "bar");
given(this.client.getNextServerFromEureka("CONFIGSERVER", false)).willReturn(
this.info);
setup("spring.cloud.config.discovery.enabled=true");
ConfigClientProperties locator = context.getBean(ConfigClientProperties.class);
ConfigClientProperties locator = this.context
.getBean(ConfigClientProperties.class);
assertEquals("http://foo:7001/", locator.getUri());
assertEquals("bar", locator.getPassword());
assertEquals("user", locator.getUsername());
@@ -85,23 +90,24 @@ public class DiscoveryClientConfigServiceBootstrapConfigurationTests {
@Test
public void setsPath() throws Exception {
info.getMetadata().put("configPath", "/bar");
Mockito.when(client.getNextServerFromEureka("CONFIGSERVER", false)).thenReturn(
info);
this.info.getMetadata().put("configPath", "/bar");
given(this.client.getNextServerFromEureka("CONFIGSERVER", false)).willReturn(
this.info);
setup("spring.cloud.config.discovery.enabled=true");
ConfigClientProperties locator = context.getBean(ConfigClientProperties.class);
ConfigClientProperties locator = this.context
.getBean(ConfigClientProperties.class);
assertEquals("http://foo:7001/bar", locator.getUri());
}
private void setup(String... env) {
context = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(context, env);
context.getDefaultListableBeanFactory().registerSingleton("mockDiscoveryClient",
client);
context.register(PropertyPlaceholderAutoConfiguration.class,
this.context = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(this.context, env);
this.context.getDefaultListableBeanFactory().registerSingleton(
"mockDiscoveryClient", this.client);
this.context.register(PropertyPlaceholderAutoConfiguration.class,
DiscoveryClientConfigServiceBootstrapConfiguration.class,
ConfigClientProperties.class);
context.refresh();
this.context.refresh();
}
}

View File

@@ -13,9 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.config;
import static org.junit.Assert.assertEquals;
package org.springframework.cloud.netflix.config;
import org.junit.After;
import org.junit.Test;
@@ -28,9 +27,10 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
import com.netflix.appinfo.EurekaInstanceConfig;
import static org.junit.Assert.assertEquals;
/**
* @author Dave Syer
*
*/
public class EurekaClientConfigServerAutoConfigurationTests {
@@ -38,29 +38,30 @@ public class EurekaClientConfigServerAutoConfigurationTests {
@After
public void close() {
if (context != null) {
context.close();
if (this.context != null) {
this.context.close();
}
}
@Test
public void offByDefault() throws Exception {
context = new AnnotationConfigApplicationContext(
this.context = new AnnotationConfigApplicationContext(
EurekaClientConfigServerAutoConfiguration.class);
assertEquals(0,
context.getBeanNamesForType(EurekaInstanceConfigBean.class).length);
this.context.getBeanNamesForType(EurekaInstanceConfigBean.class).length);
}
@Test
public void onWhenRequested() throws Exception {
setup("spring.cloud.config.server.prefix=/config");
assertEquals(1, context.getBeanNamesForType(EurekaInstanceConfig.class).length);
EurekaInstanceConfig instance = context.getBean(EurekaInstanceConfig.class);
assertEquals(1,
this.context.getBeanNamesForType(EurekaInstanceConfig.class).length);
EurekaInstanceConfig instance = this.context.getBean(EurekaInstanceConfig.class);
assertEquals("/config", instance.getMetadataMap().get("configPath"));
}
private void setup(String... env) {
context = new SpringApplicationBuilder(
this.context = new SpringApplicationBuilder(
PropertyPlaceholderAutoConfiguration.class,
EurekaClientConfigServerAutoConfiguration.class,
ConfigServerProperties.class, EurekaInstanceConfigBean.class).web(false)

View File

@@ -13,9 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.eureka;
import static org.junit.Assert.assertEquals;
package org.springframework.cloud.netflix.eureka;
import java.util.Collections;
@@ -29,9 +28,10 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.MapPropertySource;
import static org.junit.Assert.assertEquals;
/**
* @author Dave Syer
*
*/
public class EurekaClientConfigBeanTests {
@@ -39,65 +39,64 @@ public class EurekaClientConfigBeanTests {
@After
public void init() {
if (context != null) {
context.close();
if (this.context != null) {
this.context.close();
}
}
@Test
public void basicBinding() {
EnvironmentTestUtils.addEnvironment(context,
EnvironmentTestUtils.addEnvironment(this.context,
"eureka.client.proxyHost=example.com");
context.register(PropertyPlaceholderAutoConfiguration.class,
this.context.register(PropertyPlaceholderAutoConfiguration.class,
TestConfiguration.class);
context.refresh();
assertEquals("example.com", context.getBean(EurekaClientConfigBean.class)
this.context.refresh();
assertEquals("example.com", this.context.getBean(EurekaClientConfigBean.class)
.getProxyHost());
}
@Test
public void serviceUrl() {
EnvironmentTestUtils.addEnvironment(context,
EnvironmentTestUtils.addEnvironment(this.context,
"eureka.client.serviceUrl.defaultZone:http://example.com");
context.register(PropertyPlaceholderAutoConfiguration.class,
this.context.register(PropertyPlaceholderAutoConfiguration.class,
TestConfiguration.class);
context.refresh();
this.context.refresh();
assertEquals("{defaultZone=http://example.com}",
context.getBean(EurekaClientConfigBean.class).getServiceUrl().toString());
assertEquals(
"[http://example.com]",
context.getBean(EurekaClientConfigBean.class)
this.context.getBean(EurekaClientConfigBean.class).getServiceUrl()
.toString());
assertEquals("[http://example.com]",
this.context.getBean(EurekaClientConfigBean.class)
.getEurekaServerServiceUrls("defaultZone").toString());
}
@Test
public void serviceUrlWithCompositePropertySource() {
CompositePropertySource source = new CompositePropertySource("composite");
context.getEnvironment().getPropertySources().addFirst(source);
this.context.getEnvironment().getPropertySources().addFirst(source);
source.addPropertySource(new MapPropertySource("config", Collections
.<String, Object> singletonMap("eureka.client.serviceUrl.defaultZone",
"http://example.com")));
context.register(PropertyPlaceholderAutoConfiguration.class,
this.context.register(PropertyPlaceholderAutoConfiguration.class,
TestConfiguration.class);
context.refresh();
this.context.refresh();
assertEquals("{defaultZone=http://example.com}",
context.getBean(EurekaClientConfigBean.class).getServiceUrl().toString());
assertEquals(
"[http://example.com]",
context.getBean(EurekaClientConfigBean.class)
this.context.getBean(EurekaClientConfigBean.class).getServiceUrl()
.toString());
assertEquals("[http://example.com]",
this.context.getBean(EurekaClientConfigBean.class)
.getEurekaServerServiceUrls("defaultZone").toString());
}
@Test
public void serviceUrlWithDefault() {
EnvironmentTestUtils.addEnvironment(context,
EnvironmentTestUtils.addEnvironment(this.context,
"eureka.client.serviceUrl.defaultZone:http://example.com");
context.register(PropertyPlaceholderAutoConfiguration.class,
this.context.register(PropertyPlaceholderAutoConfiguration.class,
TestConfiguration.class);
context.refresh();
assertEquals(
"[http://example.com]",
context.getBean(EurekaClientConfigBean.class)
this.context.refresh();
assertEquals("[http://example.com]",
this.context.getBean(EurekaClientConfigBean.class)
.getEurekaServerServiceUrls("defaultZone").toString());
}

View File

@@ -13,11 +13,8 @@
See the License for the specific language governing permissions and
limitations under the License.
*/
package org.springframework.cloud.netflix.eureka;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.springframework.boot.test.EnvironmentTestUtils.addEnvironment;
package org.springframework.cloud.netflix.eureka;
import org.junit.After;
import org.junit.Test;
@@ -30,9 +27,12 @@ import org.springframework.context.annotation.Configuration;
import com.netflix.appinfo.InstanceInfo.InstanceStatus;
import com.netflix.appinfo.UniqueIdentifier;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.springframework.boot.test.EnvironmentTestUtils.addEnvironment;
/**
* @author Dave Syer
*
*/
public class EurekaInstanceConfigBeanTests {
@@ -40,8 +40,8 @@ public class EurekaInstanceConfigBeanTests {
@After
public void init() {
if (context != null) {
context.close();
if (this.context != null) {
this.context.close();
}
}
@@ -55,7 +55,7 @@ public class EurekaInstanceConfigBeanTests {
@Test
public void basicBinding() {
addEnvironment(context, "eureka.instance.appGroupName=mygroup");
addEnvironment(this.context, "eureka.instance.appGroupName=mygroup");
setupContext();
assertEquals("mygroup", getInstanceConfig().getAppGroupName());
}
@@ -81,7 +81,7 @@ public class EurekaInstanceConfigBeanTests {
}
private void testNonSecurePort(String propName) {
addEnvironment(context, propName + ":8888");
addEnvironment(this.context, propName + ":8888");
setupContext();
assertEquals(8888, getInstanceConfig().getNonSecurePort());
}
@@ -95,13 +95,13 @@ public class EurekaInstanceConfigBeanTests {
@Test(expected = BeanCreationException.class)
public void testBadInitialStatus() {
addEnvironment(context, "eureka.instance.initial-status:FOO");
addEnvironment(this.context, "eureka.instance.initial-status:FOO");
setupContext();
}
@Test
public void testCustomInitialStatus() {
addEnvironment(context, "eureka.instance.initial-status:STARTING");
addEnvironment(this.context, "eureka.instance.initial-status:STARTING");
setupContext();
assertEquals("initialStatus wrong", InstanceStatus.STARTING, getInstanceConfig()
.getInitialStatus());
@@ -109,17 +109,17 @@ public class EurekaInstanceConfigBeanTests {
@Test
public void testPerferIpAddress() throws Exception {
addEnvironment(context, "eureka.instance.preferIpAddress:true");
addEnvironment(this.context, "eureka.instance.preferIpAddress:true");
setupContext();
EurekaInstanceConfigBean instance = getInstanceConfig();
assertTrue("Wrong hostname: " + instance.getHostname(),
getInstanceConfig().getHostname().equals(instance.getIpAddress()));
assertTrue("Wrong hostname: " + instance.getHostname(), getInstanceConfig()
.getHostname().equals(instance.getIpAddress()));
}
@Test
public void testPerferIpAddressInDatacenter() throws Exception {
addEnvironment(context, "eureka.instance.preferIpAddress:true");
addEnvironment(this.context, "eureka.instance.preferIpAddress:true");
setupContext();
EurekaInstanceConfigBean instance = getInstanceConfig();
String id = ((UniqueIdentifier) instance.getDataCenterInfo()).getId();
@@ -128,13 +128,13 @@ public class EurekaInstanceConfigBeanTests {
}
private void setupContext() {
context.register(PropertyPlaceholderAutoConfiguration.class,
this.context.register(PropertyPlaceholderAutoConfiguration.class,
TestConfiguration.class);
context.refresh();
this.context.refresh();
}
protected EurekaInstanceConfigBean getInstanceConfig() {
return context.getBean(EurekaInstanceConfigBean.class);
return this.context.getBean(EurekaInstanceConfigBean.class);
}
@Configuration

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.eureka.sample;
import org.junit.Test;

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.eureka.sample;
import org.springframework.boot.actuate.metrics.repository.InMemoryMetricRepository;
@@ -25,21 +41,22 @@ public class EurekaSampleApplication {
return new InMemoryMetricRepository();
}
@Bean
public HealthCheckHandler healthCheckHandler() {
return new HealthCheckHandler() {
@Override
public InstanceInfo.InstanceStatus getStatus(InstanceInfo.InstanceStatus currentStatus) {
return InstanceInfo.InstanceStatus.UP;
}
};
}
@Bean
public HealthCheckHandler healthCheckHandler() {
return new HealthCheckHandler() {
@Override
public InstanceInfo.InstanceStatus getStatus(
InstanceInfo.InstanceStatus currentStatus) {
return InstanceInfo.InstanceStatus.UP;
}
};
}
@RequestMapping("/")
public String home() {
return "Hello world";
}
public static void main(String[] args) {
new SpringApplicationBuilder(EurekaSampleApplication.class).web(true).run(args);
}

View File

@@ -1,7 +1,20 @@
package org.springframework.cloud.netflix.feign;
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
package org.springframework.cloud.netflix.feign;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
@@ -28,6 +41,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* @author Spencer Gibb
*/
@@ -38,74 +54,75 @@ import org.springframework.web.bind.annotation.RestController;
@DirtiesContext
public class FeignClientTests extends FeignConfiguration {
@Value("${local.server.port}")
private int port = 0;
@Value("${local.server.port}")
private int port = 0;
@Autowired
TestClient testClient;
TestClient testClient;
//@FeignClient(value = "http://localhost:9876", loadbalance = false)
// @FeignClient(value = "http://localhost:9876", loadbalance = false)
@FeignClient("feignclienttest")
protected static interface TestClient {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
public Hello getHello();
@RequestMapping(method = RequestMethod.GET, value = "/hellos")
public List<Hello> getHellos();
@RequestMapping(method = RequestMethod.GET, value = "/hellostrings")
public List<String> getHelloStrings();
}
@Configuration
@EnableAutoConfiguration
@RestController
@FeignClientScan
protected static class Application {
protected static interface TestClient {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
public Hello getHello() {
return new Hello("hello world 1");
}
public Hello getHello();
@RequestMapping(method = RequestMethod.GET, value = "/hellos")
public List<Hello> getHellos() {
ArrayList<Hello> hellos = new ArrayList<>();
hellos.add(new Hello("hello world 1"));
hellos.add(new Hello("oi terra 2"));
return hellos;
}
public List<Hello> getHellos();
@RequestMapping(method = RequestMethod.GET, value = "/hellostrings")
public List<String> getHelloStrings() {
ArrayList<String> hellos = new ArrayList<>();
hellos.add("hello world 1");
hellos.add("oi terra 2");
return hellos;
}
public List<String> getHelloStrings();
}
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).properties(
"spring.application.name=feignclienttest", "management.contextPath=/admin")
.run(args);
}
}
@Configuration
@EnableAutoConfiguration
@RestController
@FeignClientScan
protected static class Application {
@Test
public void testClient() {
assertNotNull("testClient was null", testClient);
assertTrue("testClient is not a java Proxy", Proxy.isProxyClass(testClient.getClass()));
InvocationHandler invocationHandler = Proxy.getInvocationHandler(testClient);
@RequestMapping(method = RequestMethod.GET, value = "/hello")
public Hello getHello() {
return new Hello("hello world 1");
}
@RequestMapping(method = RequestMethod.GET, value = "/hellos")
public List<Hello> getHellos() {
ArrayList<Hello> hellos = new ArrayList<>();
hellos.add(new Hello("hello world 1"));
hellos.add(new Hello("oi terra 2"));
return hellos;
}
@RequestMapping(method = RequestMethod.GET, value = "/hellostrings")
public List<String> getHelloStrings() {
ArrayList<String> hellos = new ArrayList<>();
hellos.add("hello world 1");
hellos.add("oi terra 2");
return hellos;
}
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).properties(
"spring.application.name=feignclienttest",
"management.contextPath=/admin").run(args);
}
}
@Test
public void testClient() {
assertNotNull("testClient was null", this.testClient);
assertTrue("testClient is not a java Proxy",
Proxy.isProxyClass(this.testClient.getClass()));
InvocationHandler invocationHandler = Proxy.getInvocationHandler(this.testClient);
assertNotNull("invocationHandler was null", invocationHandler);
}
//TODO: only works if port is hardcoded cant resolve ${local.server.port} in annotation
/*@Test
public void testSimpleType() {
Hello hello = testClient.getHello();
assertNotNull("hello was null", hello);
assertEquals("first hello didn't match", new Hello("hello world 1"), hello);
}*/
// TODO: only works if port is hardcoded cant resolve ${local.server.port} in
// annotation
/*
* @Test public void testSimpleType() { Hello hello = testClient.getHello();
* assertNotNull("hello was null", hello); assertEquals("first hello didn't match",
* new Hello("hello world 1"), hello); }
*/
@Data
@AllArgsConstructor

View File

@@ -1,6 +1,24 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.feign;
import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@@ -20,8 +38,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
/**
* @author Spencer Gibb
@@ -29,85 +47,91 @@ import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SpringDecoderTests.Application.class)
@WebAppConfiguration
@IntegrationTest({ "server.port=0", "spring.application.name=springdecodertest", "spring.jmx.enabled=true" })
@IntegrationTest({ "server.port=0", "spring.application.name=springdecodertest",
"spring.jmx.enabled=true" })
@DirtiesContext
public class SpringDecoderTests extends FeignConfiguration {
@Value("${local.server.port}")
private int port = 0;
@Value("${local.server.port}")
private int port = 0;
public TestClient testClient() {
return feign().target(TestClient.class, "http://localhost:"+port);
}
public TestClient testClient() {
return feign().target(TestClient.class, "http://localhost:" + this.port);
}
protected static interface TestClient {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
public Hello getHello();
@Test
public void testSimpleType() {
Hello hello = testClient().getHello();
assertNotNull("hello was null", hello);
assertEquals("first hello didn't match", new Hello("hello world 1"), hello);
}
@RequestMapping(method = RequestMethod.GET, value = "/hellos")
public List<Hello> getHellos();
@Test
public void testUserParameterizedTypeDecode() {
List<Hello> hellos = testClient().getHellos();
assertNotNull("hellos was null", hellos);
assertEquals("hellos was not the right size", 2, hellos.size());
assertEquals("first hello didn't match", new Hello("hello world 1"),
hellos.get(0));
}
@RequestMapping(method = RequestMethod.GET, value = "/hellostrings")
public List<String> getHelloStrings();
}
@Test
public void testSimpleParameterizedTypeDecode() {
List<String> hellos = testClient().getHelloStrings();
assertNotNull("hellos was null", hellos);
assertEquals("hellos was not the right size", 2, hellos.size());
assertEquals("first hello didn't match", "hello world 1", hellos.get(0));
}
@Configuration
@EnableAutoConfiguration
@RestController
protected static class Application implements TestClient {
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Hello {
private String message;
}
public Hello getHello() {
return new Hello("hello world 1");
}
protected static interface TestClient {
@RequestMapping(method = RequestMethod.GET, value = "/hello")
public Hello getHello();
public List<Hello> getHellos() {
ArrayList<Hello> hellos = new ArrayList<>();
hellos.add(new Hello("hello world 1"));
hellos.add(new Hello("oi terra 2"));
return hellos;
}
@RequestMapping(method = RequestMethod.GET, value = "/hellos")
public List<Hello> getHellos();
public List<String> getHelloStrings() {
ArrayList<String> hellos = new ArrayList<>();
hellos.add("hello world 1");
hellos.add("oi terra 2");
return hellos;
}
@RequestMapping(method = RequestMethod.GET, value = "/hellostrings")
public List<String> getHelloStrings();
}
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).properties(
"spring.application.name=springdecodertest", "management.contextPath=/admin")
.run(args);
}
}
@Configuration
@EnableAutoConfiguration
@RestController
protected static class Application implements TestClient {
@Test
public void testSimpleType() {
Hello hello = testClient().getHello();
assertNotNull("hello was null", hello);
assertEquals("first hello didn't match", new Hello("hello world 1"), hello);
}
@Override
public Hello getHello() {
return new Hello("hello world 1");
}
@Test
public void testUserParameterizedTypeDecode() {
List<Hello> hellos = testClient().getHellos();
assertNotNull("hellos was null", hellos);
assertEquals("hellos was not the right size", 2, hellos.size());
assertEquals("first hello didn't match", new Hello("hello world 1"), hellos.get(0));
}
@Override
public List<Hello> getHellos() {
ArrayList<Hello> hellos = new ArrayList<>();
hellos.add(new Hello("hello world 1"));
hellos.add(new Hello("oi terra 2"));
return hellos;
}
@Test
public void testSimpleParameterizedTypeDecode() {
List<String> hellos = testClient().getHelloStrings();
assertNotNull("hellos was null", hellos);
assertEquals("hellos was not the right size", 2, hellos.size());
assertEquals("first hello didn't match", "hello world 1", hellos.get(0));
}
@Override
public List<String> getHelloStrings() {
ArrayList<String> hellos = new ArrayList<>();
hellos.add("hello world 1");
hellos.add("oi terra 2");
return hellos;
}
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).properties(
"spring.application.name=springdecodertest",
"management.contextPath=/admin").run(args);
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Hello {
private String message;
}
}

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.hystrix;
import org.junit.Test;
@@ -20,13 +21,13 @@ import org.springframework.boot.builder.SpringApplicationBuilder;
/**
* @author Dave Syer
*
*/
public class HystrixConfigurationTests {
@Test
public void nonWebAppStartsUp() {
new SpringApplicationBuilder(HystrixCircuitBreakerConfiguration.class).web(false).run().close();
new SpringApplicationBuilder(HystrixCircuitBreakerConfiguration.class).web(false)
.run().close();
}
}

View File

@@ -1,6 +1,23 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.hystrix;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@@ -19,9 +36,11 @@ import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* @author Spencer Gibb
@@ -38,13 +57,15 @@ public class HystrixOnlyTests {
@Test
public void testNormalExecution() {
String s = new TestRestTemplate().getForObject("http://localhost:" + port + "/", String.class);
String s = new TestRestTemplate().getForObject("http://localhost:" + this.port
+ "/", String.class);
assertEquals("incorrect response", "Hello world", s);
}
@Test
public void testFailureFallback() {
String s = new TestRestTemplate().getForObject("http://localhost:" + port + "/fail", String.class);
String s = new TestRestTemplate().getForObject("http://localhost:" + this.port
+ "/fail", String.class);
assertEquals("incorrect fallback", "Fallback Hello world", s);
}
@@ -59,12 +80,14 @@ public class HystrixOnlyTests {
@Test
public void testNoDiscoveryHealth() {
Map map = getHealth();
//There is explicitly no discovery, so there should be no discovery health key
assertFalse("Incorrect existing discovery health key", map.containsKey("discovery"));
// There is explicitly no discovery, so there should be no discovery health key
assertFalse("Incorrect existing discovery health key",
map.containsKey("discovery"));
}
private Map getHealth() {
return new TestRestTemplate().getForObject("http://localhost:" + port + "/admin/health", Map.class);
return new TestRestTemplate().getForObject("http://localhost:" + this.port
+ "/admin/health", Map.class);
}
}
@@ -84,7 +107,7 @@ class Service {
}
}
//Don't use @SpringBootApplication because we don't want to component scan
// Don't use @SpringBootApplication because we don't want to component scan
@Configuration
@EnableAutoConfiguration
@EnableCircuitBreaker
@@ -101,15 +124,16 @@ class HystrixOnlyApplication {
@RequestMapping("/")
public String home() {
return service.hello();
return this.service.hello();
}
@RequestMapping("/fail")
public String fail() {
return service.fail();
return this.service.fail();
}
public static void main(String[] args) {
SpringApplication.run(HystrixOnlyApplication.class, args);
}
}

View File

@@ -13,15 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.hystrix;
import static org.junit.Assert.assertEquals;
package org.springframework.cloud.netflix.hystrix;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/**
* @author Dave Syer
*
*/
public class HystrixStreamEndpointTests {

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.ribbon;
import org.junit.Test;
@@ -33,7 +34,6 @@ import com.netflix.loadbalancer.ZoneAwareLoadBalancer;
/**
* @author Dave Syer
*
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = TestConfiguration.class)
@@ -46,7 +46,7 @@ public class PlainRibbonClientPreprocessorIntegrationTests {
@Test
public void serverListIsWrapped() throws Exception {
@SuppressWarnings("unchecked")
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) factory
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) this.factory
.getLoadBalancer("foo");
DomainExtractingServerList.class.cast(loadBalancer.getServerListImpl());
}

View File

@@ -13,9 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.ribbon;
import static org.junit.Assert.assertEquals;
package org.springframework.cloud.netflix.ribbon;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -36,9 +35,10 @@ import com.netflix.loadbalancer.AvailabilityFilteringRule;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ZoneAwareLoadBalancer;
import static org.junit.Assert.assertEquals;
/**
* @author Dave Syer
*
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = TestConfiguration.class)
@@ -51,7 +51,7 @@ public class RibbonClientPreprocessorIntegrationTests {
@Test
public void serverListIsWrapped() throws Exception {
@SuppressWarnings("unchecked")
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) factory
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) this.factory
.getLoadBalancer("foo");
DomainExtractingServerList.class.cast(loadBalancer.getServerListImpl());
}
@@ -59,7 +59,7 @@ public class RibbonClientPreprocessorIntegrationTests {
@Test
public void ruleDefaultsToAvailability() throws Exception {
@SuppressWarnings("unchecked")
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) factory
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) this.factory
.getLoadBalancer("foo");
AvailabilityFilteringRule.class.cast(loadBalancer.getRule());
}
@@ -67,7 +67,7 @@ public class RibbonClientPreprocessorIntegrationTests {
@Test
public void serverListFilterOverride() throws Exception {
@SuppressWarnings("unchecked")
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) factory
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) this.factory
.getLoadBalancer("foo");
assertEquals("myTestZone",
ZonePreferenceServerListFilter.class.cast(loadBalancer.getFilter())

View File

@@ -13,9 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.ribbon;
import static org.junit.Assert.assertEquals;
package org.springframework.cloud.netflix.ribbon;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -24,10 +23,6 @@ import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfigurati
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration;
import org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration;
import org.springframework.cloud.netflix.ribbon.RibbonClients;
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.netflix.ribbon.RibbonClientsPreprocessorIntegrationTests.TestConfiguration;
import org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList;
import org.springframework.cloud.netflix.ribbon.eureka.RibbonEurekaAutoConfiguration;
@@ -42,9 +37,10 @@ import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ZoneAvoidanceRule;
import com.netflix.loadbalancer.ZoneAwareLoadBalancer;
import static org.junit.Assert.assertEquals;
/**
* @author Dave Syer
*
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = TestConfiguration.class)
@@ -57,7 +53,7 @@ public class RibbonClientsPreprocessorIntegrationTests {
@Test
public void serverListIsWrapped() throws Exception {
@SuppressWarnings("unchecked")
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) factory
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) this.factory
.getLoadBalancer("foo");
DomainExtractingServerList.class.cast(loadBalancer.getServerListImpl());
}
@@ -65,7 +61,7 @@ public class RibbonClientsPreprocessorIntegrationTests {
@Test
public void ruleDefaultsToZoneAvoidance() throws Exception {
@SuppressWarnings("unchecked")
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) factory
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) this.factory
.getLoadBalancer("foo");
ZoneAvoidanceRule.class.cast(loadBalancer.getRule());
}
@@ -73,10 +69,11 @@ public class RibbonClientsPreprocessorIntegrationTests {
@Test
public void serverListFilterOverride() throws Exception {
@SuppressWarnings("unchecked")
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) factory
ZoneAwareLoadBalancer<Server> loadBalancer = (ZoneAwareLoadBalancer<Server>) this.factory
.getLoadBalancer("foo");
assertEquals("myTestZone",
ZonePreferenceServerListFilter.class.cast(loadBalancer.getFilter()).getZone());
ZonePreferenceServerListFilter.class.cast(loadBalancer.getFilter())
.getZone());
}
@Configuration

View File

@@ -1,7 +1,24 @@
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.ribbon;
import com.google.common.base.Throwables;
import com.netflix.loadbalancer.Server;
import java.net.URI;
import java.net.URL;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
@@ -17,77 +34,82 @@ import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.support.HttpRequestWrapper;
import org.springframework.web.util.UriComponentsBuilder;
import java.net.URI;
import java.net.URL;
import com.google.common.base.Throwables;
import com.netflix.loadbalancer.Server;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.verify;
/**
* @author Spencer Gibb
*/
public class RibbonInterceptorTests {
@Mock
HttpRequest request;
@Mock
HttpRequest request;
@Mock
ClientHttpRequestExecution execution;
@Mock
ClientHttpRequestExecution execution;
@Mock
ClientHttpResponse response;
@Mock
ClientHttpResponse response;
@Before
public void init() {
MockitoAnnotations.initMocks(this);
}
@Before
public void init() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testIntercept() throws Exception {
RibbonServer server = new RibbonServer("myservice", new Server("myhost", 8080));
RibbonInterceptor interceptor = new RibbonInterceptor(new MyClient(server));
@Test
public void testIntercept() throws Exception {
RibbonServer server = new RibbonServer("myservice", new Server("myhost", 8080));
RibbonInterceptor interceptor = new RibbonInterceptor(new MyClient(server));
given(this.request.getURI()).willReturn(new URL("http://myservice").toURI());
given(this.execution.execute(isA(HttpRequest.class), isA(byte[].class)))
.willReturn(this.response);
ArgumentCaptor<HttpRequestWrapper> argument = ArgumentCaptor
.forClass(HttpRequestWrapper.class);
ClientHttpResponse response = interceptor.intercept(this.request, new byte[0],
this.execution);
assertNotNull("response was null", response);
verify(this.execution).execute(argument.capture(), isA(byte[].class));
HttpRequestWrapper wrapper = argument.getValue();
assertEquals("wrong constructed uri", new URL("http://myhost:8080").toURI(),
wrapper.getURI());
}
when(request.getURI()).thenReturn(new URL("http://myservice").toURI());
when(execution.execute(isA(HttpRequest.class), isA(byte[].class))).thenReturn(response);
ArgumentCaptor<HttpRequestWrapper> argument = ArgumentCaptor.forClass(HttpRequestWrapper.class);
protected static class MyClient implements LoadBalancerClient {
ClientHttpResponse response = interceptor.intercept(request, new byte[0], execution);
private ServiceInstance instance;
assertNotNull("response was null", response);
verify(execution).execute(argument.capture(), isA(byte[].class));
HttpRequestWrapper wrapper = argument.getValue();
assertEquals("wrong constructed uri", new URL("http://myhost:8080").toURI(), wrapper.getURI());
}
public MyClient(ServiceInstance instance) {
this.instance = instance;
}
protected static class MyClient implements LoadBalancerClient {
ServiceInstance instance;
@Override
public ServiceInstance choose(String serviceId) {
return this.instance;
}
public MyClient(ServiceInstance instance) {
this.instance = instance;
}
@Override
public <T> T execute(String serviceId, LoadBalancerRequest<T> request) {
try {
return request.apply(this.instance);
}
catch (Exception ex) {
Throwables.propagate(ex);
}
return null;
}
@Override
public ServiceInstance choose(String serviceId) {
return instance;
}
@Override
public URI reconstructURI(ServiceInstance instance, URI original) {
return UriComponentsBuilder.fromUri(original).host(instance.getHost())
.port(instance.getPort()).build().toUri();
}
@Override
public <T> T execute(String serviceId, LoadBalancerRequest<T> request) {
try {
return request.apply(instance);
} catch (Exception e) {
Throwables.propagate(e);
}
return null;
}
}
@Override
public URI reconstructURI(ServiceInstance instance, URI original) {
return UriComponentsBuilder.fromUri(original)
.host(instance.getHost())
.port(instance.getPort())
.build()
.toUri();
}
}
}

View File

@@ -1,12 +1,20 @@
package org.springframework.cloud.netflix.ribbon;
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.anyDouble;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
package org.springframework.cloud.netflix.ribbon;
import java.net.URI;
import java.net.URL;
@@ -14,7 +22,6 @@ import java.net.URL;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerRequest;
@@ -25,113 +32,126 @@ import com.netflix.loadbalancer.LoadBalancerStats;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerStats;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.anyDouble;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.verify;
/**
* @author Spencer Gibb
*/
public class RibbonLoadBalancerClientTests {
@Mock
SpringClientFactory clientFactory;
@Mock
private SpringClientFactory clientFactory;
@Mock
BaseLoadBalancer loadBalancer;
@Mock
private BaseLoadBalancer loadBalancer;
@Mock
LoadBalancerStats loadBalancerStats;
@Mock
private LoadBalancerStats loadBalancerStats;
@Mock
ServerStats serverStats;
@Mock
private ServerStats serverStats;
@Before
public void init() {
MockitoAnnotations.initMocks(this);
Mockito.when(clientFactory.getLoadBalancerContext(anyString())).thenReturn(new RibbonLoadBalancerContext(loadBalancer));
}
@Before
public void init() {
MockitoAnnotations.initMocks(this);
given(this.clientFactory.getLoadBalancerContext(anyString())).willReturn(
new RibbonLoadBalancerContext(this.loadBalancer));
}
@Test
public void reconstructURI() throws Exception {
RibbonServer server = getRibbonServer();
RibbonLoadBalancerClient client = getRibbonLoadBalancerClient(server);
ServiceInstance serviceInstance = client.choose(server.getServiceId());
URI uri = client.reconstructURI(serviceInstance, new URL("http://" + server.serviceId).toURI());
assertEquals(server.getHost(), uri.getHost());
assertEquals(server.getPort(), uri.getPort());
}
@Test
public void reconstructURI() throws Exception {
RibbonServer server = getRibbonServer();
RibbonLoadBalancerClient client = getRibbonLoadBalancerClient(server);
ServiceInstance serviceInstance = client.choose(server.getServiceId());
URI uri = client.reconstructURI(serviceInstance, new URL("http://"
+ server.serviceId).toURI());
assertEquals(server.getHost(), uri.getHost());
assertEquals(server.getPort(), uri.getPort());
}
@Test
public void testChoose() {
RibbonServer server = getRibbonServer();
RibbonLoadBalancerClient client = getRibbonLoadBalancerClient(server);
ServiceInstance serviceInstance = client.choose(server.getServiceId());
assertServiceInstance(server, serviceInstance);
}
@Test
public void testChoose() {
RibbonServer server = getRibbonServer();
RibbonLoadBalancerClient client = getRibbonLoadBalancerClient(server);
ServiceInstance serviceInstance = client.choose(server.getServiceId());
assertServiceInstance(server, serviceInstance);
}
@Test
public void testExecute() {
final RibbonServer server = getRibbonServer();
RibbonLoadBalancerClient client = getRibbonLoadBalancerClient(server);
@Test
public void testExecute() {
final RibbonServer server = getRibbonServer();
RibbonLoadBalancerClient client = getRibbonLoadBalancerClient(server);
final String returnVal = "myval";
Object actualReturn = client.execute(server.getServiceId(),
new LoadBalancerRequest<Object>() {
@Override
public Object apply(ServiceInstance instance) throws Exception {
assertServiceInstance(server, instance);
return returnVal;
}
});
verifyServerStats();
assertEquals("retVal was wrong", returnVal, actualReturn);
}
final String returnVal = "myval";
Object actualReturn = client.execute(server.getServiceId(), new LoadBalancerRequest<Object>() {
@Override
public Object apply(ServiceInstance instance) throws Exception {
assertServiceInstance(server, instance);
return returnVal;
}
});
@Test
public void testExecuteException() {
final RibbonServer ribbonServer = getRibbonServer();
RibbonLoadBalancerClient client = getRibbonLoadBalancerClient(ribbonServer);
try {
client.execute(ribbonServer.getServiceId(),
new LoadBalancerRequest<Object>() {
@Override
public Object apply(ServiceInstance instance) throws Exception {
assertServiceInstance(ribbonServer, instance);
throw new RuntimeException();
}
});
fail("Should have thrown exception");
}
catch (Exception ex) {
assertNotNull(ex);
}
verifyServerStats();
}
verifyServerStats();
protected RibbonServer getRibbonServer() {
return new RibbonServer("testService", new Server("myhost", 9080));
}
assertEquals("retVal was wrong", returnVal, actualReturn);
}
protected void verifyServerStats() {
verify(this.serverStats).incrementActiveRequestsCount();
verify(this.serverStats).decrementActiveRequestsCount();
verify(this.serverStats).incrementNumRequests();
verify(this.serverStats).noteResponseTime(anyDouble());
}
protected void assertServiceInstance(RibbonServer ribbonServer,
ServiceInstance instance) {
assertNotNull("instance was null", instance);
assertEquals("serviceId was wrong", ribbonServer.getServiceId(),
instance.getServiceId());
assertEquals("host was wrong", ribbonServer.getHost(), instance.getHost());
assertEquals("port was wrong", ribbonServer.getPort(), instance.getPort());
}
@Test
public void testExecuteException() {
final RibbonServer ribbonServer = getRibbonServer();
RibbonLoadBalancerClient client = getRibbonLoadBalancerClient(ribbonServer);
try {
client.execute(ribbonServer.getServiceId(), new LoadBalancerRequest<Object>() {
@Override
public Object apply(ServiceInstance instance) throws Exception {
assertServiceInstance(ribbonServer, instance);
throw new RuntimeException();
}
});
fail("Should have thrown exception");
} catch (Exception e) {
assertNotNull(e);
}
verifyServerStats();
}
protected RibbonServer getRibbonServer() {
return new RibbonServer("testService", new Server("myhost", 9080));
}
protected void verifyServerStats() {
verify(serverStats).incrementActiveRequestsCount();
verify(serverStats).decrementActiveRequestsCount();
verify(serverStats).incrementNumRequests();
verify(serverStats).noteResponseTime(anyDouble());
}
protected void assertServiceInstance(RibbonServer ribbonServer, ServiceInstance instance) {
assertNotNull("instance was null", instance);
assertEquals("serviceId was wrong", ribbonServer.getServiceId(), instance.getServiceId());
assertEquals("host was wrong", ribbonServer.getHost(), instance.getHost());
assertEquals("port was wrong", ribbonServer.getPort(), instance.getPort());
}
protected RibbonLoadBalancerClient getRibbonLoadBalancerClient(RibbonServer ribbonServer) {
when(loadBalancer.getName()).thenReturn(ribbonServer.getServiceId());
when(loadBalancer.chooseServer(anyString())).thenReturn(ribbonServer.server);
when(loadBalancer.getLoadBalancerStats()).thenReturn(loadBalancerStats);
when(loadBalancerStats.getSingleServerStat(ribbonServer.server)).thenReturn(serverStats);
when(clientFactory.getLoadBalancer(loadBalancer.getName())).thenReturn(loadBalancer);
return new RibbonLoadBalancerClient(clientFactory);
}
protected RibbonLoadBalancerClient getRibbonLoadBalancerClient(
RibbonServer ribbonServer) {
given(this.loadBalancer.getName()).willReturn(ribbonServer.getServiceId());
given(this.loadBalancer.chooseServer(anyString()))
.willReturn(ribbonServer.server);
given(this.loadBalancer.getLoadBalancerStats())
.willReturn(this.loadBalancerStats);
given(this.loadBalancerStats.getSingleServerStat(ribbonServer.server))
.willReturn(this.serverStats);
given(this.clientFactory.getLoadBalancer(this.loadBalancer.getName()))
.willReturn(this.loadBalancer);
return new RibbonLoadBalancerClient(this.clientFactory);
}
}

View File

@@ -13,9 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.netflix.ribbon;
import static org.junit.Assert.assertEquals;
package org.springframework.cloud.netflix.ribbon;
import org.junit.Test;
import org.springframework.boot.test.EnvironmentTestUtils;
@@ -24,6 +23,8 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
import com.netflix.client.DefaultLoadBalancerRetryHandler;
import static org.junit.Assert.assertEquals;
/**
* @author Dave Syer
*
@@ -34,14 +35,15 @@ public class SpringClientFactoryTests {
@Test
public void testConfigureRetry() {
AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext(ArchaiusAutoConfiguration.class);
AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext(
ArchaiusAutoConfiguration.class);
EnvironmentTestUtils.addEnvironment(parent, "foo.ribbon.MaxAutoRetries:2");
factory.setApplicationContext(parent);
DefaultLoadBalancerRetryHandler retryHandler = (DefaultLoadBalancerRetryHandler) factory
this.factory.setApplicationContext(parent);
DefaultLoadBalancerRetryHandler retryHandler = (DefaultLoadBalancerRetryHandler) this.factory
.getLoadBalancerContext("foo").getRetryHandler();
assertEquals(2, retryHandler.getMaxRetriesOnSameServer());
parent.close();
factory.destroy();
this.factory.destroy();
}
}

Some files were not shown because too many files have changed in this diff Show More