Compare commits

..

40 Commits

Author SHA1 Message Date
Vedran Pavic
98fa5ed52d Release 2.2.0.M3 2019-08-05 22:16:41 +02:00
Vedran Pavic
44468134aa Upgrade samples to Spring Framework 5.2.0.RC1
See: #1460
2019-08-05 21:58:23 +02:00
Vedran Pavic
c14c621da6 Remove Spring Framework snapshot dependency from samples
See: #1460
2019-08-05 21:43:53 +02:00
Vedran Pavic
6ceca18248 Revert to development version 2019-08-05 21:23:54 +02:00
Vedran Pavic
229ca09f10 Release 2.2.0.M3 2019-08-05 21:12:00 +02:00
Vedran Pavic
36b82d52f8 Upgrade Spring Security to 5.2.0.M4
Resolves: #1462
2019-08-05 20:49:04 +02:00
Vedran Pavic
dbeb33fd9d Add flush mode support for JDBC sessions
Resolves: #1468
2019-08-05 18:58:29 +02:00
Vedran Pavic
23bf92a086 Upgrade Spring Data to Moore-RC2
Resolves: #1461
2019-08-05 16:04:58 +02:00
Vedran Pavic
2e0c347a3a Update integration tests 2019-08-05 13:26:34 +02:00
Vedran Pavic
972537a3d5 Upgrade test dependencies 2019-08-05 13:25:15 +02:00
Vedran Pavic
99c4f5bc32 Upgrade Spring Framework to 5.2.0.RC1
Resolves: #1460
2019-08-05 12:53:10 +02:00
Vedran Pavic
89f8127763 Upgrade test dependencies 2019-08-02 22:43:08 +02:00
Vedran Pavic
63f1013a07 Upgrade Hazelcast to 3.12.2
Resolves: #1483
2019-08-02 22:39:28 +02:00
Vedran Pavic
a988b062c3 Add IBM DB2 integration tests
Resolves: #1482
2019-08-02 01:11:02 +02:00
Vedran Pavic
09368243aa Update integration tests 2019-07-30 23:28:54 +02:00
Vedran Pavic
903fa10861 Polish 2019-07-30 23:08:13 +02:00
Vedran Pavic
a883e2ee77 Upgrade test dependencies 2019-07-30 20:00:37 +02:00
Vedran Pavic
f68e569bec Upgrade Reactor to Dysprosium-M3
Resolves: #1474
2019-07-30 19:40:58 +02:00
Vedran Pavic
593c126c03 Filtering for nested ERROR dispatch
Resolves: #1470
See: spring-projects/spring-framework#23196
2019-07-19 20:38:30 +02:00
Vedran Pavic
033d6eecae Add support for session save mode
This commit introduces SaveMode enum that individual SessionRepository implementations use to allow customization of the way they handle save operation in terms of tracking delta of changes.

Resolves: #1466
2019-07-14 10:35:05 +02:00
Vedran Pavic
24b9d24e18 Upgrade Gradle to 5.5.1 2019-07-12 17:40:31 +02:00
Vedran Pavic
46bc4b0957 Use no-op TransactionOperations 2019-07-07 13:40:59 +02:00
Vedran Pavic
8cb85618c2 Polish 2019-07-02 23:19:11 +02:00
Vedran Pavic
1ca9daccb4 Remove unnecessary throws declaration 2019-07-02 19:23:35 +02:00
Vedran Pavic
0731e7f2d0 Upgrade Gradle to 5.5 2019-07-02 18:50:52 +02:00
Vedran Pavic
8d0d757e46 Polish 2019-06-25 22:11:29 +02:00
Vedran Pavic
e2f1fe5446 Add missing deprecation
See: #1465
2019-06-25 21:50:03 +02:00
Vedran Pavic
07b9433540 Add common flush mode support
Resolves: #1465
2019-06-24 19:11:12 +02:00
Vedran Pavic
a6f6042831 Introduce IndexResolver
This commit introduces IndexResolver as a strategy interface for resolving index values in FindByIndexNameSessionRepository implementations.

Resolves: #557
2019-06-24 12:01:26 +02:00
Vedran Pavic
099be441dd Fix copyright dates
See: #1441
2019-06-21 15:52:26 +02:00
Rob Winch
17d029d34d Add spring-session label to Jenkins check node
Try and troubleshoot failures in Jenkins
2019-06-20 13:16:17 -05:00
Vedran Pavic
aab9b39a6b Remove immediate flush mode support for reactive Redis sessions
Resolves: #1441
2019-06-20 10:44:22 +02:00
Vedran Pavic
090d882f98 Start building against Spring Security 5.2 snapshots
See: #1462
2019-06-19 16:55:26 +02:00
Vedran Pavic
d91d09567f Start building against Spring Data Moore snapshots
See: #1461
2019-06-19 16:54:55 +02:00
Vedran Pavic
ab5b0e3a32 Start building against Spring Framework 5.2 snapshots
See: #1460
2019-06-19 16:54:31 +02:00
Vedran Pavic
549a2b7f0b Upgrade samples to Spring Boot 2.2.0.M4
Resolves: #1459
2019-06-19 16:51:12 +02:00
Craig Andrews
050ff7538b In Oracle ignore non-existant tables when dropping
If tables don't exist, ignore that error when dropping.

This aligns Oracle with the existing mysql, postgresql, h2, and hsqldb behavior.
2019-06-19 08:25:44 -05:00
Vedran Pavic
e8e65ac09f Add IntelliJ IDEA specific config
See: #1450
2019-06-18 22:48:25 +02:00
Vedran Pavic
822db7fbbf Use spring-javaformat to format and check code
Resolves: #1450
2019-06-17 23:54:41 +02:00
Vedran Pavic
0eaeb98b0c Next development version 2019-06-14 23:27:58 +02:00
265 changed files with 4922 additions and 5151 deletions

1
Jenkinsfile vendored
View File

@@ -13,6 +13,7 @@ try {
stage('Check') {
timeout(time: 45, unit: 'MINUTES') {
node('linux') {
label 'spring-session'
checkout scm
sh "git clean -dfx"
try {

View File

@@ -4,7 +4,7 @@ buildscript {
snapshotBuild = version.endsWith('SNAPSHOT')
milestoneBuild = !(releaseBuild || snapshotBuild)
springBootVersion = '2.2.0.M2'
springBootVersion = '2.2.0.M4'
}
repositories {
@@ -13,23 +13,19 @@ buildscript {
}
dependencies {
classpath 'io.spring.gradle:spring-build-conventions:0.0.25.RELEASE'
classpath 'io.spring.gradle:spring-build-conventions:0.0.26.RELEASE'
classpath "org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion"
classpath 'io.spring.nohttp:nohttp-gradle:0.0.2.RELEASE'
}
}
apply plugin: 'io.spring.convention.root'
apply plugin: 'io.spring.nohttp'
repositories {
mavenCentral()
}
group = 'org.springframework.session'
description = 'Spring Session'
subprojects {
apply plugin: 'io.spring.javaformat'
plugins.withType(JavaPlugin) {
sourceCompatibility = JavaVersion.VERSION_1_8

View File

@@ -5,8 +5,10 @@
<module name="SuppressionFilter">
<property name="file" value="${config_loc}/suppressions.xml"/>
</module>
<module name="io.spring.nohttp.checkstyle.check.NoHttpCheck"/>
<module name="io.spring.javaformat.checkstyle.SpringChecks"/>
<module name="com.puppycrawl.tools.checkstyle.TreeWalker">
<module name="io.spring.javaformat.checkstyle.check.SpringJUnit5Check"/>
<module name="com.puppycrawl.tools.checkstyle.checks.imports.IllegalImportCheck">
<property name="regexp" value="true"/>
<property name="illegalPkgs"

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<fileset-config file-format-version="1.2.0" simple-config="true" sync-formatter="false">
<local-check-config name="Spring Session Checkstyle" location="${configDir}/checkstyle.xml" type="external" description="">
<property name="configDir" value="${configDir}"/>
<additional-data name="protect-config-file" value="false"/>
</local-check-config>
<fileset name="all" enabled="true" check-config-name="Spring Session Checkstyle" local="true">
<file-match-pattern match-pattern="." include-pattern="true"/>
</fileset>
</fileset-config>

View File

@@ -1,295 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="12">
<profile kind="CodeFormatterProfile" name="Spring Session Java Conventions" version="12">
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="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="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="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

@@ -1,391 +0,0 @@
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=all_standard_tags
org.eclipse.jdt.core.compiler.problem.missingJavadocTags=warning
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=default
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.processAnnotations=disabled
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=4
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=do not 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=true
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
org.eclipse.jdt.core.javaFormatter=org.springframework.ide.eclipse.jdt.formatter.javaformatter

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,128 @@
<code_scheme name="SpringSession" version="173">
<option name="AUTODETECT_INDENTS" value="false"/>
<option name="OTHER_INDENT_OPTIONS">
<value>
<option name="USE_TAB_CHARACTER" value="true"/>
</value>
</option>
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="50"/>
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="500"/>
<option name="IMPORT_LAYOUT_TABLE">
<value>
<package name="java" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="javax" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="org.springframework" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="" withSubpackages="true" static="true"/>
</value>
</option>
<option name="RIGHT_MARGIN" value="90"/>
<option name="ENABLE_JAVADOC_FORMATTING" value="false"/>
<option name="JD_ALIGN_PARAM_COMMENTS" value="false"/>
<option name="JD_ALIGN_EXCEPTION_COMMENTS" value="false"/>
<option name="JD_KEEP_EMPTY_LINES" value="false"/>
<GroovyCodeStyleSettings>
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="500"/>
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="500"/>
<option name="IMPORT_LAYOUT_TABLE">
<value>
<emptyLine/>
<package name="javax" withSubpackages="true" static="false"/>
<package name="java" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="org.springframework" withSubpackages="true"
static="false"/>
<emptyLine/>
<package name="" withSubpackages="true" static="true"/>
</value>
</option>
</GroovyCodeStyleSettings>
<JavaCodeStyleSettings>
<option name="CLASS_NAMES_IN_JAVADOC" value="3"/>
<option name="INSERT_INNER_CLASS_IMPORTS" value="true"/>
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="50"/>
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="500"/>
<option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
<value/>
</option>
<option name="IMPORT_LAYOUT_TABLE">
<value>
<package name="java" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="javax" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="" withSubpackages="true" static="false"/>
<emptyLine/>
<package name="org.springframework" withSubpackages="true"
static="false"/>
<emptyLine/>
<package name="" withSubpackages="true" static="true"/>
</value>
</option>
<option name="ENABLE_JAVADOC_FORMATTING" value="false"/>
<option name="JD_ALIGN_PARAM_COMMENTS" value="false"/>
<option name="JD_ALIGN_EXCEPTION_COMMENTS" value="false"/>
<option name="JD_KEEP_INVALID_TAGS" value="false"/>
<option name="JD_KEEP_EMPTY_LINES" value="false"/>
</JavaCodeStyleSettings>
<JetCodeStyleSettings>
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
<value>
<package name="java.util" withSubpackages="false" static="false"/>
<package name="kotlinx.android.synthetic" withSubpackages="false"
static="false"/>
</value>
</option>
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="20"/>
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="20"/>
</JetCodeStyleSettings>
<XML>
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true"/>
</XML>
<editorconfig>
<option name="ENABLED" value="false"/>
</editorconfig>
<codeStyleSettings language="Groovy">
<indentOptions>
<option name="USE_TAB_CHARACTER" value="true"/>
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="JAVA">
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1"/>
<option name="BLANK_LINES_AROUND_FIELD" value="1"/>
<option name="BLANK_LINES_AROUND_FIELD_IN_INTERFACE" value="1"/>
<option name="ELSE_ON_NEW_LINE" value="true"/>
<option name="CATCH_ON_NEW_LINE" value="true"/>
<option name="FINALLY_ON_NEW_LINE" value="true"/>
<option name="ALIGN_MULTILINE_PARAMETERS" value="false"/>
<option name="SPACE_WITHIN_ARRAY_INITIALIZER_BRACES" value="true"/>
<option name="SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE" value="true"/>
<option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true"/>
<option name="KEEP_SIMPLE_CLASSES_IN_ONE_LINE" value="true"/>
<option name="KEEP_MULTIPLE_EXPRESSIONS_IN_ONE_LINE" value="true"/>
<indentOptions>
<option name="USE_TAB_CHARACTER" value="true"/>
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="JSON">
<indentOptions>
<option name="TAB_SIZE" value="2"/>
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="XML">
<indentOptions>
<option name="USE_TAB_CHARACTER" value="true"/>
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="kotlin">
<indentOptions>
<option name="USE_TAB_CHARACTER" value="true"/>
</indentOptions>
</codeStyleSettings>
</code_scheme>

View File

@@ -1 +1 @@
version=2.2.0.M2
version=2.2.0.M3

View File

@@ -1,33 +1,34 @@
dependencyManagement {
imports {
mavenBom 'com.fasterxml.jackson:jackson-bom:2.9.6'
mavenBom 'io.projectreactor:reactor-bom:Dysprosium-M2'
mavenBom 'org.junit:junit-bom:5.4.2'
mavenBom 'org.springframework:spring-framework-bom:5.2.0.M3'
mavenBom 'org.springframework.data:spring-data-releasetrain:Moore-RC1'
mavenBom 'org.springframework.security:spring-security-bom:5.2.0.M3'
mavenBom 'org.testcontainers:testcontainers-bom:1.11.3'
mavenBom 'io.projectreactor:reactor-bom:Dysprosium-M3'
mavenBom 'org.junit:junit-bom:5.5.1'
mavenBom 'org.springframework:spring-framework-bom:5.2.0.RC1'
mavenBom 'org.springframework.data:spring-data-releasetrain:Moore-RC2'
mavenBom 'org.springframework.security:spring-security-bom:5.2.0.M4'
mavenBom 'org.testcontainers:testcontainers-bom:1.12.0'
}
dependencies {
dependencySet(group: 'com.hazelcast', version: '3.12.1') {
dependencySet(group: 'com.hazelcast', version: '3.12.2') {
entry 'hazelcast'
entry 'hazelcast-client'
}
dependency 'com.h2database:h2:1.4.199'
dependency 'com.microsoft.sqlserver:mssql-jdbc:7.2.2.jre8'
dependency 'com.ibm.db2:jcc:11.5.0.0'
dependency 'com.microsoft.sqlserver:mssql-jdbc:7.4.1.jre8'
dependency 'com.zaxxer:HikariCP:3.3.1'
dependency 'edu.umd.cs.mtc:multithreadedtc:1.01'
dependency 'io.lettuce:lettuce-core:5.1.7.RELEASE'
dependency 'io.lettuce:lettuce-core:5.1.8.RELEASE'
dependency 'javax.annotation:javax.annotation-api:1.3.2'
dependency 'javax.servlet:javax.servlet-api:4.0.1'
dependency 'mysql:mysql-connector-java:8.0.16'
dependency 'mysql:mysql-connector-java:8.0.17'
dependency 'org.apache.derby:derby:10.14.2.0'
dependency 'org.assertj:assertj-core:3.12.2'
dependency 'org.assertj:assertj-core:3.13.2'
dependency 'org.hsqldb:hsqldb:2.5.0'
dependency 'org.mariadb.jdbc:mariadb-java-client:2.4.1'
dependency 'org.mockito:mockito-core:2.28.2'
dependency 'org.postgresql:postgresql:42.2.5'
dependency 'org.mariadb.jdbc:mariadb-java-client:2.4.3'
dependency 'org.mockito:mockito-core:3.0.0'
dependency 'org.postgresql:postgresql:42.2.6'
}
}

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2014-2019 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
*
* https://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.session;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* An {@link IndexResolver} that resolves indexes using multiple @{link IndexResolver}
* delegates.
*
* @param <S> the type of Session being handled
* @author Vedran Pavic
* @since 2.2.0
*/
public class DelegatingIndexResolver<S extends Session> implements IndexResolver<S> {
private final List<IndexResolver<S>> delegates;
public DelegatingIndexResolver(List<IndexResolver<S>> delegates) {
this.delegates = Collections.unmodifiableList(delegates);
}
@SafeVarargs
public DelegatingIndexResolver(IndexResolver<S>... delegates) {
this(Arrays.asList(delegates));
}
public Map<String, String> resolveIndexesFor(S session) {
Map<String, String> indexes = new HashMap<>();
for (IndexResolver<S> delegate : this.delegates) {
indexes.putAll(delegate.resolveIndexesFor(session));
}
return indexes;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 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.
@@ -27,8 +27,7 @@ import java.util.Map;
* @author Rob Winch
* @author Vedran Pavic
*/
public interface FindByIndexNameSessionRepository<S extends Session>
extends SessionRepository<S> {
public interface FindByIndexNameSessionRepository<S extends Session> extends SessionRepository<S> {
/**
* A session index that contains the current principal name (i.e. username).
@@ -44,7 +43,6 @@ public interface FindByIndexNameSessionRepository<S extends Session>
/**
* Find a {@link Map} of the session id to the {@link Session} of all sessions that
* contain the specified index name index value.
*
* @param indexName the name of the index (i.e.
* {@link FindByIndexNameSessionRepository#PRINCIPAL_NAME_INDEX_NAME})
* @param indexValue the value of the index to search for.
@@ -59,7 +57,6 @@ public interface FindByIndexNameSessionRepository<S extends Session>
* contain the index with the name
* {@link FindByIndexNameSessionRepository#PRINCIPAL_NAME_INDEX_NAME} and the
* specified principal name.
*
* @param principalName the principal name
* @return a {@code Map} (never {@code null}) of the session id to the {@code Session}
* of all sessions that contain the specified principal name. If no results are found,

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2014-2019 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
*
* https://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.session;
/**
* Supported modes of writing the session to session store.
*
* @author Rob Winch
* @author Vedran Pavic
* @since 2.2.0
*/
public enum FlushMode {
/**
* Only writes to session store when {@link SessionRepository#save(Session)} is
* invoked. In a web environment this is typically done as soon as the HTTP response
* is committed.
*/
ON_SAVE,
/**
* Writes to session store as soon as possible. For example
* {@link SessionRepository#createSession()} will write the session to session store.
* Another example is that setting an attribute using
* {@link Session#setAttribute(String, Object)} will also write to session store
* immediately.
*/
IMMEDIATE
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2014-2019 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
*
* https://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.session;
import java.util.Map;
/**
* Strategy interface for resolving the {@link Session}'s indexes.
*
* @param <S> the type of Session being handled
* @author Rob Winch
* @author Vedran Pavic
* @since 2.2.0
* @see FindByIndexNameSessionRepository
*/
public interface IndexResolver<S extends Session> {
/**
* Resolve indexes for the session.
* @param session the session
* @return a map of resolved indexes, never {@code null}
*/
Map<String, String> resolveIndexesFor(S session);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 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.
@@ -47,15 +47,20 @@ import java.util.UUID;
* @since 1.0
*/
public final class MapSession implements Session, Serializable {
/**
* Default {@link #setMaxInactiveInterval(Duration)} (30 minutes).
*/
public static final int DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS = 1800;
private String id;
private final String originalId;
private Map<String, Object> sessionAttrs = new HashMap<>();
private Instant creationTime = Instant.now();
private Instant lastAccessedTime = this.creationTime;
/**
@@ -70,12 +75,10 @@ public final class MapSession implements Session, Serializable {
this(generateId());
}
/**
* Creates a new instance with the specified id. This is preferred to the default
* constructor when the id is known to prevent unnecessary consumption on entropy
* which can be slow.
*
* @param id the identifier to use
*/
public MapSession(String id) {
@@ -85,7 +88,6 @@ public final class MapSession implements Session, Serializable {
/**
* Creates a new instance from the provided {@link Session}.
*
* @param session the {@link Session} to initialize this {@link Session} with. Cannot
* be null.
*/
@@ -95,8 +97,7 @@ public final class MapSession implements Session, Serializable {
}
this.id = session.getId();
this.originalId = this.id;
this.sessionAttrs = new HashMap<>(
session.getAttributeNames().size());
this.sessionAttrs = new HashMap<>(session.getAttributeNames().size());
for (String attrName : session.getAttributeNames()) {
Object attrValue = session.getAttribute(attrName);
if (attrValue != null) {
@@ -205,7 +206,6 @@ public final class MapSession implements Session, Serializable {
* Sets the identifier for this {@link Session}. The id should be a secure random
* generated value to prevent malicious users from guessing this value. The default is
* a secure random generated identifier.
*
* @param id the identifier for this session.
*/
public void setId(String id) {
@@ -227,4 +227,5 @@ public final class MapSession implements Session, Serializable {
}
private static final long serialVersionUID = 7160779239673823561L;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 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.
@@ -49,7 +49,6 @@ public class MapSessionRepository implements SessionRepository<MapSession> {
/**
* Creates a new instance backed by the provided {@link java.util.Map}. This allows
* injecting a distributed {@link java.util.Map}.
*
* @param sessions the {@link java.util.Map} to use. Cannot be null.
*/
public MapSessionRepository(Map<String, Session> sessions) {
@@ -99,8 +98,7 @@ public class MapSessionRepository implements SessionRepository<MapSession> {
public MapSession createSession() {
MapSession result = new MapSession();
if (this.defaultMaxInactiveInterval != null) {
result.setMaxInactiveInterval(
Duration.ofSeconds(this.defaultMaxInactiveInterval));
result.setMaxInactiveInterval(Duration.ofSeconds(this.defaultMaxInactiveInterval));
}
return result;
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2014-2019 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
*
* https://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.session;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
/**
* {@link IndexResolver} to resolve the principal name from session attribute named
* {@link FindByIndexNameSessionRepository#PRINCIPAL_NAME_INDEX_NAME} or Spring Security
* context stored in the session under {@code SPRING_SECURITY_CONTEXT} attribute.
*
* @param <S> the type of Session being handled
* @author Vedran Pavic
* @since 2.2.0
*/
public class PrincipalNameIndexResolver<S extends Session> extends SingleIndexResolver<S> {
private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
private static final SpelExpressionParser parser = new SpelExpressionParser();
public PrincipalNameIndexResolver() {
super(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME);
}
public String resolveIndexValueFor(S session) {
String principalName = session.getAttribute(getIndexName());
if (principalName != null) {
return principalName;
}
Object authentication = session.getAttribute(SPRING_SECURITY_CONTEXT);
if (authentication != null) {
Expression expression = parser.parseExpression("authentication?.name");
return expression.getValue(authentication, String.class);
}
return null;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 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.
@@ -51,7 +51,6 @@ public class ReactiveMapSessionRepository implements ReactiveSessionRepository<M
/**
* Creates a new instance backed by the provided {@link Map}. This allows injecting a
* distributed {@link Map}.
*
* @param sessions the {@link Map} to use. Cannot be null.
*/
public ReactiveMapSessionRepository(Map<String, Session> sessions) {
@@ -101,8 +100,7 @@ public class ReactiveMapSessionRepository implements ReactiveSessionRepository<M
return Mono.defer(() -> {
MapSession result = new MapSession();
if (this.defaultMaxInactiveInterval != null) {
result.setMaxInactiveInterval(
Duration.ofSeconds(this.defaultMaxInactiveInterval));
result.setMaxInactiveInterval(Duration.ofSeconds(this.defaultMaxInactiveInterval));
}
return Mono.just(result);
});

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2017 the original author or authors.
* Copyright 2014-2019 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.
@@ -36,7 +36,6 @@ public interface ReactiveSessionRepository<S extends Session> {
* persisted. For example, the implementation returned might keep track of the changes
* ensuring that only the delta needs to be persisted on a save.
* </p>
*
* @return a new {@link Session} that is capable of being persisted by this
* {@link ReactiveSessionRepository}
*/
@@ -51,7 +50,6 @@ public interface ReactiveSessionRepository<S extends Session> {
* returning a {@link Session} that immediately persists any changes. In this case,
* this method may not actually do anything.
* </p>
*
* @param session the {@link Session} to save
* @return indicator of operation completion
*/
@@ -60,7 +58,6 @@ public interface ReactiveSessionRepository<S extends Session> {
/**
* Gets the {@link Session} by the {@link Session#getId()} or null if no
* {@link Session} is found.
*
* @param id the {@link Session#getId()} to lookup
* @return the {@link Session} by the {@link Session#getId()} or null if no
* {@link Session} is found.

View File

@@ -0,0 +1,49 @@
/*
* Copyright 2014-2019 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
*
* https://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.session;
/**
* Supported modes of tracking and saving session changes to session store.
*
* @author Rob Winch
* @author Vedran Pavic
* @since 2.2.0
*/
public enum SaveMode {
/**
* Save only changes made to session, for instance using
* {@link Session#setAttribute(String, Object)}. In highly concurrent environments,
* this mode minimizes the risk of attributes being overwritten during processing of
* parallel requests.
*/
ON_SET_ATTRIBUTE,
/**
* Same as {@link #ON_SET_ATTRIBUTE} with addition of saving attributes that have been
* read using {@link Session#getAttribute(String)}.
*/
ON_GET_ATTRIBUTE,
/**
* Always save all session attributes, regardless of the interaction with the session.
* In highly concurrent environments, this mode increases the risk of attributes being
* overwritten during processing of parallel requests.
*/
ALWAYS
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 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.
@@ -32,13 +32,13 @@ public interface Session {
/**
* Gets a unique string that identifies the {@link Session}.
*
* @return a unique string that identifies the {@link Session}
*/
String getId();
/**
* Changes the session id. After invoking the {@link #getId()} will return a new identifier.
* Changes the session id. After invoking the {@link #getId()} will return a new
* identifier.
* @return the new session id which {@link #getId()} will now return
*/
String changeSessionId();
@@ -46,7 +46,6 @@ public interface Session {
/**
* Gets the Object associated with the specified name or null if no Object is
* associated to that name.
*
* @param <T> the return type of the attribute
* @param attributeName the name of the attribute to get
* @return the Object associated with the specified name or null if no Object is
@@ -65,8 +64,7 @@ public interface Session {
default <T> T getRequiredAttribute(String name) {
T result = getAttribute(name);
if (result == null) {
throw new IllegalArgumentException(
"Required attribute '" + name + "' is missing.");
throw new IllegalArgumentException("Required attribute '" + name + "' is missing.");
}
return result;
}
@@ -88,7 +86,6 @@ public interface Session {
* Gets the attribute names that have a value associated with it. Each value can be
* passed into {@link org.springframework.session.Session#getAttribute(String)} to
* obtain the attribute value.
*
* @return the attribute names that have a value associated with it.
* @see #getAttribute(String)
*/
@@ -98,7 +95,6 @@ public interface Session {
* Sets the attribute value for the provided attribute name. If the attributeValue is
* null, it has the same result as removing the attribute with
* {@link org.springframework.session.Session#removeAttribute(String)} .
*
* @param attributeName the attribute name to set
* @param attributeValue the value of the attribute to set. If null, the attribute
* will be removed.
@@ -113,21 +109,18 @@ public interface Session {
/**
* Gets the time when this session was created.
*
* @return the time when this session was created.
*/
Instant getCreationTime();
/**
* Sets the last accessed time.
*
* @param lastAccessedTime the last accessed time
*/
void setLastAccessedTime(Instant lastAccessedTime);
/**
* Gets the last time this {@link Session} was accessed.
*
* @return the last time the client sent a request associated with the session
*/
Instant getLastAccessedTime();
@@ -135,7 +128,6 @@ public interface Session {
/**
* Sets the maximum inactive interval between requests before this session will be
* invalidated. A negative time indicates that the session will never timeout.
*
* @param interval the amount of time that the {@link Session} should be kept alive
* between client requests.
*/
@@ -144,7 +136,6 @@ public interface Session {
/**
* Gets the maximum inactive interval between requests before this session will be
* invalidated. A negative time indicates that the session will never timeout.
*
* @return the maximum inactive interval between requests before this session will be
* invalidated. A negative time indicates that the session will never timeout.
*/
@@ -152,7 +143,6 @@ public interface Session {
/**
* Returns true if the session is expired.
*
* @return true if the session is expired, else false.
*/
boolean isExpired();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2019 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.
@@ -34,7 +34,6 @@ public interface SessionRepository<S extends Session> {
* persisted. For example, the implementation returned might keep track of the changes
* ensuring that only the delta needs to be persisted on a save.
* </p>
*
* @return a new {@link Session} that is capable of being persisted by this
* {@link SessionRepository}
*/
@@ -49,7 +48,6 @@ public interface SessionRepository<S extends Session> {
* returning a {@link Session} that immediately persists any changes. In this case,
* this method may not actually do anything.
* </p>
*
* @param session the {@link Session} to save
*/
void save(S session);
@@ -57,7 +55,6 @@ public interface SessionRepository<S extends Session> {
/**
* Gets the {@link Session} by the {@link Session#getId()} or null if no
* {@link Session} is found.
*
* @param id the {@link org.springframework.session.Session#getId()} to lookup
* @return the {@link Session} by the {@link Session#getId()} or null if no
* {@link Session} is found.
@@ -70,4 +67,5 @@ public interface SessionRepository<S extends Session> {
* @param id the {@link org.springframework.session.Session#getId()} to delete
*/
void deleteById(String id);
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2014-2019 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
*
* https://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.session;
import java.util.Collections;
import java.util.Map;
import org.springframework.util.Assert;
/**
* Base class for {@link IndexResolver}s that resolve a single index.
*
* @param <S> the type of Session being handled
* @author Rob Winch
* @author Vedran Pavic
* @since 2.2.0
*/
public abstract class SingleIndexResolver<S extends Session> implements IndexResolver<S> {
private final String indexName;
protected SingleIndexResolver(String indexName) {
Assert.notNull(indexName, "Index name must not be null");
this.indexName = indexName;
}
protected String getIndexName() {
return this.indexName;
}
public abstract String resolveIndexValueFor(S session);
public final Map<String, String> resolveIndexesFor(S session) {
String indexValue = resolveIndexValueFor(session);
return (indexValue != null) ? Collections.singletonMap(this.indexName, indexValue) : Collections.emptyMap();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2019 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.
@@ -76,4 +76,5 @@ import org.springframework.session.events.SessionDestroyedEvent;
@Import(SpringHttpSessionConfiguration.class)
@Configuration
public @interface EnableSpringHttpSession {
}

View File

@@ -88,7 +88,6 @@ import org.springframework.util.ObjectUtils;
* @author Rob Winch
* @author Vedran Pavic
* @since 1.1
*
* @see EnableSpringHttpSession
*/
@Configuration(proxyBeanMethods = false)
@@ -110,8 +109,7 @@ public class SpringHttpSessionConfiguration implements ApplicationContextAware {
@PostConstruct
public void init() {
CookieSerializer cookieSerializer = (this.cookieSerializer != null)
? this.cookieSerializer
CookieSerializer cookieSerializer = (this.cookieSerializer != null) ? this.cookieSerializer
: createDefaultCookieSerializer();
this.defaultHttpSessionIdResolver.setCookieSerializer(cookieSerializer);
}
@@ -124,21 +122,16 @@ public class SpringHttpSessionConfiguration implements ApplicationContextAware {
@Bean
public <S extends Session> SessionRepositoryFilter<? extends Session> springSessionRepositoryFilter(
SessionRepository<S> sessionRepository) {
SessionRepositoryFilter<S> sessionRepositoryFilter = new SessionRepositoryFilter<>(
sessionRepository);
SessionRepositoryFilter<S> sessionRepositoryFilter = new SessionRepositoryFilter<>(sessionRepository);
sessionRepositoryFilter.setHttpSessionIdResolver(this.httpSessionIdResolver);
return sessionRepositoryFilter;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
if (ClassUtils.isPresent(
"org.springframework.security.web.authentication.RememberMeServices",
null)) {
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (ClassUtils.isPresent("org.springframework.security.web.authentication.RememberMeServices", null)) {
this.usesSpringSessionRememberMeServices = !ObjectUtils
.isEmpty(applicationContext
.getBeanNamesForType(SpringSessionRememberMeServices.class));
.isEmpty(applicationContext.getBeanNamesForType(SpringSessionRememberMeServices.class));
}
}
@@ -170,8 +163,7 @@ public class SpringHttpSessionConfiguration implements ApplicationContextAware {
sessionCookieConfig = this.servletContext.getSessionCookieConfig();
}
catch (UnsupportedOperationException ex) {
this.logger
.warn("Unable to obtain SessionCookieConfig: " + ex.getMessage());
this.logger.warn("Unable to obtain SessionCookieConfig: " + ex.getMessage());
}
if (sessionCookieConfig != null) {
if (sessionCookieConfig.getName() != null) {
@@ -189,8 +181,7 @@ public class SpringHttpSessionConfiguration implements ApplicationContextAware {
}
}
if (this.usesSpringSessionRememberMeServices) {
cookieSerializer.setRememberMeRequestAttribute(
SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR);
cookieSerializer.setRememberMeRequestAttribute(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR);
}
return cookieSerializer;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 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.
@@ -23,9 +23,10 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* Add this annotation to a {@code @Configuration} class to configure a {@code WebSessionManager} for a WebFlux
* application. This annotation assumes a {@code ReactiveSessionRepository} is defined somewhere in the application
* context. If not, it will fail with a clear error message. For example:
* Add this annotation to a {@code @Configuration} class to configure a
* {@code WebSessionManager} for a WebFlux application. This annotation assumes a
* {@code ReactiveSessionRepository} is defined somewhere in the application context. If
* not, it will fail with a clear error message. For example:
*
* <pre>
* <code>
@@ -39,8 +40,7 @@ import org.springframework.context.annotation.Import;
* }
*
* }
* </code>
* </pre>
* </code> </pre>
*
* @author Greg Turnquist
* @since 2.0
@@ -51,4 +51,5 @@ import org.springframework.context.annotation.Import;
@Import(SpringWebSessionConfiguration.class)
@Configuration
public @interface EnableSpringWebSession {
}

View File

@@ -27,12 +27,12 @@ import org.springframework.web.server.session.WebSessionIdResolver;
import org.springframework.web.server.session.WebSessionManager;
/**
* Wire up a {@link WebSessionManager} using a Reactive {@link ReactiveSessionRepository} from the application context.
* Wire up a {@link WebSessionManager} using a Reactive {@link ReactiveSessionRepository}
* from the application context.
*
* @author Greg Turnquist
* @author Rob Winch
* @since 2.0
*
* @see EnableSpringWebSession
*/
@Configuration(proxyBeanMethods = false)
@@ -45,10 +45,11 @@ public class SpringWebSessionConfiguration {
private WebSessionIdResolver webSessionIdResolver;
/**
* Configure a {@link WebSessionManager} using a provided {@link ReactiveSessionRepository}.
*
* Configure a {@link WebSessionManager} using a provided
* {@link ReactiveSessionRepository}.
* @param repository a bean that implements {@link ReactiveSessionRepository}.
* @return a configured {@link WebSessionManager} registered with a preconfigured name.
* @return a configured {@link WebSessionManager} registered with a preconfigured
* name.
*/
@Bean(WebHttpHandlerBuilder.WEB_SESSION_MANAGER_BEAN_NAME)
public WebSessionManager webSessionManager(ReactiveSessionRepository<? extends Session> repository) {
@@ -62,4 +63,5 @@ public class SpringWebSessionConfiguration {
return manager;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 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.
@@ -44,7 +44,6 @@ public abstract class AbstractSessionEvent extends ApplicationEvent {
* Gets the {@link Session} that was destroyed. For some {@link SessionRepository}
* implementations it may not be possible to get the original session in which case
* this may be null.
*
* @param <S> the type of Session
* @return the expired {@link Session} or null if the data store does not support
* obtaining it

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 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.
@@ -36,23 +36,18 @@ import org.springframework.session.SessionRepository;
* @author Vedran Pavic
* @since 1.3
*/
class SpringSessionBackedSessionInformation<S extends Session>
extends SessionInformation {
class SpringSessionBackedSessionInformation<S extends Session> extends SessionInformation {
static final String EXPIRED_ATTR = SpringSessionBackedSessionInformation.class
.getName() + ".EXPIRED";
static final String EXPIRED_ATTR = SpringSessionBackedSessionInformation.class.getName() + ".EXPIRED";
private static final Log logger = LogFactory
.getLog(SpringSessionBackedSessionInformation.class);
private static final Log logger = LogFactory.getLog(SpringSessionBackedSessionInformation.class);
private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
private final SessionRepository<S> sessionRepository;
SpringSessionBackedSessionInformation(S session,
SessionRepository<S> sessionRepository) {
super(resolvePrincipal(session), session.getId(),
Date.from(session.getLastAccessedTime()));
SpringSessionBackedSessionInformation(S session, SessionRepository<S> sessionRepository) {
super(resolvePrincipal(session), session.getId(), Date.from(session.getLastAccessedTime()));
this.sessionRepository = sessionRepository;
Boolean expired = session.getAttribute(EXPIRED_ATTR);
if (Boolean.TRUE.equals(expired)) {
@@ -62,20 +57,16 @@ class SpringSessionBackedSessionInformation<S extends Session>
/**
* Tries to determine the principal's name from the given Session.
*
* @param session the session
* @return the principal's name, or empty String if it couldn't be determined
*/
private static String resolvePrincipal(Session session) {
String principalName = session
.getAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME);
String principalName = session.getAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME);
if (principalName != null) {
return principalName;
}
SecurityContext securityContext = session
.getAttribute(SPRING_SECURITY_CONTEXT);
if (securityContext != null
&& securityContext.getAuthentication() != null) {
SecurityContext securityContext = session.getAttribute(SPRING_SECURITY_CONTEXT);
if (securityContext != null && securityContext.getAuthentication() != null) {
return securityContext.getAuthentication().getName();
}
return "";
@@ -84,9 +75,8 @@ class SpringSessionBackedSessionInformation<S extends Session>
@Override
public void expireNow() {
if (logger.isDebugEnabled()) {
logger.debug("Expiring session " + getSessionId() + " for user '"
+ getPrincipal() + "', presumably because maximum allowed concurrent "
+ "sessions was exceeded");
logger.debug("Expiring session " + getSessionId() + " for user '" + getPrincipal()
+ "', presumably because maximum allowed concurrent " + "sessions was exceeded");
}
super.expireNow();
S session = this.sessionRepository.findById(getSessionId());
@@ -95,8 +85,7 @@ class SpringSessionBackedSessionInformation<S extends Session>
this.sessionRepository.save(session);
}
else {
logger.info("Could not find Session with id " + getSessionId()
+ " to mark as expired");
logger.info("Could not find Session with id " + getSessionId() + " to mark as expired");
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 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.
@@ -44,13 +44,11 @@ import org.springframework.util.Assert;
* @author Vedran Pavic
* @since 1.3
*/
public class SpringSessionBackedSessionRegistry<S extends Session>
implements SessionRegistry {
public class SpringSessionBackedSessionRegistry<S extends Session> implements SessionRegistry {
private final FindByIndexNameSessionRepository<S> sessionRepository;
public SpringSessionBackedSessionRegistry(
FindByIndexNameSessionRepository<S> sessionRepository) {
public SpringSessionBackedSessionRegistry(FindByIndexNameSessionRepository<S> sessionRepository) {
Assert.notNull(sessionRepository, "sessionRepository cannot be null");
this.sessionRepository = sessionRepository;
}
@@ -63,16 +61,13 @@ public class SpringSessionBackedSessionRegistry<S extends Session>
}
@Override
public List<SessionInformation> getAllSessions(Object principal,
boolean includeExpiredSessions) {
Collection<S> sessions = this.sessionRepository
.findByPrincipalName(name(principal)).values();
public List<SessionInformation> getAllSessions(Object principal, boolean includeExpiredSessions) {
Collection<S> sessions = this.sessionRepository.findByPrincipalName(name(principal)).values();
List<SessionInformation> infos = new ArrayList<>();
for (S session : sessions) {
if (includeExpiredSessions || !Boolean.TRUE.equals(session
.getAttribute(SpringSessionBackedSessionInformation.EXPIRED_ATTR))) {
infos.add(new SpringSessionBackedSessionInformation<>(session,
this.sessionRepository));
if (includeExpiredSessions
|| !Boolean.TRUE.equals(session.getAttribute(SpringSessionBackedSessionInformation.EXPIRED_ATTR))) {
infos.add(new SpringSessionBackedSessionInformation<>(session, this.sessionRepository));
}
}
return infos;
@@ -82,8 +77,7 @@ public class SpringSessionBackedSessionRegistry<S extends Session>
public SessionInformation getSessionInformation(String sessionId) {
S session = this.sessionRepository.findById(sessionId);
if (session != null) {
return new SpringSessionBackedSessionInformation<>(session,
this.sessionRepository);
return new SpringSessionBackedSessionInformation<>(session, this.sessionRepository);
}
return null;
}
@@ -111,7 +105,6 @@ public class SpringSessionBackedSessionRegistry<S extends Session>
/**
* Derives a String name for the given principal.
*
* @param principal as provided by Spring Security
* @return name of the principal, or its {@code toString()} representation if no name
* could be derived

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2019 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.
@@ -36,21 +36,19 @@ import org.springframework.util.Assert;
* @author Vedran Pavic
* @since 1.3.0
*/
public class SpringSessionRememberMeServices
implements RememberMeServices, LogoutHandler {
public class SpringSessionRememberMeServices implements RememberMeServices, LogoutHandler {
/**
* Remember-me login request attribute name.
*/
public static final String REMEMBER_ME_LOGIN_ATTR = SpringSessionRememberMeServices.class
.getName() + "REMEMBER_ME_LOGIN_ATTR";
public static final String REMEMBER_ME_LOGIN_ATTR = SpringSessionRememberMeServices.class.getName()
+ "REMEMBER_ME_LOGIN_ATTR";
private static final String DEFAULT_REMEMBERME_PARAMETER = "remember-me";
private static final int THIRTY_DAYS_SECONDS = 2592000;
private static final Log logger = LogFactory
.getLog(SpringSessionRememberMeServices.class);
private static final Log logger = LogFactory.getLog(SpringSessionRememberMeServices.class);
private String rememberMeParameterName = DEFAULT_REMEMBERME_PARAMETER;
@@ -58,25 +56,20 @@ public class SpringSessionRememberMeServices
private int validitySeconds = THIRTY_DAYS_SECONDS;
private String sessionAttrToDeleteOnLoginFail = HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY;
@Override
public final Authentication autoLogin(HttpServletRequest request,
HttpServletResponse response) {
public final Authentication autoLogin(HttpServletRequest request, HttpServletResponse response) {
return null;
}
@Override
public final void loginFail(HttpServletRequest request,
HttpServletResponse response) {
public final void loginFail(HttpServletRequest request, HttpServletResponse response) {
logout(request);
}
@Override
public final void loginSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication successfulAuthentication) {
if (!this.alwaysRemember
&& !rememberMeRequested(request, this.rememberMeParameterName)) {
public final void loginSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication successfulAuthentication) {
if (!this.alwaysRemember && !rememberMeRequested(request, this.rememberMeParameterName)) {
logger.debug("Remember-me login not requested.");
return;
}
@@ -103,8 +96,7 @@ public class SpringSessionRememberMeServices
}
}
if (logger.isDebugEnabled()) {
logger.debug("Did not send remember-me cookie (principal did not set "
+ "parameter '" + parameter + "')");
logger.debug("Did not send remember-me cookie (principal did not set " + "parameter '" + parameter + "')");
}
return false;
}
@@ -116,8 +108,7 @@ public class SpringSessionRememberMeServices
* @param rememberMeParameterName the request parameter
*/
public void setRememberMeParameterName(String rememberMeParameterName) {
Assert.hasText(rememberMeParameterName,
"rememberMeParameterName cannot be empty or null");
Assert.hasText(rememberMeParameterName, "rememberMeParameterName cannot be empty or null");
this.rememberMeParameterName = rememberMeParameterName;
}
@@ -130,8 +121,7 @@ public class SpringSessionRememberMeServices
}
@Override
public void logout(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) {
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
logout(request);
}
@@ -139,7 +129,8 @@ public class SpringSessionRememberMeServices
logger.debug("Interactive login attempt was unsuccessful.");
HttpSession session = request.getSession(false);
if (session != null) {
session.removeAttribute(this.sessionAttrToDeleteOnLoginFail);
session.removeAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2019 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.
@@ -23,7 +23,6 @@ import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterRegistration.Dynamic;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import org.springframework.context.ApplicationContext;
import org.springframework.core.Conventions;
@@ -71,8 +70,7 @@ import org.springframework.web.filter.DelegatingFilterProxy;
*
*/
@Order(100)
public abstract class AbstractHttpSessionApplicationInitializer
implements WebApplicationInitializer {
public abstract class AbstractHttpSessionApplicationInitializer implements WebApplicationInitializer {
private static final String SERVLET_CONTEXT_PREFIX = "org.springframework.web.servlet.FrameworkServlet.CONTEXT.";
@@ -98,17 +96,15 @@ public abstract class AbstractHttpSessionApplicationInitializer
/**
* Creates a new instance that will instantiate the {@link ContextLoaderListener} with
* the specified classes.
*
* @param configurationClasses {@code @Configuration} classes that will be used to
* configure the context
*/
protected AbstractHttpSessionApplicationInitializer(
Class<?>... configurationClasses) {
protected AbstractHttpSessionApplicationInitializer(Class<?>... configurationClasses) {
this.configurationClasses = configurationClasses;
}
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
public void onStartup(ServletContext servletContext) {
beforeSessionRepositoryFilter(servletContext);
if (this.configurationClasses != null) {
AnnotationConfigWebApplicationContext rootAppContext = new AnnotationConfigWebApplicationContext();
@@ -125,8 +121,7 @@ public abstract class AbstractHttpSessionApplicationInitializer
*/
private void insertSessionRepositoryFilter(ServletContext servletContext) {
String filterName = DEFAULT_FILTER_NAME;
DelegatingFilterProxy springSessionRepositoryFilter = new DelegatingFilterProxy(
filterName);
DelegatingFilterProxy springSessionRepositoryFilter = new DelegatingFilterProxy(filterName);
String contextAttribute = getWebApplicationContextAttribute();
if (contextAttribute != null) {
springSessionRepositoryFilter.setContextAttribute(contextAttribute);
@@ -138,7 +133,6 @@ public abstract class AbstractHttpSessionApplicationInitializer
* Inserts the provided {@link Filter}s before existing {@link Filter}s using default
* generated names, {@link #getSessionDispatcherTypes()}, and
* {@link #isAsyncSessionSupported()}.
*
* @param servletContext the {@link ServletContext} to use
* @param filters the {@link Filter}s to register
*/
@@ -150,7 +144,6 @@ public abstract class AbstractHttpSessionApplicationInitializer
* Inserts the provided {@link Filter}s after existing {@link Filter}s using default
* generated names, {@link #getSessionDispatcherTypes()}, and
* {@link #isAsyncSessionSupported()}.
*
* @param servletContext the {@link ServletContext} to use
* @param filters the {@link Filter}s to register
*/
@@ -161,22 +154,18 @@ public abstract class AbstractHttpSessionApplicationInitializer
/**
* Registers the provided {@link Filter}s using default generated names,
* {@link #getSessionDispatcherTypes()}, and {@link #isAsyncSessionSupported()}.
*
* @param servletContext the {@link ServletContext} to use
* @param insertBeforeOtherFilters if true, will insert the provided {@link Filter}s
* before other {@link Filter}s. Otherwise, will insert the {@link Filter}s after
* other {@link Filter}s.
* @param filters the {@link Filter}s to register
*/
private void registerFilters(ServletContext servletContext,
boolean insertBeforeOtherFilters, Filter... filters) {
private void registerFilters(ServletContext servletContext, boolean insertBeforeOtherFilters, Filter... filters) {
Assert.notEmpty(filters, "filters cannot be null or empty");
for (Filter filter : filters) {
if (filter == null) {
throw new IllegalArgumentException(
"filters cannot contain null values. Got "
+ Arrays.asList(filters));
throw new IllegalArgumentException("filters cannot contain null values. Got " + Arrays.asList(filters));
}
String filterName = Conventions.getVariableName(filter);
registerFilter(servletContext, insertBeforeOtherFilters, filterName, filter);
@@ -186,25 +175,22 @@ public abstract class AbstractHttpSessionApplicationInitializer
/**
* Registers the provided filter using the {@link #isAsyncSessionSupported()} and
* {@link #getSessionDispatcherTypes()}.
*
* @param servletContext the servlet context
* @param insertBeforeOtherFilters should this Filter be inserted before or after
* other {@link Filter}
* @param filterName the filter name
* @param filter the filter
*/
private void registerFilter(ServletContext servletContext,
boolean insertBeforeOtherFilters, String filterName, Filter filter) {
private void registerFilter(ServletContext servletContext, boolean insertBeforeOtherFilters, String filterName,
Filter filter) {
Dynamic registration = servletContext.addFilter(filterName, filter);
if (registration == null) {
throw new IllegalStateException(
"Duplicate Filter registration for '" + filterName
+ "'. Check to ensure the Filter is only configured once.");
throw new IllegalStateException("Duplicate Filter registration for '" + filterName
+ "'. Check to ensure the Filter is only configured once.");
}
registration.setAsyncSupported(isAsyncSessionSupported());
EnumSet<DispatcherType> dispatcherTypes = getSessionDispatcherTypes();
registration.addMappingForUrlPatterns(dispatcherTypes, !insertBeforeOtherFilters,
"/*");
registration.addMappingForUrlPatterns(dispatcherTypes, !insertBeforeOtherFilters, "/*");
}
/**
@@ -218,7 +204,6 @@ public abstract class AbstractHttpSessionApplicationInitializer
* {@link ApplicationContext} is used to look up the springSessionRepositoryFilter
* bean.
* </p>
*
* @return the {@link DelegatingFilterProxy#getContextAttribute()} or null if the
* parent {@link ApplicationContext} should be used
*/
@@ -241,7 +226,6 @@ public abstract class AbstractHttpSessionApplicationInitializer
* name, you can return "dispatcher" from this method to use the DispatcherServlet's
* {@link WebApplicationContext}.
* </p>
*
* @return the {@code <servlet-name>} of the DispatcherServlet to use its
* {@link WebApplicationContext} or null (default) to use the parent
* {@link ApplicationContext}.
@@ -271,17 +255,16 @@ public abstract class AbstractHttpSessionApplicationInitializer
* @return the {@link DispatcherType} for the filter
*/
protected EnumSet<DispatcherType> getSessionDispatcherTypes() {
return EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR,
DispatcherType.ASYNC);
return EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR, DispatcherType.ASYNC);
}
/**
* Determine if the springSessionRepositoryFilter should be marked as supporting
* asynch. Default is true.
*
* @return true if springSessionRepositoryFilter should be marked as supporting asynch
*/
protected boolean isAsyncSessionSupported() {
return true;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2017 the original author or authors.
* Copyright 2014-2019 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.
@@ -63,8 +63,8 @@ import org.springframework.session.web.http.CookieSerializer.CookieValue;
*/
public final class CookieHttpSessionIdResolver implements HttpSessionIdResolver {
private static final String WRITTEN_SESSION_ID_ATTR = CookieHttpSessionIdResolver.class
.getName().concat(".WRITTEN_SESSION_ID_ATTR");
private static final String WRITTEN_SESSION_ID_ATTR = CookieHttpSessionIdResolver.class.getName()
.concat(".WRITTEN_SESSION_ID_ATTR");
private CookieSerializer cookieSerializer = new DefaultCookieSerializer();
@@ -74,14 +74,12 @@ public final class CookieHttpSessionIdResolver implements HttpSessionIdResolver
}
@Override
public void setSessionId(HttpServletRequest request, HttpServletResponse response,
String sessionId) {
public void setSessionId(HttpServletRequest request, HttpServletResponse response, String sessionId) {
if (sessionId.equals(request.getAttribute(WRITTEN_SESSION_ID_ATTR))) {
return;
}
request.setAttribute(WRITTEN_SESSION_ID_ATTR, sessionId);
this.cookieSerializer
.writeCookieValue(new CookieValue(request, response, sessionId));
this.cookieSerializer.writeCookieValue(new CookieValue(request, response, sessionId));
}
@Override
@@ -91,7 +89,6 @@ public final class CookieHttpSessionIdResolver implements HttpSessionIdResolver
/**
* Sets the {@link CookieSerializer} to be used.
*
* @param cookieSerializer the cookieSerializer to set. Cannot be null.
*/
public void setCookieSerializer(CookieSerializer cookieSerializer) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 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.
@@ -32,7 +32,6 @@ public interface CookieSerializer {
/**
* Writes a given {@link CookieValue} to the provided {@link HttpServletResponse}.
*
* @param cookieValue the {@link CookieValue} to write to
* {@link CookieValue#getResponse()}. Cannot be null.
*/
@@ -43,7 +42,6 @@ public interface CookieSerializer {
* List since there can be multiple {@link Cookie} in a single request with a matching
* name. For example, one Cookie may have a path of / and another of /context, but the
* path is not transmitted in the request.
*
* @param request the {@link HttpServletRequest} to read the cookie from. Cannot be
* null.
* @return the values of all the matching cookies
@@ -70,7 +68,6 @@ public interface CookieSerializer {
/**
* Creates a new instance.
*
* @param request the {@link HttpServletRequest} to use. Useful for determining
* the context in which the cookie is set. Cannot be null.
* @param response the {@link HttpServletResponse} to use.
@@ -78,8 +75,7 @@ public interface CookieSerializer {
* modified by the {@link CookieSerializer} when writing to the actual cookie so
* long as the original value is returned when the cookie is read.
*/
public CookieValue(HttpServletRequest request, HttpServletResponse response,
String cookieValue) {
public CookieValue(HttpServletRequest request, HttpServletResponse response, String cookieValue) {
this.request = request;
this.response = response;
this.cookieValue = cookieValue;
@@ -108,7 +104,6 @@ public interface CookieSerializer {
* The value to be written. This value may be modified by the
* {@link CookieSerializer} before written to the cookie. However, the value must
* be the same as the original when it is read back in.
*
* @return the value to be written
*/
public String getCookieValue() {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 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.
@@ -97,15 +97,12 @@ public class DefaultCookieSerializer implements CookieSerializer {
if (cookies != null) {
for (Cookie cookie : cookies) {
if (this.cookieName.equals(cookie.getName())) {
String sessionId = (this.useBase64Encoding
? base64Decode(cookie.getValue())
: cookie.getValue());
String sessionId = (this.useBase64Encoding ? base64Decode(cookie.getValue()) : cookie.getValue());
if (sessionId == null) {
continue;
}
if (this.jvmRoute != null && sessionId.endsWith(this.jvmRoute)) {
sessionId = sessionId.substring(0,
sessionId.length() - this.jvmRoute.length());
sessionId = sessionId.substring(0, sessionId.length() - this.jvmRoute.length());
}
matchingCookieValues.add(sessionId);
}
@@ -135,11 +132,9 @@ public class DefaultCookieSerializer implements CookieSerializer {
int maxAge = getMaxAge(cookieValue);
if (maxAge > -1) {
sb.append("; Max-Age=").append(cookieValue.getCookieMaxAge());
OffsetDateTime expires = (maxAge != 0)
? OffsetDateTime.now().plusSeconds(maxAge)
OffsetDateTime expires = (maxAge != 0) ? OffsetDateTime.now().plusSeconds(maxAge)
: Instant.EPOCH.atOffset(ZoneOffset.UTC);
sb.append("; Expires=")
.append(expires.format(DateTimeFormatter.RFC_1123_DATE_TIME));
sb.append("; Expires=").append(expires.format(DateTimeFormatter.RFC_1123_DATE_TIME));
}
String domain = getDomainName(request);
if (domain != null && domain.length() > 0) {
@@ -214,10 +209,8 @@ public class DefaultCookieSerializer implements CookieSerializer {
char[] chars = value.toCharArray();
for (int i = start; i < end; i++) {
char c = chars[i];
if (c < 0x21 || c == 0x22 || c == 0x2c || c == 0x3b || c == 0x5c
|| c == 0x7f) {
throw new IllegalArgumentException(
"Invalid character in cookie value: " + Integer.toString(c));
if (c < 0x21 || c == 0x22 || c == 0x2c || c == 0x3b || c == 0x5c || c == 0x7f) {
throw new IllegalArgumentException("Invalid character in cookie value: " + c);
}
}
}
@@ -225,8 +218,8 @@ public class DefaultCookieSerializer implements CookieSerializer {
private int getMaxAge(CookieValue cookieValue) {
int maxAge = cookieValue.getCookieMaxAge();
if (maxAge < 0) {
if (this.rememberMeRequestAttribute != null && cookieValue.getRequest()
.getAttribute(this.rememberMeRequestAttribute) != null) {
if (this.rememberMeRequestAttribute != null
&& cookieValue.getRequest().getAttribute(this.rememberMeRequestAttribute) != null) {
// the cookie is only written at time of session creation, so we rely on
// session expiration rather than cookie expiration if remember me is
// enabled
@@ -247,8 +240,7 @@ public class DefaultCookieSerializer implements CookieSerializer {
while (i < chars.length) {
prev = cur;
cur = chars[i];
if (!domainValid.get(cur)
|| ((prev == '.' || prev == -1) && (cur == '.' || cur == '-'))
if (!domainValid.get(cur) || ((prev == '.' || prev == -1) && (cur == '.' || cur == '-'))
|| (prev == '-' && cur == '.')) {
throw new IllegalArgumentException("Invalid cookie domain: " + domain);
}
@@ -270,7 +262,6 @@ public class DefaultCookieSerializer implements CookieSerializer {
/**
* Sets if a Cookie marked as secure should be used. The default is to use the value
* of {@link HttpServletRequest#isSecure()}.
*
* @param useSecureCookie determines if the cookie should be marked as secure.
*/
public void setUseSecureCookie(boolean useSecureCookie) {
@@ -279,7 +270,6 @@ public class DefaultCookieSerializer implements CookieSerializer {
/**
* Sets if a Cookie marked as HTTP Only should be used. The default is true.
*
* @param useHttpOnlyCookie determines if the cookie should be marked as HTTP Only.
*/
public void setUseHttpOnlyCookie(boolean useHttpOnlyCookie) {
@@ -296,7 +286,6 @@ public class DefaultCookieSerializer implements CookieSerializer {
/**
* Sets the path of the Cookie. The default is to use the context path from the
* {@link HttpServletRequest}.
*
* @param cookiePath the path of the Cookie. If null, the default of the context path
* will be used.
*/
@@ -314,7 +303,6 @@ public class DefaultCookieSerializer implements CookieSerializer {
/**
* Sets the maxAge property of the Cookie. The default is to delete the cookie when
* the browser is closed.
*
* @param cookieMaxAge the maxAge property of the Cookie
*/
public void setCookieMaxAge(int cookieMaxAge) {
@@ -325,14 +313,12 @@ public class DefaultCookieSerializer implements CookieSerializer {
* Sets an explicit Domain Name. This allow the domain of "example.com" to be used
* when the request comes from www.example.com. This allows for sharing the cookie
* across subdomains. The default is to use the current domain.
*
* @param domainName the name of the domain to use. (i.e. "example.com")
* @throws IllegalStateException if the domainNamePattern is also set
*/
public void setDomainName(String domainName) {
if (this.domainNamePattern != null) {
throw new IllegalStateException(
"Cannot set both domainName and domainNamePattern");
throw new IllegalStateException("Cannot set both domainName and domainNamePattern");
}
this.domainName = domainName;
}
@@ -362,18 +348,15 @@ public class DefaultCookieSerializer implements CookieSerializer {
* <li>localhost - null</li>
* <li>127.0.1.1 - null</li>
* </ul>
*
* @param domainNamePattern the case insensitive pattern to extract the domain name
* with
* @throws IllegalStateException if the domainName is also set
*/
public void setDomainNamePattern(String domainNamePattern) {
if (this.domainName != null) {
throw new IllegalStateException(
"Cannot set both domainName and domainNamePattern");
throw new IllegalStateException("Cannot set both domainName and domainNamePattern");
}
this.domainNamePattern = Pattern.compile(domainNamePattern,
Pattern.CASE_INSENSITIVE);
this.domainNamePattern = Pattern.compile(domainNamePattern, Pattern.CASE_INSENSITIVE);
}
/**
@@ -390,7 +373,6 @@ public class DefaultCookieSerializer implements CookieSerializer {
* To use set a custom route on each JVM instance and setup a frontend proxy to
* forward all requests to the JVM based on the route.
* </p>
*
* @param jvmRoute the JVM Route to use (i.e. "node01jvmA", "n01ja", etc)
*/
public void setJvmRoute(String jvmRoute) {
@@ -401,7 +383,6 @@ public class DefaultCookieSerializer implements CookieSerializer {
* Set if the Base64 encoding of cookie value should be used. This is valuable in
* order to support <a href="https://tools.ietf.org/html/rfc6265">RFC 6265</a> which
* recommends using Base 64 encoding to the cookie value.
*
* @param useBase64Encoding the flag to indicate whether to use Base64 encoding
*/
public void setUseBase64Encoding(boolean useBase64Encoding) {
@@ -416,8 +397,7 @@ public class DefaultCookieSerializer implements CookieSerializer {
*/
public void setRememberMeRequestAttribute(String rememberMeRequestAttribute) {
if (rememberMeRequestAttribute == null) {
throw new IllegalArgumentException(
"rememberMeRequestAttribute cannot be null");
throw new IllegalArgumentException("rememberMeRequestAttribute cannot be null");
}
this.rememberMeRequestAttribute = rememberMeRequestAttribute;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 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.
@@ -98,13 +98,11 @@ public class HeaderHttpSessionIdResolver implements HttpSessionIdResolver {
@Override
public List<String> resolveSessionIds(HttpServletRequest request) {
String headerValue = request.getHeader(this.headerName);
return (headerValue != null) ? Collections.singletonList(headerValue)
: Collections.emptyList();
return (headerValue != null) ? Collections.singletonList(headerValue) : Collections.emptyList();
}
@Override
public void setSessionId(HttpServletRequest request, HttpServletResponse response,
String sessionId) {
public void setSessionId(HttpServletRequest request, HttpServletResponse response, String sessionId) {
response.setHeader(this.headerName, sessionId);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 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.
@@ -142,8 +142,8 @@ class HttpSessionAdapter<S extends Session> implements HttpSession {
if (value != oldValue) {
if (oldValue instanceof HttpSessionBindingListener) {
try {
((HttpSessionBindingListener) oldValue).valueUnbound(
new HttpSessionBindingEvent(this, name, oldValue));
((HttpSessionBindingListener) oldValue)
.valueUnbound(new HttpSessionBindingEvent(this, name, oldValue));
}
catch (Throwable th) {
logger.error("Error invoking session binding event listener", th);
@@ -151,8 +151,7 @@ class HttpSessionAdapter<S extends Session> implements HttpSession {
}
if (value instanceof HttpSessionBindingListener) {
try {
((HttpSessionBindingListener) value)
.valueBound(new HttpSessionBindingEvent(this, name, value));
((HttpSessionBindingListener) value).valueBound(new HttpSessionBindingEvent(this, name, value));
}
catch (Throwable th) {
logger.error("Error invoking session binding event listener", th);
@@ -173,8 +172,7 @@ class HttpSessionAdapter<S extends Session> implements HttpSession {
this.session.removeAttribute(name);
if (oldValue instanceof HttpSessionBindingListener) {
try {
((HttpSessionBindingListener) oldValue)
.valueUnbound(new HttpSessionBindingEvent(this, name, oldValue));
((HttpSessionBindingListener) oldValue).valueUnbound(new HttpSessionBindingEvent(this, name, oldValue));
}
catch (Throwable th) {
logger.error("Error invoking session binding event listener", th);
@@ -205,8 +203,7 @@ class HttpSessionAdapter<S extends Session> implements HttpSession {
private void checkState() {
if (this.invalidated) {
throw new IllegalStateException(
"The HttpSession has already be invalidated.");
throw new IllegalStateException("The HttpSession has already be invalidated.");
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 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.
@@ -49,8 +49,7 @@ public interface HttpSessionIdResolver {
* @param response the current response
* @param sessionId the session id
*/
void setSessionId(HttpServletRequest request, HttpServletResponse response,
String sessionId);
void setSessionId(HttpServletRequest request, HttpServletResponse response, String sessionId);
/**
* Instruct the client to end the current session. This method is invoked when a

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 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.
@@ -36,6 +36,7 @@ import org.apache.commons.logging.LogFactory;
* @since 1.0
*/
abstract class OnCommittedResponseWrapper extends HttpServletResponseWrapper {
private final Log logger = LogFactory.getLog(getClass());
private boolean disableOnCommitted;
@@ -204,13 +205,11 @@ abstract class OnCommittedResponseWrapper extends HttpServletResponseWrapper {
/**
* Adds the contentLengthToWrite to the total contentWritten size and checks to see if
* the response should be written.
*
* @param contentLengthToWrite the size of the content that is about to be written.
*/
private void checkContentLength(long contentLengthToWrite) {
this.contentWritten += contentLengthToWrite;
boolean isBodyFullyWritten = this.contentLength > 0
&& this.contentWritten >= this.contentLength;
boolean isBodyFullyWritten = this.contentLength > 0 && this.contentWritten >= this.contentLength;
int bufferSize = getBufferSize();
boolean requiresFlush = bufferSize > 0 && this.contentWritten >= bufferSize;
if (isBodyFullyWritten || requiresFlush) {
@@ -234,9 +233,11 @@ abstract class OnCommittedResponseWrapper extends HttpServletResponseWrapper {
* calling the prior to methods that commit the response. We delegate all methods to
* the original {@link java.io.PrintWriter} to ensure that the behavior is as close to
* the original {@link java.io.PrintWriter} as possible. See SEC-2039
*
* @author Rob Winch
*/
private class SaveContextPrintWriter extends PrintWriter {
private final PrintWriter delegate;
SaveContextPrintWriter(PrintWriter delegate) {
@@ -466,6 +467,7 @@ abstract class OnCommittedResponseWrapper extends HttpServletResponseWrapper {
trackContentLength(c);
return this.delegate.append(c);
}
}
/**
@@ -477,6 +479,7 @@ abstract class OnCommittedResponseWrapper extends HttpServletResponseWrapper {
* @author Rob Winch
*/
private class SaveContextServletOutputStream extends ServletOutputStream {
private final ServletOutputStream delegate;
SaveContextServletOutputStream(ServletOutputStream delegate) {
@@ -634,5 +637,7 @@ abstract class OnCommittedResponseWrapper extends HttpServletResponseWrapper {
public void setWriteListener(WriteListener writeListener) {
this.delegate.setWriteListener(writeListener);
}
}
}

View File

@@ -37,19 +37,18 @@ import javax.servlet.http.HttpServletResponse;
* @since 1.0
*/
abstract class OncePerRequestFilter implements Filter {
/**
* Suffix that gets appended to the filter name for the "already filtered" request
* attribute.
*/
public static final String ALREADY_FILTERED_SUFFIX = ".FILTERED";
private String alreadyFilteredAttributeName = getClass().getName()
.concat(ALREADY_FILTERED_SUFFIX);
private String alreadyFilteredAttributeName = getClass().getName().concat(ALREADY_FILTERED_SUFFIX);
/**
* This {@code doFilter} implementation stores a request attribute for
* "already filtered", proceeding without filtering again if the attribute is already
* there.
* This {@code doFilter} implementation stores a request attribute for "already
* filtered", proceeding without filtering again if the attribute is already there.
* @param request the request
* @param response the response
* @param filterChain the filter chain
@@ -57,24 +56,22 @@ abstract class OncePerRequestFilter implements Filter {
* @throws IOException in case of I/O operation exception
*/
@Override
public final void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
public final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
if (!(request instanceof HttpServletRequest)
|| !(response instanceof HttpServletResponse)) {
throw new ServletException(
"OncePerRequestFilter just supports HTTP requests");
if (!(request instanceof HttpServletRequest) || !(response instanceof HttpServletResponse)) {
throw new ServletException("OncePerRequestFilter just supports HTTP requests");
}
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String alreadyFilteredAttributeName = this.alreadyFilteredAttributeName;
alreadyFilteredAttributeName = updateForErrorDispatch(
alreadyFilteredAttributeName, request);
boolean hasAlreadyFilteredAttribute = request
.getAttribute(alreadyFilteredAttributeName) != null;
boolean hasAlreadyFilteredAttribute = request.getAttribute(alreadyFilteredAttributeName) != null;
if (hasAlreadyFilteredAttribute) {
if (DispatcherType.ERROR.equals(request.getDispatcherType())) {
doFilterNestedErrorDispatch(httpRequest, httpResponse, filterChain);
return;
}
// Proceed without invoking this filter...
filterChain.doFilter(request, response);
}
@@ -91,15 +88,39 @@ abstract class OncePerRequestFilter implements Filter {
}
}
private String updateForErrorDispatch(String alreadyFilteredAttributeName,
ServletRequest request) {
// Jetty does ERROR dispatch within sendError, so request attribute is still present
// Use a separate attribute for ERROR dispatches
if (DispatcherType.ERROR.equals(request.getDispatcherType())
&& request.getAttribute(alreadyFilteredAttributeName) != null) {
return alreadyFilteredAttributeName + ".ERROR";
}
return alreadyFilteredAttributeName;
/**
* Return the name of the request attribute that identifies that a request is already
* filtered.
* <p>
* The default implementation takes the configured name of the concrete filter
* instance and appends ".FILTERED". If the filter is not fully initialized, it falls
* back to its class name.
* @return the name of request attribute indicating already filtered request
* @see #ALREADY_FILTERED_SUFFIX
*/
protected String getAlreadyFilteredAttributeName() {
return this.alreadyFilteredAttributeName;
}
/**
* Typically an ERROR dispatch happens after the REQUEST dispatch completes, and the
* filter chain starts anew. On some servers however the ERROR dispatch may be nested
* within the REQUEST dispatch, e.g. as a result of calling {@code sendError} on the
* response. In that case we are still in the filter chain, on the same thread, but
* the request and response have been switched to the original, unwrapped ones.
* <p>
* Sub-classes may use this method to filter such nested ERROR dispatches and re-apply
* wrapping on the request or response. {@code ThreadLocal} context, if any, should
* still be active as we are still nested within the filter chain.
* @param request the request
* @param response the response
* @param filterChain the filter chain
* @throws ServletException if request is not HTTP request
* @throws IOException in case of I/O operation exception
*/
protected void doFilterNestedErrorDispatch(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
doFilter(request, response, filterChain);
}
/**
@@ -108,7 +129,6 @@ abstract class OncePerRequestFilter implements Filter {
* <p>
* Provides HttpServletRequest and HttpServletResponse arguments instead of the
* default ServletRequest and ServletResponse ones.
*
* @param request the request
* @param response the response
* @param filterChain the FilterChain
@@ -116,9 +136,8 @@ abstract class OncePerRequestFilter implements Filter {
* @throws IOException thrown when an I/O exception of some sort has occurred
* @see Filter#doFilter
*/
protected abstract void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException;
protected abstract void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException;
@Override
public void init(FilterConfig config) {
@@ -127,4 +146,5 @@ abstract class OncePerRequestFilter implements Filter {
@Override
public void destroy() {
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2017 the original author or authors.
* Copyright 2014-2019 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.
@@ -40,6 +40,7 @@ import org.springframework.web.context.ServletContextAware;
*/
public class SessionEventHttpSessionListenerAdapter
implements ApplicationListener<AbstractSessionEvent>, ServletContextAware {
private final List<HttpSessionListener> listeners;
private ServletContext context;
@@ -75,8 +76,7 @@ public class SessionEventHttpSessionListenerAdapter
private HttpSessionEvent createHttpSessionEvent(AbstractSessionEvent event) {
Session session = event.getSession();
HttpSession httpSession = new HttpSessionAdapter<>(session,
this.context);
HttpSession httpSession = new HttpSessionAdapter<>(session, this.context);
return new HttpSessionEvent(httpSession);
}
@@ -91,4 +91,5 @@ public class SessionEventHttpSessionListenerAdapter
public void setServletContext(ServletContext servletContext) {
this.context = servletContext;
}
}

View File

@@ -79,25 +79,21 @@ import org.springframework.session.SessionRepository;
@Order(SessionRepositoryFilter.DEFAULT_ORDER)
public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFilter {
private static final String SESSION_LOGGER_NAME = SessionRepositoryFilter.class
.getName().concat(".SESSION_LOGGER");
private static final String SESSION_LOGGER_NAME = SessionRepositoryFilter.class.getName().concat(".SESSION_LOGGER");
private static final Log SESSION_LOGGER = LogFactory.getLog(SESSION_LOGGER_NAME);
/**
* The session repository request attribute name.
*/
public static final String SESSION_REPOSITORY_ATTR = SessionRepository.class
.getName();
public static final String SESSION_REPOSITORY_ATTR = SessionRepository.class.getName();
/**
* Invalid session id (not backed by the session repository) request attribute name.
*/
public static final String INVALID_SESSION_ID_ATTR = SESSION_REPOSITORY_ATTR
+ ".invalidSessionId";
public static final String INVALID_SESSION_ID_ATTR = SESSION_REPOSITORY_ATTR + ".invalidSessionId";
private static final String CURRENT_SESSION_ATTR = SESSION_REPOSITORY_ATTR
+ ".CURRENT_SESSION";
private static final String CURRENT_SESSION_ATTR = SESSION_REPOSITORY_ATTR + ".CURRENT_SESSION";
/**
* The default filter order.
@@ -110,7 +106,6 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
/**
* Creates a new instance.
*
* @param sessionRepository the <code>SessionRepository</code> to use. Cannot be null.
*/
public SessionRepositoryFilter(SessionRepository<S> sessionRepository) {
@@ -123,7 +118,6 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
/**
* Sets the {@link HttpSessionIdResolver} to be used. The default is a
* {@link CookieHttpSessionIdResolver}.
*
* @param httpSessionIdResolver the {@link HttpSessionIdResolver} to use. Cannot be
* null.
*/
@@ -135,15 +129,13 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
}
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
request.setAttribute(SESSION_REPOSITORY_ATTR, this.sessionRepository);
SessionRepositoryRequestWrapper wrappedRequest = new SessionRepositoryRequestWrapper(
request, response);
SessionRepositoryResponseWrapper wrappedResponse = new SessionRepositoryResponseWrapper(
wrappedRequest, response);
SessionRepositoryRequestWrapper wrappedRequest = new SessionRepositoryRequestWrapper(request, response);
SessionRepositoryResponseWrapper wrappedResponse = new SessionRepositoryResponseWrapper(wrappedRequest,
response);
try {
filterChain.doFilter(wrappedRequest, wrappedResponse);
@@ -153,14 +145,19 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
}
}
@Override
protected void doFilterNestedErrorDispatch(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
doFilterInternal(request, response, filterChain);
}
/**
* Allows ensuring that the session is saved if the response is committed.
*
* @author Rob Winch
* @since 1.0
*/
private final class SessionRepositoryResponseWrapper
extends OnCommittedResponseWrapper {
private final class SessionRepositoryResponseWrapper extends OnCommittedResponseWrapper {
private final SessionRepositoryRequestWrapper request;
@@ -169,8 +166,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
* @param request the request to be wrapped
* @param response the response to be wrapped
*/
SessionRepositoryResponseWrapper(SessionRepositoryRequestWrapper request,
HttpServletResponse response) {
SessionRepositoryResponseWrapper(SessionRepositoryRequestWrapper request, HttpServletResponse response) {
super(response);
if (request == null) {
throw new IllegalArgumentException("request cannot be null");
@@ -182,6 +178,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
protected void onResponseCommitted() {
this.request.commitSession();
}
}
/**
@@ -192,8 +189,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
* @author Rob Winch
* @since 1.0
*/
private final class SessionRepositoryRequestWrapper
extends HttpServletRequestWrapper {
private final class SessionRepositoryRequestWrapper extends HttpServletRequestWrapper {
private final HttpServletResponse response;
@@ -207,8 +203,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
private boolean requestedSessionInvalidated;
private SessionRepositoryRequestWrapper(HttpServletRequest request,
HttpServletResponse response) {
private SessionRepositoryRequestWrapper(HttpServletRequest request, HttpServletResponse response) {
super(request);
this.response = response;
}
@@ -221,8 +216,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
HttpSessionWrapper wrappedSession = getCurrentSession();
if (wrappedSession == null) {
if (isInvalidateClientSession()) {
SessionRepositoryFilter.this.httpSessionIdResolver.expireSession(this,
this.response);
SessionRepositoryFilter.this.httpSessionIdResolver.expireSession(this, this.response);
}
}
else {
@@ -230,10 +224,8 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
clearRequestedSessionCache();
SessionRepositoryFilter.this.sessionRepository.save(session);
String sessionId = session.getId();
if (!isRequestedSessionIdValid()
|| !sessionId.equals(getRequestedSessionId())) {
SessionRepositoryFilter.this.httpSessionIdResolver.setSessionId(this,
this.response, sessionId);
if (!isRequestedSessionIdValid() || !sessionId.equals(getRequestedSessionId())) {
SessionRepositoryFilter.this.httpSessionIdResolver.setSessionId(this, this.response, sessionId);
}
}
}
@@ -321,8 +313,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
SESSION_LOGGER.debug(
"A new session was created. To help you troubleshoot where the session was created we provided a StackTrace (this is not an error). You can prevent this from appearing by disabling DEBUG logging for "
+ SESSION_LOGGER_NAME,
new RuntimeException(
"For debugging purposes only (not an error)"));
new RuntimeException("For debugging purposes only (not an error)"));
}
S session = SessionRepositoryFilter.this.sessionRepository.createSession();
session.setLastAccessedTime(Instant.now());
@@ -352,14 +343,12 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
private S getRequestedSession() {
if (!this.requestedSessionCached) {
List<String> sessionIds = SessionRepositoryFilter.this.httpSessionIdResolver
.resolveSessionIds(this);
List<String> sessionIds = SessionRepositoryFilter.this.httpSessionIdResolver.resolveSessionIds(this);
for (String sessionId : sessionIds) {
if (this.requestedSessionId == null) {
this.requestedSessionId = sessionId;
}
S session = SessionRepositoryFilter.this.sessionRepository
.findById(sessionId);
S session = SessionRepositoryFilter.this.sessionRepository.findById(sessionId);
if (session != null) {
this.requestedSession = session;
this.requestedSessionId = sessionId;
@@ -397,6 +386,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
clearRequestedSessionCache();
SessionRepositoryFilter.this.sessionRepository.deleteById(getId());
}
}
/**
@@ -404,8 +394,7 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
*
* @since 1.3.4
*/
private final class SessionCommittingRequestDispatcher
implements RequestDispatcher {
private final class SessionCommittingRequestDispatcher implements RequestDispatcher {
private final RequestDispatcher delegate;
@@ -414,14 +403,12 @@ public class SessionRepositoryFilter<S extends Session> extends OncePerRequestFi
}
@Override
public void forward(ServletRequest request, ServletResponse response)
throws ServletException, IOException {
public void forward(ServletRequest request, ServletResponse response) throws ServletException, IOException {
this.delegate.forward(request, response);
}
@Override
public void include(ServletRequest request, ServletResponse response)
throws ServletException, IOException {
public void include(ServletRequest request, ServletResponse response) throws ServletException, IOException {
SessionRepositoryRequestWrapper.this.commitSession();
this.delegate.include(request, response);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 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.
@@ -61,12 +61,14 @@ public class SpringSessionWebSessionStore<S extends Session> implements WebSessi
}
/**
* Configure the {@link Clock} to use to set lastAccessTime on every created
* session and to calculate if it is expired.
* <p>This may be useful to align to different timezone or to set the clock
* back in a test, e.g. {@code Clock.offset(clock, Duration.ofMinutes(-31))}
* in order to simulate session expiration.
* <p>By default this is {@code Clock.system(ZoneId.of("GMT"))}.
* Configure the {@link Clock} to use to set lastAccessTime on every created session
* and to calculate if it is expired.
* <p>
* This may be useful to align to different timezone or to set the clock back in a
* test, e.g. {@code Clock.offset(clock, Duration.ofMinutes(-31))} in order to
* simulate session expiration.
* <p>
* By default this is {@code Clock.system(ZoneId.of("GMT"))}.
* @param clock the clock to use
*/
public void setClock(Clock clock) {
@@ -90,8 +92,7 @@ public class SpringSessionWebSessionStore<S extends Session> implements WebSessi
@Override
public Mono<WebSession> retrieveSession(String sessionId) {
return this.sessions.findById(sessionId)
.doOnNext((session) -> session.setLastAccessedTime(this.clock.instant()))
.map(this::existingSession);
.doOnNext((session) -> session.setLastAccessedTime(this.clock.instant())).map(this::existingSession);
}
@Override
@@ -133,8 +134,7 @@ public class SpringSessionWebSessionStore<S extends Session> implements WebSessi
@Override
public Mono<Void> changeSessionId() {
return Mono.defer(() -> {
this.session
.changeSessionId();
this.session.changeSessionId();
return save();
});
}
@@ -152,8 +152,7 @@ public class SpringSessionWebSessionStore<S extends Session> implements WebSessi
@Override
public boolean isStarted() {
State value = this.state.get();
return (State.STARTED.equals(value)
|| (State.NEW.equals(value) && !getAttributes().isEmpty()));
return (State.STARTED.equals(value) || (State.NEW.equals(value) && !getAttributes().isEmpty()));
}
@Override
@@ -198,10 +197,13 @@ public class SpringSessionWebSessionStore<S extends Session> implements WebSessi
public void setMaxIdleTime(Duration maxIdleTime) {
this.session.setMaxInactiveInterval(maxIdleTime);
}
}
private enum State {
NEW, STARTED, EXPIRED
}
private static class SpringSessionMap implements Map<String, Object> {
@@ -226,8 +228,7 @@ public class SpringSessionWebSessionStore<S extends Session> implements WebSessi
@Override
public boolean containsKey(Object key) {
return key instanceof String
&& this.session.getAttributeNames().contains(key);
return key instanceof String && this.session.getAttributeNames().contains(key);
}
@Override
@@ -346,5 +347,7 @@ public class SpringSessionWebSessionStore<S extends Session> implements WebSessi
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 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.
@@ -93,8 +93,7 @@ public abstract class AbstractSessionWebSocketMessageBrokerConfigurer<S extends
public final void registerStompEndpoints(StompEndpointRegistry registry) {
if (registry instanceof WebMvcStompEndpointRegistry) {
WebMvcStompEndpointRegistry mvcRegistry = (WebMvcStompEndpointRegistry) registry;
configureStompEndpoints(new SessionStompEndpointRegistry(mvcRegistry,
sessionRepositoryInterceptor()));
configureStompEndpoints(new SessionStompEndpointRegistry(mvcRegistry, sessionRepositoryInterceptor()));
}
}
@@ -102,7 +101,6 @@ public abstract class AbstractSessionWebSocketMessageBrokerConfigurer<S extends
* Register STOMP endpoints mapping each to a specific URL and (optionally) enabling
* and configuring SockJS fallback options with a
* {@link SessionRepositoryMessageInterceptor} automatically added as an interceptor.
*
* @param registry the {@link StompEndpointRegistry} which automatically has a
* {@link SessionRepositoryMessageInterceptor} added to it.
*/
@@ -133,19 +131,19 @@ public abstract class AbstractSessionWebSocketMessageBrokerConfigurer<S extends
* A {@link StompEndpointRegistry} that applies {@link HandshakeInterceptor}.
*/
static class SessionStompEndpointRegistry implements StompEndpointRegistry {
private final WebMvcStompEndpointRegistry registry;
private final HandshakeInterceptor interceptor;
SessionStompEndpointRegistry(WebMvcStompEndpointRegistry registry,
HandshakeInterceptor interceptor) {
SessionStompEndpointRegistry(WebMvcStompEndpointRegistry registry, HandshakeInterceptor interceptor) {
this.registry = registry;
this.interceptor = interceptor;
}
@Override
public StompWebSocketEndpointRegistration addEndpoint(String... paths) {
StompWebSocketEndpointRegistration endpoints = this.registry
.addEndpoint(paths);
StompWebSocketEndpointRegistration endpoints = this.registry.addEndpoint(paths);
endpoints.addInterceptors(this.interceptor);
return endpoints;
}
@@ -161,9 +159,10 @@ public abstract class AbstractSessionWebSocketMessageBrokerConfigurer<S extends
}
@Override
public WebMvcStompEndpointRegistry setErrorHandler(
StompSubProtocolErrorHandler errorHandler) {
public WebMvcStompEndpointRegistry setErrorHandler(StompSubProtocolErrorHandler errorHandler) {
return this.registry.setErrorHandler(errorHandler);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2019 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.
@@ -44,4 +44,5 @@ public class SessionConnectEvent extends ApplicationEvent {
public WebSocketSession getWebSocketSession() {
return this.webSocketSession;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2019 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.
@@ -38,24 +38,19 @@ import org.springframework.web.socket.handler.WebSocketHandlerDecoratorFactory;
*
* @author Rob Winch
* @since 1.0
*
* @see WebSocketRegistryListener
*/
public final class WebSocketConnectHandlerDecoratorFactory
implements WebSocketHandlerDecoratorFactory {
public final class WebSocketConnectHandlerDecoratorFactory implements WebSocketHandlerDecoratorFactory {
private static final Log logger = LogFactory
.getLog(WebSocketConnectHandlerDecoratorFactory.class);
private static final Log logger = LogFactory.getLog(WebSocketConnectHandlerDecoratorFactory.class);
private final ApplicationEventPublisher eventPublisher;
/**
* Creates a new instance.
*
* @param eventPublisher the {@link ApplicationEventPublisher} to use. Cannot be null.
*/
public WebSocketConnectHandlerDecoratorFactory(
ApplicationEventPublisher eventPublisher) {
public WebSocketConnectHandlerDecoratorFactory(ApplicationEventPublisher eventPublisher) {
Assert.notNull(eventPublisher, "eventPublisher cannot be null");
this.eventPublisher = eventPublisher;
}
@@ -72,8 +67,7 @@ public final class WebSocketConnectHandlerDecoratorFactory
}
@Override
public void afterConnectionEstablished(WebSocketSession wsSession)
throws Exception {
public void afterConnectionEstablished(WebSocketSession wsSession) throws Exception {
super.afterConnectionEstablished(wsSession);
publishEvent(new SessionConnectEvent(this, wsSession));
@@ -81,12 +75,13 @@ public final class WebSocketConnectHandlerDecoratorFactory
private void publishEvent(ApplicationEvent event) {
try {
WebSocketConnectHandlerDecoratorFactory.this.eventPublisher
.publishEvent(event);
WebSocketConnectHandlerDecoratorFactory.this.eventPublisher.publishEvent(event);
}
catch (Throwable ex) {
logger.error("Error publishing " + event + ".", ex);
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 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.
@@ -41,18 +41,15 @@ import org.springframework.web.socket.messaging.SessionDisconnectEvent;
* {@link WebSocketSession} is closed.
* </p>
*
*
* @author Rob Winch
* @author Mark Anderson
* @since 1.0
*/
public final class WebSocketRegistryListener
implements ApplicationListener<ApplicationEvent> {
public final class WebSocketRegistryListener implements ApplicationListener<ApplicationEvent> {
private static final Log logger = LogFactory.getLog(WebSocketRegistryListener.class);
static final CloseStatus SESSION_EXPIRED_STATUS = new CloseStatus(
CloseStatus.POLICY_VIOLATION.getCode(),
static final CloseStatus SESSION_EXPIRED_STATUS = new CloseStatus(CloseStatus.POLICY_VIOLATION.getCode(),
"This connection was established under an authenticated HTTP Session that has expired");
private final ConcurrentHashMap<String, Map<String, WebSocketSession>> httpSessionIdToWsSessions = new ConcurrentHashMap<>();
@@ -72,8 +69,7 @@ public final class WebSocketRegistryListener
Map<String, Object> sessionAttributes = SimpMessageHeaderAccessor
.getSessionAttributes(e.getMessage().getHeaders());
String httpSessionId = (sessionAttributes != null)
? SessionRepositoryMessageInterceptor.getSessionId(sessionAttributes)
: null;
? SessionRepositoryMessageInterceptor.getSessionId(sessionAttributes) : null;
afterConnectionClosed(httpSessionId, e.getSessionId());
}
}
@@ -98,8 +94,7 @@ public final class WebSocketRegistryListener
return;
}
Map<String, WebSocketSession> sessions = this.httpSessionIdToWsSessions
.get(httpSessionId);
Map<String, WebSocketSession> sessions = this.httpSessionIdToWsSessions.get(httpSessionId);
if (sessions != null) {
boolean result = sessions.remove(wsSessionId) != null;
if (logger.isDebugEnabled()) {
@@ -108,16 +103,15 @@ public final class WebSocketRegistryListener
if (sessions.isEmpty()) {
this.httpSessionIdToWsSessions.remove(httpSessionId);
if (logger.isDebugEnabled()) {
logger.debug("Removed the corresponding HTTP Session for "
+ wsSessionId + " since it contained no WebSocket mappings");
logger.debug("Removed the corresponding HTTP Session for " + wsSessionId
+ " since it contained no WebSocket mappings");
}
}
}
}
private void registerWsSession(String httpSessionId, WebSocketSession wsSession) {
Map<String, WebSocketSession> sessions = this.httpSessionIdToWsSessions
.get(httpSessionId);
Map<String, WebSocketSession> sessions = this.httpSessionIdToWsSessions.get(httpSessionId);
if (sessions == null) {
sessions = new ConcurrentHashMap<>();
this.httpSessionIdToWsSessions.putIfAbsent(httpSessionId, sessions);
@@ -127,25 +121,22 @@ public final class WebSocketRegistryListener
}
private void closeWsSessions(String httpSessionId) {
Map<String, WebSocketSession> sessionsToClose = this.httpSessionIdToWsSessions
.remove(httpSessionId);
Map<String, WebSocketSession> sessionsToClose = this.httpSessionIdToWsSessions.remove(httpSessionId);
if (sessionsToClose == null) {
return;
}
if (logger.isDebugEnabled()) {
logger.debug(
"Closing WebSocket connections associated to expired HTTP Session "
+ httpSessionId);
logger.debug("Closing WebSocket connections associated to expired HTTP Session " + httpSessionId);
}
for (WebSocketSession toClose : sessionsToClose.values()) {
try {
toClose.close(SESSION_EXPIRED_STATUS);
}
catch (IOException ex) {
logger.debug(
"Failed to close WebSocketSession (this is nothing to worry about but for debugging only)",
logger.debug("Failed to close WebSocketSession (this is nothing to worry about but for debugging only)",
ex);
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 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.
@@ -72,15 +72,13 @@ public final class SessionRepositoryMessageInterceptor<S extends Session>
/**
* Creates a new instance.
*
* @param sessionRepository the {@link SessionRepository} to use. Cannot be null.
*/
public SessionRepositoryMessageInterceptor(SessionRepository<S> sessionRepository) {
Assert.notNull(sessionRepository, "sessionRepository cannot be null");
this.sessionRepository = sessionRepository;
this.matchingMessageTypes = EnumSet.of(SimpMessageType.CONNECT,
SimpMessageType.MESSAGE, SimpMessageType.SUBSCRIBE,
SimpMessageType.UNSUBSCRIBE);
this.matchingMessageTypes = EnumSet.of(SimpMessageType.CONNECT, SimpMessageType.MESSAGE,
SimpMessageType.SUBSCRIBE, SimpMessageType.UNSUBSCRIBE);
}
/**
@@ -94,14 +92,12 @@ public final class SessionRepositoryMessageInterceptor<S extends Session>
* The default is: SimpMessageType.CONNECT, SimpMessageType.MESSAGE,
* SimpMessageType.SUBSCRIBE, SimpMessageType.UNSUBSCRIBE.
* </p>
*
* @param matchingMessageTypes the {@link SimpMessageType} to match on in
* {@link #preSend(Message, MessageChannel)}, else the {@link Message} is continued
* without accessing or updating the {@link Session}
*/
public void setMatchingMessageTypes(Set<SimpMessageType> matchingMessageTypes) {
Assert.notEmpty(matchingMessageTypes,
"matchingMessageTypes cannot be null or empty");
Assert.notEmpty(matchingMessageTypes, "matchingMessageTypes cannot be null or empty");
this.matchingMessageTypes = matchingMessageTypes;
}
@@ -110,16 +106,12 @@ public final class SessionRepositoryMessageInterceptor<S extends Session>
if (message == null) {
return message;
}
SimpMessageType messageType = SimpMessageHeaderAccessor
.getMessageType(message.getHeaders());
SimpMessageType messageType = SimpMessageHeaderAccessor.getMessageType(message.getHeaders());
if (!this.matchingMessageTypes.contains(messageType)) {
return message;
}
Map<String, Object> sessionHeaders = SimpMessageHeaderAccessor
.getSessionAttributes(message.getHeaders());
String sessionId = (sessionHeaders != null)
? (String) sessionHeaders.get(SPRING_SESSION_ID_ATTR_NAME)
: null;
Map<String, Object> sessionHeaders = SimpMessageHeaderAccessor.getSessionAttributes(message.getHeaders());
String sessionId = (sessionHeaders != null) ? (String) sessionHeaders.get(SPRING_SESSION_ID_ATTR_NAME) : null;
if (sessionId != null) {
S session = this.sessionRepository.findById(sessionId);
if (session != null) {
@@ -132,8 +124,8 @@ public final class SessionRepositoryMessageInterceptor<S extends Session>
}
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,
WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) {
if (request instanceof ServletServerHttpRequest) {
ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
HttpSession session = servletRequest.getServletRequest().getSession(false);
@@ -145,8 +137,8 @@ public final class SessionRepositoryMessageInterceptor<S extends Session>
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response,
WebSocketHandler wsHandler, Exception exception) {
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Exception exception) {
}
public static String getSessionId(Map<String, Object> attributes) {
@@ -156,4 +148,5 @@ public final class SessionRepositoryMessageInterceptor<S extends Session>
public static void setSessionId(Map<String, Object> attributes, String sessionId) {
attributes.put(SPRING_SESSION_ID_ATTR_NAME, sessionId);
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright 2014-2019 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
*
* https://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.session;
import java.util.Collections;
import java.util.Map;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link DelegatingIndexResolver}.
*
* @author Vedran Pavic
*/
class DelegatingIndexResolverTests {
private DelegatingIndexResolver<MapSession> indexResolver;
@BeforeEach
void setUp() {
this.indexResolver = new DelegatingIndexResolver<>(new TestIndexResolver("one"), new TestIndexResolver("two"));
}
@Test
void resolve() {
MapSession session = new MapSession();
session.setAttribute("one", "first");
session.setAttribute("two", "second");
Map<String, String> indexes = this.indexResolver.resolveIndexesFor(session);
assertThat(indexes).hasSize(2);
assertThat(indexes.get("one")).isEqualTo("first");
assertThat(indexes.get("two")).isEqualTo("second");
}
private static class TestIndexResolver implements IndexResolver<MapSession> {
private final String supportedIndex;
TestIndexResolver(String supportedIndex) {
this.supportedIndex = supportedIndex;
}
public Map<String, String> resolveIndexesFor(MapSession session) {
return Collections.singletonMap(this.supportedIndex, session.getAttribute(this.supportedIndex));
}
}
}

View File

@@ -29,20 +29,20 @@ import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link MapSessionRepository}.
*/
public class MapSessionRepositoryTests {
class MapSessionRepositoryTests {
private MapSessionRepository repository;
private MapSession session;
@BeforeEach
public void setup() {
void setup() {
this.repository = new MapSessionRepository(new ConcurrentHashMap<>());
this.session = new MapSession();
}
@Test
public void getSessionExpired() {
void getSessionExpired() {
this.session.setMaxInactiveInterval(Duration.ofSeconds(1));
this.session.setLastAccessedTime(Instant.now().minus(5, ChronoUnit.MINUTES));
this.repository.save(this.session);
@@ -51,29 +51,25 @@ public class MapSessionRepositoryTests {
}
@Test
public void createSessionDefaultExpiration() {
void createSessionDefaultExpiration() {
Session session = this.repository.createSession();
assertThat(session).isInstanceOf(MapSession.class);
assertThat(session.getMaxInactiveInterval())
.isEqualTo(new MapSession().getMaxInactiveInterval());
assertThat(session.getMaxInactiveInterval()).isEqualTo(new MapSession().getMaxInactiveInterval());
}
@Test
public void createSessionCustomDefaultExpiration() {
final Duration expectedMaxInterval = new MapSession().getMaxInactiveInterval()
.plusSeconds(10);
this.repository.setDefaultMaxInactiveInterval(
(int) expectedMaxInterval.getSeconds());
void createSessionCustomDefaultExpiration() {
final Duration expectedMaxInterval = new MapSession().getMaxInactiveInterval().plusSeconds(10);
this.repository.setDefaultMaxInactiveInterval((int) expectedMaxInterval.getSeconds());
Session session = this.repository.createSession();
assertThat(session.getMaxInactiveInterval())
.isEqualTo(expectedMaxInterval);
assertThat(session.getMaxInactiveInterval()).isEqualTo(expectedMaxInterval);
}
@Test
public void changeSessionIdWhenNotYetSaved() {
void changeSessionIdWhenNotYetSaved() {
MapSession createSession = this.repository.createSession();
String originalId = createSession.getId();
@@ -86,7 +82,7 @@ public class MapSessionRepositoryTests {
}
@Test
public void changeSessionIdWhenSaved() {
void changeSessionIdWhenSaved() {
MapSession createSession = this.repository.createSession();
this.repository.save(createSession);
@@ -101,7 +97,7 @@ public class MapSessionRepositoryTests {
}
@Test // gh-1120
public void getAttributeNamesAndRemove() {
void getAttributeNamesAndRemove() {
MapSession session = this.repository.createSession();
session.setAttribute("attribute1", "value1");
session.setAttribute("attribute2", "value2");

View File

@@ -26,38 +26,37 @@ import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
public class MapSessionTests {
class MapSessionTests {
private MapSession session;
@BeforeEach
public void setup() {
void setup() {
this.session = new MapSession();
this.session.setLastAccessedTime(Instant.ofEpochMilli(1413258262962L));
}
@Test
public void constructorNullSession() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new MapSession((Session) null))
void constructorNullSession() {
assertThatIllegalArgumentException().isThrownBy(() -> new MapSession((Session) null))
.withMessage("session cannot be null");
}
@Test
public void getAttributeWhenNullThenNull() {
void getAttributeWhenNullThenNull() {
String result = this.session.getAttribute("attrName");
assertThat(result).isNull();
}
@Test
public void getAttributeOrDefaultWhenNullThenDefaultValue() {
void getAttributeOrDefaultWhenNullThenDefaultValue() {
String defaultValue = "default";
String result = this.session.getAttributeOrDefault("attrName", defaultValue);
assertThat(result).isEqualTo(defaultValue);
}
@Test
public void getAttributeOrDefaultWhenNotNullThenDefaultValue() {
void getAttributeOrDefaultWhenNotNullThenDefaultValue() {
String defaultValue = "default";
String attrValue = "value";
String attrName = "attrName";
@@ -69,14 +68,13 @@ public class MapSessionTests {
}
@Test
public void getRequiredAttributeWhenNullThenException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.session.getRequiredAttribute("attrName"))
void getRequiredAttributeWhenNullThenException() {
assertThatIllegalArgumentException().isThrownBy(() -> this.session.getRequiredAttribute("attrName"))
.withMessage("Required attribute 'attrName' is missing.");
}
@Test
public void getRequiredAttributeWhenNotNullThenReturns() {
void getRequiredAttributeWhenNotNullThenReturns() {
String attrValue = "value";
String attrName = "attrName";
this.session.setAttribute(attrName, attrValue);
@@ -90,7 +88,7 @@ public class MapSessionTests {
* Ensure conforms to the javadoc of {@link Session}
*/
@Test
public void setAttributeNullObjectRemoves() {
void setAttributeNullObjectRemoves() {
String attr = "attr";
this.session.setAttribute(attr, new Object());
this.session.setAttribute(attr, null);
@@ -98,43 +96,43 @@ public class MapSessionTests {
}
@Test
public void equalsNonSessionFalse() {
void equalsNonSessionFalse() {
assertThat(this.session.equals(new Object())).isFalse();
}
@Test
public void equalsCustomSession() {
void equalsCustomSession() {
CustomSession other = new CustomSession();
this.session.setId(other.getId());
assertThat(this.session.equals(other)).isTrue();
}
@Test
public void hashCodeEqualsIdHashCode() {
void hashCodeEqualsIdHashCode() {
this.session.setId("constantId");
assertThat(this.session.hashCode()).isEqualTo(this.session.getId().hashCode());
}
@Test
public void isExpiredExact() {
void isExpiredExact() {
Instant now = Instant.ofEpochMilli(1413260062962L);
assertThat(this.session.isExpired(now)).isTrue();
}
@Test
public void isExpiredOneMsTooSoon() {
void isExpiredOneMsTooSoon() {
Instant now = Instant.ofEpochMilli(1413260062961L);
assertThat(this.session.isExpired(now)).isFalse();
}
@Test
public void isExpiredOneMsAfter() {
void isExpiredOneMsAfter() {
Instant now = Instant.ofEpochMilli(1413260062963L);
assertThat(this.session.isExpired(now)).isTrue();
}
@Test // gh-1120
public void getAttributeNamesAndRemove() {
void getAttributeNamesAndRemove() {
this.session.setAttribute("attribute1", "value1");
this.session.setAttribute("attribute2", "value2");
@@ -206,6 +204,7 @@ public class MapSessionTests {
public boolean isExpired() {
return false;
}
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright 2014-2019 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
*
* https://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.session;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextImpl;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link PrincipalNameIndexResolver}.
*
* @author Vedran Pavic
*/
class PrincipalNameIndexResolverTests {
private static final String PRINCIPAL_NAME = "principalName";
private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
private PrincipalNameIndexResolver<Session> indexResolver;
@BeforeEach
void setUp() {
this.indexResolver = new PrincipalNameIndexResolver<>();
}
@Test
void resolveFromPrincipalName() {
MapSession session = new MapSession();
session.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, PRINCIPAL_NAME);
assertThat(this.indexResolver.resolveIndexValueFor(session)).isEqualTo(PRINCIPAL_NAME);
}
@Test
void resolveFromSpringSecurityContext() {
Authentication authentication = new UsernamePasswordAuthenticationToken(PRINCIPAL_NAME, "notused",
AuthorityUtils.createAuthorityList("ROLE_USER"));
SecurityContext context = new SecurityContextImpl();
context.setAuthentication(authentication);
MapSession session = new MapSession();
session.setAttribute(SPRING_SECURITY_CONTEXT, context);
assertThat(this.indexResolver.resolveIndexValueFor(session)).isEqualTo(PRINCIPAL_NAME);
}
}

View File

@@ -35,20 +35,20 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
* @author Rob Winch
* @since 2.0
*/
public class ReactiveMapSessionRepositoryTests {
class ReactiveMapSessionRepositoryTests {
private ReactiveMapSessionRepository repository;
private MapSession session;
@BeforeEach
public void setup() {
void setup() {
this.repository = new ReactiveMapSessionRepository(new HashMap<>());
this.session = new MapSession("session-id");
}
@Test
public void constructorMapThenFound() {
void constructorMapThenFound() {
Map<String, Session> sessions = new HashMap<>();
sessions.put(this.session.getId(), this.session);
this.repository = new ReactiveMapSessionRepository(sessions);
@@ -59,21 +59,20 @@ public class ReactiveMapSessionRepositoryTests {
}
@Test
public void constructorMapWhenNullThenThrowsIllegalArgumentException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new ReactiveMapSessionRepository(null))
void constructorMapWhenNullThenThrowsIllegalArgumentException() {
assertThatIllegalArgumentException().isThrownBy(() -> new ReactiveMapSessionRepository(null))
.withMessage("sessions cannot be null");
}
@Test
public void saveWhenNoSubscribersThenNotFound() {
void saveWhenNoSubscribersThenNotFound() {
this.repository.save(this.session);
assertThat(this.repository.findById(this.session.getId()).block()).isNull();
}
@Test
public void saveWhenSubscriberThenFound() {
void saveWhenSubscriberThenFound() {
this.repository.save(this.session).block();
Session findByIdSession = this.repository.findById(this.session.getId()).block();
@@ -82,7 +81,7 @@ public class ReactiveMapSessionRepositoryTests {
}
@Test
public void findByIdWhenExpiredRemovesFromSessionMap() {
void findByIdWhenExpiredRemovesFromSessionMap() {
this.session.setMaxInactiveInterval(Duration.ofMinutes(1));
this.session.setLastAccessedTime(Instant.now().minus(5, ChronoUnit.MINUTES));
@@ -95,20 +94,17 @@ public class ReactiveMapSessionRepositoryTests {
}
@Test
public void createSessionWhenDefaultMaxInactiveIntervalThenDefaultMaxInactiveInterval() {
void createSessionWhenDefaultMaxInactiveIntervalThenDefaultMaxInactiveInterval() {
Session session = this.repository.createSession().block();
assertThat(session).isInstanceOf(MapSession.class);
assertThat(session.getMaxInactiveInterval())
.isEqualTo(new MapSession().getMaxInactiveInterval());
assertThat(session.getMaxInactiveInterval()).isEqualTo(new MapSession().getMaxInactiveInterval());
}
@Test
public void createSessionWhenCustomMaxInactiveIntervalThenCustomMaxInactiveInterval() {
final Duration expectedMaxInterval = new MapSession().getMaxInactiveInterval()
.plusSeconds(10);
this.repository
.setDefaultMaxInactiveInterval((int) expectedMaxInterval.getSeconds());
void createSessionWhenCustomMaxInactiveIntervalThenCustomMaxInactiveInterval() {
final Duration expectedMaxInterval = new MapSession().getMaxInactiveInterval().plusSeconds(10);
this.repository.setDefaultMaxInactiveInterval((int) expectedMaxInterval.getSeconds());
Session session = this.repository.createSession().block();
@@ -116,7 +112,7 @@ public class ReactiveMapSessionRepositoryTests {
}
@Test
public void changeSessionIdWhenNotYetSaved() {
void changeSessionIdWhenNotYetSaved() {
MapSession createSession = this.repository.createSession().block();
String originalId = createSession.getId();
@@ -129,7 +125,7 @@ public class ReactiveMapSessionRepositoryTests {
}
@Test
public void changeSessionIdWhenSaved() {
void changeSessionIdWhenSaved() {
MapSession createSession = this.repository.createSession().block();
this.repository.save(createSession).block();
@@ -144,7 +140,7 @@ public class ReactiveMapSessionRepositoryTests {
}
@Test // gh-1120
public void getAttributeNamesAndRemove() {
void getAttributeNamesAndRemove() {
MapSession session = this.repository.createSession().block();
session.setAttribute("attribute1", "value1");
session.setAttribute("attribute2", "value2");

View File

@@ -61,7 +61,7 @@ import static org.mockito.Mockito.verify;
@ExtendWith(SpringExtension.class)
@ContextConfiguration
@WebAppConfiguration
public class EnableSpringHttpSessionCustomCookieSerializerTests {
class EnableSpringHttpSessionCustomCookieSerializerTests {
@Autowired
private MockHttpServletRequest request;
@@ -81,7 +81,7 @@ public class EnableSpringHttpSessionCustomCookieSerializerTests {
private CookieSerializer cookieSerializer;
@BeforeEach
public void setup() {
void setup() {
this.chain = new MockFilterChain();
reset(this.sessionRepository);
@@ -89,12 +89,11 @@ public class EnableSpringHttpSessionCustomCookieSerializerTests {
}
@Test
public void usesReadSessionIds() throws Exception {
void usesReadSessionIds() throws Exception {
String sessionId = "sessionId";
given(this.cookieSerializer.readCookieValues(any(HttpServletRequest.class)))
.willReturn(Collections.singletonList(sessionId));
given(this.sessionRepository.findById(anyString()))
.willReturn(new MapSession(sessionId));
given(this.sessionRepository.findById(anyString())).willReturn(new MapSession(sessionId));
this.sessionRepositoryFilter.doFilter(this.request, this.response, this.chain);
@@ -102,19 +101,18 @@ public class EnableSpringHttpSessionCustomCookieSerializerTests {
}
@Test
public void usesWrite() throws Exception {
void usesWrite() throws Exception {
given(this.sessionRepository.createSession()).willReturn(new MapSession());
this.sessionRepositoryFilter.doFilter(this.request, this.response,
new MockFilterChain() {
this.sessionRepositoryFilter.doFilter(this.request, this.response, new MockFilterChain() {
@Override
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
((HttpServletRequest) request).getSession();
super.doFilter(request, response);
}
});
@Override
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
((HttpServletRequest) request).getSession();
super.doFilter(request, response);
}
});
verify(this.cookieSerializer).writeCookieValue(any(CookieValue.class));
}

View File

@@ -45,12 +45,12 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
*
* @author Vedran Pavic
*/
public class SpringHttpSessionConfigurationTests {
class SpringHttpSessionConfigurationTests {
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
@AfterEach
public void closeContext() {
void closeContext() {
if (this.context != null) {
this.context.close();
}
@@ -62,28 +62,26 @@ public class SpringHttpSessionConfigurationTests {
}
@Test
public void noSessionRepositoryConfiguration() {
void noSessionRepositoryConfiguration() {
assertThatExceptionOfType(UnsatisfiedDependencyException.class)
.isThrownBy(() -> registerAndRefresh(EmptyConfiguration.class))
.withMessageContaining("org.springframework.session.SessionRepository");
}
@Test
public void defaultConfiguration() {
void defaultConfiguration() {
registerAndRefresh(DefaultConfiguration.class);
assertThat(this.context.getBean(SessionEventHttpSessionListenerAdapter.class))
.isNotNull();
assertThat(this.context.getBean(SessionEventHttpSessionListenerAdapter.class)).isNotNull();
assertThat(this.context.getBean(SessionRepositoryFilter.class)).isNotNull();
assertThat(this.context.getBean(SessionRepository.class)).isNotNull();
}
@Test
public void sessionCookieConfigConfiguration() {
void sessionCookieConfigConfiguration() {
registerAndRefresh(SessionCookieConfigConfiguration.class);
SessionRepositoryFilter sessionRepositoryFilter = this.context
.getBean(SessionRepositoryFilter.class);
SessionRepositoryFilter sessionRepositoryFilter = this.context.getBean(SessionRepositoryFilter.class);
assertThat(sessionRepositoryFilter).isNotNull();
CookieHttpSessionIdResolver httpSessionIdResolver = (CookieHttpSessionIdResolver) ReflectionTestUtils
.getField(sessionRepositoryFilter, "httpSessionIdResolver");
@@ -91,22 +89,17 @@ public class SpringHttpSessionConfigurationTests {
DefaultCookieSerializer cookieSerializer = (DefaultCookieSerializer) ReflectionTestUtils
.getField(httpSessionIdResolver, "cookieSerializer");
assertThat(cookieSerializer).isNotNull();
assertThat(ReflectionTestUtils.getField(cookieSerializer, "cookieName"))
.isEqualTo("test-name");
assertThat(ReflectionTestUtils.getField(cookieSerializer, "cookiePath"))
.isEqualTo("test-path");
assertThat(ReflectionTestUtils.getField(cookieSerializer, "cookieMaxAge"))
.isEqualTo(600);
assertThat(ReflectionTestUtils.getField(cookieSerializer, "domainName"))
.isEqualTo("test-domain");
assertThat(ReflectionTestUtils.getField(cookieSerializer, "cookieName")).isEqualTo("test-name");
assertThat(ReflectionTestUtils.getField(cookieSerializer, "cookiePath")).isEqualTo("test-path");
assertThat(ReflectionTestUtils.getField(cookieSerializer, "cookieMaxAge")).isEqualTo(600);
assertThat(ReflectionTestUtils.getField(cookieSerializer, "domainName")).isEqualTo("test-domain");
}
@Test
public void rememberMeServicesConfiguration() {
void rememberMeServicesConfiguration() {
registerAndRefresh(RememberMeServicesConfiguration.class);
SessionRepositoryFilter sessionRepositoryFilter = this.context
.getBean(SessionRepositoryFilter.class);
SessionRepositoryFilter sessionRepositoryFilter = this.context.getBean(SessionRepositoryFilter.class);
assertThat(sessionRepositoryFilter).isNotNull();
CookieHttpSessionIdResolver httpSessionIdResolver = (CookieHttpSessionIdResolver) ReflectionTestUtils
.getField(sessionRepositoryFilter, "httpSessionIdResolver");
@@ -114,14 +107,14 @@ public class SpringHttpSessionConfigurationTests {
DefaultCookieSerializer cookieSerializer = (DefaultCookieSerializer) ReflectionTestUtils
.getField(httpSessionIdResolver, "cookieSerializer");
assertThat(cookieSerializer).isNotNull();
assertThat(ReflectionTestUtils.getField(cookieSerializer,
"rememberMeRequestAttribute")).isEqualTo(
SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR);
assertThat(ReflectionTestUtils.getField(cookieSerializer, "rememberMeRequestAttribute"))
.isEqualTo(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR);
}
@Configuration
@EnableSpringHttpSession
static class EmptyConfiguration {
}
static class BaseConfiguration {
@@ -136,6 +129,7 @@ public class SpringHttpSessionConfigurationTests {
@Configuration
@EnableSpringHttpSession
static class DefaultConfiguration extends BaseConfiguration {
}
@Configuration

View File

@@ -41,18 +41,19 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
*
* @author Greg Turnquist
*/
public class SpringWebSessionConfigurationTests {
class SpringWebSessionConfigurationTests {
private AnnotationConfigApplicationContext context;
@AfterEach
public void cleanup() {
void cleanup() {
if (this.context != null) {
this.context.close();
}
}
@Test
public void enableSpringWebSessionConfiguresThings() {
void enableSpringWebSessionConfiguresThings() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(GoodConfig.class);
@@ -69,19 +70,18 @@ public class SpringWebSessionConfigurationTests {
}
@Test
public void missingReactiveSessionRepositoryBreaksAppContext() {
void missingReactiveSessionRepositoryBreaksAppContext() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(BadConfig.class);
assertThatExceptionOfType(UnsatisfiedDependencyException.class)
.isThrownBy(this.context::refresh)
.withMessageContaining("Error creating bean with name 'webSessionManager'")
.withMessageContaining("No qualifying bean of type '" + ReactiveSessionRepository.class.getCanonicalName());
assertThatExceptionOfType(UnsatisfiedDependencyException.class).isThrownBy(this.context::refresh)
.withMessageContaining("Error creating bean with name 'webSessionManager'").withMessageContaining(
"No qualifying bean of type '" + ReactiveSessionRepository.class.getCanonicalName());
}
@Test
public void defaultSessionIdResolverShouldBeCookieBased() {
void defaultSessionIdResolverShouldBeCookieBased() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(GoodConfig.class);
@@ -92,7 +92,7 @@ public class SpringWebSessionConfigurationTests {
}
@Test
public void providedSessionIdResolverShouldBePickedUpAutomatically() {
void providedSessionIdResolverShouldBePickedUpAutomatically() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(OverrideSessionIdResolver.class);
@@ -109,12 +109,14 @@ public class SpringWebSessionConfigurationTests {
static class GoodConfig {
/**
* Use Reactor-friendly, {@link java.util.Map}-backed {@link ReactiveSessionRepository} for test purposes.
* Use Reactor-friendly, {@link java.util.Map}-backed
* {@link ReactiveSessionRepository} for test purposes.
*/
@Bean
ReactiveSessionRepository<?> reactiveSessionRepository() {
return new ReactiveMapSessionRepository(new HashMap<>());
}
}
/**
@@ -137,6 +139,7 @@ public class SpringWebSessionConfigurationTests {
WebSessionIdResolver alternateWebSessionIdResolver() {
return new HeaderWebSessionIdResolver();
}
}
}

View File

@@ -46,7 +46,7 @@ import static org.mockito.BDDMockito.when;
/**
* Tests for {@link SpringSessionBackedSessionRegistry}.
*/
public class SpringSessionBackedSessionRegistryTest {
class SpringSessionBackedSessionRegistryTest {
private static final String SESSION_ID = "sessionId";
@@ -54,8 +54,7 @@ public class SpringSessionBackedSessionRegistryTest {
private static final String USER_NAME = "userName";
private static final User PRINCIPAL = new User(USER_NAME, "password",
Collections.emptyList());
private static final User PRINCIPAL = new User(USER_NAME, "password", Collections.emptyList());
private static final Instant NOW = Instant.now();
@@ -71,74 +70,63 @@ public class SpringSessionBackedSessionRegistryTest {
}
@Test
public void sessionInformationForExistingSession() {
void sessionInformationForExistingSession() {
Session session = createSession(SESSION_ID, USER_NAME, NOW);
when(this.sessionRepository.findById(SESSION_ID)).thenReturn(session);
SessionInformation sessionInfo = this.sessionRegistry
.getSessionInformation(SESSION_ID);
SessionInformation sessionInfo = this.sessionRegistry.getSessionInformation(SESSION_ID);
assertThat(sessionInfo.getSessionId()).isEqualTo(SESSION_ID);
assertThat(
sessionInfo.getLastRequest().toInstant().truncatedTo(ChronoUnit.MILLIS))
.isEqualTo(NOW.truncatedTo(ChronoUnit.MILLIS));
assertThat(sessionInfo.getLastRequest().toInstant().truncatedTo(ChronoUnit.MILLIS))
.isEqualTo(NOW.truncatedTo(ChronoUnit.MILLIS));
assertThat(sessionInfo.getPrincipal()).isEqualTo(USER_NAME);
assertThat(sessionInfo.isExpired()).isFalse();
}
@Test
public void sessionInformationForExpiredSession() {
void sessionInformationForExpiredSession() {
Session session = createSession(SESSION_ID, USER_NAME, NOW);
session.setAttribute(SpringSessionBackedSessionInformation.EXPIRED_ATTR,
Boolean.TRUE);
session.setAttribute(SpringSessionBackedSessionInformation.EXPIRED_ATTR, Boolean.TRUE);
when(this.sessionRepository.findById(SESSION_ID)).thenReturn(session);
SessionInformation sessionInfo = this.sessionRegistry
.getSessionInformation(SESSION_ID);
SessionInformation sessionInfo = this.sessionRegistry.getSessionInformation(SESSION_ID);
assertThat(sessionInfo.getSessionId()).isEqualTo(SESSION_ID);
assertThat(
sessionInfo.getLastRequest().toInstant().truncatedTo(ChronoUnit.MILLIS))
assertThat(sessionInfo.getLastRequest().toInstant().truncatedTo(ChronoUnit.MILLIS))
.isEqualTo(NOW.truncatedTo(ChronoUnit.MILLIS));
assertThat(sessionInfo.getPrincipal()).isEqualTo(USER_NAME);
assertThat(sessionInfo.isExpired()).isTrue();
}
@Test
public void noSessionInformationForMissingSession() {
assertThat(this.sessionRegistry.getSessionInformation("nonExistingSessionId"))
.isNull();
void noSessionInformationForMissingSession() {
assertThat(this.sessionRegistry.getSessionInformation("nonExistingSessionId")).isNull();
}
@Test
public void getAllSessions() {
void getAllSessions() {
setUpSessions();
List<SessionInformation> allSessionInfos = this.sessionRegistry
.getAllSessions(PRINCIPAL, true);
List<SessionInformation> allSessionInfos = this.sessionRegistry.getAllSessions(PRINCIPAL, true);
assertThat(allSessionInfos).extracting("sessionId").containsExactly(SESSION_ID,
SESSION_ID2);
assertThat(allSessionInfos).extracting("sessionId").containsExactly(SESSION_ID, SESSION_ID2);
}
@Test
public void getNonExpiredSessions() {
void getNonExpiredSessions() {
setUpSessions();
List<SessionInformation> nonExpiredSessionInfos = this.sessionRegistry
.getAllSessions(PRINCIPAL, false);
List<SessionInformation> nonExpiredSessionInfos = this.sessionRegistry.getAllSessions(PRINCIPAL, false);
assertThat(nonExpiredSessionInfos).extracting("sessionId")
.containsExactly(SESSION_ID2);
assertThat(nonExpiredSessionInfos).extracting("sessionId").containsExactly(SESSION_ID2);
}
@Test
public void expireNow() {
void expireNow() {
Session session = createSession(SESSION_ID, USER_NAME, NOW);
when(this.sessionRepository.findById(SESSION_ID)).thenReturn(session);
SessionInformation sessionInfo = this.sessionRegistry
.getSessionInformation(SESSION_ID);
SessionInformation sessionInfo = this.sessionRegistry.getSessionInformation(SESSION_ID);
assertThat(sessionInfo.isExpired()).isFalse();
sessionInfo.expireNow();
@@ -146,13 +134,11 @@ public class SpringSessionBackedSessionRegistryTest {
assertThat(sessionInfo.isExpired()).isTrue();
ArgumentCaptor<Session> captor = ArgumentCaptor.forClass(Session.class);
verify(this.sessionRepository).save(captor.capture());
assertThat(captor.getValue().<Boolean>getAttribute(
SpringSessionBackedSessionInformation.EXPIRED_ATTR))
.isEqualTo(Boolean.TRUE);
assertThat(captor.getValue().<Boolean>getAttribute(SpringSessionBackedSessionInformation.EXPIRED_ATTR))
.isEqualTo(Boolean.TRUE);
}
private Session createSession(String sessionId, String userName,
Instant lastAccessed) {
private Session createSession(String sessionId, String userName, Instant lastAccessed) {
MapSession session = new MapSession(sessionId);
session.setLastAccessedTime(lastAccessed);
Authentication authentication = mock(Authentication.class);
@@ -165,14 +151,12 @@ public class SpringSessionBackedSessionRegistryTest {
private void setUpSessions() {
Session session1 = createSession(SESSION_ID, USER_NAME, NOW);
session1.setAttribute(SpringSessionBackedSessionInformation.EXPIRED_ATTR,
Boolean.TRUE);
session1.setAttribute(SpringSessionBackedSessionInformation.EXPIRED_ATTR, Boolean.TRUE);
Session session2 = createSession(SESSION_ID2, USER_NAME, NOW);
Map<String, Session> sessions = new LinkedHashMap<>();
sessions.put(session1.getId(), session1);
sessions.put(session2.getId(), session2);
when(this.sessionRepository.findByPrincipalName(USER_NAME))
.thenReturn(sessions);
when(this.sessionRepository.findByPrincipalName(USER_NAME)).thenReturn(sessions);
}
}

View File

@@ -40,60 +40,50 @@ import static org.mockito.Mockito.verifyZeroInteractions;
*
* @author Vedran Pavic
*/
public class SpringSessionRememberMeServicesTests {
class SpringSessionRememberMeServicesTests {
private SpringSessionRememberMeServices rememberMeServices;
@Test
public void create() {
void create() {
this.rememberMeServices = new SpringSessionRememberMeServices();
assertThat(ReflectionTestUtils.getField(this.rememberMeServices,
"rememberMeParameterName")).isEqualTo("remember-me");
assertThat(
ReflectionTestUtils.getField(this.rememberMeServices, "alwaysRemember"))
.isEqualTo(false);
assertThat(
ReflectionTestUtils.getField(this.rememberMeServices, "validitySeconds"))
.isEqualTo(2592000);
assertThat(ReflectionTestUtils.getField(this.rememberMeServices, "rememberMeParameterName"))
.isEqualTo("remember-me");
assertThat(ReflectionTestUtils.getField(this.rememberMeServices, "alwaysRemember")).isEqualTo(false);
assertThat(ReflectionTestUtils.getField(this.rememberMeServices, "validitySeconds")).isEqualTo(2592000);
}
@Test
public void createWithCustomParameter() {
void createWithCustomParameter() {
this.rememberMeServices = new SpringSessionRememberMeServices();
this.rememberMeServices.setRememberMeParameterName("test-param");
assertThat(ReflectionTestUtils.getField(this.rememberMeServices,
"rememberMeParameterName")).isEqualTo("test-param");
assertThat(ReflectionTestUtils.getField(this.rememberMeServices, "rememberMeParameterName"))
.isEqualTo("test-param");
}
@Test
public void createWithNullParameter() {
void createWithNullParameter() {
this.rememberMeServices = new SpringSessionRememberMeServices();
assertThatIllegalArgumentException()
.isThrownBy(
() -> this.rememberMeServices.setRememberMeParameterName(null))
assertThatIllegalArgumentException().isThrownBy(() -> this.rememberMeServices.setRememberMeParameterName(null))
.withMessage("rememberMeParameterName cannot be empty or null");
}
@Test
public void createWithAlwaysRemember() {
void createWithAlwaysRemember() {
this.rememberMeServices = new SpringSessionRememberMeServices();
this.rememberMeServices.setAlwaysRemember(true);
assertThat(
ReflectionTestUtils.getField(this.rememberMeServices, "alwaysRemember"))
.isEqualTo(true);
assertThat(ReflectionTestUtils.getField(this.rememberMeServices, "alwaysRemember")).isEqualTo(true);
}
@Test
public void createWithCustomValidity() {
void createWithCustomValidity() {
this.rememberMeServices = new SpringSessionRememberMeServices();
this.rememberMeServices.setValiditySeconds(100000);
assertThat(
ReflectionTestUtils.getField(this.rememberMeServices, "validitySeconds"))
.isEqualTo(100000);
assertThat(ReflectionTestUtils.getField(this.rememberMeServices, "validitySeconds")).isEqualTo(100000);
}
@Test
public void autoLogin() {
void autoLogin() {
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
this.rememberMeServices = new SpringSessionRememberMeServices();
@@ -103,7 +93,7 @@ public class SpringSessionRememberMeServicesTests {
// gh-752
@Test
public void loginFailRemoveSecurityContext() {
void loginFailRemoveSecurityContext() {
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
HttpSession session = mock(HttpSession.class);
@@ -111,13 +101,12 @@ public class SpringSessionRememberMeServicesTests {
this.rememberMeServices = new SpringSessionRememberMeServices();
this.rememberMeServices.loginFail(request, response);
verify(request, times(1)).getSession(eq(false));
verify(session, times(1)).removeAttribute(
HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
verify(session, times(1)).removeAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
verifyZeroInteractions(request, response, session);
}
@Test
public void loginSuccess() {
void loginSuccess() {
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
Authentication authentication = mock(Authentication.class);
@@ -128,14 +117,13 @@ public class SpringSessionRememberMeServicesTests {
this.rememberMeServices.loginSuccess(request, response, authentication);
verify(request, times(1)).getParameter(eq("remember-me"));
verify(request, times(1)).getSession();
verify(request, times(1)).setAttribute(
eq(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR), eq(true));
verify(request, times(1)).setAttribute(eq(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR), eq(true));
verify(session, times(1)).setMaxInactiveInterval(eq(2592000));
verifyZeroInteractions(request, response, session, authentication);
}
@Test
public void loginSuccessWithCustomParameter() {
void loginSuccessWithCustomParameter() {
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
Authentication authentication = mock(Authentication.class);
@@ -147,14 +135,13 @@ public class SpringSessionRememberMeServicesTests {
this.rememberMeServices.loginSuccess(request, response, authentication);
verify(request, times(1)).getParameter(eq("test-param"));
verify(request, times(1)).getSession();
verify(request, times(1)).setAttribute(
eq(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR), eq(true));
verify(request, times(1)).setAttribute(eq(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR), eq(true));
verify(session, times(1)).setMaxInactiveInterval(eq(2592000));
verifyZeroInteractions(request, response, session, authentication);
}
@Test
public void loginSuccessWithAlwaysRemember() {
void loginSuccessWithAlwaysRemember() {
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
Authentication authentication = mock(Authentication.class);
@@ -164,14 +151,13 @@ public class SpringSessionRememberMeServicesTests {
this.rememberMeServices.setAlwaysRemember(true);
this.rememberMeServices.loginSuccess(request, response, authentication);
verify(request, times(1)).getSession();
verify(request, times(1)).setAttribute(
eq(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR), eq(true));
verify(request, times(1)).setAttribute(eq(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR), eq(true));
verify(session, times(1)).setMaxInactiveInterval(eq(2592000));
verifyZeroInteractions(request, response, session, authentication);
}
@Test
public void loginSuccessWithCustomValidity() {
void loginSuccessWithCustomValidity() {
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
Authentication authentication = mock(Authentication.class);
@@ -183,8 +169,7 @@ public class SpringSessionRememberMeServicesTests {
this.rememberMeServices.loginSuccess(request, response, authentication);
verify(request, times(1)).getParameter(eq("remember-me"));
verify(request, times(1)).getSession();
verify(request, times(1)).setAttribute(
eq(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR), eq(true));
verify(request, times(1)).setAttribute(eq(SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR), eq(true));
verify(session, times(1)).setMaxInactiveInterval(eq(100000));
verifyZeroInteractions(request, response, session, authentication);
}

View File

@@ -34,17 +34,20 @@ import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link CookieHttpSessionIdResolver}.
*/
public class CookieHttpSessionIdResolverTests {
class CookieHttpSessionIdResolverTests {
private MockHttpServletRequest request;
private MockHttpServletResponse response;
private CookieHttpSessionIdResolver strategy;
private String cookieName;
private Session session;
@BeforeEach
public void setup() throws Exception {
void setup() {
this.cookieName = "SESSION";
this.session = new MapSession();
this.request = new MockHttpServletRequest();
@@ -53,19 +56,19 @@ public class CookieHttpSessionIdResolverTests {
}
@Test
public void getRequestedSessionIdNull() throws Exception {
void getRequestedSessionIdNull() {
assertThat(this.strategy.resolveSessionIds(this.request)).isEmpty();
}
@Test
public void getRequestedSessionIdNotNull() throws Exception {
void getRequestedSessionIdNotNull() {
setSessionCookie(this.session.getId());
assertThat(this.strategy.resolveSessionIds(this.request))
.isEqualTo(Collections.singletonList(this.session.getId()));
}
@Test
public void getRequestedSessionIdNotNullCustomCookieName() throws Exception {
void getRequestedSessionIdNotNullCustomCookieName() {
setCookieName("CUSTOM");
setSessionCookie(this.session.getId());
assertThat(this.strategy.resolveSessionIds(this.request))
@@ -73,13 +76,13 @@ public class CookieHttpSessionIdResolverTests {
}
@Test
public void onNewSession() throws Exception {
void onNewSession() {
this.strategy.setSessionId(this.request, this.response, this.session.getId());
assertThat(getSessionId()).isEqualTo(this.session.getId());
}
@Test
public void onNewSessionTwiceSameId() throws Exception {
void onNewSessionTwiceSameId() {
this.strategy.setSessionId(this.request, this.response, this.session.getId());
this.strategy.setSessionId(this.request, this.response, this.session.getId());
@@ -87,7 +90,7 @@ public class CookieHttpSessionIdResolverTests {
}
@Test
public void onNewSessionTwiceNewId() throws Exception {
void onNewSessionTwiceNewId() {
Session newSession = new MapSession();
this.strategy.setSessionId(this.request, this.response, this.session.getId());
@@ -101,49 +104,47 @@ public class CookieHttpSessionIdResolverTests {
}
@Test
public void onNewSessionCookiePath() throws Exception {
void onNewSessionCookiePath() {
this.request.setContextPath("/somethingunique");
this.strategy.setSessionId(this.request, this.response, this.session.getId());
Cookie sessionCookie = this.response.getCookie(this.cookieName);
assertThat(sessionCookie.getPath())
.isEqualTo(this.request.getContextPath() + "/");
assertThat(sessionCookie.getPath()).isEqualTo(this.request.getContextPath() + "/");
}
@Test
public void onNewSessionCustomCookieName() throws Exception {
void onNewSessionCustomCookieName() {
setCookieName("CUSTOM");
this.strategy.setSessionId(this.request, this.response, this.session.getId());
assertThat(getSessionId()).isEqualTo(this.session.getId());
}
@Test
public void onDeleteSession() throws Exception {
void onDeleteSession() {
this.strategy.expireSession(this.request, this.response);
assertThat(getSessionId()).isEmpty();
}
@Test
public void onDeleteSessionCookiePath() throws Exception {
void onDeleteSessionCookiePath() {
this.request.setContextPath("/somethingunique");
this.strategy.expireSession(this.request, this.response);
Cookie sessionCookie = this.response.getCookie(this.cookieName);
assertThat(sessionCookie.getPath())
.isEqualTo(this.request.getContextPath() + "/");
assertThat(sessionCookie.getPath()).isEqualTo(this.request.getContextPath() + "/");
}
@Test
public void onDeleteSessionCustomCookieName() throws Exception {
void onDeleteSessionCustomCookieName() {
setCookieName("CUSTOM");
this.strategy.expireSession(this.request, this.response);
assertThat(getSessionId()).isEmpty();
}
@Test
public void createSessionCookieValue() {
assertThat(createSessionCookieValue(17)).isEqualToIgnoringCase(
"0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 a 10 b 11 c 12 d 13 e 14 f 15 10 16");
void createSessionCookieValue() {
assertThat(createSessionCookieValue(17))
.isEqualToIgnoringCase("0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 a 10 b 11 c 12 d 13 e 14 f 15 10 16");
}
private String createSessionCookieValue(long size) {

View File

@@ -42,7 +42,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
* @author Vedran Pavic
* @author Eddú Meléndez
*/
public class DefaultCookieSerializerTests {
class DefaultCookieSerializerTests {
private String cookieName;
@@ -55,7 +55,7 @@ public class DefaultCookieSerializerTests {
private String sessionId;
@BeforeEach
public void setup() {
void setup() {
this.cookieName = "SESSION";
this.request = new MockHttpServletRequest();
this.response = new MockHttpServletResponse();
@@ -66,23 +66,21 @@ public class DefaultCookieSerializerTests {
// --- readCookieValues ---
@Test
public void readCookieValuesNull() {
void readCookieValuesNull() {
assertThat(this.serializer.readCookieValues(this.request)).isEmpty();
}
@ParameterizedTest
@ValueSource(strings = { "true", "false" })
public void readCookieValuesSingle(boolean useBase64Encoding) {
void readCookieValuesSingle(boolean useBase64Encoding) {
this.serializer.setUseBase64Encoding(useBase64Encoding);
this.request.setCookies(
createCookie(this.cookieName, this.sessionId, useBase64Encoding));
this.request.setCookies(createCookie(this.cookieName, this.sessionId, useBase64Encoding));
assertThat(this.serializer.readCookieValues(this.request))
.containsOnly(this.sessionId);
assertThat(this.serializer.readCookieValues(this.request)).containsOnly(this.sessionId);
}
@Test
public void readCookieSerializerUseBase64EncodingTrueValuesNotBase64() {
void readCookieSerializerUseBase64EncodingTrueValuesNotBase64() {
this.sessionId = "&^%$*";
this.serializer.setUseBase64Encoding(true);
this.request.setCookies(new Cookie(this.cookieName, this.sessionId));
@@ -92,48 +90,41 @@ public class DefaultCookieSerializerTests {
@ParameterizedTest
@ValueSource(strings = { "true", "false" })
public void readCookieValuesSingleAndInvalidName(boolean useBase64Encoding) {
void readCookieValuesSingleAndInvalidName(boolean useBase64Encoding) {
this.serializer.setUseBase64Encoding(useBase64Encoding);
this.request.setCookies(
createCookie(this.cookieName, this.sessionId, useBase64Encoding),
createCookie(this.cookieName + "INVALID", this.sessionId + "INVALID",
useBase64Encoding));
this.request.setCookies(createCookie(this.cookieName, this.sessionId, useBase64Encoding),
createCookie(this.cookieName + "INVALID", this.sessionId + "INVALID", useBase64Encoding));
assertThat(this.serializer.readCookieValues(this.request))
.containsOnly(this.sessionId);
assertThat(this.serializer.readCookieValues(this.request)).containsOnly(this.sessionId);
}
@ParameterizedTest
@ValueSource(strings = { "true", "false" })
public void readCookieValuesMulti(boolean useBase64Encoding) {
void readCookieValuesMulti(boolean useBase64Encoding) {
this.serializer.setUseBase64Encoding(useBase64Encoding);
String secondSession = "secondSessionId";
this.request.setCookies(
createCookie(this.cookieName, this.sessionId, useBase64Encoding),
this.request.setCookies(createCookie(this.cookieName, this.sessionId, useBase64Encoding),
createCookie(this.cookieName, secondSession, useBase64Encoding));
assertThat(this.serializer.readCookieValues(this.request))
.containsExactly(this.sessionId, secondSession);
assertThat(this.serializer.readCookieValues(this.request)).containsExactly(this.sessionId, secondSession);
}
@ParameterizedTest
@ValueSource(strings = { "true", "false" })
public void readCookieValuesMultiCustomSessionCookieName(boolean useBase64Encoding) {
void readCookieValuesMultiCustomSessionCookieName(boolean useBase64Encoding) {
this.serializer.setUseBase64Encoding(useBase64Encoding);
setCookieName("JSESSIONID");
String secondSession = "secondSessionId";
this.request.setCookies(
createCookie(this.cookieName, this.sessionId, useBase64Encoding),
this.request.setCookies(createCookie(this.cookieName, this.sessionId, useBase64Encoding),
createCookie(this.cookieName, secondSession, useBase64Encoding));
assertThat(this.serializer.readCookieValues(this.request))
.containsExactly(this.sessionId, secondSession);
assertThat(this.serializer.readCookieValues(this.request)).containsExactly(this.sessionId, secondSession);
}
// gh-392
@ParameterizedTest
@ValueSource(strings = { "true", "false" })
public void readCookieValuesNullCookieValue(boolean useBase64Encoding) {
void readCookieValuesNullCookieValue(boolean useBase64Encoding) {
this.serializer.setUseBase64Encoding(useBase64Encoding);
this.request.setCookies(createCookie(this.cookieName, null, useBase64Encoding));
@@ -142,7 +133,7 @@ public class DefaultCookieSerializerTests {
@ParameterizedTest
@ValueSource(strings = { "true", "false" })
public void readCookieValuesNullCookieValueAndJvmRoute(boolean useBase64Encoding) {
void readCookieValuesNullCookieValueAndJvmRoute(boolean useBase64Encoding) {
this.serializer.setJvmRoute("123");
this.request.setCookies(createCookie(this.cookieName, null, useBase64Encoding));
@@ -151,21 +142,20 @@ public class DefaultCookieSerializerTests {
@ParameterizedTest
@ValueSource(strings = { "true", "false" })
public void readCookieValuesNullCookieValueAndNotNullCookie(boolean useBase64Encoding) {
void readCookieValuesNullCookieValueAndNotNullCookie(boolean useBase64Encoding) {
this.serializer.setUseBase64Encoding(useBase64Encoding);
this.serializer.setJvmRoute("123");
this.request.setCookies(createCookie(this.cookieName, null, useBase64Encoding),
createCookie(this.cookieName, this.sessionId, useBase64Encoding));
assertThat(this.serializer.readCookieValues(this.request))
.containsOnly(this.sessionId);
assertThat(this.serializer.readCookieValues(this.request)).containsOnly(this.sessionId);
}
// --- writeCookie ---
@ParameterizedTest
@ValueSource(strings = { "true", "false" })
public void writeCookie(boolean useBase64Encoding) {
void writeCookie(boolean useBase64Encoding) {
this.serializer.setUseBase64Encoding(useBase64Encoding);
this.serializer.writeCookieValue(cookieValue(this.sessionId));
@@ -175,14 +165,14 @@ public class DefaultCookieSerializerTests {
// --- httpOnly ---
@Test
public void writeCookieHttpOnlyDefault() {
void writeCookieHttpOnlyDefault() {
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().isHttpOnly()).isTrue();
}
@Test
public void writeCookieHttpOnlySetTrue() {
void writeCookieHttpOnlySetTrue() {
this.serializer.setUseHttpOnlyCookie(true);
this.serializer.writeCookieValue(cookieValue(this.sessionId));
@@ -191,7 +181,7 @@ public class DefaultCookieSerializerTests {
}
@Test
public void writeCookieHttpOnlySetFalse() {
void writeCookieHttpOnlySetFalse() {
this.serializer.setUseHttpOnlyCookie(false);
this.serializer.writeCookieValue(cookieValue(this.sessionId));
@@ -202,14 +192,14 @@ public class DefaultCookieSerializerTests {
// --- domainName ---
@Test
public void writeCookieDomainNameDefault() {
void writeCookieDomainNameDefault() {
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().getDomain()).isNull();
}
@Test
public void writeCookieDomainNameCustom() {
void writeCookieDomainNameCustom() {
String domainName = "example.com";
this.serializer.setDomainName(domainName);
@@ -219,17 +209,16 @@ public class DefaultCookieSerializerTests {
}
@Test
public void setDomainNameAndDomainNamePatternThrows() {
void setDomainNameAndDomainNamePatternThrows() {
this.serializer.setDomainName("example.com");
assertThatIllegalStateException()
.isThrownBy(() -> this.serializer.setDomainNamePattern(".*"))
assertThatIllegalStateException().isThrownBy(() -> this.serializer.setDomainNamePattern(".*"))
.withMessage("Cannot set both domainName and domainNamePattern");
}
// --- domainNamePattern ---
@Test
public void writeCookieDomainNamePattern() {
void writeCookieDomainNamePattern() {
String domainNamePattern = "^.+?\\.(\\w+\\.[a-z]+)$";
this.serializer.setDomainNamePattern(domainNamePattern);
@@ -253,24 +242,23 @@ public class DefaultCookieSerializerTests {
}
@Test
public void setDomainNamePatternAndDomainNameThrows() {
void setDomainNamePatternAndDomainNameThrows() {
this.serializer.setDomainNamePattern(".*");
assertThatIllegalStateException()
.isThrownBy(() -> this.serializer.setDomainName("example.com"))
assertThatIllegalStateException().isThrownBy(() -> this.serializer.setDomainName("example.com"))
.withMessage("Cannot set both domainName and domainNamePattern");
}
// --- cookieName ---
@Test
public void writeCookieCookieNameDefault() {
void writeCookieCookieNameDefault() {
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().getName()).isEqualTo("SESSION");
}
@Test
public void writeCookieCookieNameCustom() {
void writeCookieCookieNameCustom() {
String cookieName = "JSESSIONID";
setCookieName(cookieName);
@@ -280,16 +268,15 @@ public class DefaultCookieSerializerTests {
}
@Test
public void setCookieNameNullThrows() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.serializer.setCookieName(null))
void setCookieNameNullThrows() {
assertThatIllegalArgumentException().isThrownBy(() -> this.serializer.setCookieName(null))
.withMessage("cookieName cannot be null");
}
// --- cookiePath ---
@Test
public void writeCookieCookiePathDefaultEmptyContextPathUsed() {
void writeCookieCookiePathDefaultEmptyContextPathUsed() {
this.request.setContextPath("");
this.serializer.writeCookieValue(cookieValue(this.sessionId));
@@ -298,7 +285,7 @@ public class DefaultCookieSerializerTests {
}
@Test
public void writeCookieCookiePathDefaultContextPathUsed() {
void writeCookieCookiePathDefaultContextPathUsed() {
this.request.setContextPath("/context");
this.serializer.writeCookieValue(cookieValue(this.sessionId));
@@ -307,7 +294,7 @@ public class DefaultCookieSerializerTests {
}
@Test
public void writeCookieCookiePathExplicitNullCookiePathContextPathUsed() {
void writeCookieCookiePathExplicitNullCookiePathContextPathUsed() {
this.request.setContextPath("/context");
this.serializer.setCookiePath(null);
@@ -317,7 +304,7 @@ public class DefaultCookieSerializerTests {
}
@Test
public void writeCookieCookiePathExplicitCookiePath() {
void writeCookieCookiePathExplicitCookiePath() {
this.request.setContextPath("/context");
this.serializer.setCookiePath("/");
@@ -329,14 +316,14 @@ public class DefaultCookieSerializerTests {
// --- cookieMaxAge ---
@Test
public void writeCookieCookieMaxAgeDefault() {
void writeCookieCookieMaxAgeDefault() {
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().getMaxAge()).isEqualTo(-1);
}
@Test
public void writeCookieCookieMaxAgeExplicit() {
void writeCookieCookieMaxAgeExplicit() {
this.serializer.setCookieMaxAge(100);
this.serializer.writeCookieValue(cookieValue(this.sessionId));
@@ -345,7 +332,7 @@ public class DefaultCookieSerializerTests {
}
@Test
public void writeCookieCookieMaxAgeExplicitEmptyCookie() {
void writeCookieCookieMaxAgeExplicitEmptyCookie() {
this.serializer.setCookieMaxAge(100);
this.serializer.writeCookieValue(cookieValue(""));
@@ -354,7 +341,7 @@ public class DefaultCookieSerializerTests {
}
@Test
public void writeCookieCookieMaxAgeExplicitCookieValue() {
void writeCookieCookieMaxAgeExplicitCookieValue() {
CookieValue cookieValue = cookieValue(this.sessionId);
cookieValue.setCookieMaxAge(100);
@@ -366,14 +353,14 @@ public class DefaultCookieSerializerTests {
// --- secure ---
@Test
public void writeCookieDefaultInsecureRequest() {
void writeCookieDefaultInsecureRequest() {
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().getSecure()).isFalse();
}
@Test
public void writeCookieSecureSecureRequest() {
void writeCookieSecureSecureRequest() {
this.request.setSecure(true);
this.serializer.setUseSecureCookie(true);
@@ -383,7 +370,7 @@ public class DefaultCookieSerializerTests {
}
@Test
public void writeCookieSecureInsecureRequest() {
void writeCookieSecureInsecureRequest() {
this.serializer.setUseSecureCookie(true);
this.serializer.writeCookieValue(cookieValue(this.sessionId));
@@ -392,7 +379,7 @@ public class DefaultCookieSerializerTests {
}
@Test
public void writeCookieInsecureSecureRequest() {
void writeCookieInsecureSecureRequest() {
this.request.setSecure(true);
this.serializer.setUseSecureCookie(false);
@@ -402,7 +389,7 @@ public class DefaultCookieSerializerTests {
}
@Test
public void writeCookieInecureInsecureRequest() {
void writeCookieInecureInsecureRequest() {
this.serializer.setUseSecureCookie(false);
this.serializer.writeCookieValue(cookieValue(this.sessionId));
@@ -414,51 +401,45 @@ public class DefaultCookieSerializerTests {
@ParameterizedTest
@ValueSource(strings = { "true", "false" })
public void writeCookieJvmRoute(boolean useBase64Encoding) {
void writeCookieJvmRoute(boolean useBase64Encoding) {
this.serializer.setUseBase64Encoding(useBase64Encoding);
String jvmRoute = "route";
this.serializer.setJvmRoute(jvmRoute);
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookieValue(useBase64Encoding))
.isEqualTo(this.sessionId + "." + jvmRoute);
assertThat(getCookieValue(useBase64Encoding)).isEqualTo(this.sessionId + "." + jvmRoute);
}
@ParameterizedTest
@ValueSource(strings = { "true", "false" })
public void readCookieJvmRoute(boolean useBase64Encoding) {
void readCookieJvmRoute(boolean useBase64Encoding) {
this.serializer.setUseBase64Encoding(useBase64Encoding);
String jvmRoute = "route";
this.serializer.setJvmRoute(jvmRoute);
this.request.setCookies(createCookie(this.cookieName,
this.sessionId + "." + jvmRoute, useBase64Encoding));
this.request.setCookies(createCookie(this.cookieName, this.sessionId + "." + jvmRoute, useBase64Encoding));
assertThat(this.serializer.readCookieValues(this.request))
.containsOnly(this.sessionId);
assertThat(this.serializer.readCookieValues(this.request)).containsOnly(this.sessionId);
}
@ParameterizedTest
@ValueSource(strings = { "true", "false" })
public void readCookieJvmRouteRouteMissing(boolean useBase64Encoding) {
void readCookieJvmRouteRouteMissing(boolean useBase64Encoding) {
this.serializer.setUseBase64Encoding(useBase64Encoding);
String jvmRoute = "route";
this.serializer.setJvmRoute(jvmRoute);
this.request.setCookies(
createCookie(this.cookieName, this.sessionId, useBase64Encoding));
this.request.setCookies(createCookie(this.cookieName, this.sessionId, useBase64Encoding));
assertThat(this.serializer.readCookieValues(this.request))
.containsOnly(this.sessionId);
assertThat(this.serializer.readCookieValues(this.request)).containsOnly(this.sessionId);
}
@ParameterizedTest
@ValueSource(strings = { "true", "false" })
public void readCookieJvmRouteOnlyRoute(boolean useBase64Encoding) {
void readCookieJvmRouteOnlyRoute(boolean useBase64Encoding) {
this.serializer.setUseBase64Encoding(useBase64Encoding);
String jvmRoute = "route";
this.serializer.setJvmRoute(jvmRoute);
this.request.setCookies(
createCookie(this.cookieName, "." + jvmRoute, useBase64Encoding));
this.request.setCookies(createCookie(this.cookieName, "." + jvmRoute, useBase64Encoding));
assertThat(this.serializer.readCookieValues(this.request)).containsOnly("");
}
@@ -466,7 +447,7 @@ public class DefaultCookieSerializerTests {
// --- rememberMe ---
@Test
public void writeCookieRememberMeCookieMaxAgeDefault() {
void writeCookieRememberMeCookieMaxAgeDefault() {
this.request.setAttribute("rememberMe", true);
this.serializer.setRememberMeRequestAttribute("rememberMe");
this.serializer.writeCookieValue(cookieValue(this.sessionId));
@@ -475,7 +456,7 @@ public class DefaultCookieSerializerTests {
}
@Test
public void writeCookieRememberMeCookieMaxAgeOverride() {
void writeCookieRememberMeCookieMaxAgeOverride() {
this.request.setAttribute("rememberMe", true);
this.serializer.setRememberMeRequestAttribute("rememberMe");
CookieValue cookieValue = cookieValue(this.sessionId);
@@ -488,14 +469,14 @@ public class DefaultCookieSerializerTests {
// --- sameSite ---
@Test
public void writeCookieDefaultSameSiteLax() {
void writeCookieDefaultSameSiteLax() {
this.serializer.writeCookieValue(cookieValue(this.sessionId));
assertThat(getCookie().getSameSite()).isEqualTo("Lax");
}
@Test
public void writeCookieSetSameSiteLax() {
void writeCookieSetSameSiteLax() {
this.serializer.setSameSite("Lax");
this.serializer.writeCookieValue(cookieValue(this.sessionId));
@@ -503,7 +484,7 @@ public class DefaultCookieSerializerTests {
}
@Test
public void writeCookieSetSameSiteStrict() {
void writeCookieSetSameSiteStrict() {
this.serializer.setSameSite("Strict");
this.serializer.writeCookieValue(cookieValue(this.sessionId));
@@ -511,7 +492,7 @@ public class DefaultCookieSerializerTests {
}
@Test
public void writeCookieSetSameSiteNull() {
void writeCookieSetSameSiteNull() {
this.serializer.setSameSite(null);
this.serializer.writeCookieValue(cookieValue(this.sessionId));

View File

@@ -32,7 +32,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
/**
* Tests for {@link HeaderHttpSessionIdResolver}.
*/
public class HeaderHttpSessionIdResolverTests {
class HeaderHttpSessionIdResolverTests {
private static final String HEADER_X_AUTH_TOKEN = "X-Auth-Token";
@@ -43,71 +43,64 @@ public class HeaderHttpSessionIdResolverTests {
private HeaderHttpSessionIdResolver resolver;
@BeforeEach
public void setup() {
void setup() {
this.request = new MockHttpServletRequest();
this.response = new MockHttpServletResponse();
this.resolver = HeaderHttpSessionIdResolver.xAuthToken();
}
@Test
public void createResolverWithXAuthTokenHeader() {
void createResolverWithXAuthTokenHeader() {
HeaderHttpSessionIdResolver resolver = HeaderHttpSessionIdResolver.xAuthToken();
assertThat(ReflectionTestUtils.getField(resolver, "headerName"))
.isEqualTo("X-Auth-Token");
assertThat(ReflectionTestUtils.getField(resolver, "headerName")).isEqualTo("X-Auth-Token");
}
@Test
public void createResolverWithAuthenticationInfoHeader() {
HeaderHttpSessionIdResolver resolver = HeaderHttpSessionIdResolver
.authenticationInfo();
assertThat(ReflectionTestUtils.getField(resolver, "headerName"))
.isEqualTo("Authentication-Info");
void createResolverWithAuthenticationInfoHeader() {
HeaderHttpSessionIdResolver resolver = HeaderHttpSessionIdResolver.authenticationInfo();
assertThat(ReflectionTestUtils.getField(resolver, "headerName")).isEqualTo("Authentication-Info");
}
@Test
public void createResolverWithCustomHeaderName() {
HeaderHttpSessionIdResolver resolver = new HeaderHttpSessionIdResolver(
"Custom-Header");
assertThat(ReflectionTestUtils.getField(resolver, "headerName"))
.isEqualTo("Custom-Header");
void createResolverWithCustomHeaderName() {
HeaderHttpSessionIdResolver resolver = new HeaderHttpSessionIdResolver("Custom-Header");
assertThat(ReflectionTestUtils.getField(resolver, "headerName")).isEqualTo("Custom-Header");
}
@Test
public void createResolverWithNullHeaderName() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new HeaderHttpSessionIdResolver(null))
void createResolverWithNullHeaderName() {
assertThatIllegalArgumentException().isThrownBy(() -> new HeaderHttpSessionIdResolver(null))
.withMessage("headerName cannot be null");
}
@Test
public void getRequestedSessionIdNull() {
void getRequestedSessionIdNull() {
assertThat(this.resolver.resolveSessionIds(this.request)).isEmpty();
}
@Test
public void getRequestedSessionIdNotNull() {
void getRequestedSessionIdNotNull() {
String sessionId = UUID.randomUUID().toString();
setSessionId(sessionId);
assertThat(this.resolver.resolveSessionIds(this.request))
.isEqualTo(Collections.singletonList(sessionId));
assertThat(this.resolver.resolveSessionIds(this.request)).isEqualTo(Collections.singletonList(sessionId));
}
@Test
public void onNewSession() {
void onNewSession() {
String sessionId = UUID.randomUUID().toString();
this.resolver.setSessionId(this.request, this.response, sessionId);
assertThat(getSessionId()).isEqualTo(sessionId);
}
@Test
public void onDeleteSession() {
void onDeleteSession() {
this.resolver.expireSession(this.request, this.response);
assertThat(getSessionId()).isEmpty();
}
// the header is set as apposed to added
@Test
public void onNewSessionMulti() {
void onNewSessionMulti() {
String sessionId = UUID.randomUUID().toString();
this.resolver.setSessionId(this.request, this.response, sessionId);
this.resolver.setSessionId(this.request, this.response, sessionId);
@@ -117,7 +110,7 @@ public class HeaderHttpSessionIdResolverTests {
// the header is set as apposed to added
@Test
public void onDeleteSessionMulti() {
void onDeleteSessionMulti() {
this.resolver.expireSession(this.request, this.response);
this.resolver.expireSession(this.request, this.response);
assertThat(this.response.getHeaders(HEADER_X_AUTH_TOKEN).size()).isEqualTo(1);

View File

@@ -18,6 +18,7 @@ package org.springframework.session.web.http;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
import javax.servlet.ServletOutputStream;
@@ -32,22 +33,25 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.verify;
public class OnCommittedResponseWrapperTests {
class OnCommittedResponseWrapperTests {
private static final String NL = "\r\n";
@Mock
HttpServletResponse delegate;
@Mock
PrintWriter writer;
@Mock
ServletOutputStream out;
OnCommittedResponseWrapper response;
private OnCommittedResponseWrapper response;
boolean committed;
private boolean committed;
@BeforeEach
public void setup() throws Exception {
void setup() throws Exception {
MockitoAnnotations.initMocks(this);
this.response = new OnCommittedResponseWrapper(this.delegate) {
@Override
@@ -62,14 +66,14 @@ public class OnCommittedResponseWrapperTests {
// --- printwriter
@Test
public void printWriterHashCode() throws Exception {
void printWriterHashCode() throws Exception {
int expected = this.writer.hashCode();
assertThat(this.response.getWriter().hashCode()).isEqualTo(expected);
}
@Test
public void printWriterCheckError() throws Exception {
void printWriterCheckError() throws Exception {
boolean expected = true;
given(this.writer.checkError()).willReturn(expected);
@@ -77,7 +81,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterWriteInt() throws Exception {
void printWriterWriteInt() throws Exception {
int expected = 1;
this.response.getWriter().write(expected);
@@ -86,7 +90,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterWriteCharIntInt() throws Exception {
void printWriterWriteCharIntInt() throws Exception {
char[] buff = new char[0];
int off = 2;
int len = 3;
@@ -97,7 +101,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterWriteChar() throws Exception {
void printWriterWriteChar() throws Exception {
char[] buff = new char[0];
this.response.getWriter().write(buff);
@@ -106,7 +110,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterWriteStringIntInt() throws Exception {
void printWriterWriteStringIntInt() throws Exception {
String s = "";
int off = 2;
int len = 3;
@@ -117,7 +121,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterWriteString() throws Exception {
void printWriterWriteString() throws Exception {
String s = "";
this.response.getWriter().write(s);
@@ -126,7 +130,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintBoolean() throws Exception {
void printWriterPrintBoolean() throws Exception {
boolean b = true;
this.response.getWriter().print(b);
@@ -135,7 +139,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintChar() throws Exception {
void printWriterPrintChar() throws Exception {
char c = 1;
this.response.getWriter().print(c);
@@ -144,7 +148,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintInt() throws Exception {
void printWriterPrintInt() throws Exception {
int i = 1;
this.response.getWriter().print(i);
@@ -153,7 +157,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintLong() throws Exception {
void printWriterPrintLong() throws Exception {
long l = 1;
this.response.getWriter().print(l);
@@ -162,7 +166,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintFloat() throws Exception {
void printWriterPrintFloat() throws Exception {
float f = 1;
this.response.getWriter().print(f);
@@ -171,7 +175,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintDouble() throws Exception {
void printWriterPrintDouble() throws Exception {
double x = 1;
this.response.getWriter().print(x);
@@ -180,7 +184,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintCharArray() throws Exception {
void printWriterPrintCharArray() throws Exception {
char[] x = new char[0];
this.response.getWriter().print(x);
@@ -189,7 +193,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintString() throws Exception {
void printWriterPrintString() throws Exception {
String x = "1";
this.response.getWriter().print(x);
@@ -198,7 +202,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintObject() throws Exception {
void printWriterPrintObject() throws Exception {
Object x = "1";
this.response.getWriter().print(x);
@@ -207,14 +211,14 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintln() throws Exception {
void printWriterPrintln() throws Exception {
this.response.getWriter().println();
verify(this.writer).println();
}
@Test
public void printWriterPrintlnBoolean() throws Exception {
void printWriterPrintlnBoolean() throws Exception {
boolean b = true;
this.response.getWriter().println(b);
@@ -223,7 +227,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintlnChar() throws Exception {
void printWriterPrintlnChar() throws Exception {
char c = 1;
this.response.getWriter().println(c);
@@ -232,7 +236,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintlnInt() throws Exception {
void printWriterPrintlnInt() throws Exception {
int i = 1;
this.response.getWriter().println(i);
@@ -241,7 +245,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintlnLong() throws Exception {
void printWriterPrintlnLong() throws Exception {
long l = 1;
this.response.getWriter().println(l);
@@ -250,7 +254,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintlnFloat() throws Exception {
void printWriterPrintlnFloat() throws Exception {
float f = 1;
this.response.getWriter().println(f);
@@ -259,7 +263,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintlnDouble() throws Exception {
void printWriterPrintlnDouble() throws Exception {
double x = 1;
this.response.getWriter().println(x);
@@ -268,7 +272,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintlnCharArray() throws Exception {
void printWriterPrintlnCharArray() throws Exception {
char[] x = new char[0];
this.response.getWriter().println(x);
@@ -277,7 +281,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintlnString() throws Exception {
void printWriterPrintlnString() throws Exception {
String x = "1";
this.response.getWriter().println(x);
@@ -286,7 +290,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintlnObject() throws Exception {
void printWriterPrintlnObject() throws Exception {
Object x = "1";
this.response.getWriter().println(x);
@@ -295,7 +299,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintfStringObjectVargs() throws Exception {
void printWriterPrintfStringObjectVargs() throws Exception {
String format = "format";
Object[] args = new Object[] { "1" };
@@ -305,7 +309,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterPrintfLocaleStringObjectVargs() throws Exception {
void printWriterPrintfLocaleStringObjectVargs() throws Exception {
Locale l = Locale.US;
String format = "format";
Object[] args = new Object[] { "1" };
@@ -316,7 +320,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterFormatStringObjectVargs() throws Exception {
void printWriterFormatStringObjectVargs() throws Exception {
String format = "format";
Object[] args = new Object[] { "1" };
@@ -326,7 +330,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterFormatLocaleStringObjectVargs() throws Exception {
void printWriterFormatLocaleStringObjectVargs() throws Exception {
Locale l = Locale.US;
String format = "format";
Object[] args = new Object[] { "1" };
@@ -337,7 +341,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterAppendCharSequence() throws Exception {
void printWriterAppendCharSequence() throws Exception {
String x = "a";
this.response.getWriter().append(x);
@@ -346,7 +350,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterAppendCharSequenceIntInt() throws Exception {
void printWriterAppendCharSequenceIntInt() throws Exception {
String x = "abcdef";
int start = 1;
int end = 3;
@@ -357,7 +361,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterAppendChar() throws Exception {
void printWriterAppendChar() throws Exception {
char x = 1;
this.response.getWriter().append(x);
@@ -368,14 +372,14 @@ public class OnCommittedResponseWrapperTests {
// servletoutputstream
@Test
public void outputStreamHashCode() throws Exception {
void outputStreamHashCode() throws Exception {
int expected = this.out.hashCode();
assertThat(this.response.getOutputStream().hashCode()).isEqualTo(expected);
}
@Test
public void outputStreamWriteInt() throws Exception {
void outputStreamWriteInt() throws Exception {
int expected = 1;
this.response.getOutputStream().write(expected);
@@ -384,7 +388,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamWriteByte() throws Exception {
void outputStreamWriteByte() throws Exception {
byte[] expected = new byte[0];
this.response.getOutputStream().write(expected);
@@ -393,7 +397,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamWriteByteIntInt() throws Exception {
void outputStreamWriteByteIntInt() throws Exception {
int start = 1;
int end = 2;
byte[] expected = new byte[0];
@@ -404,7 +408,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamPrintBoolean() throws Exception {
void outputStreamPrintBoolean() throws Exception {
boolean b = true;
this.response.getOutputStream().print(b);
@@ -413,7 +417,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamPrintChar() throws Exception {
void outputStreamPrintChar() throws Exception {
char c = 1;
this.response.getOutputStream().print(c);
@@ -422,7 +426,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamPrintInt() throws Exception {
void outputStreamPrintInt() throws Exception {
int i = 1;
this.response.getOutputStream().print(i);
@@ -431,7 +435,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamPrintLong() throws Exception {
void outputStreamPrintLong() throws Exception {
long l = 1;
this.response.getOutputStream().print(l);
@@ -440,7 +444,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamPrintFloat() throws Exception {
void outputStreamPrintFloat() throws Exception {
float f = 1;
this.response.getOutputStream().print(f);
@@ -449,7 +453,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamPrintDouble() throws Exception {
void outputStreamPrintDouble() throws Exception {
double x = 1;
this.response.getOutputStream().print(x);
@@ -458,7 +462,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamPrintString() throws Exception {
void outputStreamPrintString() throws Exception {
String x = "1";
this.response.getOutputStream().print(x);
@@ -467,14 +471,14 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamPrintln() throws Exception {
void outputStreamPrintln() throws Exception {
this.response.getOutputStream().println();
verify(this.out).println();
}
@Test
public void outputStreamPrintlnBoolean() throws Exception {
void outputStreamPrintlnBoolean() throws Exception {
boolean b = true;
this.response.getOutputStream().println(b);
@@ -483,7 +487,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamPrintlnChar() throws Exception {
void outputStreamPrintlnChar() throws Exception {
char c = 1;
this.response.getOutputStream().println(c);
@@ -492,7 +496,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamPrintlnInt() throws Exception {
void outputStreamPrintlnInt() throws Exception {
int i = 1;
this.response.getOutputStream().println(i);
@@ -501,7 +505,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamPrintlnLong() throws Exception {
void outputStreamPrintlnLong() throws Exception {
long l = 1;
this.response.getOutputStream().println(l);
@@ -510,7 +514,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamPrintlnFloat() throws Exception {
void outputStreamPrintlnFloat() throws Exception {
float f = 1;
this.response.getOutputStream().println(f);
@@ -519,7 +523,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamPrintlnDouble() throws Exception {
void outputStreamPrintlnDouble() throws Exception {
double x = 1;
this.response.getOutputStream().println(x);
@@ -528,7 +532,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void outputStreamPrintlnString() throws Exception {
void outputStreamPrintlnString() throws Exception {
String x = "1";
this.response.getOutputStream().println(x);
@@ -540,7 +544,7 @@ public class OnCommittedResponseWrapperTests {
// has been greater than zero and has been written to the response.
@Test
public void contentLengthPrintWriterWriteIntCommits() throws Exception {
void contentLengthPrintWriterWriteIntCommits() throws Exception {
int expected = 1;
this.response.setContentLength(String.valueOf(expected).length());
@@ -550,7 +554,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterWriteIntMultiDigitCommits() throws Exception {
void contentLengthPrintWriterWriteIntMultiDigitCommits() throws Exception {
int expected = 10000;
this.response.setContentLength(String.valueOf(expected).length());
@@ -560,8 +564,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPlus1PrintWriterWriteIntMultiDigitCommits()
throws Exception {
void contentLengthPlus1PrintWriterWriteIntMultiDigitCommits() throws Exception {
int expected = 10000;
this.response.setContentLength(String.valueOf(expected).length() + 1);
@@ -575,7 +578,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterWriteCharIntIntCommits() throws Exception {
void contentLengthPrintWriterWriteCharIntIntCommits() throws Exception {
char[] buff = new char[0];
int off = 2;
int len = 3;
@@ -587,7 +590,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterWriteCharCommits() throws Exception {
void contentLengthPrintWriterWriteCharCommits() throws Exception {
char[] buff = new char[4];
this.response.setContentLength(buff.length);
@@ -597,7 +600,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterWriteStringIntIntCommits() throws Exception {
void contentLengthPrintWriterWriteStringIntIntCommits() throws Exception {
String s = "";
int off = 2;
int len = 3;
@@ -609,7 +612,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterWriteStringCommits() throws IOException {
void contentLengthPrintWriterWriteStringCommits() throws IOException {
String body = "something";
this.response.setContentLength(body.length());
@@ -619,7 +622,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterWriteStringContentLengthCommits() throws IOException {
void printWriterWriteStringContentLengthCommits() throws IOException {
String body = "something";
this.response.getWriter().write(body);
@@ -629,7 +632,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void printWriterWriteStringDoesNotCommit() throws IOException {
void printWriterWriteStringDoesNotCommit() throws IOException {
String body = "something";
this.response.getWriter().write(body);
@@ -638,7 +641,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintBooleanCommits() throws Exception {
void contentLengthPrintWriterPrintBooleanCommits() throws Exception {
boolean b = true;
this.response.setContentLength(1);
@@ -648,7 +651,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintCharCommits() throws Exception {
void contentLengthPrintWriterPrintCharCommits() throws Exception {
char c = 1;
this.response.setContentLength(1);
@@ -658,7 +661,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintIntCommits() throws Exception {
void contentLengthPrintWriterPrintIntCommits() throws Exception {
int i = 1234;
this.response.setContentLength(String.valueOf(i).length());
@@ -668,7 +671,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintLongCommits() throws Exception {
void contentLengthPrintWriterPrintLongCommits() throws Exception {
long l = 12345;
this.response.setContentLength(String.valueOf(l).length());
@@ -678,7 +681,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintFloatCommits() throws Exception {
void contentLengthPrintWriterPrintFloatCommits() throws Exception {
float f = 12345;
this.response.setContentLength(String.valueOf(f).length());
@@ -688,7 +691,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintDoubleCommits() throws Exception {
void contentLengthPrintWriterPrintDoubleCommits() throws Exception {
double x = 1.2345;
this.response.setContentLength(String.valueOf(x).length());
@@ -698,7 +701,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintCharArrayCommits() throws Exception {
void contentLengthPrintWriterPrintCharArrayCommits() throws Exception {
char[] x = new char[10];
this.response.setContentLength(x.length);
@@ -708,7 +711,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintStringCommits() throws Exception {
void contentLengthPrintWriterPrintStringCommits() throws Exception {
String x = "12345";
this.response.setContentLength(x.length());
@@ -718,7 +721,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintObjectCommits() throws Exception {
void contentLengthPrintWriterPrintObjectCommits() throws Exception {
Object x = "12345";
this.response.setContentLength(String.valueOf(x).length());
@@ -728,7 +731,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintlnCommits() throws Exception {
void contentLengthPrintWriterPrintlnCommits() throws Exception {
this.response.setContentLength(NL.length());
this.response.getWriter().println();
@@ -737,7 +740,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintlnBooleanCommits() throws Exception {
void contentLengthPrintWriterPrintlnBooleanCommits() throws Exception {
boolean b = true;
this.response.setContentLength(1);
@@ -747,7 +750,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintlnCharCommits() throws Exception {
void contentLengthPrintWriterPrintlnCharCommits() throws Exception {
char c = 1;
this.response.setContentLength(1);
@@ -757,7 +760,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintlnIntCommits() throws Exception {
void contentLengthPrintWriterPrintlnIntCommits() throws Exception {
int i = 12345;
this.response.setContentLength(String.valueOf(i).length());
@@ -767,7 +770,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintlnLongCommits() throws Exception {
void contentLengthPrintWriterPrintlnLongCommits() throws Exception {
long l = 12345678;
this.response.setContentLength(String.valueOf(l).length());
@@ -777,7 +780,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintlnFloatCommits() throws Exception {
void contentLengthPrintWriterPrintlnFloatCommits() throws Exception {
float f = 1234;
this.response.setContentLength(String.valueOf(f).length());
@@ -787,7 +790,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintlnDoubleCommits() throws Exception {
void contentLengthPrintWriterPrintlnDoubleCommits() throws Exception {
double x = 1;
this.response.setContentLength(String.valueOf(x).length());
@@ -797,7 +800,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintlnCharArrayCommits() throws Exception {
void contentLengthPrintWriterPrintlnCharArrayCommits() throws Exception {
char[] x = new char[20];
this.response.setContentLength(x.length);
@@ -807,9 +810,9 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintlnStringCommits() throws Exception {
void contentLengthPrintWriterPrintlnStringCommits() throws Exception {
String x = "1";
this.response.setContentLength(String.valueOf(x).length());
this.response.setContentLength(x.length());
this.response.getWriter().println(x);
@@ -817,7 +820,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterPrintlnObjectCommits() throws Exception {
void contentLengthPrintWriterPrintlnObjectCommits() throws Exception {
Object x = "1";
this.response.setContentLength(String.valueOf(x).length());
@@ -827,9 +830,9 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterAppendCharSequenceCommits() throws Exception {
void contentLengthPrintWriterAppendCharSequenceCommits() throws Exception {
String x = "a";
this.response.setContentLength(String.valueOf(x).length());
this.response.setContentLength(x.length());
this.response.getWriter().append(x);
@@ -837,8 +840,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterAppendCharSequenceIntIntCommits()
throws Exception {
void contentLengthPrintWriterAppendCharSequenceIntIntCommits() throws Exception {
String x = "abcdef";
int start = 1;
int end = 3;
@@ -850,7 +852,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPrintWriterAppendCharCommits() throws Exception {
void contentLengthPrintWriterAppendCharCommits() throws Exception {
char x = 1;
this.response.setContentLength(1);
@@ -860,7 +862,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamWriteIntCommits() throws Exception {
void contentLengthOutputStreamWriteIntCommits() throws Exception {
int expected = 1;
this.response.setContentLength(String.valueOf(expected).length());
@@ -870,7 +872,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamWriteIntMultiDigitCommits() throws Exception {
void contentLengthOutputStreamWriteIntMultiDigitCommits() throws Exception {
int expected = 10000;
this.response.setContentLength(String.valueOf(expected).length());
@@ -880,8 +882,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthPlus1OutputStreamWriteIntMultiDigitCommits()
throws Exception {
void contentLengthPlus1OutputStreamWriteIntMultiDigitCommits() throws Exception {
int expected = 10000;
this.response.setContentLength(String.valueOf(expected).length() + 1);
@@ -896,24 +897,23 @@ public class OnCommittedResponseWrapperTests {
// gh-171
@Test
public void contentLengthPlus1OutputStreamWriteByteArrayMultiDigitCommits()
throws Exception {
void contentLengthPlus1OutputStreamWriteByteArrayMultiDigitCommits() throws Exception {
String expected = "{\n" + " \"parameterName\" : \"_csrf\",\n"
+ " \"token\" : \"06300b65-c4aa-4c8f-8cda-39ee17f545a0\",\n"
+ " \"headerName\" : \"X-CSRF-TOKEN\"\n" + "}";
+ " \"token\" : \"06300b65-c4aa-4c8f-8cda-39ee17f545a0\",\n" + " \"headerName\" : \"X-CSRF-TOKEN\"\n"
+ "}";
this.response.setContentLength(expected.length() + 1);
this.response.getOutputStream().write(expected.getBytes());
assertThat(this.committed).isFalse();
this.response.getOutputStream().write("1".getBytes("UTF-8"));
this.response.getOutputStream().write("1".getBytes(StandardCharsets.UTF_8));
assertThat(this.committed).isTrue();
}
@Test
public void contentLengthOutputStreamPrintBooleanCommits() throws Exception {
void contentLengthOutputStreamPrintBooleanCommits() throws Exception {
boolean b = true;
this.response.setContentLength(1);
@@ -923,7 +923,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamPrintCharCommits() throws Exception {
void contentLengthOutputStreamPrintCharCommits() throws Exception {
char c = 1;
this.response.setContentLength(1);
@@ -933,7 +933,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamPrintIntCommits() throws Exception {
void contentLengthOutputStreamPrintIntCommits() throws Exception {
int i = 1234;
this.response.setContentLength(String.valueOf(i).length());
@@ -943,7 +943,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamPrintLongCommits() throws Exception {
void contentLengthOutputStreamPrintLongCommits() throws Exception {
long l = 12345;
this.response.setContentLength(String.valueOf(l).length());
@@ -953,7 +953,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamPrintFloatCommits() throws Exception {
void contentLengthOutputStreamPrintFloatCommits() throws Exception {
float f = 12345;
this.response.setContentLength(String.valueOf(f).length());
@@ -963,7 +963,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamPrintDoubleCommits() throws Exception {
void contentLengthOutputStreamPrintDoubleCommits() throws Exception {
double x = 1.2345;
this.response.setContentLength(String.valueOf(x).length());
@@ -973,7 +973,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamPrintStringCommits() throws Exception {
void contentLengthOutputStreamPrintStringCommits() throws Exception {
String x = "12345";
this.response.setContentLength(x.length());
@@ -983,7 +983,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamPrintlnCommits() throws Exception {
void contentLengthOutputStreamPrintlnCommits() throws Exception {
this.response.setContentLength(NL.length());
this.response.getOutputStream().println();
@@ -992,7 +992,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamPrintlnBooleanCommits() throws Exception {
void contentLengthOutputStreamPrintlnBooleanCommits() throws Exception {
boolean b = true;
this.response.setContentLength(1);
@@ -1002,7 +1002,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamPrintlnCharCommits() throws Exception {
void contentLengthOutputStreamPrintlnCharCommits() throws Exception {
char c = 1;
this.response.setContentLength(1);
@@ -1012,7 +1012,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamPrintlnIntCommits() throws Exception {
void contentLengthOutputStreamPrintlnIntCommits() throws Exception {
int i = 12345;
this.response.setContentLength(String.valueOf(i).length());
@@ -1022,7 +1022,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamPrintlnLongCommits() throws Exception {
void contentLengthOutputStreamPrintlnLongCommits() throws Exception {
long l = 12345678;
this.response.setContentLength(String.valueOf(l).length());
@@ -1032,7 +1032,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamPrintlnFloatCommits() throws Exception {
void contentLengthOutputStreamPrintlnFloatCommits() throws Exception {
float f = 1234;
this.response.setContentLength(String.valueOf(f).length());
@@ -1042,7 +1042,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamPrintlnDoubleCommits() throws Exception {
void contentLengthOutputStreamPrintlnDoubleCommits() throws Exception {
double x = 1;
this.response.setContentLength(String.valueOf(x).length());
@@ -1052,9 +1052,9 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamPrintlnStringCommits() throws Exception {
void contentLengthOutputStreamPrintlnStringCommits() throws Exception {
String x = "1";
this.response.setContentLength(String.valueOf(x).length());
this.response.setContentLength(x.length());
this.response.getOutputStream().println(x);
@@ -1062,7 +1062,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthDoesNotCommit() throws IOException {
void contentLengthDoesNotCommit() {
String body = "something";
this.response.setContentLength(body.length());
@@ -1071,7 +1071,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void contentLengthOutputStreamWriteStringCommits() throws IOException {
void contentLengthOutputStreamWriteStringCommits() throws IOException {
String body = "something";
this.response.setContentLength(body.length());
@@ -1081,10 +1081,9 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void addHeaderContentLengthPrintWriterWriteStringCommits() throws Exception {
void addHeaderContentLengthPrintWriterWriteStringCommits() throws Exception {
int expected = 1234;
this.response.addHeader("Content-Length",
String.valueOf(String.valueOf(expected).length()));
this.response.addHeader("Content-Length", String.valueOf(String.valueOf(expected).length()));
this.response.getWriter().write(expected);
@@ -1092,7 +1091,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void bufferSizePrintWriterWriteCommits() throws Exception {
void bufferSizePrintWriterWriteCommits() throws Exception {
String expected = "1234567890";
given(this.response.getBufferSize()).willReturn(expected.length());
@@ -1102,7 +1101,7 @@ public class OnCommittedResponseWrapperTests {
}
@Test
public void bufferSizeCommitsOnce() throws Exception {
void bufferSizeCommitsOnce() throws Exception {
String expected = "1234567890";
given(this.response.getBufferSize()).willReturn(expected.length());
@@ -1116,4 +1115,5 @@ public class OnCommittedResponseWrapperTests {
assertThat(this.committed).isFalse();
}
}

View File

@@ -20,6 +20,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.DispatcherType;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
@@ -32,21 +33,27 @@ import org.junit.jupiter.api.Test;
import org.springframework.mock.web.MockFilterChain;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.web.util.WebUtils;
import static org.assertj.core.api.Assertions.assertThat;
public class OncePerRequestFilterTests {
class OncePerRequestFilterTests {
private MockHttpServletRequest request;
private MockHttpServletResponse response;
private MockFilterChain chain;
private OncePerRequestFilter filter;
private HttpServlet servlet;
private List<OncePerRequestFilter> invocations;
@BeforeEach
@SuppressWarnings("serial")
public void setup() {
void setup() {
this.servlet = new HttpServlet() {
};
this.request = new MockHttpServletRequest();
@@ -55,9 +62,8 @@ public class OncePerRequestFilterTests {
this.invocations = new ArrayList<>();
this.filter = new OncePerRequestFilter() {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
OncePerRequestFilterTests.this.invocations.add(this);
filterChain.doFilter(request, response);
}
@@ -65,34 +71,63 @@ public class OncePerRequestFilterTests {
}
@Test
public void doFilterOnce() throws ServletException, IOException {
void doFilterOnce() throws ServletException, IOException {
this.filter.doFilter(this.request, this.response, this.chain);
assertThat(this.invocations).containsOnly(this.filter);
}
@Test
public void doFilterMultiOnlyIvokesOnce() throws ServletException, IOException {
this.filter.doFilter(this.request, this.response,
new MockFilterChain(this.servlet, this.filter));
void doFilterMultiOnlyIvokesOnce() throws ServletException, IOException {
this.filter.doFilter(this.request, this.response, new MockFilterChain(this.servlet, this.filter));
assertThat(this.invocations).containsOnly(this.filter);
}
@Test
public void doFilterOtherSubclassInvoked() throws ServletException, IOException {
void doFilterOtherSubclassInvoked() throws ServletException, IOException {
OncePerRequestFilter filter2 = new OncePerRequestFilter() {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
OncePerRequestFilterTests.this.invocations.add(this);
filterChain.doFilter(request, response);
}
};
this.filter.doFilter(this.request, this.response,
new MockFilterChain(this.servlet, filter2));
this.filter.doFilter(this.request, this.response, new MockFilterChain(this.servlet, filter2));
assertThat(this.invocations).containsOnly(this.filter, filter2);
}
@Test // gh-1470
void filterNestedErrorDispatch() throws ServletException, IOException {
TestOncePerRequestFilter filter = new TestOncePerRequestFilter();
this.request.setAttribute(filter.getAlreadyFilteredAttributeName(), Boolean.TRUE);
this.request.setDispatcherType(DispatcherType.ERROR);
this.request.setAttribute(WebUtils.ERROR_REQUEST_URI_ATTRIBUTE, "/error");
filter.doFilter(this.request, new MockHttpServletResponse(), this.chain);
assertThat(filter.didFilter).isFalse();
assertThat(filter.didFilterNestedErrorDispatch).isTrue();
}
private static class TestOncePerRequestFilter extends OncePerRequestFilter {
private boolean didFilter;
private boolean didFilterNestedErrorDispatch;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) {
this.didFilter = true;
}
@Override
protected void doFilterNestedErrorDispatch(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) {
this.didFilterNestedErrorDispatch = true;
}
}
}

View File

@@ -47,7 +47,7 @@ import static org.mockito.Mockito.verifyZeroInteractions;
* @author Rob Winch
* @since 1.1
*/
public class SessionEventHttpSessionListenerAdapterTests {
class SessionEventHttpSessionListenerAdapterTests {
@Mock
private HttpSessionListener listener1;
@@ -68,10 +68,9 @@ public class SessionEventHttpSessionListenerAdapterTests {
private SessionEventHttpSessionListenerAdapter listener;
@BeforeEach
public void setup() {
void setup() {
MockitoAnnotations.initMocks(this);
this.listener = new SessionEventHttpSessionListenerAdapter(
Arrays.asList(this.listener1, this.listener2));
this.listener = new SessionEventHttpSessionListenerAdapter(Arrays.asList(this.listener1, this.listener2));
this.listener.setServletContext(new MockServletContext());
Session session = new MapSession();
@@ -83,7 +82,7 @@ public class SessionEventHttpSessionListenerAdapterTests {
// make configuration easier (i.e. autowire all HttpSessionListeners and might get
// none)
@Test
public void constructorEmptyWorks() {
void constructorEmptyWorks() {
new SessionEventHttpSessionListenerAdapter(Collections.emptyList());
}
@@ -92,9 +91,8 @@ public class SessionEventHttpSessionListenerAdapterTests {
* listeners
*/
@Test
public void onApplicationEventEmptyListenersDoesNotUseEvent() {
this.listener = new SessionEventHttpSessionListenerAdapter(
Collections.emptyList());
void onApplicationEventEmptyListenersDoesNotUseEvent() {
this.listener = new SessionEventHttpSessionListenerAdapter(Collections.emptyList());
this.destroyed = mock(SessionDestroyedEvent.class);
this.listener.onApplicationEvent(this.destroyed);
@@ -103,25 +101,23 @@ public class SessionEventHttpSessionListenerAdapterTests {
}
@Test
public void onApplicationEventDestroyed() {
void onApplicationEventDestroyed() {
this.listener.onApplicationEvent(this.destroyed);
verify(this.listener1).sessionDestroyed(this.sessionEvent.capture());
verify(this.listener2).sessionDestroyed(this.sessionEvent.capture());
assertThat(this.sessionEvent.getValue().getSession().getId())
.isEqualTo(this.destroyed.getSessionId());
assertThat(this.sessionEvent.getValue().getSession().getId()).isEqualTo(this.destroyed.getSessionId());
}
@Test
public void onApplicationEventCreated() {
void onApplicationEventCreated() {
this.listener.onApplicationEvent(this.created);
verify(this.listener1).sessionCreated(this.sessionEvent.capture());
verify(this.listener2).sessionCreated(this.sessionEvent.capture());
assertThat(this.sessionEvent.getValue().getSession().getId())
.isEqualTo(this.created.getSessionId());
assertThat(this.sessionEvent.getValue().getSession().getId()).isEqualTo(this.created.getSessionId());
}
}

View File

@@ -43,7 +43,7 @@ import static org.mockito.Mockito.verify;
* @author Rob Winch
* @author Vedran Pavic
*/
public class SpringSessionWebSessionStoreTests<S extends Session> {
class SpringSessionWebSessionStoreTests<S extends Session> {
@Mock
private ReactiveSessionRepository<S> sessionRepository;
@@ -57,68 +57,62 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
private SpringSessionWebSessionStore<S> webSessionStore;
@BeforeEach
public void setup() {
void setup() {
MockitoAnnotations.initMocks(this);
this.webSessionStore = new SpringSessionWebSessionStore<>(this.sessionRepository);
given(this.sessionRepository.findById(any()))
.willReturn(Mono.just(this.findByIdSession));
given(this.sessionRepository.createSession())
.willReturn(Mono.just(this.createSession));
given(this.sessionRepository.findById(any())).willReturn(Mono.just(this.findByIdSession));
given(this.sessionRepository.createSession()).willReturn(Mono.just(this.createSession));
}
@Test
public void constructorWhenNullRepositoryThenThrowsIllegalArgumentException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new SpringSessionWebSessionStore<S>(null))
void constructorWhenNullRepositoryThenThrowsIllegalArgumentException() {
assertThatIllegalArgumentException().isThrownBy(() -> new SpringSessionWebSessionStore<S>(null))
.withMessage("reactiveSessionRepository cannot be null");
}
@Test
public void createSessionWhenNoAttributesThenNotStarted() {
void createSessionWhenNoAttributesThenNotStarted() {
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
assertThat(createdWebSession.isStarted()).isFalse();
}
@Test
public void createSessionWhenAddAttributeThenStarted() {
given(this.createSession.getAttributeNames())
.willReturn(Collections.singleton("a"));
void createSessionWhenAddAttributeThenStarted() {
given(this.createSession.getAttributeNames()).willReturn(Collections.singleton("a"));
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
assertThat(createdWebSession.isStarted()).isTrue();
}
@Test
public void createSessionWhenGetAttributesAndSizeThenDelegatesToCreateSession() {
void createSessionWhenGetAttributesAndSizeThenDelegatesToCreateSession() {
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
Map<String, Object> attributes = createdWebSession.getAttributes();
assertThat(attributes.size()).isEqualTo(0);
given(this.createSession.getAttributeNames())
.willReturn(Collections.singleton("a"));
given(this.createSession.getAttributeNames()).willReturn(Collections.singleton("a"));
assertThat(attributes.size()).isEqualTo(1);
}
@Test
public void createSessionWhenGetAttributesAndIsEmptyThenDelegatesToCreateSession() {
void createSessionWhenGetAttributesAndIsEmptyThenDelegatesToCreateSession() {
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
Map<String, Object> attributes = createdWebSession.getAttributes();
assertThat(attributes.isEmpty()).isTrue();
given(this.createSession.getAttributeNames())
.willReturn(Collections.singleton("a"));
given(this.createSession.getAttributeNames()).willReturn(Collections.singleton("a"));
assertThat(attributes.isEmpty()).isFalse();
}
@Test
public void createSessionWhenGetAttributesAndContainsKeyAndNotStringThenFalse() {
void createSessionWhenGetAttributesAndContainsKeyAndNotStringThenFalse() {
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
Map<String, Object> attributes = createdWebSession.getAttributes();
@@ -127,7 +121,7 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
}
@Test
public void createSessionWhenGetAttributesAndContainsKeyAndNotFoundThenFalse() {
void createSessionWhenGetAttributesAndContainsKeyAndNotFoundThenFalse() {
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
Map<String, Object> attributes = createdWebSession.getAttributes();
@@ -136,9 +130,8 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
}
@Test
public void createSessionWhenGetAttributesAndContainsKeyAndFoundThenTrue() {
given(this.createSession.getAttributeNames())
.willReturn(Collections.singleton("a"));
void createSessionWhenGetAttributesAndContainsKeyAndFoundThenTrue() {
given(this.createSession.getAttributeNames()).willReturn(Collections.singleton("a"));
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
Map<String, Object> attributes = createdWebSession.getAttributes();
@@ -147,7 +140,7 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
}
@Test
public void createSessionWhenGetAttributesAndPutThenDelegatesToCreateSession() {
void createSessionWhenGetAttributesAndPutThenDelegatesToCreateSession() {
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
Map<String, Object> attributes = createdWebSession.getAttributes();
@@ -157,7 +150,7 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
}
@Test
public void createSessionWhenGetAttributesAndPutNullThenDelegatesToCreateSession() {
void createSessionWhenGetAttributesAndPutNullThenDelegatesToCreateSession() {
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
Map<String, Object> attributes = createdWebSession.getAttributes();
@@ -167,7 +160,7 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
}
@Test
public void createSessionWhenGetAttributesAndRemoveThenDelegatesToCreateSession() {
void createSessionWhenGetAttributesAndRemoveThenDelegatesToCreateSession() {
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
Map<String, Object> attributes = createdWebSession.getAttributes();
@@ -177,7 +170,7 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
}
@Test
public void createSessionWhenGetAttributesAndPutAllThenDelegatesToCreateSession() {
void createSessionWhenGetAttributesAndPutAllThenDelegatesToCreateSession() {
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
Map<String, Object> attributes = createdWebSession.getAttributes();
@@ -187,9 +180,8 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
}
@Test
public void createSessionWhenGetAttributesAndClearThenDelegatesToCreateSession() {
given(this.createSession.getAttributeNames())
.willReturn(Collections.singleton("a"));
void createSessionWhenGetAttributesAndClearThenDelegatesToCreateSession() {
given(this.createSession.getAttributeNames()).willReturn(Collections.singleton("a"));
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
Map<String, Object> attributes = createdWebSession.getAttributes();
@@ -199,9 +191,8 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
}
@Test
public void createSessionWhenGetAttributesAndKeySetThenDelegatesToCreateSession() {
given(this.createSession.getAttributeNames())
.willReturn(Collections.singleton("a"));
void createSessionWhenGetAttributesAndKeySetThenDelegatesToCreateSession() {
given(this.createSession.getAttributeNames()).willReturn(Collections.singleton("a"));
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
Map<String, Object> attributes = createdWebSession.getAttributes();
@@ -210,9 +201,8 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
}
@Test
public void createSessionWhenGetAttributesAndValuesThenDelegatesToCreateSession() {
given(this.createSession.getAttributeNames())
.willReturn(Collections.singleton("a"));
void createSessionWhenGetAttributesAndValuesThenDelegatesToCreateSession() {
given(this.createSession.getAttributeNames()).willReturn(Collections.singleton("a"));
given(this.createSession.getAttribute("a")).willReturn("b");
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
@@ -222,10 +212,9 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
}
@Test
public void createSessionWhenGetAttributesAndEntrySetThenDelegatesToCreateSession() {
void createSessionWhenGetAttributesAndEntrySetThenDelegatesToCreateSession() {
String attrName = "attrName";
given(this.createSession.getAttributeNames())
.willReturn(Collections.singleton(attrName));
given(this.createSession.getAttributeNames()).willReturn(Collections.singleton(attrName));
String attrValue = "attrValue";
given(this.createSession.getAttribute(attrName)).willReturn(attrValue);
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
@@ -233,12 +222,11 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
Map<String, Object> attributes = createdWebSession.getAttributes();
Set<Map.Entry<String, Object>> entries = attributes.entrySet();
assertThat(entries)
.containsExactly(new AbstractMap.SimpleEntry<>(attrName, attrValue));
assertThat(entries).containsExactly(new AbstractMap.SimpleEntry<>(attrName, attrValue));
}
@Test
public void retrieveSessionThenStarted() {
void retrieveSessionThenStarted() {
String id = "id";
WebSession retrievedWebSession = this.webSessionStore.retrieveSession(id).block();
@@ -247,7 +235,7 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
}
@Test
public void removeSessionWhenInvokedThenSessionSaved() {
void removeSessionWhenInvokedThenSessionSaved() {
String sessionId = "session-id";
given(this.sessionRepository.deleteById(sessionId)).willReturn(Mono.empty());
@@ -257,21 +245,20 @@ public class SpringSessionWebSessionStoreTests<S extends Session> {
}
@Test
public void setClockWhenNullThenException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.webSessionStore.setClock(null))
void setClockWhenNullThenException() {
assertThatIllegalArgumentException().isThrownBy(() -> this.webSessionStore.setClock(null))
.withMessage("clock cannot be null");
}
@Test // gh-1114
public void createSessionThenSessionIsNotExpired() {
void createSessionThenSessionIsNotExpired() {
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
assertThat(createdWebSession.isExpired()).isFalse();
}
@Test // gh-1114
public void invalidateSessionThenSessionIsExpired() {
void invalidateSessionThenSessionIsExpired() {
WebSession createdWebSession = this.webSessionStore.createWebSession().block();
given(createdWebSession.invalidate()).willReturn(Mono.empty());

View File

@@ -35,33 +35,36 @@ import static org.mockito.BDDMockito.willThrow;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.verify;
public class WebSocketConnectHandlerDecoratorFactoryTests {
class WebSocketConnectHandlerDecoratorFactoryTests {
@Mock
ApplicationEventPublisher eventPublisher;
@Mock
WebSocketHandler delegate;
@Mock
WebSocketSession session;
@Captor
ArgumentCaptor<SessionConnectEvent> event;
WebSocketConnectHandlerDecoratorFactory factory;
private WebSocketConnectHandlerDecoratorFactory factory;
@BeforeEach
public void setup() {
void setup() {
MockitoAnnotations.initMocks(this);
this.factory = new WebSocketConnectHandlerDecoratorFactory(this.eventPublisher);
}
@Test
public void constructorNullEventPublisher() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new WebSocketConnectHandlerDecoratorFactory(null))
void constructorNullEventPublisher() {
assertThatIllegalArgumentException().isThrownBy(() -> new WebSocketConnectHandlerDecoratorFactory(null))
.withMessage("eventPublisher cannot be null");
}
@Test
public void decorateAfterConnectionEstablished() throws Exception {
void decorateAfterConnectionEstablished() throws Exception {
WebSocketHandler decorated = this.factory.decorate(this.delegate);
decorated.afterConnectionEstablished(this.session);
@@ -71,13 +74,14 @@ public class WebSocketConnectHandlerDecoratorFactoryTests {
}
@Test
public void decorateAfterConnectionEstablishedEventError() throws Exception {
void decorateAfterConnectionEstablishedEventError() throws Exception {
WebSocketHandler decorated = this.factory.decorate(this.delegate);
willThrow(new IllegalStateException("Test throw on publishEvent"))
.given(this.eventPublisher).publishEvent(any(ApplicationEvent.class));
willThrow(new IllegalStateException("Test throw on publishEvent")).given(this.eventPublisher)
.publishEvent(any(ApplicationEvent.class));
decorated.afterConnectionEstablished(this.session);
verify(this.eventPublisher).publishEvent(any(SessionConnectEvent.class));
}
}

View File

@@ -44,7 +44,7 @@ import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
public class WebSocketRegistryListenerTests {
class WebSocketRegistryListenerTests {
@Mock
private WebSocketSession wsSession;
@@ -73,7 +73,7 @@ public class WebSocketRegistryListenerTests {
private WebSocketRegistryListener listener;
@BeforeEach
public void setup() {
void setup() {
MockitoAnnotations.initMocks(this);
String sessionId = "session-id";
MapSession session = new MapSession(sessionId);
@@ -96,14 +96,14 @@ public class WebSocketRegistryListenerTests {
this.listener = new WebSocketRegistryListener();
this.connect = new SessionConnectEvent(this.listener, this.wsSession);
this.connect2 = new SessionConnectEvent(this.listener, this.wsSession2);
this.disconnect = new SessionDisconnectEvent(this.listener, this.message,
this.wsSession.getId(), CloseStatus.NORMAL);
this.disconnect = new SessionDisconnectEvent(this.listener, this.message, this.wsSession.getId(),
CloseStatus.NORMAL);
this.deleted = new SessionDeletedEvent(this.listener, session);
this.expired = new SessionExpiredEvent(this.listener, session);
}
@Test
public void onApplicationEventConnectSessionDeleted() throws Exception {
void onApplicationEventConnectSessionDeleted() throws Exception {
this.listener.onApplicationEvent(this.connect);
this.listener.onApplicationEvent(this.deleted);
@@ -112,7 +112,7 @@ public class WebSocketRegistryListenerTests {
}
@Test
public void onApplicationEventConnectSessionExpired() throws Exception {
void onApplicationEventConnectSessionExpired() throws Exception {
this.listener.onApplicationEvent(this.connect);
this.listener.onApplicationEvent(this.expired);
@@ -121,7 +121,7 @@ public class WebSocketRegistryListenerTests {
}
@Test
public void onApplicationEventConnectSessionDeletedNullPrincipal() throws Exception {
void onApplicationEventConnectSessionDeletedNullPrincipal() throws Exception {
given(this.wsSession.getPrincipal()).willReturn(null);
this.listener.onApplicationEvent(this.connect);
@@ -131,7 +131,7 @@ public class WebSocketRegistryListenerTests {
}
@Test
public void onApplicationEventConnectDisconnect() throws Exception {
void onApplicationEventConnectDisconnect() throws Exception {
this.listener.onApplicationEvent(this.connect);
this.listener.onApplicationEvent(this.disconnect);
@@ -143,7 +143,7 @@ public class WebSocketRegistryListenerTests {
// gh-76
@Test
@SuppressWarnings("unchecked")
public void onApplicationEventConnectDisconnectCleanup() {
void onApplicationEventConnectDisconnectCleanup() {
this.listener.onApplicationEvent(this.connect);
this.listener.onApplicationEvent(this.disconnect);
@@ -154,7 +154,7 @@ public class WebSocketRegistryListenerTests {
}
@Test
public void onApplicationEventConnectDisconnectNullSession() throws Exception {
void onApplicationEventConnectDisconnectNullSession() {
this.listener.onApplicationEvent(this.connect);
this.attributes.clear();
@@ -164,7 +164,7 @@ public class WebSocketRegistryListenerTests {
}
@Test
public void onApplicationEventConnectConnectDisonnect() throws Exception {
void onApplicationEventConnectConnectDisonnect() throws Exception {
this.listener.onApplicationEvent(this.connect);
this.listener.onApplicationEvent(this.connect2);
this.listener.onApplicationEvent(this.disconnect);

View File

@@ -51,25 +51,27 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
public class SessionRepositoryMessageInterceptorTests {
class SessionRepositoryMessageInterceptorTests {
@Mock
SessionRepository<Session> sessionRepository;
@Mock
MessageChannel channel;
@Mock
Session session;
Message<?> createMessage;
private Message<?> createMessage;
SimpMessageHeaderAccessor headers;
private SimpMessageHeaderAccessor headers;
SessionRepositoryMessageInterceptor<Session> interceptor;
private SessionRepositoryMessageInterceptor<Session> interceptor;
@BeforeEach
public void setup() {
void setup() {
MockitoAnnotations.initMocks(this);
this.interceptor = new SessionRepositoryMessageInterceptor<>(
this.sessionRepository);
this.interceptor = new SessionRepositoryMessageInterceptor<>(this.sessionRepository);
this.headers = SimpMessageHeaderAccessor.create();
this.headers.setSessionId("session");
this.headers.setSessionAttributes(new HashMap<>());
@@ -80,123 +82,112 @@ public class SessionRepositoryMessageInterceptorTests {
}
@Test
public void preSendconstructorNullRepository() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new SessionRepositoryMessageInterceptor<>(null))
void preSendconstructorNullRepository() {
assertThatIllegalArgumentException().isThrownBy(() -> new SessionRepositoryMessageInterceptor<>(null))
.withMessage("sessionRepository cannot be null");
}
@Test
public void preSendNullMessage() {
void preSendNullMessage() {
assertThat(this.interceptor.preSend(null, this.channel)).isNull();
}
@Test
public void preSendConnectAckDoesNotInvokeSessionRepository() {
void preSendConnectAckDoesNotInvokeSessionRepository() {
setMessageType(SimpMessageType.CONNECT_ACK);
assertThat(this.interceptor.preSend(createMessage(), this.channel))
.isSameAs(this.createMessage);
assertThat(this.interceptor.preSend(createMessage(), this.channel)).isSameAs(this.createMessage);
verifyZeroInteractions(this.sessionRepository);
}
@Test
public void preSendHeartbeatDoesNotInvokeSessionRepository() {
void preSendHeartbeatDoesNotInvokeSessionRepository() {
setMessageType(SimpMessageType.HEARTBEAT);
assertThat(this.interceptor.preSend(createMessage(), this.channel))
.isSameAs(this.createMessage);
assertThat(this.interceptor.preSend(createMessage(), this.channel)).isSameAs(this.createMessage);
verifyZeroInteractions(this.sessionRepository);
}
@Test
public void preSendDisconnectDoesNotInvokeSessionRepository() {
void preSendDisconnectDoesNotInvokeSessionRepository() {
setMessageType(SimpMessageType.DISCONNECT);
assertThat(this.interceptor.preSend(createMessage(), this.channel))
.isSameAs(this.createMessage);
assertThat(this.interceptor.preSend(createMessage(), this.channel)).isSameAs(this.createMessage);
verifyZeroInteractions(this.sessionRepository);
}
@Test
public void preSendOtherDoesNotInvokeSessionRepository() {
void preSendOtherDoesNotInvokeSessionRepository() {
setMessageType(SimpMessageType.OTHER);
assertThat(this.interceptor.preSend(createMessage(), this.channel))
.isSameAs(this.createMessage);
assertThat(this.interceptor.preSend(createMessage(), this.channel)).isSameAs(this.createMessage);
verifyZeroInteractions(this.sessionRepository);
}
@Test
public void setMatchingMessageTypesNull() {
void setMatchingMessageTypesNull() {
assertThatIllegalArgumentException().isThrownBy(() -> this.interceptor.setMatchingMessageTypes(null))
.withMessage("matchingMessageTypes cannot be null or empty");
}
@Test
void setMatchingMessageTypesEmpty() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.interceptor.setMatchingMessageTypes(null))
.isThrownBy(() -> this.interceptor.setMatchingMessageTypes(Collections.emptySet()))
.withMessage("matchingMessageTypes cannot be null or empty");
}
@Test
public void setMatchingMessageTypesEmpty() {
assertThatIllegalArgumentException().isThrownBy(
() -> this.interceptor.setMatchingMessageTypes(Collections.emptySet()))
.withMessage("matchingMessageTypes cannot be null or empty");
}
@Test
public void preSendSetMatchingMessageTypes() {
void preSendSetMatchingMessageTypes() {
this.interceptor.setMatchingMessageTypes(EnumSet.of(SimpMessageType.DISCONNECT));
setMessageType(SimpMessageType.DISCONNECT);
assertThat(this.interceptor.preSend(createMessage(), this.channel))
.isSameAs(this.createMessage);
assertThat(this.interceptor.preSend(createMessage(), this.channel)).isSameAs(this.createMessage);
verify(this.sessionRepository).findById(anyString());
verify(this.sessionRepository).save(this.session);
}
@Test
public void preSendConnectUpdatesLastUpdateTime() {
void preSendConnectUpdatesLastUpdateTime() {
setMessageType(SimpMessageType.CONNECT);
assertThat(this.interceptor.preSend(createMessage(), this.channel))
.isSameAs(this.createMessage);
assertThat(this.interceptor.preSend(createMessage(), this.channel)).isSameAs(this.createMessage);
verify(this.session).setLastAccessedTime(argThat(isAlmostNow()));
verify(this.sessionRepository).save(this.session);
}
@Test
public void preSendMessageUpdatesLastUpdateTime() {
void preSendMessageUpdatesLastUpdateTime() {
setMessageType(SimpMessageType.MESSAGE);
assertThat(this.interceptor.preSend(createMessage(), this.channel))
.isSameAs(this.createMessage);
assertThat(this.interceptor.preSend(createMessage(), this.channel)).isSameAs(this.createMessage);
verify(this.session).setLastAccessedTime(argThat(isAlmostNow()));
verify(this.sessionRepository).save(this.session);
}
@Test
public void preSendSubscribeUpdatesLastUpdateTime() {
void preSendSubscribeUpdatesLastUpdateTime() {
setMessageType(SimpMessageType.SUBSCRIBE);
assertThat(this.interceptor.preSend(createMessage(), this.channel))
.isSameAs(this.createMessage);
assertThat(this.interceptor.preSend(createMessage(), this.channel)).isSameAs(this.createMessage);
verify(this.session).setLastAccessedTime(argThat(isAlmostNow()));
verify(this.sessionRepository).save(this.session);
}
@Test
public void preSendUnsubscribeUpdatesLastUpdateTime() {
void preSendUnsubscribeUpdatesLastUpdateTime() {
setMessageType(SimpMessageType.UNSUBSCRIBE);
this.session.setLastAccessedTime(Instant.EPOCH);
assertThat(this.interceptor.preSend(createMessage(), this.channel))
.isSameAs(this.createMessage);
assertThat(this.interceptor.preSend(createMessage(), this.channel)).isSameAs(this.createMessage);
verify(this.session).setLastAccessedTime(argThat(isAlmostNow()));
verify(this.sessionRepository).save(this.session);
@@ -204,7 +195,7 @@ public class SessionRepositoryMessageInterceptorTests {
// This will updated when SPR-12288 is resolved
@Test
public void preSendExpiredSession() {
void preSendExpiredSession() {
setSessionId("expired");
this.interceptor.preSend(createMessage(), this.channel);
@@ -213,74 +204,67 @@ public class SessionRepositoryMessageInterceptorTests {
}
@Test
public void preSendNullSessionId() {
void preSendNullSessionId() {
setSessionId(null);
assertThat(this.interceptor.preSend(createMessage(), this.channel))
.isSameAs(this.createMessage);
assertThat(this.interceptor.preSend(createMessage(), this.channel)).isSameAs(this.createMessage);
verifyZeroInteractions(this.sessionRepository);
}
@Test
public void preSendNullSessionAttributes() {
void preSendNullSessionAttributes() {
this.headers.setSessionAttributes(null);
assertThat(this.interceptor.preSend(createMessage(), this.channel))
.isSameAs(this.createMessage);
assertThat(this.interceptor.preSend(createMessage(), this.channel)).isSameAs(this.createMessage);
verifyZeroInteractions(this.sessionRepository);
}
@Test
public void beforeHandshakeNotServletServerHttpRequest() throws Exception {
void beforeHandshakeNotServletServerHttpRequest() {
assertThat(this.interceptor.beforeHandshake(null, null, null, null)).isTrue();
verifyZeroInteractions(this.sessionRepository);
}
@Test
public void beforeHandshakeNullSession() throws Exception {
ServletServerHttpRequest request = new ServletServerHttpRequest(
new MockHttpServletRequest());
void beforeHandshakeNullSession() {
ServletServerHttpRequest request = new ServletServerHttpRequest(new MockHttpServletRequest());
assertThat(this.interceptor.beforeHandshake(request, null, null, null)).isTrue();
verifyZeroInteractions(this.sessionRepository);
}
@Test
public void beforeHandshakeSession() throws Exception {
void beforeHandshakeSession() {
MockHttpServletRequest httpRequest = new MockHttpServletRequest();
HttpSession httpSession = httpRequest.getSession();
ServletServerHttpRequest request = new ServletServerHttpRequest(httpRequest);
Map<String, Object> attributes = new HashMap<>();
assertThat(this.interceptor.beforeHandshake(request, null, null, attributes))
.isTrue();
assertThat(this.interceptor.beforeHandshake(request, null, null, attributes)).isTrue();
assertThat(attributes.size()).isEqualTo(1);
assertThat(SessionRepositoryMessageInterceptor.getSessionId(attributes))
.isEqualTo(httpSession.getId());
assertThat(SessionRepositoryMessageInterceptor.getSessionId(attributes)).isEqualTo(httpSession.getId());
}
/**
* At the moment there is no need for afterHandshake to do anything.
*/
@Test
public void afterHandshakeDoesNothing() {
void afterHandshakeDoesNothing() {
this.interceptor.afterHandshake(null, null, null, null);
verifyZeroInteractions(this.sessionRepository);
}
private void setSessionId(String id) {
SessionRepositoryMessageInterceptor
.setSessionId(this.headers.getSessionAttributes(), id);
SessionRepositoryMessageInterceptor.setSessionId(this.headers.getSessionAttributes(), id);
}
private Message<?> createMessage() {
this.createMessage = MessageBuilder.createMessage("",
this.headers.getMessageHeaders());
this.createMessage = MessageBuilder.createMessage("", this.headers.getMessageHeaders());
return this.createMessage;
}
@@ -302,4 +286,5 @@ public class SessionRepositoryMessageInterceptorTests {
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 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.
@@ -25,7 +25,9 @@ import org.springframework.context.ApplicationListener;
import org.springframework.session.events.AbstractSessionEvent;
public class SessionEventRegistry implements ApplicationListener<AbstractSessionEvent> {
private Map<String, AbstractSessionEvent> events = new HashMap<>();
private ConcurrentMap<String, Object> locks = new ConcurrentHashMap<>();
@Override
@@ -48,14 +50,12 @@ public class SessionEventRegistry implements ApplicationListener<AbstractSession
}
@SuppressWarnings("unchecked")
public <E extends AbstractSessionEvent> E getEvent(String sessionId)
throws InterruptedException {
public <E extends AbstractSessionEvent> E getEvent(String sessionId) throws InterruptedException {
return (E) waitForEvent(sessionId);
}
@SuppressWarnings("unchecked")
private <E extends AbstractSessionEvent> E waitForEvent(String sessionId)
throws InterruptedException {
private <E extends AbstractSessionEvent> E waitForEvent(String sessionId) throws InterruptedException {
Object lock = getLock(sessionId);
synchronized (lock) {
if (!this.events.containsKey(sessionId)) {
@@ -68,4 +68,5 @@ public class SessionEventRegistry implements ApplicationListener<AbstractSession
private Object getLock(String sessionId) {
return this.locks.computeIfAbsent(sessionId, (k) -> new Object());
}
}

View File

@@ -35,8 +35,7 @@ public abstract class AbstractRedisITests {
@Bean
public GenericContainer redisContainer() {
GenericContainer redisContainer = new GenericContainer(DOCKER_IMAGE)
.withExposedPorts(6379);
GenericContainer redisContainer = new GenericContainer(DOCKER_IMAGE).withExposedPorts(6379);
redisContainer.start();
return redisContainer;
}
@@ -44,8 +43,7 @@ public abstract class AbstractRedisITests {
@Bean
public LettuceConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration(
redisContainer().getContainerIpAddress(),
redisContainer().getFirstMappedPort());
redisContainer().getContainerIpAddress(), redisContainer().getFirstMappedPort());
return new LettuceConnectionFactory(configuration);
}

View File

@@ -41,15 +41,14 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
@ExtendWith(SpringExtension.class)
@ContextConfiguration
@WebAppConfiguration
public class ReactiveRedisOperationsSessionRepositoryITests extends AbstractRedisITests {
class ReactiveRedisOperationsSessionRepositoryITests extends AbstractRedisITests {
@Autowired
private ReactiveRedisOperationsSessionRepository repository;
@Test
public void saves() throws InterruptedException {
ReactiveRedisOperationsSessionRepository.RedisSession toSave = this.repository
.createSession().block();
void saves() {
ReactiveRedisOperationsSessionRepository.RedisSession toSave = this.repository.createSession().block();
String expectedAttributeName = "a";
String expectedAttributeValue = "b";
@@ -70,9 +69,8 @@ public class ReactiveRedisOperationsSessionRepositoryITests extends AbstractRedi
}
@Test // gh-1399
public void saveMultipleTimes() {
ReactiveRedisOperationsSessionRepository.RedisSession session = this.repository
.createSession().block();
void saveMultipleTimes() {
ReactiveRedisOperationsSessionRepository.RedisSession session = this.repository.createSession().block();
session.setAttribute("attribute1", "value1");
Mono<Void> save1 = this.repository.save(session);
session.setAttribute("attribute2", "value2");
@@ -81,9 +79,8 @@ public class ReactiveRedisOperationsSessionRepositoryITests extends AbstractRedi
}
@Test
public void putAllOnSingleAttrDoesNotRemoveOld() {
ReactiveRedisOperationsSessionRepository.RedisSession toSave = this.repository
.createSession().block();
void putAllOnSingleAttrDoesNotRemoveOld() {
ReactiveRedisOperationsSessionRepository.RedisSession toSave = this.repository.createSession().block();
toSave.setAttribute("a", "b");
this.repository.save(toSave).block();
@@ -103,17 +100,16 @@ public class ReactiveRedisOperationsSessionRepositoryITests extends AbstractRedi
}
@Test
public void changeSessionIdWhenOnlyChangeId() throws Exception {
void changeSessionIdWhenOnlyChangeId() {
String attrName = "changeSessionId";
String attrValue = "changeSessionId-value";
ReactiveRedisOperationsSessionRepository.RedisSession toSave = this.repository
.createSession().block();
ReactiveRedisOperationsSessionRepository.RedisSession toSave = this.repository.createSession().block();
toSave.setAttribute(attrName, attrValue);
this.repository.save(toSave).block();
ReactiveRedisOperationsSessionRepository.RedisSession findById = this.repository
.findById(toSave.getId()).block();
ReactiveRedisOperationsSessionRepository.RedisSession findById = this.repository.findById(toSave.getId())
.block();
assertThat(findById.<String>getAttribute(attrName)).isEqualTo(attrValue);
@@ -127,14 +123,12 @@ public class ReactiveRedisOperationsSessionRepositoryITests extends AbstractRedi
ReactiveRedisOperationsSessionRepository.RedisSession findByChangeSessionId = this.repository
.findById(changeSessionId).block();
assertThat(findByChangeSessionId.<String>getAttribute(attrName))
.isEqualTo(attrValue);
assertThat(findByChangeSessionId.<String>getAttribute(attrName)).isEqualTo(attrValue);
}
@Test
public void changeSessionIdWhenChangeTwice() throws Exception {
ReactiveRedisOperationsSessionRepository.RedisSession toSave = this.repository
.createSession().block();
void changeSessionIdWhenChangeTwice() {
ReactiveRedisOperationsSessionRepository.RedisSession toSave = this.repository.createSession().block();
this.repository.save(toSave).block();
@@ -150,17 +144,16 @@ public class ReactiveRedisOperationsSessionRepositoryITests extends AbstractRedi
}
@Test
public void changeSessionIdWhenSetAttributeOnChangedSession() throws Exception {
void changeSessionIdWhenSetAttributeOnChangedSession() {
String attrName = "changeSessionId";
String attrValue = "changeSessionId-value";
ReactiveRedisOperationsSessionRepository.RedisSession toSave = this.repository
.createSession().block();
ReactiveRedisOperationsSessionRepository.RedisSession toSave = this.repository.createSession().block();
this.repository.save(toSave).block();
ReactiveRedisOperationsSessionRepository.RedisSession findById = this.repository
.findById(toSave.getId()).block();
ReactiveRedisOperationsSessionRepository.RedisSession findById = this.repository.findById(toSave.getId())
.block();
findById.setAttribute(attrName, attrValue);
@@ -174,14 +167,12 @@ public class ReactiveRedisOperationsSessionRepositoryITests extends AbstractRedi
ReactiveRedisOperationsSessionRepository.RedisSession findByChangeSessionId = this.repository
.findById(changeSessionId).block();
assertThat(findByChangeSessionId.<String>getAttribute(attrName))
.isEqualTo(attrValue);
assertThat(findByChangeSessionId.<String>getAttribute(attrName)).isEqualTo(attrValue);
}
@Test
public void changeSessionIdWhenHasNotSaved() throws Exception {
ReactiveRedisOperationsSessionRepository.RedisSession toSave = this.repository
.createSession().block();
void changeSessionIdWhenHasNotSaved() {
ReactiveRedisOperationsSessionRepository.RedisSession toSave = this.repository.createSession().block();
String originalId = toSave.getId();
toSave.changeSessionId();
@@ -193,9 +184,8 @@ public class ReactiveRedisOperationsSessionRepositoryITests extends AbstractRedi
// gh-954
@Test
public void changeSessionIdSaveTwice() {
ReactiveRedisOperationsSessionRepository.RedisSession toSave = this.repository
.createSession().block();
void changeSessionIdSaveTwice() {
ReactiveRedisOperationsSessionRepository.RedisSession toSave = this.repository.createSession().block();
String originalId = toSave.getId();
toSave.changeSessionId();
@@ -208,23 +198,20 @@ public class ReactiveRedisOperationsSessionRepositoryITests extends AbstractRedi
// gh-1111
@Test
public void changeSessionSaveOldSessionInstance() {
ReactiveRedisOperationsSessionRepository.RedisSession toSave = this.repository
.createSession().block();
void changeSessionSaveOldSessionInstance() {
ReactiveRedisOperationsSessionRepository.RedisSession toSave = this.repository.createSession().block();
String sessionId = toSave.getId();
this.repository.save(toSave).block();
ReactiveRedisOperationsSessionRepository.RedisSession session = this.repository
.findById(sessionId).block();
ReactiveRedisOperationsSessionRepository.RedisSession session = this.repository.findById(sessionId).block();
session.changeSessionId();
session.setLastAccessedTime(Instant.now());
this.repository.save(session).block();
toSave.setLastAccessedTime(Instant.now());
assertThatIllegalStateException()
.isThrownBy(() -> this.repository.save(toSave).block())
assertThatIllegalStateException().isThrownBy(() -> this.repository.save(toSave).block())
.withMessage("Session was invalidated");
assertThat(this.repository.findById(sessionId).block()).isNull();

View File

@@ -51,7 +51,7 @@ import static org.assertj.core.api.Assertions.assertThat;
@ExtendWith(SpringExtension.class)
@ContextConfiguration
@WebAppConfiguration
public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests {
class RedisOperationsSessionRepositoryITests extends AbstractRedisITests {
private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
@@ -71,34 +71,31 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
private SecurityContext changedContext;
@BeforeEach
public void setup() {
void setup() {
if (this.registry != null) {
this.registry.clear();
}
this.context = SecurityContextHolder.createEmptyContext();
this.context.setAuthentication(
new UsernamePasswordAuthenticationToken("username-" + UUID.randomUUID(),
"na", AuthorityUtils.createAuthorityList("ROLE_USER")));
this.context.setAuthentication(new UsernamePasswordAuthenticationToken("username-" + UUID.randomUUID(), "na",
AuthorityUtils.createAuthorityList("ROLE_USER")));
this.changedContext = SecurityContextHolder.createEmptyContext();
this.changedContext.setAuthentication(new UsernamePasswordAuthenticationToken(
"changedContext-" + UUID.randomUUID(), "na",
AuthorityUtils.createAuthorityList("ROLE_USER")));
"changedContext-" + UUID.randomUUID(), "na", AuthorityUtils.createAuthorityList("ROLE_USER")));
}
@Test
public void saves() throws InterruptedException {
void saves() throws InterruptedException {
String username = "saves-" + System.currentTimeMillis();
String usernameSessionKey = "RedisOperationsSessionRepositoryITests:index:"
+ INDEX_NAME + ":" + username;
String usernameSessionKey = "RedisOperationsSessionRepositoryITests:index:" + INDEX_NAME + ":" + username;
RedisSession toSave = this.repository.createSession();
String expectedAttributeName = "a";
String expectedAttributeValue = "b";
toSave.setAttribute(expectedAttributeName, expectedAttributeValue);
Authentication toSaveToken = new UsernamePasswordAuthenticationToken(username,
"password", AuthorityUtils.createAuthorityList("ROLE_USER"));
Authentication toSaveToken = new UsernamePasswordAuthenticationToken(username, "password",
AuthorityUtils.createAuthorityList("ROLE_USER"));
SecurityContext toSaveContext = SecurityContextHolder.createEmptyContext();
toSaveContext.setAuthentication(toSaveToken);
toSave.setAttribute(SPRING_SECURITY_CONTEXT, toSaveContext);
@@ -108,10 +105,8 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
this.repository.save(toSave);
assertThat(this.registry.receivedEvent(toSave.getId())).isTrue();
assertThat(this.registry.<SessionCreatedEvent>getEvent(toSave.getId()))
.isInstanceOf(SessionCreatedEvent.class);
assertThat(this.redis.boundSetOps(usernameSessionKey).members())
.contains(toSave.getId());
assertThat(this.registry.<SessionCreatedEvent>getEvent(toSave.getId())).isInstanceOf(SessionCreatedEvent.class);
assertThat(this.redis.boundSetOps(usernameSessionKey).members()).contains(toSave.getId());
Session session = this.repository.findById(toSave.getId());
@@ -127,16 +122,14 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
assertThat(this.repository.findById(toSave.getId())).isNull();
assertThat(this.registry.<SessionDestroyedEvent>getEvent(toSave.getId()))
.isInstanceOf(SessionDestroyedEvent.class);
assertThat(this.redis.boundSetOps(usernameSessionKey).members())
.doesNotContain(toSave.getId());
assertThat(this.redis.boundSetOps(usernameSessionKey).members()).doesNotContain(toSave.getId());
assertThat(this.registry.getEvent(toSave.getId()).getSession()
.<String>getAttribute(expectedAttributeName))
assertThat(this.registry.getEvent(toSave.getId()).getSession().<String>getAttribute(expectedAttributeName))
.isEqualTo(expectedAttributeValue);
}
@Test
public void putAllOnSingleAttrDoesNotRemoveOld() {
void putAllOnSingleAttrDoesNotRemoveOld() {
RedisSession toSave = this.repository.createSession();
toSave.setAttribute("a", "b");
@@ -157,15 +150,15 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
}
@Test
public void findByPrincipalName() throws Exception {
void findByPrincipalName() throws Exception {
String principalName = "findByPrincipalName" + UUID.randomUUID();
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(INDEX_NAME, principalName);
this.repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalName);
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
@@ -173,7 +166,28 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
this.repository.deleteById(toSave.getId());
assertThat(this.registry.receivedEvent(toSave.getId())).isTrue();
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
assertThat(findByPrincipalName).hasSize(0);
assertThat(findByPrincipalName.keySet()).doesNotContain(toSave.getId());
}
@Test
void findByPrincipalNameExpireRemovesIndex() {
String principalName = "findByPrincipalNameExpireRemovesIndex" + UUID.randomUUID();
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(INDEX_NAME, principalName);
this.repository.save(toSave);
String body = "RedisOperationsSessionRepositoryITests:sessions:expires:" + toSave.getId();
String channel = "__keyevent@0__:expired";
DefaultMessage message = new DefaultMessage(channel.getBytes(StandardCharsets.UTF_8),
body.getBytes(StandardCharsets.UTF_8));
byte[] pattern = new byte[] {};
this.repository.onMessage(message, pattern);
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalName);
assertThat(findByPrincipalName).hasSize(0);
@@ -181,34 +195,8 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
}
@Test
public void findByPrincipalNameExpireRemovesIndex() throws Exception {
String principalName = "findByPrincipalNameExpireRemovesIndex"
+ UUID.randomUUID();
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(INDEX_NAME, principalName);
this.repository.save(toSave);
String body = "RedisOperationsSessionRepositoryITests:sessions:expires:"
+ toSave.getId();
String channel = "__keyevent@0__:expired";
DefaultMessage message = new DefaultMessage(
channel.getBytes(StandardCharsets.UTF_8),
body.getBytes(StandardCharsets.UTF_8));
byte[] pattern = new byte[] {};
this.repository.onMessage(message, pattern);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
assertThat(findByPrincipalName).hasSize(0);
assertThat(findByPrincipalName.keySet()).doesNotContain(toSave.getId());
}
@Test
public void findByPrincipalNameNoPrincipalNameChange() throws Exception {
String principalName = "findByPrincipalNameNoPrincipalNameChange"
+ UUID.randomUUID();
void findByPrincipalNameNoPrincipalNameChange() {
String principalName = "findByPrincipalNameNoPrincipalNameChange" + UUID.randomUUID();
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(INDEX_NAME, principalName);
@@ -217,17 +205,16 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
toSave.setAttribute("other", "value");
this.repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalName);
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
}
@Test
public void findByPrincipalNameNoPrincipalNameChangeReload() throws Exception {
String principalName = "findByPrincipalNameNoPrincipalNameChangeReload"
+ UUID.randomUUID();
void findByPrincipalNameNoPrincipalNameChangeReload() {
String principalName = "findByPrincipalNameNoPrincipalNameChangeReload" + UUID.randomUUID();
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(INDEX_NAME, principalName);
@@ -238,15 +225,15 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
toSave.setAttribute("other", "value");
this.repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalName);
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
}
@Test
public void findByDeletedPrincipalName() throws Exception {
void findByDeletedPrincipalName() {
String principalName = "findByDeletedPrincipalName" + UUID.randomUUID();
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(INDEX_NAME, principalName);
@@ -256,14 +243,14 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
toSave.setAttribute(INDEX_NAME, null);
this.repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalName);
assertThat(findByPrincipalName).isEmpty();
}
@Test
public void findByChangedPrincipalName() throws Exception {
void findByChangedPrincipalName() {
String principalName = "findByChangedPrincipalName" + UUID.randomUUID();
String principalNameChanged = "findByChangedPrincipalName" + UUID.randomUUID();
RedisSession toSave = this.repository.createSession();
@@ -274,19 +261,18 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
toSave.setAttribute(INDEX_NAME, principalNameChanged);
this.repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalName);
assertThat(findByPrincipalName).isEmpty();
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalNameChanged);
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME, principalNameChanged);
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
}
@Test
public void findByDeletedPrincipalNameReload() throws Exception {
void findByDeletedPrincipalNameReload() {
String principalName = "findByDeletedPrincipalName" + UUID.randomUUID();
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(INDEX_NAME, principalName);
@@ -297,14 +283,14 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
getSession.setAttribute(INDEX_NAME, null);
this.repository.save(getSession);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalName);
assertThat(findByPrincipalName).isEmpty();
}
@Test
public void findByChangedPrincipalNameReload() throws Exception {
void findByChangedPrincipalNameReload() {
String principalName = "findByChangedPrincipalName" + UUID.randomUUID();
String principalNameChanged = "findByChangedPrincipalName" + UUID.randomUUID();
RedisSession toSave = this.repository.createSession();
@@ -317,26 +303,25 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
getSession.setAttribute(INDEX_NAME, principalNameChanged);
this.repository.save(getSession);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, principalName);
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalName);
assertThat(findByPrincipalName).isEmpty();
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
principalNameChanged);
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME, principalNameChanged);
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
}
@Test
public void findBySecurityPrincipalName() throws Exception {
void findBySecurityPrincipalName() throws Exception {
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
this.repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
getSecurityName());
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
@@ -344,7 +329,27 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
this.repository.deleteById(toSave.getId());
assertThat(this.registry.receivedEvent(toSave.getId())).isTrue();
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
assertThat(findByPrincipalName).hasSize(0);
assertThat(findByPrincipalName.keySet()).doesNotContain(toSave.getId());
}
@Test
void findBySecurityPrincipalNameExpireRemovesIndex() {
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
this.repository.save(toSave);
String body = "RedisOperationsSessionRepositoryITests:sessions:expires:" + toSave.getId();
String channel = "__keyevent@0__:expired";
DefaultMessage message = new DefaultMessage(channel.getBytes(StandardCharsets.UTF_8),
body.getBytes(StandardCharsets.UTF_8));
byte[] pattern = new byte[] {};
this.repository.onMessage(message, pattern);
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
getSecurityName());
assertThat(findByPrincipalName).hasSize(0);
@@ -352,30 +357,7 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
}
@Test
public void findBySecurityPrincipalNameExpireRemovesIndex() throws Exception {
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
this.repository.save(toSave);
String body = "RedisOperationsSessionRepositoryITests:sessions:expires:"
+ toSave.getId();
String channel = "__keyevent@0__:expired";
DefaultMessage message = new DefaultMessage(
channel.getBytes(StandardCharsets.UTF_8),
body.getBytes(StandardCharsets.UTF_8));
byte[] pattern = new byte[] {};
this.repository.onMessage(message, pattern);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
assertThat(findByPrincipalName).hasSize(0);
assertThat(findByPrincipalName.keySet()).doesNotContain(toSave.getId());
}
@Test
public void findByPrincipalNameNoSecurityPrincipalNameChange() throws Exception {
void findByPrincipalNameNoSecurityPrincipalNameChange() {
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
@@ -384,16 +366,15 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
toSave.setAttribute("other", "value");
this.repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
getSecurityName());
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
}
@Test
public void findByPrincipalNameNoSecurityPrincipalNameChangeReload()
throws Exception {
void findByPrincipalNameNoSecurityPrincipalNameChangeReload() {
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
@@ -404,15 +385,15 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
toSave.setAttribute("other", "value");
this.repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
getSecurityName());
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
}
@Test
public void findByDeletedSecurityPrincipalName() throws Exception {
void findByDeletedSecurityPrincipalName() {
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
@@ -421,14 +402,14 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
toSave.setAttribute(SPRING_SECURITY_CONTEXT, null);
this.repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
getSecurityName());
assertThat(findByPrincipalName).isEmpty();
}
@Test
public void findByChangedSecurityPrincipalName() throws Exception {
void findByChangedSecurityPrincipalName() {
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
@@ -437,19 +418,18 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.changedContext);
this.repository.save(toSave);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
getSecurityName());
assertThat(findByPrincipalName).isEmpty();
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
getChangedSecurityName());
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME, getChangedSecurityName());
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
}
@Test
public void findByDeletedSecurityPrincipalNameReload() throws Exception {
void findByDeletedSecurityPrincipalNameReload() {
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
@@ -459,14 +439,14 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
getSession.setAttribute(INDEX_NAME, null);
this.repository.save(getSession);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, getChangedSecurityName());
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
getChangedSecurityName());
assertThat(findByPrincipalName).isEmpty();
}
@Test
public void findByChangedSecurityPrincipalNameReload() throws Exception {
void findByChangedSecurityPrincipalNameReload() {
RedisSession toSave = this.repository.createSession();
toSave.setAttribute(SPRING_SECURITY_CONTEXT, this.context);
@@ -477,19 +457,18 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
getSession.setAttribute(SPRING_SECURITY_CONTEXT, this.changedContext);
this.repository.save(getSession);
Map<String, RedisSession> findByPrincipalName = this.repository
.findByIndexNameAndIndexValue(INDEX_NAME, getSecurityName());
Map<String, RedisSession> findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
getSecurityName());
assertThat(findByPrincipalName).isEmpty();
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME,
getChangedSecurityName());
findByPrincipalName = this.repository.findByIndexNameAndIndexValue(INDEX_NAME, getChangedSecurityName());
assertThat(findByPrincipalName).hasSize(1);
assertThat(findByPrincipalName.keySet()).containsOnly(toSave.getId());
}
@Test
public void changeSessionIdWhenOnlyChangeId() throws Exception {
void changeSessionIdWhenOnlyChangeId() {
String attrName = "changeSessionId";
String attrValue = "changeSessionId-value";
RedisSession toSave = this.repository.createSession();
@@ -514,7 +493,7 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
}
@Test
public void changeSessionIdWhenChangeTwice() throws Exception {
void changeSessionIdWhenChangeTwice() {
RedisSession toSave = this.repository.createSession();
this.repository.save(toSave);
@@ -531,7 +510,7 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
}
@Test
public void changeSessionIdWhenSetAttributeOnChangedSession() throws Exception {
void changeSessionIdWhenSetAttributeOnChangedSession() {
String attrName = "changeSessionId";
String attrValue = "changeSessionId-value";
@@ -556,7 +535,7 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
}
@Test
public void changeSessionIdWhenHasNotSaved() throws Exception {
void changeSessionIdWhenHasNotSaved() {
String attrName = "changeSessionId";
String attrValue = "changeSessionId-value";
@@ -572,7 +551,7 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
// gh-962
@Test
public void changeSessionIdSaveTwice() {
void changeSessionIdSaveTwice() {
RedisSession toSave = this.repository.createSession();
String originalId = toSave.getId();
toSave.changeSessionId();
@@ -586,7 +565,7 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
// gh-1137
@Test
public void changeSessionIdWhenSessionIsDeleted() {
void changeSessionIdWhenSessionIsDeleted() {
RedisSession toSave = this.repository.createSession();
String sessionId = toSave.getId();
this.repository.save(toSave);
@@ -601,7 +580,7 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
}
@Test // gh-1270
public void changeSessionIdSaveConcurrently() {
void changeSessionIdSaveConcurrently() {
RedisSession toSave = this.repository.createSession();
String originalId = toSave.getId();
this.repository.save(toSave);

View File

@@ -56,10 +56,9 @@ class SimpleRedisOperationsSessionRepositoryITests extends AbstractRedisITests {
@Test
void save_NewSession_ShouldSaveSession() {
RedisSession session = createAndSaveSession(Instant.now());
assertThat(session.getMaxInactiveInterval()).isEqualTo(
Duration.ofSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS));
assertThat(session.getAttributeNames())
.isEqualTo(Collections.singleton("attribute1"));
assertThat(session.getMaxInactiveInterval())
.isEqualTo(Duration.ofSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS));
assertThat(session.getAttributeNames()).isEqualTo(Collections.singleton("attribute1"));
assertThat(session.<String>getAttribute("attribute1")).isEqualTo("value1");
}
@@ -72,8 +71,7 @@ class SimpleRedisOperationsSessionRepositoryITests extends AbstractRedisITests {
void save_DeletedSession_ShouldThrowException() {
RedisSession session = createAndSaveSession(Instant.now());
this.sessionRepository.deleteById(session.getId());
assertThatIllegalStateException()
.isThrownBy(() -> this.sessionRepository.save(session))
assertThatIllegalStateException().isThrownBy(() -> this.sessionRepository.save(session))
.withMessage("Session was invalidated");
}
@@ -164,8 +162,7 @@ class SimpleRedisOperationsSessionRepositoryITests extends AbstractRedisITests {
this.sessionRepository.deleteById(originalSessionId);
updateSession(session, Instant.now(), "attribute1", "value1");
String newSessionId = session.changeSessionId();
assertThatIllegalStateException()
.isThrownBy(() -> this.sessionRepository.save(session))
assertThatIllegalStateException().isThrownBy(() -> this.sessionRepository.save(session))
.withMessage("Session was invalidated");
assertThat(this.sessionRepository.findById(newSessionId)).isNull();
assertThat(this.sessionRepository.findById(originalSessionId)).isNull();
@@ -182,8 +179,7 @@ class SimpleRedisOperationsSessionRepositoryITests extends AbstractRedisITests {
this.sessionRepository.save(copy1);
updateSession(copy2, now.plusSeconds(2L), "attribute3", "value3");
String newSessionId2 = copy2.changeSessionId();
assertThatIllegalStateException()
.isThrownBy(() -> this.sessionRepository.save(copy2))
assertThatIllegalStateException().isThrownBy(() -> this.sessionRepository.save(copy2))
.withMessage("Session was invalidated");
assertThat(this.sessionRepository.findById(newSessionId1)).isNotNull();
assertThat(this.sessionRepository.findById(newSessionId2)).isNull();
@@ -220,8 +216,8 @@ class SimpleRedisOperationsSessionRepositoryITests extends AbstractRedisITests {
return this.sessionRepository.findById(session.getId());
}
private static void updateSession(RedisSession session, Instant lastAccessedTime,
String attributeName, Object attributeValue) {
private static void updateSession(RedisSession session, Instant lastAccessedTime, String attributeName,
Object attributeValue) {
session.setLastAccessedTime(lastAccessedTime);
session.setAttribute(attributeName, attributeValue);
}
@@ -231,8 +227,7 @@ class SimpleRedisOperationsSessionRepositoryITests extends AbstractRedisITests {
static class Config extends BaseConfig {
@Bean
public SimpleRedisOperationsSessionRepository sessionRepository(
RedisConnectionFactory redisConnectionFactory) {
public SimpleRedisOperationsSessionRepository sessionRepository(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.afterPropertiesSet();

View File

@@ -44,8 +44,7 @@ import static org.assertj.core.api.Assertions.assertThat;
@ExtendWith(SpringExtension.class)
@ContextConfiguration
@WebAppConfiguration
public class EnableRedisHttpSessionExpireSessionDestroyedTests<S extends Session>
extends AbstractRedisITests {
class EnableRedisHttpSessionExpireSessionDestroyedTests<S extends Session> extends AbstractRedisITests {
@Autowired
private SessionRepository<S> repository;
@@ -56,16 +55,16 @@ public class EnableRedisHttpSessionExpireSessionDestroyedTests<S extends Session
private final Object lock = new Object();
@BeforeEach
public void setup() {
void setup() {
this.registry.setLock(this.lock);
}
@Test
public void expireFiresSessionExpiredEvent() throws InterruptedException {
void expireFiresSessionExpiredEvent() throws InterruptedException {
S toSave = this.repository.createSession();
toSave.setAttribute("a", "b");
Authentication toSaveToken = new UsernamePasswordAuthenticationToken("user",
"password", AuthorityUtils.createAuthorityList("ROLE_USER"));
Authentication toSaveToken = new UsernamePasswordAuthenticationToken("user", "password",
AuthorityUtils.createAuthorityList("ROLE_USER"));
SecurityContext toSaveContext = SecurityContextHolder.createEmptyContext();
toSaveContext.setAuthentication(toSaveToken);
toSave.setAttribute("SPRING_SECURITY_CONTEXT", toSaveContext);
@@ -89,9 +88,10 @@ public class EnableRedisHttpSessionExpireSessionDestroyedTests<S extends Session
assertThat(this.registry.receivedEvent()).isTrue();
}
static class SessionExpiredEventRegistry
implements ApplicationListener<SessionExpiredEvent> {
static class SessionExpiredEventRegistry implements ApplicationListener<SessionExpiredEvent> {
private boolean receivedEvent;
private Object lock;
@Override
@@ -109,6 +109,7 @@ public class EnableRedisHttpSessionExpireSessionDestroyedTests<S extends Session
public void setLock(Object lock) {
this.lock = lock;
}
}
@Configuration

View File

@@ -21,10 +21,10 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.session.FlushMode;
import org.springframework.session.Session;
import org.springframework.session.SessionRepository;
import org.springframework.session.data.redis.AbstractRedisITests;
import org.springframework.session.data.redis.RedisFlushMode;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@@ -35,14 +35,13 @@ import static org.assertj.core.api.Assertions.assertThat;
@ExtendWith(SpringExtension.class)
@ContextConfiguration
@WebAppConfiguration
public class RedisOperationsSessionRepositoryFlushImmediatelyITests<S extends Session>
extends AbstractRedisITests {
class RedisOperationsSessionRepositoryFlushImmediatelyITests<S extends Session> extends AbstractRedisITests {
@Autowired
private SessionRepository<S> sessionRepository;
@Test
public void savesOnCreate() throws InterruptedException {
void savesOnCreate() {
S created = this.sessionRepository.createSession();
S getSession = this.sessionRepository.findById(created.getId());
@@ -51,7 +50,7 @@ public class RedisOperationsSessionRepositoryFlushImmediatelyITests<S extends Se
}
@Configuration
@EnableRedisHttpSession(redisFlushMode = RedisFlushMode.IMMEDIATE)
@EnableRedisHttpSession(flushMode = FlushMode.IMMEDIATE)
static class RedisHttpSessionConfig extends BaseConfig {
}

View File

@@ -45,7 +45,7 @@ import static org.assertj.core.api.Assertions.assertThat;
@ExtendWith(SpringExtension.class)
@ContextConfiguration
@WebAppConfiguration
public class RedisListenerContainerTaskExecutorITests extends AbstractRedisITests {
class RedisListenerContainerTaskExecutorITests extends AbstractRedisITests {
@Autowired
private SessionTaskExecutor executor;
@@ -54,10 +54,9 @@ public class RedisListenerContainerTaskExecutorITests extends AbstractRedisITest
private RedisOperations<Object, Object> redis;
@Test
public void testRedisDelEventsAreDispatchedInSessionTaskExecutor()
throws InterruptedException {
BoundSetOperations<Object, Object> ops = this.redis.boundSetOps(
"spring:session:RedisListenerContainerTaskExecutorITests:expirations:dummy");
void testRedisDelEventsAreDispatchedInSessionTaskExecutor() throws InterruptedException {
BoundSetOperations<Object, Object> ops = this.redis
.boundSetOps("spring:session:RedisListenerContainerTaskExecutorITests:expirations:dummy");
ops.add("value");
ops.remove("value");
assertThat(this.executor.taskDispatched()).isTrue();
@@ -65,7 +64,8 @@ public class RedisListenerContainerTaskExecutorITests extends AbstractRedisITest
}
static class SessionTaskExecutor implements TaskExecutor {
private Object lock = new Object();
private final Object lock = new Object();
private final Executor executor;
@@ -97,6 +97,7 @@ public class RedisListenerContainerTaskExecutorITests extends AbstractRedisITest
}
return (this.taskDispatched != null) ? this.taskDispatched : Boolean.FALSE;
}
}
@Configuration

View File

@@ -28,6 +28,7 @@ import reactor.core.publisher.Mono;
import org.springframework.data.redis.core.ReactiveRedisOperations;
import org.springframework.session.MapSession;
import org.springframework.session.ReactiveSessionRepository;
import org.springframework.session.SaveMode;
import org.springframework.session.Session;
import org.springframework.util.Assert;
@@ -38,8 +39,8 @@ import org.springframework.util.Assert;
* @author Vedran Pavic
* @since 2.0
*/
public class ReactiveRedisOperationsSessionRepository implements
ReactiveSessionRepository<ReactiveRedisOperationsSessionRepository.RedisSession> {
public class ReactiveRedisOperationsSessionRepository
implements ReactiveSessionRepository<ReactiveRedisOperationsSessionRepository.RedisSession> {
/**
* The default namespace for each key and channel in Redis used by Spring Session.
@@ -59,10 +60,9 @@ public class ReactiveRedisOperationsSessionRepository implements
*/
private Integer defaultMaxInactiveInterval;
private RedisFlushMode redisFlushMode = RedisFlushMode.ON_SAVE;
private SaveMode saveMode = SaveMode.ON_SET_ATTRIBUTE;
public ReactiveRedisOperationsSessionRepository(
ReactiveRedisOperations<String, Object> sessionRedisOperations) {
public ReactiveRedisOperationsSessionRepository(ReactiveRedisOperations<String, Object> sessionRedisOperations) {
Assert.notNull(sessionRedisOperations, "sessionRedisOperations cannot be null");
this.sessionRedisOperations = sessionRedisOperations;
}
@@ -76,7 +76,6 @@ public class ReactiveRedisOperationsSessionRepository implements
* Sets the maximum inactive interval in seconds between requests before newly created
* sessions will be invalidated. A negative time indicates that the session will never
* timeout. The default is 1800 (30 minutes).
*
* @param defaultMaxInactiveInterval the number of seconds that the {@link Session}
* should be kept alive between client requests.
*/
@@ -86,12 +85,21 @@ public class ReactiveRedisOperationsSessionRepository implements
/**
* Sets the redis flush mode. Default flush mode is {@link RedisFlushMode#ON_SAVE}.
*
* @param redisFlushMode the new redis flush mode
* @deprecated since 2.2.0 as support {@code IMMEDIATE} is removed
*/
@Deprecated
public void setRedisFlushMode(RedisFlushMode redisFlushMode) {
Assert.notNull(redisFlushMode, "redisFlushMode cannot be null");
this.redisFlushMode = redisFlushMode;
}
/**
* Set the save mode.
* @param saveMode the save mode
*/
public void setSaveMode(SaveMode saveMode) {
Assert.notNull(saveMode, "saveMode must not be null");
this.saveMode = saveMode;
}
/**
@@ -106,13 +114,11 @@ public class ReactiveRedisOperationsSessionRepository implements
@Override
public Mono<RedisSession> createSession() {
return Mono.defer(() -> {
RedisSession session = new RedisSession();
MapSession cached = new MapSession();
if (this.defaultMaxInactiveInterval != null) {
session.setMaxInactiveInterval(
Duration.ofSeconds(this.defaultMaxInactiveInterval));
cached.setMaxInactiveInterval(Duration.ofSeconds(this.defaultMaxInactiveInterval));
}
RedisSession session = new RedisSession(cached, true);
return Mono.just(session);
});
}
@@ -122,12 +128,9 @@ public class ReactiveRedisOperationsSessionRepository implements
if (session.isNew) {
return session.save();
}
String sessionKey = getSessionKey(
session.hasChangedSessionId() ? session.originalSessionId
: session.getId());
return this.sessionRedisOperations.hasKey(sessionKey).flatMap((exists) -> exists
? session.save()
: Mono.error(new IllegalStateException("Session was invalidated")));
String sessionKey = getSessionKey(session.hasChangedSessionId() ? session.originalSessionId : session.getId());
return this.sessionRedisOperations.hasKey(sessionKey).flatMap(
(exists) -> exists ? session.save() : Mono.error(new IllegalStateException("Session was invalidated")));
}
@Override
@@ -140,7 +143,7 @@ public class ReactiveRedisOperationsSessionRepository implements
.filter((map) -> !map.isEmpty())
.map(new RedisSessionMapper(id))
.filter((session) -> !session.isExpired())
.map(RedisSession::new)
.map((session) -> new RedisSession(session, false))
.switchIfEmpty(Mono.defer(() -> deleteById(id).then(Mono.empty())));
// @formatter:on
}
@@ -176,32 +179,20 @@ public class ReactiveRedisOperationsSessionRepository implements
private String originalSessionId;
/**
* Creates a new instance ensuring to mark all of the new attributes to be
* persisted in the next save operation.
*/
RedisSession() {
this(new MapSession());
this.delta.put(RedisSessionMapper.CREATION_TIME_KEY,
getCreationTime().toEpochMilli());
this.delta.put(RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY,
(int) getMaxInactiveInterval().getSeconds());
this.delta.put(RedisSessionMapper.LAST_ACCESSED_TIME_KEY,
getLastAccessedTime().toEpochMilli());
this.isNew = true;
this.flushImmediateIfNecessary();
}
/**
* Creates a new instance from the provided {@link MapSession}.
*
* @param mapSession the {@link MapSession} that represents the persisted session
* that was retrieved. Cannot be null.
*/
RedisSession(MapSession mapSession) {
Assert.notNull(mapSession, "mapSession cannot be null");
this.cached = mapSession;
this.originalSessionId = mapSession.getId();
RedisSession(MapSession cached, boolean isNew) {
this.cached = cached;
this.isNew = isNew;
this.originalSessionId = cached.getId();
if (this.isNew) {
this.delta.put(RedisSessionMapper.CREATION_TIME_KEY, cached.getCreationTime().toEpochMilli());
this.delta.put(RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY,
(int) cached.getMaxInactiveInterval().getSeconds());
this.delta.put(RedisSessionMapper.LAST_ACCESSED_TIME_KEY, cached.getLastAccessedTime().toEpochMilli());
}
if (this.isNew || (ReactiveRedisOperationsSessionRepository.this.saveMode == SaveMode.ALWAYS)) {
getAttributeNames().forEach((attributeName) -> this.delta.put(getAttributeKey(attributeName),
cached.getAttribute(attributeName)));
}
}
@Override
@@ -216,7 +207,12 @@ public class ReactiveRedisOperationsSessionRepository implements
@Override
public <T> T getAttribute(String attributeName) {
return this.cached.getAttribute(attributeName);
T attributeValue = this.cached.getAttribute(attributeName);
if (attributeValue != null
&& ReactiveRedisOperationsSessionRepository.this.saveMode.equals(SaveMode.ON_GET_ATTRIBUTE)) {
this.delta.put(getAttributeKey(attributeName), attributeValue);
}
return attributeValue;
}
@Override
@@ -227,13 +223,13 @@ public class ReactiveRedisOperationsSessionRepository implements
@Override
public void setAttribute(String attributeName, Object attributeValue) {
this.cached.setAttribute(attributeName, attributeValue);
putAndFlush(getAttributeKey(attributeName), attributeValue);
this.delta.put(getAttributeKey(attributeName), attributeValue);
}
@Override
public void removeAttribute(String attributeName) {
this.cached.removeAttribute(attributeName);
putAndFlush(getAttributeKey(attributeName), null);
this.delta.put(getAttributeKey(attributeName), null);
}
@Override
@@ -244,8 +240,7 @@ public class ReactiveRedisOperationsSessionRepository implements
@Override
public void setLastAccessedTime(Instant lastAccessedTime) {
this.cached.setLastAccessedTime(lastAccessedTime);
putAndFlush(RedisSessionMapper.LAST_ACCESSED_TIME_KEY,
getLastAccessedTime().toEpochMilli());
this.delta.put(RedisSessionMapper.LAST_ACCESSED_TIME_KEY, getLastAccessedTime().toEpochMilli());
}
@Override
@@ -256,8 +251,7 @@ public class ReactiveRedisOperationsSessionRepository implements
@Override
public void setMaxInactiveInterval(Duration interval) {
this.cached.setMaxInactiveInterval(interval);
putAndFlush(RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY,
(int) getMaxInactiveInterval().getSeconds());
this.delta.put(RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY, (int) getMaxInactiveInterval().getSeconds());
}
@Override
@@ -274,20 +268,8 @@ public class ReactiveRedisOperationsSessionRepository implements
return !getId().equals(this.originalSessionId);
}
private void flushImmediateIfNecessary() {
if (ReactiveRedisOperationsSessionRepository.this.redisFlushMode == RedisFlushMode.IMMEDIATE) {
save();
}
}
private void putAndFlush(String a, Object v) {
this.delta.put(a, v);
flushImmediateIfNecessary();
}
private Mono<Void> save() {
return Mono.defer(() -> saveChangeSessionId().then(saveDelta())
.doOnSuccess((aVoid) -> this.isNew = false));
return Mono.defer(() -> saveChangeSessionId().then(saveDelta()).doOnSuccess((aVoid) -> this.isNew = false));
}
private Mono<Void> saveDelta() {
@@ -296,8 +278,8 @@ public class ReactiveRedisOperationsSessionRepository implements
}
String sessionKey = getSessionKey(getId());
Mono<Boolean> update = ReactiveRedisOperationsSessionRepository.this.sessionRedisOperations
.opsForHash().putAll(sessionKey, new HashMap<>(this.delta));
Mono<Boolean> update = ReactiveRedisOperationsSessionRepository.this.sessionRedisOperations.opsForHash()
.putAll(sessionKey, new HashMap<>(this.delta));
Mono<Boolean> setTtl = ReactiveRedisOperationsSessionRepository.this.sessionRedisOperations
.expire(sessionKey, getMaxInactiveInterval());

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2019 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.
@@ -16,6 +16,7 @@
package org.springframework.session.data.redis;
import org.springframework.session.FlushMode;
import org.springframework.session.SessionRepository;
/**
@@ -23,14 +24,17 @@ import org.springframework.session.SessionRepository;
*
* @author Rob Winch
* @since 1.1
* @deprecated since 2.2.0 in favor of {@link FlushMode}
*/
@Deprecated
public enum RedisFlushMode {
/**
* Only writes to Redis when
* {@link SessionRepository#save(org.springframework.session.Session)} is invoked. In
* a web environment this is typically done as soon as the HTTP response is committed.
*/
ON_SAVE,
ON_SAVE(FlushMode.ON_SAVE),
/**
* Writes to Redis as soon as possible. For example
@@ -38,5 +42,16 @@ public enum RedisFlushMode {
* example is that setting an attribute on the session will also write to Redis
* immediately.
*/
IMMEDIATE
IMMEDIATE(FlushMode.IMMEDIATE);
private final FlushMode flushMode;
RedisFlushMode(FlushMode flushMode) {
this.flushMode = flushMode;
}
public FlushMode getFlushMode() {
return this.flushMode;
}
}

View File

@@ -36,10 +36,13 @@ import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.session.DelegatingIndexResolver;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.FlushMode;
import org.springframework.session.IndexResolver;
import org.springframework.session.MapSession;
import org.springframework.session.PrincipalNameIndexResolver;
import org.springframework.session.SaveMode;
import org.springframework.session.Session;
import org.springframework.session.events.SessionCreatedEvent;
import org.springframework.session.events.SessionDeletedEvent;
@@ -72,8 +75,8 @@ import org.springframework.util.Assert;
*
* <p>
* For additional information on how to create a RedisTemplate, refer to the
* <a href = "https://docs.spring.io/spring-data/data-redis/docs/current/reference/html/" >
* Spring Data Redis Reference</a>.
* <a href = "https://docs.spring.io/spring-data/data-redis/docs/current/reference/html/"
* > Spring Data Redis Reference</a>.
* </p>
*
* <h2>Storage Details</h2>
@@ -123,10 +126,12 @@ import org.springframework.util.Assert;
* <h3>Optimized Writes</h3>
*
* <p>
* The {@link org.springframework.session.data.redis.RedisOperationsSessionRepository.RedisSession} keeps track of the properties that have changed and only
* updates those. This means if an attribute is written once and read many times we only
* need to write that attribute once. For example, assume the session attribute
* "sessionAttr2" from earlier was updated. The following would be executed upon saving:
* The
* {@link org.springframework.session.data.redis.RedisOperationsSessionRepository.RedisSession}
* keeps track of the properties that have changed and only updates those. This means if
* an attribute is written once and read many times we only need to write that attribute
* once. For example, assume the session attribute "sessionAttr2" from earlier was
* updated. The following would be executed upon saving:
* </p>
*
* <pre>
@@ -170,15 +175,14 @@ import org.springframework.util.Assert;
* </p>
*
* <p>
* <b>NOTE:</b> The {@link #findById(String)} method ensures that no expired sessions
* will be returned. This means there is no need to check the expiration before using a
* session
* <b>NOTE:</b> The {@link #findById(String)} method ensures that no expired sessions will
* be returned. This means there is no need to check the expiration before using a session
* </p>
*
* <p>
* Spring Session relies on the expired and delete
* <a href="https://redis.io/topics/notifications">keyspace notifications</a> from Redis to
* fire a SessionDestroyedEvent. It is the SessionDestroyedEvent that ensures resources
* <a href="https://redis.io/topics/notifications">keyspace notifications</a> from Redis
* to fire a SessionDestroyedEvent. It is the SessionDestroyedEvent that ensures resources
* associated with the Session are cleaned up. For example, when using Spring Session's
* WebSocket support the Redis expired or delete event is what triggers any WebSocket
* connections associated with the session to be closed.
@@ -244,16 +248,13 @@ import org.springframework.util.Assert;
* @author Vedran Pavic
* @since 1.0
*/
public class RedisOperationsSessionRepository implements
FindByIndexNameSessionRepository<RedisOperationsSessionRepository.RedisSession>,
MessageListener {
private static final Log logger = LogFactory
.getLog(RedisOperationsSessionRepository.class);
public class RedisOperationsSessionRepository
implements FindByIndexNameSessionRepository<RedisOperationsSessionRepository.RedisSession>, MessageListener {
private static final Log logger = LogFactory.getLog(RedisOperationsSessionRepository.class);
private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
static PrincipalNameResolver PRINCIPAL_NAME_RESOLVER = new PrincipalNameResolver();
/**
* The default Redis database used by Spring Session.
*/
@@ -281,14 +282,9 @@ public class RedisOperationsSessionRepository implements
private final RedisSessionExpirationPolicy expirationPolicy;
private ApplicationEventPublisher eventPublisher = new ApplicationEventPublisher() {
@Override
public void publishEvent(ApplicationEvent event) {
}
private final IndexResolver<RedisSession> indexResolver;
@Override
public void publishEvent(Object event) {
}
private ApplicationEventPublisher eventPublisher = (event) -> {
};
/**
@@ -299,20 +295,21 @@ public class RedisOperationsSessionRepository implements
private RedisSerializer<Object> defaultSerializer = new JdkSerializationRedisSerializer();
private RedisFlushMode redisFlushMode = RedisFlushMode.ON_SAVE;
private FlushMode flushMode = FlushMode.ON_SAVE;
private SaveMode saveMode = SaveMode.ON_SET_ATTRIBUTE;
/**
* Creates a new instance. For an example, refer to the class level javadoc.
*
* @param sessionRedisOperations the {@link RedisOperations} to use for managing the
* sessions. Cannot be null.
*/
public RedisOperationsSessionRepository(
RedisOperations<Object, Object> sessionRedisOperations) {
public RedisOperationsSessionRepository(RedisOperations<Object, Object> sessionRedisOperations) {
Assert.notNull(sessionRedisOperations, "sessionRedisOperations cannot be null");
this.sessionRedisOperations = sessionRedisOperations;
this.expirationPolicy = new RedisSessionExpirationPolicy(sessionRedisOperations,
this::getExpirationsKey, this::getSessionKey);
this.expirationPolicy = new RedisSessionExpirationPolicy(sessionRedisOperations, this::getExpirationsKey,
this::getSessionKey);
this.indexResolver = new DelegatingIndexResolver<>(new PrincipalNameIndexResolver<>());
configureSessionChannels();
}
@@ -320,14 +317,11 @@ public class RedisOperationsSessionRepository implements
* Sets the {@link ApplicationEventPublisher} that is used to publish
* {@link SessionDestroyedEvent}. The default is to not publish a
* {@link SessionDestroyedEvent}.
*
* @param applicationEventPublisher the {@link ApplicationEventPublisher} that is used
* to publish {@link SessionDestroyedEvent}. Cannot be null.
*/
public void setApplicationEventPublisher(
ApplicationEventPublisher applicationEventPublisher) {
Assert.notNull(applicationEventPublisher,
"applicationEventPublisher cannot be null");
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
Assert.notNull(applicationEventPublisher, "applicationEventPublisher cannot be null");
this.eventPublisher = applicationEventPublisher;
}
@@ -335,7 +329,6 @@ public class RedisOperationsSessionRepository implements
* Sets the maximum inactive interval in seconds between requests before newly created
* sessions will be invalidated. A negative time indicates that the session will never
* timeout. The default is 1800 (30 minutes).
*
* @param defaultMaxInactiveInterval the number of seconds that the {@link Session}
* should be kept alive between client requests.
*/
@@ -346,7 +339,6 @@ public class RedisOperationsSessionRepository implements
/**
* Sets the default redis serializer. Replaces default serializer which is based on
* {@link JdkSerializationRedisSerializer}.
*
* @param defaultSerializer the new default redis serializer
*/
public void setDefaultSerializer(RedisSerializer<Object> defaultSerializer) {
@@ -356,12 +348,31 @@ public class RedisOperationsSessionRepository implements
/**
* Sets the redis flush mode. Default flush mode is {@link RedisFlushMode#ON_SAVE}.
*
* @param redisFlushMode the new redis flush mode
* @deprecated since 2.2.0 in favor of {@link #setFlushMode(FlushMode)}
*/
@Deprecated
public void setRedisFlushMode(RedisFlushMode redisFlushMode) {
Assert.notNull(redisFlushMode, "redisFlushMode cannot be null");
this.redisFlushMode = redisFlushMode;
setFlushMode(redisFlushMode.getFlushMode());
}
/**
* Sets the redis flush mode. Default flush mode is {@link FlushMode#ON_SAVE}.
* @param flushMode the flush mode
*/
public void setFlushMode(FlushMode flushMode) {
Assert.notNull(flushMode, "flushMode cannot be null");
this.flushMode = flushMode;
}
/**
* Set the save mode.
* @param saveMode the save mode
*/
public void setSaveMode(SaveMode saveMode) {
Assert.notNull(saveMode, "saveMode must not be null");
this.saveMode = saveMode;
}
/**
@@ -374,8 +385,7 @@ public class RedisOperationsSessionRepository implements
}
private void configureSessionChannels() {
this.sessionCreatedChannelPrefix = this.namespace + "event:" + this.database
+ ":created:";
this.sessionCreatedChannelPrefix = this.namespace + "event:" + this.database + ":created:";
this.sessionDeletedChannel = "__keyevent@" + this.database + "__:del";
this.sessionExpiredChannel = "__keyevent@" + this.database + "__:expired";
}
@@ -409,16 +419,13 @@ public class RedisOperationsSessionRepository implements
}
@Override
public Map<String, RedisSession> findByIndexNameAndIndexValue(String indexName,
String indexValue) {
public Map<String, RedisSession> findByIndexNameAndIndexValue(String indexName, String indexValue) {
if (!PRINCIPAL_NAME_INDEX_NAME.equals(indexName)) {
return Collections.emptyMap();
}
String principalKey = getPrincipalKey(indexValue);
Set<Object> sessionIds = this.sessionRedisOperations.boundSetOps(principalKey)
.members();
Map<String, RedisSession> sessions = new HashMap<>(
sessionIds.size());
Set<Object> sessionIds = this.sessionRedisOperations.boundSetOps(principalKey).members();
Map<String, RedisSession> sessions = new HashMap<>(sessionIds.size());
for (Object id : sessionIds) {
RedisSession session = findById((String) id);
if (session != null) {
@@ -444,7 +451,7 @@ public class RedisOperationsSessionRepository implements
if (!allowExpired && loaded.isExpired()) {
return null;
}
RedisSession result = new RedisSession(loaded);
RedisSession result = new RedisSession(loaded, false);
result.originalLastAccessTime = loaded.getLastAccessedTime();
return result;
}
@@ -463,9 +470,7 @@ public class RedisOperationsSessionRepository implements
loaded.setLastAccessedTime(Instant.ofEpochMilli((long) entry.getValue()));
}
else if (key.startsWith(RedisSessionMapper.ATTRIBUTE_PREFIX)) {
loaded.setAttribute(
key.substring(RedisSessionMapper.ATTRIBUTE_PREFIX.length()),
entry.getValue());
loaded.setAttribute(key.substring(RedisSessionMapper.ATTRIBUTE_PREFIX.length()), entry.getValue());
}
}
return loaded;
@@ -490,11 +495,11 @@ public class RedisOperationsSessionRepository implements
@Override
public RedisSession createSession() {
Duration maxInactiveInterval = Duration
.ofSeconds((this.defaultMaxInactiveInterval != null)
? this.defaultMaxInactiveInterval
: MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS);
RedisSession session = new RedisSession(maxInactiveInterval);
MapSession cached = new MapSession();
if (this.defaultMaxInactiveInterval != null) {
cached.setMaxInactiveInterval(Duration.ofSeconds(this.defaultMaxInactiveInterval));
}
RedisSession session = new RedisSession(cached, true);
session.flushImmediateIfNecessary();
return session;
}
@@ -509,8 +514,7 @@ public class RedisOperationsSessionRepository implements
if (channel.startsWith(this.sessionCreatedChannelPrefix)) {
// TODO: is this thread safe?
Map<Object, Object> loaded = (Map<Object, Object>) this.defaultSerializer
.deserialize(message.getBody());
Map<Object, Object> loaded = (Map<Object, Object>) this.defaultSerializer.deserialize(message.getBody());
handleCreated(loaded, channel);
return;
}
@@ -529,8 +533,7 @@ public class RedisOperationsSessionRepository implements
RedisSession session = getSession(sessionId, true);
if (session == null) {
logger.warn("Unable to publish SessionDestroyedEvent for session "
+ sessionId);
logger.warn("Unable to publish SessionDestroyedEvent for session " + sessionId);
return;
}
@@ -551,10 +554,10 @@ public class RedisOperationsSessionRepository implements
private void cleanupPrincipalIndex(RedisSession session) {
String sessionId = session.getId();
String principal = PRINCIPAL_NAME_RESOLVER.resolvePrincipal(session);
Map<String, String> indexes = RedisOperationsSessionRepository.this.indexResolver.resolveIndexesFor(session);
String principal = indexes.get(PRINCIPAL_NAME_INDEX_NAME);
if (principal != null) {
this.sessionRedisOperations.boundSetOps(getPrincipalKey(principal))
.remove(sessionId);
this.sessionRedisOperations.boundSetOps(getPrincipalKey(principal)).remove(sessionId);
}
}
@@ -589,7 +592,6 @@ public class RedisOperationsSessionRepository implements
/**
* Gets the Hash key for this session by prefixing it appropriately.
*
* @param sessionId the session id
* @return the Hash key for this session by prefixing it appropriately.
*/
@@ -598,8 +600,7 @@ public class RedisOperationsSessionRepository implements
}
String getPrincipalKey(String principalName) {
return this.namespace + "index:"
+ FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME + ":"
return this.namespace + "index:" + FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME + ":"
+ principalName;
}
@@ -650,15 +651,13 @@ public class RedisOperationsSessionRepository implements
* @param sessionId the id of the {@link Session} to work with
* @return the {@link BoundHashOperations} to operate on a {@link Session}
*/
private BoundHashOperations<Object, Object, Object> getSessionBoundHashOperations(
String sessionId) {
private BoundHashOperations<Object, Object, Object> getSessionBoundHashOperations(String sessionId) {
String key = getSessionKey(sessionId);
return this.sessionRedisOperations.boundHashOps(key);
}
/**
* Gets the key for the specified session attribute.
*
* @param attributeName the attribute name
* @return the attribute key name
*/
@@ -676,43 +675,35 @@ public class RedisOperationsSessionRepository implements
* @since 1.0
*/
final class RedisSession implements Session {
private final MapSession cached;
private Instant originalLastAccessTime;
private Map<String, Object> delta = new HashMap<>();
private boolean isNew;
private String originalPrincipalName;
private String originalSessionId;
/**
* Creates a new instance ensuring to mark all of the new attributes to be
* persisted in the next save operation.
*
* @param maxInactiveInterval the amount of time that the {@link Session} should
* be kept alive between client requests.
*/
RedisSession(Duration maxInactiveInterval) {
this(new MapSession());
this.cached.setMaxInactiveInterval(maxInactiveInterval);
this.delta.put(RedisSessionMapper.CREATION_TIME_KEY,
getCreationTime().toEpochMilli());
this.delta.put(RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY,
(int) getMaxInactiveInterval().getSeconds());
this.delta.put(RedisSessionMapper.LAST_ACCESSED_TIME_KEY,
getLastAccessedTime().toEpochMilli());
this.isNew = true;
}
/**
* Creates a new instance from the provided {@link MapSession}.
*
* @param cached the {@link MapSession} that represents the persisted session that
* was retrieved. Cannot be null.
*/
RedisSession(MapSession cached) {
Assert.notNull(cached, "MapSession cannot be null");
RedisSession(MapSession cached, boolean isNew) {
this.cached = cached;
this.originalPrincipalName = PRINCIPAL_NAME_RESOLVER.resolvePrincipal(this);
this.isNew = isNew;
this.originalSessionId = cached.getId();
Map<String, String> indexes = RedisOperationsSessionRepository.this.indexResolver.resolveIndexesFor(this);
this.originalPrincipalName = indexes.get(PRINCIPAL_NAME_INDEX_NAME);
if (this.isNew) {
this.delta.put(RedisSessionMapper.CREATION_TIME_KEY, cached.getCreationTime().toEpochMilli());
this.delta.put(RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY,
(int) cached.getMaxInactiveInterval().getSeconds());
this.delta.put(RedisSessionMapper.LAST_ACCESSED_TIME_KEY, cached.getLastAccessedTime().toEpochMilli());
}
if (this.isNew || (RedisOperationsSessionRepository.this.saveMode == SaveMode.ALWAYS)) {
getAttributeNames().forEach((attributeName) -> this.delta.put(getSessionAttrNameKey(attributeName),
cached.getAttribute(attributeName)));
}
}
public void setNew(boolean isNew) {
@@ -722,8 +713,8 @@ public class RedisOperationsSessionRepository implements
@Override
public void setLastAccessedTime(Instant lastAccessedTime) {
this.cached.setLastAccessedTime(lastAccessedTime);
this.putAndFlush(RedisSessionMapper.LAST_ACCESSED_TIME_KEY,
getLastAccessedTime().toEpochMilli());
this.delta.put(RedisSessionMapper.LAST_ACCESSED_TIME_KEY, getLastAccessedTime().toEpochMilli());
flushImmediateIfNecessary();
}
@Override
@@ -758,8 +749,8 @@ public class RedisOperationsSessionRepository implements
@Override
public void setMaxInactiveInterval(Duration interval) {
this.cached.setMaxInactiveInterval(interval);
this.putAndFlush(RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY,
(int) getMaxInactiveInterval().getSeconds());
this.delta.put(RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY, (int) getMaxInactiveInterval().getSeconds());
flushImmediateIfNecessary();
}
@Override
@@ -769,7 +760,12 @@ public class RedisOperationsSessionRepository implements
@Override
public <T> T getAttribute(String attributeName) {
return this.cached.getAttribute(attributeName);
T attributeValue = this.cached.getAttribute(attributeName);
if (attributeValue != null
&& RedisOperationsSessionRepository.this.saveMode.equals(SaveMode.ON_GET_ATTRIBUTE)) {
this.delta.put(getSessionAttrNameKey(attributeName), attributeValue);
}
return attributeValue;
}
@Override
@@ -780,26 +776,23 @@ public class RedisOperationsSessionRepository implements
@Override
public void setAttribute(String attributeName, Object attributeValue) {
this.cached.setAttribute(attributeName, attributeValue);
this.putAndFlush(getSessionAttrNameKey(attributeName), attributeValue);
this.delta.put(getSessionAttrNameKey(attributeName), attributeValue);
flushImmediateIfNecessary();
}
@Override
public void removeAttribute(String attributeName) {
this.cached.removeAttribute(attributeName);
this.putAndFlush(getSessionAttrNameKey(attributeName), null);
this.delta.put(getSessionAttrNameKey(attributeName), null);
flushImmediateIfNecessary();
}
private void flushImmediateIfNecessary() {
if (RedisOperationsSessionRepository.this.redisFlushMode == RedisFlushMode.IMMEDIATE) {
if (RedisOperationsSessionRepository.this.flushMode == FlushMode.IMMEDIATE) {
save();
}
}
private void putAndFlush(String a, Object v) {
this.delta.put(a, v);
this.flushImmediateIfNecessary();
}
private void save() {
saveChangeSessionId();
saveDelta();
@@ -817,33 +810,29 @@ public class RedisOperationsSessionRepository implements
getSessionBoundHashOperations(sessionId).putAll(this.delta);
String principalSessionKey = getSessionAttrNameKey(
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME);
String securityPrincipalSessionKey = getSessionAttrNameKey(
SPRING_SECURITY_CONTEXT);
if (this.delta.containsKey(principalSessionKey)
|| this.delta.containsKey(securityPrincipalSessionKey)) {
String securityPrincipalSessionKey = getSessionAttrNameKey(SPRING_SECURITY_CONTEXT);
if (this.delta.containsKey(principalSessionKey) || this.delta.containsKey(securityPrincipalSessionKey)) {
if (this.originalPrincipalName != null) {
String originalPrincipalRedisKey = getPrincipalKey(
this.originalPrincipalName);
RedisOperationsSessionRepository.this.sessionRedisOperations
.boundSetOps(originalPrincipalRedisKey).remove(sessionId);
String originalPrincipalRedisKey = getPrincipalKey(this.originalPrincipalName);
RedisOperationsSessionRepository.this.sessionRedisOperations.boundSetOps(originalPrincipalRedisKey)
.remove(sessionId);
}
String principal = PRINCIPAL_NAME_RESOLVER.resolvePrincipal(this);
Map<String, String> indexes = RedisOperationsSessionRepository.this.indexResolver
.resolveIndexesFor(this);
String principal = indexes.get(PRINCIPAL_NAME_INDEX_NAME);
this.originalPrincipalName = principal;
if (principal != null) {
String principalRedisKey = getPrincipalKey(principal);
RedisOperationsSessionRepository.this.sessionRedisOperations
.boundSetOps(principalRedisKey).add(sessionId);
RedisOperationsSessionRepository.this.sessionRedisOperations.boundSetOps(principalRedisKey)
.add(sessionId);
}
}
this.delta = new HashMap<>(this.delta.size());
Long originalExpiration = (this.originalLastAccessTime != null)
? this.originalLastAccessTime.plus(getMaxInactiveInterval())
.toEpochMilli()
: null;
RedisOperationsSessionRepository.this.expirationPolicy
.onExpirationUpdated(originalExpiration, this);
? this.originalLastAccessTime.plus(getMaxInactiveInterval()).toEpochMilli() : null;
RedisOperationsSessionRepository.this.expirationPolicy.onExpirationUpdated(originalExpiration, this);
}
private void saveChangeSessionId() {
@@ -855,8 +844,8 @@ public class RedisOperationsSessionRepository implements
String originalSessionIdKey = getSessionKey(this.originalSessionId);
String sessionIdKey = getSessionKey(sessionId);
try {
RedisOperationsSessionRepository.this.sessionRedisOperations
.rename(originalSessionIdKey, sessionIdKey);
RedisOperationsSessionRepository.this.sessionRedisOperations.rename(originalSessionIdKey,
sessionIdKey);
}
catch (NonTransientDataAccessException ex) {
handleErrNoSuchKeyError(ex);
@@ -864,8 +853,7 @@ public class RedisOperationsSessionRepository implements
String originalExpiredKey = getExpiredKey(this.originalSessionId);
String expiredKey = getExpiredKey(sessionId);
try {
RedisOperationsSessionRepository.this.sessionRedisOperations
.rename(originalExpiredKey, expiredKey);
RedisOperationsSessionRepository.this.sessionRedisOperations.rename(originalExpiredKey, expiredKey);
}
catch (NonTransientDataAccessException ex) {
handleErrNoSuchKeyError(ex);
@@ -875,33 +863,11 @@ public class RedisOperationsSessionRepository implements
}
private void handleErrNoSuchKeyError(NonTransientDataAccessException ex) {
if (!"ERR no such key"
.equals(NestedExceptionUtils.getMostSpecificCause(ex).getMessage())) {
if (!"ERR no such key".equals(NestedExceptionUtils.getMostSpecificCause(ex).getMessage())) {
throw ex;
}
}
}
/**
* Principal name resolver helper class.
*/
static class PrincipalNameResolver {
private SpelExpressionParser parser = new SpelExpressionParser();
public String resolvePrincipal(Session session) {
String principalName = session.getAttribute(PRINCIPAL_NAME_INDEX_NAME);
if (principalName != null) {
return principalName;
}
Object authentication = session.getAttribute(SPRING_SECURITY_CONTEXT);
if (authentication != null) {
Expression expression = this.parser
.parseExpression("authentication?.name");
return expression.getValue(authentication, String.class);
}
return null;
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2017 the original author or authors.
* Copyright 2014-2019 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.
@@ -48,11 +48,12 @@ import org.springframework.session.data.redis.RedisOperationsSessionRepository.R
*/
final class RedisSessionExpirationPolicy {
private static final Log logger = LogFactory
.getLog(RedisSessionExpirationPolicy.class);
private static final Log logger = LogFactory.getLog(RedisSessionExpirationPolicy.class);
private final RedisOperations<Object, Object> redis;
private final Function<Long, String> lookupExpirationKey;
private final Function<String, String> lookupSessionKey;
RedisSessionExpirationPolicy(RedisOperations<Object, Object> sessionRedisOperations,
@@ -92,12 +93,10 @@ final class RedisSessionExpirationPolicy {
}
String expireKey = getExpirationKey(toExpire);
BoundSetOperations<Object, Object> expireOperations = this.redis
.boundSetOps(expireKey);
BoundSetOperations<Object, Object> expireOperations = this.redis.boundSetOps(expireKey);
expireOperations.add(keyToExpire);
long fiveMinutesAfterExpires = sessionExpireInSeconds
+ TimeUnit.MINUTES.toSeconds(5);
long fiveMinutesAfterExpires = sessionExpireInSeconds + TimeUnit.MINUTES.toSeconds(5);
expireOperations.expire(fiveMinutesAfterExpires, TimeUnit.SECONDS);
if (sessionExpireInSeconds == 0) {
@@ -105,11 +104,9 @@ final class RedisSessionExpirationPolicy {
}
else {
this.redis.boundValueOps(sessionKey).append("");
this.redis.boundValueOps(sessionKey).expire(sessionExpireInSeconds,
TimeUnit.SECONDS);
this.redis.boundValueOps(sessionKey).expire(sessionExpireInSeconds, TimeUnit.SECONDS);
}
this.redis.boundHashOps(getSessionKey(session.getId()))
.expire(fiveMinutesAfterExpires, TimeUnit.SECONDS);
this.redis.boundHashOps(getSessionKey(session.getId())).expire(fiveMinutesAfterExpires, TimeUnit.SECONDS);
}
String getExpirationKey(long expires) {
@@ -141,7 +138,6 @@ final class RedisSessionExpirationPolicy {
* By trying to access the session we only trigger a deletion if it the TTL is
* expired. This is done to handle
* https://github.com/spring-projects/spring-session/issues/93
*
* @param key the key
*/
private void touch(String key) {
@@ -171,4 +167,5 @@ final class RedisSessionExpirationPolicy {
date.clear(Calendar.MILLISECOND);
return date.getTimeInMillis();
}
}

View File

@@ -24,7 +24,9 @@ import java.util.Map;
import java.util.Set;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.session.FlushMode;
import org.springframework.session.MapSession;
import org.springframework.session.SaveMode;
import org.springframework.session.Session;
import org.springframework.session.SessionRepository;
import org.springframework.util.Assert;
@@ -38,27 +40,27 @@ import org.springframework.util.Assert;
* @author Vedran Pavic
* @since 2.2.0
*/
public class SimpleRedisOperationsSessionRepository implements
SessionRepository<SimpleRedisOperationsSessionRepository.RedisSession> {
public class SimpleRedisOperationsSessionRepository
implements SessionRepository<SimpleRedisOperationsSessionRepository.RedisSession> {
private static final String DEFAULT_KEY_NAMESPACE = "spring:session:";
private final RedisOperations<String, Object> sessionRedisOperations;
private Duration defaultMaxInactiveInterval = Duration
.ofSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS);
private Duration defaultMaxInactiveInterval = Duration.ofSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS);
private String keyNamespace = DEFAULT_KEY_NAMESPACE;
private RedisFlushMode flushMode = RedisFlushMode.ON_SAVE;
private FlushMode flushMode = FlushMode.ON_SAVE;
private SaveMode saveMode = SaveMode.ON_SET_ATTRIBUTE;
/**
* Create a new {@link SimpleRedisOperationsSessionRepository} instance.
* @param sessionRedisOperations the {@link RedisOperations} to use for managing
* sessions
* sessions
*/
public SimpleRedisOperationsSessionRepository(
RedisOperations<String, Object> sessionRedisOperations) {
public SimpleRedisOperationsSessionRepository(RedisOperations<String, Object> sessionRedisOperations) {
Assert.notNull(sessionRedisOperations, "sessionRedisOperations mut not be null");
this.sessionRedisOperations = sessionRedisOperations;
}
@@ -68,8 +70,7 @@ public class SimpleRedisOperationsSessionRepository implements
* @param defaultMaxInactiveInterval the default maxInactiveInterval
*/
public void setDefaultMaxInactiveInterval(Duration defaultMaxInactiveInterval) {
Assert.notNull(defaultMaxInactiveInterval,
"defaultMaxInactiveInterval must not be null");
Assert.notNull(defaultMaxInactiveInterval, "defaultMaxInactiveInterval must not be null");
this.defaultMaxInactiveInterval = defaultMaxInactiveInterval;
}
@@ -86,14 +87,25 @@ public class SimpleRedisOperationsSessionRepository implements
* Set the flush mode.
* @param flushMode the flush mode
*/
public void setFlushMode(RedisFlushMode flushMode) {
public void setFlushMode(FlushMode flushMode) {
Assert.notNull(flushMode, "flushMode must not be null");
this.flushMode = flushMode;
}
/**
* Set the save mode.
* @param saveMode the save mode
*/
public void setSaveMode(SaveMode saveMode) {
Assert.notNull(saveMode, "saveMode must not be null");
this.saveMode = saveMode;
}
@Override
public RedisSession createSession() {
RedisSession session = new RedisSession(this.defaultMaxInactiveInterval);
MapSession cached = new MapSession();
cached.setMaxInactiveInterval(this.defaultMaxInactiveInterval);
RedisSession session = new RedisSession(cached, true);
session.flushIfRequired();
return session;
}
@@ -101,9 +113,7 @@ public class SimpleRedisOperationsSessionRepository implements
@Override
public void save(RedisSession session) {
if (!session.isNew) {
String key = getSessionKey(
session.hasChangedSessionId() ? session.originalSessionId
: session.getId());
String key = getSessionKey(session.hasChangedSessionId() ? session.originalSessionId : session.getId());
Boolean sessionExists = this.sessionRedisOperations.hasKey(key);
if (sessionExists == null || !sessionExists) {
throw new IllegalStateException("Session was invalidated");
@@ -115,8 +125,7 @@ public class SimpleRedisOperationsSessionRepository implements
@Override
public RedisSession findById(String sessionId) {
String key = getSessionKey(sessionId);
Map<String, Object> entries = this.sessionRedisOperations
.<String, Object>opsForHash().entries(key);
Map<String, Object> entries = this.sessionRedisOperations.<String, Object>opsForHash().entries(key);
if (entries.isEmpty()) {
return null;
}
@@ -125,7 +134,7 @@ public class SimpleRedisOperationsSessionRepository implements
deleteById(sessionId);
return null;
}
return new RedisSession(session);
return new RedisSession(session, false);
}
@Override
@@ -146,6 +155,10 @@ public class SimpleRedisOperationsSessionRepository implements
return this.keyNamespace + "sessions:" + sessionId;
}
private static String getAttributeKey(String attributeName) {
return RedisSessionMapper.ATTRIBUTE_PREFIX + attributeName;
}
/**
* An internal {@link Session} implementation used by this {@link SessionRepository}.
*/
@@ -159,21 +172,20 @@ public class SimpleRedisOperationsSessionRepository implements
private String originalSessionId;
RedisSession(Duration maxInactiveInterval) {
this(new MapSession());
this.cached.setMaxInactiveInterval(maxInactiveInterval);
this.delta.put(RedisSessionMapper.CREATION_TIME_KEY,
getCreationTime().toEpochMilli());
this.delta.put(RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY,
(int) getMaxInactiveInterval().getSeconds());
this.delta.put(RedisSessionMapper.LAST_ACCESSED_TIME_KEY,
getLastAccessedTime().toEpochMilli());
this.isNew = true;
}
RedisSession(MapSession cached) {
RedisSession(MapSession cached, boolean isNew) {
this.cached = cached;
this.isNew = isNew;
this.originalSessionId = cached.getId();
if (this.isNew) {
this.delta.put(RedisSessionMapper.CREATION_TIME_KEY, cached.getCreationTime().toEpochMilli());
this.delta.put(RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY,
(int) cached.getMaxInactiveInterval().getSeconds());
this.delta.put(RedisSessionMapper.LAST_ACCESSED_TIME_KEY, cached.getLastAccessedTime().toEpochMilli());
}
if (this.isNew || (SimpleRedisOperationsSessionRepository.this.saveMode == SaveMode.ALWAYS)) {
getAttributeNames().forEach((attributeName) -> this.delta.put(getAttributeKey(attributeName),
cached.getAttribute(attributeName)));
}
}
@Override
@@ -188,7 +200,12 @@ public class SimpleRedisOperationsSessionRepository implements
@Override
public <T> T getAttribute(String attributeName) {
return this.cached.getAttribute(attributeName);
T attributeValue = this.cached.getAttribute(attributeName);
if (attributeValue != null
&& SimpleRedisOperationsSessionRepository.this.saveMode.equals(SaveMode.ON_GET_ATTRIBUTE)) {
this.delta.put(getAttributeKey(attributeName), attributeValue);
}
return attributeValue;
}
@Override
@@ -199,8 +216,8 @@ public class SimpleRedisOperationsSessionRepository implements
@Override
public void setAttribute(String attributeName, Object attributeValue) {
this.cached.setAttribute(attributeName, attributeValue);
putAttribute(RedisSessionMapper.ATTRIBUTE_PREFIX + attributeName,
attributeValue);
this.delta.put(getAttributeKey(attributeName), attributeValue);
flushIfRequired();
}
@Override
@@ -216,8 +233,8 @@ public class SimpleRedisOperationsSessionRepository implements
@Override
public void setLastAccessedTime(Instant lastAccessedTime) {
this.cached.setLastAccessedTime(lastAccessedTime);
putAttribute(RedisSessionMapper.LAST_ACCESSED_TIME_KEY,
getLastAccessedTime().toEpochMilli());
this.delta.put(RedisSessionMapper.LAST_ACCESSED_TIME_KEY, getLastAccessedTime().toEpochMilli());
flushIfRequired();
}
@Override
@@ -228,8 +245,8 @@ public class SimpleRedisOperationsSessionRepository implements
@Override
public void setMaxInactiveInterval(Duration interval) {
this.cached.setMaxInactiveInterval(interval);
putAttribute(RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY,
(int) getMaxInactiveInterval().getSeconds());
this.delta.put(RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY, (int) getMaxInactiveInterval().getSeconds());
flushIfRequired();
}
@Override
@@ -243,7 +260,7 @@ public class SimpleRedisOperationsSessionRepository implements
}
private void flushIfRequired() {
if (SimpleRedisOperationsSessionRepository.this.flushMode == RedisFlushMode.IMMEDIATE) {
if (SimpleRedisOperationsSessionRepository.this.flushMode == FlushMode.IMMEDIATE) {
save();
}
}
@@ -265,8 +282,8 @@ public class SimpleRedisOperationsSessionRepository implements
if (!this.isNew) {
String originalSessionIdKey = getSessionKey(this.originalSessionId);
String sessionIdKey = getSessionKey(getId());
SimpleRedisOperationsSessionRepository.this.sessionRedisOperations
.rename(originalSessionIdKey, sessionIdKey);
SimpleRedisOperationsSessionRepository.this.sessionRedisOperations.rename(originalSessionIdKey,
sessionIdKey);
}
this.originalSessionId = getId();
}
@@ -277,21 +294,14 @@ public class SimpleRedisOperationsSessionRepository implements
return;
}
String key = getSessionKey(getId());
SimpleRedisOperationsSessionRepository.this.sessionRedisOperations
.opsForHash().putAll(key, new HashMap<>(this.delta));
SimpleRedisOperationsSessionRepository.this.sessionRedisOperations
.expireAt(key,
Date.from(Instant
.ofEpochMilli(getLastAccessedTime().toEpochMilli())
.plusSeconds(getMaxInactiveInterval().getSeconds())));
SimpleRedisOperationsSessionRepository.this.sessionRedisOperations.opsForHash().putAll(key,
new HashMap<>(this.delta));
SimpleRedisOperationsSessionRepository.this.sessionRedisOperations.expireAt(key,
Date.from(Instant.ofEpochMilli(getLastAccessedTime().toEpochMilli())
.plusSeconds(getMaxInactiveInterval().getSeconds())));
this.delta.clear();
}
private void putAttribute(String name, Object value) {
this.delta.put(name, value);
flushIfRequired();
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2017 the original author or authors.
* Copyright 2014-2019 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.
@@ -33,8 +33,7 @@ import org.springframework.session.data.redis.RedisOperationsSessionRepository;
* @author Vedran Pavic
* @since 2.0.0
*/
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE,
ElementType.ANNOTATION_TYPE })
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Qualifier

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 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.
@@ -33,8 +33,7 @@ import org.springframework.beans.factory.annotation.Value;
* @see org.springframework.session.data.redis.ReactiveRedisOperationsSessionRepository#getSessionRedisOperations()
* @since 2.0.0
*/
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER,
ElementType.ANNOTATION_TYPE })
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Value("#{sessionRepository.sessionRedisOperations}")

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2017 the original author or authors.
* Copyright 2014-2019 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.
@@ -25,7 +25,9 @@ import java.lang.annotation.Target;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.session.FlushMode;
import org.springframework.session.MapSession;
import org.springframework.session.SaveMode;
import org.springframework.session.Session;
import org.springframework.session.SessionRepository;
import org.springframework.session.config.annotation.web.http.EnableSpringHttpSession;
@@ -94,9 +96,23 @@ public @interface EnableRedisHttpSession {
* Session are immediately written to the Redis instance.
* @return the {@link RedisFlushMode} to use
* @since 1.1
* @deprecated since 2.2.0 in favor of {@link #flushMode()}
*/
@Deprecated
RedisFlushMode redisFlushMode() default RedisFlushMode.ON_SAVE;
/**
* Flush mode for the Redis sessions. The default is {@code ON_SAVE} which only
* updates the backing Redis when {@link SessionRepository#save(Session)} is invoked.
* In a web environment this happens just before the HTTP response is committed.
* <p>
* Setting the value to {@code IMMEDIATE} will ensure that the any updates to the
* Session are immediately written to the Redis instance.
* @return the {@link FlushMode} to use
* @since 2.2.0
*/
FlushMode flushMode() default FlushMode.ON_SAVE;
/**
* The cron expression for expired session cleanup job. By default runs every minute.
* @return the session cleanup cron expression
@@ -104,4 +120,12 @@ public @interface EnableRedisHttpSession {
*/
String cleanupCron() default RedisHttpSessionConfiguration.DEFAULT_CLEANUP_CRON;
/**
* Save mode for the session. The default is {@link SaveMode#ON_SET_ATTRIBUTE}, which
* only saves changes made to session.
* @return the save mode
* @since 2.2.0
*/
SaveMode saveMode() default SaveMode.ON_SET_ATTRIBUTE;
}

View File

@@ -48,7 +48,9 @@ import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.session.FlushMode;
import org.springframework.session.MapSession;
import org.springframework.session.SaveMode;
import org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration;
import org.springframework.session.data.redis.RedisFlushMode;
import org.springframework.session.data.redis.RedisOperationsSessionRepository;
@@ -75,8 +77,7 @@ import org.springframework.util.StringValueResolver;
@Configuration(proxyBeanMethods = false)
@EnableScheduling
public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguration
implements BeanClassLoaderAware, EmbeddedValueResolverAware, ImportAware,
SchedulingConfigurer {
implements BeanClassLoaderAware, EmbeddedValueResolverAware, ImportAware, SchedulingConfigurer {
static final String DEFAULT_CLEANUP_CRON = "0 * * * * *";
@@ -84,7 +85,9 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio
private String redisNamespace = RedisOperationsSessionRepository.DEFAULT_NAMESPACE;
private RedisFlushMode redisFlushMode = RedisFlushMode.ON_SAVE;
private FlushMode flushMode = FlushMode.ON_SAVE;
private SaveMode saveMode = SaveMode.ON_SET_ATTRIBUTE;
private String cleanupCron = DEFAULT_CLEANUP_CRON;
@@ -107,18 +110,17 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio
@Bean
public RedisOperationsSessionRepository sessionRepository() {
RedisTemplate<Object, Object> redisTemplate = createRedisTemplate();
RedisOperationsSessionRepository sessionRepository = new RedisOperationsSessionRepository(
redisTemplate);
RedisOperationsSessionRepository sessionRepository = new RedisOperationsSessionRepository(redisTemplate);
sessionRepository.setApplicationEventPublisher(this.applicationEventPublisher);
if (this.defaultRedisSerializer != null) {
sessionRepository.setDefaultSerializer(this.defaultRedisSerializer);
}
sessionRepository
.setDefaultMaxInactiveInterval(this.maxInactiveIntervalInSeconds);
sessionRepository.setDefaultMaxInactiveInterval(this.maxInactiveIntervalInSeconds);
if (StringUtils.hasText(this.redisNamespace)) {
sessionRepository.setRedisKeyNamespace(this.redisNamespace);
}
sessionRepository.setRedisFlushMode(this.redisFlushMode);
sessionRepository.setFlushMode(this.flushMode);
sessionRepository.setSaveMode(this.saveMode);
int database = resolveDatabase();
sessionRepository.setDatabase(database);
return sessionRepository;
@@ -136,19 +138,16 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio
container.setSubscriptionExecutor(this.redisSubscriptionExecutor);
}
container.addMessageListener(sessionRepository,
Arrays.asList(
new ChannelTopic(sessionRepository.getSessionDeletedChannel()),
Arrays.asList(new ChannelTopic(sessionRepository.getSessionDeletedChannel()),
new ChannelTopic(sessionRepository.getSessionExpiredChannel())));
container.addMessageListener(sessionRepository,
Collections.singletonList(new PatternTopic(
sessionRepository.getSessionCreatedChannelPrefix() + "*")));
Collections.singletonList(new PatternTopic(sessionRepository.getSessionCreatedChannelPrefix() + "*")));
return container;
}
@Bean
public InitializingBean enableRedisKeyspaceNotificationsInitializer() {
return new EnableRedisKeyspaceNotificationsInitializer(
this.redisConnectionFactory, this.configureRedisAction);
return new EnableRedisKeyspaceNotificationsInitializer(this.redisConnectionFactory, this.configureRedisAction);
}
public void setMaxInactiveIntervalInSeconds(int maxInactiveIntervalInSeconds) {
@@ -159,9 +158,19 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio
this.redisNamespace = namespace;
}
@Deprecated
public void setRedisFlushMode(RedisFlushMode redisFlushMode) {
Assert.notNull(redisFlushMode, "redisFlushMode cannot be null");
this.redisFlushMode = redisFlushMode;
setFlushMode(redisFlushMode.getFlushMode());
}
public void setFlushMode(FlushMode flushMode) {
Assert.notNull(flushMode, "flushMode cannot be null");
this.flushMode = flushMode;
}
public void setSaveMode(SaveMode saveMode) {
this.saveMode = saveMode;
}
public void setCleanupCron(String cleanupCron) {
@@ -170,7 +179,6 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio
/**
* Sets the action to perform for configuring Redis.
*
* @param configureRedisAction the configureRedis to set. The default is
* {@link ConfigureNotifyKeyspaceEventsAction}.
*/
@@ -183,8 +191,7 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio
public void setRedisConnectionFactory(
@SpringSessionRedisConnectionFactory ObjectProvider<RedisConnectionFactory> springSessionRedisConnectionFactory,
ObjectProvider<RedisConnectionFactory> redisConnectionFactory) {
RedisConnectionFactory redisConnectionFactoryToUse = springSessionRedisConnectionFactory
.getIfAvailable();
RedisConnectionFactory redisConnectionFactoryToUse = springSessionRedisConnectionFactory.getIfAvailable();
if (redisConnectionFactoryToUse == null) {
redisConnectionFactoryToUse = redisConnectionFactory.getObject();
}
@@ -193,14 +200,12 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio
@Autowired(required = false)
@Qualifier("springSessionDefaultRedisSerializer")
public void setDefaultRedisSerializer(
RedisSerializer<Object> defaultRedisSerializer) {
public void setDefaultRedisSerializer(RedisSerializer<Object> defaultRedisSerializer) {
this.defaultRedisSerializer = defaultRedisSerializer;
}
@Autowired
public void setApplicationEventPublisher(
ApplicationEventPublisher applicationEventPublisher) {
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
@@ -227,18 +232,23 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio
}
@Override
@SuppressWarnings("deprecation")
public void setImportMetadata(AnnotationMetadata importMetadata) {
Map<String, Object> attributeMap = importMetadata
.getAnnotationAttributes(EnableRedisHttpSession.class.getName());
AnnotationAttributes attributes = AnnotationAttributes.fromMap(attributeMap);
this.maxInactiveIntervalInSeconds = attributes
.getNumber("maxInactiveIntervalInSeconds");
this.maxInactiveIntervalInSeconds = attributes.getNumber("maxInactiveIntervalInSeconds");
String redisNamespaceValue = attributes.getString("redisNamespace");
if (StringUtils.hasText(redisNamespaceValue)) {
this.redisNamespace = this.embeddedValueResolver
.resolveStringValue(redisNamespaceValue);
this.redisNamespace = this.embeddedValueResolver.resolveStringValue(redisNamespaceValue);
}
this.redisFlushMode = attributes.getEnum("redisFlushMode");
FlushMode flushMode = attributes.getEnum("flushMode");
RedisFlushMode redisFlushMode = attributes.getEnum("redisFlushMode");
if (flushMode == FlushMode.ON_SAVE && redisFlushMode != RedisFlushMode.ON_SAVE) {
flushMode = redisFlushMode.getFlushMode();
}
this.flushMode = flushMode;
this.saveMode = attributes.getEnum("saveMode");
String cleanupCron = attributes.getString("cleanupCron");
if (StringUtils.hasText(cleanupCron)) {
this.cleanupCron = cleanupCron;
@@ -247,8 +257,7 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.addCronTask(() -> sessionRepository().cleanupExpiredSessions(),
this.cleanupCron);
taskRegistrar.addCronTask(() -> sessionRepository().cleanupExpiredSessions(), this.cleanupCron);
}
private RedisTemplate<Object, Object> createRedisTemplate() {
@@ -289,15 +298,14 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio
private ConfigureRedisAction configure;
EnableRedisKeyspaceNotificationsInitializer(
RedisConnectionFactory connectionFactory,
EnableRedisKeyspaceNotificationsInitializer(RedisConnectionFactory connectionFactory,
ConfigureRedisAction configure) {
this.connectionFactory = connectionFactory;
this.configure = configure;
}
@Override
public void afterPropertiesSet() throws Exception {
public void afterPropertiesSet() {
if (this.configure == ConfigureRedisAction.NO_OP) {
return;
}
@@ -310,8 +318,7 @@ public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguratio
connection.close();
}
catch (Exception ex) {
LogFactory.getLog(getClass()).error("Error closing RedisConnection",
ex);
LogFactory.getLog(getClass()).error("Error closing RedisConnection", ex);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2017 the original author or authors.
* Copyright 2014-2019 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.
@@ -27,6 +27,7 @@ import org.springframework.context.annotation.Import;
import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory;
import org.springframework.session.MapSession;
import org.springframework.session.ReactiveSessionRepository;
import org.springframework.session.SaveMode;
import org.springframework.session.Session;
import org.springframework.session.config.annotation.web.server.EnableSpringWebSession;
import org.springframework.session.data.redis.ReactiveRedisOperationsSessionRepository;
@@ -93,7 +94,17 @@ public @interface EnableRedisWebSession {
* Setting the value to {@code IMMEDIATE} will ensure that the any updates to the
* Session are immediately written to the Redis instance.
* @return the {@link RedisFlushMode} to use
* @deprecated since 2.2.0 as support {@code IMMEDIATE} is removed
*/
@Deprecated
RedisFlushMode redisFlushMode() default RedisFlushMode.ON_SAVE;
/**
* Save mode for the session. The default is {@link SaveMode#ON_SET_ATTRIBUTE}, which
* only saves changes made to session.
* @return the save mode
* @since 2.2.0
*/
SaveMode saveMode() default SaveMode.ON_SET_ATTRIBUTE;
}

View File

@@ -35,6 +35,7 @@ import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.session.MapSession;
import org.springframework.session.SaveMode;
import org.springframework.session.config.annotation.web.server.SpringWebSessionConfiguration;
import org.springframework.session.data.redis.ReactiveRedisOperationsSessionRepository;
import org.springframework.session.data.redis.RedisFlushMode;
@@ -61,7 +62,7 @@ public class RedisWebSessionConfiguration extends SpringWebSessionConfiguration
private String redisNamespace = ReactiveRedisOperationsSessionRepository.DEFAULT_NAMESPACE;
private RedisFlushMode redisFlushMode = RedisFlushMode.ON_SAVE;
private SaveMode saveMode = SaveMode.ON_SET_ATTRIBUTE;
private ReactiveRedisConnectionFactory redisConnectionFactory;
@@ -76,12 +77,11 @@ public class RedisWebSessionConfiguration extends SpringWebSessionConfiguration
ReactiveRedisTemplate<String, Object> reactiveRedisTemplate = createReactiveRedisTemplate();
ReactiveRedisOperationsSessionRepository sessionRepository = new ReactiveRedisOperationsSessionRepository(
reactiveRedisTemplate);
sessionRepository
.setDefaultMaxInactiveInterval(this.maxInactiveIntervalInSeconds);
sessionRepository.setDefaultMaxInactiveInterval(this.maxInactiveIntervalInSeconds);
if (StringUtils.hasText(this.redisNamespace)) {
sessionRepository.setRedisKeyNamespace(this.redisNamespace);
}
sessionRepository.setRedisFlushMode(this.redisFlushMode);
sessionRepository.setSaveMode(this.saveMode);
return sessionRepository;
}
@@ -93,9 +93,13 @@ public class RedisWebSessionConfiguration extends SpringWebSessionConfiguration
this.redisNamespace = namespace;
}
@Deprecated
public void setRedisFlushMode(RedisFlushMode redisFlushMode) {
Assert.notNull(redisFlushMode, "redisFlushMode cannot be null");
this.redisFlushMode = redisFlushMode;
}
public void setSaveMode(SaveMode saveMode) {
this.saveMode = saveMode;
}
@Autowired
@@ -112,8 +116,7 @@ public class RedisWebSessionConfiguration extends SpringWebSessionConfiguration
@Autowired(required = false)
@Qualifier("springSessionDefaultRedisSerializer")
public void setDefaultRedisSerializer(
RedisSerializer<Object> defaultRedisSerializer) {
public void setDefaultRedisSerializer(RedisSerializer<Object> defaultRedisSerializer) {
this.defaultRedisSerializer = defaultRedisSerializer;
}
@@ -132,26 +135,22 @@ public class RedisWebSessionConfiguration extends SpringWebSessionConfiguration
Map<String, Object> attributeMap = importMetadata
.getAnnotationAttributes(EnableRedisWebSession.class.getName());
AnnotationAttributes attributes = AnnotationAttributes.fromMap(attributeMap);
this.maxInactiveIntervalInSeconds = attributes
.getNumber("maxInactiveIntervalInSeconds");
this.maxInactiveIntervalInSeconds = attributes.getNumber("maxInactiveIntervalInSeconds");
String redisNamespaceValue = attributes.getString("redisNamespace");
if (StringUtils.hasText(redisNamespaceValue)) {
this.redisNamespace = this.embeddedValueResolver
.resolveStringValue(redisNamespaceValue);
this.redisNamespace = this.embeddedValueResolver.resolveStringValue(redisNamespaceValue);
}
this.redisFlushMode = attributes.getEnum("redisFlushMode");
this.saveMode = attributes.getEnum("saveMode");
}
private ReactiveRedisTemplate<String, Object> createReactiveRedisTemplate() {
RedisSerializer<String> keySerializer = new StringRedisSerializer();
RedisSerializer<Object> defaultSerializer = (this.defaultRedisSerializer != null)
? this.defaultRedisSerializer
RedisSerializer<Object> defaultSerializer = (this.defaultRedisSerializer != null) ? this.defaultRedisSerializer
: new JdkSerializationRedisSerializer(this.classLoader);
RedisSerializationContext<String, Object> serializationContext = RedisSerializationContext
.<String, Object>newSerializationContext(defaultSerializer)
.key(keySerializer).hashKey(keySerializer).build();
return new ReactiveRedisTemplate<>(this.redisConnectionFactory,
serializationContext);
.<String, Object>newSerializationContext(defaultSerializer).key(keySerializer).hashKey(keySerializer)
.build();
return new ReactiveRedisTemplate<>(this.redisConnectionFactory, serializationContext);
}
}

View File

@@ -32,6 +32,7 @@ import reactor.test.StepVerifier;
import org.springframework.data.redis.core.ReactiveHashOperations;
import org.springframework.data.redis.core.ReactiveRedisOperations;
import org.springframework.session.MapSession;
import org.springframework.session.SaveMode;
import org.springframework.session.data.redis.ReactiveRedisOperationsSessionRepository.RedisSession;
import org.springframework.test.util.ReflectionTestUtils;
@@ -49,28 +50,24 @@ import static org.mockito.Mockito.verifyZeroInteractions;
*
* @author Vedran Pavic
*/
public class ReactiveRedisOperationsSessionRepositoryTests {
class ReactiveRedisOperationsSessionRepositoryTests {
@SuppressWarnings("unchecked")
private ReactiveRedisOperations<String, Object> redisOperations = mock(
ReactiveRedisOperations.class);
private ReactiveRedisOperations<String, Object> redisOperations = mock(ReactiveRedisOperations.class);
@SuppressWarnings("unchecked")
private ReactiveHashOperations<String, Object, Object> hashOperations = mock(
ReactiveHashOperations.class);
private ReactiveHashOperations<String, Object, Object> hashOperations = mock(ReactiveHashOperations.class);
@SuppressWarnings("unchecked")
private ArgumentCaptor<Map<String, Object>> delta = ArgumentCaptor
.forClass(Map.class);
private ArgumentCaptor<Map<String, Object>> delta = ArgumentCaptor.forClass(Map.class);
private ReactiveRedisOperationsSessionRepository repository;
private MapSession cached;
@BeforeEach
public void setUp() {
this.repository = new ReactiveRedisOperationsSessionRepository(
this.redisOperations);
void setUp() {
this.repository = new ReactiveRedisOperationsSessionRepository(this.redisOperations);
this.cached = new MapSession();
this.cached.setId("session-id");
@@ -79,84 +76,62 @@ public class ReactiveRedisOperationsSessionRepositoryTests {
}
@Test
public void constructorWithNullReactiveRedisOperations() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new ReactiveRedisOperationsSessionRepository(null))
void constructorWithNullReactiveRedisOperations() {
assertThatIllegalArgumentException().isThrownBy(() -> new ReactiveRedisOperationsSessionRepository(null))
.withMessageContaining("sessionRedisOperations cannot be null");
}
@Test
public void customRedisKeyNamespace() {
void customRedisKeyNamespace() {
this.repository.setRedisKeyNamespace("test");
assertThat(ReflectionTestUtils.getField(this.repository, "namespace"))
.isEqualTo("test:");
assertThat(ReflectionTestUtils.getField(this.repository, "namespace")).isEqualTo("test:");
}
@Test
public void nullRedisKeyNamespace() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.repository.setRedisKeyNamespace(null))
void nullRedisKeyNamespace() {
assertThatIllegalArgumentException().isThrownBy(() -> this.repository.setRedisKeyNamespace(null))
.withMessage("namespace cannot be null or empty");
}
@Test
public void emptyRedisKeyNamespace() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.repository.setRedisKeyNamespace(""))
void emptyRedisKeyNamespace() {
assertThatIllegalArgumentException().isThrownBy(() -> this.repository.setRedisKeyNamespace(""))
.withMessage("namespace cannot be null or empty");
}
@Test
public void customMaxInactiveInterval() {
void customMaxInactiveInterval() {
this.repository.setDefaultMaxInactiveInterval(600);
assertThat(ReflectionTestUtils.getField(this.repository,
"defaultMaxInactiveInterval")).isEqualTo(600);
assertThat(ReflectionTestUtils.getField(this.repository, "defaultMaxInactiveInterval")).isEqualTo(600);
}
@Test
public void customRedisFlushMode() {
this.repository.setRedisFlushMode(RedisFlushMode.IMMEDIATE);
assertThat(ReflectionTestUtils.getField(this.repository, "redisFlushMode"))
.isEqualTo(RedisFlushMode.IMMEDIATE);
}
@Test
public void nullRedisFlushMode() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.repository.setRedisFlushMode(null))
.withMessage("redisFlushMode cannot be null");
}
@Test
public void createSessionDefaultMaxInactiveInterval() {
void createSessionDefaultMaxInactiveInterval() {
StepVerifier.create(this.repository.createSession())
.consumeNextWith((session) -> assertThat(session.getMaxInactiveInterval())
.isEqualTo(Duration.ofSeconds(
MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS)))
.isEqualTo(Duration.ofSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS)))
.verifyComplete();
}
@Test
public void createSessionCustomMaxInactiveInterval() {
void createSessionCustomMaxInactiveInterval() {
this.repository.setDefaultMaxInactiveInterval(600);
StepVerifier.create(this.repository.createSession())
.consumeNextWith((session) -> assertThat(session.getMaxInactiveInterval())
.isEqualTo(Duration.ofSeconds(600)))
.consumeNextWith(
(session) -> assertThat(session.getMaxInactiveInterval()).isEqualTo(Duration.ofSeconds(600)))
.verifyComplete();
}
@Test
public void saveNewSession() {
void saveNewSession() {
given(this.redisOperations.opsForHash()).willReturn(this.hashOperations);
given(this.hashOperations.putAll(anyString(), any())).willReturn(Mono.just(true));
given(this.redisOperations.expire(anyString(), any()))
.willReturn(Mono.just(true));
given(this.redisOperations.expire(anyString(), any())).willReturn(Mono.just(true));
RedisSession newSession = this.repository.new RedisSession();
RedisSession newSession = this.repository.new RedisSession(new MapSession(), true);
StepVerifier.create(this.repository.save(newSession)).verifyComplete();
verify(this.redisOperations).opsForHash();
@@ -176,13 +151,11 @@ public class ReactiveRedisOperationsSessionRepositoryTests {
}
@Test
public void saveSessionNothingChanged() {
void saveSessionNothingChanged() {
given(this.redisOperations.hasKey(anyString())).willReturn(Mono.just(true));
given(this.redisOperations.expire(anyString(), any()))
.willReturn(Mono.just(true));
given(this.redisOperations.expire(anyString(), any())).willReturn(Mono.just(true));
RedisSession session = this.repository.new RedisSession(
new MapSession(this.cached));
RedisSession session = this.repository.new RedisSession(this.cached, false);
StepVerifier.create(this.repository.save(session)).verifyComplete();
@@ -192,14 +165,13 @@ public class ReactiveRedisOperationsSessionRepositoryTests {
}
@Test
public void saveLastAccessChanged() {
void saveLastAccessChanged() {
given(this.redisOperations.hasKey(anyString())).willReturn(Mono.just(true));
given(this.redisOperations.opsForHash()).willReturn(this.hashOperations);
given(this.hashOperations.putAll(anyString(), any())).willReturn(Mono.just(true));
given(this.redisOperations.expire(anyString(), any()))
.willReturn(Mono.just(true));
given(this.redisOperations.expire(anyString(), any())).willReturn(Mono.just(true));
RedisSession session = this.repository.new RedisSession(this.cached);
RedisSession session = this.repository.new RedisSession(this.cached, false);
session.setLastAccessedTime(Instant.ofEpochMilli(12345678L));
StepVerifier.create(this.repository.save(session)).verifyComplete();
@@ -210,21 +182,19 @@ public class ReactiveRedisOperationsSessionRepositoryTests {
verifyZeroInteractions(this.redisOperations);
verifyZeroInteractions(this.hashOperations);
assertThat(this.delta.getAllValues().get(0))
.isEqualTo(map(RedisSessionMapper.LAST_ACCESSED_TIME_KEY,
session.getLastAccessedTime().toEpochMilli()));
assertThat(this.delta.getAllValues().get(0)).isEqualTo(
map(RedisSessionMapper.LAST_ACCESSED_TIME_KEY, session.getLastAccessedTime().toEpochMilli()));
}
@Test
public void saveSetAttribute() {
void saveSetAttribute() {
given(this.redisOperations.hasKey(anyString())).willReturn(Mono.just(true));
given(this.redisOperations.opsForHash()).willReturn(this.hashOperations);
given(this.hashOperations.putAll(anyString(), any())).willReturn(Mono.just(true));
given(this.redisOperations.expire(anyString(), any()))
.willReturn(Mono.just(true));
given(this.redisOperations.expire(anyString(), any())).willReturn(Mono.just(true));
String attrName = "attrName";
RedisSession session = this.repository.new RedisSession(this.cached);
RedisSession session = this.repository.new RedisSession(this.cached, false);
session.setAttribute(attrName, "attrValue");
StepVerifier.create(this.repository.save(session)).verifyComplete();
@@ -236,20 +206,18 @@ public class ReactiveRedisOperationsSessionRepositoryTests {
verifyZeroInteractions(this.hashOperations);
assertThat(this.delta.getAllValues().get(0)).isEqualTo(
map(RedisOperationsSessionRepository.getSessionAttrNameKey(attrName),
session.getAttribute(attrName)));
map(RedisOperationsSessionRepository.getSessionAttrNameKey(attrName), session.getAttribute(attrName)));
}
@Test
public void saveRemoveAttribute() {
void saveRemoveAttribute() {
given(this.redisOperations.hasKey(anyString())).willReturn(Mono.just(true));
given(this.redisOperations.opsForHash()).willReturn(this.hashOperations);
given(this.hashOperations.putAll(anyString(), any())).willReturn(Mono.just(true));
given(this.redisOperations.expire(anyString(), any()))
.willReturn(Mono.just(true));
given(this.redisOperations.expire(anyString(), any())).willReturn(Mono.just(true));
String attrName = "attrName";
RedisSession session = this.repository.new RedisSession(new MapSession());
RedisSession session = this.repository.new RedisSession(new MapSession(), false);
session.removeAttribute(attrName);
StepVerifier.create(this.repository.save(session)).verifyComplete();
@@ -260,14 +228,14 @@ public class ReactiveRedisOperationsSessionRepositoryTests {
verifyZeroInteractions(this.redisOperations);
verifyZeroInteractions(this.hashOperations);
assertThat(this.delta.getAllValues().get(0)).isEqualTo(map(
RedisOperationsSessionRepository.getSessionAttrNameKey(attrName), null));
assertThat(this.delta.getAllValues().get(0))
.isEqualTo(map(RedisOperationsSessionRepository.getSessionAttrNameKey(attrName), null));
}
@Test
public void redisSessionGetAttributes() {
void redisSessionGetAttributes() {
String attrName = "attrName";
RedisSession session = this.repository.new RedisSession(this.cached);
RedisSession session = this.repository.new RedisSession(this.cached, false);
assertThat(session.getAttributeNames()).isEmpty();
session.setAttribute(attrName, "attrValue");
@@ -278,7 +246,7 @@ public class ReactiveRedisOperationsSessionRepositoryTests {
}
@Test
public void delete() {
void delete() {
given(this.redisOperations.delete(anyString())).willReturn(Mono.just(1L));
StepVerifier.create(this.repository.deleteById("test")).verifyComplete();
@@ -289,7 +257,7 @@ public class ReactiveRedisOperationsSessionRepositoryTests {
}
@Test
public void getSessionNotFound() {
void getSessionNotFound() {
given(this.redisOperations.opsForHash()).willReturn(this.hashOperations);
given(this.hashOperations.entries(anyString())).willReturn(Flux.empty());
given(this.redisOperations.delete(anyString())).willReturn(Mono.just(0L));
@@ -305,7 +273,7 @@ public class ReactiveRedisOperationsSessionRepositoryTests {
@Test
@SuppressWarnings("unchecked")
public void getSessionFound() {
void getSessionFound() {
given(this.redisOperations.opsForHash()).willReturn(this.hashOperations);
String attribute1 = "attribute1";
String attribute2 = "attribute2";
@@ -313,54 +281,38 @@ public class ReactiveRedisOperationsSessionRepositoryTests {
expected.setLastAccessedTime(Instant.now().minusSeconds(60));
expected.setAttribute(attribute1, "test");
expected.setAttribute(attribute2, null);
Map map = map(RedisSessionMapper.ATTRIBUTE_PREFIX + attribute1,
expected.getAttribute(attribute1),
RedisSessionMapper.ATTRIBUTE_PREFIX + attribute2,
expected.getAttribute(attribute2), RedisSessionMapper.CREATION_TIME_KEY,
expected.getCreationTime().toEpochMilli(),
RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY,
(int) expected.getMaxInactiveInterval().getSeconds(),
RedisSessionMapper.LAST_ACCESSED_TIME_KEY,
expected.getLastAccessedTime().toEpochMilli());
given(this.hashOperations.entries(anyString()))
.willReturn(Flux.fromIterable(map.entrySet()));
Map map = map(RedisSessionMapper.ATTRIBUTE_PREFIX + attribute1, expected.getAttribute(attribute1),
RedisSessionMapper.ATTRIBUTE_PREFIX + attribute2, expected.getAttribute(attribute2),
RedisSessionMapper.CREATION_TIME_KEY, expected.getCreationTime().toEpochMilli(),
RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY, (int) expected.getMaxInactiveInterval().getSeconds(),
RedisSessionMapper.LAST_ACCESSED_TIME_KEY, expected.getLastAccessedTime().toEpochMilli());
given(this.hashOperations.entries(anyString())).willReturn(Flux.fromIterable(map.entrySet()));
StepVerifier.create(this.repository.findById("test"))
.consumeNextWith((session) -> {
verify(this.redisOperations).opsForHash();
verify(this.hashOperations).entries(anyString());
verifyZeroInteractions(this.redisOperations);
verifyZeroInteractions(this.hashOperations);
StepVerifier.create(this.repository.findById("test")).consumeNextWith((session) -> {
verify(this.redisOperations).opsForHash();
verify(this.hashOperations).entries(anyString());
verifyZeroInteractions(this.redisOperations);
verifyZeroInteractions(this.hashOperations);
assertThat(session.getId()).isEqualTo(expected.getId());
assertThat(session.getAttributeNames())
.isEqualTo(expected.getAttributeNames());
assertThat(session.<String>getAttribute(attribute1))
.isEqualTo(expected.getAttribute(attribute1));
assertThat(session.<String>getAttribute(attribute2))
.isEqualTo(expected.getAttribute(attribute2));
assertThat(session.getCreationTime().truncatedTo(ChronoUnit.MILLIS))
.isEqualTo(expected.getCreationTime()
.truncatedTo(ChronoUnit.MILLIS));
assertThat(session.getMaxInactiveInterval())
.isEqualTo(expected.getMaxInactiveInterval());
assertThat(
session.getLastAccessedTime().truncatedTo(ChronoUnit.MILLIS))
.isEqualTo(expected.getLastAccessedTime()
.truncatedTo(ChronoUnit.MILLIS));
}).verifyComplete();
assertThat(session.getId()).isEqualTo(expected.getId());
assertThat(session.getAttributeNames()).isEqualTo(expected.getAttributeNames());
assertThat(session.<String>getAttribute(attribute1)).isEqualTo(expected.getAttribute(attribute1));
assertThat(session.<String>getAttribute(attribute2)).isEqualTo(expected.getAttribute(attribute2));
assertThat(session.getCreationTime().truncatedTo(ChronoUnit.MILLIS))
.isEqualTo(expected.getCreationTime().truncatedTo(ChronoUnit.MILLIS));
assertThat(session.getMaxInactiveInterval()).isEqualTo(expected.getMaxInactiveInterval());
assertThat(session.getLastAccessedTime().truncatedTo(ChronoUnit.MILLIS))
.isEqualTo(expected.getLastAccessedTime().truncatedTo(ChronoUnit.MILLIS));
}).verifyComplete();
}
@Test
@SuppressWarnings("unchecked")
public void getSessionExpired() {
void getSessionExpired() {
given(this.redisOperations.opsForHash()).willReturn(this.hashOperations);
Map map = map(RedisSessionMapper.CREATION_TIME_KEY, 0L,
RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY, 1,
RedisSessionMapper.LAST_ACCESSED_TIME_KEY,
Instant.now().minus(5, ChronoUnit.MINUTES).toEpochMilli());
given(this.hashOperations.entries(anyString()))
.willReturn(Flux.fromIterable(map.entrySet()));
Map map = map(RedisSessionMapper.CREATION_TIME_KEY, 0L, RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY, 1,
RedisSessionMapper.LAST_ACCESSED_TIME_KEY, Instant.now().minus(5, ChronoUnit.MINUTES).toEpochMilli());
given(this.hashOperations.entries(anyString())).willReturn(Flux.fromIterable(map.entrySet()));
given(this.redisOperations.delete(anyString())).willReturn(Mono.just(0L));
StepVerifier.create(this.repository.findById("test")).verifyComplete();
@@ -373,8 +325,8 @@ public class ReactiveRedisOperationsSessionRepositoryTests {
}
@Test // gh-1120
public void getAttributeNamesAndRemove() {
RedisSession session = this.repository.new RedisSession(this.cached);
void getAttributeNamesAndRemove() {
RedisSession session = this.repository.new RedisSession(this.cached, false);
session.setAttribute("attribute1", "value1");
session.setAttribute("attribute2", "value2");
@@ -385,6 +337,78 @@ public class ReactiveRedisOperationsSessionRepositoryTests {
assertThat(session.getAttributeNames()).isEmpty();
}
@Test
void saveWithSaveModeOnSetAttribute() {
given(this.redisOperations.hasKey(anyString())).willReturn(Mono.just(true));
given(this.redisOperations.opsForHash()).willReturn(this.hashOperations);
given(this.hashOperations.putAll(anyString(), any())).willReturn(Mono.just(true));
given(this.redisOperations.expire(anyString(), any())).willReturn(Mono.just(true));
this.repository.setSaveMode(SaveMode.ON_SET_ATTRIBUTE);
MapSession delegate = new MapSession();
delegate.setAttribute("attribute1", "value1");
delegate.setAttribute("attribute2", "value2");
delegate.setAttribute("attribute3", "value3");
RedisSession session = this.repository.new RedisSession(delegate, false);
session.getAttribute("attribute2");
session.setAttribute("attribute3", "value4");
StepVerifier.create(this.repository.save(session)).verifyComplete();
verify(this.redisOperations).hasKey(anyString());
verify(this.redisOperations).opsForHash();
verify(this.hashOperations).putAll(anyString(), this.delta.capture());
assertThat(this.delta.getValue()).hasSize(1);
verify(this.redisOperations).expire(anyString(), any());
verifyZeroInteractions(this.redisOperations);
verifyZeroInteractions(this.hashOperations);
}
@Test
void saveWithSaveModeOnGetAttribute() {
given(this.redisOperations.hasKey(anyString())).willReturn(Mono.just(true));
given(this.redisOperations.opsForHash()).willReturn(this.hashOperations);
given(this.hashOperations.putAll(anyString(), any())).willReturn(Mono.just(true));
given(this.redisOperations.expire(anyString(), any())).willReturn(Mono.just(true));
this.repository.setSaveMode(SaveMode.ON_GET_ATTRIBUTE);
MapSession delegate = new MapSession();
delegate.setAttribute("attribute1", "value1");
delegate.setAttribute("attribute2", "value2");
delegate.setAttribute("attribute3", "value3");
RedisSession session = this.repository.new RedisSession(delegate, false);
session.getAttribute("attribute2");
session.setAttribute("attribute3", "value4");
StepVerifier.create(this.repository.save(session)).verifyComplete();
verify(this.redisOperations).hasKey(anyString());
verify(this.redisOperations).opsForHash();
verify(this.hashOperations).putAll(anyString(), this.delta.capture());
assertThat(this.delta.getValue()).hasSize(2);
verify(this.redisOperations).expire(anyString(), any());
verifyZeroInteractions(this.redisOperations);
verifyZeroInteractions(this.hashOperations);
}
@Test
void saveWithSaveModeAlways() {
given(this.redisOperations.hasKey(anyString())).willReturn(Mono.just(true));
given(this.redisOperations.opsForHash()).willReturn(this.hashOperations);
given(this.hashOperations.putAll(anyString(), any())).willReturn(Mono.just(true));
given(this.redisOperations.expire(anyString(), any())).willReturn(Mono.just(true));
this.repository.setSaveMode(SaveMode.ALWAYS);
MapSession delegate = new MapSession();
delegate.setAttribute("attribute1", "value1");
delegate.setAttribute("attribute2", "value2");
delegate.setAttribute("attribute3", "value3");
RedisSession session = this.repository.new RedisSession(delegate, false);
session.getAttribute("attribute2");
session.setAttribute("attribute3", "value4");
StepVerifier.create(this.repository.save(session)).verifyComplete();
verify(this.redisOperations).hasKey(anyString());
verify(this.redisOperations).opsForHash();
verify(this.hashOperations).putAll(anyString(), this.delta.capture());
assertThat(this.delta.getValue()).hasSize(3);
verify(this.redisOperations).expire(anyString(), any());
verifyZeroInteractions(this.redisOperations);
verifyZeroInteractions(this.hashOperations);
}
private Map<String, Object> map(Object... objects) {
Map<String, Object> result = new HashMap<>();
if (objects == null) {

View File

@@ -39,54 +39,52 @@ import static org.mockito.Mockito.verify;
/**
* @author Rob Winch
*/
public class RedisSessionExpirationPolicyTests {
class RedisSessionExpirationPolicyTests {
// Wed Apr 15 10:28:32 CDT 2015
static final Long NOW = 1429111712346L;
// Wed Apr 15 10:27:32 CDT 2015
static final Long ONE_MINUTE_AGO = 1429111652346L;
private static final Long ONE_MINUTE_AGO = 1429111652346L;
@Mock
RedisOperations<Object, Object> sessionRedisOperations;
@Mock
BoundSetOperations<Object, Object> setOperations;
@Mock
BoundHashOperations<Object, Object, Object> hashOperations;
@Mock
BoundValueOperations<Object, Object> valueOperations;
RedisSessionExpirationPolicy policy;
private RedisSessionExpirationPolicy policy;
private MapSession session;
@BeforeEach
public void setup() {
void setup() {
MockitoAnnotations.initMocks(this);
RedisOperationsSessionRepository repository = new RedisOperationsSessionRepository(
this.sessionRedisOperations);
this.policy = new RedisSessionExpirationPolicy(this.sessionRedisOperations,
repository::getExpirationsKey, repository::getSessionKey);
RedisOperationsSessionRepository repository = new RedisOperationsSessionRepository(this.sessionRedisOperations);
this.policy = new RedisSessionExpirationPolicy(this.sessionRedisOperations, repository::getExpirationsKey,
repository::getSessionKey);
this.session = new MapSession();
this.session.setLastAccessedTime(Instant.ofEpochMilli(1429116694675L));
this.session.setId("12345");
given(this.sessionRedisOperations.boundSetOps(anyString()))
.willReturn(this.setOperations);
given(this.sessionRedisOperations.boundHashOps(anyString()))
.willReturn(this.hashOperations);
given(this.sessionRedisOperations.boundValueOps(anyString()))
.willReturn(this.valueOperations);
given(this.sessionRedisOperations.boundSetOps(anyString())).willReturn(this.setOperations);
given(this.sessionRedisOperations.boundHashOps(anyString())).willReturn(this.hashOperations);
given(this.sessionRedisOperations.boundValueOps(anyString())).willReturn(this.valueOperations);
}
// gh-169
@Test
public void onExpirationUpdatedRemovesOriginalExpirationTimeRoundedUp()
throws Exception {
void onExpirationUpdatedRemovesOriginalExpirationTimeRoundedUp() {
long originalExpirationTimeInMs = ONE_MINUTE_AGO;
long originalRoundedToNextMinInMs = RedisSessionExpirationPolicy
.roundUpToNextMinute(originalExpirationTimeInMs);
String originalExpireKey = this.policy
.getExpirationKey(originalRoundedToNextMinInMs);
String originalExpireKey = this.policy.getExpirationKey(originalRoundedToNextMinInMs);
this.policy.onExpirationUpdated(originalExpirationTimeInMs, this.session);
@@ -96,14 +94,11 @@ public class RedisSessionExpirationPolicyTests {
}
@Test
public void onExpirationUpdatedDoNotSendDeleteWhenExpirationTimeDoesNotChange()
throws Exception {
long originalExpirationTimeInMs = RedisSessionExpirationPolicy
.expiresInMillis(this.session) - 10;
void onExpirationUpdatedDoNotSendDeleteWhenExpirationTimeDoesNotChange() {
long originalExpirationTimeInMs = RedisSessionExpirationPolicy.expiresInMillis(this.session) - 10;
long originalRoundedToNextMinInMs = RedisSessionExpirationPolicy
.roundUpToNextMinute(originalExpirationTimeInMs);
String originalExpireKey = this.policy
.getExpirationKey(originalRoundedToNextMinInMs);
String originalExpireKey = this.policy.getExpirationKey(originalRoundedToNextMinInMs);
this.policy.onExpirationUpdated(originalExpirationTimeInMs, this.session);
@@ -113,36 +108,32 @@ public class RedisSessionExpirationPolicyTests {
}
@Test
public void onExpirationUpdatedAddsExpirationTimeRoundedUp() throws Exception {
long expirationTimeInMs = RedisSessionExpirationPolicy
.expiresInMillis(this.session);
long expirationRoundedUpInMs = RedisSessionExpirationPolicy
.roundUpToNextMinute(expirationTimeInMs);
void onExpirationUpdatedAddsExpirationTimeRoundedUp() {
long expirationTimeInMs = RedisSessionExpirationPolicy.expiresInMillis(this.session);
long expirationRoundedUpInMs = RedisSessionExpirationPolicy.roundUpToNextMinute(expirationTimeInMs);
String expectedExpireKey = this.policy.getExpirationKey(expirationRoundedUpInMs);
this.policy.onExpirationUpdated(null, this.session);
verify(this.sessionRedisOperations).boundSetOps(expectedExpireKey);
verify(this.setOperations).add("expires:" + this.session.getId());
verify(this.setOperations).expire(
this.session.getMaxInactiveInterval().plusMinutes(5).getSeconds(),
verify(this.setOperations).expire(this.session.getMaxInactiveInterval().plusMinutes(5).getSeconds(),
TimeUnit.SECONDS);
}
@Test
public void onExpirationUpdatedSetExpireSession() throws Exception {
void onExpirationUpdatedSetExpireSession() {
String sessionKey = this.policy.getSessionKey(this.session.getId());
this.policy.onExpirationUpdated(null, this.session);
verify(this.sessionRedisOperations).boundHashOps(sessionKey);
verify(this.hashOperations).expire(
this.session.getMaxInactiveInterval().plusMinutes(5).getSeconds(),
verify(this.hashOperations).expire(this.session.getMaxInactiveInterval().plusMinutes(5).getSeconds(),
TimeUnit.SECONDS);
}
@Test
public void onExpirationUpdatedDeleteOnZero() throws Exception {
void onExpirationUpdatedDeleteOnZero() {
String sessionKey = this.policy.getSessionKey("expires:" + this.session.getId());
long originalExpirationTimeInMs = ONE_MINUTE_AGO;
@@ -155,13 +146,12 @@ public class RedisSessionExpirationPolicyTests {
verify(this.setOperations).remove("expires:" + this.session.getId());
verify(this.setOperations).add("expires:" + this.session.getId());
verify(this.sessionRedisOperations).delete(sessionKey);
verify(this.setOperations).expire(
this.session.getMaxInactiveInterval().plusMinutes(5).getSeconds(),
verify(this.setOperations).expire(this.session.getMaxInactiveInterval().plusMinutes(5).getSeconds(),
TimeUnit.SECONDS);
}
@Test
public void onExpirationUpdatedPersistOnNegativeExpiration() throws Exception {
void onExpirationUpdatedPersistOnNegativeExpiration() {
long originalExpirationTimeInMs = ONE_MINUTE_AGO;
this.session.setMaxInactiveInterval(Duration.ofSeconds(-1));
@@ -173,4 +163,5 @@ public class RedisSessionExpirationPolicyTests {
verify(this.valueOperations).persist();
verify(this.hashOperations).persist();
}
}

View File

@@ -47,8 +47,7 @@ class RedisSessionMapperTests {
@Test
void constructor_NullId_ShouldThrowException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new RedisSessionMapper(null))
assertThatIllegalArgumentException().isThrownBy(() -> new RedisSessionMapper(null))
.withMessage("sessionId must not be empty");
}
@@ -66,8 +65,7 @@ class RedisSessionMapperTests {
@Test
void apply_EmptyMap_ShouldThrowException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.mapper.apply(Collections.emptyMap()))
assertThatIllegalArgumentException().isThrownBy(() -> this.mapper.apply(Collections.emptyMap()))
.withMessage("map must not be empty");
}
@@ -77,8 +75,7 @@ class RedisSessionMapperTests {
sessionMap.put(RedisSessionMapper.LAST_ACCESSED_TIME_KEY, 0L);
sessionMap.put(RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY, 1800);
assertThatIllegalStateException().isThrownBy(() -> this.mapper.apply(sessionMap))
.withMessage(
RedisSessionMapper.CREATION_TIME_KEY + " key must not be null");
.withMessage(RedisSessionMapper.CREATION_TIME_KEY + " key must not be null");
}
@Test
@@ -87,8 +84,7 @@ class RedisSessionMapperTests {
sessionMap.put(RedisSessionMapper.CREATION_TIME_KEY, 0L);
sessionMap.put(RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY, 1800);
assertThatIllegalStateException().isThrownBy(() -> this.mapper.apply(sessionMap))
.withMessage(RedisSessionMapper.LAST_ACCESSED_TIME_KEY
+ " key must not be null");
.withMessage(RedisSessionMapper.LAST_ACCESSED_TIME_KEY + " key must not be null");
}
@Test
@@ -97,8 +93,7 @@ class RedisSessionMapperTests {
sessionMap.put(RedisSessionMapper.CREATION_TIME_KEY, 0L);
sessionMap.put(RedisSessionMapper.LAST_ACCESSED_TIME_KEY, 0L);
assertThatIllegalStateException().isThrownBy(() -> this.mapper.apply(sessionMap))
.withMessage(RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY
+ " key must not be null");
.withMessage(RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY + " key must not be null");
}
@Test

View File

@@ -33,7 +33,9 @@ import org.mockito.MockitoAnnotations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.session.FlushMode;
import org.springframework.session.MapSession;
import org.springframework.session.SaveMode;
import org.springframework.session.data.redis.SimpleRedisOperationsSessionRepository.RedisSession;
import org.springframework.test.util.ReflectionTestUtils;
@@ -70,74 +72,78 @@ class SimpleRedisOperationsSessionRepositoryTests {
@BeforeEach
void setUp() {
MockitoAnnotations.initMocks(this);
given(this.sessionRedisOperations.<String, Object>opsForHash())
.willReturn(this.sessionHashOperations);
this.sessionRepository = new SimpleRedisOperationsSessionRepository(
this.sessionRedisOperations);
given(this.sessionRedisOperations.<String, Object>opsForHash()).willReturn(this.sessionHashOperations);
this.sessionRepository = new SimpleRedisOperationsSessionRepository(this.sessionRedisOperations);
}
@Test
void constructor_NullRedisOperations_ShouldThrowException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new ReactiveRedisOperationsSessionRepository(null))
assertThatIllegalArgumentException().isThrownBy(() -> new ReactiveRedisOperationsSessionRepository(null))
.withMessageContaining("sessionRedisOperations cannot be null");
}
@Test
void setDefaultMaxInactiveInterval_ValidInterval_ShouldSetInterval() {
this.sessionRepository.setDefaultMaxInactiveInterval(Duration.ofMinutes(10));
assertThat(ReflectionTestUtils.getField(this.sessionRepository,
"defaultMaxInactiveInterval")).isEqualTo(Duration.ofMinutes(10));
assertThat(ReflectionTestUtils.getField(this.sessionRepository, "defaultMaxInactiveInterval"))
.isEqualTo(Duration.ofMinutes(10));
}
@Test
void setDefaultMaxInactiveInterval_NullInterval_ShouldThrowException() {
assertThatIllegalArgumentException()
.isThrownBy(
() -> this.sessionRepository.setDefaultMaxInactiveInterval(null))
.isThrownBy(() -> this.sessionRepository.setDefaultMaxInactiveInterval(null))
.withMessage("defaultMaxInactiveInterval must not be null");
}
@Test
void setKeyNamespace_ValidNamespace_ShouldSetNamespace() {
this.sessionRepository.setKeyNamespace("test:");
assertThat(ReflectionTestUtils.getField(this.sessionRepository, "keyNamespace"))
.isEqualTo("test:");
assertThat(ReflectionTestUtils.getField(this.sessionRepository, "keyNamespace")).isEqualTo("test:");
}
@Test
void setKeyNamespace_NullNamespace_ShouldThrowException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.sessionRepository.setKeyNamespace(null))
assertThatIllegalArgumentException().isThrownBy(() -> this.sessionRepository.setKeyNamespace(null))
.withMessage("keyNamespace must not be empty");
}
@Test
void setKeyNamespace_EmptyNamespace_ShouldThrowException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.sessionRepository.setKeyNamespace(" "))
assertThatIllegalArgumentException().isThrownBy(() -> this.sessionRepository.setKeyNamespace(" "))
.withMessage("keyNamespace must not be empty");
}
@Test
void setFlushMode_ValidFlushMode_ShouldSetFlushMode() {
this.sessionRepository.setFlushMode(RedisFlushMode.IMMEDIATE);
assertThat(ReflectionTestUtils.getField(this.sessionRepository, "flushMode"))
.isEqualTo(RedisFlushMode.IMMEDIATE);
this.sessionRepository.setFlushMode(FlushMode.IMMEDIATE);
assertThat(ReflectionTestUtils.getField(this.sessionRepository, "flushMode")).isEqualTo(FlushMode.IMMEDIATE);
}
@Test
void setFlushMode_NullFlushMode_ShouldThrowException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> this.sessionRepository.setFlushMode(null))
assertThatIllegalArgumentException().isThrownBy(() -> this.sessionRepository.setFlushMode(null))
.withMessage("flushMode must not be null");
}
@Test
void setSaveMode_ValidSaveMode_ShouldSetSaveMode() {
this.sessionRepository.setSaveMode(SaveMode.ON_GET_ATTRIBUTE);
assertThat(ReflectionTestUtils.getField(this.sessionRepository, "saveMode"))
.isEqualTo(SaveMode.ON_GET_ATTRIBUTE);
}
@Test
void setSaveMode_NullSaveMode_ShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> this.sessionRepository.setSaveMode(null))
.withMessage("saveMode must not be null");
}
@Test
void createSession_DefaultMaxInactiveInterval_ShouldCreateSession() {
RedisSession redisSession = this.sessionRepository.createSession();
assertThat(redisSession.getMaxInactiveInterval()).isEqualTo(
Duration.ofSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS));
assertThat(redisSession.getMaxInactiveInterval())
.isEqualTo(Duration.ofSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS));
verifyNoMoreInteractions(this.sessionRedisOperations);
verifyNoMoreInteractions(this.sessionHashOperations);
}
@@ -146,15 +152,14 @@ class SimpleRedisOperationsSessionRepositoryTests {
void createSession_CustomMaxInactiveInterval_ShouldCreateSession() {
this.sessionRepository.setDefaultMaxInactiveInterval(Duration.ofMinutes(10));
RedisSession redisSession = this.sessionRepository.createSession();
assertThat(redisSession.getMaxInactiveInterval())
.isEqualTo(Duration.ofMinutes(10));
assertThat(redisSession.getMaxInactiveInterval()).isEqualTo(Duration.ofMinutes(10));
verifyNoMoreInteractions(this.sessionRedisOperations);
verifyNoMoreInteractions(this.sessionHashOperations);
}
@Test
void createSession_ImmediateFlushMode_ShouldCreateSession() {
this.sessionRepository.setFlushMode(RedisFlushMode.IMMEDIATE);
this.sessionRepository.setFlushMode(FlushMode.IMMEDIATE);
RedisSession session = this.sessionRepository.createSession();
String key = getSessionKey(session.getId());
verify(this.sessionRedisOperations).opsForHash();
@@ -215,10 +220,8 @@ class SimpleRedisOperationsSessionRepositoryTests {
this.sessionRepository.save(session);
verify(this.sessionRedisOperations).hasKey(eq(TEST_SESSION_KEY));
verify(this.sessionRedisOperations).opsForHash();
verify(this.sessionRedisOperations).expireAt(eq(TEST_SESSION_KEY),
eq(getExpiry(session)));
verify(this.sessionHashOperations).putAll(eq(TEST_SESSION_KEY),
this.delta.capture());
verify(this.sessionRedisOperations).expireAt(eq(TEST_SESSION_KEY), eq(getExpiry(session)));
verify(this.sessionHashOperations).putAll(eq(TEST_SESSION_KEY), this.delta.capture());
assertThat(this.delta.getValue()).hasSize(2);
verifyNoMoreInteractions(this.sessionRedisOperations);
verifyNoMoreInteractions(this.sessionHashOperations);
@@ -234,11 +237,73 @@ class SimpleRedisOperationsSessionRepositoryTests {
verifyNoMoreInteractions(this.sessionHashOperations);
}
@Test
void save_WithSaveModeOnSetAttribute_SholdSaveSession() {
given(this.sessionRedisOperations.hasKey(eq(TEST_SESSION_KEY))).willReturn(true);
this.sessionRepository.setSaveMode(SaveMode.ON_SET_ATTRIBUTE);
Map<String, Object> attributes = new HashMap<>();
attributes.put("attribute1", "value1");
attributes.put("attribute2", "value2");
attributes.put("attribute3", "value3");
RedisSession session = createTestSession(attributes);
session.getAttribute("attribute2");
session.setAttribute("attribute3", "value4");
this.sessionRepository.save(session);
verify(this.sessionRedisOperations).hasKey(eq(TEST_SESSION_KEY));
verify(this.sessionRedisOperations).opsForHash();
verify(this.sessionRedisOperations).expireAt(eq(TEST_SESSION_KEY), eq(getExpiry(session)));
verify(this.sessionHashOperations).putAll(eq(TEST_SESSION_KEY), this.delta.capture());
assertThat(this.delta.getValue()).hasSize(1);
verifyNoMoreInteractions(this.sessionRedisOperations);
verifyNoMoreInteractions(this.sessionHashOperations);
}
@Test
void saveWithSaveModeOnGetAttribute() {
given(this.sessionRedisOperations.hasKey(eq(TEST_SESSION_KEY))).willReturn(true);
this.sessionRepository.setSaveMode(SaveMode.ON_GET_ATTRIBUTE);
Map<String, Object> attributes = new HashMap<>();
attributes.put("attribute1", "value1");
attributes.put("attribute2", "value2");
attributes.put("attribute3", "value3");
RedisSession session = createTestSession(attributes);
session.getAttribute("attribute2");
session.setAttribute("attribute3", "value4");
this.sessionRepository.save(session);
verify(this.sessionRedisOperations).hasKey(eq(TEST_SESSION_KEY));
verify(this.sessionRedisOperations).opsForHash();
verify(this.sessionRedisOperations).expireAt(eq(TEST_SESSION_KEY), eq(getExpiry(session)));
verify(this.sessionHashOperations).putAll(eq(TEST_SESSION_KEY), this.delta.capture());
assertThat(this.delta.getValue()).hasSize(2);
verifyNoMoreInteractions(this.sessionRedisOperations);
verifyNoMoreInteractions(this.sessionHashOperations);
}
@Test
void saveWithSaveModeAlways() {
given(this.sessionRedisOperations.hasKey(eq(TEST_SESSION_KEY))).willReturn(true);
this.sessionRepository.setSaveMode(SaveMode.ALWAYS);
Map<String, Object> attributes = new HashMap<>();
attributes.put("attribute1", "value1");
attributes.put("attribute2", "value2");
attributes.put("attribute3", "value3");
RedisSession session = createTestSession(attributes);
session.getAttribute("attribute2");
session.setAttribute("attribute3", "value4");
this.sessionRepository.save(session);
verify(this.sessionRedisOperations).hasKey(eq(TEST_SESSION_KEY));
verify(this.sessionRedisOperations).opsForHash();
verify(this.sessionRedisOperations).expireAt(eq(TEST_SESSION_KEY), eq(getExpiry(session)));
verify(this.sessionHashOperations).putAll(eq(TEST_SESSION_KEY), this.delta.capture());
assertThat(this.delta.getValue()).hasSize(3);
verifyNoMoreInteractions(this.sessionRedisOperations);
verifyNoMoreInteractions(this.sessionHashOperations);
}
@Test
void save_SessionNotExists_ShouldThrowException() {
RedisSession session = createTestSession();
assertThatIllegalStateException()
.isThrownBy(() -> this.sessionRepository.save(session))
assertThatIllegalStateException().isThrownBy(() -> this.sessionRepository.save(session))
.withMessage("Session was invalidated");
verify(this.sessionRedisOperations).hasKey(eq(TEST_SESSION_KEY));
verifyNoMoreInteractions(this.sessionRedisOperations);
@@ -249,20 +314,18 @@ class SimpleRedisOperationsSessionRepositoryTests {
@SuppressWarnings("unchecked")
void findById_SessionExists_ShouldReturnSession() {
Instant now = Instant.now().truncatedTo(ChronoUnit.MILLIS);
given(this.sessionHashOperations.entries(eq(TEST_SESSION_KEY))).willReturn(
mapOf(RedisSessionMapper.CREATION_TIME_KEY, Instant.EPOCH.toEpochMilli(),
given(this.sessionHashOperations.entries(eq(TEST_SESSION_KEY)))
.willReturn(mapOf(RedisSessionMapper.CREATION_TIME_KEY, Instant.EPOCH.toEpochMilli(),
RedisSessionMapper.LAST_ACCESSED_TIME_KEY, now.toEpochMilli(),
RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY,
MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS,
RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY, MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS,
RedisSessionMapper.ATTRIBUTE_PREFIX + "attribute1", "value1"));
RedisSession session = this.sessionRepository.findById(TEST_SESSION_ID);
assertThat(session.getId()).isEqualTo(TEST_SESSION_ID);
assertThat(session.getCreationTime()).isEqualTo(Instant.EPOCH);
assertThat(session.getLastAccessedTime()).isEqualTo(now);
assertThat(session.getMaxInactiveInterval()).isEqualTo(
Duration.ofSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS));
assertThat(session.getAttributeNames())
.isEqualTo(Collections.singleton("attribute1"));
assertThat(session.getMaxInactiveInterval())
.isEqualTo(Duration.ofSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS));
assertThat(session.getAttributeNames()).isEqualTo(Collections.singleton("attribute1"));
assertThat(session.<String>getAttribute("attribute1")).isEqualTo("value1");
verify(this.sessionRedisOperations).opsForHash();
verify(this.sessionHashOperations).entries(eq(TEST_SESSION_KEY));
@@ -273,12 +336,11 @@ class SimpleRedisOperationsSessionRepositoryTests {
@Test
@SuppressWarnings("unchecked")
void findById_SessionExistsAndIsExpired_ShouldReturnNull() {
given(this.sessionHashOperations.entries(eq(TEST_SESSION_KEY))).willReturn(mapOf(
RedisSessionMapper.CREATION_TIME_KEY, Instant.EPOCH.toEpochMilli(),
RedisSessionMapper.LAST_ACCESSED_TIME_KEY, Instant.EPOCH.toEpochMilli(),
RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY,
MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS,
RedisSessionMapper.ATTRIBUTE_PREFIX + "attribute1", "value1"));
given(this.sessionHashOperations.entries(eq(TEST_SESSION_KEY)))
.willReturn(mapOf(RedisSessionMapper.CREATION_TIME_KEY, Instant.EPOCH.toEpochMilli(),
RedisSessionMapper.LAST_ACCESSED_TIME_KEY, Instant.EPOCH.toEpochMilli(),
RedisSessionMapper.MAX_INACTIVE_INTERVAL_KEY, MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS,
RedisSessionMapper.ATTRIBUTE_PREFIX + "attribute1", "value1"));
assertThat(this.sessionRepository.findById(TEST_SESSION_ID)).isNull();
verify(this.sessionRedisOperations).opsForHash();
verify(this.sessionHashOperations).entries(eq(TEST_SESSION_KEY));
@@ -306,8 +368,7 @@ class SimpleRedisOperationsSessionRepositoryTests {
@Test
void getSessionRedisOperations__ShouldReturnRedisOperations() {
assertThat(this.sessionRepository.getSessionRedisOperations())
.isEqualTo(this.sessionRedisOperations);
assertThat(this.sessionRepository.getSessionRedisOperations()).isEqualTo(this.sessionRedisOperations);
verifyNoMoreInteractions(this.sessionRedisOperations);
verifyNoMoreInteractions(this.sessionHashOperations);
}
@@ -317,9 +378,8 @@ class SimpleRedisOperationsSessionRepositoryTests {
}
private static Date getExpiry(RedisSession session) {
return Date
.from(Instant.ofEpochMilli(session.getLastAccessedTime().toEpochMilli())
.plusSeconds(session.getMaxInactiveInterval().getSeconds()));
return Date.from(Instant.ofEpochMilli(session.getLastAccessedTime().toEpochMilli())
.plusSeconds(session.getMaxInactiveInterval().getSeconds()));
}
private static Map mapOf(Object... objects) {
@@ -332,12 +392,16 @@ class SimpleRedisOperationsSessionRepositoryTests {
return result;
}
private RedisSession createTestSession() {
private RedisSession createTestSession(Map<String, Object> attributes) {
MapSession cached = new MapSession(TEST_SESSION_ID);
cached.setCreationTime(Instant.EPOCH);
cached.setLastAccessedTime(Instant.EPOCH);
cached.setAttribute("attribute1", "value1");
return this.sessionRepository.new RedisSession(cached);
attributes.forEach(cached::setAttribute);
return this.sessionRepository.new RedisSession(cached, false);
}
private RedisSession createTestSession() {
return createTestSession(Collections.singletonMap("attribute1", "value1"));
}
}

View File

@@ -36,20 +36,23 @@ import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
public class EnableRedisKeyspaceNotificationsInitializerTests {
static final String CONFIG_NOTIFY_KEYSPACE_EVENTS = "notify-keyspace-events";
class EnableRedisKeyspaceNotificationsInitializerTests {
private static final String CONFIG_NOTIFY_KEYSPACE_EVENTS = "notify-keyspace-events";
@Mock
RedisConnectionFactory connectionFactory;
@Mock
RedisConnection connection;
@Captor
ArgumentCaptor<String> options;
RedisHttpSessionConfiguration.EnableRedisKeyspaceNotificationsInitializer initializer;
private RedisHttpSessionConfiguration.EnableRedisKeyspaceNotificationsInitializer initializer;
@BeforeEach
public void setup() {
void setup() {
MockitoAnnotations.initMocks(this);
given(this.connectionFactory.getConnection()).willReturn(this.connection);
@@ -58,7 +61,7 @@ public class EnableRedisKeyspaceNotificationsInitializerTests {
}
@Test
public void afterPropertiesSetUnset() throws Exception {
void afterPropertiesSetUnset() {
setConfigNotification("");
this.initializer.afterPropertiesSet();
@@ -67,7 +70,7 @@ public class EnableRedisKeyspaceNotificationsInitializerTests {
}
@Test
public void afterPropertiesSetA() throws Exception {
void afterPropertiesSetA() {
setConfigNotification("A");
this.initializer.afterPropertiesSet();
@@ -76,7 +79,7 @@ public class EnableRedisKeyspaceNotificationsInitializerTests {
}
@Test
public void afterPropertiesSetE() throws Exception {
void afterPropertiesSetE() {
setConfigNotification("E");
this.initializer.afterPropertiesSet();
@@ -85,7 +88,7 @@ public class EnableRedisKeyspaceNotificationsInitializerTests {
}
@Test
public void afterPropertiesSetK() throws Exception {
void afterPropertiesSetK() {
setConfigNotification("K");
this.initializer.afterPropertiesSet();
@@ -94,7 +97,7 @@ public class EnableRedisKeyspaceNotificationsInitializerTests {
}
@Test
public void afterPropertiesSetAE() throws Exception {
void afterPropertiesSetAE() {
setConfigNotification("AE");
this.initializer.afterPropertiesSet();
@@ -103,7 +106,7 @@ public class EnableRedisKeyspaceNotificationsInitializerTests {
}
@Test
public void afterPropertiesSetAK() throws Exception {
void afterPropertiesSetAK() {
setConfigNotification("AK");
this.initializer.afterPropertiesSet();
@@ -112,7 +115,7 @@ public class EnableRedisKeyspaceNotificationsInitializerTests {
}
@Test
public void afterPropertiesSetEK() throws Exception {
void afterPropertiesSetEK() {
setConfigNotification("EK");
this.initializer.afterPropertiesSet();
@@ -121,7 +124,7 @@ public class EnableRedisKeyspaceNotificationsInitializerTests {
}
@Test
public void afterPropertiesSetEg() throws Exception {
void afterPropertiesSetEg() {
setConfigNotification("Eg");
this.initializer.afterPropertiesSet();
@@ -130,7 +133,7 @@ public class EnableRedisKeyspaceNotificationsInitializerTests {
}
@Test
public void afterPropertiesSetE$() throws Exception {
void afterPropertiesSetE$() {
setConfigNotification("E$");
this.initializer.afterPropertiesSet();
@@ -139,7 +142,7 @@ public class EnableRedisKeyspaceNotificationsInitializerTests {
}
@Test
public void afterPropertiesSetKg() throws Exception {
void afterPropertiesSetKg() {
setConfigNotification("Kg");
this.initializer.afterPropertiesSet();
@@ -148,7 +151,7 @@ public class EnableRedisKeyspaceNotificationsInitializerTests {
}
@Test
public void afterPropertiesSetAEK() throws Exception {
void afterPropertiesSetAEK() {
setConfigNotification("AEK");
this.initializer.afterPropertiesSet();
@@ -157,8 +160,7 @@ public class EnableRedisKeyspaceNotificationsInitializerTests {
}
private void assertOptionsContains(String... expectedValues) {
verify(this.connection).setConfig(eq(CONFIG_NOTIFY_KEYSPACE_EVENTS),
this.options.capture());
verify(this.connection).setConfig(eq(CONFIG_NOTIFY_KEYSPACE_EVENTS), this.options.capture());
for (String expectedValue : expectedValues) {
assertThat(this.options.getValue()).contains(expectedValue);
}
@@ -168,7 +170,7 @@ public class EnableRedisKeyspaceNotificationsInitializerTests {
private void setConfigNotification(String value) {
Properties properties = new Properties();
properties.setProperty(CONFIG_NOTIFY_KEYSPACE_EVENTS, value);
given(this.connection.getConfig(CONFIG_NOTIFY_KEYSPACE_EVENTS))
.willReturn(properties);
given(this.connection.getConfig(CONFIG_NOTIFY_KEYSPACE_EVENTS)).willReturn(properties);
}
}

View File

@@ -41,7 +41,7 @@ public class RedisHttpSessionConfigurationClassPathXmlApplicationContextTests {
// gh-318
@Test
public void contextLoads() {
void contextLoads() {
}
static RedisConnectionFactory connectionFactory() {
@@ -52,4 +52,5 @@ public class RedisHttpSessionConfigurationClassPathXmlApplicationContextTests {
return factory;
}
}

View File

@@ -32,23 +32,24 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
public class RedisHttpSessionConfigurationMockTests {
class RedisHttpSessionConfigurationMockTests {
@Mock
RedisConnectionFactory factory;
@Mock
RedisConnection connection;
@BeforeEach
public void setup() {
void setup() {
MockitoAnnotations.initMocks(this);
given(this.factory.getConnection()).willReturn(this.connection);
}
@Test
public void enableRedisKeyspaceNotificationsInitializerAfterPropertiesSetWhenNoOpThenNoInteractionWithConnectionFactory()
throws Exception {
EnableRedisKeyspaceNotificationsInitializer init = new EnableRedisKeyspaceNotificationsInitializer(
this.factory, ConfigureRedisAction.NO_OP);
void enableRedisKeyspaceNotificationsInitializerAfterPropertiesSetWhenNoOpThenNoInteractionWithConnectionFactory() {
EnableRedisKeyspaceNotificationsInitializer init = new EnableRedisKeyspaceNotificationsInitializer(this.factory,
ConfigureRedisAction.NO_OP);
init.afterPropertiesSet();
@@ -56,13 +57,12 @@ public class RedisHttpSessionConfigurationMockTests {
}
@Test
public void enableRedisKeyspaceNotificationsInitializerAfterPropertiesSetWhenExceptionThenCloseConnection()
throws Exception {
void enableRedisKeyspaceNotificationsInitializerAfterPropertiesSetWhenExceptionThenCloseConnection() {
ConfigureRedisAction action = mock(ConfigureRedisAction.class);
willThrow(new RuntimeException()).given(action).configure(this.connection);
EnableRedisKeyspaceNotificationsInitializer init = new EnableRedisKeyspaceNotificationsInitializer(
this.factory, action);
EnableRedisKeyspaceNotificationsInitializer init = new EnableRedisKeyspaceNotificationsInitializer(this.factory,
action);
try {
init.afterPropertiesSet();
@@ -75,15 +75,15 @@ public class RedisHttpSessionConfigurationMockTests {
}
@Test
public void enableRedisKeyspaceNotificationsInitializerAfterPropertiesSetWhenNoExceptionThenCloseConnection()
throws Exception {
void enableRedisKeyspaceNotificationsInitializerAfterPropertiesSetWhenNoExceptionThenCloseConnection() {
ConfigureRedisAction action = mock(ConfigureRedisAction.class);
EnableRedisKeyspaceNotificationsInitializer init = new EnableRedisKeyspaceNotificationsInitializer(
this.factory, action);
EnableRedisKeyspaceNotificationsInitializer init = new EnableRedisKeyspaceNotificationsInitializer(this.factory,
action);
init.afterPropertiesSet();
verify(this.connection).close();
}
}

View File

@@ -35,10 +35,10 @@ import static org.mockito.Mockito.mock;
@ExtendWith(SpringExtension.class)
@ContextConfiguration
@WebAppConfiguration
public class RedisHttpSessionConfigurationNoOpConfigureRedisActionTests {
class RedisHttpSessionConfigurationNoOpConfigureRedisActionTests {
@Test
public void redisConnectionFactoryNotUsedSinceNoValidation() {
void redisConnectionFactoryNotUsedSinceNoValidation() {
}
@EnableRedisHttpSession
@@ -54,5 +54,7 @@ public class RedisHttpSessionConfigurationNoOpConfigureRedisActionTests {
public RedisConnectionFactory redisConnectionFactory() {
return mock(RedisConnectionFactory.class);
}
}
}

View File

@@ -46,7 +46,7 @@ import static org.mockito.Mockito.mock;
@ExtendWith(SpringExtension.class)
@ContextConfiguration
@WebAppConfiguration
public class RedisHttpSessionConfigurationOverrideDefaultSerializerTests {
class RedisHttpSessionConfigurationOverrideDefaultSerializerTests {
@SpringSessionRedisOperations
RedisTemplate<Object, Object> template;
@@ -55,14 +55,14 @@ public class RedisHttpSessionConfigurationOverrideDefaultSerializerTests {
RedisSerializer<Object> defaultRedisSerializer;
@Test
public void overrideDefaultRedisTemplate() {
assertThat(this.template.getDefaultSerializer())
.isSameAs(this.defaultRedisSerializer);
void overrideDefaultRedisTemplate() {
assertThat(this.template.getDefaultSerializer()).isSameAs(this.defaultRedisSerializer);
}
@EnableRedisHttpSession
@Configuration
static class Config {
@Bean
@SuppressWarnings("unchecked")
public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
@@ -78,5 +78,7 @@ public class RedisHttpSessionConfigurationOverrideDefaultSerializerTests {
return factory;
}
}
}

View File

@@ -47,7 +47,7 @@ import static org.mockito.Mockito.verify;
@ExtendWith(SpringExtension.class)
@ContextConfiguration
@WebAppConfiguration
public class RedisHttpSessionConfigurationOverrideSessionTaskExecutor {
class RedisHttpSessionConfigurationOverrideSessionTaskExecutor {
@Autowired
RedisMessageListenerContainer redisMessageListenerContainer;
@@ -56,14 +56,14 @@ public class RedisHttpSessionConfigurationOverrideSessionTaskExecutor {
Executor springSessionRedisTaskExecutor;
@Test
public void overrideSessionTaskExecutor() {
verify(this.springSessionRedisTaskExecutor, times(1))
.execute(any(SchedulingAwareRunnable.class));
void overrideSessionTaskExecutor() {
verify(this.springSessionRedisTaskExecutor, times(1)).execute(any(SchedulingAwareRunnable.class));
}
@EnableRedisHttpSession
@Configuration
static class Config {
@Bean
public Executor springSessionRedisTaskExecutor() {
return mock(Executor.class);
@@ -78,5 +78,7 @@ public class RedisHttpSessionConfigurationOverrideSessionTaskExecutor {
return factory;
}
}
}

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